From 1713e81b9cdf06d2a9a365a7ded13a54fad84798 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Sun, 24 Oct 2004 05:37:23 +0000 Subject: Import the HighPoint RocketRAID 182x driver. Thanks to HighPoint for providing the original driver, and thanks to IronSystems for providing hardware for testing. --- sys/dev/hptmv/gui_lib.c | 1384 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 1384 insertions(+) create mode 100644 sys/dev/hptmv/gui_lib.c (limited to 'sys/dev/hptmv/gui_lib.c') diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c new file mode 100644 index 000000000000..e20ef55d8daa --- /dev/null +++ b/sys/dev/hptmv/gui_lib.c @@ -0,0 +1,1384 @@ +/* + * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ +/* + * gui_lib.c + * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved. + * + * Platform independent ioctl interface implementation. + * The platform dependent part may reuse this function and/or use it own + * implementation for each ioctl function. + * + * This implementation doesn't use any synchronization; the caller must + * assure the proper context when calling these functions. + */ + +#include +#include +#include +#include + +#include +#include +#include +#include + +static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap); +static int hpt_get_controller_count(void); +static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo); +static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo); +static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount); +static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo); +static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam); +static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk); +static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk); +static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo); +static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo); + +int check_VDevice_valid(PVDevice p) +{ + int i; + PVDevice pVDevice; + PVBus _vbus_p; + IAL_ADAPTER_T *pAdapter = gIal_Adapter; + + while(pAdapter != 0) + { + for (i = 0; i < MV_SATA_CHANNELS_NUM; i++) + if(&(pAdapter->VDevices[i]) == p) return 0; + pAdapter = pAdapter->next; + } + +#ifdef SUPPORT_ARRAY + pAdapter = gIal_Adapter; + while(pAdapter != 0) + { + _vbus_p = &pAdapter->VBus; + for (i=0;iu.array.dArStamp != 0) && (pVDevice == p)) + return 0; + } + pAdapter = pAdapter->next; + } +#endif + + return -1; +} + +#ifdef SUPPORT_ARRAY +static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) +{ + int i; + + pInfo->Type = LDT_ARRAY; + pInfo->Capacity = pVDevice->VDeviceCapacity; + pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); + + memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME); + + switch( pVDevice->VDeviceType ) + { + case VD_RAID_0: + pInfo->u.array.ArrayType = AT_RAID0; + break; + case VD_RAID_1: + pInfo->u.array.ArrayType = AT_RAID1; + break; + case VD_JBOD: + pInfo->u.array.ArrayType = AT_JBOD; + break; + case VD_RAID_5: + pInfo->u.array.ArrayType = AT_RAID5; + break; + default: + pInfo->u.array.ArrayType = AT_UNKNOWN; + } + + pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; + + pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors; + + /* The array is disabled */ + if(!pVDevice->vf_online) { + pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED; + goto ignore_info; + } + + /* array need synchronizing */ + if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create) + pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING; + + pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 / + (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10; + + /* array is in rebuilding process */ + if(pVDevice->u.array.rf_rebuilding) + pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; + + /* array is being verified */ + if(pVDevice->u.array.rf_verifying) + pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; + + /* array is being initialized */ + if(pVDevice->u.array.rf_initializing) + pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; + + /* broken but may still working */ + if(pVDevice->u.array.rf_broken) + pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; + + /* array has a active partition */ + if(pVDevice->vf_bootable) + pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK; + + /* a newly created array */ + if(pVDevice->u.array.rf_newly_created) + pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; + + /* array has boot mark set */ + if(pVDevice->vf_bootmark) + pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK; + + /* auto-rebuild should start */ + if(pVDevice->u.array.rf_auto_rebuild) + pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; + + for(i = 0; i < pVDevice->u.array.bArnMember; i++) + { + PVDevice pMember = pVDevice->u.array.pMember[i]; + if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK)) + continue; + + /* array need synchronizing */ + if(pMember->u.array.rf_need_rebuild && + !pMember->u.array.rf_duplicate_and_create) + pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING; + + /* array is in rebuilding process */ + if(pMember->u.array.rf_rebuilding) + pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; + + /* array is being verified */ + if(pMember->u.array.rf_verifying) + pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; + + /* array is being initialized */ + if(pMember->u.array.rf_initializing) + pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; + + /* broken but may still working */ + if(pMember->u.array.rf_broken) + pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; + + /* a newly created array */ + if(pMember->u.array.rf_newly_created) + pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; + + /* auto-rebuild should start */ + if(pMember->u.array.rf_auto_rebuild) + pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; + + /* for RAID1/0 case */ + if (pMember->u.array.rf_rebuilding || + pMember->u.array.rf_verifying || + pMember->u.array.rf_initializing) + { + DWORD percent = ((pMember->u.array.RebuildSectors>>11)*1000 / + (pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10; + if (pInfo->u.array.RebuildingProgress==0 || + pInfo->u.array.RebuildingProgress>percent) + pInfo->u.array.RebuildingProgress = percent; + } + } + + if (pInfo->u.array.RebuildingProgress>10000) + pInfo->u.array.RebuildingProgress = 10000; + +ignore_info: + + pInfo->u.array.nDisk = 0; + for(i=0; iu.array.Members[i] = INVALID_DEVICEID; + + for(i = 0; i < pVDevice->u.array.bArnMember; i++) + { + if(pVDevice->u.array.pMember[i] != NULL) + { + pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); + pInfo->u.array.nDisk++; + } + } +} +#endif + +static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) +{ + MV_SATA_ADAPTER *pSataAdapter; + MV_SATA_CHANNEL *pSataChannel; + IAL_ADAPTER_T *pAdapter; + char *p; + int i; + + pInfo->Type = LDT_DEVICE; + + if (pVDevice->pParent) + pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); + else + pInfo->ParentArray = INVALID_DEVICEID; + + /* report real capacity to be compatible with old arrays */ + pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity; + + /* device location */ + pSataChannel = pVDevice->u.disk.mv; + if(pSataChannel == NULL) return -1; + pInfo->u.device.TargetId = 0; + pSataAdapter = pSataChannel->mvSataAdapter; + if(pSataAdapter == NULL) return -1; + + pAdapter = pSataAdapter->IALData; + + pInfo->u.device.PathId = pSataChannel->channelNumber; + pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId; + +/*GUI uses DeviceModeSetting to display to users +(1) if users select a mode, GUI/BIOS should display that mode. +(2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied. +(3) display real mode if case (1)&&(2) not satisfied. +*/ + if (pVDevice->u.disk.df_user_mode_set) + pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode; + else if ((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability & 3)==2) + pInfo->u.device.DeviceModeSetting = 15; + else { + p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber; + if (*(WORD*)p==0x5354 /*'ST'*/ && + (*(WORD*)(p+8)==0x4153/*'AS'*/ || (p[8]=='A' && p[11]=='S'))) + pInfo->u.device.DeviceModeSetting = 15; + else + pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting; + } + + pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode; + + pInfo->u.device.DeviceType = PDT_HARDDISK; + + pInfo->u.device.Flags = 0x0; + + /* device is disabled */ + if(!pVDevice->u.disk.df_on_line) + pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED; + + /* disk has a active partition */ + if(pVDevice->vf_bootable) + pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK; + + /* disk has boot mark set */ + if(pVDevice->vf_bootmark) + pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK; + + pInfo->u.device.Flags |= DEVICE_FLAG_SATA; + + /* is a spare disk */ + if(pVDevice->VDeviceType == VD_SPARE) + pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE; + + memcpy(&(pInfo->u.device.IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2)); + p = (char *)&pInfo->u.device.IdentifyData.ModelNumber; + for (i = 0; i < 20; i++) + ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]); + p[39] = '\0'; + + return 0; +} + +static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) +{ + ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES)); + cap->dwSize = sizeof(DRIVER_CAPABILITIES); + cap->MaximumControllers = MAX_VBUS; + + /* cap->SupportCrossControllerRAID = 0; */ + /* take care for various OSes! */ + cap->SupportCrossControllerRAID = 0; + + + cap->MinimumBlockSizeShift = MinBlockSizeShift; + cap->MaximumBlockSizeShift = MaxBlockSizeShift; + cap->SupportDiskModeSetting = 0; + cap->SupportSparePool = 1; + cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1; + cap->SupportDedicatedSpare = 0; + +#ifdef SUPPORT_HOTSWAP + cap->SupportHotSwap = 1; +#endif + +#ifdef SUPPORT_ARRAY + /* Stripe */ + cap->SupportedRAIDTypes[0] = AT_RAID0; + cap->MaximumArrayMembers[0] = MAX_MEMBERS; + /* Mirror */ + cap->SupportedRAIDTypes[1] = AT_RAID1; + cap->MaximumArrayMembers[1] = 2; + /* Mirror + Stripe */ +#ifdef ARRAY_V2_ONLY + cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */ +#else + cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */ +#endif + cap->MaximumArrayMembers[2] = MAX_MEMBERS; + /* Jbod */ + cap->SupportedRAIDTypes[3] = AT_JBOD; + cap->MaximumArrayMembers[3] = MAX_MEMBERS; + /* RAID5 */ +#if SUPPORT_RAID5 + cap->SupportedRAIDTypes[4] = AT_RAID5; + cap->MaximumArrayMembers[4] = MAX_MEMBERS; +#endif +#if 0 /* don't let GUI create RAID 0/1. */ + /* Stripe + Mirror */ + cap->SupportedRAIDTypes[5] = (AT_RAID1<<4)|AT_RAID0; + cap->MaximumArrayMembers[5] = 4; +#endif +#endif /* SUPPORT_ARRAY */ + return 0; +} + +static int hpt_get_controller_count(void) +{ + IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; + int iControllerCount = 0; + + while(pAdapTemp != 0) + { + iControllerCount++; + pAdapTemp = pAdapTemp->next; + } + + return iControllerCount; +} + +static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) +{ + IAL_ADAPTER_T *pAdapTemp; + int iControllerCount = 0; + + for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { + if (iControllerCount++==id) { + pInfo->InterruptLevel = 0; + pInfo->ChipType = 0; + pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100; + strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc."); +#ifdef GUI_CONTROLLER_NAME +#ifdef FORCE_ATA150_DISPLAY + /* show "Bus Type: ATA/150" in GUI for SATA controllers */ + pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150; +#endif + strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME); +#define _set_product_id(x) +#else +#define _set_product_id(x) strcpy(pInfo->szProductID, x) +#endif + _set_product_id("RocketRAID 182x SATA Controller"); + pInfo->NumBuses = 8; + pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150; + return 0; + } + } + return -1; +} + + +static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) +{ + IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; + int i,iControllerCount = 0; + + while(pAdapTemp != 0) + { + if (iControllerCount++==id) + goto found; + pAdapTemp = pAdapTemp->next; + } + return -1; + +found: + + pInfo->IoPort = 0; + pInfo->ControlPort = 0; + + for (i=0; i<2 ;i++) + { + pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID; + } + + if (pAdapTemp->mvChannel[bus].online == MV_TRUE) + pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]); + else + pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID; + + return 0; + + +} + +static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) +{ + int count = 0; + int i,j; + PVDevice pPhysical, pLogical; + IAL_ADAPTER_T *pAdapTemp; + + for(i = 0; i < nMaxCount; i++) + pIds[i] = INVALID_DEVICEID; + + /* append the arrays not registered on VBus */ + for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { + for(i = 0; i < MV_SATA_CHANNELS_NUM; i++) + { + pPhysical = &pAdapTemp->VDevices[i]; + pLogical = pPhysical; + + while (pLogical->pParent) pLogical = pLogical->pParent; + if (pLogical->VDeviceType==VD_SPARE) + continue; + + for (j=0; j=nMaxCount) goto done; + next:; + } + } + +done: + return count; +} + +static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) +{ + PVDevice pVDevice = ID_TO_VDEV(id); + + if((id == HPT_NULL_ID) || check_VDevice_valid(pVDevice)) + return -1; + +#ifdef SUPPORT_ARRAY + if (mIsArray(pVDevice)) + get_array_info(pVDevice, pInfo); + else +#endif + return get_disk_info(pVDevice, pInfo); + + return 0; +} + +#ifdef SUPPORT_ARRAY +static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) +{ + ULONG Stamp = GetStamp(); + int i,j; + ULONG capacity = MAX_LBA_T; + PVDevice pArray,pChild; +#if MAX_VBUS==1 + PVBus _vbus_p = NULL; +#endif + int Loca = -1; + + for(i = 0; i < pParam->nDisk; i++) + { + PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]); + if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID; + if (mIsArray(pVDev)) return INVALID_DEVICEID; + if (!pVDev->vf_online) return INVALID_DEVICEID; + if (!_vbus_p) + _vbus_p = pVDev->u.disk.pVBus; + else if (_vbus_p != pVDev->u.disk.pVBus) + return INVALID_DEVICEID; + } + if (!_vbus_p) return INVALID_DEVICEID; + + mArGetArrayTable(pArray); + if(!pArray) return INVALID_DEVICEID; + + switch (pParam->ArrayType) + { + case AT_JBOD: + pArray->VDeviceType = VD_JBOD; + goto simple; + + case AT_RAID0: + if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) + goto error; + pArray->VDeviceType = VD_RAID_0; + goto simple; + + case AT_RAID5: + if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) + goto error; + pArray->VDeviceType = VD_RAID_5; + /* only "no build" R5 is not critical after creation. */ + if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0) + pArray->u.array.rf_need_rebuild = 1; + goto simple; + + case AT_RAID1: + if(pParam->nDisk <= 2) + { + pArray->VDeviceType = VD_RAID_1; +simple: + pArray->u.array.bArnMember = pParam->nDisk; + pArray->u.array.bArRealnMember = pParam->nDisk; + pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; + pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); + pArray->u.array.dArStamp = Stamp; + + pArray->u.array.rf_need_sync = 1; + pArray->u.array.rf_newly_created = 1; + + if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && + (pArray->VDeviceType == VD_RAID_1)) + { + pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */ + pArray->u.array.rf_need_rebuild = 1; + pArray->u.array.rf_auto_rebuild = 1; + pArray->u.array.rf_duplicate_and_create = 1; + + for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) + if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0])) + Loca = i; + } + + pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T; + + memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); + + for(i = 0; i < pParam->nDisk; i++) + { + pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]); + pArray->u.array.pMember[i]->bSerialNumber = i; + pArray->u.array.pMember[i]->pParent = pArray; + + /* don't unregister source disk for duplicate RAID1 */ + if (i || + pArray->VDeviceType!=VD_RAID_1 || + (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0) + UnregisterVDevice(pArray->u.array.pMember[i]); + + if(pArray->VDeviceType == VD_RAID_5) + pArray->u.array.pMember[i]->vf_cache_disk = 1; + } + } + else + { + for(i = 0; i < (pParam->nDisk / 2); i++) + { + mArGetArrayTable(pChild); + pChild->VDeviceType = VD_RAID_1; + + pChild->u.array.bArnMember = 2; + pChild->u.array.bArRealnMember = 2; + pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift; + pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); + pChild->u.array.dArStamp = Stamp; + + pChild->u.array.rf_need_sync = 1; + pChild->u.array.rf_newly_created = 1; + + pChild->u.array.RebuildSectors = MAX_LBA_T; + + memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); + + for(j = 0; j < 2; j++) + { + pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]); + pChild->u.array.pMember[j]->bSerialNumber = j; + pChild->u.array.pMember[j]->pParent = pChild; + pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType]; + UnregisterVDevice(pChild->u.array.pMember[j]); + } + + pArray->u.array.pMember[i] = pChild; + + pChild->vf_online = 1; + pChild->bSerialNumber = i; + pChild->pParent = pArray; + pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity, + pChild->u.array.pMember[1]->VDeviceCapacity); + + pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType]; + pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0]; + } + + pArray->VDeviceType = VD_RAID_0; + + pArray->u.array.bArnMember = pParam->nDisk / 2; + pArray->u.array.bArRealnMember = pParam->nDisk / 2; + pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; + pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); + pArray->u.array.dArStamp = Stamp; + + pArray->u.array.rf_need_sync = 1; + pArray->u.array.rf_newly_created = 1; + + memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); + } + break; + + default: + goto error; + } + + for(i = 0; i < pArray->u.array.bArnMember; i++) + pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; + + if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && + (pArray->VDeviceType == VD_RAID_1)) + { + pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark; + pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable; + pArray->u.array.pMember[0]->vf_bootable = 0; + pArray->u.array.pMember[0]->vf_bootmark = 0; + if (Loca>=0) { + _vbus_p->pVDevice[Loca] = pArray; + /* to comfort OS */ + pArray->u.array.rf_duplicate_and_created = 1; + pArray->pVBus = _vbus_p; + } + } + else { + UCHAR TempBuffer[512]; + ZeroMemory(TempBuffer, 512); + for(i = 0; i < pParam->nDisk; i++) + { + PVDevice pDisk = ID_TO_VDEV(pParam->Members[i]); + pDisk->vf_bootmark = pDisk->vf_bootable = 0; + fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer); + } + } + + pArray->vf_online = 1; + pArray->pParent = NULL; + + switch(pArray->VDeviceType) + { + case VD_RAID_0: + for(i = 0; i < pArray->u.array.bArnMember; i++) + if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) + capacity = pArray->u.array.pMember[i]->VDeviceCapacity; +#ifdef ARRAY_V2_ONLY + capacity -= 10; +#endif + capacity &= ~(pArray->u.array.bStripeWitch - 1); + /* shrink member capacity for RAID 1/0 */ + for(i = 0; i < pArray->u.array.bArnMember; i++) + if (mIsArray(pArray->u.array.pMember[i])) + pArray->u.array.pMember[i]->VDeviceCapacity = capacity; + pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember; + break; + + case VD_RAID_1: + pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity, + pArray->u.array.pMember[1]->VDeviceCapacity); + break; + + case VD_JBOD: + for(i = 0; i < pArray->u.array.bArnMember; i++) + pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity +#ifdef ARRAY_V2_ONLY + -10 +#endif + ; + break; + + case VD_RAID_5: + for(i = 0; i < pArray->u.array.bArnMember; i++) + if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) + capacity = pArray->u.array.pMember[i]->VDeviceCapacity; + pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1)) + * (pArray->u.array.bArnMember - 1); + break; + + default: + goto error; + } + + pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType]; + pArray->pfnDeviceFailed = fOsDiskFailed; + SyncArrayInfo(pArray); + + if (!pArray->u.array.rf_duplicate_and_created) + RegisterVDevice(pArray); + return VDEV_TO_ID(pArray); + +error: + for(i = 0; i < pArray->u.array.bArnMember; i++) + { + pChild = pArray->u.array.pMember[i]; + if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK)) + mArFreeArrayTable(pChild); + } + mArFreeArrayTable(pArray); + return INVALID_DEVICEID; +} + +#ifdef SUPPORT_OLD_ARRAY +/* this is only for old RAID 0/1 */ +int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) +{ + PVDevice pArray1 = ID_TO_VDEV(idArray); + PVDevice pArray2 = 0; + PVDevice pDisk = ID_TO_VDEV(idDisk); + int i; + IAL_ADAPTER_T *pAdapter = gIal_Adapter; + +#if MAX_VBUS>1 + if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} +#endif + + if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2)) + return -1; + + pArray2 = pArray1->u.array.pMember[1]; + if(pArray2 == NULL) { + /* create a Stripe */ + mArGetArrayTable(pArray2); + pArray2->VDeviceType = VD_RAID_0; + pArray2->u.array.dArStamp = GetStamp(); + pArray2->vf_format_v2 = 1; + pArray2->u.array.rf_broken = 1; + pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift; + pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift); + pArray2->u.array.bArnMember = 2; + pArray2->VDeviceCapacity = pArray1->VDeviceCapacity; + pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType]; + pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType]; + memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME); + pArray2->pParent = pArray1; + pArray2->bSerialNumber = 1; + pArray1->u.array.pMember[1] = pArray2; + pArray1->u.array.bArRealnMember++; + } + + for(i = 0; i < pArray2->u.array.bArnMember; i++) + if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online) + { + if(pArray2->u.array.pMember[i] != NULL) + pArray2->u.array.pMember[i]->pParent = NULL; + pArray2->u.array.pMember[i] = pDisk; + goto find; + } + return -1; + +find: + UnregisterVDevice(pDisk); + pDisk->VDeviceType = VD_SINGLE_DISK; + pDisk->bSerialNumber = i; + pDisk->pParent = pArray2; + pDisk->vf_format_v2 = 1; + pDisk->u.disk.dDeHiddenLba = i? 10 : 0; + pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; + pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType]; + + pArray2->u.array.bArRealnMember++; + if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){ + pArray2->vf_online = 1; + pArray2->u.array.rf_broken = 0; + } + + if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){ + pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember; + pArray1->u.array.rf_broken = 0; + pArray1->u.array.rf_need_rebuild = 1; + pArray1->u.array.rf_auto_rebuild = 1; + + } + pArray1->u.array.RebuildSectors = 0; + pArray1->u.array.dArStamp = GetStamp(); + SyncArrayInfo(pArray1); + return 1; +} +#endif + +int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) +{ + int i; + + ULONG Capacity; + PVDevice pArray = ID_TO_VDEV(idArray); + PVDevice pDisk = ID_TO_VDEV(idDisk); + + if((idArray == HPT_NULL_ID) || (idDisk == HPT_NULL_ID)) return -1; + if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1; + if(!pArray->u.array.rf_broken) return -1; + + if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) + return -1; + if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE)) + return -1; + +#ifdef SUPPORT_OLD_ARRAY + /* RAID 0 + 1 */ + if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 && + pArray->u.array.pMember[0] && + mIsArray(pArray->u.array.pMember[0])) + { + if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk)) + return 0; + else + return -1; + } +#endif + + Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1); + + if (pArray->vf_format_v2) { + if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1; + } + else + if(pDisk->VDeviceCapacity < Capacity) return -1; + +#if MAX_VBUS>1 + if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} +#endif + + for(i = 0; i < pArray->u.array.bArnMember; i++) + if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online) + { + if(pArray->u.array.pMember[i] != NULL) + pArray->u.array.pMember[i]->pParent = NULL; + pArray->u.array.pMember[i] = pDisk; + goto find; + } + return -1; + +find: + UnregisterVDevice(pDisk); + pDisk->VDeviceType = VD_SINGLE_DISK; + pDisk->bSerialNumber = i; + pDisk->pParent = pArray; + if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1; + pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; + if (pArray->vf_format_v2) { + pDisk->vf_format_v2 = 1; + pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; + } + + pArray->u.array.bArRealnMember++; + if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember) + { + pArray->u.array.rf_need_rebuild = 1; + pArray->u.array.RebuildSectors = 0; + pArray->u.array.rf_auto_rebuild = 1; + pArray->u.array.rf_broken = 0; + } + pArray->u.array.RebuildSectors = 0; + + /* sync the whole array */ + while (pArray->pParent) pArray = pArray->pParent; + pArray->u.array.dArStamp = GetStamp(); + SyncArrayInfo(pArray); + return 0; +} + +static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) +{ + PVDevice pVDevice = ID_TO_VDEV(idDisk); + DECLARE_BUFFER(PUCHAR, pbuffer); + + if(idDisk == HPT_NULL_ID || check_VDevice_valid(pVDevice)) + return -1; + if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) + return -1; + +#if MAX_VBUS>1 + if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; +#endif + + UnregisterVDevice(pVDevice); + pVDevice->VDeviceType = VD_SPARE; + pVDevice->vf_bootmark = 0; + + ZeroMemory((char *)pbuffer, 512); + fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer); + SyncArrayInfo(pVDevice); + return 0; +} + +static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) +{ + PVDevice pVDevice = ID_TO_VDEV(idDisk); + + if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; + +#if MAX_VBUS>1 + if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; +#endif + + pVDevice->VDeviceType = VD_SINGLE_DISK; + + SyncArrayInfo(pVDevice); + RegisterVDevice(pVDevice); + return 0; +} + +static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) +{ + PVDevice pVDevice = ID_TO_VDEV(idArray); + + if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) return -1; + if (!mIsArray(pVDevice)) return -1; + + /* if the pVDevice isn't a top level, return -1; */ + if(pVDevice->pParent != NULL) return -1; + +#if MAX_VBUS>1 + if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} +#endif + + if (pInfo->ValidFields & AAIF_NAME) { + memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME); + memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name)); + pVDevice->u.array.rf_need_sync = 1; + } + + if (pInfo->ValidFields & AAIF_DESCRIPTION) { + memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description)); + pVDevice->u.array.rf_need_sync = 1; + } + + if (pVDevice->u.array.rf_need_sync) + SyncArrayInfo(pVDevice); + return 0; +} + +static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) +{ + PVDevice pVDevice = ID_TO_VDEV(idDisk); + + /* stop buzzer. */ + if(idDisk == HPT_NULL_ID) { +#ifndef FOR_DEMO + IAL_ADAPTER_T *pAdapter; + for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { + if (pAdapter->beeping) { + pAdapter->beeping = 0; + BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); + } + } +#endif + return 0; + } + + if (check_VDevice_valid(pVDevice)) return -1; + if (mIsArray(pVDevice)) + return -1; + +#if MAX_VBUS>1 + if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; +#endif + +/* if (pInfo->ValidFields & ADIF_MODE) { + pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting; + pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting; + pVDevice->u.disk.df_user_mode_set = 1; + fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting); + SyncArrayInfo(pVDevice); + }*/ + return 0; +} +#endif /* SUPPORT_ARRAY */ + +#ifdef SUPPORT_HPT601 +int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) +{ + PVDevice pVDevice = ID_TO_VDEV(idDisk); + PChannel pChan = pVDevice->u.disk.pChannel; + PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; + + if(!pVDevice->u.disk.df_with_601) return -1; + + mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); + pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); + + BeginAccess601(IoPort); + + mSetBlockCount(IoPort, 0); + pInfo->DeviceId = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 0x14); + pInfo->Temperature = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 0xA); + pInfo->FanStatus = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 7); + pInfo->BeeperControl = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 3); + pInfo->LED1Control = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 5); + pInfo->LED2Control = InWord(&IoPort->Data); + + mSetBlockCount(IoPort, 0x18); + pInfo->PowerStatus = InWord(&IoPort->Data); + + EndAccess601(IoPort); + pInfo->ValidFields = 0x7F; + /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/ + return 0; +} + +int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) +{ + PVDevice pVDevice = ID_TO_VDEV(idDisk); + PChannel pChan = pVDevice->u.disk.pChannel; + PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; + + if(!pVDevice->u.disk.df_with_601) return -1; + + mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); + pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); + + BeginAccess601(IoPort); + + if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) { + mSetBlockCount(IoPort, 1); + OutWord(&IoPort->Data, pInfo->Temperature); + } + + if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) { + mSetBlockCount(IoPort, 0xA); + OutWord(&IoPort->Data, pInfo->FanStatus); + } + + if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) { + mSetBlockCount(IoPort, 7); + OutWord(&IoPort->Data, pInfo->BeeperControl); + } + + if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) { + mSetBlockCount(IoPort, 3); + OutWord(&IoPort->Data, pInfo->LED1Control); + } + + if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) { + mSetBlockCount(IoPort, 5); + OutWord(&IoPort->Data, pInfo->LED2Control); + } + + EndAccess601(IoPort); + + return 0; +} +#endif + +/* hpt_default_ioctl() + * This is a default implementation. The platform dependent part + * may reuse this function and/or use it own implementation for + * each ioctl function. + */ +int hpt_default_ioctl(_VBUS_ARG + DWORD dwIoControlCode, /* operation control code */ + PVOID lpInBuffer, /* input data buffer */ + DWORD nInBufferSize, /* size of input data buffer */ + PVOID lpOutBuffer, /* output data buffer */ + DWORD nOutBufferSize, /* size of output data buffer */ + PDWORD lpBytesReturned /* byte count */ + ) +{ + switch(dwIoControlCode) { + + case HPT_IOCTL_GET_VERSION: + + if (nInBufferSize != 0) return -1; + if (nOutBufferSize != sizeof(DWORD)) return -1; + *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION; + break; + + case HPT_IOCTL_GET_CONTROLLER_COUNT: + + if (nOutBufferSize!=sizeof(DWORD)) return -1; + *(PDWORD)lpOutBuffer = hpt_get_controller_count(); + break; + + case HPT_IOCTL_GET_CONTROLLER_INFO: + { + int id; + PCONTROLLER_INFO pInfo; + + if (nInBufferSize!=sizeof(DWORD)) return -1; + if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1; + + id = *(DWORD *)lpInBuffer; + pInfo = (PCONTROLLER_INFO)lpOutBuffer; + if (hpt_get_controller_info(id, pInfo)!=0) + return -1; + } + break; + + case HPT_IOCTL_GET_CHANNEL_INFO: + { + int id, bus; + PCHANNEL_INFO pInfo; + + if (nInBufferSize!=8) return -1; + if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1; + + id = *(DWORD *)lpInBuffer; + bus = ((DWORD *)lpInBuffer)[1]; + pInfo = (PCHANNEL_INFO)lpOutBuffer; + + if (hpt_get_channel_info(id, bus, pInfo)!=0) + return -1; + } + break; + + case HPT_IOCTL_GET_LOGICAL_DEVICES: + { + DWORD nMax; + DEVICEID *pIds; + + if (nInBufferSize!=sizeof(DWORD)) return -1; + nMax = *(DWORD *)lpInBuffer; + if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1; + + pIds = ((DEVICEID *)lpOutBuffer)+1; + *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax); + } + break; + + case HPT_IOCTL_GET_DEVICE_INFO: + { + DEVICEID id; + PLOGICAL_DEVICE_INFO pInfo; + + if (nInBufferSize!=sizeof(DEVICEID)) return -1; + if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1; + + id = *(DWORD *)lpInBuffer; + if (id == INVALID_DEVICEID) return -1; + + pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer; + memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO)); + + if (hpt_get_device_info(id, pInfo)!=0) + return -1; + } + break; + +#ifdef SUPPORT_ARRAY + case HPT_IOCTL_CREATE_ARRAY: + { + CREATE_ARRAY_PARAMS *pParam; + DEVICEID id; + + if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1; + if (nOutBufferSize!=sizeof(DEVICEID)) return -1; + + pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer; + + id = hpt_create_array(_VBUS_P pParam); + *(DEVICEID *)lpOutBuffer = id; + + if(id == (DEVICEID)INVALID_DEVICEID) + return -1; + } + break; + + case HPT_IOCTL_SET_ARRAY_INFO: + { + DEVICEID idArray; + PALTERABLE_ARRAY_INFO pInfo; + + if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1; + if (nOutBufferSize!=0) return -1; + + idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray; + pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info; + + if(hpt_set_array_info(_VBUS_P idArray, pInfo)) + return -1; + } + break; + + case HPT_IOCTL_SET_DEVICE_INFO: + { + DEVICEID idDisk; + PALTERABLE_DEVICE_INFO pInfo; + + if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1; + if (nOutBufferSize!=0) return -1; + + idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk; + pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info; + if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0) + return -1; + } + break; + + case HPT_IOCTL_SET_BOOT_MARK: + { + DEVICEID id; + PVDevice pTop; + int i; + IAL_ADAPTER_T *pAdapter = gIal_Adapter; + PVBus pVBus; + + if (nInBufferSize!=sizeof(DEVICEID)) return -1; + id = *(DEVICEID *)lpInBuffer; + while(pAdapter != 0) + { + pVBus = &pAdapter->VBus; + for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) + { + if(!(pTop = pVBus->pVDevice[i])) continue; +#if MAX_VBUS>1 + if (pTop->pVBus!=_vbus_p) return -1; +#endif + while (pTop->pParent) pTop = pTop->pParent; + if (id==0 && pTop->vf_bootmark) + pTop->vf_bootmark = 0; + else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark) + pTop->vf_bootmark = 1; + else + continue; + SyncArrayInfo(pTop); + break; + } + pAdapter = pAdapter->next; + } + } + break; +#endif /* SUPPORT_ARRAY */ + case HPT_IOCTL_RESCAN_DEVICES: + { + fRescanAllDevice(_VBUS_P0); + if (nInBufferSize!=0) return -1; + if (nOutBufferSize!=0) return -1; + fRescanAllDevice(_VBUS_P0); + } + break; + +#ifdef SUPPORT_ARRAY + case HPT_IOCTL_ADD_SPARE_DISK: + { + DEVICEID id; + + if (nInBufferSize!=sizeof(DEVICEID)) return -1; + if (nOutBufferSize!=0) return -1; + + id = *(DEVICEID *)lpInBuffer; + + if(hpt_add_spare_disk(_VBUS_P id)) + return -1; + } + break; + + case HPT_IOCTL_REMOVE_SPARE_DISK: + { + DEVICEID id; + + if (nInBufferSize!=sizeof(DEVICEID)) return -1; + if (nOutBufferSize!=0) return -1; + + id = *(DEVICEID *)lpInBuffer; + + if(hpt_remove_spare_disk(_VBUS_P id)) + return -1; + } + break; + + case HPT_IOCTL_ADD_DISK_TO_ARRAY: + { + DEVICEID id1,id2; + id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray; + id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk; + + if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1; + if (nOutBufferSize != 0) return -1; + + if(hpt_add_disk_to_array(_VBUS_P id1, id2)) + return -1; + } + break; +#endif + case HPT_IOCTL_GET_DRIVER_CAPABILITIES: + { + PDRIVER_CAPABILITIES cap; + if (nOutBufferSizeidDisk; + pInfo = &((PHPT_SET_601_INFO)lpInBuffer)->Info; + if(hpt_set_601_info(id, pInfo) != 0) + return -1; + } + break; +#endif + default: + return -1; + } + + if (lpBytesReturned) + *lpBytesReturned = nOutBufferSize; + return 0; +} -- cgit v1.3 From d38d9c9e5ec4c6387ee8a555753ecbd64ea35c13 Mon Sep 17 00:00:00 2001 From: Scott Long Date: Wed, 2 Mar 2005 05:14:28 +0000 Subject: Move all of the hptmv files to /sys/dev/hptmv so that they won't be mistaken for being on a CVS vendor branch. The files were moved via a repo-copy. --- sys/conf/files.i386 | 10 +- sys/contrib/dev/hptmv/access601.h | 41 - sys/contrib/dev/hptmv/array.h | 265 ------ sys/contrib/dev/hptmv/atapi.h | 556 ------------ sys/contrib/dev/hptmv/command.h | 265 ------ sys/contrib/dev/hptmv/gui_lib.c | 1384 ------------------------------ sys/contrib/dev/hptmv/hptproc.c | 600 ------------- sys/contrib/dev/hptmv/i386-elf.raid.o.uu | 1346 ----------------------------- sys/contrib/dev/hptmv/ioctl.c | 928 -------------------- sys/contrib/dev/hptmv/mvSata.h | 429 --------- sys/contrib/dev/hptmv/mvStorageDev.h | 210 ----- sys/contrib/dev/hptmv/raid5n.h | 120 --- sys/contrib/dev/hptmv/readme.txt | 96 --- sys/contrib/dev/hptmv/vdevice.h | 280 ------ sys/dev/hptmv/access601.h | 2 + sys/dev/hptmv/array.h | 2 + sys/dev/hptmv/atapi.h | 2 + sys/dev/hptmv/command.h | 2 + sys/dev/hptmv/gui_lib.c | 2 + sys/dev/hptmv/hptproc.c | 2 + sys/dev/hptmv/ioctl.c | 2 + sys/dev/hptmv/mvSata.h | 2 + sys/dev/hptmv/mvStorageDev.h | 4 +- sys/dev/hptmv/raid5n.h | 2 + sys/dev/hptmv/readme.txt | 1 + sys/dev/hptmv/vdevice.h | 2 + sys/modules/hptmv/Makefile | 4 +- 27 files changed, 31 insertions(+), 6528 deletions(-) delete mode 100644 sys/contrib/dev/hptmv/access601.h delete mode 100644 sys/contrib/dev/hptmv/array.h delete mode 100644 sys/contrib/dev/hptmv/atapi.h delete mode 100644 sys/contrib/dev/hptmv/command.h delete mode 100644 sys/contrib/dev/hptmv/gui_lib.c delete mode 100644 sys/contrib/dev/hptmv/hptproc.c delete mode 100644 sys/contrib/dev/hptmv/i386-elf.raid.o.uu delete mode 100644 sys/contrib/dev/hptmv/ioctl.c delete mode 100644 sys/contrib/dev/hptmv/mvSata.h delete mode 100644 sys/contrib/dev/hptmv/mvStorageDev.h delete mode 100644 sys/contrib/dev/hptmv/raid5n.h delete mode 100644 sys/contrib/dev/hptmv/readme.txt delete mode 100644 sys/contrib/dev/hptmv/vdevice.h (limited to 'sys/dev/hptmv/gui_lib.c') diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 18680feebfc6..edaaba8f7e2a 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -62,8 +62,8 @@ opt_ah.h optional ath_hal \ clean "opt_ah.h" # hptmvraid.o optional hptmv \ - dependency "$S/contrib/dev/hptmv/i386-elf.raid.o.uu" \ - compile-with "uudecode < $S/contrib/dev/hptmv/i386-elf.raid.o.uu" \ + dependency "$S/dev/hptmv/i386-elf.raid.o.uu" \ + compile-with "uudecode < $S/dev/hptmv/i386-elf.raid.o.uu" \ no-implicit-rule # # @@ -104,9 +104,6 @@ compat/svr4/svr4_sysent.c optional compat_svr4 compat/svr4/svr4_sysvec.c optional compat_svr4 compat/svr4/svr4_termios.c optional compat_svr4 compat/svr4/svr4_ttold.c optional compat_svr4 -contrib/dev/hptmv/gui_lib.c optional hptmv -contrib/dev/hptmv/hptproc.c optional hptmv -contrib/dev/hptmv/ioctl.c optional hptmv contrib/dev/oltr/if_oltr.c optional oltr contrib/dev/oltr/if_oltr_isa.c optional oltr isa contrib/dev/oltr/if_oltr_pci.c optional oltr pci @@ -160,6 +157,9 @@ dev/fdc/fdc_pccard.c optional fdc pccard dev/fe/if_fe_isa.c optional fe isa dev/hptmv/entry.c optional hptmv dev/hptmv/mv.c optional hptmv +dev/hptmv/gui_lib.c optional hptmv +dev/hptmv/hptproc.c optional hptmv +dev/hptmv/ioctl.c optional hptmv dev/ichwd/ichwd.c optional ichwd dev/if_ndis/if_ndis.c optional ndis dev/if_ndis/if_ndis_pccard.c optional ndis pccard diff --git a/sys/contrib/dev/hptmv/access601.h b/sys/contrib/dev/hptmv/access601.h deleted file mode 100644 index 54e1902b687d..000000000000 --- a/sys/contrib/dev/hptmv/access601.h +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifndef _ACCESS601_H_ -#define _ACCESS601_H_ - -void HPTLIBAPI BeepOn(MV_BUS_ADDR_T BaseAddr); -void HPTLIBAPI BeepOff(MV_BUS_ADDR_T BaseAddr); -UCHAR HPTLIBAPI check_protect_circuit(MV_BUS_ADDR_T BaseAddr); - -#ifdef SUPPORT_FAIL_LED -void HPTLIBAPI set_fail_led(MV_SATA_ADAPTER *pAdapter, UCHAR channel, UCHAR state); -void HPTLIBAPI set_fail_leds(MV_SATA_ADAPTER *pAdapter, UCHAR mask); -#else -#define set_fail_led(pAdapter, channel, state) -#define set_fail_leds(pAdapter, mask) -#endif - -#endif diff --git a/sys/contrib/dev/hptmv/array.h b/sys/contrib/dev/hptmv/array.h deleted file mode 100644 index 29e0a9bbd3f2..000000000000 --- a/sys/contrib/dev/hptmv/array.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ARRAY_H_ -#define _ARRAY_H_ - -/* - * time represented in DWORD format - */ -#pragma pack(1) -#ifdef __BIG_ENDIAN_BITFIELD -typedef DWORD TIME_RECORD; -#else -typedef struct _TIME_RECORD { - UINT seconds:6; /* 0 - 59 */ - UINT minutes:6; /* 0 - 59 */ - UINT month:4; /* 1 - 12 */ - UINT hours:6; /* 0 - 59 */ - UINT day:5; /* 1 - 31 */ - UINT year:5; /* 0=2000, 31=2031 */ -} TIME_RECORD; -#endif -#pragma pack() - -/*************************************************************************** - * Description: Virtual Device Table - ***************************************************************************/ - -typedef struct _RaidArray -{ - /* - * basic information - */ - UCHAR bArnMember; /* the number of members in array */ - UCHAR bArRealnMember; /* real member count */ - UCHAR bArBlockSizeShift; /* the number of shift bit for a block */ - UCHAR reserve1; - - ULONG dArStamp; /* array ID. all disks in a array has same ID */ - USHORT bStripeWitch; /* = (1 << BlockSizeShift) */ - - USHORT rf_broken: 1; - USHORT rf_need_rebuild: 1; /* one member's data are incorrect. - for R5, if CriticalMembers==0, it means - parity needs to be constructed */ - USHORT rf_need_sync: 1; /* need write array info to disk */ - /* ioctl flags */ - USHORT rf_auto_rebuild: 1; - USHORT rf_newly_created: 1; - USHORT rf_rebuilding: 1; - USHORT rf_verifying: 1; - USHORT rf_initializing: 1; - USHORT rf_abort_rebuild: 1; - USHORT rf_duplicate_and_create: 1; - USHORT rf_duplicate_and_created: 1; - USHORT rf_duplicate_must_done: 1; - USHORT rf_raid15: 1; - - USHORT CriticalMembers; /* tell which member is critial */ - UCHAR last_read; /* for RAID 1 load banlancing */ - UCHAR pad1; - - LBA_T RebuildSectors; /* how many sectors is OK (LBA on member disk) */ - - PVDevice pMember[MAX_MEMBERS]; - /* - * utility working data - */ - UCHAR ArrayName[MAX_ARRAY_NAME]; /* The Name of the array */ - TIME_RECORD CreateTime; /* when created it */ - UCHAR Description[64]; /* array description */ - UCHAR CreateManager[16]; /* who created it */ -} RaidArray; - -/*************************************************************************** - * Array Descripton on disk - ***************************************************************************/ -#pragma pack(1) -typedef struct _ArrayDescript -{ - ULONG Signature; /* This block is vaild array info block */ - ULONG dArStamp; /* array ID. all disks in a array has same ID */ - - UCHAR bCheckSum; /* check sum of ArrayDescript_3_0_size bytes */ - -#ifdef __BIG_ENDIAN_BITFIELD - UCHAR df_reservedbits: 6; /* put more flags here */ - UCHAR df_user_mode_set: 1;/* user select device mode */ - UCHAR df_bootmark:1; /* user set boot mark on the disk */ -#else - UCHAR df_bootmark:1; /* user set boot mark on the disk */ - UCHAR df_user_mode_set: 1;/* user select device mode */ - UCHAR df_reservedbits: 6; /* put more flags here */ -#endif - - UCHAR bUserDeviceMode; /* see device.h */ - UCHAR ArrayLevel; /* how many level[] is valid */ - - struct { - ULONG Capacity; /* capacity for the array */ - - UCHAR VDeviceType; /* see above & arrayType in array.h */ - UCHAR bMemberCount; /* all disk in the array */ - UCHAR bSerialNumber; /* Serial Number */ - UCHAR bArBlockSizeShift; /* the number of shift bit for a block */ - -#ifdef __BIG_ENDIAN_BITFIELD - USHORT rf_reserved: 14; - USHORT rf_raid15: 1; /* don't remove even you don't use it */ - USHORT rf_need_rebuild:1; /* array is critical */ -#else - USHORT rf_need_rebuild:1; /* array is critical */ - USHORT rf_raid15: 1; /* don't remove even you don't use it */ - USHORT rf_reserved: 14; -#endif - USHORT CriticalMembers; /* record critical members */ - ULONG RebuildSectors; /* how many sectors is OK (LBA on member disk) */ - } level[2]; - - UCHAR ArrayName[MAX_ARRAY_NAME]; /* The Name of the array */ - TIME_RECORD CreateTime; /* when created it */ - UCHAR Description[64]; /* array description */ - UCHAR CreateManager[16]; /* who created it */ - -#define ArrayDescript_3_0_size ((unsigned)(ULONG_PTR)&((struct _ArrayDescript *)0)->bCheckSum31) -#define ArrayDescript_3_1_size 512 - - UCHAR bCheckSum31; /* new check sum */ - UCHAR reserve2[2]; -#ifdef __BIG_ENDIAN_BITFIELD - UCHAR df_read_ahead: 1; /* enable read ahead */ - UCHAR df_read_ahead_set: 1; - UCHAR df_write_cache: 1; /* enable write cache */ - UCHAR df_write_cache_set: 1; - UCHAR df_ncq: 1; /* enable NCQ */ - UCHAR df_ncq_set: 1; - UCHAR df_tcq: 1; /* enable TCQ */ - UCHAR df_tcq_set: 1; -#else - UCHAR df_tcq_set: 1; - UCHAR df_tcq: 1; /* enable TCQ */ - UCHAR df_ncq_set: 1; - UCHAR df_ncq: 1; /* enable NCQ */ - UCHAR df_write_cache_set: 1; - UCHAR df_write_cache: 1; /* enable write cache */ - UCHAR df_read_ahead_set: 1; - UCHAR df_read_ahead: 1; /* enable read ahead */ -#endif - - struct { - ULONG CapacityHi32; - ULONG RebuildSectorsHi32; - } - levelex[2]; - -} ArrayDescript; - -#pragma pack() - -/* Signature */ -#define HPT_ARRAY_V3 0x5a7816f3 -#ifdef ARRAY_V2_ONLY -#define SAVE_FOR_RAID_INFO 0 -#else -#define SAVE_FOR_RAID_INFO 10 -#endif - -/*************************************************************************** - * Function protocol for array layer - ***************************************************************************/ - -/* - * array.c - */ -ULONG FASTCALL GetStamp(void); -void HPTLIBAPI SyncArrayInfo(PVDevice pVDev); -void HPTLIBAPI fDeleteArray(_VBUS_ARG PVDevice pVArray, BOOLEAN del_block0); - -/* - * iArray.c - */ -void HPTLIBAPI fCheckArray(PDevice pDevice); -void HPTLIBAPI CheckArrayCritical(_VBUS_ARG0); -PVDevice HPTLIBAPI GetSpareDisk(_VBUS_ARG PVDevice pArray); -#ifdef SUPPORT_OLD_ARRAY -void HPTLIBAPI fFixRAID01Stripe(_VBUS_ARG PVDevice pStripe); -#endif - -/*************************************************************************** - * Macro defination - ***************************************************************************/ -#ifndef MAX_ARRAY_PER_VBUS -#define MAX_ARRAY_PER_VBUS (MAX_VDEVICE_PER_VBUS*2) /* worst case */ -#endif - - -#if defined(MAX_ARRAY_DEVICE) -#if MAX_ARRAY_DEVICE!=MAX_ARRAY_PER_VBUS -#error "remove MAX_ARRAY_DEVICE and use MAX_ARRAY_PER_VBUS instead" -#endif -#endif - -#define _SET_ARRAY_BUS_(pArray) pArray->pVBus = _vbus_p; - -#ifdef ARRAY_V2_ONLY -#define _SET_ARRAY_VER_(pArray) pArray->vf_format_v2 = 1; -#else -#define _SET_ARRAY_VER_(pArray) -#endif - -#define mArGetArrayTable(pVArray) \ - if((pVArray = _vbus_(pFreeArrayLink)) != 0) { \ - _vbus_(pFreeArrayLink) = (PVDevice)_vbus_(pFreeArrayLink)->pVBus; \ - ZeroMemory(pVArray, ARRAY_VDEV_SIZE); \ - _SET_ARRAY_BUS_(pVArray) \ - _SET_ARRAY_VER_(pVArray) \ - } else - -#define mArFreeArrayTable(pVArray) \ - do { \ - pVArray->pVBus = (PVBus)_vbus_(pFreeArrayLink);\ - _vbus_(pFreeArrayLink) = pVArray; \ - pVArray->u.array.dArStamp = 0; \ - } while(0) - -UCHAR CheckSum(UCHAR *p, int size); - -void HPTLIBAPI fRAID0SendCommand(_VBUS_ARG PCommand pCmd); -void HPTLIBAPI fRAID1SendCommand(_VBUS_ARG PCommand pCmd); -void HPTLIBAPI fJBODSendCommand(_VBUS_ARG PCommand pCmd); -void HPTLIBAPI fRAID0MemberFailed(_VBUS_ARG PVDevice pVDev); -void HPTLIBAPI fRAID1MemberFailed(_VBUS_ARG PVDevice pVDev); -void HPTLIBAPI fJBODMemberFailed(_VBUS_ARG PVDevice pVDev); -#if SUPPORT_RAID5 -void HPTLIBAPI fRAID5SendCommand(_VBUS_ARG PCommand pCmd); -void HPTLIBAPI fRAID5MemberFailed(_VBUS_ARG PVDevice pVDev); -#else -#define fRAID5SendCommand 0 -#define fRAID5MemberFailed 0 -#endif - -#endif diff --git a/sys/contrib/dev/hptmv/atapi.h b/sys/contrib/dev/hptmv/atapi.h deleted file mode 100644 index a46c1148c9ce..000000000000 --- a/sys/contrib/dev/hptmv/atapi.h +++ /dev/null @@ -1,556 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _ATAPI_H_ -#define _ATAPI_H_ - -#pragma pack(1) - -/*************************************************************************** - * IDE IO Register File - ***************************************************************************/ - -/* - * IDE IO Port definition - */ -typedef struct _IDE_REGISTERS_1 { - USHORT Data; /* RW: Data port feature register */ - UCHAR BlockCount; /* RW: Sector count */ - UCHAR BlockNumber; /* RW: Sector number & LBA 0-7 */ - UCHAR CylinderLow; /* RW: Cylinder low & LBA 8-15 */ - UCHAR CylinderHigh; /* RW: Cylinder hign & LBA 16-23 */ - UCHAR DriveSelect; /* RW: Drive/head & LBA 24-27 */ - UCHAR Command; /* RO: Status WR:Command */ -} IDE_REGISTERS_1, *PIDE_REGISTERS_1; - - -/* - * IDE status definitions - */ -#define IDE_STATUS_ERROR 0x01 /* Error Occurred in Execution */ -#define IDE_STATUS_INDEX 0x02 /* is vendor specific */ -#define IDE_STATUS_CORRECTED_ERROR 0x04 /* Corrected Data */ -#define IDE_STATUS_DRQ 0x08 /* Ready to transfer data */ -#define IDE_STATUS_DSC 0x10 /* not defined in ATA-2 */ -#define IDE_STATUS_DWF 0x20 /* Device Fault has been detected */ -#define IDE_STATUS_DRDY 0x40 /* Device Ready to accept command */ -#define IDE_STATUS_IDLE 0x50 /* Device is OK */ -#define IDE_STATUS_BUSY 0x80 /* Device Busy, must wait */ - - -#define IDE_ERROR_BAD_BLOCK 0x80 /* Reserved now */ -#define IDE_ERROR_DATA_ERROR 0x40 /* Uncorreectable Data Error */ -#define IDE_ERROR_MEDIA_CHANGE 0x20 /* Media Changed */ -#define IDE_ERROR_ID_NOT_FOUND 0x10 /* ID Not Found */ -#define IDE_ERROR_MEDIA_CHANGE_REQ 0x08 /* Media Change Requested */ -#define IDE_ERROR_COMMAND_ABORTED 0x04 /* Aborted Command */ -#define IDE_ERROR_TRACK0_NOT_FOUND 0x02 /* Track 0 Not Found */ -#define IDE_ERROR_ADDRESS_NOT_FOUND 0x01 /* Address Mark Not Found */ - - -#define LBA_MODE 0x40 - -/* - * IDE command definitions - */ - -#define IDE_COMMAND_RECALIBRATE 0x10 /* Recalibrate */ -#define IDE_COMMAND_READ 0x20 /* Read Sectors with retry */ -#define IDE_COMMAND_WRITE 0x30 /* Write Sectors with retry */ -#define IDE_COMMAND_VERIFY 0x40 /* Read Verify Sectors with Retry */ -#define IDE_COMMAND_SEEK 0x70 /* Seek */ -#define IDE_COMMAND_SET_DRIVE_PARAMETER 0x91 /* Initialize Device Parmeters */ -#define IDE_COMMAND_GET_MEDIA_STATUS 0xDA -#define IDE_COMMAND_DOOR_LOCK 0xDE /* Door Lock */ -#define IDE_COMMAND_DOOR_UNLOCK 0xDF /* Door Unlock */ -#define IDE_COMMAND_ENABLE_MEDIA_STATUS 0xEF /* Set Features */ -#define IDE_COMMAND_IDENTIFY 0xEC /* Identify Device */ -#define IDE_COMMAND_MEDIA_EJECT 0xED -#define IDE_COMMAND_SET_FEATURES 0xEF /* IDE set features command */ - -#define IDE_COMMAND_FLUSH_CACHE 0xE7 -#define IDE_COMMAND_STANDBY_IMMEDIATE 0xE0 - -#ifndef NOT_SUPPORT_MULTIPLE -#define IDE_COMMAND_READ_MULTIPLE 0xC4 /* Read Multiple */ -#define IDE_COMMAND_WRITE_MULTIPLE 0xC5 /* Write Multiple */ -#define IDE_COMMAND_SET_MULTIPLE 0xC6 /* Set Multiple Mode */ -#endif - -#ifndef NOT_SUPPORT_DMA -#define IDE_COMMAND_DMA_READ 0xc8 /* IDE DMA read command */ -#define IDE_COMMAND_DMA_WRITE 0xca /* IDE DMA write command */ -#endif - -#define IDE_COMMAND_READ_DMA_QUEUE 0xc7 /* IDE read DMA queue command */ -#define IDE_COMMAND_WRITE_DMA_QUEUE 0xcc /* IDE write DMA queue command */ -#define IDE_COMMAND_SERVICE 0xA2 /* IDE service command command */ -#define IDE_COMMAND_NOP 0x00 /* IDE NOP command */ -#define IDE_STATUS_SRV 0x10 -#define IDE_RELEASE_BUS 4 - -/*#define IDE_COMMAND_FLUSH_CACHE_EXT */ -#define IDE_COMMAND_READ_DMA_EXT 0x25 -#define IDE_COMMAND_READ_QUEUE_EXT 0x26 -#define IDE_COMMAND_READ_MULTIPLE_EXT 0x29 -#define IDE_COMMAND_READ_MAX_ADDR 0x27 -#define IDE_COMMAND_READ_EXT 0x24 -#define IDE_COMMAND_VERIFY_EXT 0x42 -#define IDE_COMMAND_SET_MULTIPLE_EXT 0x37 -#define IDE_COMMAND_WRITE_DMA_EXT 0x35 -#define IDE_COMMAND_WRITE_QUEUE_EXT 0x36 -#define IDE_COMMAND_WRITE_EXT 0x34 -#define IDE_COMMAND_WRITE_MULTIPLE_EXT 0x39 - -/* - * IDE_COMMAND_SET_FEATURES - */ -#define FT_USE_ULTRA 0x40 /* Set feature for Ultra DMA */ -#define FT_USE_MWDMA 0x20 /* Set feature for MW DMA */ -#define FT_USE_SWDMA 0x10 /* Set feature for SW DMA */ -#define FT_USE_PIO 0x8 /* Set feature for PIO */ -#define FT_DISABLE_IORDY 0x10 /* Set feature for disabling IORDY */ - -/* - * S.M.A.R.T. commands - */ -#define IDE_COMMAND_SMART 0xB0 -#define SMART_READ_VALUES 0xd0 -#define SMART_READ_THRESHOLDS 0xd1 -#define SMART_AUTOSAVE 0xd2 -#define SMART_SAVE 0xd3 -#define SMART_IMMEDIATE_OFFLINE 0xd4 -#define SMART_READ_LOG_SECTOR 0xd5 -#define SMART_WRITE_LOG_SECTOR 0xd6 -#define SMART_ENABLE 0xd8 -#define SMART_DISABLE 0xd9 -#define SMART_STATUS 0xda -#define SMART_AUTO_OFFLINE 0xdb - - /*************************************************************************** - * IDE Control Register File - ***************************************************************************/ - -typedef struct _IDE_REGISTERS_2 { - UCHAR AlternateStatus; /* RW: device control port */ -} IDE_REGISTERS_2, *PIDE_REGISTERS_2; - - -/* - * IDE drive control definitions - */ -#define IDE_DC_DISABLE_INTERRUPTS 0x02 -#define IDE_DC_RESET_CONTROLLER 0x04 -#define IDE_DC_REENABLE_CONTROLLER 0x00 - -/*************************************************************************** - * MSNS: Removable device - ***************************************************************************/ -/* - * Media syatus - */ -#define MSNS_NO_MEDIA 2 -#define MSNS_MEDIA_CHANGE_REQUEST 8 -#define MSNS_MIDIA_CHANGE 0x20 -#define MSNS_WRITE_PROTECT 0x40 -#define MSNS_READ_PROTECT 0x80 - -/*************************************************************************** - * ATAPI IO Register File - ***************************************************************************/ - -/* - * ATAPI register definition - */ - -typedef struct _ATAPI_REGISTERS_1 { - USHORT Data; - UCHAR InterruptReason; /* Atapi Phase Port */ - UCHAR Unused1; - UCHAR ByteCountLow; /* Byte Count LSB */ - UCHAR ByteCountHigh; /* Byte Count MSB */ - UCHAR DriveSelect; - UCHAR Command; -} ATAPI_REGISTERS_1, *PATAPI_REGISTERS_1; - -/* - * Atapi Error Status - */ -#define IDE_ERROR_END_OF_MEDIA IDE_ERROR_TRACK0_NOT_FOUND -#define IDE_ERROR_ILLEGAL_LENGTH IDE_ERROR_ADDRESS_NOT_FOUND - -/* - * ATAPI interrupt reasons - */ -#define ATAPI_IR_COD 0x01 -#define ATAPI_IR_IO 0x02 - -/* sense key */ -#define ATAPI_SENSE_NO_SENSE 0x00 -#define ATAPI_SENSE_RECOVERED_ERROR 0x01 -#define ATAPI_SENSE_NOT_READY 0x02 -#define ATAPI_SENSE_MEDIUM_ERROR 0x03 -#define ATAPI_SENSE_HARDWARE_ERROR 0x04 -#define ATAPI_SENSE_ILLEGAL_REQUEST 0x05 -#define ATAPI_SENSE_UNIT_ATTENTION 0x06 -#define ATAPI_SENSE_DATA_PROTECT 0x07 -#define ATAPI_SENSE_BLANK_CHECK 0x08 -#define ATAPI_SENSE_UNIQUE 0x09 -#define ATAPI_SENSE_COPY_ABORTED 0x0A -#define ATAPI_SENSE_ABORTED_COMMAND 0x0B -#define ATAPI_SENSE_EQUAL 0x0C -#define ATAPI_SENSE_VOL_OVERFLOW 0x0D -#define ATAPI_SENSE_MISCOMPARE 0x0E -#define ATAPI_SENSE_RESERVED 0x0F - -/* Additional Sense codes */ -#define ATAPI_ASC_NO_SENSE 0x00 -#define ATAPI_ASC_LUN_NOT_READY 0x04 -#define ATAPI_ASC_TRACK_ERROR 0x14 -#define ATAPI_ASC_SEEK_ERROR 0x15 -#define ATAPI_ASC_REC_DATA_NOECC 0x17 -#define ATAPI_ASC_REC_DATA_ECC 0x18 -#define ATAPI_ASC_ILLEGAL_COMMAND 0x20 -#define ATAPI_ASC_ILLEGAL_BLOCK 0x21 -#define ATAPI_ASC_INVALID_CDB 0x24 -#define ATAPI_ASC_INVALID_LUN 0x25 -#define ATAPI_ASC_PROTECT 0x27 -#define ATAPI_ASC_MEDIUM_CHANGED 0x28 -#define ATAPI_ASC_BUS_RESET 0x29 -#define ATAPI_ASC_NO_MEDIA_IN_DEVICE 0x3a -#define ATAPI_ASC_MUSIC_AREA 0xA0 -#define ATAPI_ASC_DATA_AREA 0xA1 -#define ATAPI_ASC_VOLUME_OVERFLOW 0xA7 - -/* - * IDE command definitions ( for ATAPI ) - */ - -#define IDE_COMMAND_ATAPI_RESET 0x08 /* Atapi Software Reset command */ -#define IDE_COMMAND_ATAPI_PACKET 0xA0 /* Atapi Identify command */ -#define IDE_COMMAND_ATAPI_IDENTIFY 0xA1 /* Atapi Packet Command */ - - -/* - * ATAPI command definitions - */ - -#define ATAPI_TEST_UNIT_READY 0x00 -#define ATAPI_REZERO_UNIT 0x01 -#define ATAPI_REQUEST_SENSE 0x03 -#define ATAPI_FORMAT_UNIT6 0x04 -#define ATAPI_FORMAT_UNIT 0x24 -#define ATAPI_INQUIRY 0x12 -#define ATAPI_MODE_SELECT 0x15 -#define ATAPI_MODE_SENSE 0x1A -#define ATAPI_START_STOP_UNIT 0x1B -#define ATAPI_LOAD_UNLOAD 0x1B -#define ATAPI_MEDIUM_REMOVAL 0x1E -#define ATAPI_READ_CAPACITY 0x25 -#define ATAPI_READ 0x28 -#define ATAPI_WRITE 0x2A -#define ATAPI_SEEK 0x2B -#define ATAPI_VERIFY 0x2F -#define ATAPI_READ_DATA_BUFF 0x3C -#define ATAPI_READ_SUB_CHANNEL 0x42 -#define ATAPI_READ_TOC 0x43 -#define ATAPI_READ_HEADER 0x44 -#define ATAPI_GET_CONFIGURATION 0x46 -#define ATAPI_PLAY_AUDIO_MSF 0x47 -#define ATAPI_GET_EVENT_STATUS_NOTIFICATION 0x4A -#define ATAPI_PAUSE_RESUME 0x4B -#define ATAPI_STOP_PLAY_SCAN 0x4E -#define ATAPI_READ_DISK_INFORMATION 0x51 -#define ATAPI_READ_TRACK_INFORMATION 0x52 -#define ATAPI_MODE_SELECT10 0x55 -#define ATAPI_MODE_SENSE10 0x5A -#define ATAPI_CLOSE_TRACK_SESSION 0x5B -#define ATAPI_READ_BUFFER_CAPACITY 0x5C -#define ATAPI_BLANK_COMMAND 0xA1 /*Provide the ability to erase any part of a CD-RW disc.*/ -#define ATAPI_REPORT_KEY 0xA4 -#define ATAPI_PLAY_AUDIO 0xA5 -#define ATAPI_READ12 0xA8 -#define ATAPI_READ_DVD_STRUCTURE 0xAD -#define ATAPI_READ_CD_MSF 0xB9 -#define ATAPI_SET_CD_SPEED 0xBB -#define ATAPI_MECHANISM_STATUS 0xBD -#define ATAPI_READ_CD 0xBE -#define ATAPI_SET_CDRW_SPEED 0xDA /*WindowsXP need*/ - -#define MODE_DSP_WRITE_PROTECT 0x80 - - -/*************************************************************************** - * ATAPI IO Register File - ***************************************************************************/ - - -typedef struct _ATAPI_REGISTERS_2 { - UCHAR AlternateStatus; -} ATAPI_REGISTERS_2, *PATAPI_REGISTERS_2; - - -/*************************************************************************** - * ATAPI packets - ***************************************************************************/ -typedef struct _ATAPI_SENSE_DATA { -#ifdef __BIG_ENDIAN_BITFIELD - UCHAR Valid:1; - UCHAR ErrorCode:7; - UCHAR SegmentNumber; - UCHAR FileMark:1; - UCHAR EndOfMedia:1; - UCHAR IncorrectLength:1; - UCHAR Reserved:1; - UCHAR SenseKey:4; -#else - UCHAR ErrorCode:7; - UCHAR Valid:1; - UCHAR SegmentNumber; - UCHAR SenseKey:4; - UCHAR Reserved:1; - UCHAR IncorrectLength:1; - UCHAR EndOfMedia:1; - UCHAR FileMark:1; -#endif - UCHAR Information[4]; - UCHAR AdditionalSenseLength; - UCHAR CommandSpecificInformation[4]; - UCHAR AdditionalSenseCode; - UCHAR AdditionalSenseCodeQualifier; - UCHAR FieldReplaceableUnitCode; - UCHAR SenseKeySpecific[3]; -} ATAPI_SENSE_DATA, *PATAPI_SENSE_DATA; - -/* - * IDENTIFY data - */ -typedef struct _IDENTIFY_DATA { - USHORT GeneralConfiguration; /* 00 00 */ - USHORT NumberOfCylinders; /* 02 1 */ - USHORT Reserved1; /* 04 2 */ - USHORT NumberOfHeads; /* 06 3 */ - USHORT UnformattedBytesPerTrack; /* 08 4 */ - USHORT UnformattedBytesPerSector; /* 0A 5 */ - USHORT SectorsPerTrack; /* 0C 6 */ - USHORT VendorUnique1[3]; /* 0E 7-9 */ - USHORT SerialNumber[10]; /* 14 10-19 */ - USHORT BufferType; /* 28 20 */ - USHORT BufferSectorSize; /* 2A 21 */ - USHORT NumberOfEccBytes; /* 2C 22 */ - USHORT FirmwareRevision[4]; /* 2E 23-26 */ - USHORT ModelNumber[20]; /* 36 27-46 */ - UCHAR MaximumBlockTransfer; /* 5E 47 */ - UCHAR VendorUnique2; /* 5F */ - USHORT DoubleWordIo; /* 60 48 */ - USHORT Capabilities; /* 62 49 */ - USHORT Reserved2; /* 64 50 */ - UCHAR VendorUnique3; /* 66 51 */ - UCHAR PioCycleTimingMode; /* 67 */ - UCHAR VendorUnique4; /* 68 52 */ - UCHAR DmaCycleTimingMode; /* 69 */ - USHORT TranslationFieldsValid; /* 6A 53 */ - USHORT NumberOfCurrentCylinders; /* 6C 54 */ - USHORT NumberOfCurrentHeads; /* 6E 55 */ - USHORT CurrentSectorsPerTrack; /* 70 56 */ - ULONG CurrentSectorCapacity; /* 72 57-58 */ - USHORT CurrentMultiSectorSetting; /* 76 59 */ - ULONG UserAddressableSectors; /* 78 60-61 */ - UCHAR SingleWordDMASupport; /* 7C 62 */ - UCHAR SingleWordDMAActive; /* 7D */ - UCHAR MultiWordDMASupport; /* 7E 63 */ - UCHAR MultiWordDMAActive; /* 7F */ - UCHAR AdvancedPIOModes; /* 80 64 */ - UCHAR Reserved4; /* 81 */ - USHORT MinimumMWXferCycleTime; /* 82 65 */ - USHORT RecommendedMWXferCycleTime; /* 84 66 */ - USHORT MinimumPIOCycleTime; /* 86 67 */ - USHORT MinimumPIOCycleTimeIORDY; /* 88 68 */ - USHORT Reserved5[2]; /* 8A 69-70 */ - USHORT ReleaseTimeOverlapped; /* 8E 71 */ - USHORT ReleaseTimeServiceCommand; /* 90 72 */ - USHORT MajorRevision; /* 92 73 */ - USHORT MinorRevision; /* 94 74 */ - USHORT MaxQueueDepth; /* 96 75 */ - USHORT SataCapability; /* 76 */ - USHORT Reserved6[9]; /* 98 77-85 */ - USHORT CommandSupport; /* 86 */ - USHORT CommandEnable; /* 87 */ - USHORT UtralDmaMode; /* 88 */ - USHORT Reserved7[11]; /* 89-99 */ - ULONG Lba48BitLow; /* 101-100 */ - ULONG Lba48BitHigh; /* 103-102 */ - USHORT Reserved8[23]; /* 104-126 */ - USHORT SpecialFunctionsEnabled; /* 127 */ - USHORT Reserved9[128]; /* 128-255 */ - -} IDENTIFY_DATA, *PIDENTIFY_DATA; - -typedef struct _CONFIGURATION_IDENTIFY_DATA { - USHORT Revision; - USHORT MWDMAModeSupported; - USHORT UDMAModeSupported; - ULONG MaximumLbaLow; - ULONG MaximumLbaHigh; - USHORT CommandSupport; - USHORT Reserved[247]; - UCHAR Signature; /* 0xA5 */ - UCHAR CheckSum; -} -CONFIGURATION_IDENTIFY_DATA, *PCONFIGURATION_IDENTIFY_DATA; - -/* */ -/* Identify data without the Reserved4. */ -/* */ -typedef struct _IDENTIFY_DATA2 { - USHORT GeneralConfiguration; /* 00 00 */ - USHORT NumberOfCylinders; /* 02 1 */ - USHORT Reserved1; /* 04 2 */ - USHORT NumberOfHeads; /* 06 3 */ - USHORT UnformattedBytesPerTrack; /* 08 4 */ - USHORT UnformattedBytesPerSector; /* 0A 5 */ - USHORT SectorsPerTrack; /* 0C 6 */ - USHORT VendorUnique1[3]; /* 0E 7-9 */ - USHORT SerialNumber[10]; /* 14 10-19 */ - USHORT BufferType; /* 28 20 */ - USHORT BufferSectorSize; /* 2A 21 */ - USHORT NumberOfEccBytes; /* 2C 22 */ - USHORT FirmwareRevision[4]; /* 2E 23-26 */ - USHORT ModelNumber[20]; /* 36 27-46 */ - UCHAR MaximumBlockTransfer; /* 5E 47 */ - UCHAR VendorUnique2; /* 5F */ - USHORT DoubleWordIo; /* 60 48 */ - USHORT Capabilities; /* 62 49 */ - USHORT Reserved2; /* 64 50 */ - UCHAR VendorUnique3; /* 66 51 */ - UCHAR PioCycleTimingMode; /* 67 */ - UCHAR VendorUnique4; /* 68 52 */ - UCHAR DmaCycleTimingMode; /* 69 */ - USHORT TranslationFieldsValid; /* 6A 53 */ - USHORT NumberOfCurrentCylinders; /* 6C 54 */ - USHORT NumberOfCurrentHeads; /* 6E 55 */ - USHORT CurrentSectorsPerTrack; /* 70 56 */ - ULONG CurrentSectorCapacity; /* 72 57-58 */ - USHORT CurrentMultiSectorSetting; /* 59 */ - ULONG UserAddressableSectors; /* 60-61 */ - UCHAR SingleWordDMASupport; /* 62 */ - UCHAR SingleWordDMAActive; - UCHAR MultiWordDMASupport; /* 63 */ - UCHAR MultiWordDMAActive; - UCHAR AdvancedPIOModes; /* 64 */ - UCHAR Reserved4; - USHORT MinimumMWXferCycleTime; /* 65 */ - USHORT RecommendedMWXferCycleTime; /* 66 */ - USHORT MinimumPIOCycleTime; /* 67 */ - USHORT MinimumPIOCycleTimeIORDY; /* 68 */ - USHORT Reserved5[2]; /* 69-70 */ - USHORT ReleaseTimeOverlapped; /* 71 */ - USHORT ReleaseTimeServiceCommand; /* 72 */ - USHORT MajorRevision; /* 73 */ - USHORT MinorRevision; /* 74 */ -/* USHORT Reserved6[14]; // 75-88 */ -} IDENTIFY_DATA2, *PIDENTIFY_DATA2; - -#define IDENTIFY_DATA_SIZE sizeof(IDENTIFY_DATA2) - -/* */ -/* IDENTIFY DMA timing cycle modes. */ -/* */ - -#define IDENTIFY_DMA_CYCLES_MODE_0 0x00 -#define IDENTIFY_DMA_CYCLES_MODE_1 0x01 -#define IDENTIFY_DMA_CYCLES_MODE_2 0x02 - -/* - * Mode definitions - */ -typedef enum _DISK_MODE -{ - IDE_PIO_0 = 0, - IDE_PIO_1, - IDE_PIO_2, - IDE_PIO_3, - IDE_PIO_4, - IDE_MWDMA_0, - IDE_MWDMA_1, - IDE_MWDMA_2, - IDE_UDMA_0, - IDE_UDMA_1, - IDE_UDMA_2, - IDE_UDMA_3, - IDE_UDMA_4, - IDE_UDMA_5, - IDE_UDMA_6, - IDE_UDMA_7, -} DISK_MODE; - -/*************************************************************************** - * IDE Macro - ***************************************************************************/ -#ifndef MAX_LBA_T -#define MAX_LBA_T ((LBA_T)-1) -#endif - -#define SECTOR_TO_BYTE_SHIFT 9 -#define SECTOR_TO_BYTE(x) ((ULONG)(x) << SECTOR_TO_BYTE_SHIFT) - -#define mGetStatus(IOPort2) (UCHAR)InPort(&IOPort2->AlternateStatus) -#define mUnitControl(IOPort2, Value) OutPort(&IOPort2->AlternateStatus,(UCHAR)(Value)) - -#define mGetErrorCode(IOPort) (UCHAR)InPort((PUCHAR)&IOPort->Data+1) -#define mSetFeaturePort(IOPort,x) OutPort((PUCHAR)&IOPort->Data+1, x) -#define mSetBlockCount(IOPort,x) OutPort(&IOPort->BlockCount, x) -#define mGetBlockCount(IOPort) (UCHAR)InPort(&IOPort->BlockCount) -#define mGetInterruptReason(IOPort) (UCHAR)InPort(&IOPort->BlockCount) -#define mSetBlockNumber(IOPort,x) OutPort(&IOPort->BlockNumber, x) -#define mGetBlockNumber(IOPort) (UCHAR)InPort((PUCHAR)&IOPort->BlockNumber) -#define mGetByteLow(IOPort) (UCHAR)InPort(&IOPort->CylinderLow) -#define mSetCylinderLow(IOPort,x) OutPort(&IOPort->CylinderLow, x) -#define mGetByteHigh(IOPort) (UCHAR)InPort(&IOPort->CylinderHigh) -#define mSetCylinderHigh(IOPort,x) OutPort(&IOPort->CylinderHigh, x) -#define mGetBaseStatus(IOPort) (UCHAR)InPort(&IOPort->Command) -#ifdef SUPPORT_HPT601 -#define mSelectUnit(IOPort,UnitId) do {\ - OutPort(&IOPort->DriveSelect, (UCHAR)(UnitId));\ - OutPort(&IOPort->DriveSelect, (UCHAR)(UnitId));\ - } while (0) -#else -#define mSelectUnit(IOPort,UnitId) OutPort(&IOPort->DriveSelect, (UCHAR)(UnitId)) -#endif -#define mGetUnitNumber(IOPort) InPort(&IOPort->DriveSelect) -#define mIssueCommand(IOPort,Cmd) OutPort(&IOPort->Command, (UCHAR)(Cmd)) - -/* - * WDC old disk, don't care right now - */ -#define WDC_MW1_FIX_FLAG_OFFSET 129 -#define WDC_MW1_FIX_FLAG_VALUE 0x00005555 - -#pragma pack() -#endif - - - diff --git a/sys/contrib/dev/hptmv/command.h b/sys/contrib/dev/hptmv/command.h deleted file mode 100644 index 0b03e155dc19..000000000000 --- a/sys/contrib/dev/hptmv/command.h +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifndef _COMMAND_H_ -#define _COMMAND_H_ - -/*************************************************************************** - * Description: Command - ***************************************************************************/ -typedef struct _AtaCommand -{ - LBA_T Lba; /* Current Logic Disk command: LBA */ - USHORT nSectors; /* sector count. May great than 0x80 */ - UCHAR Command; /* IDE_COMMAND_READ, _WRITE, _VERIFY */ - UCHAR QueueTag; -} AtaComm, *PAtaComm; - -typedef struct _PassthroughCmd { - BYTE bFeaturesReg; /* feature register */ - BYTE bSectorCountReg; /* IDE sector count register. */ - BYTE bSectorNumberReg; /* IDE sector number register. */ - BYTE bCylLowReg; /* IDE low order cylinder value. */ - BYTE bCylHighReg; /* IDE high order cylinder value. */ - BYTE bDriveHeadReg; /* IDE drive/head register. */ - BYTE bCommandReg; /* Actual IDE command. Checked for validity by driver. */ - BYTE nSectors; /* data transfer */ - ADDRESS pDataBuffer; /* data buffer */ -} -PassthroughCmd; - -/* control commands */ -#define CTRL_CMD_REBUILD 1 -#define CTRL_CMD_VERIFY 2 -#define CTRL_CMD_INIT 3 - -/* - * RAID5 rebuild/verify - * Rebuild/verify one stripe line. - * The caller needn't supply a buffer for rebuild. - * RebuildSectors member will be updated if its previous location is the - * begin of this stripe line. - */ -typedef struct _R5ControlCmd { - LBA_T StripeLine; /* _physical_ stripe line on array */ - USHORT Offset; /* internal use, don't set */ - UCHAR Command; /* CTRL_CMD_XXX */ - UCHAR reserve1; -} -R5ControlCmd, *PR5ControlCmd; - -/* - * RAID1 rebuild/verify - * Rebuild/verify specified sectors. - * The caller must supply a valid buffer and a physical SG table (or a - * pfnBuildSgl routine). - * For rebuild/initialize, the buffer size should be nSectors<<9; - * For verify, the buffer size should be (nSectors*2)<<9. - * RebuildSectors member will be updated if its previous value equals Lba. - */ -typedef struct _R1ControlCmd { - LBA_T Lba; - USHORT nSectors; - UCHAR Command; /* CTRL_CMD_XXX */ - UCHAR reserve1; - ADDRESS Buffer; /* buffer logical address */ -#ifdef _MACOSX_ - ADDRESS PhysicalAddress; -#endif -} -R1ControlCmd, *PR1ControlCmd; - -typedef struct _Command -{ - PVDevice pVDevice; - union{ - /* Ide Command */ - AtaComm Ide; - PassthroughCmd Passthrough; - /* Atapi Command */ - UCHAR Atapi[12]; - /* Control command */ - R5ControlCmd R5Control; - R1ControlCmd R1Control; - } uCmd; - - USHORT cf_physical_sg: 1; - USHORT cf_data_in: 1; - USHORT cf_data_out: 1; - USHORT cf_atapi: 1; - USHORT cf_ide_passthrough: 1; - USHORT cf_control: 1; - - /* return status */ - UCHAR Result; - /* retry count */ - UCHAR RetryCount; - - /* S/G table address, if already prepared */ - FPSCAT_GATH pSgTable; - - /* called if pSgTable is invalid. */ - int (* HPTLIBAPI pfnBuildSgl)(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical); - - /* called when this command is finished */ - void (* HPTLIBAPI pfnCompletion)(_VBUS_ARG PCommand pCmd); - - /* pointer to origional command */ - void *pOrgCommand; - - - /* scratch data area */ - union { - struct { - LBA_T StartLBA; - UCHAR FirstMember; /* the sequence number of the first member */ - UCHAR LastMember; /* the sequence number of the last member */ - USHORT LastSectors; /* the number of sectors for the last member */ - USHORT FirstSectors; /* the number of sectors for the first member */ - USHORT FirstOffset; /* the offset from the StartLBA for the first member */ - USHORT AllMemberBlocks;/* the number of sectors for all member */ - USHORT WaitInterrupt; /* bit map the members who wait interrupt */ - UCHAR InSameLine; /* if the start and end on the same line */ - UCHAR pad1; - } array; - struct { - LBA_T StartLBA; - USHORT FirstSectors; /* the number of sectors for the first member */ - USHORT FirstOffset; /* the offset from the StartLBA for the first member */ - USHORT WaitInterrupt; /* bit map the members who wait interrupt */ - USHORT r5_gap; /* see raid5.c */ - UCHAR ParDiskNo; /* parity for startLba */ - UCHAR BadDiskNo; - UCHAR FirstMember; - UCHAR pad1; - } r5; - struct { - PCommand pCmd1; - PCommand pCmd2; - } r5split; -#ifdef _RAID5N_ - struct { - ULONG dummy[2]; /* uScratch.wait shall be moved out uScratch. - now just fix it thisway */ - struct range_lock *range_lock; - struct stripe *stripes[5]; - UCHAR nstripes; - UCHAR finished_stripes; - USHORT pad2; - /* for direct-read: */ - struct { - UCHAR cmds; - UCHAR finished; - UCHAR first; - UCHAR parity; - LBA_T base; - USHORT firstoffset; - USHORT firstsectors; - } dr; - } r5n2; -#endif - struct { - ULONG WordsLeft; - FPSCAT_GATH pPIOSg; - void (* HPTLIBAPI pfnOrgDone)(_VBUS_ARG PCommand pCmd); -#ifdef SUPPORT_HPT584 - UCHAR cmd; -#endif - } disk; - struct { - PCommand pNext; - void (* HPTLIBAPI WaitEntry)(_VBUS_ARG PCommand pCmd); - } wait; - - struct { - PVOID prdAddr; - ULONG cmd_priv; - USHORT responseFlags; - UCHAR bIdeStatus; - UCHAR errorRegister; - } sata_param; - } uScratch; -} Command; - -/*************************************************************************** - * command return value - ***************************************************************************/ -#define RETURN_PENDING 0 -#define RETURN_SUCCESS 1 -#define RETURN_BAD_DEVICE 2 -#define RETURN_BAD_PARAMETER 3 -#define RETURN_WRITE_NO_DRQ 4 -#define RETURN_DEVICE_BUSY 5 -#define RETURN_INVALID_REQUEST 6 -#define RETURN_SELECTION_TIMEOUT 7 -#define RETURN_IDE_ERROR 8 -#define RETURN_NEED_LOGICAL_SG 9 -#define RETURN_NEED_PHYSICAL_SG 10 -#define RETURN_RETRY 11 -#define RETURN_DATA_ERROR 12 -#define RETURN_BUS_RESET 13 -#define RETURN_BAD_TRANSFER_LENGTH 14 - -typedef void (* HPTLIBAPI DPC_PROC)(_VBUS_ARG void *); -typedef struct _dpc_routine { - DPC_PROC proc; - void *arg; -} -DPC_ROUTINE; - -/* - * MAX_QUEUE_COMM is defined in platform related compiler.h - * to specify the maximum requests allowed (for each VBus) from system. - * - * Maximum command blocks needed for each VBus: - * Each OS command requests 1+MAX_MEMBERS*2 command blocks (RAID1/0 case) - * This space is allocated by platform dependent part, either static or - * dynamic, continuous or non-continous. - * The code only needs _vbus_(pFreeCommands) to be set. - * - * PendingRoutines[] size: - * Each command may invoke CallAfterReturn once. - * - * IdleRoutines[] size: - * Each command may invoke CallWhenIdle once. - */ -#define MAX_COMMAND_BLOCKS_FOR_EACH_VBUS (MAX_QUEUE_COMM * (1+MAX_MEMBERS*2)) -#define MAX_PENDING_ROUTINES (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1) -#define MAX_IDLE_ROUTINES (MAX_COMMAND_BLOCKS_FOR_EACH_VBUS+1) - -#define mWaitingForIdle(pVBus) ((pVBus)->IdleRoutinesFirst!=(pVBus)->IdleRoutinesLast) - -PCommand HPTLIBAPI AllocateCommand(_VBUS_ARG0); -void FASTCALL FreeCommand(_VBUS_ARG PCommand pCmd); - -void FASTCALL CallAfterReturn(_VBUS_ARG DPC_PROC proc, void *arg); -void HPTLIBAPI CheckPendingCall(_VBUS_ARG0); -void FASTCALL CallWhenIdle(_VBUS_ARG DPC_PROC proc, void *arg); -void HPTLIBAPI CheckIdleCall(_VBUS_ARG0); - -void HPTLIBAPI AddToWaitingList(PCommand *ppList, PCommand pCmd); -void HPTLIBAPI DoWaitingList(_VBUS_ARG PCommand *ppList); - -#endif diff --git a/sys/contrib/dev/hptmv/gui_lib.c b/sys/contrib/dev/hptmv/gui_lib.c deleted file mode 100644 index e20ef55d8daa..000000000000 --- a/sys/contrib/dev/hptmv/gui_lib.c +++ /dev/null @@ -1,1384 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * gui_lib.c - * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved. - * - * Platform independent ioctl interface implementation. - * The platform dependent part may reuse this function and/or use it own - * implementation for each ioctl function. - * - * This implementation doesn't use any synchronization; the caller must - * assure the proper context when calling these functions. - */ - -#include -#include -#include -#include - -#include -#include -#include -#include - -static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap); -static int hpt_get_controller_count(void); -static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo); -static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo); -static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount); -static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo); -static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam); -static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk); -static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk); -static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo); -static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo); - -int check_VDevice_valid(PVDevice p) -{ - int i; - PVDevice pVDevice; - PVBus _vbus_p; - IAL_ADAPTER_T *pAdapter = gIal_Adapter; - - while(pAdapter != 0) - { - for (i = 0; i < MV_SATA_CHANNELS_NUM; i++) - if(&(pAdapter->VDevices[i]) == p) return 0; - pAdapter = pAdapter->next; - } - -#ifdef SUPPORT_ARRAY - pAdapter = gIal_Adapter; - while(pAdapter != 0) - { - _vbus_p = &pAdapter->VBus; - for (i=0;iu.array.dArStamp != 0) && (pVDevice == p)) - return 0; - } - pAdapter = pAdapter->next; - } -#endif - - return -1; -} - -#ifdef SUPPORT_ARRAY -static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) -{ - int i; - - pInfo->Type = LDT_ARRAY; - pInfo->Capacity = pVDevice->VDeviceCapacity; - pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); - - memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME); - - switch( pVDevice->VDeviceType ) - { - case VD_RAID_0: - pInfo->u.array.ArrayType = AT_RAID0; - break; - case VD_RAID_1: - pInfo->u.array.ArrayType = AT_RAID1; - break; - case VD_JBOD: - pInfo->u.array.ArrayType = AT_JBOD; - break; - case VD_RAID_5: - pInfo->u.array.ArrayType = AT_RAID5; - break; - default: - pInfo->u.array.ArrayType = AT_UNKNOWN; - } - - pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; - - pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors; - - /* The array is disabled */ - if(!pVDevice->vf_online) { - pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED; - goto ignore_info; - } - - /* array need synchronizing */ - if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create) - pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING; - - pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 / - (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10; - - /* array is in rebuilding process */ - if(pVDevice->u.array.rf_rebuilding) - pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; - - /* array is being verified */ - if(pVDevice->u.array.rf_verifying) - pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; - - /* array is being initialized */ - if(pVDevice->u.array.rf_initializing) - pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; - - /* broken but may still working */ - if(pVDevice->u.array.rf_broken) - pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; - - /* array has a active partition */ - if(pVDevice->vf_bootable) - pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK; - - /* a newly created array */ - if(pVDevice->u.array.rf_newly_created) - pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; - - /* array has boot mark set */ - if(pVDevice->vf_bootmark) - pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK; - - /* auto-rebuild should start */ - if(pVDevice->u.array.rf_auto_rebuild) - pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; - - for(i = 0; i < pVDevice->u.array.bArnMember; i++) - { - PVDevice pMember = pVDevice->u.array.pMember[i]; - if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK)) - continue; - - /* array need synchronizing */ - if(pMember->u.array.rf_need_rebuild && - !pMember->u.array.rf_duplicate_and_create) - pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING; - - /* array is in rebuilding process */ - if(pMember->u.array.rf_rebuilding) - pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; - - /* array is being verified */ - if(pMember->u.array.rf_verifying) - pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; - - /* array is being initialized */ - if(pMember->u.array.rf_initializing) - pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; - - /* broken but may still working */ - if(pMember->u.array.rf_broken) - pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; - - /* a newly created array */ - if(pMember->u.array.rf_newly_created) - pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; - - /* auto-rebuild should start */ - if(pMember->u.array.rf_auto_rebuild) - pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; - - /* for RAID1/0 case */ - if (pMember->u.array.rf_rebuilding || - pMember->u.array.rf_verifying || - pMember->u.array.rf_initializing) - { - DWORD percent = ((pMember->u.array.RebuildSectors>>11)*1000 / - (pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10; - if (pInfo->u.array.RebuildingProgress==0 || - pInfo->u.array.RebuildingProgress>percent) - pInfo->u.array.RebuildingProgress = percent; - } - } - - if (pInfo->u.array.RebuildingProgress>10000) - pInfo->u.array.RebuildingProgress = 10000; - -ignore_info: - - pInfo->u.array.nDisk = 0; - for(i=0; iu.array.Members[i] = INVALID_DEVICEID; - - for(i = 0; i < pVDevice->u.array.bArnMember; i++) - { - if(pVDevice->u.array.pMember[i] != NULL) - { - pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); - pInfo->u.array.nDisk++; - } - } -} -#endif - -static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) -{ - MV_SATA_ADAPTER *pSataAdapter; - MV_SATA_CHANNEL *pSataChannel; - IAL_ADAPTER_T *pAdapter; - char *p; - int i; - - pInfo->Type = LDT_DEVICE; - - if (pVDevice->pParent) - pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); - else - pInfo->ParentArray = INVALID_DEVICEID; - - /* report real capacity to be compatible with old arrays */ - pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity; - - /* device location */ - pSataChannel = pVDevice->u.disk.mv; - if(pSataChannel == NULL) return -1; - pInfo->u.device.TargetId = 0; - pSataAdapter = pSataChannel->mvSataAdapter; - if(pSataAdapter == NULL) return -1; - - pAdapter = pSataAdapter->IALData; - - pInfo->u.device.PathId = pSataChannel->channelNumber; - pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId; - -/*GUI uses DeviceModeSetting to display to users -(1) if users select a mode, GUI/BIOS should display that mode. -(2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied. -(3) display real mode if case (1)&&(2) not satisfied. -*/ - if (pVDevice->u.disk.df_user_mode_set) - pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode; - else if ((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability & 3)==2) - pInfo->u.device.DeviceModeSetting = 15; - else { - p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber; - if (*(WORD*)p==0x5354 /*'ST'*/ && - (*(WORD*)(p+8)==0x4153/*'AS'*/ || (p[8]=='A' && p[11]=='S'))) - pInfo->u.device.DeviceModeSetting = 15; - else - pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting; - } - - pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode; - - pInfo->u.device.DeviceType = PDT_HARDDISK; - - pInfo->u.device.Flags = 0x0; - - /* device is disabled */ - if(!pVDevice->u.disk.df_on_line) - pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED; - - /* disk has a active partition */ - if(pVDevice->vf_bootable) - pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK; - - /* disk has boot mark set */ - if(pVDevice->vf_bootmark) - pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK; - - pInfo->u.device.Flags |= DEVICE_FLAG_SATA; - - /* is a spare disk */ - if(pVDevice->VDeviceType == VD_SPARE) - pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE; - - memcpy(&(pInfo->u.device.IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2)); - p = (char *)&pInfo->u.device.IdentifyData.ModelNumber; - for (i = 0; i < 20; i++) - ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]); - p[39] = '\0'; - - return 0; -} - -static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) -{ - ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES)); - cap->dwSize = sizeof(DRIVER_CAPABILITIES); - cap->MaximumControllers = MAX_VBUS; - - /* cap->SupportCrossControllerRAID = 0; */ - /* take care for various OSes! */ - cap->SupportCrossControllerRAID = 0; - - - cap->MinimumBlockSizeShift = MinBlockSizeShift; - cap->MaximumBlockSizeShift = MaxBlockSizeShift; - cap->SupportDiskModeSetting = 0; - cap->SupportSparePool = 1; - cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1; - cap->SupportDedicatedSpare = 0; - -#ifdef SUPPORT_HOTSWAP - cap->SupportHotSwap = 1; -#endif - -#ifdef SUPPORT_ARRAY - /* Stripe */ - cap->SupportedRAIDTypes[0] = AT_RAID0; - cap->MaximumArrayMembers[0] = MAX_MEMBERS; - /* Mirror */ - cap->SupportedRAIDTypes[1] = AT_RAID1; - cap->MaximumArrayMembers[1] = 2; - /* Mirror + Stripe */ -#ifdef ARRAY_V2_ONLY - cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */ -#else - cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */ -#endif - cap->MaximumArrayMembers[2] = MAX_MEMBERS; - /* Jbod */ - cap->SupportedRAIDTypes[3] = AT_JBOD; - cap->MaximumArrayMembers[3] = MAX_MEMBERS; - /* RAID5 */ -#if SUPPORT_RAID5 - cap->SupportedRAIDTypes[4] = AT_RAID5; - cap->MaximumArrayMembers[4] = MAX_MEMBERS; -#endif -#if 0 /* don't let GUI create RAID 0/1. */ - /* Stripe + Mirror */ - cap->SupportedRAIDTypes[5] = (AT_RAID1<<4)|AT_RAID0; - cap->MaximumArrayMembers[5] = 4; -#endif -#endif /* SUPPORT_ARRAY */ - return 0; -} - -static int hpt_get_controller_count(void) -{ - IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; - int iControllerCount = 0; - - while(pAdapTemp != 0) - { - iControllerCount++; - pAdapTemp = pAdapTemp->next; - } - - return iControllerCount; -} - -static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) -{ - IAL_ADAPTER_T *pAdapTemp; - int iControllerCount = 0; - - for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { - if (iControllerCount++==id) { - pInfo->InterruptLevel = 0; - pInfo->ChipType = 0; - pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100; - strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc."); -#ifdef GUI_CONTROLLER_NAME -#ifdef FORCE_ATA150_DISPLAY - /* show "Bus Type: ATA/150" in GUI for SATA controllers */ - pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150; -#endif - strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME); -#define _set_product_id(x) -#else -#define _set_product_id(x) strcpy(pInfo->szProductID, x) -#endif - _set_product_id("RocketRAID 182x SATA Controller"); - pInfo->NumBuses = 8; - pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150; - return 0; - } - } - return -1; -} - - -static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) -{ - IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; - int i,iControllerCount = 0; - - while(pAdapTemp != 0) - { - if (iControllerCount++==id) - goto found; - pAdapTemp = pAdapTemp->next; - } - return -1; - -found: - - pInfo->IoPort = 0; - pInfo->ControlPort = 0; - - for (i=0; i<2 ;i++) - { - pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID; - } - - if (pAdapTemp->mvChannel[bus].online == MV_TRUE) - pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]); - else - pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID; - - return 0; - - -} - -static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) -{ - int count = 0; - int i,j; - PVDevice pPhysical, pLogical; - IAL_ADAPTER_T *pAdapTemp; - - for(i = 0; i < nMaxCount; i++) - pIds[i] = INVALID_DEVICEID; - - /* append the arrays not registered on VBus */ - for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { - for(i = 0; i < MV_SATA_CHANNELS_NUM; i++) - { - pPhysical = &pAdapTemp->VDevices[i]; - pLogical = pPhysical; - - while (pLogical->pParent) pLogical = pLogical->pParent; - if (pLogical->VDeviceType==VD_SPARE) - continue; - - for (j=0; j=nMaxCount) goto done; - next:; - } - } - -done: - return count; -} - -static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) -{ - PVDevice pVDevice = ID_TO_VDEV(id); - - if((id == HPT_NULL_ID) || check_VDevice_valid(pVDevice)) - return -1; - -#ifdef SUPPORT_ARRAY - if (mIsArray(pVDevice)) - get_array_info(pVDevice, pInfo); - else -#endif - return get_disk_info(pVDevice, pInfo); - - return 0; -} - -#ifdef SUPPORT_ARRAY -static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) -{ - ULONG Stamp = GetStamp(); - int i,j; - ULONG capacity = MAX_LBA_T; - PVDevice pArray,pChild; -#if MAX_VBUS==1 - PVBus _vbus_p = NULL; -#endif - int Loca = -1; - - for(i = 0; i < pParam->nDisk; i++) - { - PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]); - if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID; - if (mIsArray(pVDev)) return INVALID_DEVICEID; - if (!pVDev->vf_online) return INVALID_DEVICEID; - if (!_vbus_p) - _vbus_p = pVDev->u.disk.pVBus; - else if (_vbus_p != pVDev->u.disk.pVBus) - return INVALID_DEVICEID; - } - if (!_vbus_p) return INVALID_DEVICEID; - - mArGetArrayTable(pArray); - if(!pArray) return INVALID_DEVICEID; - - switch (pParam->ArrayType) - { - case AT_JBOD: - pArray->VDeviceType = VD_JBOD; - goto simple; - - case AT_RAID0: - if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) - goto error; - pArray->VDeviceType = VD_RAID_0; - goto simple; - - case AT_RAID5: - if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) - goto error; - pArray->VDeviceType = VD_RAID_5; - /* only "no build" R5 is not critical after creation. */ - if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0) - pArray->u.array.rf_need_rebuild = 1; - goto simple; - - case AT_RAID1: - if(pParam->nDisk <= 2) - { - pArray->VDeviceType = VD_RAID_1; -simple: - pArray->u.array.bArnMember = pParam->nDisk; - pArray->u.array.bArRealnMember = pParam->nDisk; - pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; - pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); - pArray->u.array.dArStamp = Stamp; - - pArray->u.array.rf_need_sync = 1; - pArray->u.array.rf_newly_created = 1; - - if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && - (pArray->VDeviceType == VD_RAID_1)) - { - pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */ - pArray->u.array.rf_need_rebuild = 1; - pArray->u.array.rf_auto_rebuild = 1; - pArray->u.array.rf_duplicate_and_create = 1; - - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) - if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0])) - Loca = i; - } - - pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T; - - memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); - - for(i = 0; i < pParam->nDisk; i++) - { - pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]); - pArray->u.array.pMember[i]->bSerialNumber = i; - pArray->u.array.pMember[i]->pParent = pArray; - - /* don't unregister source disk for duplicate RAID1 */ - if (i || - pArray->VDeviceType!=VD_RAID_1 || - (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0) - UnregisterVDevice(pArray->u.array.pMember[i]); - - if(pArray->VDeviceType == VD_RAID_5) - pArray->u.array.pMember[i]->vf_cache_disk = 1; - } - } - else - { - for(i = 0; i < (pParam->nDisk / 2); i++) - { - mArGetArrayTable(pChild); - pChild->VDeviceType = VD_RAID_1; - - pChild->u.array.bArnMember = 2; - pChild->u.array.bArRealnMember = 2; - pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift; - pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); - pChild->u.array.dArStamp = Stamp; - - pChild->u.array.rf_need_sync = 1; - pChild->u.array.rf_newly_created = 1; - - pChild->u.array.RebuildSectors = MAX_LBA_T; - - memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); - - for(j = 0; j < 2; j++) - { - pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]); - pChild->u.array.pMember[j]->bSerialNumber = j; - pChild->u.array.pMember[j]->pParent = pChild; - pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType]; - UnregisterVDevice(pChild->u.array.pMember[j]); - } - - pArray->u.array.pMember[i] = pChild; - - pChild->vf_online = 1; - pChild->bSerialNumber = i; - pChild->pParent = pArray; - pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity, - pChild->u.array.pMember[1]->VDeviceCapacity); - - pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType]; - pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0]; - } - - pArray->VDeviceType = VD_RAID_0; - - pArray->u.array.bArnMember = pParam->nDisk / 2; - pArray->u.array.bArRealnMember = pParam->nDisk / 2; - pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; - pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); - pArray->u.array.dArStamp = Stamp; - - pArray->u.array.rf_need_sync = 1; - pArray->u.array.rf_newly_created = 1; - - memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); - } - break; - - default: - goto error; - } - - for(i = 0; i < pArray->u.array.bArnMember; i++) - pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; - - if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && - (pArray->VDeviceType == VD_RAID_1)) - { - pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark; - pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable; - pArray->u.array.pMember[0]->vf_bootable = 0; - pArray->u.array.pMember[0]->vf_bootmark = 0; - if (Loca>=0) { - _vbus_p->pVDevice[Loca] = pArray; - /* to comfort OS */ - pArray->u.array.rf_duplicate_and_created = 1; - pArray->pVBus = _vbus_p; - } - } - else { - UCHAR TempBuffer[512]; - ZeroMemory(TempBuffer, 512); - for(i = 0; i < pParam->nDisk; i++) - { - PVDevice pDisk = ID_TO_VDEV(pParam->Members[i]); - pDisk->vf_bootmark = pDisk->vf_bootable = 0; - fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer); - } - } - - pArray->vf_online = 1; - pArray->pParent = NULL; - - switch(pArray->VDeviceType) - { - case VD_RAID_0: - for(i = 0; i < pArray->u.array.bArnMember; i++) - if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) - capacity = pArray->u.array.pMember[i]->VDeviceCapacity; -#ifdef ARRAY_V2_ONLY - capacity -= 10; -#endif - capacity &= ~(pArray->u.array.bStripeWitch - 1); - /* shrink member capacity for RAID 1/0 */ - for(i = 0; i < pArray->u.array.bArnMember; i++) - if (mIsArray(pArray->u.array.pMember[i])) - pArray->u.array.pMember[i]->VDeviceCapacity = capacity; - pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember; - break; - - case VD_RAID_1: - pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity, - pArray->u.array.pMember[1]->VDeviceCapacity); - break; - - case VD_JBOD: - for(i = 0; i < pArray->u.array.bArnMember; i++) - pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity -#ifdef ARRAY_V2_ONLY - -10 -#endif - ; - break; - - case VD_RAID_5: - for(i = 0; i < pArray->u.array.bArnMember; i++) - if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) - capacity = pArray->u.array.pMember[i]->VDeviceCapacity; - pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1)) - * (pArray->u.array.bArnMember - 1); - break; - - default: - goto error; - } - - pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType]; - pArray->pfnDeviceFailed = fOsDiskFailed; - SyncArrayInfo(pArray); - - if (!pArray->u.array.rf_duplicate_and_created) - RegisterVDevice(pArray); - return VDEV_TO_ID(pArray); - -error: - for(i = 0; i < pArray->u.array.bArnMember; i++) - { - pChild = pArray->u.array.pMember[i]; - if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK)) - mArFreeArrayTable(pChild); - } - mArFreeArrayTable(pArray); - return INVALID_DEVICEID; -} - -#ifdef SUPPORT_OLD_ARRAY -/* this is only for old RAID 0/1 */ -int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) -{ - PVDevice pArray1 = ID_TO_VDEV(idArray); - PVDevice pArray2 = 0; - PVDevice pDisk = ID_TO_VDEV(idDisk); - int i; - IAL_ADAPTER_T *pAdapter = gIal_Adapter; - -#if MAX_VBUS>1 - if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif - - if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2)) - return -1; - - pArray2 = pArray1->u.array.pMember[1]; - if(pArray2 == NULL) { - /* create a Stripe */ - mArGetArrayTable(pArray2); - pArray2->VDeviceType = VD_RAID_0; - pArray2->u.array.dArStamp = GetStamp(); - pArray2->vf_format_v2 = 1; - pArray2->u.array.rf_broken = 1; - pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift; - pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift); - pArray2->u.array.bArnMember = 2; - pArray2->VDeviceCapacity = pArray1->VDeviceCapacity; - pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType]; - pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType]; - memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME); - pArray2->pParent = pArray1; - pArray2->bSerialNumber = 1; - pArray1->u.array.pMember[1] = pArray2; - pArray1->u.array.bArRealnMember++; - } - - for(i = 0; i < pArray2->u.array.bArnMember; i++) - if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online) - { - if(pArray2->u.array.pMember[i] != NULL) - pArray2->u.array.pMember[i]->pParent = NULL; - pArray2->u.array.pMember[i] = pDisk; - goto find; - } - return -1; - -find: - UnregisterVDevice(pDisk); - pDisk->VDeviceType = VD_SINGLE_DISK; - pDisk->bSerialNumber = i; - pDisk->pParent = pArray2; - pDisk->vf_format_v2 = 1; - pDisk->u.disk.dDeHiddenLba = i? 10 : 0; - pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; - pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType]; - - pArray2->u.array.bArRealnMember++; - if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){ - pArray2->vf_online = 1; - pArray2->u.array.rf_broken = 0; - } - - if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){ - pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember; - pArray1->u.array.rf_broken = 0; - pArray1->u.array.rf_need_rebuild = 1; - pArray1->u.array.rf_auto_rebuild = 1; - - } - pArray1->u.array.RebuildSectors = 0; - pArray1->u.array.dArStamp = GetStamp(); - SyncArrayInfo(pArray1); - return 1; -} -#endif - -int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) -{ - int i; - - ULONG Capacity; - PVDevice pArray = ID_TO_VDEV(idArray); - PVDevice pDisk = ID_TO_VDEV(idDisk); - - if((idArray == HPT_NULL_ID) || (idDisk == HPT_NULL_ID)) return -1; - if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1; - if(!pArray->u.array.rf_broken) return -1; - - if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) - return -1; - if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE)) - return -1; - -#ifdef SUPPORT_OLD_ARRAY - /* RAID 0 + 1 */ - if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 && - pArray->u.array.pMember[0] && - mIsArray(pArray->u.array.pMember[0])) - { - if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk)) - return 0; - else - return -1; - } -#endif - - Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1); - - if (pArray->vf_format_v2) { - if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1; - } - else - if(pDisk->VDeviceCapacity < Capacity) return -1; - -#if MAX_VBUS>1 - if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif - - for(i = 0; i < pArray->u.array.bArnMember; i++) - if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online) - { - if(pArray->u.array.pMember[i] != NULL) - pArray->u.array.pMember[i]->pParent = NULL; - pArray->u.array.pMember[i] = pDisk; - goto find; - } - return -1; - -find: - UnregisterVDevice(pDisk); - pDisk->VDeviceType = VD_SINGLE_DISK; - pDisk->bSerialNumber = i; - pDisk->pParent = pArray; - if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1; - pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; - if (pArray->vf_format_v2) { - pDisk->vf_format_v2 = 1; - pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; - } - - pArray->u.array.bArRealnMember++; - if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember) - { - pArray->u.array.rf_need_rebuild = 1; - pArray->u.array.RebuildSectors = 0; - pArray->u.array.rf_auto_rebuild = 1; - pArray->u.array.rf_broken = 0; - } - pArray->u.array.RebuildSectors = 0; - - /* sync the whole array */ - while (pArray->pParent) pArray = pArray->pParent; - pArray->u.array.dArStamp = GetStamp(); - SyncArrayInfo(pArray); - return 0; -} - -static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) -{ - PVDevice pVDevice = ID_TO_VDEV(idDisk); - DECLARE_BUFFER(PUCHAR, pbuffer); - - if(idDisk == HPT_NULL_ID || check_VDevice_valid(pVDevice)) - return -1; - if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) - return -1; - -#if MAX_VBUS>1 - if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif - - UnregisterVDevice(pVDevice); - pVDevice->VDeviceType = VD_SPARE; - pVDevice->vf_bootmark = 0; - - ZeroMemory((char *)pbuffer, 512); - fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer); - SyncArrayInfo(pVDevice); - return 0; -} - -static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) -{ - PVDevice pVDevice = ID_TO_VDEV(idDisk); - - if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; - -#if MAX_VBUS>1 - if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif - - pVDevice->VDeviceType = VD_SINGLE_DISK; - - SyncArrayInfo(pVDevice); - RegisterVDevice(pVDevice); - return 0; -} - -static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) -{ - PVDevice pVDevice = ID_TO_VDEV(idArray); - - if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) return -1; - if (!mIsArray(pVDevice)) return -1; - - /* if the pVDevice isn't a top level, return -1; */ - if(pVDevice->pParent != NULL) return -1; - -#if MAX_VBUS>1 - if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif - - if (pInfo->ValidFields & AAIF_NAME) { - memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME); - memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name)); - pVDevice->u.array.rf_need_sync = 1; - } - - if (pInfo->ValidFields & AAIF_DESCRIPTION) { - memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description)); - pVDevice->u.array.rf_need_sync = 1; - } - - if (pVDevice->u.array.rf_need_sync) - SyncArrayInfo(pVDevice); - return 0; -} - -static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) -{ - PVDevice pVDevice = ID_TO_VDEV(idDisk); - - /* stop buzzer. */ - if(idDisk == HPT_NULL_ID) { -#ifndef FOR_DEMO - IAL_ADAPTER_T *pAdapter; - for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { - if (pAdapter->beeping) { - pAdapter->beeping = 0; - BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); - } - } -#endif - return 0; - } - - if (check_VDevice_valid(pVDevice)) return -1; - if (mIsArray(pVDevice)) - return -1; - -#if MAX_VBUS>1 - if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif - -/* if (pInfo->ValidFields & ADIF_MODE) { - pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting; - pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting; - pVDevice->u.disk.df_user_mode_set = 1; - fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting); - SyncArrayInfo(pVDevice); - }*/ - return 0; -} -#endif /* SUPPORT_ARRAY */ - -#ifdef SUPPORT_HPT601 -int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) -{ - PVDevice pVDevice = ID_TO_VDEV(idDisk); - PChannel pChan = pVDevice->u.disk.pChannel; - PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; - - if(!pVDevice->u.disk.df_with_601) return -1; - - mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); - pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); - - BeginAccess601(IoPort); - - mSetBlockCount(IoPort, 0); - pInfo->DeviceId = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 0x14); - pInfo->Temperature = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 0xA); - pInfo->FanStatus = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 7); - pInfo->BeeperControl = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 3); - pInfo->LED1Control = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 5); - pInfo->LED2Control = InWord(&IoPort->Data); - - mSetBlockCount(IoPort, 0x18); - pInfo->PowerStatus = InWord(&IoPort->Data); - - EndAccess601(IoPort); - pInfo->ValidFields = 0x7F; - /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/ - return 0; -} - -int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) -{ - PVDevice pVDevice = ID_TO_VDEV(idDisk); - PChannel pChan = pVDevice->u.disk.pChannel; - PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; - - if(!pVDevice->u.disk.df_with_601) return -1; - - mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); - pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); - - BeginAccess601(IoPort); - - if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) { - mSetBlockCount(IoPort, 1); - OutWord(&IoPort->Data, pInfo->Temperature); - } - - if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) { - mSetBlockCount(IoPort, 0xA); - OutWord(&IoPort->Data, pInfo->FanStatus); - } - - if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) { - mSetBlockCount(IoPort, 7); - OutWord(&IoPort->Data, pInfo->BeeperControl); - } - - if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) { - mSetBlockCount(IoPort, 3); - OutWord(&IoPort->Data, pInfo->LED1Control); - } - - if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) { - mSetBlockCount(IoPort, 5); - OutWord(&IoPort->Data, pInfo->LED2Control); - } - - EndAccess601(IoPort); - - return 0; -} -#endif - -/* hpt_default_ioctl() - * This is a default implementation. The platform dependent part - * may reuse this function and/or use it own implementation for - * each ioctl function. - */ -int hpt_default_ioctl(_VBUS_ARG - DWORD dwIoControlCode, /* operation control code */ - PVOID lpInBuffer, /* input data buffer */ - DWORD nInBufferSize, /* size of input data buffer */ - PVOID lpOutBuffer, /* output data buffer */ - DWORD nOutBufferSize, /* size of output data buffer */ - PDWORD lpBytesReturned /* byte count */ - ) -{ - switch(dwIoControlCode) { - - case HPT_IOCTL_GET_VERSION: - - if (nInBufferSize != 0) return -1; - if (nOutBufferSize != sizeof(DWORD)) return -1; - *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION; - break; - - case HPT_IOCTL_GET_CONTROLLER_COUNT: - - if (nOutBufferSize!=sizeof(DWORD)) return -1; - *(PDWORD)lpOutBuffer = hpt_get_controller_count(); - break; - - case HPT_IOCTL_GET_CONTROLLER_INFO: - { - int id; - PCONTROLLER_INFO pInfo; - - if (nInBufferSize!=sizeof(DWORD)) return -1; - if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1; - - id = *(DWORD *)lpInBuffer; - pInfo = (PCONTROLLER_INFO)lpOutBuffer; - if (hpt_get_controller_info(id, pInfo)!=0) - return -1; - } - break; - - case HPT_IOCTL_GET_CHANNEL_INFO: - { - int id, bus; - PCHANNEL_INFO pInfo; - - if (nInBufferSize!=8) return -1; - if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1; - - id = *(DWORD *)lpInBuffer; - bus = ((DWORD *)lpInBuffer)[1]; - pInfo = (PCHANNEL_INFO)lpOutBuffer; - - if (hpt_get_channel_info(id, bus, pInfo)!=0) - return -1; - } - break; - - case HPT_IOCTL_GET_LOGICAL_DEVICES: - { - DWORD nMax; - DEVICEID *pIds; - - if (nInBufferSize!=sizeof(DWORD)) return -1; - nMax = *(DWORD *)lpInBuffer; - if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1; - - pIds = ((DEVICEID *)lpOutBuffer)+1; - *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax); - } - break; - - case HPT_IOCTL_GET_DEVICE_INFO: - { - DEVICEID id; - PLOGICAL_DEVICE_INFO pInfo; - - if (nInBufferSize!=sizeof(DEVICEID)) return -1; - if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1; - - id = *(DWORD *)lpInBuffer; - if (id == INVALID_DEVICEID) return -1; - - pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer; - memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO)); - - if (hpt_get_device_info(id, pInfo)!=0) - return -1; - } - break; - -#ifdef SUPPORT_ARRAY - case HPT_IOCTL_CREATE_ARRAY: - { - CREATE_ARRAY_PARAMS *pParam; - DEVICEID id; - - if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1; - if (nOutBufferSize!=sizeof(DEVICEID)) return -1; - - pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer; - - id = hpt_create_array(_VBUS_P pParam); - *(DEVICEID *)lpOutBuffer = id; - - if(id == (DEVICEID)INVALID_DEVICEID) - return -1; - } - break; - - case HPT_IOCTL_SET_ARRAY_INFO: - { - DEVICEID idArray; - PALTERABLE_ARRAY_INFO pInfo; - - if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1; - if (nOutBufferSize!=0) return -1; - - idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray; - pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info; - - if(hpt_set_array_info(_VBUS_P idArray, pInfo)) - return -1; - } - break; - - case HPT_IOCTL_SET_DEVICE_INFO: - { - DEVICEID idDisk; - PALTERABLE_DEVICE_INFO pInfo; - - if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1; - if (nOutBufferSize!=0) return -1; - - idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk; - pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info; - if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0) - return -1; - } - break; - - case HPT_IOCTL_SET_BOOT_MARK: - { - DEVICEID id; - PVDevice pTop; - int i; - IAL_ADAPTER_T *pAdapter = gIal_Adapter; - PVBus pVBus; - - if (nInBufferSize!=sizeof(DEVICEID)) return -1; - id = *(DEVICEID *)lpInBuffer; - while(pAdapter != 0) - { - pVBus = &pAdapter->VBus; - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) - { - if(!(pTop = pVBus->pVDevice[i])) continue; -#if MAX_VBUS>1 - if (pTop->pVBus!=_vbus_p) return -1; -#endif - while (pTop->pParent) pTop = pTop->pParent; - if (id==0 && pTop->vf_bootmark) - pTop->vf_bootmark = 0; - else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark) - pTop->vf_bootmark = 1; - else - continue; - SyncArrayInfo(pTop); - break; - } - pAdapter = pAdapter->next; - } - } - break; -#endif /* SUPPORT_ARRAY */ - case HPT_IOCTL_RESCAN_DEVICES: - { - fRescanAllDevice(_VBUS_P0); - if (nInBufferSize!=0) return -1; - if (nOutBufferSize!=0) return -1; - fRescanAllDevice(_VBUS_P0); - } - break; - -#ifdef SUPPORT_ARRAY - case HPT_IOCTL_ADD_SPARE_DISK: - { - DEVICEID id; - - if (nInBufferSize!=sizeof(DEVICEID)) return -1; - if (nOutBufferSize!=0) return -1; - - id = *(DEVICEID *)lpInBuffer; - - if(hpt_add_spare_disk(_VBUS_P id)) - return -1; - } - break; - - case HPT_IOCTL_REMOVE_SPARE_DISK: - { - DEVICEID id; - - if (nInBufferSize!=sizeof(DEVICEID)) return -1; - if (nOutBufferSize!=0) return -1; - - id = *(DEVICEID *)lpInBuffer; - - if(hpt_remove_spare_disk(_VBUS_P id)) - return -1; - } - break; - - case HPT_IOCTL_ADD_DISK_TO_ARRAY: - { - DEVICEID id1,id2; - id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray; - id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk; - - if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1; - if (nOutBufferSize != 0) return -1; - - if(hpt_add_disk_to_array(_VBUS_P id1, id2)) - return -1; - } - break; -#endif - case HPT_IOCTL_GET_DRIVER_CAPABILITIES: - { - PDRIVER_CAPABILITIES cap; - if (nOutBufferSizeidDisk; - pInfo = &((PHPT_SET_601_INFO)lpInBuffer)->Info; - if(hpt_set_601_info(id, pInfo) != 0) - return -1; - } - break; -#endif - default: - return -1; - } - - if (lpBytesReturned) - *lpBytesReturned = nOutBufferSize; - return 0; -} diff --git a/sys/contrib/dev/hptmv/hptproc.c b/sys/contrib/dev/hptmv/hptproc.c deleted file mode 100644 index e05798f1eb74..000000000000 --- a/sys/contrib/dev/hptmv/hptproc.c +++ /dev/null @@ -1,600 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * hptproc.c sysctl support - */ -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -int hpt_rescan_all(void); - -/***************************************************************************/ - -static char hptproc_buffer[256]; - -#define FORMAL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \ - struct sysctl_req *req -#define REAL_HANDLER_ARGS oidp, arg1, arg2, req -typedef struct sysctl_req HPT_GET_INFO; - -static int hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length) -{ - int orig_length = length+4; - PVBus _vbus_p = &pAdapter->VBus; - PVDevice pArray; - PVDevice pSubArray, pVDev; - UINT i, iarray, ichan; - struct cam_periph *periph = NULL; - intrmask_t oldspl; - -#ifdef SUPPORT_ARRAY - if (length>=8 && strncmp(buffer, "rebuild ", 8)==0) - { - buffer+=8; - length-=8; - if (length>=5 && strncmp(buffer, "start", 5)==0) - { - oldspl = lock_driver(); - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) - if ((pArray=ArrayTables(i))->u.array.dArStamp==0) - continue; - else{ - if (pArray->u.array.rf_need_rebuild && !pArray->u.array.rf_rebuilding) - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, - (UCHAR)((pArray->u.array.CriticalMembers || pArray->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); - } - unlock_driver(oldspl); - return orig_length; - } - else if (length>=4 && strncmp(buffer, "stop", 4)==0) - { - oldspl = lock_driver(); - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) - if ((pArray=ArrayTables(i))->u.array.dArStamp==0) - continue; - else{ - if (pArray->u.array.rf_rebuilding) - pArray->u.array.rf_abort_rebuild = 1; - } - unlock_driver(oldspl); - return orig_length; - } - else if (length>=3 && buffer[1]==','&& buffer[0]>='1'&& buffer[2]>='1') - { - iarray = buffer[0]-'1'; - ichan = buffer[2]-'1'; - - if(iarray >= MAX_VDEVICE_PER_VBUS || ichan >= MV_SATA_CHANNELS_NUM) return -EINVAL; - - pArray = _vbus_p->pVDevice[iarray]; - if (!pArray || (pArray->vf_online == 0)) return -EINVAL; - - for (i=0;iVDevices[ichan]; - if(!pVDev->u.disk.df_on_line || pVDev->pParent) return -EINVAL; - - /* Not allow to use a mounted disk ??? test*/ - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) - if(pVDev == _vbus_p->pVDevice[i]) - { - periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i); - if (periph != NULL && periph->refcount == 1) - { - hpt_printk(("Can not use disk used by OS!\n")); - return -EINVAL; - } - /* the Mounted Disk isn't delete */ - } - - switch(pArray->VDeviceType) - { - case VD_RAID_1: - case VD_RAID_5: - { - pSubArray = pArray; -loop: - oldspl = lock_driver(); - if(hpt_add_disk_to_array(_VBUS_P VDEV_TO_ID(pSubArray), VDEV_TO_ID(pVDev)) == -1) { - unlock_driver(oldspl); - return -EINVAL; - } - pArray->u.array.rf_auto_rebuild = 0; - pArray->u.array.rf_abort_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); - unlock_driver(oldspl); - break; - } - case VD_RAID_0: - for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) - if(pArray->u.array.pMember[i] && mIsArray(pArray->u.array.pMember[i]) && - (pArray->u.array.pMember[i]->u.array.rf_broken == 1)) - { - pSubArray = pArray->u.array.pMember[i]; - goto loop; - } - default: - return -EINVAL; - } - return orig_length; - } - } - else if (length>=7 && strncmp(buffer, "verify ", 7)==0) - { - buffer+=7; - length-=7; - if (length>=6 && strncmp(buffer, "start ", 6)==0) - { - buffer+=6; - length-=6; - if (length>=1 && *buffer>='1') - { - iarray = *buffer-'1'; - if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL; - - pArray = _vbus_p->pVDevice[iarray]; - if (!pArray || (pArray->vf_online == 0)) return -EINVAL; - - if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) - return -EINVAL; - - if (!(pArray->u.array.rf_need_rebuild || - pArray->u.array.rf_rebuilding || - pArray->u.array.rf_verifying || - pArray->u.array.rf_initializing)) - { - oldspl = lock_driver(); - pArray->u.array.RebuildSectors = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, VERIFY); - unlock_driver(oldspl); - } - return orig_length; - } - } - else if (length>=5 && strncmp(buffer, "stop ", 5)==0) - { - buffer+=5; - length-=5; - if (length>=1 && *buffer>='1') - { - iarray = *buffer-'1'; - if(iarray >= MAX_VDEVICE_PER_VBUS) return -EINVAL; - - pArray = _vbus_p->pVDevice[iarray]; - if (!pArray || (pArray->vf_online == 0)) return -EINVAL; - if(pArray->u.array.rf_verifying) - { - oldspl = lock_driver(); - pArray->u.array.rf_abort_rebuild = 1; - unlock_driver(oldspl); - } - return orig_length; - } - } - } - else -#ifdef _RAID5N_ - if (length>=10 && strncmp(buffer, "writeback ", 10)==0) { - buffer+=10; - length-=10; - if (length>=1 && *buffer>='0' && *buffer<='1') { - _vbus_(r5.enable_write_back) = *buffer-'0'; - if (_vbus_(r5.enable_write_back)) - hpt_printk(("RAID5 write back enabled")); - return orig_length; - } - } - else -#endif -#endif /* SUPPORT_ARRAY */ - if (0) {} /* just to compile */ -#if DBGUG - else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) { - buffer+=9; - length-=9; - if (length>=1 && *buffer>='0' && *buffer<='3') { - hpt_dbg_level = *buffer-'0'; - return orig_length; - } - } - else if (length>=8 && strncmp(buffer, "disable ", 8)==0) { - /* TO DO */ - } -#endif - - return -EINVAL; -} - -/* - * Since we have only one sysctl node, add adapter ID in the command - * line string: e.g. "hpt 0 rebuild start" - */ -static int hpt_set_info(int length) -{ - int retval; - -#ifdef SUPPORT_IOCTL - PUCHAR ke_area; - int err; - DWORD dwRet; - PHPT_IOCTL_PARAM32 piop; -#endif - char *buffer = hptproc_buffer; - if (length >= 6) { - if (strncmp(buffer,"hpt ",4) == 0) { - IAL_ADAPTER_T *pAdapter; - retval = buffer[4]-'0'; - for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { - if (pAdapter->mvSataAdapter.adapterId==retval) - return (retval = hpt_set_asc_info(pAdapter, buffer+6, length-6)) >= 0? retval : -EINVAL; - } - return -EINVAL; - } -#ifdef SUPPORT_IOCTL - piop = (PHPT_IOCTL_PARAM32)buffer; - if (piop->Magic == HPT_IOCTL_MAGIC) { - KdPrintE(("ioctl=%d in=%x len=%d out=%x len=%ld\n", - piop->dwIoControlCode, - piop->lpInBuffer, - piop->nInBufferSize, - piop->lpOutBuffer, - (u_long)piop->nOutBufferSize)); - - /* - * map buffer to kernel. - */ - if (piop->nInBufferSize+piop->nOutBufferSize > PAGE_SIZE) { - KdPrintE(("User buffer too large\n")); - return -EINVAL; - } - - ke_area = malloc(piop->nInBufferSize+piop->nOutBufferSize, M_DEVBUF, M_NOWAIT); - if (ke_area == NULL) { - KdPrintE(("Couldn't allocate kernel mem.\n")); - return -EINVAL; - } - - if (piop->nInBufferSize) - copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize); - - /* - * call kernel handler. - */ - err = Kernel_DeviceIoControl(&gIal_Adapter->VBus, - piop->dwIoControlCode, ke_area, piop->nInBufferSize, - ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet); - - if (err==0) { - if (piop->nOutBufferSize) - copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize); - - if (piop->lpBytesReturned) - copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD)); - - free(ke_area, M_DEVBUF); - return length; - } - else KdPrintW(("Kernel_ioctl(): return %d\n", err)); - - free(ke_area, M_DEVBUF); - return -EINVAL; - } else { - KdPrintW(("Wrong signature: %x\n", piop->Magic)); - return -EINVAL; - } -#endif - } - - return -EINVAL; -} - -#define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8)) - -static void get_disk_name(char *name, PDevice pDev) -{ - int i; - MV_SATA_CHANNEL *pMvSataChannel = pDev->mv; - IDENTIFY_DATA2 *pIdentifyData = (IDENTIFY_DATA2 *)pMvSataChannel->identifyDevice; - - for (i = 0; i < 10; i++) - ((WORD*)name)[i] = shortswap(pIdentifyData->ModelNumber[i]); - name[20] = '\0'; -} - -static int hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) -{ - int printfretval; - va_list ap; - - if(fmt == NULL) { - *hptproc_buffer = 0; - return (SYSCTL_OUT(pinfo, hptproc_buffer, 1)); - } - else - { - va_start(ap, fmt); - printfretval = vsnprintf(hptproc_buffer, sizeof(hptproc_buffer), fmt, ap); - va_end(ap); - return(SYSCTL_OUT(pinfo, hptproc_buffer, strlen(hptproc_buffer))); - } -} - -static void hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan) -{ - char name[32], arrayname[16]; - - get_disk_name(name, &pVDev->u.disk); - -#ifdef SUPPORT_ARRAY - if(pVDev->pParent) - memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME); - else -#endif - arrayname[0]=0; - - hpt_copy_info(pinfo, "Channel %d %s %5dMB %s %s\n", - iChan+1, - name, pVDev->VDeviceCapacity>>11, - ((!pVDev->u.disk.df_on_line)? "Disabled" : - ((pVDev->VDeviceType != VD_SPARE)?"Normal ":"Spare ")), arrayname); -} - -#ifdef SUPPORT_ARRAY -static void hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) -{ - int i; - char *sType=0, *sStatus=0; - char buf[32]; - PVDevice pTmpArray; - - switch (pArray->VDeviceType) { - case VD_RAID_0: - for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) - if(pArray->u.array.pMember[i]) { - if(mIsArray(pArray->u.array.pMember[i])) - sType = "RAID 1/0 "; - /* TO DO */ - else - sType = "RAID 0 "; - break; - } - break; - - case VD_RAID_1: - sType = "RAID 1 "; - break; - - case VD_JBOD: - sType = "JBOD "; - break; - - case VD_RAID_5: - sType = "RAID 5 "; - break; - - default: - sType = "N/A "; - break; - } - - if (pArray->vf_online == 0) - sStatus = "Disabled"; - else if (pArray->u.array.rf_broken) - sStatus = "Critical"; - for (i = 0; (UCHAR)i < pArray->u.array.bArnMember; i++) - { - if (!sStatus) - { - if(mIsArray(pArray->u.array.pMember[i])) - pTmpArray = pArray->u.array.pMember[i]; - else - pTmpArray = pArray; - - if (pTmpArray->u.array.rf_rebuilding) { -#ifdef DEBUG - sprintf(buf, "Rebuilding %dMB", (pTmpArray->u.array.RebuildSectors>>11)); -#else - sprintf(buf, "Rebuilding %d%%", (pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)); -#endif - sStatus = buf; - } - else if (pTmpArray->u.array.rf_verifying) { - sprintf(buf, "Verifying %d%%", (pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)); - sStatus = buf; - } - else if (pTmpArray->u.array.rf_need_rebuild) - sStatus = "Critical"; - else if (pTmpArray->u.array.rf_broken) - sStatus = "Critical"; - - if(pTmpArray == pArray) goto out; - } - else - goto out; - } -out: - if (!sStatus) sStatus = "Normal"; - hpt_copy_info(pinfo, "%2d %11s %-20s %5dMB %-16s", nld, sType, pArray->u.array.ArrayName, pArray->VDeviceCapacity>>11, sStatus); -} -#endif - -static int hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) -{ - PVBus _vbus_p = &pAdapter->VBus; - struct cam_periph *periph = NULL; - UINT channel,j,i; - PVDevice pVDev; - -#ifndef FOR_DEMO - if (pAdapter->beeping) { - intrmask_t oldspl = lock_driver(); - pAdapter->beeping = 0; - BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); - unlock_driver(oldspl); - } -#endif - - hpt_copy_info(pinfo, "Controller #%d:\n\n", pAdapter->mvSataAdapter.adapterId); - - hpt_copy_info(pinfo, "Physical device list\n"); - hpt_copy_info(pinfo, "Channel Model Capacity Status Array\n"); - hpt_copy_info(pinfo, "-------------------------------------------------------------------\n"); - - for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) - { - pVDev = &(pAdapter->VDevices[channel]); - if(pVDev->u.disk.df_on_line) - hpt_copy_disk_info(pinfo, pVDev, channel); - } - - hpt_copy_info(pinfo, "\nLogical device list\n"); - hpt_copy_info(pinfo, "No. Type Name Capacity Status OsDisk\n"); - hpt_copy_info(pinfo, "--------------------------------------------------------------------------\n"); - - j=1; - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++){ - pVDev = _vbus_p->pVDevice[i]; - if(pVDev){ - j=i+1; -#ifdef SUPPORT_ARRAY - if (mIsArray(pVDev)) - { - is_array: - hpt_copy_array_info(pinfo, j, pVDev); - } - else -#endif - { - char name[32]; - /* it may be add to an array after driver loaded, check it */ -#ifdef SUPPORT_ARRAY - if (pVDev->pParent) - /* in this case, pVDev can only be a RAID 1 source disk. */ - if (pVDev->pParent->VDeviceType==VD_RAID_1 && pVDev==pVDev->pParent->u.array.pMember[0]) - goto is_array; -#endif - get_disk_name(name, &pVDev->u.disk); - - hpt_copy_info(pinfo, "%2d %s %s %5dMB %-16s", - j, "Single disk", name, pVDev->VDeviceCapacity>>11, - /* gmm 2001-6-19: Check if pDev has been added to an array. */ - ((pVDev->pParent) ? "Unavailable" : "Normal")); - } - periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); - if (periph == NULL) - hpt_copy_info(pinfo," %s\n","not registered"); - else - hpt_copy_info(pinfo," %s%d\n", periph->periph_name, periph->unit_number); - } - } - return 0; -} - -static inline int hpt_proc_in(FORMAL_HANDLER_ARGS, int *len) -{ - int i, error=0; - - *len = 0; - if ((req->newlen - req->newidx) >= sizeof(hptproc_buffer)) { - error = EINVAL; - } else { - i = (req->newlen - req->newidx); - error = SYSCTL_IN(req, hptproc_buffer, i); - if (!error) - *len = i; - (hptproc_buffer)[i] = '\0'; - } - return (error); -} - -static int hpt_status(FORMAL_HANDLER_ARGS) -{ - int length, error=0, retval=0; - IAL_ADAPTER_T *pAdapter; - - error = hpt_proc_in(REAL_HANDLER_ARGS, &length); - - if (req->newptr != NULL) - { - if (error || length == 0) - { - KdPrint(("error!\n")); - retval = EINVAL; - goto out; - } - - if (hpt_set_info(length) >= 0) - retval = 0; - else - retval = EINVAL; - goto out; - } - - hpt_copy_info(req, "%s Version %s\n", DRIVER_NAME, DRIVER_VERSION); - for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { - if (hpt_get_info(pAdapter, req) < 0) { - retval = EINVAL; - break; - } - } - - hpt_copy_info(req, NULL); - goto out; - -out: - return (retval); -} - - -#define xhptregister_node(name) hptregister_node(name) - -#if (__FreeBSD_version < 500043) -#define hptregister_node(name) \ - SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node") \ - SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ - NULL, 0, hpt_status, "A", "Get/Set " #name " state") -#else -#define hptregister_node(name) \ - SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \ - SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ - NULL, 0, hpt_status, "A", "Get/Set " #name " state"); -#endif - -xhptregister_node(PROC_DIR_NAME); diff --git a/sys/contrib/dev/hptmv/i386-elf.raid.o.uu b/sys/contrib/dev/hptmv/i386-elf.raid.o.uu deleted file mode 100644 index f8d041348847..000000000000 --- a/sys/contrib/dev/hptmv/i386-elf.raid.o.uu +++ /dev/null @@ -1,1346 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * $FreeBSD$ - */ -begin 664 hptmvraid.o -M?T5,1@$!`0D```````````$``P`!``````````````#0N````````#0````` -M`"@`#``)`%6)Y5=64X'L%`(``(M]"(M'#(F%\/W__X!_`0"-=\0/A5<%``"` -M?P(`#X1%!0``L0&`3@$$B`Z+1PR)1@@/ML&+5Q"+!(4`````@/D#QT8$```` -M`(E6#(E&-'0<#[8&BP2%`````(!.`02)1CB-9?1;7E_)PXUV`(U"]HV5]/W_ -M_XE&#%)J((M'$(/H"E!7Z/S___^#Q!"!O?3]___S%GA:=;EHD````(V%]/W_ -M_U#H_/___X3`6EEUHHJ%_?W__X/@`H3`=!;&1P@!BH7^_?__.D<)B$<+#X*# -M!```:``"``"-E?3]__]2Z/S___^$P%I9#X5(!```BI6'_O__BD<$B-.#XP&# -MX/R(T8/A`@G8"3]__\/A,S^ -M__\QT@^VG?_]__\YVGTMC8WT_?__@\$0B@$\"`^'K/[__P^VP(L$A0````"% -MP`^$FO[__T*#P1`YVGSC]__^)5TR*A17^__^(1SR*E13^__^(%XN%$/[__XE'#(E? -M!(J-%_[__[@!````T^"(3SYFB4=$#[;2BP25`````(E'-`^V`XL$A0````") -M1SB*A>_]__^(1P.+E>#]__^-A?3]__^)?)-0_D,]@\`L:A!0C4=P4.C\____ -MC87T_?__:@2#P#Q0C8>`````4.C\____C87T_?__:A"#Z(!0C8?$````4.C\ -M____@\0DC87T_?__:D"#P$!0C8>$````4.C\____@\0,Z6;^__\/MH7O_?__ -MBU2#4(72#X5/^___B72#4/Y#/8J5[_W__XA6`P^V`XE>!(L$A0````#I-/S_ -M_VAP`0``C87T_?__:@`%D````%#H_/___X/$#.F8^___#[;`4%?H_/___UM8 -MZ6S[__^-=@"Q`^FV^O__D+$"Z:[Z__^058GE5E.+=0PQVP^V1CPYPWT/B?:+ -M5)Y0A=)T#$,YPWSSC67X6U[)PXC9N`$```#3X&8)1DA6_W4(Z/S___^)PH72 -M6%ETV\8"`X`^"`^4P(I*`<'@`X/A]PG!B$H!B%H#H0P```")0C0/M@:+!(4` -M````B7($B4(XBD8!@^`0A,!T#(/)$(M"3(A*`8E"#(E4GE"*1D:#X/Z#R`J( -M1D;'1DP`````_D8]4FH'Z/S___^`3D8$6U[I9O___Y!5B>575E-7BT4(B47P -MBUT,#[8#@_@�X`0``@_@&#X^+````@_@$?`J*4SPX4SUT-8GVBTL$AG\____ -M@$L!!(!C1OXQ_X32=+^-=@"+=+M0A?9T!8`^`W<*1P^VPCG'?.OKI5;_=?#H -M_/___XI&1H/@!%F$P%YT!(!+1@2*4SSKV(UV`(/X"`^%>____XI#/8I3/#C0 -M='(/ML!`#[;2.=!T#@^W0T3WV"%#3.E8____9HM#2&:%P'1"#[?0,7^O=BE-&B-"#X`*$P'71Z]N*0T:#X/Z`2P$$9H-[2`"(0T9T -MA8/(`HA#1NEZ____@$L!!(![/0)T/HM#4(!C1OV%P'41BT-4QD`#`(E#4,=# -M5`````"`.`-T$(!+1@3'0TP`````Z:7^__]3_W7PZ/S___]86NOC@&-&_NF/ -M_O__C78`58GE5U:+?0A3O@\```"-GV`B``"+0T"%P'0'BT,$A7\G#D%-7Z/S___^*0P&#X`1:A,!9=-O'0S@`````Z])5B>57 -M5E.![`0"``"+=0R*11!6B(7S_?__Z/S___^`/@A9#X3I````BD8\,?\\`'9_ -MC78`BUR^4(7;=&V`.P,/A[,```"*4P&#XO[&0P,`QT-0`````(A3`8"]\_W_ -M_P#'0P0`````QT,X`````'4%@#X&=&QH``(``&H`C97T_?__4NC\____C87T -M_?__4&HP:@"-0SQ0Z/S___^#Q!Q3Z/S___]8BD8\1XGZ.-!WA&C4````:@!6 -MZ/S___^+50B+@EPB``")1@B)LEPB``"#Q`S'1D``````C67T6UY?R<.+1@2% -MP'6-BD8!@^`!"<*(4P'KJHUV``^VA?/]__]0_W2^4/]U".C\____@\0,ZY56 -M_W4(Z/S___]86ND'____C78`58GE5U93@>P,`@``BU4,BP*+6`2)G?#]__^+ -M6B"+4Q2)E>S]__^+M>S]__\/MD`#A?:+?1"+312)A>C]__^-E?3]__\/A+,` -M``!F#[9#$(/@`0^WP#G(#X2@````#[=3+,'B"0^V6RB+C>S]__]FBT$$9H7` -MBS$/M\AU"+D```$`C78`.C]__]T6"G!`<8IPG4=BY7P_?__ -M#[9"/$,YPP^4P`^VP$@/MU)$(S]___KDF;'1_X`@+@!````C67T6UY?R<.-=@!FB4<$9L='!@``B3>#QPCK -MEXM#&(7`B97L_?__=00QP.O345)3_W4(_]"#Q!"%P`^%//___^OGD%6)Y5=6 -M4X/L"(M%"(M0!(E5\(M=#(I0`XI+*#C*BWLD9HMS,'1B.,IS"8M%\`^W0$0! -MQSC*=$F*0RDXPG0Z@'LT`'0D.,IV"SC"

+1?!F`W!$BU409HER"(EZ!(/$ -M"%M>7\G#C78`.,IVW(M-\&8#<43KTXUV`&8#S(`6G47@'L1`'4$QD,1`5/_7\G#_W4(Z/S___^)PXM%\(M$L%") -M1>R)`XE[((I7$(I#$(/B`H/@_0G0B$,0BE<0@^($@^#["="(0Q"*1PJ(0PI3 -M5_]U[.A\_?__QT,<`````,=#&`````!3_W4(BU7L_U(TBTWP@\08BE$\Z7K_ -M__^)]L9'$0)7_W<<_W4(Z/S____I<____XUV`%6)Y8M5#(M*!(I!`<#H`H!B -M`?OWT(M1.(/@`8!A`?O^23V`248!A=)T!(7`=`+)PU'_=0C_TEA:Z_2)]E6) -MY593BT4,BU`@BTH4AR<,QP.OUD(I&`<#H`H/@`0^VP.OFB?95B>575E.#[`B+?0R+7R"+`XLW -MB47PB77LBD\1@/D!=$^*4Q"(T(/@`H3`#X3/````@'L2`'4YBU7PBD)&@^`" -MA,!U+,9#$@$QP(!^`P`/E,"+=()0A?9T$U;H2?___X7`6G5UBP>)1>R*3Q&+ -M=>R0B$L15_]U".C\____#[9.`[C^____T\!F(T,R9HE#,E]FAQ$` -M=03&0Q$!4_]S'/]U".C\____BU7P9HM"%DB#Q`QFA7\G#:C"-1R1J`%#H_/___P^V3@.X`0```-/@9HE# -M,HDW5_]U"/]6-.O1@^($A-(/A&7___]6Z)?^__^%P%EU*8![$0$/A%/___\/ -MMDX#N`$````/MU,RT^`YP@^%//___XI/$>DQ____:C!J`(U')%#H_/___^NI -MB?95B>56BW444XM5#(7VBUT0BTH@=".+00R)`V:+0@C!X`EFB4,$9L=#!@"` -MN`$```"-9?A;7LG#D(M1%(72="V*01"#X`&$P'0CB=&0BP&+402)4P2)`V:+ -M008E`(#__X/#"(/!"&:%P'3BZ[^+01B%P'4$,<#KN5934?]U"/_0ZZ^-=@!5 -MB>575E.+=0R+!@^V2`.X_O___]/`BUX@BWT(9B%#,HI&$3P!=`.(0Q%65^C\ -M____66:#>S(`6'4X@'L1`'4.QD,1`8L+BU%,.U8$="Q3_W,<5^C\____BP-F -MQT`4``"#P!A0:`````!7Z/S___^#Q!B-9?1;7E_)PP^W1@B-!!")04SKR(GV -M58GE5U93BW4,BD81/`&+?0B+7B!T-HA#$597Z/S___]3_W,<5^C\____BP-F -MQT`4``"#P!A0:`````!7Z/S___^-9?1;7E_)PXUV`(!^"B!T&L9#$0&+"XM1 -M3#M6!'6Y#[=&"(T$$(E!3.NMBP/&1A$`BT!4B09J,&H`C48D4.C\____BD80 -M@^#]@\@$B$80QD82`,9&"C"+!E97_U`TZZ"-=@!5B>575HM5%%.+10R%THM] -M$(M(('1"BTD,B0]FBU`(P>()9HE7!&;'1P8`@(L`@'@#`'0-9H72=!@'L#``^$;?___SG/#X1E____BP&+402)5P2)!V:+008E`(#__X/' -M"(/!"&:%P'3BZ4+___^)T&8I\`$Q9HE!!.N^.?)RLV:)<01FQT$&`(#KKHM! -M&(7`=0?___\9#$0&+"XM13#M6!`^%9____P^W1@B- -M!!")04SI6/___XUV`%6)Y5=64XM=#(LSBD9&@^`!A,#'1AP`````=14/MD,* -M@_@"#X3_````@_@"?WY(="S&0Q$&4_]S'/]U".C\____@\0,C4884&@````` -M_W4(Z/S___^-9?1;7E_)PXM#!(E&$&:+0PAFB484_W4(Z/S____&0`H@B<*+ -M0P2)0@1FBT,(@$H0`F:)0@B)6B#'0AP`````QT(8`````(M&4(D"4O]U"/]0 -M-.N7B?:#^`-U@(M#!(E&$&:+0PAFB484#[=#",'@"5!J`/]S#.C\____,?]F -MQT,R`P"#Q`S_=0CH_/___\9`"C")PHM#!(E"!&:+0PAFB4((@$H0!(E:(,=" -M'`````#'0A@`````BT2^4(D"4O]U"$?_4#2#Q`R#_P%^N>D<____BT,$B480 -M9HM#"&:)1A3_=0CH_/___\9`"B")PHM#!(E"!&:+0PAFB4((@$H0`HE:(,=" -M'`````#'0A@`````Z3#___]5B>575E.#[!"+10B+?0R)1?"+-XI&`8/@!(3` -M#X32`0``BD<0@^`@A,!T-&:#?A8`QT8<7!,``(E^('0+C67T6UY?R<.-=@"+ -M5?")?0R)50B-9?1;7E_)Z3?^__^-=@"+1AR%P`^%;0$``&:+1A1FA0`````BTWDBT2.4(7`=!^*0`&#X`2$P'05BD<0@^`$ -MA,!U'(I%[SA%[G04C78`_D7O_T7D@'WO`7;*Z2#_____=?#H_/___VHD5U") -MP^C\____BDWDN`$```#3X&8)1S*)>R#'0QP`````QT,8`````(M5Y(M$EE") -M`U/_=?#_4#2#Q!CKJ(`Y`P^%5O___XM?!(M"6"M95(E%Z(M'!"M"5(M)6'A! -MA=MX.3G8?1^%R<9%[@`/A3G___^#?>@%#X8O____QD7N`>DF____BUWHA=O& -M1>X`=>R#^04/AQ+____KX??;Z\/WV.N[C78`QD7N`.G\_O__C78`C488QT7\GI_/___\9'$0)7_W<<_W7PZ/S____I-/[__XUV -M`%6)Y5=64XMU#(M>!(M]"(!F`?N*0SV*4T9(@\H!A,`/MDX#QT-,`````(A3 -M1HA#/703B-"#X`*$P'0.@^+5AC\____B4-`B5T(C67T6UY?R>G\____ -M4U?_T%A:Z\R%R744BU-0BT-4QD(#`8E#4,9``P")4U2+4P2%TG0*BD(!@^`$ -MA,!TIHM#4(`X`W6>4U?H_/___X7`68G"7W2,Q@`#QD`#`8E8!*$,````B4(T -MH1@```")0CB*0P&#X!"$P'0*BT),@$H!$(E"#,=&!`````"*0T:#X/Z#R`J) -M4U2(0T;^0SU2:@?H_/___^EH____B?95B>575E.![!`"``"+10R+$(M`((MP -M%(7VB97P_?__BTT4B87D_?__QX7L_?__$0```(V5]/W__P^$5@$``&8/MD`0 -M@^`!#[?`.<@/A$,!``"+O>3]__^`?RG_#X2E````9HM&!`^W7RS!XPEFA<`/ -MM\AU!;D```$`.O]__^+O>3]__^*5RB-=@`X -ME>O]__\/A)P```"#Q@AFBT8$*.`#4%;_=1#H_/___[@!````C67T6UY? -MR<-FQT<&`(#KZXM5$(L&B0)FB5H$9L="!@"`Z]B-=@"+?1"+!HM6!(E7!(D' -MBX7P_?__@\<(BD`#B7T0B(7K_?__B[WD_?__BEO]__^+O>3]__^*5RCI-____XUV`(N=Y/W__XM#&(7`B=9U!S'`Z73___]1 -M4E/_=0C_T(/$$(7`#X64_O__Z^2058GEBTT,4XI1*(M%"#A0`XM=$'079HM! -M*F:)0PC'0P0`````BQPDR<.-=@!FBT$L9HE#"(M!)(E#!.OH58GE5U93@^P, -MBWT,9HM'"(M?!(MU"&:)1?**1CPQR83`B$7KQT7L`````'09C78`BU2.4(M" -M##G#7\G#N`$```#3X&:+=S()QHE?)(A/ -M*&:)=S(/MT7RC008.T(,=C*-00''1>P!````B$S(` -M6G47@'L1`'4$QD,1`5/_ -M7\G#_W4(Z/S___^)PXM%\(M$L%")1>R)`XE[((I7$(I#$(/B`H/@_0G0B$,0 -MBE<0@^($@^#["="(0Q"*1PJ(0PI35_]U[.@(_O__QT,<`````,=#&`````!3 -M_W4(BU7L_U(TBTWP@\08BE$\Z7K___^)]L9'$0)7_W<<_W4(Z/S____I<___ -M_XUV`%6)Y8M%#(!@`?N+4`2+0CB`8@'[_DH]@$I&`87`=07)PXUV`%+_=0C_ -MT%A:Z_&)]E6)Y8M-#%.+70B+E(N\+P``A=)T"8L"B82+O"\``(G0BQPDR<.- -M=@!5B>6+51!3BUT(BX23O"\``(M-#(D!B8R3O"\``(L<),G#B?95B>575E.# -M[`B+10P]``@``(M5$+X`$```=T0]``0``+X`"```=S@]``(``+X`!```=RP] -M``$``+X``@``=R`]@````+X``0``=Q2#^$`/A]P```"#^"$9]H/FX(/&0`^O -MUH'"_P\``(E5\,%M\`S_3?"#??#_QT7L``````^$FP```)#_=0CH_/___XG# -M,=*X`!```#'_]_;_1>PYQUES<(UV`('^``@``+@'````=T.!_@`$``"X!@`` -M`'>)GN`O``!J`E=6Z/S]__^-9?1;7E_)PU6)Y593BW4(BQY+@_O_ -M=!EH`!```&H`_W2>!$OH_/___X/$#(/[_W7GC67X6U[)PU6)Y5.+70B+"TF# -M^?]T((M$BP0QTHUV`(,X`'4:0H/`!('Z_P,``';O28/Y_W7@N`$```!;R<,Q -MP.OYD%6)Y6H0:@#_=0CH_/___\G#C78`58GEBTT,BU$,A=)T!HM!"(E""(M! -M"(D0QT$(`````&H`4?]U".A*_?__R<-5B>564XM="(M#,(M-#(7`C7,PB4$, -M=`F+4S"-00R)0@B)<0B)2S!;7LG#D%6)Y5=64XM%#(M8,(7;BWT0BW44=!*) -M]CDSP1W*XM;#(7;=?!J`/]U".C"_/__B3B)<`10B575E.+=0P/ME8FC4+]T?@QVP'" -M.=.+?0A\$VH'5E?H;OS__XUE]%M>7\G#B?;_M)Z<"```5^@7_O__6%H/ME8F -MC4+]T?A#`<(YTWSAZ\R-=@!5B>575E.#[!2*10R+512(1?-FB57PBT4(BY#@ -M+P``#[9-\P^W1?")1>2-0?W1^(T$",'B`P^O1>0YP@^#@P```(M5"('"I"\` -M`(E5X(G/D(M%"(N8I"\``#M=X`^$+`$``(L#BU,$B5`$B0*+0Q")WH7`B1Z) -M7@1T%HM3%(72=`.)0A"+1A")$,=&$`````"+5?!F.5,D#X3W````4_]U".@& -M____6(M%"%J+D.`O``"-1_W1^(T$.,'B`P^O1>0YPG*,:@?_=0CH2OO__XG& -M7U@QP(7V#X2"````BU40B58@BE7SBT7PB%8F#[95\V:)1B2-0OW1^#'_C000 -M.<>)-HEV!,=&&`````!]3V;!;?`##[=5\(E5Z(E%[/]UZ/]U".AY_/__B82^ -MG`@``%F%P%MT,HG[P>,$C1PSC8/$"```4('#1`D``.AJ_?__1U/H8_W__UD[ -M?>Q;?,")\(UE]%M>7\G#3X/__W07_[2^G`@``/]U"$_HA/S__UB#__]:=>EJ -M!U;_=0CHLOK__S'`Z\R)]HI%\SA#)@^%_?[__P^VP(M5$(7`B1N)6P2)4R!T -M%8VS1`D``(G'5NCX_/__@\803UEU\XG8ZY.058GE5U93@^P(BT449HE%\HM5 -M#(M]$`^V2CZ)^-/H)?\#``"+4BR-'(*+,X7V=`V0.7X@=&N+=A2%]G7T#[=% -M\E!7BU4,#[9"/%#_=0CHXOW__X/$$(7`B<9T.XM-#(E('(L#A<")1A1T"(L3 -MC484B4(0BT4,B3.)7A"*6#R(7B8/MD@^T^\QT@^V2#R)^/?Q*--+B%XGC67T -M6XGP7E_)PXM6!(L&B5`$B0*)=@2)-NOEC78`58GE5U93@>RT````BT4,BE`0 -MB-#0Z(G!]]�&)C6#___^+30R+012%P'0+@^(!A-(/A%0"``!J`8V%9/__ -M_U#_=0S_=0B)A5S___^+50S_4AB#Q!"+C5S___]FBT$$#[?09H7`B95$____ -M=0K'A43___\```$`QX5,____`````(M-#(I11(32QX58____``````^$C0$` -M`(M-#(N%6/___XM$@3")A5#___^*B!P*``"(C5?___^*@!T*```XA5?___\/ -MAT8)`=>-=@"+A43___\YA4S_ -M__\/A-(```"+G43___\KG4S___\Y\W8"B?.+A6#___^%P`^$F@```%.+A4S_ -M__^+E5S___\#`E!7Z/S___^#Q`P!G4S___\IWG0$`=_KIXN%2/___V8IA4K_ -M__]T%O^%0/___S'29L>%2/___P@`Z3[___^+E5#___^*@AT*``#^A5?___\X -MA5?___\/AK_^__^+30R*443_A5C___\/ML(YA5C___\/C'/^__]J`/]U#/]U -M"/]5$(UE]%M>7\G#B?935XN%3/___XN-7/___P,!4.EA____B?:#A5S___\( -MBY5<____9HM"!`^WR&:%P(F-1/___W4*QX5$____```!`,>%3/___P````#I -M]O[__XF%7/___^F__?__D%6)Y5=64X/L%(M%"(E%\(M%$(7`BWT,=`3&1Q$+ -MQT7L`````(!_1``/A)\```"+5?"+1?"!PJPO```%I"\``(E5Z(E%Y(UV`(M5 -M[(M,ES"*028QVSC#QX'T"0```````(A%XW-"C78`#[;#P>`$C00(C9#$"``` -MBX#$"```,?:%P'45BT($A+0@R%P'0%O@$```"%]G5(0SI= -MXW+!,<"%P'0WBU7HBT($B1&)2@3_1>R)002)"`^V1T0Y1>P/C'O___^+1?") -M?0R)10B#Q!1;7E_)Z59```")]HM5Y.O'N`$```#KN56)Y5=64X/L&(M=#(M% -M"/^(Y"\``(E%\(NS]`D``(U#"(M(!(M3"(7VB4H$B1&)0`2)0P@/A)8"``"* -M5A"(T(/@((3`#X3R````#[=3)(M%\`6D+P``B57D`U,@B57HBU`$B0.)6`2) -M&HJ#'@H``#P!BS['@_0)````````B5,$=0J`?@H"='<\`708B$81BT7PB74, -MB44(C67T6UY?R>FD/P``BT8$0`^W5T0/K\(Y1>AR&P-73#M5Z'0+BU7PB74, -MB54(Z]&+1>B)1TSK[?]UY/]UZ%?_=?#HYOK__XFP]`D``(E&,(M5\(E%#(E5 -M"(/$$(UE]%M>7\GI50X```^V0R?_M(.<"```Z&7W__^%P%IU',:#'@H```P/ -MMT=$@$]&"O?8(T,@.4=,=@.)1TR*@QX*``#I3?___Y"*1D5`BDY$.,B(1D4/ -MA(H```"+5?"+@N@O``"%P'0)@+L>"@```70(C67T6UY?R<.+4QR+2B2%R746 -MA7\GI_/___U+H(CT``(7`6G0+BU7PBX+H+P``Z]2+ -M0QS_<"B+0QS_<"3_=?#H_/___XM#'(M5\,=`)`````"+@N@O``!(@\0,B8+H -M+P``ZZ&-=@"#X@2$T@^$F0```,9%[P`X3>]S4HM%\(M5\`6D+P``@<*L+P`` -MB47@B57^+7(8PBH,>"@``/`''@_0)````````="Z(1A&+5=R+0@3^ -M1>^)6@2)$XE#!(D8BD7O.D9$7^D`____,?^)^#I#)G(% -MBU7@Z\J)^@^VPL'@!(V$&,0(``!01^@^]O__6(GX.D,F]S -M((UV``^V1>^+7(8PBH,>"@``/`%T`XA&$?Y%[SA-[W+C@'X1`'46:"`E``!6 -M_W7PZ+_Y__^#Q`SIC?[__VH`5O]U\.A$_/__Z^N)]H"['@H```$/A)\```"+ -M1?`%K"\``(M0!(D#B5@$B1J)4P2+D_@)``"%TG55_W,8_W7PZ+WU__^+0QS' -M0Q@`````BW@86H7_674IBU7PB[+L+P``A?8/A"/^__^)T`7L+P``4&@````` -M4NC\____Z7;___^#P!A0:`````#_=?#KZ(J#'@H``(A"$?^S^`D``&A89@`` -M_W7PZ/S____'@_@)````````Z>C]__\Q]HGR.E,F6+ -M10R+`(!X*@!U`LG#QD`J`%!H2#,``/]U".C\____@\0,Z^>058GE5U93@^P( -MBU4,BT(@BP@/MD`)BX2!G`@``(E%\(M"!"M!(,'@"0^W6@B)PL'H#(M]$,'C -M"8'B_P\``(E%[+X`$```*=8YWG8"B=Z+112%P'0\BT7LBTWP`U2!!#G>B1=F -MB7<$=!)FQT<&``#_1>R#QP@I\S'2Z\9FQT<&`("-9?1;7K@!````7\G#C78` -MBTWPBT7L`U2!!%+H_/___XG"6>NYC78`58GE5U93BUT(BD,+`$,*C7,,B?:* -M4PH/MLJ#^1\/AZ4```"X`0```-/@A4,,#Y7`#[;`A7\G##[;ZQD,+`8GVBE,+#[;"C0PX@_D?=R:X`0```-/@A4,,#Y7` -M#[;`AB$8&4E?H_/___UF`?@8!6'06QD8%`HEU#(E]"(UE]%M>7\GI -MW/W__U;HIO[__X7`6G5"@'X$`779BD8(.D,G=-$Z1@EUS`^VP,'@!(T$&(M6 -M#`F01`D``(U>#(V(1`D``(M#!`E!!(M#"`E!"(M##`E!#.N=QD8&`(EU#(E] -M"(UE]%M>7\GK*%6)Y593BUT,BW4(QD,+`,9#"@!3Z#/^__]8B5T,B74(C67X -M6U[)ZP!5B>575E.+70R+,XM6'`^V0PB+?()0_W4(Z/S___^).(![!`&)PEAT -M.X!*$`3&0@HP#[9#"@-&((E"!&8/MD,+9HE""(E:(,="&"`J``#'0AS@*P`` -M4O]U"/]7-(UE]%M>7\G#@$H0`L9""B#KPXGV58GE5U93@^P(,?\QVXUV`(/[ -M'P^'\P```+@!````B-G3X(M5"(4"#Y7`#[;`A<"^`0```'42@_M_=P-#Z]*# -MQ`A;7HGX7\G#C10>@_H?=VB(T;@!````T^"+30B%`0^5P`^VP(7`=`-&Z]V) -M7>R)TXM%[(M-#,'H`X@$N8I%[(/@!XA$N0&Q""C!BT4,B$RX`@^VP3GP#^G\/AEW____KB8UV`(/Z/W<3C4K@N`$```#3 -MX(M-"(5!!.N/D(/Z7W<5C4K`N`$```#3X(M-"(5!".ET____@_I_=Q6-2J"X -M`0```-/@BTT(A4$,Z5K___\QP.E9____D(/[/W<7C4O@N`$```#3X(M-"(5! -M!.D!____B?:#^U]W%XU+P+@!````T^"+50B%0@CIY?[__XGV@_M_=Q6-2Z"X -M`0```-/@BTT(A4$,ZP8`0``BT4,BU@( -M@'L5`(LP#X0"`0``BWL0A?]U"XE#$(UE]%M>7\G#C87T_O__QD,5`%!3Z%?^ -M__^)A>#^__\/MD,4BX2&G`@``(F%Z/[__XM#$`^V0`R+A(:<"```B87<_O__ -MBU4,#[9"#(N$AIP(```Q]ED[M>#^__^)A>3^__];?7`/MH2U]/[__P^VG+7U -M_O__B[W<_O__BU2'!,'C"0':#[:,M?;^__^)E>S^__^+E>3^__^+?(($`=^) -MO?#^__^+E>C^__\#7(($BX7L_O__P>$).=AT+E'_M?#^__]04^C\____@\00 -M1CNUX/[__WR0:@#_=0S_=0CHYP(``.D:____B?915U#H_/___X/$#.O6C78` -MC87T_O__4%/H:_W__XF%X/[__P^V0Q2+A(:<"```B87H_O__BWT,#[9'#(N$ -MAIP(```Q]HF%W/[__SNUX/[__UA:?9@/MI2U]/[__P^VG+7U_O__B[WH_O__ -MBT27!,'C"0^VC+7V_O__`=B)A>S^___!X0F+A=S^__\#7)`$45/_M>S^__]& -MB9WP_O__Z/S___^#Q`P[M>#^__]\I^DZ____B?95B>575E.![!0!``"+10R+ -M&(V%]/[__U"+10R#P`A0Z+#\__^)A>3^__^+50P/MD(8BX2#G`@``(F%Z/[_ -M_P^V0AF+A(.<"```,?:)A>#^__\[M>3^__]86GU5D`^VE+7T_O__#[:$M?7^ -M__^+O>C^__^+7)<$P>`)#[:,M?;^__\!P\'A"8F=[/[__XN]X/[__P-$EP11 -M4%-&B87P_O__Z/S___^#Q`P[M>3^__]\K&H`_W4,_W4(Z&\!``"-9?1;7E_) -MPXUV`%6)Y5=64X'L5`$``(M%#(M8"(LPC87T_O__4%/HZ_O__XF%I/[__P^V -M0Q2+A(:<"```B86P_O__BU4,BE(4,,)P><) -MBH2%]/[__SJ-H_[__XB%K_[__W,C#[;P#[;!BY2%U/[__XM4L@1!`=HZC:/^ -M__^)E(6T_O__P0#6G0+ -MC67T6UY?R<.-=@"+4PB+0A"%P'3KA?;'0A``````QD`%`K(,=0*R`8A0!HE% -M#(E]"(UE]%M>7\GI(O?__XGV58GE5E-3BT4(C5`LBD`I,=N$P(MU#(A%]W0M -MD(/['W\_N`$```"(V=/@A48@=`V`>@4"=22*0@8\`7460P^V1?>#PB0YPWS4 -MN`$```!96U[)P\9&!0*(1@8QP.OPC78`C4O@N`$```#3X(5&'.N^D%6)Y5=6 -M4X/L$(M%"(E%\(MU#("^'PH```#&1BH`=':-1BR)1>2*5BDQ_X32BUWD=!2- -M=@"`>P4!="!'#[;"@\,D.<=\[XM%\(EU#(E%"(UE]%M>7\GI;O+__X![!`-U -M*8M#"(!X%0!T((M0$(72=!G'0!``````QD,%`HJ&'@H``(A#!HI6*>NQQD8J -M`8UE]%M>7\G#C48LB47DBE8IB?8Q_X32QT7H`0```(M=Y,=%[`````!T)Y"* -M0P6$P`^$W0```#P"=#''1>@`````BD8I1XC"#[;`@\,D.<=\VHM%[(7`=;N+ -M?>B%_W2=QH8>"@```>E-____BD,&/`%TSX!^*P`/A(0```"+5AP/MD,(BT2" -M4(I``8/@!(3`=&;'1>@`````#[9#!(/X!L9#!0'&0P8`=YC_)(4`````4_]U -M\.CN]___6%KKA,9#!0+&0P8!4_]U\.A5]?__Z^E3_W7PZ,[Y___KWE/_=?#H -MA_O__^O34_]U\.A$_/__Z\C&1BL!Z\;&0P8!Z4'___^(AAX*``#&AA\*```! -MZ8;^__^04U;HZ?W__X7`6EET'P^V0P2#^`;&0P4!=Q+_)(4<````4_]U\.AJ -M]___65B*0P4\`@^%\/[___]%[.GD_O__QD,%`L9#!@%3_W7PZ,#T___KV%/_ -M=?#H.?G__^O-4_]U\.CR^O__Z\)3_W7PZ*_[___KM\9&*P'KQHUV`%6)Y5=6 -M4X'LB`$``(M%#(NP]`D``(7VBU@"@```,:''PH```#'A_@)```````` -M#X2U````BE80B-"#X""$P`^$+2(```^V1@J#^`(/A$8>``"#^`(/CQ\=``!( -M=!?_=0S_=0CH\?S__S'2C67T6UZ)T%_)PXM%#(I`)C').,&(A7?^__]S1@^V -MP<'@!`-%#(V0Q`@``(N`Q`@``#';A3^__]0 -MZ+WG__]9_W4,Z'#H__^)A8S^__]:QD`$!HM%#,:%S_[__P"*0"8XA<_^__^( -MA73^__\/@S`*``"+50R*6B`$`T4,C9#$ -M"```BX#$"```,+<@R%]G0%N0$```"%R0^$ -MTP````^VA<_^___!X`2+?0P!QXN'Q`@```F%Y/[__XVWQ`@``(M&!`F%Z/[_ -M_XM&"`F%[/[__XM&#`F%\/[__XJ-S_[__XM%##I(*`^$A0```%#HG^?__UG& -M0`0"BI7/_O__B%`(B%`)BY?$"```B5`,BU8$B5`0BU8(B5`4BU8,B5`8BXV, -M_O__*PB#Z2S!^0*)QHT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y -M'P^/!0D``+@!````T^`)1B"+30R*62>*02:(A73^__^-=@#^A<_^__^*A73^ -M__\XA<_^__\/@LC^____=0SH`.?__UK&0`0"B%@(B%@)B<:+A>3^__^)1@R+ -MA>C^__^)1A"+A>S^__^)1A2+A?#^__^)1AB+C8S^__\K#H/I+,'Y`HT$S0`` -M```IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'P^/40@``+@!````T^`)1B"+ -M30R*22@/MM'!X@0#50R-@D0)``"+6`2+<`B(C7/^__^+0`R+BD0)``")G8C^ -M__^)A8#^__^)Q_?1BX7D_O__]],AP2.=Z/[__XFUA/[__XF-U/[__XF=V/[_ -M_XN-\/[__XN=[/[___?6]]`$C97T -M_O__`<(!\(NX1`D``/?7B3J-L$0)``"+7@3WTXE:!(M."/?1B4H(BT8,]]") -M0@PCO>3^__^).B.=Z/[__XE:!".-[/[__XE*"".%\/[__XE"#(M=#/]U#.C* -MY/__@(/*<*-#-&#^1\/CY\%``"X`0```-/@ -MBXV,_O__"4$@#[:%S_[__\'@!(V]]/[__XT$.(L8,=*%VW47BT@$A"(A>"8N%U/[__XE&#(N%V/[_ -M_XE&$(N%W/[__XE&%(N%X/[__XE&&,:%S_[__P#'A=#^__\`````BT4,BD`F -M.(7/_O__B(5T_O__#X,C^O__C78`BU4,BE(H.)7/_O__B)5[_O__='&*C<_^ -M__^+70PZ2R=T8P^VP<'@!(V-]/[__P'!`=B-D,0(``"+@,0(```CA=3^__^) -M`8M:!".=V/[__XE9!(MR"".UW/[__XEQ"(M2#".5X/[__XE1##')A_[__\'C!(VU -M]/[__XA7"8T<,XL#B4<,BT,$B4<0BT,(B4<4BT,,B4<8BX70_O__A(#*<*-%-")T<'A#RG1 -MC0S(@_D?#X^*`@``N`$```#3X`E'((M=#(I;)XB=>O[__XM%#`^VG<_^__^* -M0"B-E?3^___!XP3_=0R-'!.(A7G^___HX>'__U[&0`0$BHUZ_O__B$@8B<:* -MA7G^__^(1AF+`XE&"(M#!(E&#(M#"(E&$(M##(E&%(N-?/[__RL.@^DLP?D" -MC03-`````"G(C03!P>`#*(#*<*-%-")T<'A#RG1 -MC0S(@_D?#X^%`0``N`$```#3X`E&((N5C/[__RLRC4;4P?@"C13%`````"G" -MC130P>(#*<*-%-")T<'A#RG1C0S(@_D?#X\N`0``N`$```#3X(N-C/[__PE! -M((M%#`^VG<_^__^*0">-E?3^___!XP3_=0R-'!.(A7C^___HQ^#__UG&0`0$ -MBHUX_O__B$@8B<:*A<_^__^(1AF+`XE&"(M#!(E&#(M#"(E&$(M##(E&%(N- -M?/[__RL.@^DLP?D"C03-`````"G(C03!P>`#*(# -M*<*-%-")T<'A#RG1C0S(@_D??R&X`0```-/@BXV,_O__"4$@BUT,BELFB)UT -M_O__Z3O]__^#Z2"X`0```-/@B[6,_O__"48,$C87T_O___W4,C1P#Z&??__]9QD`$`8J5S_[__XA0 -M"(A0"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8*P:#Z"S!^`*-%,4`````*<*- -M%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1]_&[@!````T^`)1B"+30R*22:(C73^ -M___IVOK__X/I(+@!````T^`)1AR+70R*6R:(G73^___IO/K__X/I(+@!```` -MT^"+G8S^__\)0QSI6?K__XM=#/]U#.BXWO__@`$`T4,C9#$"```BX#$"```,+0@R%P'0%N0$```"%R74C_H7/_O__BIUT_O__.)W/ -M_O__#X-?]/__BW4,BEXGZYN-=@`/MIW/_O___W4,P>,$`UT,Z&_=__]?QD`$ -M`HJ5S_[__XA0"(A0"8N3Q`@``(E0#(VSQ`@``(M6!(E0$(M6"(E0%(M6#(E0 -M&(M-#(I))HB-=/[__^N(C87D_O__4.AGW/__QH7/_O__`,:%SO[__P!8BT4, -MBD`F.(7/_O__B(5U_O__#X/##```BU4,BEHGB?8XG<_^__]T?0^VA<_^___! -MX`0#10R-D,0(``"+@,0(```QR87`=16+0@2%P'4.BWH(A?]U!XMR#(7V=`6Y -M`0```(7)=$`/MH7/_O__P>`$`T4,C9#$"```BX#$"```"87D_O__BT($"87H -M_O__BT(("87L_O__BT(,"87P_O___H7._O___H7/_O__BHUU_O__.(W/_O__ -M#X)C____#[:%=?[__X/H`P^VE<[^___1^#G"#X[]!@``BWT,B)_8"0``BX7D -M_O__B8?$"0``BX7H_O__B8?("0``BX7L_O__B8?,"0``BX7P_O__B8?0"0`` -MQH?9"0```<>'U`D```````!7Z.S;__^(6`B(6`G&0`0"BY7D_O__B5`,BY7H -M_O__B5`0BY7L_O__B5`4BY7P_O__B5`8B<:)/"3HM-O__XF%J/[__UO&0`0& -MBXVH_O__*PZ#Z2S!^0*-!,T`````*(/*<*-#-&# -M^1\/CR,&``"X`0```-/@"48@BT4,BD`F/`*(A73^__\/AOX"``#&A<_^__\` -M.(7/_O__#X,3\O__C78`BIW/_O__BW4,.EXG#X1E`0``#[;3P>($B?`!T(N8 -M1`D``/?3B9W4_O__C8A$"0``BT$$]]")A=C^__^+00CWT(F%W/[__XM!#(V] -M]/[__R.=Y/[__XT4.O?0B87@_O__B1J+A=C^__\CA>C^__^)0@2+A=S^__\C -MA>S^__^)0@B+A>#^__\CA?#^__^)0@R)\U;HJ=K__X'#Q`D``%[&0`0#B5@( -MB<:*A<_^__^(1@R+E:C^__^)\2L*@^DLP?D"C03-`````"G(C03!P>`#*`$`T4,C9#$"```BX#$"```,+6@R%VW0%N0$```"%R74IBU4,BE(FB)5T_O___H7/_O__BHUT_O__.(W/ -M_O__#X)Q_O__Z7SP__\/MIW/_O__P>,$_W4,`UT,Z)?9__]9QD`$`HJ-S_[_ -M_XA("(A("8N3Q`@``(E0#(VSQ`@``(M6!(E0$(M6"(E0%(M6#(E0&(N-J/[_ -M_RL(@^DLP?D"B<:-!,T`````*(/*<*-#-&#^1]_ -M&[@!````T^`)1B"+70R*6R:(G73^___I3O___X/I(+@!````T^`)1AR+10R* -M0":(A73^___I,/____]U#`^VG<_^___HZMC__UK&0`0!BI7/_O__P>,$B%`( -MB%`)C1P[BQ.)4`R+4P2)4!"+4PB)4!2+4PR)4!@K!H/H+,'X`HT4Q0`````I -MPHT4T,'B`RG"C130B='!X0\IT8T,R(/Y'W\/N`$```#3X`E&(.EP_O__@^D@ -MN`$```#3X`E&'.E>_O__@^D@N`$```#3X(N=J/[__PE#'.D/_O__BUT,_W4, -MZ$W8__^!P\0)``!9QD`$!8E8",9`%`")P8N5J/[__RL*@^DLP?D"B<>-!,T` -M````*(/*<*-#-&#^1\/CYD"``"X`0```-/@BXVH -M_O__"4$@QH7/_O__`(M%#(I`)CB%S_[__XB%=/[__P^#H^[__XJ5S_[__XM- -M##I1)P^$^0```(I'%(J=S_[__P^VT(A<.@Q`#[;3B$<4P>($B<@!T(N(1`D` -M`/?1B8W4_O__C9A$"0``BT,$]]")A=C^__^+0PCWT(F%W/[__XM##(VU]/[_ -M_XT4,B.-Y/[___?0B87@_O__B0J+G=C^__\CG>C^__^)6@2+M=S^__\CM>S^ -M__^)<@B+A>#^__\CA?#^__^)0@PQTH7)=0R%VW4(A?9U!(7`=`6Z`0```(72 -M#X49`0``#[:%S_[__\'@!`-%#(V0Q`@``(N`Q`@``#')A`#*,$C87T_O___W4,C1P#Z-W5__]: -MQD`$`8J5S_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8*P>#Z"S! -M^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1]_#[@!````T^`) -M1R#I:O[__X/I(+@!````T^`)1QSI6/[__X/I(+@!````T^"+G:C^__\)0QSI -M7_W__X/I(+@!````T^`)1ASIU?G___]U#.@WU?__B86D_O__QD`$`8NUI/[_ -M_XA>"(A>"8N%Y/[__XE&#(N%Z/[__XE&$(N%[/[__XE&%(N%\/[__XE&&(M] -M#(I?)XD\).COU/__QD`$`HA8"(A8"8N5Y/[__XE0#(N5Z/[__XE0$(N5[/[_ -M_XE0%(N5\/[__XE0&(G&B3PDZ+?4__^)A:#^__]:QD`$!HN-H/[__RL.@^DL -MP?D"C03-`````"G(C03!P>`#*`$`@2%_W41BW(( -MA?9U"HM:#(7;=`B-=@"Y`0```(7)=1G^A<_^__^*A73^__\XA<_^__]RH^FZ -MZO___HW._O__BIUT_O__BH7._O__C3P8#[:=S_[__\'C!/]U#`-=#.C`T___ -MB86<_O__6<9`!`&*E<_^__^+C9S^__^)^(A1"(A!"8N#Q`@``(E!#(VSQ`@` -M`(M&!(E!$(M&"(E!%(M&#(E!&(M5#(I2)_]U#(B5F_[__^ALT___B864_O__ -M6L9`!`2*C9O^__^+A93^__^)^HA0&8A(&(N#Q`@``(N-E/[__XE!"(M&!(E! -M#(M&"(E!$(M&#(E!%(G+BXVD_O__*PN#Z2S!^0*-!,T`````*(/*<*-#-&#^1\/CY@"``"X`0```-/@"4,@BYV4_O__BQLIG9S^ -M__^+A9S^__^#Z"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B# -M^1\/CS4"``"X`0```-/@B[64_O__"48@BX6@_O__BP`IA93^__^+A93^__^# -MZ"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1\/C\P!``"X -M`0```-/@BY6@_O__"4(@BUT,BELGB)V3_O__#[:=S_[__\'C!/]U#`-=#.@H -MTO__6<9`!`2)QXJ%D_[__XA'&(J5S_[__XA7&8N#Q`@``(E'"(VSQ`@``(M& -M!(E'#(M&"(E'$(M&#(E'%(N-I/[__RL/@^DLP?D"C03-`````"G(C03!P>`# -M*(#*<*-%-")T<'A#RG1C0S(@_D?#X_#````N`$` -M``#3X(N=H/[__PE#(`^VG<_^___!XP3_=0P#70SH5='__UK&0`0"BI7/_O__ -MB%`(B%`)BY/$"```B5`,C;/$"```BU8$B5`0BU8(B5`4BU8,B5`8BXV@_O__ -M*PB#Z2S!^0*)QHT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'W\; -MN`$```#3X`E&((M-#(I))HB-=/[__^G2_/__@^D@N`$```#3X`E&'(M=#(I; -M)HB==/[__^FT_/__@^D@N`$```#3X(NUH/[__PE&'.DU____@^D@N`$```#3 -MX`E''.G>_O__@^D@N`$```#3X(N-H/[__PE!'.DL_O__@^D@N`$```#3X(N] -ME/[__PE''.G#_?__@^D@N`$```#3X`E#'.E@_?__@^D@N`$```#3X`E&'.G, -M^___BW4,BEXGZ=?S__^-G>3^__]3Z&;/__]9BTT,,?8/MU$D,?^#_A\/A^<# -M``"Y(````"GQ.=%V`HG1@_D@#X3&`P``N`$```#3X$B)\=/@"0.X(````"GP -M.<)V$(U4%N`Q]D>)^(/#!#P#=KB+50R*4BB`^@B(E7/^__\/A'0#``"+=0R* -MG7/^__^(GM@)``#&AMD)```!BX7D_O__B8;$"0``BX7H_O__B8;("0``BX7L -M_O__B8;,"0``BX7P_O__B8;0"0``QX;4"0```````%;H8\___XF%R/[__UK& -M0`0"B[W(_O__B%\(B%\)BX7D_O__B4<,BX7H_O__B4<0BX7L_O__B4<4BX7P -M_O__B4<8BT4,BD`F/`*)_HB%=/[__P^&:`$``,:%S_[__P`XA<_^__\/@\_E -M__^+70R!P\0)``")G<3^__^*A<_^__^+50PZ0B@/A.0```!2Z-C.__]9QD`$ -M`8J-S_[__XA("(A("8N5Y/[__XE0#(N5Z/[__XE0$(N5[/[__XE0%(N5\/[_ -M_XE0&/]U#(G&Z)G.__^)QUK&0`0#BYW$_O__*S>)6`B-3M3!^0**A<_^__^( -M1PR-!,T`````*(/*<*-#-&#^1\/CY4```"X`0`` -M`-/@"4<@BY7(_O__*SJ-1]3!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/ -M*=&-#,B#^1]_.;@!````T^"+C3__X/I(+@!````T^"+M`#*$/*=&-#,B#^1]_,[@!````T^`)1R"+10R*0":(A73^___^A<_^ -M__^*C73^__\XC<_^__\/@D;____I0N/__X/I(+@!````T^`)1QR+50R*4B:( -ME73^___KR(/I(+@!````T^`)1ASI]?[__XM-#(I!)XA!*(B%<_[__^EX_/__ -MQP/_____Z3W\__^#[B#I1OS__[@!````Z57C__^#^`,/A=OB__^-G>3^__]3 -MZ$/+__^+10Q?,?8/MU`D,?^#_A\/A^P```"Y(````"GQ.=%V`HG1@_D@#X3+ -M````N`$```#3X$B)\=/@"0.X(````"GP.<)V$(U4%N`Q]D>)^(/#!#P#=KB+ -M50S_LIP(``#H=,$ -M`UT,C8/$"```4('#1`D``.BLRO__4^BFRO__65O_=0SH6,O__UK&0`0"BI7/ -M_O__B%`(QD`)`(N5Y/[__XE0#(N5Z/[__XE0$(N5[/[__XE0%(N5\/[__XE0 -M&/Z%S_[__XJ-S_[__XM=##I+)G*'Z=GA___'`______I./___X/N(.E!____ -MBUT,BELF,`$`T4,C9#$"```BX#$"```,=N%P'45 -MBT($A+>@R%_W0%NP$```"%VP^%?P,``$$ZC7;^__]RNC'` -MA']`D```````#IW.'__XV=Y/[__U/HN,G__XM%#%DQ -M]@^W4"0Q_X/^'P^'+P,``+D@````*?$YT78"B=&#^2`/A`X#``"X`0```-/@ -M2(GQT^`)`[@@````*?`YPG80C506X#'V1XGX@\,$/`-VN(M5#(I:)XB:V`D` -M`,:"V0D```"+A>3^__^)@L0)``"+A>C^__^)@L@)``"+A>S^__^)@LP)``"+ -MA?#^__^`>B8"B8+0"0``QX+4"0````````^'XP```%*)T^C!R?__@(# -M*<*-%-"(7#$,B='!X0\IT8T,R(/Y'W\GN`$```#3X`E&(/Z%S_[__XJ%S_[_ -M_XM5##I")@^"8O___^G%W___@^D@N`$```#3X`E&'.O4_W4,Z-[(__^)A<#^ -M__]>QD`$`8N-P/[__XA9"(A9"8N%Y/[__XE!#(N%Z/[__XE!$(N%[/[__XE! -M%(N%\/[__XE!&(M=#,:%S_[__P"*6R8XG<_^__^(G73^__\/@U3?__^+=0R! -MQL0)``")M;S^__^*A<_^__^+50PZ0B)6`B-3M3!^0**A<_^__^(1PR-!,T` -M````*(/*<*-#-&#^1\/CXD```"X`0```-/@"4<@ -MBX7`_O__*P>#Z"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B# -M^1]_,[@!````T^`)1R"+50R*4B:(E73^___^A<_^__^*G73^__\XG<_^__\/ -M@OC^___I.-[__X/I(+@!````T^`)1QR+30R*22:(C73^___KR(/I(+@!```` -MT^`)1QSI;____\<#_____^GU_/__@^X@Z?[\__^X`0```.F"_/__B?:%]@^$ -M<-[__X/B`H32#X1EWO__BT4,BH`<"@``B(7/_O__BTT,BI$="@``.-`/AUT! -M``"0BIW/_O__BW4,.EXG#X0X`0``#[;SB?.-O73____!XP2-'#M3Z`/&__^+ -M10P/MX2P_`D``(M5#%^)A6S^__\/M[2R_@D``#'_@[UL_O__'P^'^PD``+H@ -M````*Y5L_O__.?)V`HGR@_H@#X35"0``B-&X`0```-/@2(J-;/[__]/@"0.X -M(````"N%;/[__SG&=A^+A6S^__^-=##@QX5L_O__`````$>)^H/#!(#Z`W:7 -M#[:5S_[__\'B!(M%#`'0BYA$"0``]].)G>3^__^-B$0)``"+003WT(F%Z/[_ -M_XM!"/?0B87L_O__BT$,]]"-C73___^)A?#^__^-A"KT_O__C10*BSHAWXDX -MB[7H_O__(W($B7`$BYWL_O__(UH(B5@(BXWP_O__(TH,B4@,BU4,BH7/_O__ -M.D(H#X3%"```BUT,BI,="@``_H7/_O__.)7/_O__#X:D_O__@+W-_O__``^% -MMP```(M=#(J;'`H``#C3B)W/_O__#X`B%_W4)BU@,A=MT!XGVN0$` -M``"%R743_H7/_O__.)7/_O__=JWIX-O___]U#`^VG<_^___H`<7__UK&0`0! -MBI7/_O__P>,$B%`(B%`)C1PSBQ.)4`R+4P2)4!"+4PB)4!2+4PR)4!B+30R* -MD1T*``#KI8V%Y/[__U#H`,3__\:%S_[__P"+10R*0"8XA<_^__];B,$/@ZT' -M``"+50R*4BB(E7/^__^*G7/^__\XG<_^__]T0XJ%S_[__XM5##I")W0U#[;` -MP>`$`="-D,0(``"+@,0(```)A>3^__^+0@0)A>C^__^+0@@)A>S^__^+0@P) -MA?#^___^A<_^__\XC<_^__]RH0^VC7/^___!X02-G?3^__^-#!F+,2.UY/[_ -M_XFUU/[__XM9!".=Z/[__XF=V/[__XM1"".5[/[__XF5W/[__XM!#".%\/[_ -M_XF%X/[___?6]]/WTO?0B;7D_O__B9WH_O__B97L_O__B87P_O__(S&)M>3^ -M__\C602)G>C^__\C40B)E>S^__\C00S_=0R)A?#^___HG,/__XF%N/[__UG& -M0`0`BY7D_O__,<"%TG4>B[WH_O__A?]U%(NU[/[__X7V=0J+G?#^__^%VW0% -MN`$```"%P`^$A@4``(M%#(M5#(I`*(B%<_[__XB"V`D``(N%Y/[__XF"Q`D` -M`(N%Z/[__XF"R`D``(N%[/[__XF"S`D``(N%\/[__\:"V0D```'&A<_^__\` -MBDHF.(W/_O__B8+0"0``QX+4"0```````(B-=/[__P^#1`$``(J%<_[__SB% -MS_[__P^$#0$``(J5S_[__XM-##J1'`H```^"K@0``#J1'0H```^'H@0``#I1 -M)P^$F00```^VG<_^___!XP2-M?3^__^-'#.+A>3^__\)`XN%Z/[__PE#!(N% -M[/[__PE#"(N%\/[__PE##/]U#.ANPO__6L9`!`&*E<_^__^(4`B(4`F+$XE0 -M#(M3!(E0$(M3"(E0%(M3#(E0&(M=#/]U#(G&@-!,T`````*(/ -M*<*-#-&#^1\/C\P#``"X`0```-/@"4<@BIW/_O__BW4,.EXG#X0]`P``BU4, -MBE(FB)5T_O___H7/_O__BHUT_O__.(W/_O__#^__^*6B>)@N@)``#&@O$)```` -MQX+L"0```````%+H#L'__XF%L/[__U_&0`0!BXVP_O__B%D(BIVW_O__B%D) -MBX74_O__B4$,BX78_O__B4$0BX7<_O__B4$4BX7@_O__B4$8QH7/_O__`,>% -MT/[__P````"+10R*0"8XA<_^__^(A73^__\/@W37__^*E<_^__^+30PZ42@/ -MA(P!``"*62*A<_^__^(1PB(7PF+A=3^ -M__^)1PR+A=C^__^)1Q"+A=S^__^)1Q2+A>#^__^)1QB+C;C^__\K#X/I+,'Y -M`HT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'P^/:P$``+@!```` -MT^`)1R"+C=#^__^%R71%BQ$/*=&-#,B#^1\/CPH!``"X`0```-/@"4<@BTT,BDDG -M_W4,BUT,B(VO_O__Z*6___^!P]P)```K.%J-3]3&0`0#B5@(P?D"BIVO_O__ -MB%@,B<:)A=#^__^-!,T`````*(/*<*-#-&#^1\/ -MCXD```"X`0```-/@"48@BX6P_O__*P:#Z"S!^`*-%,4`````*<*-%-#!X@,I -MPHT4T(G1P>$/*=&-#,B#^1]_,[@!````T^`)1B"+10R*0":(A73^___^A<_^ -M__^*C73^__\XC<_^__\/@DK^___IN=7__X/I(+@!````T^`)1AR+50R*4B:( -ME73^___KR(/I(+@!````T^`)1ASI;____X/I(+@!````T^`)1QSI[O[__X/I -M(+@!````T^`)1QSIC?[__XN%N/[__RLXC4?4P?@"C13%`````"G"C130P>(# -M*<*-%-")T<'A#RG1C0S(@_D??QZX`0```-/@BY6X_O__"4(@BDXFB(UT_O__ -MZ8#\__^#Z2"X`0```-/@BYVX_O__"4,`$C808Q`@``%!&Z):Z__^) -M\3I+)EARXHM3'.N(D%/_=0CH(]'__X7`6EETGHM-"(N!K"\``(E8!(D#BT7P -MB4,$B9FL+P``Z7K___^)]E6)Y593BT4(BU@(BX/D+P``A -MR<.-LZPO```YLZPO``!TZ>O`58GE5U93@^P,BT4(BT`(B<>+D*PO``"!QZPO -M```Y^HE%\'02BTT(.4H<#X2D````BQ(Y^G7NBTWPBY&T+P``@<&T+P``.AT$HU:^(M%"#E#''01BQ([5>AU[C'`@\0,6UY?R<,Q]HI#)HGQ.,%S2HA% -M[XGVB?$/ML'!X`2-!!B-B,0(``"+@,0(```Q_X7`=1>+002%P'40BT$(A)]K\!````A?]U%4:)\#I%[W*[,)]E6)Y5=64U.+70B+2R2+10R%R8E%\(M]$(MS -M"'4+4^BA_O__A7\G#C78`BT7PB4,DB7LH_X;H+P`` -MB74(C67T6UY?R>G\____B?95B>564XM=#(I#$83`BW4(=0;&0Q$!L`$\`706 -M/`9T$CP#=`Z*0Q"#X""$P'4$QD,1"_]S+%;H0;C__U/_R<.)=0B-9?A;7LGI_/___XV&["\``%!H```` -M`%;H_/___X/$#.O4D(/`&.OIC78`58GE5U93@>R\````BT4,BU`@BPJ)C4#_ -M__\/MD$\2(F%5/___V:+0@AFB85B____BTI,B8U<____#[9"2HF%4/___P^V -M2DN)C4S___]FBT)2BTH49HF%8/___X7)BW409HM:4`^$;@(``&8/MD(0@^`! -M#[?`.T44#X1:`@``B8U$____BU4,BP(/MD`#,?^)A4C___\QR9`/M\,#A5S_ -M__^)A5C___^+A4C___\YA5#___\/A`8!```/MYU@____P>,)D(N%1/___P^W -M4`2%TG4%N@```0")T"GX.=AW#2G#@X5$____"#'_Z]@!WXN58/___V8IE6+_ -M__\/A*D```#_A5#___^+A4S___\QVSF%4/___P^$A````(N50/___P^V0CPY -MA5#___]T+8N%0/___V:+4$1FBX5B____9CG09HF%8/___P^&2O___V:)E6#_ -M___I/O___XN%3/___X7`="W_C4S___\QP(.]3/___P`/E,")A5#___^+A4#_ -M__]FBU!$#[?"`85<____ZZ:+A53___^)A4S____KR_^%4/___^EQ____9L=& -M_@"`N0$```"-9?1;7HG(7\G#A58/___XG3B94\____P>,)C78`BXU$____#[=1!(72=06Z```!`(G0*?@Y -MV(F%./___W,OBX5$____BPB)T`'Y9BGXB0YFB48$9L=&!@``*YTX____@\8( -M@X5$____"#'_Z["+C43___^+`0'X`=^)!F:)7@1FQT8&``"#Q@@YUW0CBU4, -MBXU8____#[=""`.-//___P-"!#G!#X5%_O__Z?S^__^#P0@Q_XF-1/___^O0 -M9HE>!(/&".E`_____S4$````Z/S___]:Z0K___^+0A@QR87`#X30_O___W44 -MC8UD____45*)C43_____=0C_T(/$$#')A<`/A*W^___I=_W__XUV`%6)Y593 -MBU4,BD(1/`&+=0B+6B!T`XA#$5)6Z/S___^*0TE`B$-)6CI#2%ET!XUE^%M> -MR<.*0Q&$P'4&QD,1`;`!/`%T##P&=`@\`W0$QD,1"U-6_U,<6U[KTXGV58GE -M5U93@^Q(BT4,BE`0BSB(T(/@!(3`#X1#`@``BU4,BEI$A-O'1<``````#X1F -M`0``BT4,BTW`BTR(,(E-O(J!'`H``(A%NXJ!'0H``#A%NP^',@$``(I5NXM- -MO#I1)P^$$0$```^VP@^WE('\"0``#[>T@?X)``#!X`2)5:PQ_XV<",0(``"# -M?:P?#X?%`0``NB`````K5:PY\G8"B?*#^B`/A*,!``"(T;@!````T^!(BDVL -MT^`)`[@@````*T6L.<9V&8M%K(UT,.#'1:P`````1XGZ@\,$@/H#=JD/MD6[ -MB<*+3;S!X@2-E`I$"0``B56T#[>4@?P)``")5:P/M[2!_@D``#'_D(-]K!\/ -MARX!``")^8M5M`^VP8T<@KH@````*U6L.?)V`HGR@_H@#X0``0``B-&X`0`` -M`-/@2(I-K-/@"0.X(````"M%K#G&#X;1````BT6LC70PX,=%K`````!'B?J` -M^@-VG8M-O(J!'0H``/Y%NSA%NP^&U/[__XM-#(I91/]%P`^VPSE%P`^,FO[_ -M_XM%"(N0H"\``(72=%2$V\=%P`````!T-HV0K"\``(M%#(M-P(M,B#"+0@2) -M$8E*!(D(B4$$_T7`QX'T"0```````(M-#`^V040Y1(04L/MH(< -M"@``9HN$@OP)``!FB4%0#[:"'`H``&:+A(+^"0``9HE!4L9!2`#&04D`BT,$ -MBU6\B5,$B1K_1<")0@2)$(M-#`^V040Y1575E.#["B+10R+ -M`(E%\&:+6$0QR6:!^X``9HE=[G8&9L=%[H``BU4,BD(0@^`@A,`/A>T"``"+ -M11"*0!(/MM"+=1"(1=>+!HG6,=+W]HA5ZXM%\`^V4#R+=1"+1@2)UC'2]_:* -M1=Y((?AFBUWN -M9BG#9CM=['8#BUWLBW78]]Z+1>0A_H7`#X2$````QT7D`````&:+5>Z+1?!F -M.U!$MT/'0QBW7P9HM>1&8Y7>YS!\=%Y`$```"+11!F -MBT`09CG89HE%[`^&H?[__V:)7>SIF/[__X!]Z@!T)?Y-ZH!]Z@`/E$7KBUWP -M#[=#1(MU$`%&",=%Y`$```!FBUM$Z[B+11"*0!*(1>KKT_Y%Z^N),<"-9?1; -M7E_)PXM-#(I!1$B(043^P`^$GP```(M="('#K"\``(M]"(E=X(''I"\``(MU -M#`^V1D2+3(8PBD$F,=LXP\>!]`D```````"(1=]S08GV#[;#P>`$C00(C9#$ -M"```BX#$"```,?:%P'45BT($A+0@R%P'0%O@$```"%]G5" -M0SI=WW+!,<"%P'0LBU7@BT($B1&)2@2)"(E!!(M-#(I!1$B(043^P`^%=O__ -M_[C_____Z3W___^+1P2).8E/!.O5N`$```#KOP^W1>Y0BTT0_W$(_W7P_W4( -MZ."N__^)P8/$$(7)N/____\/A`3___^+70S&0T0!B4LPB9GT"0``Z>W^__^0 -M58GEBTT0AG\____D(E%#(E5 -M",GI+/?__U6)Y5=64X/L,(M%#(LXBD"+50P/ -MMUH(9HE=Y(I7/$J(5>8/MD\^#[;2B57(T^@QTHE%U/=UR(E%V`^V3S[3X(E% -MW`^W=T0/KT7(BTW(`UW,#Z_.*<.-1!G_,=+W\8G!#Z_.BT7C78`58GE4XM=#(M# -M+(7`=06+7?S)PU/H_/___S'26(M#+(L$D(7`=!")]L=`$`````"+0!2%P'7R -M0H'Z_P,``';=:@?_+?0A6C8>D -M+P``4XF'I"\``(F'J"\``(V'K"\``(F'K"\``(F'L"\``(V'M"\``(F'M"\` -M`(F'N"\``*$`````P>`,NJNJJJKWXHG3P>L/QX>@+P```````%-H(`H``%># -MPR#H3*;__U-J$%>)QNA!IO__`<:A`````,'@#,'H#E!J1%?H*Z;__X/$)&H( -M:``0``!7`<;H&:;__P'&5T;H_/___X/$$#LU`````*,$````<@B-9?1;7E_) -MPU?H_/___XG"A=)8=.M&BX?<+P``_X?@+P``.S4`````B0*)E]PO``!RUNO, -M58GE5U9348M%"(E%\(MU#(!F`?N+7@0/MDX#N`$```#3X(I31HG!B-"#X`*$ -MP,=#3`````")UP^$YP```&:+0TAFA7\G#4_]U\/_06%H/MGM&Z^*)]HC0@\@%_DL]A,!F -MB4M(QT-,`````(A#1GD&@^!_Z\:0@^"?B$-&4_]U\.C\____B<%?A* -M5@.(40.`20$(Q@$#H0P```")030/MM*A(````(E9!(E,DU")03C'1@0````` -MBD-&@^#^@\@*B$-&_D,]46H'Z/S___]86HM#!(7`=`R-=@")PXM`!(7`=??H -M_/___XE#0(E="(UE]%M>7\GI_/___V:+0TAFA<`/A$O____I$/___XGV58GE -MBU4,2E,QVX/Z_XM-"'0.B?8/M@%*`<-!@_K_=?0/ML-;R<.)]E6)Y593BUT( -M@#L#=D>*4SPQ]H32=!*)]HM,LU"%R7441@^VPCG&?/"`8T;[C67X6U[)PY"* -M4P&*00&#X@&#X/X)T(A!`?]TLU#H_/___UB*4SSKS(E="(UE^%M>R>L!D%6) -MY5=64X'L!`(``(M%",>%\/W__P````"`>#P`C;7T_?__#X0L`@``BW@$A?]T -M#XM'!(7`=`B)O?#]__^)QV@``@``:@!6Z/S___^#Q`PQP(7_QP;S%GA:=`.+ -M1T")1@2+50B`>D0`=`J`3@D"BD)'B$8*BT4(BE!`B-.*AI,```"#XP&#X/R( -MT8/A`@G8"&F`````````#H_/__ -M_VH$C8>`````4(U&/%#H_/___VH0C8?$````4(V&@````%#H_/___X/$)&I` -MC8>$````4(U&0%#H_/___X/$#(N%\/W__X7`=&*+E?#]__^+0@R)1AS'AIP` -M````````B@*(1B"*0CR(1B&+50B*0@.(1B*+E?#]__^*0CZ(1B.*0D:#X`*$ -MP'0$@$XD`8N5\/W__V:+0DAFB48FBT),B48HQX:@`````````(7_=$-HD``` -M`%;H_/___V@``@``5O?8B$8(Z/S____WV%:(AI````!J,(M5"(M"3(/H"E") -MT(/`/%#H_/___XUE]%M>7\G#BU4(B@*(1A#KLXM5".F[_O__,=+I>O[__XGV -M58GEBT4(4X`X`W8;,4(7`=1!##[;".<-\\(UE -M^%M>R<.04.C\____6(I6/.OD@&8!_NOFB?95B>6+30B+40@QP#D,@G0(0(/X -M!W;UR6+10R`8`'[B44(R>G\____D%6)Y5=64X'L -M!`0``(M]"(I7`8C0@^`$A,"-G?3]__^)_G0%@#\"=PB-9?1;7E_)PX/B_8A7 -M`6@``@``:@!3Z/S___^*!X/$##P#=!`\"(MV4`^$@0```(`^`W7P4VH@:@"- -M1CQ0Z/S___^#Q!!F@;O^`0``5:IUL(N+R@$``(7)=!6!>P9,24Q/=$&!NW8! -M``!'4E5"=#6)V,>%\/O__P,```"`N+X!``"`=!"#P!#_C?#[__]Y[.EL____ -MBY#*`0``A=)TYH!/`0+KX(!/`0+I4____XUV`(7V=`MF@W](`0^%% -M\/O__P$````/MD<\.87P^___C;7T^___#XUF____5FH@:@"+E?#[__^+1)=0 -M@\`\4.C\____,=*#Q!"+!)8Q!)-"@_I_?O3_A?#[__\/MD<\.87P^___?,7I -M)O___Y!5B>564XM="(N+2!$``(U!`;HA`@``B=:9]_Z+10R)1,L\BT40B43+ -M0(F32!$``%M>R<.058GE5U93BW4(BX9$$0``.X9($0``="N_(0(``(M6+30B+`87`BU4,=!&+0"2)0B2+`8E0)(D1R<.)]HE2).OUC78` -M58GE5U93BW4,BQ:%THG7="6-=@"+6B0YVG0EBT,DB4(D4_]U"/]3*%@Y^UIT -M"(L&A<")PG7>C67T6UY?R<.)]L<&`````.O958GEBT4(@#@(=`7)PXUV`,GI -M_/___XGV58GE4XM%"(`X"(M=#(M-$(M0"'0+45+_TXM=_,G#B?:+7?S)Z?S_ -M__^-=@!5B>575E-1BE40B%7SBT4(BW@HB@`/MMA35XA%\NC\____:@!35^C\ -M____:@!J`&H`:@!J`U-7Z/S___^#Q#`QTH7`#X2'````,=OW10P```#P#Y7# -MA=L/A(\````QP(!]\R`/E/___XUV`%6)Y8I%"(G"@^(#@^`$P>(- -MA,!T"XV"`"`#`,G#C78`C8(`(`(`Z_-5B>564U"*10QH(*$'`(A%]XMU"+L@ -MH0<`Z/S___]8D`^V1?=0Z*[___\%'`$``(D$)/]V#.C\____A,!:6;H!```` -M>1MH$"<``('#$"<``.C\____@?L_2TP`6';",=*-9?A;B=!>R<.-=@!5B>56 -M4VH`#[9%#%#H6____XG&C4`(B00DBUT(_W,,Z/S___]H&`$``(U&#%#_R<.058GE#[9%#&H`4.@=____@\`,B00DBT4(_W`,Z/S_ -M___)PXGV58GE9H-]%`"+10QU$_=%$````/!U"JD`_P``=`N-=@"X`0```,G# -MD&:%P'4+@WT(`;@!````=.TQP.OI58GE5U934(M=%(M#$(M-"(D!BT,4B4$$ -MBP,QTH7`BWT0B47P=06Z`0````^V1P31X`G"BT4,B[`X`@``A?9FB5$(#X0@ -M`0``@_X"#X07`0``@WL$`71Y9@^V0PX-`!(``&:)00IF#[9#"`T`$P``BU,( -M9HE!#(G09L'H"`T`%```9HE!#HG0)0``_P"!X@````_!Z!#!ZA@-`!4``('* -M0!8``&:)01!FB5$2C5$4BTWPA#"-AP0!``"+<@Q05HM=%.C\____B`.-AP@! -M``!05HE%\.C\____9@^VP&:)0P*-APP!``!05HE%[.C\____9@^VP&:)0P2- -MAQ`!``!05HE%Z.C\____9@^VP(/$(&:)0P:-AQ0!``!05HE%Y.C\____9@^V -MP&:)0PA8@WT0`5IT*8V'&`$``%!6Z/S___^(0PJ-AQP!``!05NC\____B$,+ -MC67T6UY?R<.0C8<@`0``4%:)1=SH_/___XA%XX/(@`^VP%#_==Q6Z/S_____ -M=?!6Z/S____!X`AF"4,"_W7L5NC\____P>`(@\0D9@E#!/]UZ%;H_/___\'@ -M"&8)0P;_=>16Z/S____!X`AF"4,(#[9%XU#_==Q6Z/S___^#Q!SI6____U6) -MY5=64X/L&(M5"`^V=0R+?+(DBT409HE%XHM',(/`,%#_<@SH_/___X/@'XT4 -MQ0`````IPHT$UXV01`(``%F#N$0"```!B57<6W0_C9A8`@``C47D4/]S!%;_ -M=0CH8?[__XU5Y/Z/40D``%)J``^W1>)0_W,<:@%6_W575E.#["B+51`/MD4,BTT(BW2!)(E%T&:+`F:)1=QF -MBT("9HE%WHM"!(E%X&:+1=R#X!^-%,4`````*<*-'-:-@T0"``")1=AFBT7> -MA,#'1=0`````9L=%S@``="YFBT7>)?\```!FB47.QT74`0```&:!3& -M3`D```````#'AC0"````````9HM%WH/@!&:%P(V[6`(```^%D````(.[1`(` -M``%T2_Z.40D``(U%Y%"+1>!0#[=%SE#_=QS_==3_==#_=BC_5QC_==A6Z`@/ -M``"+ODP)``"#Q"2%_W03BX9$"0``A7\G#_W70 -M_W4(Z*40``#_MD0)``!6Z)D1``"#Q!"%P'7::@#_MD0)``!6Z*0%``"#Q`SK -MQXUV`(U%Y%#_=P3_==#_=0CHZOS__X/$$.E6____B?95B>575E-0BUT(BW4, -MBWT0:"P-``#_G\____C78` -M58GE5U93@^PDBT4(BT@,B47PBU4<#[9%#,'@`HE5[(I5$`G"B4WDBT7P#[;* -MBW2()(M%&(7`BWT4QT7@`````(A5ZXE-W'1LA?8/A,X```"-!/T`````"T8D -MBY[<"0``4(M&,(/`)%#_=>3H_/___X/$##G[=":+5=R)5=B-=@"+1A2-!-A0 -M_W780_]U\(/C'^B&_?__@\0,.?MUXXN&3`D``(7`=0?'1>`!````B9[<"0`` -MBT7LAF@!#X3/````BT7P@WA@ -M`0^$K@```(-X9`$/A*0```"#>&@!#X2:````BU7P@WI<`70R#[9=ZU/H]_;_ -M_P4<`0``B00D_W7DZ/S___]97E-J`&H!_W7PBTWP_U$@C67T6UY?R<-J!`^V -M7>M3Z,/V__^-<"B)-"3_=>3H_/___U;_=>3H_/___VH9Z/S___]J`%;_=>3H -M_/___X/$)%;_=>3H_/___VC0!P``Z/S___]3_W7PZ'<&``"#Q!3IM0_W7PZ'<'``!?6.E;____BDWKN``!``#3X%!0_W7PZ%3]__^#Q`SI -M%?___XG8@^`09H7`=5N!XP`!``!FA=L/A%#___^#OC0"```!=!R#/0`````! -M#X4Z____B74(C67T6UY?R>DF#@``QX9,"0```````,>&-`(```````#_==#_ -M==3_=?#H"/O__X/$#.N]_W74_W7PZ,P%``!8BT7P@WAD`5IT'8-X:`%T%P^V -M1>M0:@%J`?]U\(M5\/]2(.G1_O__:@"*3=2X``$``-/@4/]U\.B?_/__@\0, -MZ\^)]E6)Y5,/MD4,P>`""T40BUT(#[;`BTR#)(7)=#"+D40)``"%TG0+@SH! -M=`:#>A`!=`^)10R)70B+'"3)Z>P+``")50R)30B+'"3)ZPB)10SKYHUV`%6) -MY5=64U&+50B*&HM"*(MX#(C8BW(P@^`#B$7SC88@`0``4%>!QAP!``#H_/__ -M_U97@^,$Z/S____`ZP*)Q@^V3?.#XP&X``$``-/@2_?0@>,``/__4('#%``# -M`%-7Z/S___^)\H/$'(32>".)\(/@`83`#X62````BU4,BT(4@_@!=%N#^`%R -M3X/X`G0)D(UE]%M>7\G#@^9@B?`\0'7OBU4,BUH@A=MU$FH`4HGV_W4(Z`P! -M``"#Q`SKTXM%#(/`%%#_=0CH5````(7`6EEUOFH!_W4,Z]=J`.OWC78`@^9` -MB?"$P'0CBT4,@\`44/]U".@H````2%]:==6+50R+O(C78` -M58GE5U93@^P4BUT,C7WD5X/#%/]S!(MU",=%X``````/M@90_W8HZ#3W__^# -MQ!"#?1`!#X3W````5VH`:@#_`/M@90_W8H_U,<_W4,5NBY"```@\0D -M@WT0`0^$L````(N&1`D``(7`="^#>!`!='Z+CC@"``"%R71*#[8&4/]V*.BZ -M"0``BYY$"0``6(7;6G0'BWL0A?]T"XUE]%M>7\G#C78`C4,44%-6Z'T*``"+ -M6PB#Q`R%VW3@BTL0AC\____@\04ZXQ05NCG"@``A:@#_MD0)``!6Z//^__^# -MQ`SKBXGV@ST``````0^%0____U;H<0H``%CI-____XUV`,=%X`$```#'ADP) -M````````Z?/^__^)]E6)Y5=64U.+70B+0RB+>`R+0S")QH/&*%97B47PZ/S_ -M__^#X`1:60^$2`$``&H"5E?H_/___U97Z/S___]HT`<``.C\____#[8#4/]S -M*.C5`0``@\0@QH,\`@```,:#4`D```#&@U$)````QX/8"0```````,>#W`D` -M``````#'@S0"````````QX/4"0``(````#'`C78`B82#5`D``$"#^!]^\XV3 -M1`(``+@?````QP(!````@\(X2'GTBT7PQX-$"0```````,>#2`D```````#' -M@TP)````````@\`(:@!05^C\____BT7P:!@!``"#P`Q05^C\____@\08BT7P -M_W,8@\`04%?H_/___XM#'"4`_/__4(M%\(/`%%!7Z/S___^+1?!J`(/`&%!7 -MZ/S___^#Q"2+1?#_N`$```!?R<-J`E97Z/S___^#Q`SIT/[__XGV -M58GE5U93@^P8BT449HE%XHM%#(7`=6J+70B^'P```)"+NT0"``"%_W51@[M4 -M`@```719BX-<`@``B[MT`@``BY-P`@``B5710:@`/MT7B4%?_=1"+50@/M@)0_W(H_U7<@\0L@\,X3GF?C67T6UY? -MR<.-=@"+@UP"``"+NW@"``"+DW0"``#KI56)Y5=64U`/MG4,B?"#X`2+70B_ -M`P```,#H`B'W@WM<`8A%\P^$D@```(-[8`$/A(@```")^@^VPL'@"(!]\P!T -M<@5T`0,`4/]S#.C\____B<&)\`^VT`^V1!-ZP>`%)>````"!X1____\)P0^V -MA!."````P>`+@>'_Y___)0`8```)R(GZ4`^VPL'@"(!]\P!T&05T`0,`4/]S -M#.C\____@\04C67T6UY?R<,%=`$"`.OED`5T`0(`ZXR0B?H/ML+!X`B`??,` -M=$8%#`$#`%#_575E,/MG4, -MBUT(5NC9[O__B30D4XUX*.BA[___:@17_W,,Z/S___]7_W,,Z/S___]J&>C\ -M____@\0@:@!7_W,,Z/S___]7_W,,Z/S___]64^B0_O__B74,B5T(@\0D3[___C78`58GE5U934,9%\@"0QD7S`(I5\XI%\HTT@H'F_P```%;H -M5^[__XU8*(G'QP0D`@```(M%"%/_<`SH_/___U.+50C_<@SH_/___U;_=0CH -M/O___VH`BT4(4_]P#.C\____@\0H:!\!``!7BU4(_W(,Z/S___]J`(U'!%"+ -M10C_<`SH_/___VH`C4<(4(M5"/]R#.C\____@\0D:@"-1PQ0BT4(_W`,Z/S_ -M__]J`(U'$%"+50C_<@SH_/___VH`C4<44(M%"/]P#.C\____@\0D:@"-1QA0 -MBU4(_W(,Z/S___]J`(U''%"+10C_<`SH_/___VH`C4 -M7\G#B?95B>5H___/#VAL!`$`BT4(_W`,Z/S____)PXGV58GE4XM="(M#!##` -M/0``@%!T(6@L#0``_W,,Z/S___^#R`%0:"P-``#_6+30R+50C' -M00@`````BX)("0``B4$,BX)("0``A-=@"+00R)0@SKQ%6)Y5=64XM=$(L#A<"+?0B+=0QU,VH@C4,$ -M4(U&%%#H_/___XL#@\0,B4805E?H*?___\<&`````/Z'/`(``(UE]%M>7\G# -MD&HDC4,$4(U&%%#H_/____Z'4`D``.O%D%6)Y593BW4,BT80A<"+70AT!OZ+ -M4`D``%93Z!W___^+@]0)```/ME8$B92#5`D``,<&`0```$")@]0)``#^BSP" -M``"-9?A;7LG#B?95B>6*10@\`W82#[;(C4P)`K@!````T^#)PXGV#[;(C4P) -M`>OLC78`58GE5U93#[9]#(GX#[;PBUT(5NC`____"4-4B30DZ,WI__\%'`$` -M`(D$)/]S#.C\____B?F#X0.X``$``-/@@^<$]]!0B?B$P`^5P`^VP$@E``#_ -M_P44``,`4/]S#.C\_____W-4:&0=``#_#-`(```$```!0,<"$T@^5P$@E``#__P44 -M``,`4%?H_/___VH`BT,P@\`(4%?H_/____]U\/]U".AD____@\0@C88<`0`` -M4%?H_/___X/&*,>#0`(```$```!J`597Z/S___^-9?1;7E_)PXGV58GE5U93 -M48MU"`^V10R)1?"+1(8DBU@PBWX,QX`T`@```````(/#*&H"4U?H_/___U-7 -MZ/S___^+5?")50R)=0B#Q!2-9?1;7E_)Z53^__]5B>564XM="(M#*(MP#/]U -M$/]U#%.+@]@)``#!X`4#0Q!0Z%'I__^+D]@)``!"BT,<@^(?B9/8"0``)0#\ -M___!X@4)T/Z#40D``(E%$(M#,(/`%(E%#(EU"(/$$(UE^%M>R>G\____D%6) -MY5-J`&H":@"+70A3Z"7W__]3Z)?U__]3Z/S___^#Q!A(=`>+7?S)PXGV#[8# -MQX-,"0```0```%#_B=!?R<.# -M?@0!#X1&`0``]T80`/\`_W41]T84`/\`_W4(9O=&&`#_=`0QTNO.C8<$`0`` -MB47HC8<(`0``B47DC8<,`0``B47@C8<0`0``B47A3Z/S___\/MD824/]UY%/H_/___P^V1A10_W7@4^C\____@\0D#[9&%E#_ -M==Q3Z/S___\/MD884/]UV%/H_/___P^V1AI0C8<8`0``4%/H_/___X/$)`^V -M1AM0_W7L4^C\____@\0,@SX"=`JZ`0```.DC____C8<@`0``4%/H_/___VID -M:@I74^C\____@\08,=*%P`^$_O[___]U[%/H_/___X/@B5HQTCP(60^%YO[_ -M_\=%\`````"!QP`!``"-=@"+1@@/MQ!2@\`"B48(5U/H_/____]%\(/$#(%] -M\/\```!VW8%N#``!``#I>O___Y`/MD814(V'!`$``%!3B47HZ/S___\/MD83 -M4(V'"`$``%!3B47DZ/S___\/MD854(V'#`$``%!3B47@Z/S___^#Q"0/MD87 -M4(V'$`$``%!3B47((A,`/A!,"``"-@G0!`P!0_W,,Z/S___^)PH'BX````"4`&```P>@+ -MP>H%B%0[>HB$.X(```!&65B)\$<\!W:T4^@6]O__4^CX]___4^@.^/__:@!H -M\`0!`/]S#.C\____:"P-``#_#YS!86@^$<@$``(M#1*G@`P"`=`@E'_S_ -M?XE#1(-[7`$/A#T!``"#>V`!#X0S`0``@WMD`0^$*0$``(-[:`$/A!\!```Q -M]C'_D%=31NCL\___68GQ1X#Y!UAV[O]S1&@`#```_W,,Z/S_____=!"#>V@!=`JZ`0```.D+_O__,?\Q]L=% -M\`````")]O]U\%/H_/___X7`6EEU#+@``0``BDWPT^`)QT:)\/]%\#P'=MM7 -M:`#_``!3Z._I__^#Q`SKLXM#1*D0````#X33_O__@^#OB4-$Z7'!0`````!```` -MR<.058GEQP4``````````,G#D%6)Y593BW4(#[9%#(M#3`D```````#'@S0"````````B5T(C67X6U[)Z>7O__^0C67X -M6S'`7LG#C78`58GEBT4(#[95#(M4D"0QP(72=`PQP(.Z3`D```$/E<#)PXGV -M58GEBD4,B<*#X@.#X`16P>((A,!3BW4(C9H``0,`=0:-F@`!`@!3_W8,Z/S_ -M__^#X`]9@_@!6G0;@_@!<@6#^`-T"3'`C67X6U[)P[@!````Z_*04_]V#.C\ -M____:$`-`P#H_/___U/_=@SH_/___X/@#X/$%.O&58GE5U93@^P4BD4,B$7S -M@^`#B$7GBD7S@^`$P.@"BW4(#[9]\XA%YHM4OB2+1@R)1>PQP(72#X1$`0`` -MBT(P@[I,"0```8E%Z`^$+P$``%=6Z.;A__^+7>AJ!(/#*%/_=>SH_/___U/_ -M=>SH_/___VH9Z/S___^#Q"!J`%/_=>SH_/___U/_=>SH_/___U=6Z,_P__\/ -MMD7GP>`(,?^#Q!R)1>"`?>8`#X0N`0``BT7@!0@!`P!0_W8,Z/S___^)PX/C -M\`^V1>>#RP'!X`B`?>8`4P^$]P````4(`0,`4/]V#.C\____#[9%Y\'@"(/$ -M%(!]Y@`/A,D````%"`$#`%#_=@SH_/___VH9Z/S___\/MD7G@^/PP>`(@'WF -M`%,/A),````%"`$#`%#_=@SH_/___P^V1>?!X`B#Q!B`?>8`=&T%"`$#`%#_ -M=@SH_/___VC0!P``Z/S___\/MEWS4U;H_/___X/$%(7`=1M'@_\##X4M____ -M4U;H?N#__S'`C67T6UY?R<.+1>@%'`$``%#_=>SH_/___X/@P%D\0%]UU5-6 -MZ%/@__^X`0```.O0!0@!`@#KD9`%"`$"`.EH____B?8%"`$"`.DR____B?8% -M"`$"`.D$____B?:+1>`%"`$"`.G-_O__C78`58GE5U934XM5"`^V10R+7((D -M,S!T>E?_=?#H_/___XG"6(M%$(7` -M6752C4;_,+__O__4E?_=?#H_/___[D!````C67T6UZ)R%_)PX'*``$``.O?D,>#.`(` -M``$```"!XL#]___KP(GV,"3`D```$```!14^AQ]?__N`$```"+7?S)PXUV`#'`Z_15B>4/MDT, -M4XM="(M4BR0QP(72=0>+7?S)PXGVQX),"0```````%%3Z,_U__^X`0```.OA -M58GEBT4(4P^V50R+7)`D,<"%VW0A@[M,"0```70>:@!J`O]U$%/HC>W__U/H -M_^O__[@!````BUW\R<.0,<#K]E6)Y8M%"`^V50R+5)`DA=*X_P```'0'#[:" -M/`(``,G#58GE5E.+50@/MD4,BW(,BU2")#')A=)T'(M:,(/#+%-6Z/S___]: -M@WT0`5ET)C')@^`"=0N-9?A;BR<.)]FH`4U;H_/___X/$#+D!````Z^*0 -M,7\G#C78`#[;2P>((A,!T:H'"=`$#`(E5 -M\/]U\(M%"/]P#.C\____B?+!X@6!XN`````E'____PG0B?K!X@LE_^?__X'B -M`!@```G"4O]U\(M5"/]R#.C\____#[;#B?F+50B(C`*"````B?&(3`)Z@\04 -MN`$```#K@I"!PG0!`@#KE%6)Y5=64[\#````BET,(=^#XP3`ZP(/E<`/ML!( -M)0``__\%&``#`%"+=0C_=@SH_/___XGY#[;1C4H8N@$```#3X@G"B=B#X`%( -M)0``__^#XP%2!1@``P!+4('C``#___]V#('#&``#`.C\____4_]V#.C\____ -M@\0575E-6BD4,B$7SBE7S@^`#B$7R@^($#[9% -M\U"+?0C`Z@)7B=;H+.S__XGP@^`!2"4``/__!1@``P!0_W<,Z/S___\/MEWR -MC4L8NO[____3PB'"B?"#X`%()0``__]2!1@``P!0_W<,Z/S___^)\(/@`4@E -M``#__P48``,`4/]W#.C\____B=B)\L'@"(/$)(32=%8%"`$#`%#_=PSH_/__ -M_X/@\(/(`5")\@^V1?+!X`B$TG0L!0@!`P!0_W<,Z/S___\/MD7S4%?HA^O_ -M_X/$'(UE]%M>N`$```!?R<.-=@`%"`$"`.O2D`4(`0(`ZZB058GE5U93@^P( -M#[9]#(M%"(M`#(GZB47P#[;"BU4(BUR")(GZB?B#X@.#X`3!X@B$P(MU$`^$ -M$`$``(V"=`$#`%"+10C_<`SH_/___XE&6%F%VU@/A.D```"+4S")5>R)^@^V -MPE#_=0CH_/___XD&7X7`6@^$O````(N#3`D``(E&+(N#.`(``(E&,(J#/`(` -M`(A&-#'2B?:*1!IJB$0R!$*#^B=V\O]U[/]U\.C\____B48XBT7L@\`04/]U -M\.C\____B48\BT7L@\`44/]U\.C\____B49`BT7L@\`84/]U\.C\____B49$ -MBT7L@\0@@\`<4/]U\.C\____B49(BT7L@\`@4/]U\.C\____B49,BT7L@\`D -M4/]U\.C\____B490BT7L@\`H4/]U\.C\____B494C67T6UZX`0```%_)P\<& -M`````.OKC8)T`0(`Z>O^__^-=@!5B>6#[#"+11")1=2+112)1=R+11AFB47@ -MBT4<9HE%XHM%((E%Y(M%)(E%Z(M%*(U5T(E%[(M%+%*)1?`/MD4,4/]U",=% -MT`````#H_/___\G#B?95B>575E.#[`B*10P/MOB(1?.+10B+=+@DA?:X!``` -M``^$L````(N.3`D``(7)#X1$`0``@+X\`@``'P^$3P$``(N&U`D``$B+G(94 -M"0``B8;4"0``C03=`````"G8C83&1`(``(E%[(A8!(M%$(L0A=(/A<````") -MQX/'!(.^.`(```(/A*(````/MT<,#[=7#E#_=PA2_W8(Z!7:__^)1P2#Q!!( -M=&*`OE`)````=4B+AC0"``"%P'0C_W40_W7L5N@Q[O__5_]U[%;HI_#__X/$ -M&#'`C67T6UY?R<,/MEWS4_]U".AQ[___4_]U".B8[___@\00Z\+_=1#_=>Q6 -MZ//M__^#Q`SKRHM&"(7`=9>+AM0)``")G(94"0``0(F&U`D``+@#````ZZK' -M1P0!````Z7#_____=1#_=>Q6Z+3M__^#Q`R`OCP"```!=82#OC0"```!="G_ -M=>Q6Z,;P__^%P%I9#X5H_____W7L5NCC[?__C78`N`$```#I5/___U?_=0CH -MG>___UM?Z\J0N`(```#I//___XGV58GE5U93@^P4BT4(BT`,:&`=``!0B47D -MZ/S___^+50B)QHM25%DQP(76B57P6W0U]\8```0`#X4=`0``QD7K`,=%X``` -M``#WQO\!``!U(<'N"/Y%Z]'N_T7@@'WK`7;GN`$```"-9?1;7E_)PXUV`#'; -M@'WK``^5PTN!XP``__]J[X'#%``#`%/_=>3H_/___U/_=>3H_/___XE%[/?0 -M@\@04%/_=>3H_/___X/$(#'`@'WK``^5P$@E``#__P4(``,`4/]UY.C\____ -MB<=8QD7J`%H/MDWJNP`!``"X`0```-/CT^")\B-=[(/B`2-%['4$A=)T&O]U -M[%)0B?B#X!]04?]UX/]U".BRWO__@\0S_ -M_X5%\%MU%_Y%ZL'N`L'O"(!]Z@-VF.D1____C78`#[9%ZE#_=>#_=0CH0.'_ -M_X/$#.O4:%@=``#_=>3H_/___XG#]]!0:%@=``#_=>3H_/___VH`4VH`_W4( -MBU4(_U(@@\0DZ:[^__^)]E6)Y6H`BT4(:&0=``#_<`SH_/___[@!````R<-5 -MB>6+10C_<%1H9!T``/]P#.C\____N`$```#)PXUV`%6)Y5=64XM]$#';.?MS -M)HM%#(VP'`$``%;_=0CH_/___X3`6EEY&/]U%$/H_/___SG[6'+C,<"-9?1; -M7E_)PX/@`8/P`0^VP.OMB?95B>53:@"+70B+0S`%(`$``%"+0RC_<`SH_/__ -M_XM#,`4@`0``4(M#*/]P#.C\____BUW\R<.)]E6)Y5-J`HM="(M#,`4@`0`` -M4(M#*/]P#.C\____BT,P!1P!``!0BT,H_W`,Z/S___^+7?S)PXGV58GE5U93 -M4XM5"(M"*(MP##';BT(P@[HT`@```8E%\'1#BWWP@<<@`0``5U;H_/___ZF! -M````6EEU8(GV5U;H_/___ZF!````6EET(HG80V8]MPMW#VCH`P``Z/S___]8 -MZ]J)]C'`C67T6UY?R<-J9&H*_W7P5NC\____BT7P!1P!``!05NC\____@^#! -M@\08/$`/E,`/ML#KS&HRZ[R)]E6)Y5=6BT4(4P^V50R+7)`D,<"%VW1'BT,H -M@[M,"0```8MX#(MS,'0S4^C\____:.$```"-AAP!``!05^C\____:F1H$"<` -M`%97Z/S___^#Q""%P'424^C\____,<"-9?1;7E_)PXGV4^C\____N`$```#K -MZ8UV`%6)Y593BTT(#[95#(M$D20Q]H7`=$=H[````&H`:@!J`&H`:@!J`&@` -M`0``C5@T4VH`:@%24>C\____,?:#Q#2%P'09]H.@````X'0+,G\____,<#)PU6)Y6CO```` -M:@`/MD4@4`^V11Q0#[9%&%`/MD444`^V11!0:@!J`&H`:@`/MD4,4/]U".C\ -M____R<.)]E6)Y5=64X/L'(M%"(E%\(M%$(E%[(M%%(E%Z(M%&(E%Y(M%'(E% -MX(M%(&:)1=Z+121FB47)12@/ -MMT77\GI_/___U6)Y5=64X/L<(M5(&:)5>2+ -M52AFB57$BU4P9HE5I(I5.(M%"(M-)(A5H@^V50R+7)`D9HE-U(M-+&:)3;2+ -M<`R*332+>S!3B$VCZ!G]__]:,=*%P'4*C67T6UZ)T%_)PU/H_/___X-]%`%8 -M#X3'`0``]T7D`/\```^%^@```/=%U`#_```/A>T```#W1<0`_P``#X7@```` -M]T6T`/\```^%TP```(V'!`$``(V7"`$``(E%E(E5D(V/#`$``(V'$`$``(V7 -M%`$``/=%I`#_``")38R)18B)580/A9D````/MD7D4/]UE%;H_/___P^V1=10 -M_W605NC\____#[9%Q%#_=8Q6Z/S___^#Q"0/MD6T4/]UB%;H_/___P^V1:10 -M_W6$5NC\____#[9%HU"-AQ@!``!05NC\____@\0D#[9%HE"-CQP!``!15HE- -MF.C\____BTT0@\0,A0/ML50C8<$`0``4%:)193H_/___XM5U`^VQE"-CP@! -M``!15HE-D.C\____BU7$#[;&4(V/#`$``%%6B4V,Z/S___^+5;2#Q"0/ML90 -MC8\0`0``45:)38CH_/___XM5I`^VQE"-CQ0!``!15HE-A.C\____@\08Z2G^ -M__^)]E6)Y5=64XM="(M#*(MS,(MX#&H&C88@`0``4%?H_/___XM#,`4@`0`` -M4%?H_/___VH*Z/S___]3Z/S___]H]`$``.C\____@\0@:/0!``#H_/___VCT -M`0``Z/S___]H]`$``.C\____,=N#Q`R!QAP!``"05E?H_/___X3`6EFZ`0`` -M`'D6:/0!``!#Z/S___^!^P\G``!9=MHQTHUE]%M>B=!?R<.)]E6)Y5.+70A3 -MZ$O___](6G07:/0!``#H_/___UB)70B+7?S)Z3#___^X`0```(M=_,G#B?95 -MB>564VB@````H0````"+0!@%```$`%"+=0A6Z/S___^[!````(/$#*$````` -MBT`0!0``!`!05NC\____64M8>>>[!0```)"A`````(M`%`4```0`4%;H_/__ -M_UA+6GGGNP0```"A`````(M`$`4```0`4%;H_/___UE+6'GGC67X6U[)PXGV -M58GE4VB`````H0````"+0`P%```$`%"+70A3Z/S___]HL````*$`````BT`8 -M!0``!`!04^C\____BUW\R<.)]E6)Y593BW4(5N@J____:@"A`````(M`"`4` -M``0`4%;H_/___Z$`````BP`%```$`%!6Z/S___^(PU;H@?___P^VVXUE^(G8 -M6U[)PY!5B>575E-H+`T``(M="%/H_/___XG'@\@!4&@L#0``4^C\____:/`$ -M`0!3Z/S___^)QH/@8H/$'&:#^&)T%XGP@\AB#[;`4&CP!`$`4^C\____@\0, -M:```!`!3Z/S___]86E/HA/[__VH'H0````"+0`@%```$`%!3Z/S___]J$:$` -M````BP`%```$`%!3Z/S___]J!:$`````BT`(!0``!`!04^C\____@\0H:A&A -M`````(L`!0``!`!04^C\____4^BM_O__5FCP!`$`4^C\____:/`$`0!3Z/S_ -M__^#Q"17:"P-``!3Z/S___^#Q`R-9?1;7E_)PU6)Y5=64V@L#0``BUT(4^C\ -M____B<>#R`%0:"P-``!3Z/S___]H\`0!`%/H_/___XG&@^!B@\0<9H/X8G07 -MB?"#R&(/ML!0:/`$`0!3Z/S___^#Q`QH```$`%/H_/___UE84^B,_?__:@>A -M`````(M`"`4```0`4%/H_/___VH`H0````"+``4```0`4%/H_/___VH%H0`` -M``"+0`@%```$`%!3Z/S___^#Q"AJ`*$`````BP`%```$`%!3Z/S___]3Z+7] -M__]6:/`$`0!3Z/S___]H\`0!`%/H_/___X/$)%=H+`T``%/H_/___X/$#(UE -M]%M>7\G#58GE4XM="%/H[_S__VH*H0````"+0`@%```$`%!3Z/S___]J`*$` -M````BP`%```$`%!3Z/S___]3Z$;]__^#Q"!H`0`$`%/H_/___X/@`EJ$P%FZ -M_____W0*B="+7?S)PXUV`%/HDOS__VH!H0````"+``4```0`4%/H_/___U/H -M__S__VIDZ/S___]H`0`$`%/H_/___X/@`C'2@\0@A,`/E<)*Z[.058GE5U93 -M@^P(BT4(BU@,BWT,:"P-``!3B?J(5?/H_/___XE%[(/(`5!H+`T``%/H_/__ -M_VCP!`$`4^C\____B<:#X&*#Q!QF@_AB=!>)\(/(8@^VP%!H\`0!`%/H_/__ -M_X/$#&@```0`4^C\____6%J+10B)^HA0>0^V1?-0:`#@!0!3Z/S___]6:/`$ -M`0!3Z/S___]H\`0!`%/H_/___X/$(/]U[&@L#0``4^C\____@\0,C67T6UY? -MR<-5B>6`?1``BU4(BDT,=!VX`0```-/@"$)Y#[9">8E%#(E5",GI_/___XUV -M`+C^____T\`@0GGKX56)Y5=64X/L#&@L#0``BW4(5L9%\P#H_/___XE%Z(/( -M`5!H+`T``%;H_/___VCP!`$`5NC\____B47LBT7L@^!B@\0<9H/X8G08BD7L -M@\AB#[;`4&CP!`$`5NC\____@\0,:```!`!6Z/S___]96V@```0`5NC\____ -MB<-F@?M5JEA:=%)HL````*$`````BT`8!0``!`!05NC\_____W7L:/`$`0!6 -MZ/S___]H\`0!`%;H_/___X/$(/]UZ&@L#0``5NC\____#[9%\X/$#(UE]%M> -M7\G#,?^-=@"%_W@CC5\!D&B@````H0````"+0!@%```$`%!6Z/S___^#Q`Q+ -M=>&!_\@````/CYT```!H```$`%;H_/___XG#:+````"A`````(M`&`4```0` -M4%;H_/___X/$%&:!^U6J=1%'@?_'````?I3I./___XUV`&BP````H0````"+ -M0!@%```$`%!6Z/S___]H```$`%;H_/___X/$%&8]5:H/A03___]6QD7S`>B= -M^O__/#Y;#X7Q_O__5NC*_/__AR<,````````````` -M``````````````0````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M```````````````````````````````````````````````````````````` -M`````````0```````0`!``$``@`!``,``0`$``$`!0`!``8``0````$``"`! -M``!``0``8`$``(`!``"@`0``P`$`DC0``(4T``"%-```I30``+`T``"[-``` -MQC0``"``!,```` -M`@`!`*L```!4'@``,`````(``0"S````A!X``#L````"``$`O@```,`>```1 -M`````@`!`,8```#4'@``+`````(``0#8`````!\``"L````"``$`YP```"P? -M``!0`````@`!`/(```!\'P``.`````(``0#_````M!\``%$````"``$`"P$` -M``@@``#+`0```@`!`!@!``#4(0``L0````(``0`E`0``B"(``)<"```"``$` -M+P$``"`E``#P`````@`!`#X!``!89@``M0````(``0!)`0``$"8``.@#```" -M``$`50$``&0U``#W+0```@`!`&,!``#$9```.@$```(``0!O`0``^"D``"<` -M```"``$`>0$``$@S```9`@```@`!`(L!```@*@``I0````(``0"<`0``R"H` -M`!8!```"``$`J0$``.`K``"<`````@`!`+8!``"D+```;@````(``0##`0`` -M?"P``"@````"``$`S@$``!0M``!E`0```@`!`-D!``!\+@``P@$```(``0#E -M`0``;#(``&H````"``$`\P$``$`P``#%`````@`!```"```(,0``8@$```(` -M`0`-`@``V#(``&\````"``$``````````````````P`&`!X"```09P``#0,` -M``(``0`N`@``(&H``%H````"``$`10(``'QJ```\!0```@`!`%`"``"X;P`` -M8P,```(``0!<`@``'',``#0````"``$`;`(``&!X``!V`@```@`!`'D"``#@ -M?P``*`````(``0"*`@``=(```#\````"``$`GP(``+2````B`````@`!`+(" -M``#8@```/`````(``0"_`@``%($``+4"```"``$`U0(``,R#```\`0```@`! -M`.P"```(A0``E`````(``0`$`P``?)4``$H````"``$`$@,``)R%``!.`0`` -M`@`!`"4#``!,EP``4`````(``0`T`P``3)@```0"```"``$`2`,``&R,``!& -M`0```@`!`%L#``#LA@``D0````(``0!J`P``@(<``-("```"``$`?@,``-R/ -M```7`0```@`!`(P#``#TD```;0````(``0">`P``!)@``$8````"``$`JP,` -M`%2*``!1`````@`!`,$#``"`E@``+@````(``0#8`P``J(H``!X!```"``$` -MZP,``,B+``"A`````@`!`/L#``"PE@``F@````(``0`(!```G)<``&<````" -M``$`&P0``+2-``"&`0```@`!`"P$```\CP``H`````(``0`Z!```9)$``.8! -M```"``$`2P0``$R3```:`````@`!`&0$``!HDP``#0$```(``0![!```>)0` -M`#X````"``$`D`0``+B4``!D`````@`!`*0$``````7P```!(``0`'!@``Z`<``%`````2``$`&@8``'![ -M```3````$@`!`"@&```X"```(0$``!(``0`U!@``3'L``"$````2``$`1P8` -M`%QU``!8````$@`!`%(&``!<"0``(P$``!(``0!E!@``_`L``%<````2``$` -M=@8``"!^```3````$@`!`((&``#,?```,P```!(``0"2!@``5`P``.T````2 -M``$`I`8``/1]```K````$@`!`+0&``!$#0``.@```!(``0#'!@``@`T``'4` -M```2``$`V08``%`.``!.`0``$@`!`.\&``"@#P``@0```!(``0`,!P``)!`` -M`(8````2``$`(`<``%Q^``!(````$@`!`"X'``"L$```H0```!(``0!%!P`` -M4!$``$8!```2``$`70<``)@2``#!````$@`!`','`````````````!````!] -M!P``R!0```D"```2``$`CP<``#1^```E````$@`!`*`'``#4%@``(@$``!(` -M`0"S!P``^!<``+\!```2``$`Q`<``*@:``!7````$@`!`-0'````&P``[0`` -M`!(``0#E!P``\!L``"X````2``$`]P<````````$````$0`#``<(```````` -M`````!`````5"```7&,```H!```2``$`*`@`````````````$````#L(```` -M`````````!````!""``````````````0````20@``&AD``!<````$@`!`%4( -M`````````````!````!W"```B'T``&D````2``$`A0@```!F``!6````$@`! -M`)<(``!0P``0@```!(``0`1"0``A'L``$)X``.D!```2``$`?@L``&2@``"L````$@`!`),+``#$ -MH0``(````!(``0"J"P``Y*$``%\````2``$`RPL``$2B``"X````$@`!`.4+ -M``#\H@``AP```!(``0#^"P``A*,``/,````2``$`%@P``'BD``!5`0``$@`! -M`"T,``#0I0``4@```!(``0!$#```)*8``)H!```2``$`5PP``,"G``".`0`` -M$@`!`'4,``!0J0``'````!(``0"0#```;*D``!T````2``$`K0P``-BI```V -M````$@`!`,<,```0J@``-@```!(``0#B#```Z*H``'4````2``$`_PP``&"K -M``!_````$@`!`!T-``#@JP``*````!(``0`\#0``X*P``+8"```2``$`4@T` -M`(BQ``#X````$@`!`%D-``"`L@``^````!(``0!A#0``(+0``+P````2``$` -M;PT``-RT```X````$@`!``!R86ED+F,`4W1R:7!E1V5T0V]M;6%N9`!3=')I -M<&53<&QI=$-O;6UA;F0`27-61&5V3VYL:6YE`$1O0V]N=')O;$-M9`!*0D]$ -M1V5T0V]M;6%N9`!*0D]$4W!L:71#;VUM86YD`%]?:'!T7V%L;&]C`%]?:'!T -M7V9R964`9V%R8F%G95]A9&1R`&EN:71?:&5A<%]B;&]C:P!C8E]A;&QO8P!C -M8E]FF5R;P!C9E]I;FET`')E;6]V95]R86YG -M95]L;V-K`&%D9%]R86YG95]L;V-K`&QO8VM?&9E0!T87-K7V1O;F4`&]R -M7W1A&]R7W1A&]R;E]T87-K -M`&-H96-K7V1E<&5N9&5N8WD`9&ER96-T7W)E861?0!M=E-A=&%);FET061A<'1E<@!C:&5C:U]P&5C=71E3F]N541-04-O -M;6UA;F0`0F5E<$]N`$)E97!/9F8`00```%B``"&!``` -M`6,``+0$```"9P``S`0```)G``#D!````F<``/\$```"9P``-P4```%C``!4 -M!0```F8``&8%```":```O@4```)J``#E!0```6(``/(%```!8P``,`8```)K -M``"1!@```FT``-0&```";```7P<```)I``#4!P```FD``!\(```";```,@@` -M``%P``!2"````G(``*((```!<```O`@```)F``#0"````F0``-D(```";@`` -M\0@```)F``!`"0```G$``$X)```"0``!PT```%U```.#0```70``#@-```"=P``R`X```)V``#X#@```G<``#(/ -M```"9@``F`\```)F``!1$````G8``'@0```"=P``B1````%_``"/$````G<` -M`,@0```"=@``TA````)W``#C$````7\``.D0```"=P``+!$```)F``"T$@`` -M`G8``+X2```"=P``SQ(```%_``#5$@```G<````3```"9@``)!,```*#``"9 -M$P```G<``*43```!?P``K1,```)W``#+$P```GD``.T3```!@```]!,```%] -M```I%````F8``#P4```">0``7A0```%^``!E%````7T``)84```">0``N!0` -M``&"``"_%````8$``/P4```!`@``Z14```)Y``#T%0```F<```P6```!?``` -M$Q8```%[``"F%@```80``,@6```"=P``1!<```)M``"6%P```FH``*T7```! -M8@``M1<```%C``#M%P```FL```T9```"9P``U!H```)V``#Q&@```G<``&P; -M```">0``LQL```&(``"Z&P```8<``.0;```"=P``]!P```*,``!Q'@```F8` -M`,L>```"9@``/"0```)G``#")P```G<``+PH```!`@``1"D```%_``!**0`` -M`G<``%@I```!?P``<2D```$"``!Y*0```G<```XJ```!`@``%BH```)W``"\ -M*@```HX``/HK```"=@``OBP```)Y``#N+````0(``/4L```!`@``:"\```*/ -M``"0+P```I```"HP```"D```X3````*0```7,@```H\``&$R```"D```@30` -M``$N```%-0```2X``/5C```"=P``AF0```*-``",9````I(``))D```"DP`` -MF68```)W``#X9@```7\``/YF```"=P``[F@```$#``#9:0```0,``-YI```" -MC@``.VH```)V```&;0```F8``.1N```">0``#&\```$"```3;P```0(``#)O -M```!?P``.F\```)W```V````F8``,=Y```"9P``V7D` -M``)G``#N>0```F<```-Z```"9P``@7H```)E``"1>@```F4``+%Z```"9``` -M.GL```*;``##>P```F8``.I[```"9```GWP```)D``#J?0```I(``!=^```" -M9@``!G\```*B```/?P```J,``"!_```"I```IG\```*E``"R?P```J8``"*` -M```"J```/H````*I``!9@````J@``)2````"J@``I8````*J``#0@````JH` -M`/*#```"J0``!(0```*I```$```"J0``_(0```*L```NA0```JT```6'```"K0``&8<```*J -M```FAP```JT``#.'```"K0``2H<```*J``!7AP```JT``.R'```"J@``78@` -M``*M``!QB````JH``/6(```"J0``)XD```*J```PB0```JT``#>)```"J``` -M0HD```*J``!.B0```JT``%B)```"J```Q(D```&K``#4B@```JD``-Z*```" -MJ0``"(L```*J```BC````JX``$R,```"KP``3HT```*M``!5C0```J@``(*- -M```!JP``THT```*M``#FC0```JH``.V-```"K0``]XT```*H``"9C@```JH` -M`*N.```"J@``OHX```*J``#4C@```JH``...```"J@``]HX```*J```%CP`` -M`JH``!B/```"J@``+H\```*J```HD````JT``'F0```"J@``L)````*M``#5 -MD````JH``!J1```"J@``(Y$```*M```JD0```J@``#B1```"J@``09$```*M -M``"=D0```JH``*F1```"K0``P)$```*J``#4D0```JH``.61```"J@``]I$` -M``*J```*D@```JH``!N2```"J@``+)(```*J``!`D@```JH``%&2```"J@`` -M8I(```*J``!VD@```JH``(>2```"J@``FY(```*J``#2D@```JH``..2```" -MJ@``])(```*J```+DP```JH``!>3```"K0``+I,```*J``!@DP```JH``(23 -M```"K0``E9,```*J``"EDP```JT``+B3```"J@``QY,```*J``#9DP```JH` -M`.N3```"J@``^I,```*J```,E````JH``!N4```"J@``*I0```*J```\E``` -M`JH``$N4```"J@``6I0```*J``!LE````JH``#R5```"9P``;Y4```)G```? -ME@```JD``$^6```"J@``7Y8```*J``"EE@```JH``/Z6```"J@``#9<```*J -M```HEP```JD``#Z7```"J@``>9<```*J``"`EP```JT``!^8```"L```<)@` -M``*I``#KF````JP``/F8```"K```!YD```*L```8F0```JP``":9```"K``` -M.)D```*L``!)F0```JP``&B9```"J0``:```"K```+YH```*L``!$F@```JP``&R: -M```"J@``=)H```*S``````"K0``8YX```*H``!LG@```JT``-N>```"J@``Y)X```*M -M``#KG@```J@``/F>```"J@```I\```*M```SGP```JT``%N?```"J@``?9\` -M``*M``"$GP```J@``*>?```"J@``Q9\```*M``#/GP```J@``-J?```"IP`` -M#:````*I``"7H````JT``-R@```"J@``!J(```*M```IH@```JH``)VB```" -MK0``T*(```*J```KHP```JT``&:C```"J@``;Z,```*M``#%HP```JT``.^C -M```"J@``"*0```*M```DI````JT``$:D```"J@``P*0```*M``#AI````K0` -M`"6E```"K0``-Z4```*M``!)I0```JT``%NE```"K0``<*4```*M``""I0`` -M`JT``)2E```"K0``IJ4```*M```S```"K``` -MGK,```$$``"LLP```JP``,"S```"J0``Y;,```$$``#SLP```JP```"T```" -MJ```"[0```*I```^M````JT``%"T```"J@``6[0```*M``!]M````JX``(NT -M```"K0``I;0```*L``"QM````JH``+RT```"K0``S;0```*J```KM0```JT` -M`#VU```"J@``2+4```*M``!OM0```JX``'VU```"K0``BK4```*O``"?M0`` -M`00``*ZU```"K```O+4```*J``#'M0```JT``-BU```"J@``_K4```$$```- -MM@```JP``"JV```"KP``-K8```$$``!%M@```JP``&JV```!!```>;8```*L -M``"$M@```J\``,.V```"J```W[8```$$``#CM@```0,``/2V```!!```^+8` -M``$#``"C!@```FX``+@6```"A0``5A<```)N``"8)P```HT``%)F```"C0`` -M[&8```*-```_8<```*J``![E@```JT``/^7```"J@```*P```*P``#```.`````&$``!``````94``&`````!<```9`````%P``!H```` -M`7```&P````!<```<`````&*``!T`````7H``'@````!A@``@`````&6```` -M`````0(```0````!`@``"`````$"```,`````0(``!`````!`@``%`````$" -M```8`````0(``!P````!`@``(`````$"```D`````0(``"@````!`@``+``` -5``$"```P`````0(``#0````!`@`` -` -end diff --git a/sys/contrib/dev/hptmv/ioctl.c b/sys/contrib/dev/hptmv/ioctl.c deleted file mode 100644 index 2cfe97912c28..000000000000 --- a/sys/contrib/dev/hptmv/ioctl.c +++ /dev/null @@ -1,928 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/* - * ioctl.c ioctl interface implementation - */ -#include -#include -#include -#include - -#include -#include -#include -#include - -#pragma pack(1) - -typedef struct _HPT_REBUILD_PARAM -{ - DEVICEID idMirror; - DWORD Lba; - UCHAR nSector; -} HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; - -#pragma pack() - -#define MAX_EVENTS 10 -static HPT_EVENT hpt_event_queue[MAX_EVENTS]; -static int event_queue_head=0, event_queue_tail=0; - -static int hpt_get_event(PHPT_EVENT pEvent); -static int hpt_set_array_state(DEVICEID idArray, DWORD state); -static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter); -static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); -static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, - FPSCAT_GATH pSgTable, int logical); - -static void get_disk_location(PDevice pDev, int *controller, int *channel) -{ - IAL_ADAPTER_T *pAdapTemp; - int i, j; - - for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { - for (j=0; jVDevices[j].u.disk) { - *controller = i; - *channel = j; - return; - } - } -} - -static int event_queue_add(PHPT_EVENT pEvent) -{ - int p; - p = (event_queue_tail + 1) % MAX_EVENTS; - if (p==event_queue_head) - { - return -1; - } - hpt_event_queue[event_queue_tail] = *pEvent; - event_queue_tail = p; - return 0; -} - -static int event_queue_remove(PHPT_EVENT pEvent) -{ - if (event_queue_head != event_queue_tail) - { - *pEvent = hpt_event_queue[event_queue_head]; - event_queue_head++; - event_queue_head %= MAX_EVENTS; - return 0; - } - return -1; -} - -void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param) -{ - HPT_EVENT e; - ZeroMemory(&e, sizeof(e)); - e.EventType = event; - switch(event) - { - case ET_INITIALIZE_ABORTED: - case ET_INITIALIZE_FAILED: - memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); - case ET_INITIALIZE_STARTED: - case ET_INITIALIZE_FINISHED: - - case ET_REBUILD_STARTED: - case ET_REBUILD_ABORTED: - case ET_REBUILD_FAILED: - case ET_REBUILD_FINISHED: - - case ET_VERIFY_STARTED: - case ET_VERIFY_ABORTED: - case ET_VERIFY_FAILED: - case ET_VERIFY_FINISHED: - case ET_VERIFY_DATA_ERROR: - - case ET_SPARE_TOOK_OVER: - case ET_DEVICE_REMOVED: - case ET_DEVICE_PLUGGED: - case ET_DEVICE_ERROR: - e.DeviceID = VDEV_TO_ID((PVDevice)param); - break; - - default: - break; - } - event_queue_add(&e); - if (event==ET_DEVICE_REMOVED) { - int controller, channel; - get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); - hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); - } -} - -static int hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) -{ - PVDevice pArray = ID_TO_VDEV(id); - BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; - int i; - PVDevice pa; - - if((id== HPT_NULL_ID) || check_VDevice_valid(pArray)) - return -1; - - if(!mIsArray(pArray)) return -1; - - if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || - pArray->u.array.rf_initializing) - return -1; - - for(i=0; iu.array.bArnMember; i++) { - pa = pArray->u.array.pMember[i]; - if (pa && mIsArray(pa)) { - if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || - pa->u.array.rf_initializing) - return -1; - } - } - - if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} - fDeleteArray(_VBUS_P pArray, del_block0); - return 0; - -} - -/* just to prevent driver from sending more commands */ -static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} - -static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter) -{ - intrmask_t oldspl; - _VBUS_INST(&pAdapter->VBus) - oldspl = lock_driver(); - while (pAdapter->outstandingCommands) { - KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); - if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); - unlock_driver(oldspl); - oldspl = lock_driver(); - } - CheckIdleCall(_VBUS_P0); - return oldspl; -} - -int Kernel_DeviceIoControl(_VBUS_ARG - DWORD dwIoControlCode, /* operation control code */ - PVOID lpInBuffer, /* input data buffer */ - DWORD nInBufferSize, /* size of input data buffer */ - PVOID lpOutBuffer, /* output data buffer */ - DWORD nOutBufferSize, /* size of output data buffer */ - PDWORD lpBytesReturned /* byte count */ - ) -{ - IAL_ADAPTER_T *pAdapter; - - switch(dwIoControlCode) { - case HPT_IOCTL_DELETE_ARRAY: - { - DEVICEID idArray; - int iSuccess; - int i; - PVDevice pArray; - PVBus _vbus_p; - struct cam_periph *periph = NULL; - - if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; - if (nOutBufferSize!=sizeof(int)) return -1; - idArray = *(DEVICEID *)lpInBuffer; - - pArray = ID_TO_VDEV(idArray); - - if((idArray == HPT_NULL_ID) || check_VDevice_valid(pArray)) - return -1; - - if(!mIsArray(pArray)) - return -1; - - _vbus_p=pArray->pVBus; - pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; - - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { - if(pArray == _vbus_p->pVDevice[i]) - { - periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); - if (periph != NULL && periph->refcount == 1) - { - hpt_printk(("Can not delete a mounted device.\n")); - return -1; - } - } - /* the Mounted Disk isn't delete */ - } - - iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); - - *(int*)lpOutBuffer = iSuccess; - - if(iSuccess != 0) - return -1; - break; - } - - case HPT_IOCTL_GET_EVENT: - { - PHPT_EVENT pInfo; - - if (nInBufferSize!=0) return -1; - if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; - - pInfo = (PHPT_EVENT)lpOutBuffer; - - if (hpt_get_event(pInfo)!=0) - return -1; - } - break; - - case HPT_IOCTL_SET_ARRAY_STATE: - { - DEVICEID idArray; - DWORD state; - - if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; - if (nOutBufferSize!=0) return -1; - - idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; - state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; - - if(hpt_set_array_state(idArray, state)!=0) - return -1; - } - break; - - case HPT_IOCTL_RESCAN_DEVICES: - { - if (nInBufferSize!=0) return -1; - if (nOutBufferSize!=0) return -1; - -#ifndef FOR_DEMO - /* stop buzzer if user perform rescan */ - for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { - if (pAdapter->beeping) { - pAdapter->beeping = 0; - BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); - } - } -#endif - } - break; - - default: - { - PVDevice pVDev; -#ifdef SUPPORT_ARRAY - intrmask_t oldspl; -#endif - switch(dwIoControlCode) { - /* read-only ioctl functions can be called directly. */ - case HPT_IOCTL_GET_VERSION: - case HPT_IOCTL_GET_CONTROLLER_IDS: - case HPT_IOCTL_GET_CONTROLLER_COUNT: - case HPT_IOCTL_GET_CONTROLLER_INFO: - case HPT_IOCTL_GET_CHANNEL_INFO: - case HPT_IOCTL_GET_LOGICAL_DEVICES: - case HPT_IOCTL_GET_DEVICE_INFO: - case HPT_IOCTL_GET_EVENT: - case HPT_IOCTL_GET_DRIVER_CAPABILITIES: - if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, - lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; - break; - - default: - /* - * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be - * wrong for second controller. - */ - switch(dwIoControlCode) { - case HPT_IOCTL_CREATE_ARRAY: - pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; - case HPT_IOCTL_SET_ARRAY_INFO: - pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; - case HPT_IOCTL_SET_DEVICE_INFO: - pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; - case HPT_IOCTL_SET_BOOT_MARK: - case HPT_IOCTL_ADD_SPARE_DISK: - case HPT_IOCTL_REMOVE_SPARE_DISK: - pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; - case HPT_IOCTL_ADD_DISK_TO_ARRAY: - pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; - default: - pVDev = 0; - } - - if (pVDev && !check_VDevice_valid(pVDev)){ - _vbus_p = pVDev->pVBus; - - pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; - /* - * create_array, and other functions can't be executed while channel is - * perform I/O commands. Wait until driver is idle. - */ - oldspl = lock_driver_idle(pAdapter); - if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, - lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { - unlock_driver(oldspl); - return -1; - } - unlock_driver(oldspl); - } - else - return -1; - break; - } - -#ifdef SUPPORT_ARRAY - switch(dwIoControlCode) - { - case HPT_IOCTL_CREATE_ARRAY: - { - pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; - oldspl = lock_driver(); - if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) - { - (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); - } - else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) - { - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); - } - else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) - { - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); - } - unlock_driver(oldspl); - break; - } - - case HPT_IOCTL_ADD_DISK_TO_ARRAY: - { - PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); - pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; - if(pArray->u.array.rf_rebuilding == HPT_NULL_ID) - { - DWORD timeout = 0; - oldspl = lock_driver(); - pArray->u.array.rf_auto_rebuild = 0; - pArray->u.array.rf_abort_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); - unlock_driver(oldspl); - while (!pArray->u.array.rf_rebuilding) - { - tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1); - if ( timeout >= hz*3) - break; - timeout ++; - } - } - break; - } - } -#endif - return 0; - } - } - - if (lpBytesReturned) - *lpBytesReturned = nOutBufferSize; - return 0; -} - -static int hpt_get_event(PHPT_EVENT pEvent) -{ - intrmask_t oldspl = lock_driver(); - int ret = event_queue_remove(pEvent); - unlock_driver(oldspl); - return ret; -} - -static int hpt_set_array_state(DEVICEID idArray, DWORD state) -{ - IAL_ADAPTER_T *pAdapter; - PVDevice pVDevice = ID_TO_VDEV(idArray); - int i; - DWORD timeout = 0; - intrmask_t oldspl; - - if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) - return -1; - if(!mIsArray(pVDevice)) - return -1; - if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; - - pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; - - switch(state) - { - case MIRROR_REBUILD_START: - { - if (pVDevice->u.array.rf_rebuilding || - pVDevice->u.array.rf_verifying || - pVDevice->u.array.rf_initializing) - return -1; - - oldspl = lock_driver(); - - pVDevice->u.array.rf_auto_rebuild = 0; - pVDevice->u.array.rf_abort_rebuild = 0; - - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, - (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); - - unlock_driver(oldspl); - - while (!pVDevice->u.array.rf_rebuilding) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*20) - break; - timeout ++; - } - } - - break; - - case MIRROR_REBUILD_ABORT: - { - for(i = 0; i < pVDevice->u.array.bArnMember; i++) { - if(pVDevice->u.array.pMember[i] != NULL && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) - hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); - } - - if(pVDevice->u.array.rf_rebuilding != 1) - return -1; - - oldspl = lock_driver(); - pVDevice->u.array.rf_abort_rebuild = 1; - unlock_driver(oldspl); - - while (pVDevice->u.array.rf_abort_rebuild) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*20) - break; - timeout ++; - } - } - break; - - case AS_VERIFY_START: - { - /*if(pVDevice->u.array.rf_verifying) - return -1;*/ - if (pVDevice->u.array.rf_rebuilding || - pVDevice->u.array.rf_verifying || - pVDevice->u.array.rf_initializing) - return -1; - - oldspl = lock_driver(); - pVDevice->u.array.RebuildSectors = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); - unlock_driver(oldspl); - - while (!pVDevice->u.array.rf_verifying) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*20) - break; - timeout ++; - } - } - break; - - case AS_VERIFY_ABORT: - { - if(pVDevice->u.array.rf_verifying != 1) - return -1; - - oldspl = lock_driver(); - pVDevice->u.array.rf_abort_rebuild = 1; - unlock_driver(oldspl); - - while (pVDevice->u.array.rf_abort_rebuild) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*80) - break; - timeout ++; - } - } - break; - - case AS_INITIALIZE_START: - { - if (pVDevice->u.array.rf_rebuilding || - pVDevice->u.array.rf_verifying || - pVDevice->u.array.rf_initializing) - return -1; - - oldspl = lock_driver(); - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); - unlock_driver(oldspl); - - while (!pVDevice->u.array.rf_initializing) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*80) - break; - timeout ++; - } - } - break; - - case AS_INITIALIZE_ABORT: - { - if(pVDevice->u.array.rf_initializing != 1) - return -1; - - oldspl = lock_driver(); - pVDevice->u.array.rf_abort_rebuild = 1; - unlock_driver(oldspl); - - while (pVDevice->u.array.rf_abort_rebuild) - { - tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); - if ( timeout >= hz*80) - break; - timeout ++; - } - } - break; - - default: - return -1; - } - - return 0; -} - -static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) -{ - ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); - if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) - bufferSize<<=1; - if (logical) { - pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; - pSgTable->wSgSize = (USHORT)bufferSize; - pSgTable->wSgFlag = SG_FLAG_EOT; - } - else { - /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ - ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; - ULONG length; - int idx = 0; - - v = pCmd->uCmd.R1Control.Buffer; - dataPointer = (ADDRESS)fOsPhysicalAddress(v); - - if ((ULONG_PTR)dataPointer & 0x1) - return FALSE; - - #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) - #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) - - do { - if (idx >= MAX_SG_DESCRIPTORS) return FALSE; - - pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); - currvaddr = v; - currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); - - - do { - nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); - nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); - - if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; - nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); - - if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { - nextvaddr = nextpage; - break; - } - - currvaddr = nextvaddr; - currphypage = nextphypage; - }while (1); - - length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; - v = nextvaddr; - bufferSize -= length; - - pSgTable[idx].wSgSize = (USHORT)length; - pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; - idx++; - - }while (bufferSize); - } - return 1; -} - -static int End_Job=0; -static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd) -{ - End_Job = 1; - wakeup((caddr_t)pCmd); -} - -void hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) -{ - DWORD timeout = 0; - ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); - PCommand pCmd; - UINT result; - int needsync=0, retry=0, needdelete=0; - void *buffer = 0; - intrmask_t oldspl; - - _VBUS_INST(&pAdapter->VBus) - - if (pArray->u.array.rf_broken==1 || - pArray->u.array.RebuildSectors>=capacity) - return; - - oldspl = lock_driver(); - - switch(flags) - { - case DUPLICATE: - case REBUILD_PARITY: - if(pArray->u.array.rf_rebuilding == 0) - { - pArray->u.array.rf_rebuilding = 1; - hpt_printk(("Rebuilding started.\n")); - ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); - } - break; - - case INITIALIZE: - if(pArray->u.array.rf_initializing == 0) - { - pArray->u.array.rf_initializing = 1; - hpt_printk(("Initializing started.\n")); - ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); - } - break; - - case VERIFY: - if(pArray->u.array.rf_verifying == 0) - { - pArray->u.array.rf_verifying = 1; - hpt_printk(("Verifying started.\n")); - ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); - } - break; - } - -retry_cmd: - pCmd = AllocateCommand(_VBUS_P0); - HPT_ASSERT(pCmd); - pCmd->cf_control = 1; - End_Job = 0; - - if (pArray->VDeviceType==VD_RAID_1) - { - #define MAX_REBUILD_SECTORS 0x40 - - /* take care for discontinuous buffer in R1ControlSgl */ - buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); - if(!buffer) { - FreeCommand(_VBUS_P pCmd); - hpt_printk(("can't allocate rebuild buffer\n")); - goto fail; - } - switch(flags) - { - case DUPLICATE: - pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; - pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; - break; - - case VERIFY: - pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; - pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; - break; - - case INITIALIZE: - pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; - pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; - break; - } - - pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; - - if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) - pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; - - pCmd->uCmd.R1Control.Buffer = buffer; - pCmd->pfnBuildSgl = R1ControlSgl; - } - else if (pArray->VDeviceType==VD_RAID_5) - { - switch(flags) - { - case DUPLICATE: - case REBUILD_PARITY: - pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; - case VERIFY: - pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; - case INITIALIZE: - pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; - } - pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; - } - else - HPT_ASSERT(0); - - pCmd->pVDevice = pArray; - pCmd->pfnCompletion = thread_io_done; - pArray->pfnSendCommand(_VBUS_P pCmd); - CheckPendingCall(_VBUS_P0); - - if (!End_Job) { - unlock_driver(oldspl); - while (!End_Job) { - tsleep((caddr_t)pCmd, PPAUSE, "pause", hz); - if (timeout++>60) break; - } - oldspl = lock_driver(); - if (!End_Job) { - hpt_printk(("timeout, reset\n")); - fResetVBus(_VBUS_P0); - } - } - - result = pCmd->Result; - FreeCommand(_VBUS_P pCmd); - if (buffer) { - free(buffer, M_DEVBUF); - /* beware of goto retry_cmd below */ - buffer = NULL; - } - KdPrintI(("cmd finished %d", result)); - - switch(result) - { - case RETURN_SUCCESS: - if (!pArray->u.array.rf_abort_rebuild) - { - if(pArray->u.array.RebuildSectors < capacity) - { - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); - } - else - { - switch (flags) - { - case DUPLICATE: - case REBUILD_PARITY: - needsync = 1; - pArray->u.array.rf_rebuilding = 0; - pArray->u.array.rf_need_rebuild = 0; - pArray->u.array.CriticalMembers = 0; - pArray->u.array.RebuildSectors = MAX_LBA_T; - pArray->u.array.rf_duplicate_and_create = 0; - hpt_printk(("Rebuilding finished.\n")); - ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); - break; - case INITIALIZE: - needsync = 1; - pArray->u.array.rf_initializing = 0; - pArray->u.array.rf_need_rebuild = 0; - pArray->u.array.RebuildSectors = MAX_LBA_T; - hpt_printk(("Initializing finished.\n")); - ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); - break; - case VERIFY: - pArray->u.array.rf_verifying = 0; - hpt_printk(("Verifying finished.\n")); - ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); - break; - } - } - } - else - { - pArray->u.array.rf_abort_rebuild = 0; - if (pArray->u.array.rf_rebuilding) - { - hpt_printk(("Abort rebuilding.\n")); - pArray->u.array.rf_rebuilding = 0; - pArray->u.array.rf_duplicate_and_create = 0; - ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); - } - else if (pArray->u.array.rf_verifying) - { - hpt_printk(("Abort verifying.\n")); - pArray->u.array.rf_verifying = 0; - ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); - } - else if (pArray->u.array.rf_initializing) - { - hpt_printk(("Abort initializing.\n")); - pArray->u.array.rf_initializing = 0; - ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); - } - needdelete=1; - } - break; - - case RETURN_DATA_ERROR: - if (flags==VERIFY) - { - needsync = 1; - pArray->u.array.rf_verifying = 0; - pArray->u.array.rf_need_rebuild = 1; - hpt_printk(("Verifying failed: found inconsistency\n")); - ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); - ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); - - if (!pArray->vf_online || pArray->u.array.rf_broken) break; - - pArray->u.array.rf_auto_rebuild = 0; - pArray->u.array.rf_abort_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, - (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); - } - break; - - default: - hpt_printk(("command failed with error %d\n", result)); - if (++retry<3) - { - hpt_printk(("retry (%d)\n", retry)); - goto retry_cmd; - } -fail: - pArray->u.array.rf_abort_rebuild = 0; - switch (flags) - { - case DUPLICATE: - case REBUILD_PARITY: - needsync = 1; - pArray->u.array.rf_rebuilding = 0; - pArray->u.array.rf_duplicate_and_create = 0; - hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); - ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); - break; - - case INITIALIZE: - needsync = 1; - pArray->u.array.rf_initializing = 0; - hpt_printk(("Initializing failed.\n")); - ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); - break; - - case VERIFY: - needsync = 1; - pArray->u.array.rf_verifying = 0; - hpt_printk(("Verifying failed.\n")); - ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); - break; - } - needdelete=1; - } - - while (pAdapter->outstandingCommands) - { - KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); - /* put this to have driver stop processing system commands quickly */ - if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); - unlock_driver(oldspl); - oldspl = lock_driver(); - } - - if (needsync) SyncArrayInfo(pArray); - if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) - fDeleteArray(_VBUS_P pArray, TRUE); - - Check_Idle_Call(pAdapter); - unlock_driver(oldspl); -} diff --git a/sys/contrib/dev/hptmv/mvSata.h b/sys/contrib/dev/hptmv/mvSata.h deleted file mode 100644 index 486f64ffa8f7..000000000000 --- a/sys/contrib/dev/hptmv/mvSata.h +++ /dev/null @@ -1,429 +0,0 @@ -/* - * Copyright (c) 2003-2004 MARVELL SEMICONDUCTOR ISRAEL, LTD. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifndef __INCmvSatah -#define __INCmvSatah - -#ifndef SUPPORT_MV_SATA_GEN_1 -#define SUPPORT_MV_SATA_GEN_1 1 -#endif - -#ifndef SUPPORT_MV_SATA_GEN_2 -#define SUPPORT_MV_SATA_GEN_2 0 -#endif - -#if SUPPORT_MV_SATA_GEN_1==1 && SUPPORT_MV_SATA_GEN_2==1 -#define MV_SATA_GEN_1(x) ((x)->sataAdapterGeneration==1) -#define MV_SATA_GEN_2(x) ((x)->sataAdapterGeneration==2) -#elif SUPPORT_MV_SATA_GEN_1==1 -#define MV_SATA_GEN_1(x) 1 -#define MV_SATA_GEN_2(x) 0 -#elif SUPPORT_MV_SATA_GEN_2==1 -#define MV_SATA_GEN_1(x) 0 -#define MV_SATA_GEN_2(x) 1 -#else -#error "Which IC do you support?" -#endif - -/* Definitions */ -/* MV88SX50XX specific defines */ -#define MV_SATA_VENDOR_ID 0x11AB -#define MV_SATA_DEVICE_ID_5080 0x5080 -#define MV_SATA_DEVICE_ID_5081 0x5081 -#define MV_SATA_DEVICE_ID_6080 0x6080 -#define MV_SATA_DEVICE_ID_6081 0x6081 -#define MV_SATA_CHANNELS_NUM 8 -#define MV_SATA_UNITS_NUM 2 -#define MV_SATA_PCI_BAR0_SPACE_SIZE (1<<18) /* 256 Kb*/ - -#define CHANNEL_QUEUE_LENGTH 32 -#define CHANNEL_QUEUE_MASK 0x1F - -#define MV_EDMA_QUEUE_LENGTH 32 /* Up to 32 outstanding */ - /* commands per SATA channel*/ -#define MV_EDMA_QUEUE_MASK 0x1F -#define MV_EDMA_REQUEST_QUEUE_SIZE 1024 /* 32*32 = 1KBytes */ -#define MV_EDMA_RESPONSE_QUEUE_SIZE 256 /* 32*8 = 256 Bytes */ - -#define MV_EDMA_REQUEST_ENTRY_SIZE 32 -#define MV_EDMA_RESPONSE_ENTRY_SIZE 8 - -#define MV_EDMA_PRD_ENTRY_SIZE 16 /* 16Bytes*/ -#define MV_EDMA_PRD_NO_SNOOP_FLAG 0x00000001 /* MV_BIT0 */ -#define MV_EDMA_PRD_EOT_FLAG 0x00008000 /* MV_BIT15 */ - -#define MV_ATA_IDENTIFY_DEV_DATA_LENGTH 256 /* number of words(2 byte)*/ -#define MV_ATA_MODEL_NUMBER_LEN 40 -#define ATA_SECTOR_SIZE 512 -/* Log messages level defines */ -#define MV_DEBUG 0x1 -#define MV_DEBUG_INIT 0x2 -#define MV_DEBUG_INTERRUPTS 0x4 -#define MV_DEBUG_SATA_LINK 0x8 -#define MV_DEBUG_UDMA_COMMAND 0x10 -#define MV_DEBUG_NON_UDMA_COMMAND 0x20 -#define MV_DEBUG_ERROR 0x40 - - -/* Typedefs */ -typedef enum mvUdmaType -{ - MV_UDMA_TYPE_READ, MV_UDMA_TYPE_WRITE -} MV_UDMA_TYPE; - -typedef enum mvFlushType -{ - MV_FLUSH_TYPE_CALLBACK, MV_FLUSH_TYPE_NONE -} MV_FLUSH_TYPE; - -typedef enum mvCompletionType -{ - MV_COMPLETION_TYPE_NORMAL, MV_COMPLETION_TYPE_ERROR, - MV_COMPLETION_TYPE_ABORT -} MV_COMPLETION_TYPE; - -typedef enum mvEventType -{ - MV_EVENT_TYPE_ADAPTER_ERROR, MV_EVENT_TYPE_SATA_CABLE -} MV_EVENT_TYPE; - -typedef enum mvEdmaMode -{ - MV_EDMA_MODE_QUEUED, - MV_EDMA_MODE_NOT_QUEUED, - MV_EDMA_MODE_NATIVE_QUEUING -} MV_EDMA_MODE; - -typedef enum mvEdmaQueueResult -{ - MV_EDMA_QUEUE_RESULT_OK = 0, - MV_EDMA_QUEUE_RESULT_EDMA_DISABLED, - MV_EDMA_QUEUE_RESULT_FULL, - MV_EDMA_QUEUE_RESULT_BAD_LBA_ADDRESS, - MV_EDMA_QUEUE_RESULT_BAD_PARAMS -} MV_EDMA_QUEUE_RESULT; - -typedef enum mvQueueCommandResult -{ - MV_QUEUE_COMMAND_RESULT_OK = 0, - MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED, - MV_QUEUE_COMMAND_RESULT_FULL, - MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS, - MV_QUEUE_COMMAND_RESULT_BAD_PARAMS -} MV_QUEUE_COMMAND_RESULT; - -typedef enum mvNonUdmaProtocol -{ - MV_NON_UDMA_PROTOCOL_NON_DATA, - MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, - MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT -} MV_NON_UDMA_PROTOCOL; - - -struct mvDmaRequestQueueEntry; -struct mvDmaResponseQueueEntry; -struct mvDmaCommandEntry; - -struct mvSataAdapter; -struct mvStorageDevRegisters; - -typedef MV_BOOLEAN (* HPTLIBAPI mvSataCommandCompletionCallBack_t)(struct mvSataAdapter *, - MV_U8, - MV_COMPLETION_TYPE, - MV_VOID_PTR, MV_U16, - MV_U32, - struct mvStorageDevRegisters FAR*); - -typedef enum mvQueuedCommandType -{ - MV_QUEUED_COMMAND_TYPE_UDMA, - MV_QUEUED_COMMAND_TYPE_NONE_UDMA -} MV_QUEUED_COMMAND_TYPE; - -typedef struct mvUdmaCommandParams -{ - MV_UDMA_TYPE readWrite; - MV_BOOLEAN isEXT; - MV_U32 lowLBAAddress; - MV_U16 highLBAAddress; - MV_U16 numOfSectors; - MV_U32 prdLowAddr; - MV_U32 prdHighAddr; - mvSataCommandCompletionCallBack_t callBack; - MV_VOID_PTR commandId; -} MV_UDMA_COMMAND_PARAMS; - -typedef struct mvNoneUdmaCommandParams -{ - MV_NON_UDMA_PROTOCOL protocolType; - MV_BOOLEAN isEXT; - MV_U16_PTR bufPtr; - MV_U32 count; - MV_U16 features; - MV_U16 sectorCount; - MV_U16 lbaLow; - MV_U16 lbaMid; - MV_U16 lbaHigh; - MV_U8 device; - MV_U8 command; - mvSataCommandCompletionCallBack_t callBack; - MV_VOID_PTR commandId; -} MV_NONE_UDMA_COMMAND_PARAMS; - -typedef struct mvQueueCommandInfo -{ - MV_QUEUED_COMMAND_TYPE type; - union - { - MV_UDMA_COMMAND_PARAMS udmaCommand; - MV_NONE_UDMA_COMMAND_PARAMS NoneUdmaCommand; - } commandParams; -} MV_QUEUE_COMMAND_INFO; - -/* The following structure is for the Core Driver internal usage */ -typedef struct mvQueuedCommandEntry -{ - MV_BOOLEAN isFreeEntry; - MV_U8 commandTag; - struct mvQueuedCommandEntry *next; - struct mvQueuedCommandEntry *prev; - MV_QUEUE_COMMAND_INFO commandInfo; -} MV_QUEUED_COMMAND_ENTRY; - -/* The following structures are part of the Core Driver API */ -typedef struct mvSataChannel -{ - /* Fields set by Intermediate Application Layer */ - MV_U8 channelNumber; - MV_BOOLEAN waitingForInterrupt; - MV_BOOLEAN lba48Address; - MV_BOOLEAN maxReadTransfer; - struct mvDmaRequestQueueEntry FAR *requestQueue; - struct mvDmaResponseQueueEntry FAR *responseQueue; - MV_U32 requestQueuePciHiAddress; - MV_U32 requestQueuePciLowAddress; - MV_U32 responseQueuePciHiAddress; - MV_U32 responseQueuePciLowAddress; - /* Fields set by CORE driver */ - struct mvSataAdapter *mvSataAdapter; - MV_OS_SEMAPHORE semaphore; - MV_U32 eDmaRegsOffset; - MV_U16 identifyDevice[MV_ATA_IDENTIFY_DEV_DATA_LENGTH]; - MV_BOOLEAN EdmaActive; - MV_EDMA_MODE queuedDMA; - MV_U8 outstandingCommands; - MV_BOOLEAN workAroundDone; - struct mvQueuedCommandEntry commandsQueue[CHANNEL_QUEUE_LENGTH]; - struct mvQueuedCommandEntry *commandsQueueHead; - struct mvQueuedCommandEntry *commandsQueueTail; - MV_BOOLEAN queueCommandsEnabled; - MV_U8 noneUdmaOutstandingCommands; - MV_U8 EdmaQueuedCommands; - MV_U32 freeIDsStack[MV_EDMA_QUEUE_LENGTH]; - MV_U32 freeIDsNum; - MV_U32 reqInPtr; - MV_U32 rspOutPtr; -} MV_SATA_CHANNEL; - -typedef struct mvSataAdapter -{ - /* Fields set by Intermediate Application Layer */ - MV_U32 adapterId; - MV_U8 pcbVersion; - MV_U8 pciConfigRevisionId; - MV_U16 pciConfigDeviceId; - MV_VOID_PTR IALData; - MV_BUS_ADDR_T adapterIoBaseAddress; - MV_U32 intCoalThre[MV_SATA_UNITS_NUM]; - MV_U32 intTimeThre[MV_SATA_UNITS_NUM]; - MV_BOOLEAN (* HPTLIBAPI mvSataEventNotify)(struct mvSataAdapter *, - MV_EVENT_TYPE, - MV_U32, MV_U32); - MV_SATA_CHANNEL *sataChannel[MV_SATA_CHANNELS_NUM]; - MV_U32 pciCommand; - MV_U32 pciSerrMask; - MV_U32 pciInterruptMask; - - /* Fields set by CORE driver */ - MV_OS_SEMAPHORE semaphore; - MV_U32 mainMask; - MV_OS_SEMAPHORE interruptsMaskSem; - MV_BOOLEAN implementA0Workarounds; - MV_BOOLEAN implement50XXB0Workarounds; - MV_BOOLEAN implement50XXB1Workarounds; - MV_BOOLEAN implement50XXB2Workarounds; - MV_BOOLEAN implement60X1A0Workarounds; - MV_BOOLEAN implement60X1A1Workarounds; - MV_BOOLEAN implement60X1B0Workarounds; - MV_U8 sataAdapterGeneration; - MV_U8 failLEDMask; - MV_U8 signalAmps[MV_SATA_CHANNELS_NUM]; - MV_U8 pre[MV_SATA_CHANNELS_NUM]; - MV_BOOLEAN staggaredSpinup[MV_SATA_CHANNELS_NUM]; /* For 60x1 only */ -} MV_SATA_ADAPTER; - -typedef struct mvSataAdapterStatus -{ - /* Fields set by CORE driver */ - MV_BOOLEAN channelConnected[MV_SATA_CHANNELS_NUM]; - MV_U32 pciDLLStatusAndControlRegister; - MV_U32 pciCommandRegister; - MV_U32 pciModeRegister; - MV_U32 pciSERRMaskRegister; - MV_U32 intCoalThre[MV_SATA_UNITS_NUM]; - MV_U32 intTimeThre[MV_SATA_UNITS_NUM]; - MV_U32 R00StatusBridgePortRegister[MV_SATA_CHANNELS_NUM]; -}MV_SATA_ADAPTER_STATUS; - - -typedef struct mvSataChannelStatus -{ - /* Fields set by CORE driver */ - MV_BOOLEAN isConnected; - MV_U8 modelNumber[MV_ATA_MODEL_NUMBER_LEN]; - MV_BOOLEAN DMAEnabled; - MV_EDMA_MODE queuedDMA; - MV_U8 outstandingCommands; - MV_U32 EdmaConfigurationRegister; - MV_U32 EdmaRequestQueueBaseAddressHighRegister; - MV_U32 EdmaRequestQueueInPointerRegister; - MV_U32 EdmaRequestQueueOutPointerRegister; - MV_U32 EdmaResponseQueueBaseAddressHighRegister; - MV_U32 EdmaResponseQueueInPointerRegister; - MV_U32 EdmaResponseQueueOutPointerRegister; - MV_U32 EdmaCommandRegister; - MV_U32 PHYModeRegister; -}MV_SATA_CHANNEL_STATUS; - -/* this structure used by the IAL defines the PRD entries used by the EDMA HW */ -typedef struct mvSataEdmaPRDEntry -{ - volatile MV_U32 lowBaseAddr; - volatile MV_U16 byteCount; - volatile MV_U16 flags; - volatile MV_U32 highBaseAddr; - volatile MV_U32 reserved; -}MV_SATA_EDMA_PRD_ENTRY; - -/* API Functions */ - -/* CORE driver Adapter Management */ -MV_BOOLEAN HPTLIBAPI mvSataInitAdapter(MV_SATA_ADAPTER *pAdapter); - -MV_BOOLEAN HPTLIBAPI mvSataShutdownAdapter(MV_SATA_ADAPTER *pAdapter); - -MV_BOOLEAN HPTLIBAPI mvSataGetAdapterStatus(MV_SATA_ADAPTER *pAdapter, - MV_SATA_ADAPTER_STATUS *pAdapterStatus); - -MV_U32 HPTLIBAPI mvSataReadReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset); - -MV_VOID HPTLIBAPI mvSataWriteReg(MV_SATA_ADAPTER *pAdapter, MV_U32 regOffset, - MV_U32 regValue); - -MV_VOID HPTLIBAPI mvEnableAutoFlush(MV_VOID); -MV_VOID HPTLIBAPI mvDisableAutoFlush(MV_VOID); - - -/* CORE driver SATA Channel Management */ -MV_BOOLEAN HPTLIBAPI mvSataConfigureChannel(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataRemoveChannel(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataIsStorageDeviceConnected(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataChannelHardReset(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataConfigEdmaMode(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, - MV_EDMA_MODE eDmaMode, MV_U8 maxQueueDepth); - -MV_BOOLEAN HPTLIBAPI mvSataEnableChannelDma(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataDisableChannelDma(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataFlushDmaQueue(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, - MV_FLUSH_TYPE flushType); - -MV_U8 HPTLIBAPI mvSataNumOfDmaCommands(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataSetIntCoalParams (MV_SATA_ADAPTER *pAdapter, MV_U8 sataUnit, - MV_U32 intCoalThre, MV_U32 intTimeThre); - -MV_BOOLEAN HPTLIBAPI mvSataSetChannelPhyParams(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, - MV_U8 signalAmps, MV_U8 pre); - -MV_BOOLEAN HPTLIBAPI mvSataChannelPhyShutdown(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataChannelPhyPowerOn(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvSataChannelSetEdmaLoopBackMode(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, - MV_BOOLEAN loopBackOn); - -MV_BOOLEAN HPTLIBAPI mvSataGetChannelStatus(MV_SATA_ADAPTER *pAdapter, MV_U8 channelIndex, - MV_SATA_CHANNEL_STATUS *pChannelStatus); - -/* Execute UDMA ATA commands */ -MV_EDMA_QUEUE_RESULT HPTLIBAPI mvSataQueueUDmaCommand(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, - MV_UDMA_TYPE readWrite, - MV_U32 lowLBAAddr, - MV_U16 highLBAAddr, - MV_U16 sectorCount, - MV_U32 prdLowAddr, - MV_U32 prdHighAddr, - mvSataCommandCompletionCallBack_t callBack, - MV_VOID_PTR commandId); - -MV_QUEUE_COMMAND_RESULT HPTLIBAPI mvSataQueueCommand(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, - MV_QUEUE_COMMAND_INFO FAR *pCommandParams); - -/* Interrupt Service Routine */ -MV_BOOLEAN HPTLIBAPI mvSataInterruptServiceRoutine(MV_SATA_ADAPTER *pAdapter); - -MV_BOOLEAN HPTLIBAPI mvSataMaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter); - -MV_BOOLEAN HPTLIBAPI mvSataUnmaskAdapterInterrupt(MV_SATA_ADAPTER *pAdapter); - -/* Command Completion and Event Notification (user implemented) */ -MV_BOOLEAN HPTLIBAPI mvSataEventNotify(MV_SATA_ADAPTER *, MV_EVENT_TYPE , - MV_U32, MV_U32); - -/* - * Staggered spin-ip support and SATA interface speed control - * (relevant for 60x1 adapters) - */ -MV_BOOLEAN HPTLIBAPI mvSataEnableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter); -MV_BOOLEAN HPTLIBAPI mvSataDisableStaggeredSpinUpAll (MV_SATA_ADAPTER *pAdapter); - -#endif diff --git a/sys/contrib/dev/hptmv/mvStorageDev.h b/sys/contrib/dev/hptmv/mvStorageDev.h deleted file mode 100644 index a5f3eb945a89..000000000000 --- a/sys/contrib/dev/hptmv/mvStorageDev.h +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) 2003-2004 MARVELL SEMICONDUCTOR ISRAEL, LTD. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifndef __INCmvStorageDevh -#define __INCmvStorageDevh - -/* Definitions */ - -/* ATA register on the ATA drive*/ - -#define MV_EDMA_ATA_FEATURES_ADDR 0x11 -#define MV_EDMA_ATA_SECTOR_COUNT_ADDR 0x12 -#define MV_EDMA_ATA_LBA_LOW_ADDR 0x13 -#define MV_EDMA_ATA_LBA_MID_ADDR 0x14 -#define MV_EDMA_ATA_LBA_HIGH_ADDR 0x15 -#define MV_EDMA_ATA_DEVICE_ADDR 0x16 -#define MV_EDMA_ATA_COMMAND_ADDR 0x17 - -#define MV_ATA_ERROR_STATUS 0x00000001 /* MV_BIT0 */ -#define MV_ATA_DATA_REQUEST_STATUS 0x00000008 /* MV_BIT3 */ -#define MV_ATA_SERVICE_STATUS 0x00000010 /* MV_BIT4 */ -#define MV_ATA_DEVICE_FAULT_STATUS 0x00000020 /* MV_BIT5 */ -#define MV_ATA_READY_STATUS 0x00000040 /* MV_BIT6 */ -#define MV_ATA_BUSY_STATUS 0x00000080 /* MV_BIT7 */ - - -#define MV_ATA_COMMAND_READ_SECTORS 0x20 -#define MV_ATA_COMMAND_READ_SECTORS_EXT 0x24 -#define MV_ATA_COMMAND_READ_VERIFY_SECTORS 0x40 -#define MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT 0x42 -#define MV_ATA_COMMAND_READ_BUFFER 0xE4 -#define MV_ATA_COMMAND_WRITE_BUFFER 0xE8 -#define MV_ATA_COMMAND_WRITE_SECTORS 0x30 -#define MV_ATA_COMMAND_WRITE_SECTORS_EXT 0x34 -#define MV_ATA_COMMAND_DIAGNOSTIC 0x90 -#define MV_ATA_COMMAND_SMART 0xb0 -#define MV_ATA_COMMAND_READ_MULTIPLE 0xc4 -#define MV_ATA_COMMAND_WRITE_MULTIPLE 0xc5 -#define MV_ATA_COMMAND_STANDBY_IMMEDIATE 0xe0 -#define MV_ATA_COMMAND_IDLE_IMMEDIATE 0xe1 -#define MV_ATA_COMMAND_STANDBY 0xe2 -#define MV_ATA_COMMAND_IDLE 0xe3 -#define MV_ATA_COMMAND_SLEEP 0xe6 -#define MV_ATA_COMMAND_IDENTIFY 0xec -#define MV_ATA_COMMAND_DEVICE_CONFIG 0xb1 -#define MV_ATA_COMMAND_SET_FEATURES 0xef -#define MV_ATA_COMMAND_WRITE_DMA 0xca -#define MV_ATA_COMMAND_WRITE_DMA_EXT 0x35 -#define MV_ATA_COMMAND_WRITE_DMA_QUEUED 0xcc -#define MV_ATA_COMMAND_WRITE_DMA_QUEUED_EXT 0x36 -#define MV_ATA_COMMAND_WRITE_FPDMA_QUEUED_EXT 0x61 -#define MV_ATA_COMMAND_READ_DMA 0xc8 -#define MV_ATA_COMMAND_READ_DMA_EXT 0x25 -#define MV_ATA_COMMAND_READ_DMA_QUEUED 0xc7 -#define MV_ATA_COMMAND_READ_DMA_QUEUED_EXT 0x26 -#define MV_ATA_COMMAND_READ_FPDMA_QUEUED_EXT 0x60 -#define MV_ATA_COMMAND_FLUSH_CACHE 0xe7 -#define MV_ATA_COMMAND_FLUSH_CACHE_EXT 0xea - - -#define MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO 0x01 -#define MV_ATA_SET_FEATURES_ENABLE_WCACHE 0x02 /* Enable write cache */ -#define MV_ATA_SET_FEATURES_TRANSFER 0x03 /* Set transfer mode */ -#define MV_ATA_TRANSFER_UDMA_0 0x40 -#define MV_ATA_TRANSFER_UDMA_1 0x41 -#define MV_ATA_TRANSFER_UDMA_2 0x42 -#define MV_ATA_TRANSFER_UDMA_3 0x43 -#define MV_ATA_TRANSFER_UDMA_4 0x44 -#define MV_ATA_TRANSFER_UDMA_5 0x45 -#define MV_ATA_TRANSFER_UDMA_6 0x46 -#define MV_ATA_TRANSFER_UDMA_7 0x47 -#define MV_ATA_TRANSFER_PIO_SLOW 0x00 -#define MV_ATA_TRANSFER_PIO_0 0x08 -#define MV_ATA_TRANSFER_PIO_1 0x09 -#define MV_ATA_TRANSFER_PIO_2 0x0A -#define MV_ATA_TRANSFER_PIO_3 0x0B -#define MV_ATA_TRANSFER_PIO_4 0x0C -/* Enable advanced power management */ -#define MV_ATA_SET_FEATURES_ENABLE_APM 0x05 -/* Disable media status notification*/ -#define MV_ATA_SET_FEATURES_DISABLE_MSN 0x31 -/* Disable read look-ahead */ -#define MV_ATA_SET_FEATURES_DISABLE_RLA 0x55 -/* Enable release interrupt */ -#define MV_ATA_SET_FEATURES_ENABLE_RI 0x5D -/* Enable SERVICE interrupt */ -#define MV_ATA_SET_FEATURES_ENABLE_SI 0x5E -/* Disable revert power-on defaults */ -#define MV_ATA_SET_FEATURES_DISABLE_RPOD 0x66 -/* Disable write cache */ -#define MV_ATA_SET_FEATURES_DISABLE_WCACHE 0x82 -/* Disable advanced power management*/ -#define MV_ATA_SET_FEATURES_DISABLE_APM 0x85 -/* Enable media status notification */ -#define MV_ATA_SET_FEATURES_ENABLE_MSN 0x95 -/* Enable read look-ahead */ -#define MV_ATA_SET_FEATURES_ENABLE_RLA 0xAA -/* Enable revert power-on defaults */ -#define MV_ATA_SET_FEATURES_ENABLE_RPOD 0xCC -/* Disable release interrupt */ -#define MV_ATA_SET_FEATURES_DISABLE_RI 0xDD -/* Disable SERVICE interrupt */ -#define MV_ATA_SET_FEATURES_DISABLE_SI 0xDE - -/* Defines for parsing the IDENTIFY command results*/ -#define IDEN_SERIAL_NUM_OFFSET 10 -#define IDEN_SERIAL_NUM_SIZE 19-10 -#define IDEN_FIRMWARE_OFFSET 23 -#define IDEN_FIRMWARE_SIZE 26-23 -#define IDEN_MODEL_OFFSET 27 -#define IDEN_MODEL_SIZE 46-27 -#define IDEN_CAPACITY_1_OFFSET 49 -#define IDEN_VALID 53 -#define IDEN_NUM_OF_ADDRESSABLE_SECTORS 60 -#define IDEN_PIO_MODE_SPPORTED 64 -#define IDEN_QUEUE_DEPTH 75 -#define IDEN_SATA_CAPABILITIES 76 -#define IDEN_SATA_FEATURES_SUPPORTED 78 -#define IDEN_SATA_FEATURES_ENABLED 79 -#define IDEN_ATA_VERSION 80 -#define IDEN_SUPPORTED_COMMANDS1 82 -#define IDEN_SUPPORTED_COMMANDS2 83 -#define IDEN_ENABLED_COMMANDS1 85 -#define IDEN_ENABLED_COMMANDS2 86 -#define IDEN_UDMA_MODE 88 -#define IDEN_SATA_CAPABILITY 76 - - -/* Typedefs */ - -/* Structures */ -typedef struct mvStorageDevRegisters -{ - /* Fields set by CORE driver */ - MV_U8 errorRegister; - MV_U16 sectorCountRegister; - MV_U16 lbaLowRegister; - MV_U16 lbaMidRegister; - MV_U16 lbaHighRegister; - MV_U8 deviceRegister; - MV_U8 statusRegister; -} MV_STORAGE_DEVICE_REGISTERS; - -/* Bits for HD_ERROR */ -#define NM_ERR 0x02 /* media present */ -#define ABRT_ERR 0x04 /* Command aborted */ -#define MCR_ERR 0x08 /* media change request */ -#define IDNF_ERR 0x10 /* ID field not found */ -#define MC_ERR 0x20 /* media changed */ -#define UNC_ERR 0x40 /* Uncorrect data */ -#define WP_ERR 0x40 /* write protect */ -#define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ - -/* Function */ - -MV_BOOLEAN HPTLIBAPI mvStorageDevATAExecuteNonUDMACommand(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, - MV_NON_UDMA_PROTOCOL protocolType, - MV_BOOLEAN isEXT, - MV_U16 FAR *bufPtr, MV_U32 count, - MV_U16 features, - MV_U16 sectorCount, - MV_U16 lbaLow, MV_U16 lbaMid, - MV_U16 lbaHigh, MV_U8 device, - MV_U8 command); - -MV_BOOLEAN HPTLIBAPI mvStorageDevATAIdentifyDevice(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvStorageDevATASetFeatures(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex, MV_U8 subCommand, - MV_U8 subCommandSpecific1, - MV_U8 subCommandSpecific2, - MV_U8 subCommandSpecific3, - MV_U8 subCommandSpecific4); - -MV_BOOLEAN HPTLIBAPI mvStorageDevATAIdleImmediate(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvStorageDevATAFlushWriteCache(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvStorageDevATASoftResetDevice(MV_SATA_ADAPTER *pAdapter, - MV_U8 channelIndex); - -MV_BOOLEAN HPTLIBAPI mvReadWrite(MV_SATA_CHANNEL *pSataChannel, LBA_T Lba, UCHAR Cmd, void *tmpBuffer); - -#endif diff --git a/sys/contrib/dev/hptmv/raid5n.h b/sys/contrib/dev/hptmv/raid5n.h deleted file mode 100644 index a590b91a6030..000000000000 --- a/sys/contrib/dev/hptmv/raid5n.h +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -#ifdef _RAID5N_ - -/* OS provided function, call only at initialization time */ -extern void * HPTLIBAPI os_alloc_page(_VBUS_ARG0); /* may be cached memory */ -extern void * HPTLIBAPI os_alloc_dma_page(_VBUS_ARG0); /* must be non-cached memory */ -/* implement if the driver can be unloaded */ -void HPTLIBAPI os_free_page(_VBUS_ARG void *p); -void HPTLIBAPI os_free_dma_page(_VBUS_ARG void *p); - -typedef void (* HPTLIBAPI xfer_done_fn)(_VBUS_ARG void *tag, int result); - - -#define DATAXFER_STACK_VAR -#define DATAXFER_INIT_ARG 0 - -#define dataxfer_init(arg) 0 -#define dataxfer_add_item(handle, host, cache, bytes, tocache) \ - if (tocache) memcpy((PUCHAR)(cache), (PUCHAR)(host), bytes); \ - else memcpy((PUCHAR)(host), (PUCHAR)(cache), bytes) -#define dataxfer_exec(handle, done, tag) done(_VBUS_P tag, 0) -#define dataxfer_poll() - - -typedef void (* HPTLIBAPI xor_done_fn)(_VBUS_ARG void *tag, int result); - - -#define XOR_STACK_VAR -#define XOR_INIT_ARG 0 - -/* DoXor1, DoXor2 provided by platform dependent code */ -void HPTLIBAPI DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes); -void HPTLIBAPI DoXor2(ULONG *p0, ULONG *p2, UINT nBytes); -#define max_xor_way 2 -#define xor_init(arg) 0 -#define xor_add_item(handle, dest, src, nsrc, bytes) \ - do {\ - if (((void**)src)[0]==dest)\ - DoXor2((PULONG)(dest), ((PULONG *)src)[1], bytes);\ - else\ - DoXor1((PULONG)(dest), ((PULONG *)src)[0], ((PULONG *)src)[1], bytes);\ - } while(0) -#define xor_exec(handle, done, tag) done(_VBUS_P tag, 0) -#define xor_poll() - - -/* set before calling init_raid5_memory */ -extern UINT num_raid5_pages; - -/* called by init.c */ -extern void HPTLIBAPI init_raid5_memory(_VBUS_ARG0); -extern void HPTLIBAPI free_raid5_memory(_VBUS_ARG0); - -/* asynchronous flush, may be called periodly */ -extern void HPTLIBAPI flush_stripe_cache(_VBUS_ARG0); -extern void HPTLIBAPI flush_raid5_async(PVDevice pArray, DPC_PROC done, void *arg); - -/* synchronous function called at shutdown */ -extern int HPTLIBAPI flush_raid5(PVDevice pArray); - -extern void HPTLIBAPI raid5_free(_VBUS_ARG PVDevice pArray); - -struct free_heap_block { - struct free_heap_block *next; -}; - -#ifndef LIST_H_INCLUDED -struct list_head { - struct list_head *next, *prev; -}; -#endif - -struct free_page { - struct free_page *link; -}; - -struct r5_global_data { - int enable_write_back; - struct list_head inactive_list; - struct list_head dirty_list; - struct list_head active_list; -#ifdef R5_CONTIG_CACHE - BUS_ADDR page_base_phys; - PUCHAR page_base_virt; - PUCHAR page_current; -#endif - struct free_heap_block *free_heap_slots[8]; - struct free_page *free_pages; - UINT num_free_pages; - UINT active_stripes; - UINT num_flushing; - PCommand cache_wait_list; -}; - - -#endif diff --git a/sys/contrib/dev/hptmv/readme.txt b/sys/contrib/dev/hptmv/readme.txt deleted file mode 100644 index 67c681067e07..000000000000 --- a/sys/contrib/dev/hptmv/readme.txt +++ /dev/null @@ -1,96 +0,0 @@ -RocketRAID 182x Driver for FreeBSD -Copyright (C) 2003-2004 HighPoint Technologies, Inc. All rights reserved. - -############################################################################# -Revision History: - - v1.1 2004-9-23 - Fix activity LED problem. - Cleanup diagnostic code. - - v1.01 2004-5-24 - First source code release - -############################################################################# - -1. Overview ---------------------- - This package contains FreeBSD driver source code for HighPoint RocketRAID - 182x SATA controller. - - NO WARRANTY - - THE DRIVER SOURCE CODE HIGHPOINT PROVIDED IS FREE OF CHARGE, AND THERE IS - NO WARRANTY FOR THE PROGRAM. THERE ARE NO RESTRICTIONS ON THE USE OF THIS - FREE SOURCE CODE. HIGHPOINT DOES NOT PROVIDE ANY TECHNICAL SUPPORT IF THE - CODE HAS BEEN CHANGED FROM ORIGINAL SOURCE CODE. - - LIMITATION OF LIABILITY - - IN NO EVENT WILL HIGHPOINT BE LIABLE FOR DIRECT, INDIRECT, SPECIAL, - INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OF OR - INABILITY TO USE THIS PRODUCT OR DOCUMENTATION, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGES. IN PARTICULAR, HIGHPOINT SHALL NOT HAVE - LIABILITY FOR ANY HARDWARE, SOFTWARE, OR DATA STORED USED WITH THE - PRODUCT, INCLUDING THE COSTS OF REPAIRING, REPLACING, OR RECOVERING - SUCH HARDWARE, OR DATA. - -2. Build the driver ---------------------- - 1) Install kernel source package and building tools. - - 2) Extract the driver files to somewhere. - - 3) Run "make" to build the driver. - - -3. Using the driver ---------------------- - 1) Copy the driver module to /modules/ (FreeBSD 4.x) or /boot/kernel/ - (FreeBSD 5.x). - - 2) The driver can't be loaded by kldload command on a running system. - Please load the driver during system booting stage. e.g: - - BTX loader 1.00 BTX version is 1.01 - Console: internal video/keyboard - BIOS driver A: is disk0 - BIOS driver C: is disk2 - BIOS 636kB/74512kB available memory - - FreeBSD/i386 bootstrap loader, Revision 0.8 - (mailto:jkh@narf.osd.bsdi.com, Sat Apr 21 08:46:19 GMT 2001) - Loading /boot/defaults/loader.conf - /kernel text=0x24f1db data=0x3007ec+0x2062c - - - Hit [Enter] to boot immediagely, or any other key for command prompt. - Booting [kernel] in 9 seconds¡­ - - <-- press SPACE key here - Type '?' for a list of commands, 'help' for more detailed help. - ok load hptmv - /modules/hptmv.ko text=0xf571 data=0x2c8+0x254 - ok autoboot - - Please refer to the installation guide in HighPoint FreeBSD driver release - package for more information. - - -############################################################################# -Technical support and service - - If you have questions about installing or using your HighPoint product, - check the user's guide or readme file first, and you will find answers to - most of your questions here. If you need further assistance, please - contact us. We offer the following support and information services: - - 1) The HighPoint Web Site provides information on software upgrades, - answers to common questions, and other topics. The Web Site is - available from Internet 24 hours a day, 7 days a week, at - http://www.highpoint-tech.com. - - 2) For technical support, send e-mail to support@highpoint-tech.com - - NOTE: Before you send an e-mail, please visit our Web Site - (http://www.highpoint-tech.com) to check if there is a new or - updated device driver for your system. diff --git a/sys/contrib/dev/hptmv/vdevice.h b/sys/contrib/dev/hptmv/vdevice.h deleted file mode 100644 index a25822195f35..000000000000 --- a/sys/contrib/dev/hptmv/vdevice.h +++ /dev/null @@ -1,280 +0,0 @@ -/* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef _VDEVICE_H_ -#define _VDEVICE_H_ - -/*************************************************************************** - * Description: virtual device header - ***************************************************************************/ - -typedef struct _VDevice -{ - UCHAR VDeviceType; - UCHAR vf_bootmark: 1; /* is boot device? */ - UCHAR vf_bootable: 1; /* has active partition */ - UCHAR vf_online: 1; /* is usable? */ - UCHAR vf_cache_disk: 1; /* Cache enabled */ - UCHAR vf_format_v2: 1; /* old array block */ - UCHAR vf_freed: 1; /* memory free */ - UCHAR reserve1; - UCHAR bSerialNumber; /* valid if pParent!=0 */ - - PVDevice pParent; /* parent array */ - PVBus pVBus; /* vbus this device located. Must not be NULL. */ - - LBA_T VDeviceCapacity; /* number of blocks */ - - LBA_T LockedLba; - USHORT LockedSectors; - USHORT ActiveRequests; - PCommand LockWaitList; - void (* HPTLIBAPI QuiesceAction)(_VBUS_ARG void *arg); - void *QuiesceArg; - void (* HPTLIBAPI flush_callback)(_VBUS_ARG void *arg); - void *flush_callback_arg; - - -#if defined(_RAID5N_) - struct stripe **CacheEntry; - struct range_lock *range_lock; -#endif - - void (* HPTLIBAPI pfnSendCommand)(_VBUS_ARG PCommand pCmd); /* call this to send a command to a VDevice */ - void (* HPTLIBAPI pfnDeviceFailed)(_VBUS_ARG PVDevice pVDev); /* call this when a VDevice failed */ - - union { -#ifdef SUPPORT_ARRAY - RaidArray array; -#endif - Device disk; - } u; - -} VDevice; - -#define ARRAY_VDEV_SIZE ((UINT)(ULONG_PTR)&((PVDevice)0)->u+sizeof(RaidArray)) -#define DISK_VDEV_SIZE ((UINT)(ULONG_PTR)&((PVDevice)0)->u+sizeof(Device)) - -#define Map2pVDevice(pDev) ((PVDevice)((UINT_PTR)pDev - (UINT)(UINT_PTR)&((PVDevice)0)->u.disk)) - -/* - * bUserDeviceMode - */ -#define MEMBER_NOT_SET_MODE 0x5F - -/* - * arrayType - */ -#define VD_SPARE 0 -#define VD_REMOVABLE 1 -#define VD_ATAPI 2 -#define VD_SINGLE_DISK 3 - -#define VD_JBOD 4 /* JBOD */ -#define VD_RAID_0 5 /* RAID 0 stripe */ -#define VD_RAID_1 6 /* RAID 1 mirror */ -#define VD_RAID_3 7 /* RAID 3 */ -#define VD_RAID_5 8 /* RAID 5 */ -#define VD_MAX_TYPE 8 - -#ifdef SUPPORT_ARRAY -#define mIsArray(pVDev) (pVDev->VDeviceType>VD_SINGLE_DISK) -#else -#define mIsArray(pVDev) 0 -#endif - -extern void (* HPTLIBAPI pfnSendCommand[])(_VBUS_ARG PCommand pCmd); -extern void (* HPTLIBAPI pfnDeviceFailed[])(_VBUS_ARG PVDevice pVDev); -void HPTLIBAPI fOsDiskFailed(_VBUS_ARG PVDevice pVDev); -void HPTLIBAPI fDeviceSendCommand(_VBUS_ARG PCommand pCmd); -void HPTLIBAPI fSingleDiskFailed(_VBUS_ARG PVDevice pVDev); - -/*************************************************************************** - * Description: RAID Adapter - ***************************************************************************/ - -typedef struct _VBus { - /* pVDevice[] may be non-continuous */ - PVDevice pVDevice[MAX_VDEVICE_PER_VBUS]; - - UINT nInstances; - PChipInstance pChipInstance[MAX_CHIP_IN_VBUS]; - - void * OsExt; /* for OS private use */ - - - int serial_mode; - int next_active; - int working_devs; - - - - PCommand pFreeCommands; - DPC_ROUTINE PendingRoutines[MAX_PENDING_ROUTINES]; - int PendingRoutinesFirst, PendingRoutinesLast; - DPC_ROUTINE IdleRoutines[MAX_IDLE_ROUTINES]; - int IdleRoutinesFirst, IdleRoutinesLast; - -#ifdef SUPPORT_ARRAY - PVDevice pFreeArrayLink; - BYTE _ArrayTables[MAX_ARRAY_PER_VBUS * ARRAY_VDEV_SIZE]; -#endif - - -#ifdef _RAID5N_ - struct r5_global_data r5; -#endif - -} VBus; - -/* - * Array members must be on same VBus. - * The platform dependent part shall select one of the following strategy. - */ -#ifdef SET_VBUS_FOR_EACH_IRQ -#define CHIP_ON_SAME_VBUS(pChip1, pChip2) ((pChip1)->bChipIntrNum==(pChip2)->bChipIntrNum) -#elif defined(SET_VBUS_FOR_EACH_CONTROLLER) -#define CHIP_ON_SAME_VBUS(pChip1, pChip2) \ - ((pChip1)->pci_bus==(pChip2)->pci_bus && (pChip1)->pci_dev==(pChip2)->pci_dev) -#elif defined(SET_VBUS_FOR_EACH_FUNCTION) -#define CHIP_ON_SAME_VBUS(pChip1, pChip2) \ - ((pChip1)->pci_bus==(pChip2)->pci_bus && (pChip1)->pci_dev==(pChip2)->pci_dev && (pChip1)->pci_func==(pChip2)->pci_func) -#else -#error You must set one vbus setting -#endif - -#define FOR_EACH_CHANNEL_ON_VBUS(_pVBus, _pChan) \ - for (_pChan=pChanStart; _pChanpChipInstance->pVBus!=_pVBus) ; else - -#define FOR_EACH_DEV_ON_VBUS(pVBus, pVDev, i) \ - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) \ - if ((pVDev=pVBus->pVDevice[i])==0) continue; else - -#define FOR_EACH_DEV_ON_ALL_VBUS(pVBus, pVDev, i) \ - for(pVBus = gVBus; pVBus < &gVBus[MAX_VBUS]; pVBus++) \ - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) \ - if ((pVDev=pVBus->pVDevice[i])==0) continue; else - -#define FOR_EACH_ARRAY_ON_ALL_VBUS(pVBus, pArray, i) \ - for(pVBus = gVBus; pVBus < &gVBus[MAX_VBUS]; pVBus++) \ - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) \ - if ((pArray=((PVDevice)&pVBus->_ArrayTables[i*ARRAY_VDEV_SIZE]))->u.array.dArStamp==0) continue; else - -/*************************************************************************** - * Description: the functions called by IDE layer - ***************************************************************************/ -#ifdef SUPPORT_ARRAY -#define IdeRegisterDevice fCheckArray -#else -void HPTLIBAPI IdeRegisterDevice(PDevice pDev); -#endif - -/*************************************************************************** - * Description: the functions OS must provided - ***************************************************************************/ - -void OsSetDeviceTable(PDevice pDevice, PIDENTIFY_DATA pIdentify); - -/* - * allocate and free data structure - */ -PChannel fGetChannelTable(void); -PDevice fGetDeviceTable(void); -#define OsGetChannelTable(x, y) fGetChannelTable() -#define OsGetDeviceTable(x, y) fGetDeviceTable() -void OsReturnTable(PDevice pDevice); -/*************************************************************************** - * Description: the functions Prototype - ***************************************************************************/ -/* - * vdevice.c - */ -int Initialize(void); -int InitializeAllChips(void); -void InitializeVBus(PVBus pVBus); -void fRegisterChip(PChipInstance pChip); -void __fRegisterVDevices(PVBus pVBus); -void fRegisterVDevices(void); -void HPTLIBAPI UnregisterVDevice(PVDevice); -void HPTLIBAPI fCheckBootable(PVDevice pVDev); -void HPTLIBAPI fFlushVDev(PVDevice pVDev); -void HPTLIBAPI fFlushVDevAsync(PVDevice pVDev, DPC_PROC done, void *arg); -void HPTLIBAPI fShutdownVDev(PVDevice pVDev); -void HPTLIBAPI fResetVBus(_VBUS_ARG0); -void HPTLIBAPI fCompleteAllCommandsSynchronously(PVBus _vbus_p); - -#define RegisterVDevice(pVDev) -#define OsRegisterDevice(pVDev) -#define OsUnregisterDevice(pVDev) - -#ifdef SUPPORT_VBUS_CONFIG -void VBus_Config(PVBus pVBus, char *str); -#else -#define VBus_Config(pVBus, str) -#endif - -#pragma pack(1) -struct fdisk_partition_table -{ - UCHAR bootid; /* bootable? 0=no, 128=yes */ - UCHAR beghead; /* beginning head number */ - UCHAR begsect; /* beginning sector number */ - UCHAR begcyl; /* 10 bit nmbr, with high 2 bits put in begsect */ - UCHAR systid; /* Operating System type indicator code */ - UCHAR endhead; /* ending head number */ - UCHAR endsect; /* ending sector number */ - UCHAR endcyl; /* also a 10 bit nmbr, with same high 2 bit trick */ - UINT relsect; /* first sector relative to start of disk */ - UINT numsect; /* number of sectors in partition */ -}; - -typedef struct _Master_Boot_Record -{ - UCHAR bootinst[446]; /* space to hold actual boot code */ - struct fdisk_partition_table parts[4]; - USHORT signature; /* set to 0xAA55 to indicate PC MBR format */ -} -Master_Boot_Record, *PMaster_Boot_Record; - -#ifndef SUPPORT_ARRAY -/* TODO: move it later */ -#ifdef __BIG_ENDIAN_BITFIELD -typedef DWORD TIME_RECORD; -#else -typedef struct _TIME_RECORD { - UINT seconds:6; /* 0 - 59 */ - UINT minutes:6; /* 0 - 59 */ - UINT month:4; /* 1 - 12 */ - UINT hours:6; /* 0 - 59 */ - UINT day:5; /* 1 - 31 */ - UINT year:5; /* 0=2000, 31=2031 */ -} TIME_RECORD; -#endif -#endif - -#pragma pack() -#endif diff --git a/sys/dev/hptmv/access601.h b/sys/dev/hptmv/access601.h index 54e1902b687d..57acf8f5e4d8 100644 --- a/sys/dev/hptmv/access601.h +++ b/sys/dev/hptmv/access601.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef _ACCESS601_H_ #define _ACCESS601_H_ diff --git a/sys/dev/hptmv/array.h b/sys/dev/hptmv/array.h index 29e0a9bbd3f2..104eb9b94275 100644 --- a/sys/dev/hptmv/array.h +++ b/sys/dev/hptmv/array.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef _ARRAY_H_ diff --git a/sys/dev/hptmv/atapi.h b/sys/dev/hptmv/atapi.h index a46c1148c9ce..f6dda77a5cb3 100644 --- a/sys/dev/hptmv/atapi.h +++ b/sys/dev/hptmv/atapi.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef _ATAPI_H_ diff --git a/sys/dev/hptmv/command.h b/sys/dev/hptmv/command.h index 0b03e155dc19..dbc0bd67ce7d 100644 --- a/sys/dev/hptmv/command.h +++ b/sys/dev/hptmv/command.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef _COMMAND_H_ #define _COMMAND_H_ diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c index e20ef55d8daa..9ef289e99ac6 100644 --- a/sys/dev/hptmv/gui_lib.c +++ b/sys/dev/hptmv/gui_lib.c @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ /* * gui_lib.c diff --git a/sys/dev/hptmv/hptproc.c b/sys/dev/hptmv/hptproc.c index e05798f1eb74..dc43129ec82b 100644 --- a/sys/dev/hptmv/hptproc.c +++ b/sys/dev/hptmv/hptproc.c @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ /* * hptproc.c sysctl support diff --git a/sys/dev/hptmv/ioctl.c b/sys/dev/hptmv/ioctl.c index 2cfe97912c28..0f9f71d49b47 100644 --- a/sys/dev/hptmv/ioctl.c +++ b/sys/dev/hptmv/ioctl.c @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ /* * ioctl.c ioctl interface implementation diff --git a/sys/dev/hptmv/mvSata.h b/sys/dev/hptmv/mvSata.h index 486f64ffa8f7..4a5c75c81d60 100644 --- a/sys/dev/hptmv/mvSata.h +++ b/sys/dev/hptmv/mvSata.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef __INCmvSatah #define __INCmvSatah diff --git a/sys/dev/hptmv/mvStorageDev.h b/sys/dev/hptmv/mvStorageDev.h index a5f3eb945a89..8b9895874926 100644 --- a/sys/dev/hptmv/mvStorageDev.h +++ b/sys/dev/hptmv/mvStorageDev.h @@ -22,7 +22,9 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. - */ + * + * $FreeBSD$ + * #ifndef __INCmvStorageDevh #define __INCmvStorageDevh diff --git a/sys/dev/hptmv/raid5n.h b/sys/dev/hptmv/raid5n.h index a590b91a6030..07101c8f2650 100644 --- a/sys/dev/hptmv/raid5n.h +++ b/sys/dev/hptmv/raid5n.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifdef _RAID5N_ diff --git a/sys/dev/hptmv/readme.txt b/sys/dev/hptmv/readme.txt index 67c681067e07..df03e97efe81 100644 --- a/sys/dev/hptmv/readme.txt +++ b/sys/dev/hptmv/readme.txt @@ -1,5 +1,6 @@ RocketRAID 182x Driver for FreeBSD Copyright (C) 2003-2004 HighPoint Technologies, Inc. All rights reserved. +$FreeBSD$ ############################################################################# Revision History: diff --git a/sys/dev/hptmv/vdevice.h b/sys/dev/hptmv/vdevice.h index a25822195f35..c9a613618548 100644 --- a/sys/dev/hptmv/vdevice.h +++ b/sys/dev/hptmv/vdevice.h @@ -22,6 +22,8 @@ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. + * + * $FreeBSD$ */ #ifndef _VDEVICE_H_ diff --git a/sys/modules/hptmv/Makefile b/sys/modules/hptmv/Makefile index a444cd66a9e4..29c2e25a28c7 100644 --- a/sys/modules/hptmv/Makefile +++ b/sys/modules/hptmv/Makefile @@ -4,8 +4,8 @@ # # $FreeBSD$ -HPTMV= ${.CURDIR}/../../contrib/dev/hptmv -.PATH: ${.CURDIR}/../../dev/hptmv ${HPTMV} +HPTMV= ${.CURDIR}/../../dev/hptmv +.PATH: ${HPTMV} KMOD= hptmv SRCS= opt_scsi.h opt_cam.h -- cgit v1.3 From f7f3900b9fc4d895fb7d5be8ba7627729375793c Mon Sep 17 00:00:00 2001 From: Scott Long Date: Wed, 2 Mar 2005 15:13:37 +0000 Subject: Clean up the botching of the previous repo-copy. Reference the included headers from the correct location. Submitted by: Tai-hwa Liang --- sys/dev/hptmv/entry.c | 2 +- sys/dev/hptmv/global.h | 14 +++++++------- sys/dev/hptmv/gui_lib.c | 2 +- sys/dev/hptmv/hptproc.c | 2 +- sys/dev/hptmv/ioctl.c | 2 +- sys/dev/hptmv/mvStorageDev.h | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'sys/dev/hptmv/gui_lib.c') diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c index 0e42f6ed0c6e..504ac5bff79a 100644 --- a/sys/dev/hptmv/entry.c +++ b/sys/dev/hptmv/entry.c @@ -44,7 +44,7 @@ #include #include #include -#include +#include #ifdef DEBUG #ifdef DEBUG_LEVEL diff --git a/sys/dev/hptmv/global.h b/sys/dev/hptmv/global.h index 3f8d4dd7ae3b..90c62aea90d1 100644 --- a/sys/dev/hptmv/global.h +++ b/sys/dev/hptmv/global.h @@ -29,8 +29,8 @@ #define _GLOBAL_H_ #include -#include -#include +#include +#include #define COMPANY "HighPoint Technologies, Inc." #define COPYRIGHT "(c) 2000-2004. HighPoint Technologies, Inc." @@ -203,11 +203,11 @@ extern void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param); UCHAR ptr##__buf[512]; \ type ptr=(type)ptr##__buf -#include -#include -#include -#include -#include +#include +#include +#include +#include +#include int HPTLIBAPI fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer); void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode); diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c index 9ef289e99ac6..41ab69a518fb 100644 --- a/sys/dev/hptmv/gui_lib.c +++ b/sys/dev/hptmv/gui_lib.c @@ -45,7 +45,7 @@ #include #include #include -#include +#include static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap); static int hpt_get_controller_count(void); diff --git a/sys/dev/hptmv/hptproc.c b/sys/dev/hptmv/hptproc.c index dc43129ec82b..1c4fb90b0082 100644 --- a/sys/dev/hptmv/hptproc.c +++ b/sys/dev/hptmv/hptproc.c @@ -38,7 +38,7 @@ #include #include #include -#include +#include int hpt_rescan_all(void); diff --git a/sys/dev/hptmv/ioctl.c b/sys/dev/hptmv/ioctl.c index 0f9f71d49b47..c75c98fd1942 100644 --- a/sys/dev/hptmv/ioctl.c +++ b/sys/dev/hptmv/ioctl.c @@ -36,7 +36,7 @@ #include #include #include -#include +#include #pragma pack(1) diff --git a/sys/dev/hptmv/mvStorageDev.h b/sys/dev/hptmv/mvStorageDev.h index 8b9895874926..5d533fedb866 100644 --- a/sys/dev/hptmv/mvStorageDev.h +++ b/sys/dev/hptmv/mvStorageDev.h @@ -24,7 +24,7 @@ * SUCH DAMAGE. * * $FreeBSD$ - * + */ #ifndef __INCmvStorageDevh #define __INCmvStorageDevh -- cgit v1.3 From 14f1a8cc086dce23cf113f16d983161486da97a4 Mon Sep 17 00:00:00 2001 From: David Schultz Date: Fri, 18 Mar 2005 05:43:34 +0000 Subject: Don't read past the end of pVDevice[]. (Previously, we would iterate twice as many times as there were entries in the array.) Spotted by: Ted Unangst using the Coverity Prevent static analysis tool Reviewed by: scottl --- sys/dev/hptmv/gui_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'sys/dev/hptmv/gui_lib.c') diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c index 41ab69a518fb..19fd2f8362fa 100644 --- a/sys/dev/hptmv/gui_lib.c +++ b/sys/dev/hptmv/gui_lib.c @@ -1257,7 +1257,7 @@ int hpt_default_ioctl(_VBUS_ARG while(pAdapter != 0) { pVBus = &pAdapter->VBus; - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) + for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { if(!(pTop = pVBus->pVDevice[i])) continue; #if MAX_VBUS>1 -- cgit v1.3 From 53f5bec08c5419fa69543f30087b47479847f996 Mon Sep 17 00:00:00 2001 From: Xin LI Date: Thu, 6 Oct 2005 18:47:58 +0000 Subject: MFC Import of the new version of the HPTMV driver from Highpoint. The major change here is the support for amd64, as well as possible support for PAE. Many thanks to Highpoint for continuing to support FreeBSD. Obtained from: Steve Chang @ Highpoint Merged revisions: | 1.3 dev/hptmv/access601.h | 1.1 dev/hptmv/amd64-elf.raid.o.uu | 1.3 dev/hptmv/array.h | 1.3 dev/hptmv/atapi.h | 1.3 dev/hptmv/command.h | 1.9+1.10 dev/hptmv/entry.c | 1.4 dev/hptmv/global.h | 1.5 dev/hptmv/gui_lib.c | 1.3 dev/hptmv/hptintf.h | 1.6 dev/hptmv/hptproc.c | 1.5 dev/hptmv/i386-elf.raid.o.uu | 1.5 dev/hptmv/ioctl.c | 1.3 dev/hptmv/mv.c | 1.4 dev/hptmv/mvOs.h | 1.3 dev/hptmv/mvSata.h | 1.4 dev/hptmv/mvStorageDev.h | 1.5 dev/hptmv/osbsd.h | 1.3 dev/hptmv/raid5n.h | 1.3 dev/hptmv/readme.txt | 1.3 dev/hptmv/vdevice.h | 1.4 modules/hptmv/Makefile Approved by: re (scottl) --- sys/amd64/conf/GENERIC | 1 + sys/amd64/conf/NOTES | 2 +- sys/conf/files.amd64 | 10 + sys/dev/hptmv/access601.h | 2 +- sys/dev/hptmv/array.h | 14 +- sys/dev/hptmv/atapi.h | 31 +- sys/dev/hptmv/command.h | 2 +- sys/dev/hptmv/entry.c | 2880 ++++++++++++++++++-------------------- sys/dev/hptmv/global.h | 109 +- sys/dev/hptmv/gui_lib.c | 80 +- sys/dev/hptmv/hptintf.h | 68 +- sys/dev/hptmv/hptproc.c | 104 +- sys/dev/hptmv/i386-elf.raid.o.uu | 2669 ++++++++++++++++++----------------- sys/dev/hptmv/ioctl.c | 81 +- sys/dev/hptmv/mv.c | 74 +- sys/dev/hptmv/mvOs.h | 108 +- sys/dev/hptmv/mvSata.h | 2 +- sys/dev/hptmv/mvStorageDev.h | 2 +- sys/dev/hptmv/osbsd.h | 292 ++-- sys/dev/hptmv/raid5n.h | 7 +- sys/dev/hptmv/readme.txt | 145 +- sys/dev/hptmv/vdevice.h | 6 +- sys/modules/Makefile | 1 + sys/modules/hptmv/Makefile | 19 +- 24 files changed, 3389 insertions(+), 3320 deletions(-) (limited to 'sys/dev/hptmv/gui_lib.c') diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 3575ad4c3efd..afe55f50a570 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -118,6 +118,7 @@ device amr # AMI MegaRAID device arcmsr # Areca SATA II RAID device ciss # Compaq Smart RAID 5* device dpt # DPT Smartcache III, IV - See NOTES for options +device hptmv # Highpoint RocketRAID 182x device iir # Intel Integrated RAID device ips # IBM (Adaptec) ServeRAID device mly # Mylex AcceleRAID/eXtremeRAID diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES index facd111bf18e..a4f06343b54d 100644 --- a/sys/amd64/conf/NOTES +++ b/sys/amd64/conf/NOTES @@ -278,7 +278,7 @@ device aacp # SCSI Passthrough interface (optional, CAM required) # # Highpoint RocketRAID 182x. This is really just software RAID on a # Marvell SATA chip. -#device hptmv # Broken, i386-only binary. +device hptmv # # IBM (now Adaptec) ServeRAID controllers diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64 index a1b201fa4425..f37c62b8415f 100644 --- a/sys/conf/files.amd64 +++ b/sys/conf/files.amd64 @@ -68,6 +68,11 @@ os+%DIKED-nve.h optional nve pci \ no-implicit-rule no-obj before-depend \ clean "os+%DIKED-nve.h" # +hptmvraid.o optional hptmv \ + dependency "$S/dev/hptmv/amd64-elf.raid.o.uu" \ + compile-with "uudecode < $S/dev/hptmv/amd64-elf.raid.o.uu" \ + no-implicit-rule +# amd64/acpica/OsdEnvironment.c optional acpi amd64/acpica/acpi_machdep.c optional acpi amd64/acpica/acpi_wakeup.c optional acpi @@ -151,6 +156,11 @@ dev/fdc/fdc.c optional fdc dev/fdc/fdc_acpi.c optional fdc dev/fdc/fdc_isa.c optional fdc isa dev/fdc/fdc_pccard.c optional fdc pccard +dev/hptmv/entry.c optional hptmv +dev/hptmv/mv.c optional hptmv +dev/hptmv/gui_lib.c optional hptmv +dev/hptmv/hptproc.c optional hptmv +dev/hptmv/ioctl.c optional hptmv dev/hwpmc/hwpmc_amd.c optional hwpmc dev/hwpmc/hwpmc_piv.c optional hwpmc dev/hwpmc/hwpmc_x86.c optional hwpmc diff --git a/sys/dev/hptmv/access601.h b/sys/dev/hptmv/access601.h index 57acf8f5e4d8..26eaab283b95 100644 --- a/sys/dev/hptmv/access601.h +++ b/sys/dev/hptmv/access601.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/hptmv/array.h b/sys/dev/hptmv/array.h index 104eb9b94275..14d627af5832 100644 --- a/sys/dev/hptmv/array.h +++ b/sys/dev/hptmv/array.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -62,6 +62,7 @@ typedef struct _RaidArray UCHAR reserve1; ULONG dArStamp; /* array ID. all disks in a array has same ID */ + ULONG failedStamp; /* stamp for failed member */ USHORT bStripeWitch; /* = (1 << BlockSizeShift) */ USHORT rf_broken: 1; @@ -83,7 +84,7 @@ typedef struct _RaidArray USHORT CriticalMembers; /* tell which member is critial */ UCHAR last_read; /* for RAID 1 load banlancing */ - UCHAR pad1; + UCHAR PrivateFlag1; LBA_T RebuildSectors; /* how many sectors is OK (LBA on member disk) */ @@ -151,7 +152,9 @@ typedef struct _ArrayDescript #define ArrayDescript_3_1_size 512 UCHAR bCheckSum31; /* new check sum */ - UCHAR reserve2[2]; + UCHAR PrivateFlag1; /* private */ + UCHAR reserve1; + #ifdef __BIG_ENDIAN_BITFIELD UCHAR df_read_ahead: 1; /* enable read ahead */ UCHAR df_read_ahead_set: 1; @@ -178,8 +181,13 @@ typedef struct _ArrayDescript } levelex[2]; + ULONG failedStamp; /* array stamp for failed memebr */ + } ArrayDescript; +/* report an error if ArrayDescript size exceed 512 */ +typedef char ArrayDescript_size_should_not_exceed_512[512-sizeof(ArrayDescript)]; + #pragma pack() /* Signature */ diff --git a/sys/dev/hptmv/atapi.h b/sys/dev/hptmv/atapi.h index f6dda77a5cb3..b00100a900e9 100644 --- a/sys/dev/hptmv/atapi.h +++ b/sys/dev/hptmv/atapi.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -267,39 +267,66 @@ typedef struct _ATAPI_REGISTERS_1 { #define ATAPI_FORMAT_UNIT 0x24 #define ATAPI_INQUIRY 0x12 #define ATAPI_MODE_SELECT 0x15 +#define ATAPI_RELEASE6 0x17 #define ATAPI_MODE_SENSE 0x1A #define ATAPI_START_STOP_UNIT 0x1B #define ATAPI_LOAD_UNLOAD 0x1B +#define ATAPI_RECEIVE_DIAGNOSTIC 0x1C +#define ATAPI_SEND_DIAGNOSTIC 0x1D #define ATAPI_MEDIUM_REMOVAL 0x1E +#define ATAPI_READ_FORMAT_CAPACITY 0x23 #define ATAPI_READ_CAPACITY 0x25 #define ATAPI_READ 0x28 #define ATAPI_WRITE 0x2A #define ATAPI_SEEK 0x2B +#define ATAPI_ERASE 0x2C #define ATAPI_VERIFY 0x2F +#define ATAPI_WRITE_VERIFY 0x2E +#define ATAPI_SYNCHRONIZE_CACHE 0x35 +#define ATAPI_LOCK_CACHE 0x36 +#define ATAPI_COMPARE 0x39 +#define ATAPI_WRITE_BUFFER 0x3B #define ATAPI_READ_DATA_BUFF 0x3C #define ATAPI_READ_SUB_CHANNEL 0x42 #define ATAPI_READ_TOC 0x43 #define ATAPI_READ_HEADER 0x44 +#define ATAPI_PLAY_AUDIO10 0x45 #define ATAPI_GET_CONFIGURATION 0x46 #define ATAPI_PLAY_AUDIO_MSF 0x47 #define ATAPI_GET_EVENT_STATUS_NOTIFICATION 0x4A #define ATAPI_PAUSE_RESUME 0x4B +#define ATAPI_LOG_SELECT 0x4C +#define ATAPI_LOG_SENSE 0x4D #define ATAPI_STOP_PLAY_SCAN 0x4E #define ATAPI_READ_DISK_INFORMATION 0x51 #define ATAPI_READ_TRACK_INFORMATION 0x52 +#define ATAPI_RESERVE_TRACK_RZONE 0x53 +#define ATAPI_SEND_OPC_INFORMATION 0x54 #define ATAPI_MODE_SELECT10 0x55 +#define ATAPI_RELEASE10 0x57 +#define ATAPI_REPAIR_ZONE 0x58 #define ATAPI_MODE_SENSE10 0x5A #define ATAPI_CLOSE_TRACK_SESSION 0x5B #define ATAPI_READ_BUFFER_CAPACITY 0x5C +#define ATAPI_SEND_CUE_SHEET 0x5D #define ATAPI_BLANK_COMMAND 0xA1 /*Provide the ability to erase any part of a CD-RW disc.*/ +#define ATAPI_SEND_EVENT 0xA2 /* add for DVD */ +#define ATAPI_SEND_KEY 0xA3 /* add for DVD */ #define ATAPI_REPORT_KEY 0xA4 #define ATAPI_PLAY_AUDIO 0xA5 +#define ATAPI_LOAD_UNLOAD_MEDIUM 0xA6 +#define ATAPI_SET_READ_AHEAD 0xA7 #define ATAPI_READ12 0xA8 #define ATAPI_READ_DVD_STRUCTURE 0xAD +#define ATAPI_WRITE12 0xAA +#define ATAPI_GET_PERFORM_NOTIFICATION 0xAC /* add for DVD-RW */ +#define ATAPI_SET_STREAM 0xB6 /* add for DVD-RW */ #define ATAPI_READ_CD_MSF 0xB9 -#define ATAPI_SET_CD_SPEED 0xBB +#define ATAPI_SCAN 0xBA +#define ATAPI_SET_SPEED 0xBB /* no payload */ #define ATAPI_MECHANISM_STATUS 0xBD #define ATAPI_READ_CD 0xBE +#define ATAPI_SEND_DVD_STRUCTURE 0xBF #define ATAPI_SET_CDRW_SPEED 0xDA /*WindowsXP need*/ #define MODE_DSP_WRITE_PROTECT 0x80 diff --git a/sys/dev/hptmv/command.h b/sys/dev/hptmv/command.h index dbc0bd67ce7d..12eb694af81d 100644 --- a/sys/dev/hptmv/command.h +++ b/sys/dev/hptmv/command.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/hptmv/entry.c b/sys/dev/hptmv/entry.c index fa2d41d698b4..6b7631e2db37 100644 --- a/sys/dev/hptmv/entry.c +++ b/sys/dev/hptmv/entry.c @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,6 +25,7 @@ * * $FreeBSD$ */ + #include #include #include @@ -38,41 +39,85 @@ #include #include +#if (__FreeBSD_version >= 500000) +#include +#include +#endif + +#if (__FreeBSD_version >= 500000) #include #include +#else +#include +#include +#include +#include +#include +#endif + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif #include #include #include #include + #ifdef DEBUG #ifdef DEBUG_LEVEL int hpt_dbg_level = DEBUG_LEVEL; -#else +#else int hpt_dbg_level = 0; #endif #endif #define MV_ERROR printf + /* * CAM SIM entry points */ -static int hpt_probe(device_t dev); -static int hpt_attach(device_t dev); -static int hpt_detach(device_t dev); -static int hpt_shutdown(device_t dev); -static void hpt_poll(struct cam_sim *sim); -static void hpt_intr(void *arg); -static void hpt_action(struct cam_sim *sim, union ccb *ccb); -static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); -static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); -static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); -static void ccb_done(union ccb *ccb); -static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); -static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); -static void launch_worker_thread(void); -static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; +static int hpt_probe (device_t dev); +static void launch_worker_thread(void); +static int hpt_attach(device_t dev); +static int hpt_detach(device_t dev); +static int hpt_shutdown(device_t dev); +static void hpt_poll(struct cam_sim *sim); +static void hpt_intr(void *arg); +static void hpt_async(void *callback_arg, u_int32_t code, struct cam_path *path, void *arg); +static void hpt_action(struct cam_sim *sim, union ccb *ccb); + +static device_method_t driver_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, hpt_probe), + DEVMETHOD(device_attach, hpt_attach), + DEVMETHOD(device_detach, hpt_detach), + +/* DEVMETHOD(device_shutdown, hpt_shutdown), */ + { 0, 0 } +}; + +static driver_t hpt_pci_driver = { + __str(PROC_DIR_NAME), + driver_methods, + sizeof(IAL_ADAPTER_T) +}; + +static devclass_t hpt_devclass; + +#define __DRIVER_MODULE(p1, p2, p3, p4, p5, p6) DRIVER_MODULE(p1, p2, p3, p4, p5, p6) +__DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); + +#define ccb_ccb_ptr spriv_ptr0 +#define ccb_adapter ccb_h.spriv_ptr1 + +static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev); +static void HPTLIBAPI OsSendCommand (_VBUS_ARG union ccb * ccb); +static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd); +static void ccb_done(union ccb *ccb); +static void hpt_queue_ccb(union ccb **ccb_Q, union ccb *ccb); +static void hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb); static void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter); static void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); static void handleEdmaError(_VBUS_ARG PCommand pCmd); @@ -85,8 +130,6 @@ static void hptmv_handle_event_connect(void *data); static int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum); static void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel); static int hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel); -static void hpt_async(void *callback_arg, u_int32_t code, - struct cam_path *path, void *arg); static int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical); static MV_BOOLEAN CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, @@ -101,6 +144,7 @@ static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, IAL_ADAPTER_T *gIal_Adapter = 0; IAL_ADAPTER_T *pCurAdapter = 0; +static MV_SATA_CHANNEL gMvSataChannels[MAX_VBUS][MV_SATA_CHANNELS_NUM]; typedef struct st_HPT_DPC { IAL_ADAPTER_T *pAdapter; @@ -115,37 +159,46 @@ static ST_HPT_DPC DpcQueue[MAX_DPC]; static int DpcQueue_First=0; static int DpcQueue_Last = 0; -static device_method_t driver_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, hpt_probe), - DEVMETHOD(device_attach, hpt_attach), - DEVMETHOD(device_detach, hpt_detach), - { 0, 0 } -}; - -static driver_t hpt_pci_driver = { - __str(PROC_DIR_NAME), - driver_methods, - sizeof(IAL_ADAPTER_T) -}; - -static devclass_t hpt_devclass; +char DRIVER_VERSION[] = "v1.12 (" __DATE__ " " __TIME__ ")"; -DRIVER_MODULE(PROC_DIR_NAME, pci, hpt_pci_driver, hpt_devclass, 0, 0); -MODULE_DEPEND(PROC_DIR_NAME, cam, 1, 1, 1); +#if (__FreeBSD_version >= 500000) +static struct mtx driver_lock; +intrmask_t lock_driver() +{ -intrmask_t -lock_driver() + intrmask_t spl = 0; + mtx_lock_spin(&driver_lock); + return spl; +} +void unlock_driver(intrmask_t spl) +{ + mtx_unlock_spin(&driver_lock); +} +#else +static int driver_locked = 0; +intrmask_t lock_driver() { intrmask_t spl = splcam(); +loop: + while (driver_locked) + tsleep(&driver_locked, PRIBIO, "hptlck", hz); + atomic_add_int(&driver_locked, 1); + if (driver_locked>1) { + atomic_subtract_int(&driver_locked, 1); + goto loop; + } return spl; } -void -unlock_driver(intrmask_t spl) +void unlock_driver(intrmask_t spl) { + atomic_subtract_int(&driver_locked, 1); + if (driver_locked==0) { + wakeup(&driver_locked); + } splx(spl); } +#endif /******************************************************************************* * Name: hptmv_free_channel @@ -160,25 +213,33 @@ unlock_driver(intrmask_t spl) static void hptmv_free_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) { - PVDevice pVDev = &(pAdapter->VDevices[channelNum]); - _VBUS_INST(&pAdapter->VBus); - HPT_ASSERT(channelNum < MV_SATA_CHANNELS_NUM); - pAdapter->mvSataAdapter.sataChannel[channelNum] = NULL; +} - if(pVDev->vf_online) - { - pVDev->u.disk.df_on_line = 0; - pVDev->vf_online = 0; - if (pVDev->pfnDeviceFailed) { - CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, - pVDev); - } +static void failDevice(PVDevice pVDev) +{ + PVBus _vbus_p = pVDev->pVBus; + IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; + + pVDev->u.disk.df_on_line = 0; + pVDev->vf_online = 0; + if (pVDev->pfnDeviceFailed) + CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, pVDev); + + fNotifyGUI(ET_DEVICE_REMOVED, pVDev); + +#ifndef FOR_DEMO + if (pAdapter->ver_601==2 && !pAdapter->beeping) { + pAdapter->beeping = 1; + BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); + set_fail_led(&pAdapter->mvSataAdapter, pVDev->u.disk.mv->channelNumber, 1); } +#endif } int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel); +/*void fDeviceSendCommand(_VBUS_ARG PCommand pCmd); */ static void handleEdmaError(_VBUS_ARG PCommand pCmd) @@ -186,10 +247,6 @@ handleEdmaError(_VBUS_ARG PCommand pCmd) PDevice pDevice = &pCmd->pVDevice->u.disk; MV_SATA_ADAPTER * pSataAdapter = pDevice->mv->mvSataAdapter; - MV_ERROR("Reset channel\n"); - - MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber); - /*now no other cmds on this channel*/ if (!pDevice->df_on_line) { KdPrint(("Device is offline")); pCmd->Result = RETURN_BAD_DEVICE; @@ -198,26 +255,30 @@ handleEdmaError(_VBUS_ARG PCommand pCmd) } if (pCmd->RetryCount++>5) { - pDevice->df_on_line = 0; - pCmd->pVDevice->vf_online = 0; - if (pCmd->pVDevice->pfnDeviceFailed) - CallWhenIdle(_VBUS_P - (DPC_PROC)pCmd->pVDevice->pfnDeviceFailed, - pCmd->pVDevice); - fNotifyGUI(ET_DEVICE_REMOVED, Map2pVDevice(pDevice)); + hpt_printk(("too many retries on channel(%d)\n", pDevice->mv->channelNumber)); +failed: + failDevice(pCmd->pVDevice); pCmd->Result = RETURN_IDE_ERROR; CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); return; } - /* retry the command */ + + /* reset the channel and retry the command */ + if (MvSataResetChannel(pSataAdapter, pDevice->mv->channelNumber)) + goto failed; + + fNotifyGUI(ET_DEVICE_ERROR, Map2pVDevice(pDevice)); + + hpt_printk(("Retry on channel(%d)\n", pDevice->mv->channelNumber)); fDeviceSendCommand(_VBUS_P pCmd); } /**************************************************************** * Name: hptmv_init_channel * - * Description: allocate request and response queues for the EDMA of - * the given channel and sets other fields. + * Description: allocate request and response queues for the EDMA of the + * given channel and sets other fields. + * * Parameters: * pAdapter - pointer to the emulated adapter data structure * channelNum - channel number. @@ -237,58 +298,49 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) return -1; } - pMvSataChannel = - &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; + pMvSataChannel = &gMvSataChannels[pAdapter->mvSataAdapter.adapterId][channelNum]; pAdapter->mvSataAdapter.sataChannel[channelNum] = pMvSataChannel; pMvSataChannel->channelNumber = channelNum; pMvSataChannel->lba48Address = MV_FALSE; pMvSataChannel->maxReadTransfer = MV_FALSE; - pMvSataChannel->requestQueue = - (struct mvDmaRequestQueueEntry *) - (pAdapter->requestsArrayBaseAlignedAddr + - (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); - req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + - (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); + pMvSataChannel->requestQueue = (struct mvDmaRequestQueueEntry *) + (pAdapter->requestsArrayBaseAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE)); + req_dma_addr = pAdapter->requestsArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_REQUEST_QUEUE_SIZE); - KdPrint(("requestQueue addr is 0x%lX", (u_long)req_dma_addr)); + KdPrint(("requestQueue addr is 0x%llX", (HPT_U64)(ULONG_PTR)req_dma_addr)); /* check the 1K alignment of the request queue*/ if (req_dma_addr & 0x3ff) { - MV_ERROR("RR182x[%d]: request queue allocated not 1 K aligned," - " dma_addr=%lx channel=%d\n", - pAdapter->mvSataAdapter.adapterId,(u_long)req_dma_addr, - channelNum); + MV_ERROR("RR182x[%d]: request queue allocated isn't 1 K aligned," + " dma_addr=%llx channel=%d\n", pAdapter->mvSataAdapter.adapterId, + (HPT_U64)(ULONG_PTR)req_dma_addr, channelNum); return -1; } pMvSataChannel->requestQueuePciLowAddress = req_dma_addr; pMvSataChannel->requestQueuePciHiAddress = 0; KdPrint(("RR182x[%d,%d]: request queue allocated: 0x%p", - pAdapter->mvSataAdapter.adapterId, channelNum, - pMvSataChannel->requestQueue)); - pMvSataChannel->responseQueue = - (struct mvDmaResponseQueueEntry *) - (pAdapter->responsesArrayBaseAlignedAddr + - (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); - rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + - (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); + pAdapter->mvSataAdapter.adapterId, channelNum, + pMvSataChannel->requestQueue)); + pMvSataChannel->responseQueue = (struct mvDmaResponseQueueEntry *) + (pAdapter->responsesArrayBaseAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE)); + rsp_dma_addr = pAdapter->responsesArrayBaseDmaAlignedAddr + (channelNum * MV_EDMA_RESPONSE_QUEUE_SIZE); /* check the 256 alignment of the response queue*/ if (rsp_dma_addr & 0xff) { - MV_ERROR("RR182x[%d,%d]: response queue allocated not 256 byte" - " aligned, dma_addr=%lx\n", - pAdapter->mvSataAdapter.adapterId, channelNum, - (u_long)rsp_dma_addr); + MV_ERROR("RR182x[%d,%d]: response queue allocated isn't 256 byte " + "aligned, dma_addr=%llx\n", + pAdapter->mvSataAdapter.adapterId, channelNum, (HPT_U64)(ULONG_PTR)rsp_dma_addr); return -1; } pMvSataChannel->responseQueuePciLowAddress = rsp_dma_addr; pMvSataChannel->responseQueuePciHiAddress = 0; KdPrint(("RR182x[%d,%d]: response queue allocated: 0x%p", - pAdapter->mvSataAdapter.adapterId, channelNum, - pMvSataChannel->responseQueue)); + pAdapter->mvSataAdapter.adapterId, channelNum, + pMvSataChannel->responseQueue)); pAdapter->mvChannel[channelNum].online = MV_TRUE; return 0; @@ -297,10 +349,10 @@ hptmv_init_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) /****************************************************************************** * Name: hptmv_parse_identify_results * - * Description: this functions parses the identify command results, - * checks that the connected deives can be accesed by - * RR182x EDMA, and updates the channel stucture - * accordingly. + * Description: this functions parses the identify command results, checks + * that the connected deives can be accesed by RR182x EDMA, + * and updates the channel stucture accordingly. + * * Parameters: pMvSataChannel, pointer to the channel data structure. * * Returns: =0 ->success, < 0 ->failure. @@ -312,40 +364,49 @@ hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) MV_U16 *iden = pMvSataChannel->identifyDevice; /*LBA addressing*/ - if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) { + if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x200)) + { KdPrint(("IAL Error in IDENTIFY info: LBA not supported\n")); return -1; - } else { + } + else + { KdPrint(("%25s - %s\n", "Capabilities", "LBA supported")); } /*DMA support*/ - if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) { + if (! (iden[IDEN_CAPACITY_1_OFFSET] & 0x100)) + { KdPrint(("IAL Error in IDENTIFY info: DMA not supported\n")); return -1; - } else { + } + else + { KdPrint(("%25s - %s\n", "Capabilities", "DMA supported")); } /* PIO */ - if ((iden[IDEN_VALID] & 2) == 0) { - KdPrint(("IAL Error in IDENTIFY info: not able to find PIO " - "mode\n")); + if ((iden[IDEN_VALID] & 2) == 0) + { + KdPrint(("IAL Error in IDENTIFY info: not able to find PIO mode\n")); return -1; } KdPrint(("%25s - 0x%02x\n", "PIO modes supported", iden[IDEN_PIO_MODE_SPPORTED] & 0xff)); /*UDMA*/ - if ((iden[IDEN_VALID] & 4) == 0) { - KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA " - "mode\n")); + if ((iden[IDEN_VALID] & 4) == 0) + { + KdPrint(("IAL Error in IDENTIFY info: not able to find UDMA mode\n")); return -1; } /* 48 bit address */ - if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) { + if ((iden[IDEN_SUPPORTED_COMMANDS2] & 0x400)) + { KdPrint(("%25s - %s\n", "LBA48 addressing", "supported")); pMvSataChannel->lba48Address = MV_TRUE; - } else { + } + else + { KdPrint(("%25s - %s\n", "LBA48 addressing", "Not supported")); pMvSataChannel->lba48Address = MV_FALSE; } @@ -355,14 +416,11 @@ hptmv_parse_identify_results(MV_SATA_CHANNEL *pMvSataChannel) static void init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) { - PVDevice pVDev; - MV_SATA_CHANNEL *pMvSataChannel; - MV_U16_PTR IdentifyData; + PVDevice pVDev = &pAdapter->VDevices[channel]; + MV_SATA_CHANNEL *pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; + MV_U16_PTR IdentifyData = pMvSataChannel->identifyDevice; - pVDev = &pAdapter->VDevices[channel]; - pMvSataChannel = pAdapter->mvSataAdapter.sataChannel[channel]; pMvSataChannel->outstandingCommands = 0; - IdentifyData = pMvSataChannel->identifyDevice; pVDev->u.disk.mv = pMvSataChannel; pVDev->u.disk.df_on_line = 1; @@ -371,67 +429,54 @@ init_vdev_params(IAL_ADAPTER_T *pAdapter, MV_U8 channel) #ifdef SUPPORT_48BIT_LBA if (pMvSataChannel->lba48Address == MV_TRUE) - pVDev->u.disk.dDeRealCapacity = - ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; + pVDev->u.disk.dDeRealCapacity = ((IdentifyData[101]<<16) | IdentifyData[100]) - 1; else #endif if(IdentifyData[53] & 1) { - pVDev->u.disk.dDeRealCapacity = - (((IdentifyData[58]<<16 | IdentifyData[57]) < - (IdentifyData[61]<<16 | IdentifyData[60])) ? - (IdentifyData[61]<<16 | IdentifyData[60]) : - (IdentifyData[58]<<16 | IdentifyData[57])) - 1; + pVDev->u.disk.dDeRealCapacity = + (((IdentifyData[58]<<16 | IdentifyData[57]) < (IdentifyData[61]<<16 | IdentifyData[60])) ? + (IdentifyData[61]<<16 | IdentifyData[60]) : + (IdentifyData[58]<<16 | IdentifyData[57])) - 1; } else pVDev->u.disk.dDeRealCapacity = - (IdentifyData[61]<<16 | IdentifyData[60]) - 1; + (IdentifyData[61]<<16 | IdentifyData[60]) - 1; pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = - pAdapter->mvChannel[channel].maxPioModeSupported - - MV_ATA_TRANSFER_PIO_0; + pAdapter->mvChannel[channel].maxPioModeSupported - MV_ATA_TRANSFER_PIO_0; if (pAdapter->mvChannel[channel].maxUltraDmaModeSupported!=0xFF) { pVDev->u.disk.bDeUsable_Mode = pVDev->u.disk.bDeModeSetting = - pAdapter->mvChannel[channel].maxUltraDmaModeSupported - - MV_ATA_TRANSFER_UDMA_0 + 8; + pAdapter->mvChannel[channel].maxUltraDmaModeSupported - MV_ATA_TRANSFER_UDMA_0 + 8; } } -static void -device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) +static void device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) { PVDevice pVDev; - MV_SATA_ADAPTER *pMvSataAdapter; - MV_SATA_CHANNEL *pMvSataChannel; - PVBus _vbus_p; - - pMvSataAdapter = &pAdapter->mvSataAdapter; - pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; - _vbus_p = &pAdapter->VBus; - - if (!pMvSataChannel) - return; + MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; + MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelIndex]; + + if (!pMvSataChannel) return; - if (plugged) { + if (plugged) + { pVDev = &(pAdapter->VDevices[channelIndex]); init_vdev_params(pAdapter, channelIndex); - pVDev->VDeviceType = pVDev->u.disk.df_atapi ? VD_ATAPI : - pVDev->u.disk.df_removable_drive ? VD_REMOVABLE : - VD_SINGLE_DISK; + pVDev->VDeviceType = pVDev->u.disk.df_atapi? VD_ATAPI : + pVDev->u.disk.df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; - pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity; + pVDev->VDeviceCapacity = pVDev->u.disk.dDeRealCapacity-SAVE_FOR_RAID_INFO; pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; pVDev->pfnDeviceFailed = pfnDeviceFailed[pVDev->VDeviceType]; pVDev->vf_online = 1; #ifdef SUPPORT_ARRAY - if(pVDev->pParent) { + if(pVDev->pParent) + { int iMember; - - for (iMember = 0; - iMember < pVDev->pParent->u.array.bArnMember; - iMember++) - if ((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) + for(iMember = 0; iMember < pVDev->pParent->u.array.bArnMember; iMember++) + if((PVDevice)pVDev->pParent->u.array.pMember[iMember] == pVDev) pVDev->pParent->u.array.pMember[iMember] = NULL; pVDev->pParent = NULL; } @@ -447,315 +492,291 @@ device_change(IAL_ADAPTER_T *pAdapter , MV_U8 channelIndex, int plugged) } #endif - } else { + } + else + { pVDev = &(pAdapter->VDevices[channelIndex]); - pVDev->u.disk.df_on_line = 0; - pVDev->vf_online = 0; - if (pVDev->pfnDeviceFailed) { - _VBUS_INST(&pAdapter->VBus) - CallWhenIdle(_VBUS_P (DPC_PROC)pVDev->pfnDeviceFailed, - pVDev); - } - fNotifyGUI(ET_DEVICE_REMOVED,pVDev); - -#ifndef FOR_DEMO - if (pAdapter->ver_601==2 && !pAdapter->beeping) { - pAdapter->beeping = 1; - BeepOn(pAdapter->mvSataAdapter.adapterIoBaseAddress); - set_fail_led(&pAdapter->mvSataAdapter, channelIndex, 1); - } -#endif - + failDevice(pVDev); } } static int start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) { - MV_SATA_ADAPTER *pMvSataAdapter; - MV_SATA_CHANNEL *pMvSataChannel; - MV_CHANNEL *pChannelInfo; - MV_U32 udmaMode,pioMode; - - pMvSataAdapter = &pAdapter->mvSataAdapter; - pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; - pChannelInfo = &(pAdapter->mvChannel[channelNum]); + MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; + MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channelNum]; + MV_CHANNEL *pChannelInfo = &(pAdapter->mvChannel[channelNum]); + MV_U32 udmaMode,pioMode; KdPrint(("RR182x [%d]: start channel (%d)", pMvSataAdapter->adapterId, - channelNum)); + channelNum)); /* Software reset channel */ - if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == - MV_FALSE) { + if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) + { MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); return -1; } /* Hardware reset channel */ - if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) { - /* - * If failed, try again - this is when trying to hardreset a - * channel when drive is just spinning up - */ + if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) + { + /* If failed, try again - this is when trying to hardreset a channel */ + /* when drive is just spinning up */ StallExec(5000000); /* wait 5 sec before trying again */ - if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == - MV_FALSE) { - MV_ERROR("RR182x [%d,%d]: failed to perform Hard " - "reset\n", pMvSataAdapter->adapterId, - channelNum); + if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) + { + MV_ERROR("RR182x [%d,%d]: failed to perform Hard reset\n", + pMvSataAdapter->adapterId, channelNum); return -1; } } /* identify device*/ - if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == - MV_FALSE) { - MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify " - "command\n", pMvSataAdapter->adapterId, channelNum); + if (mvStorageDevATAIdentifyDevice(pMvSataAdapter, channelNum) == MV_FALSE) + { + MV_ERROR("RR182x [%d,%d]: failed to perform ATA Identify command\n" + , pMvSataAdapter->adapterId, channelNum); return -1; } - if (hptmv_parse_identify_results(pMvSataChannel)) { - MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify " - "message\n", pMvSataAdapter->adapterId, channelNum); + if (hptmv_parse_identify_results(pMvSataChannel)) + { + MV_ERROR("RR182x [%d,%d]: Error in parsing ATA Identify message\n" + , pMvSataAdapter->adapterId, channelNum); return -1; } /* mvStorageDevATASetFeatures */ /* Disable 8 bit PIO in case CFA enabled */ - if (pMvSataChannel->identifyDevice[86] & 4) { + if (pMvSataChannel->identifyDevice[86] & 4) + { KdPrint(("RR182x [%d]: Disable 8 bit PIO (CFA enabled) \n", - pMvSataAdapter->adapterId)); + pMvSataAdapter->adapterId)); if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, 0, 0, 0) == - MV_FALSE) { - MV_ERROR("RR182x [%d]: channel %d: " - "mvStorageDevATASetFeatures failed\n", - pMvSataAdapter->adapterId, channelNum); + MV_ATA_SET_FEATURES_DISABLE_8_BIT_PIO, 0, + 0, 0, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures" + " failed\n", pMvSataAdapter->adapterId, channelNum); return -1; } } - -#ifdef ENABLE_WRITE_CACHE /* Write cache */ - if (pMvSataChannel->identifyDevice[82] & 0x20) { - if (!(pMvSataChannel->identifyDevice[85] & 0x20)) { - /* if not enabled by default */ - if (mvStorageDevATASetFeatures(pMvSataAdapter, - channelNum, MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, - 0, 0, 0) == MV_FALSE) { - MV_ERROR("RR182x [%d]: channel %d: " - "mvStorageDevATASetFeatures failed\n", - pMvSataAdapter->adapterId, channelNum); +#ifdef ENABLE_WRITE_CACHE + if (pMvSataChannel->identifyDevice[82] & 0x20) + { + if (!(pMvSataChannel->identifyDevice[85] & 0x20)) /* if not enabled by default */ + { + if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_ENABLE_WCACHE, 0, + 0, 0, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n", + pMvSataAdapter->adapterId, channelNum); return -1; } } KdPrint(("RR182x [%d]: channel %d, write cache enabled\n", - pMvSataAdapter->adapterId, channelNum)); - } else { + pMvSataAdapter->adapterId, channelNum)); + } + else + { KdPrint(("RR182x [%d]: channel %d, write cache not supported\n", - pMvSataAdapter->adapterId, channelNum)); + pMvSataAdapter->adapterId, channelNum)); } -#else - /* disable write cache */ - if (pMvSataChannel->identifyDevice[85] & 0x20) { - KdPrint(("RR182x [%d]: channel =%d, disable write cache\n", - pMvSataAdapter->adapterId, channelNum)); - if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, 0, 0, 0) == - MV_FALSE) { - MV_ERROR("RR182x [%d]: channel %d: " - "mvStorageDevATASetFeatures failed\n", - pMvSataAdapter->adapterId, channelNum); - return -1; +#else /* disable write cache */ + { + if (pMvSataChannel->identifyDevice[85] & 0x20) + { + KdPrint(("RR182x [%d]: channel =%d, disable write cache\n", + pMvSataAdapter->adapterId, channelNum)); + if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_DISABLE_WCACHE, 0, + 0, 0, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d]: channel %d: mvStorageDevATASetFeatures failed\n", + pMvSataAdapter->adapterId, channelNum); + return -1; + } } + KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n", + pMvSataAdapter->adapterId, channelNum)); } - KdPrint(("RR182x [%d]: channel=%d, write cache disabled\n", - pMvSataAdapter->adapterId, channelNum)); #endif /* Set transfer mode */ KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_SLOW\n", - pMvSataAdapter->adapterId)); + pMvSataAdapter->adapterId)); if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_TRANSFER, MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == - MV_FALSE) { + MV_ATA_SET_FEATURES_TRANSFER, + MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == + MV_FALSE) + { MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); return -1; } - if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) { + if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 1) + { pioMode = MV_ATA_TRANSFER_PIO_4; - } else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) { + } + else if (pMvSataChannel->identifyDevice[IDEN_PIO_MODE_SPPORTED] & 2) + { pioMode = MV_ATA_TRANSFER_PIO_3; - } else { - MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not " - "supported\n"); + } + else + { + MV_ERROR("IAL Error in IDENTIFY info: PIO modes 3 and 4 not supported\n"); pioMode = MV_ATA_TRANSFER_PIO_SLOW; } KdPrint(("RR182x [%d] Set transfer mode XFER_PIO_4\n", - pMvSataAdapter->adapterId)); + pMvSataAdapter->adapterId)); pAdapter->mvChannel[channelNum].maxPioModeSupported = pioMode; if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_TRANSFER, pioMode, 0, 0, 0) == MV_FALSE) { + MV_ATA_SET_FEATURES_TRANSFER, + pioMode, 0, 0, 0) == MV_FALSE) + { MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); return -1; } udmaMode = MV_ATA_TRANSFER_UDMA_0; - if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) { + if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x40) + { udmaMode = MV_ATA_TRANSFER_UDMA_6; - } else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) { + } + else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x20) + { udmaMode = MV_ATA_TRANSFER_UDMA_5; - } else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) { + } + else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 0x10) + { udmaMode = MV_ATA_TRANSFER_UDMA_4; - } else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) { + } + else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 8) + { udmaMode = MV_ATA_TRANSFER_UDMA_3; - } else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) { + } + else if (pMvSataChannel->identifyDevice[IDEN_UDMA_MODE] & 4) + { udmaMode = MV_ATA_TRANSFER_UDMA_2; } KdPrint(("RR182x [%d] Set transfer mode XFER_UDMA_%d\n", - pMvSataAdapter->adapterId, udmaMode & 0xf)); + pMvSataAdapter->adapterId, udmaMode & 0xf)); pChannelInfo->maxUltraDmaModeSupported = udmaMode; -#if 0 - if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_TRANSFER, udmaMode, 0, 0, 0) == MV_FALSE) { + /*if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_TRANSFER, udmaMode, + 0, 0, 0) == MV_FALSE) + { MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); return -1; - } -#endif + }*/ if (pChannelInfo->maxUltraDmaModeSupported == 0xFF) return TRUE; - - do { - if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_TRANSFER, - pChannelInfo->maxUltraDmaModeSupported, 0, 0, 0) != - MV_FALSE) { + else + do + { + if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_TRANSFER, + pChannelInfo->maxUltraDmaModeSupported, + 0, 0, 0) == MV_FALSE) + { + if (pChannelInfo->maxUltraDmaModeSupported > MV_ATA_TRANSFER_UDMA_0) + { + if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) + { + MV_REG_WRITE_BYTE(pMvSataAdapter->adapterIoBaseAddress, + pMvSataChannel->eDmaRegsOffset + + 0x11c, /* command reg */ + MV_ATA_COMMAND_IDLE_IMMEDIATE); + mvMicroSecondsDelay(10000); + mvSataChannelHardReset(pMvSataAdapter, channelNum); + if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channelNum) == MV_FALSE) + return FALSE; + } + if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == MV_FALSE) + return FALSE; + pChannelInfo->maxUltraDmaModeSupported--; + continue; + } + else return FALSE; + } break; - } + }while (1); - if (pChannelInfo->maxUltraDmaModeSupported <= - MV_ATA_TRANSFER_UDMA_0) { - return FALSE; - } - if (mvStorageDevATASoftResetDevice(pMvSataAdapter, - channelNum) == MV_FALSE) { - mv_reg_write_byte(pMvSataAdapter->adapterIoBaseAddress, - pMvSataChannel->eDmaRegsOffset + 0x11c, - /* command reg */ MV_ATA_COMMAND_IDLE_IMMEDIATE); - mvMicroSecondsDelay(10000); - mvSataChannelHardReset(pMvSataAdapter, channelNum); - if (mvStorageDevATASoftResetDevice(pMvSataAdapter, - channelNum) == MV_FALSE) - return FALSE; - } - if (mvSataChannelHardReset(pMvSataAdapter, channelNum) == - MV_FALSE) - return FALSE; - pChannelInfo->maxUltraDmaModeSupported--; - } while (1); - -#ifdef ENABLE_READ_AHEAD /* Read look ahead */ - if (pMvSataChannel->identifyDevice[82] & 0x40) { - if (!(pMvSataChannel->identifyDevice[85] & 0x40)) { - /* if not enabled by default */ - if (mvStorageDevATASetFeatures(pMvSataAdapter, - channelNum, MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, - 0, 0) == MV_FALSE) { - MV_ERROR("RR182x [%d] channel %d: Set Features " - "failed\n", pMvSataAdapter->adapterId, - channelNum); +#ifdef ENABLE_READ_AHEAD + if (pMvSataChannel->identifyDevice[82] & 0x40) + { + if (!(pMvSataChannel->identifyDevice[85] & 0x40)) /* if not enabled by default */ + { + if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_ENABLE_RLA, 0, 0, + 0, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d] channel %d: Set Features failed\n", + pMvSataAdapter->adapterId, channelNum); return -1; } } KdPrint(("RR182x [%d]: channel=%d, read look ahead enabled\n", - pMvSataAdapter->adapterId, channelNum)); - } else { - KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not " - "supported\n", pMvSataAdapter->adapterId, channelNum)); - } -#else - if (pMvSataChannel->identifyDevice[86] & 0x20) { - KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n", - pMvSataAdapter->adapterId, channelNum)); - if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, - MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, 0, 0) == MV_FALSE) { - MV_ERROR("RR182x [%d]:channel %d: ATA Set Features " - "failed\n", pMvSataAdapter->adapterId, - channelNum); - return -1; - } + pMvSataAdapter->adapterId, channelNum)); } - KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n", - pMvSataAdapter->adapterId, channelNum)); -#endif - -#if 0 - KdPrint(("RR182x [%d]:channel %d, Set standby timer to 200 seconds\n", - pMvSataAdapter->adapterId, channelNum)); - if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channelNum, - MV_NON_UDMA_PROTOCOL_NON_DATA, - MV_FALSE, /* isEXT*/ - NULL, 0, 0, /* features*/ - 40, /*sectorCount*/ - 0, /*lbaLow*/ - 0, /*lbaMid*/ - 0, /*lbaHigh*/ - 0, /*device*/ - MV_ATA_COMMAND_IDLE) == - MV_FALSE) { - MV_ERROR("RR182x [%d]:channel %d: ATA Idle command failed\n", - pMvSataAdapter->adapterId, channelNum); - return -1; + else + { + KdPrint(("RR182x [%d]: channel %d, Read Look Ahead not supported\n", + pMvSataAdapter->adapterId, channelNum)); } +#else + { + if (pMvSataChannel->identifyDevice[86] & 0x20) + { + KdPrint(("RR182x [%d]:channel %d, disable read look ahead\n", + pMvSataAdapter->adapterId, channelNum)); + if (mvStorageDevATASetFeatures(pMvSataAdapter, channelNum, + MV_ATA_SET_FEATURES_DISABLE_RLA, 0, 0, + 0, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d]:channel %d: ATA Set Features failed\n", + pMvSataAdapter->adapterId, channelNum); + return -1; + } + } + KdPrint(("RR182x [%d]:channel %d, read look ahead disabled\n", + pMvSataAdapter->adapterId, channelNum)); + } #endif -#if 0 - /* 2003-9-16 disable TCQ until we have better solution */ - if ((pMvSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & 2)) { - MV_U8 depth; - MV_BOOLEAN result; - - depth = (pMvSataChannel->identifyDevice[IDEN_QUEUE_DEPTH] & - 0x1f) + 1; - KdPrint(("RR182x [%d]: channel %d config EDMA, Queued Mode, " - "queue depth %d\n", pMvSataAdapter->adapterId, - channelNum, depth)); - result = mvSataConfigEdmaMode(pMvSataAdapter, channelNum, - MV_EDMA_MODE_QUEUED, depth); - if (result == MV_FALSE) { - MV_ERROR("RR182x [%d] Error: mvSataConfigEdmaMode " - "failed\n", pMvSataAdapter->adapterId); + + { + KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n", + pMvSataAdapter->adapterId, + channelNum)); + if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, + MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) + { + MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode failed\n", + pMvSataAdapter->adapterId, channelNum); return -1; } - } else { -#endif - KdPrint(("RR182x [%d]: channel %d config EDMA, Non Queued Mode\n", - pMvSataAdapter->adapterId, channelNum)); - if (mvSataConfigEdmaMode(pMvSataAdapter, channelNum, - MV_EDMA_MODE_NOT_QUEUED, 0) == MV_FALSE) { - MV_ERROR("RR182x [%d] channel %d Error: mvSataConfigEdmaMode " - "failed\n", pMvSataAdapter->adapterId, channelNum); - return -1; } - /* Enable EDMA */ - if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) { + if (mvSataEnableChannelDma(pMvSataAdapter, channelNum) == MV_FALSE) + { MV_ERROR("RR182x [%d] Failed to enable DMA, channel=%d\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); return -1; } MV_ERROR("RR182x [%d,%d]: channel started successfully\n", - pMvSataAdapter->adapterId, channelNum); + pMvSataAdapter->adapterId, channelNum); #ifndef FOR_DEMO set_fail_led(pMvSataAdapter, channelNum, 0); @@ -766,91 +787,82 @@ start_channel(IAL_ADAPTER_T *pAdapter, MV_U8 channelNum) static void hptmv_handle_event(void * data, int flag) { - IAL_ADAPTER_T *pAdapter; - MV_SATA_ADAPTER *pMvSataAdapter; - MV_U8 channelIndex; - - pAdapter = (IAL_ADAPTER_T *)data; - pMvSataAdapter = &pAdapter->mvSataAdapter; - - mvOsSemTake(&pMvSataAdapter->semaphore); - for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; - channelIndex++) { - switch(pAdapter->sataEvents[channelIndex]) { - case SATA_EVENT_CHANNEL_CONNECTED: - /* Handle only connects */ - if (flag == 1) - break; - KdPrint(("RR182x [%d,%d]: new device connected\n", - pMvSataAdapter->adapterId, channelIndex)); - hptmv_init_channel(pAdapter, channelIndex); - if (mvSataConfigureChannel( pMvSataAdapter, - channelIndex) == MV_FALSE) { - MV_ERROR("RR182x [%d,%d] Failed to configure\n", - pMvSataAdapter->adapterId, - channelIndex); - hptmv_free_channel(pAdapter, channelIndex); - } else { -#if 0 - mvSataChannelHardReset(pMvSataAdapter, channel); -#endif - if (start_channel( pAdapter, channelIndex)) { - MV_ERROR("RR182x [%d,%d]Failed to start" - " channel\n", - pMvSataAdapter->adapterId, - channelIndex); - hptmv_free_channel(pAdapter, - channelIndex); - } else { - device_change(pAdapter, channelIndex, - TRUE); + IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)data; + MV_SATA_ADAPTER *pMvSataAdapter = &pAdapter->mvSataAdapter; + MV_U8 channelIndex; + +/* mvOsSemTake(&pMvSataAdapter->semaphore); */ + for (channelIndex = 0; channelIndex < MV_SATA_CHANNELS_NUM; channelIndex++) + { + switch(pAdapter->sataEvents[channelIndex]) + { + case SATA_EVENT_CHANNEL_CONNECTED: + /* Handle only connects */ + if (flag == 1) + break; + KdPrint(("RR182x [%d,%d]: new device connected\n", + pMvSataAdapter->adapterId, channelIndex)); + hptmv_init_channel(pAdapter, channelIndex); + if (mvSataConfigureChannel( pMvSataAdapter, channelIndex) == MV_FALSE) + { + MV_ERROR("RR182x [%d,%d] Failed to configure\n", + pMvSataAdapter->adapterId, channelIndex); + hptmv_free_channel(pAdapter, channelIndex); } - } - pAdapter->sataEvents[channelIndex] = - SATA_EVENT_NO_CHANGE; - break; - - case SATA_EVENT_CHANNEL_DISCONNECTED: - /* Handle only disconnects */ - if (flag == 0) + else + { + /*mvSataChannelHardReset(pMvSataAdapter, channel);*/ + if (start_channel( pAdapter, channelIndex)) + { + MV_ERROR("RR182x [%d,%d]Failed to start channel\n", + pMvSataAdapter->adapterId, channelIndex); + hptmv_free_channel(pAdapter, channelIndex); + } + else + { + device_change(pAdapter, channelIndex, TRUE); + } + } + pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; + break; + + case SATA_EVENT_CHANNEL_DISCONNECTED: + /* Handle only disconnects */ + if (flag == 0) + break; + KdPrint(("RR182x [%d,%d]: device disconnected\n", + pMvSataAdapter->adapterId, channelIndex)); + /* Flush pending commands */ + if(pMvSataAdapter->sataChannel[channelIndex]) + { + _VBUS_INST(&pAdapter->VBus) + mvSataFlushDmaQueue (pMvSataAdapter, channelIndex, + MV_FLUSH_TYPE_CALLBACK); + CheckPendingCall(_VBUS_P0); + mvSataRemoveChannel(pMvSataAdapter,channelIndex); + hptmv_free_channel(pAdapter, channelIndex); + pMvSataAdapter->sataChannel[channelIndex] = NULL; + KdPrint(("RR182x [%d,%d]: channel removed\n", + pMvSataAdapter->adapterId, channelIndex)); + if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) + Check_Idle_Call(pAdapter); + } + else + { + KdPrint(("RR182x [%d,%d]: channel already removed!!\n", + pMvSataAdapter->adapterId, channelIndex)); + } + pAdapter->sataEvents[channelIndex] = SATA_EVENT_NO_CHANGE; break; - KdPrint(("RR182x [%d,%d]: device disconnected\n", - pMvSataAdapter->adapterId, channelIndex)); - /* Flush pending commands */ - if(pMvSataAdapter->sataChannel[channelIndex]) { - _VBUS_INST(&pAdapter->VBus) - mvSataFlushDmaQueue (pMvSataAdapter, - channelIndex, MV_FLUSH_TYPE_CALLBACK); - CheckPendingCall(_VBUS_P0); - mvSataRemoveChannel(pMvSataAdapter, - channelIndex); - hptmv_free_channel(pAdapter, channelIndex); - pMvSataAdapter->sataChannel[channelIndex] = - NULL; - KdPrint(("RR182x [%d,%d]: channel removed\n", - pMvSataAdapter->adapterId, - channelIndex)); - if (pAdapter->outstandingCommands==0 && - DPC_Request_Nums==0) - Check_Idle_Call(pAdapter); - } else { - KdPrint(("RR182x [%d,%d]: channel already " - "removed!!\n", - pMvSataAdapter->adapterId, - channelIndex)); - } - pAdapter->sataEvents[channelIndex] = - SATA_EVENT_NO_CHANGE; - break; - case SATA_EVENT_NO_CHANGE: - break; + case SATA_EVENT_NO_CHANGE: + break; - default: - break; + default: + break; } } - mvOsSemRelease(&pMvSataAdapter->semaphore); +/* mvOsSemRelease(&pMvSataAdapter->semaphore); */ } #define EVENT_CONNECT 1 @@ -859,161 +871,122 @@ hptmv_handle_event(void * data, int flag) static void hptmv_handle_event_connect(void *data) { - hptmv_handle_event (data, 0); + hptmv_handle_event (data, 0); } static void hptmv_handle_event_disconnect(void *data) { - hptmv_handle_event (data, 1); + hptmv_handle_event (data, 1); } static MV_BOOLEAN hptmv_event_notify(MV_SATA_ADAPTER *pMvSataAdapter, MV_EVENT_TYPE eventType, - MV_U32 param1, MV_U32 param2) -{ - IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; - - switch (eventType) { - case MV_EVENT_TYPE_SATA_CABLE: - { - MV_U8 channel = param2; - - if (param1 == EVENT_CONNECT) { - pAdapter->sataEvents[channel] = - SATA_EVENT_CHANNEL_CONNECTED; - KdPrint(("RR182x [%d,%d]: device connected event " - "received\n", pMvSataAdapter->adapterId, - channel)); - /* - * Delete previous timers (if multiple drives connected - * in the same time - */ - pAdapter->event_timer_connect = - timeout(hptmv_handle_event_connect, pAdapter,10*hz); - } else if (param1 == EVENT_DISCONNECT) { - pAdapter->sataEvents[channel] = - SATA_EVENT_CHANNEL_DISCONNECTED; - KdPrint(("RR182x [%d,%d]: device disconnected event " - "received \n", pMvSataAdapter->adapterId, - channel)); - device_change(pAdapter, channel, FALSE); - /* - * Delete previous timers (if multiple drives - * disconnected in the same time - */ - pAdapter->event_timer_disconnect = - timeout(hptmv_handle_event_disconnect, pAdapter, - 10*hz); - } else { - MV_ERROR("RR182x: illigal value for param1(%d) at " - "connect/disconect event, host=%d\n", param1, - pMvSataAdapter->adapterId ); - - } - break; - } - case MV_EVENT_TYPE_ADAPTER_ERROR: - KdPrint(("RR182x: DEVICE error event received, pci cause " - "reg=%x, don't how to handle this\n", param1)); - return MV_TRUE; - default: - MV_ERROR("RR182x[%d]: unknown event type (%d)\n", - pMvSataAdapter->adapterId, eventType); - return MV_FALSE; - } - return MV_TRUE; -} - -static void -hptmv_map_req(void *arg, bus_dma_segment_t *segs, int nsegs, int error) + MV_U32 param1, MV_U32 param2) { - dma_addr_t *addr; - - addr = (dma_addr_t *)arg; + IAL_ADAPTER_T *pAdapter = pMvSataAdapter->IALData; - if (error || nsegs != 1) - return; + switch (eventType) + { + case MV_EVENT_TYPE_SATA_CABLE: + { + MV_U8 channel = param2; + + if (param1 == EVENT_CONNECT) + { + pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_CONNECTED; + KdPrint(("RR182x [%d,%d]: device connected event received\n", + pMvSataAdapter->adapterId, channel)); + /* Delete previous timers (if multiple drives connected in the same time */ + pAdapter->event_timer_connect = timeout(hptmv_handle_event_connect, pAdapter, 10*hz); + } + else if (param1 == EVENT_DISCONNECT) + { + pAdapter->sataEvents[channel] = SATA_EVENT_CHANNEL_DISCONNECTED; + KdPrint(("RR182x [%d,%d]: device disconnected event received \n", + pMvSataAdapter->adapterId, channel)); + device_change(pAdapter, channel, FALSE); + /* Delete previous timers (if multiple drives disconnected in the same time */ + /*pAdapter->event_timer_disconnect = timeout(hptmv_handle_event_disconnect, pAdapter, 10*hz); */ + /*It is not necessary to wait, handle it directly*/ + hptmv_handle_event_disconnect(pAdapter); + } + else + { - *addr = segs[0].ds_addr; + MV_ERROR("RR182x: illigal value for param1(%d) at " + "connect/disconect event, host=%d\n", param1, + pMvSataAdapter->adapterId ); - return; + } + } + break; + case MV_EVENT_TYPE_ADAPTER_ERROR: + KdPrint(("RR182x: DEVICE error event received, pci cause " + "reg=%x, don't how to handle this\n", param1)); + return MV_TRUE; + default: + MV_ERROR("RR182x[%d]: unknown event type (%d)\n", + pMvSataAdapter->adapterId, eventType); + return MV_FALSE; + } + return MV_TRUE; } -static int +static int hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) { - if (bus_dmamem_alloc(pAdapter->req_dmat, - (void **)&pAdapter->requestsArrayBaseAddr, BUS_DMA_WAITOK, - &pAdapter->req_map) != 0) { - MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA " - "request queues\n", pAdapter->mvSataAdapter.adapterId); + pAdapter->requestsArrayBaseAddr = (MV_U8 *)contigmalloc(REQUESTS_ARRAY_SIZE, + M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); + if (pAdapter->requestsArrayBaseAddr == NULL) + { + MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA request" + " queues\n", pAdapter->mvSataAdapter.adapterId); return -1; } - - (void)bus_dmamap_load(pAdapter->req_dmat, pAdapter->req_map, - pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, hptmv_map_req, - &pAdapter->requestsArrayBaseDmaAddr, 0); - - pAdapter->requestsArrayBaseAlignedAddr = - pAdapter->requestsArrayBaseAddr; + pAdapter->requestsArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->requestsArrayBaseAddr); + pAdapter->requestsArrayBaseAlignedAddr = pAdapter->requestsArrayBaseAddr; pAdapter->requestsArrayBaseAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; - pAdapter->requestsArrayBaseAlignedAddr = - (MV_U8 *)(((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & - ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); - pAdapter->requestsArrayBaseDmaAlignedAddr = - pAdapter->requestsArrayBaseDmaAddr; + pAdapter->requestsArrayBaseAlignedAddr = (MV_U8 *) + (((ULONG_PTR)pAdapter->requestsArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1)); + pAdapter->requestsArrayBaseDmaAlignedAddr = pAdapter->requestsArrayBaseDmaAddr; pAdapter->requestsArrayBaseDmaAlignedAddr += MV_EDMA_REQUEST_QUEUE_SIZE; - pAdapter->requestsArrayBaseDmaAlignedAddr &= - ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); + pAdapter->requestsArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_REQUEST_QUEUE_SIZE - 1); - if ((pAdapter->requestsArrayBaseDmaAlignedAddr - - pAdapter->requestsArrayBaseDmaAddr) != - (pAdapter->requestsArrayBaseAlignedAddr - - pAdapter->requestsArrayBaseAddr)) { + if ((pAdapter->requestsArrayBaseDmaAlignedAddr - pAdapter->requestsArrayBaseDmaAddr) != + (pAdapter->requestsArrayBaseAlignedAddr - pAdapter->requestsArrayBaseAddr)) + { MV_ERROR("RR182x[%d]: Error in Request Quueues Alignment\n", - pAdapter->mvSataAdapter.adapterId); - bus_dmamap_unload(pAdapter->req_dmat, pAdapter->req_map); - bus_dmamem_free(pAdapter->req_dmat, - pAdapter->requestsArrayBaseAddr, pAdapter->req_map); + pAdapter->mvSataAdapter.adapterId); + contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); return -1; } /* response queues */ - if (bus_dmamem_alloc(pAdapter->resp_dmat, - (void **)&pAdapter->responsesArrayBaseAddr, BUS_DMA_WAITOK, - &pAdapter->resp_map) != 0) { - MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA " - "response queues\n", pAdapter->mvSataAdapter.adapterId); - bus_dmamap_unload(pAdapter->req_dmat, pAdapter->req_map); - bus_dmamem_free(pAdapter->req_dmat, - pAdapter->requestsArrayBaseAddr, pAdapter->req_map); + pAdapter->responsesArrayBaseAddr = (MV_U8 *)contigmalloc(RESPONSES_ARRAY_SIZE, + M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); + if (pAdapter->responsesArrayBaseAddr == NULL) + { + MV_ERROR("RR182x[%d]: Failed to allocate memory for EDMA response" + " queues\n", pAdapter->mvSataAdapter.adapterId); + contigfree(pAdapter->requestsArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); return -1; } - - (void)bus_dmamap_load(pAdapter->resp_dmat, pAdapter->resp_map, - pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, - hptmv_map_req, &pAdapter->responsesArrayBaseDmaAddr, 0); - - pAdapter->responsesArrayBaseAlignedAddr = - pAdapter->responsesArrayBaseAddr; + pAdapter->responsesArrayBaseDmaAddr = fOsPhysicalAddress(pAdapter->responsesArrayBaseAddr); + pAdapter->responsesArrayBaseAlignedAddr = pAdapter->responsesArrayBaseAddr; pAdapter->responsesArrayBaseAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; - pAdapter->responsesArrayBaseAlignedAddr = - (MV_U8 *)(((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & - ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); - pAdapter->responsesArrayBaseDmaAlignedAddr = - pAdapter->responsesArrayBaseDmaAddr; - pAdapter->responsesArrayBaseDmaAlignedAddr += - MV_EDMA_RESPONSE_QUEUE_SIZE; - pAdapter->responsesArrayBaseDmaAlignedAddr &= - ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); - - if ((pAdapter->responsesArrayBaseDmaAlignedAddr - - pAdapter->responsesArrayBaseDmaAddr) != - (pAdapter->responsesArrayBaseAlignedAddr - - pAdapter->responsesArrayBaseAddr)) { + pAdapter->responsesArrayBaseAlignedAddr = (MV_U8 *) + (((ULONG_PTR)pAdapter->responsesArrayBaseAlignedAddr) & ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1)); + pAdapter->responsesArrayBaseDmaAlignedAddr = pAdapter->responsesArrayBaseDmaAddr; + pAdapter->responsesArrayBaseDmaAlignedAddr += MV_EDMA_RESPONSE_QUEUE_SIZE; + pAdapter->responsesArrayBaseDmaAlignedAddr &= ~(ULONG_PTR)(MV_EDMA_RESPONSE_QUEUE_SIZE - 1); + + if ((pAdapter->responsesArrayBaseDmaAlignedAddr - pAdapter->responsesArrayBaseDmaAddr) != + (pAdapter->responsesArrayBaseAlignedAddr - pAdapter->responsesArrayBaseAddr)) + { MV_ERROR("RR182x[%d]: Error in Response Quueues Alignment\n", - pAdapter->mvSataAdapter.adapterId); - hptmv_free_edma_queues(pAdapter); + pAdapter->mvSataAdapter.adapterId); + contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); + contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); return -1; } return 0; @@ -1022,12 +995,8 @@ hptmv_allocate_edma_queues(IAL_ADAPTER_T *pAdapter) static void hptmv_free_edma_queues(IAL_ADAPTER_T *pAdapter) { - bus_dmamap_unload(pAdapter->req_dmat, pAdapter->req_map); - bus_dmamem_free(pAdapter->req_dmat, pAdapter->requestsArrayBaseAddr, - pAdapter->req_map); - bus_dmamap_unload(pAdapter->resp_dmat, pAdapter->resp_map); - bus_dmamem_free(pAdapter->resp_dmat, pAdapter->responsesArrayBaseAddr, - pAdapter->resp_map); + contigfree(pAdapter->requestsArrayBaseAddr, REQUESTS_ARRAY_SIZE, M_DEVBUF); + contigfree(pAdapter->responsesArrayBaseAddr, RESPONSES_ARRAY_SIZE, M_DEVBUF); } static PVOID @@ -1035,8 +1004,7 @@ AllocatePRDTable(IAL_ADAPTER_T *pAdapter) { PVOID ret; if (pAdapter->pFreePRDLink) { - KdPrint(("pAdapter->pFreePRDLink:%p\n", - pAdapter->pFreePRDLink)); + KdPrint(("pAdapter->pFreePRDLink:%p\n",pAdapter->pFreePRDLink)); ret = pAdapter->pFreePRDLink; pAdapter->pFreePRDLink = *(void**)ret; return ret; @@ -1060,7 +1028,7 @@ fRegisterVdevice(IAL_ADAPTER_T *pAdapter) PVBus pVBus; int i,j; - for(i = 0; i < MV_SATA_CHANNELS_NUM; i++) { + for(i=0;iVDevices[i]); pLogical = pPhysical; while (pLogical->pParent) pLogical = pLogical->pParent; @@ -1068,27 +1036,24 @@ fRegisterVdevice(IAL_ADAPTER_T *pAdapter) pPhysical->vf_bootmark = pLogical->vf_bootmark = 0; continue; } - if (pLogical->VDeviceType == VD_SPARE || - pPhysical != fGetFirstChild(pLogical)) + if (pLogical->VDeviceType==VD_SPARE || pPhysical!=fGetFirstChild(pLogical)) continue; pVBus = &pAdapter->VBus; - if(pVBus) { + if(pVBus) + { j=0; - while(j < MAX_VDEVICE_PER_VBUS && pVBus->pVDevice[j]) - j++; - if (j < MAX_VDEVICE_PER_VBUS) { + while(jpVDevice[j]) j++; + if(jpVDevice[j] = pLogical; pLogical->pVBus = pVBus; if (j>0 && pLogical->vf_bootmark) { if (pVBus->pVDevice[0]->vf_bootmark) { fResetBootMark(pLogical); - } else { - do { - pVBus->pVDevice[j] = - pVBus->pVDevice[j-1]; - } while (--j); + } + else { + do { pVBus->pVDevice[j] = pVBus->pVDevice[j-1]; } while (--j); pVBus->pVDevice[0] = pLogical; } } @@ -1100,27 +1065,26 @@ fRegisterVdevice(IAL_ADAPTER_T *pAdapter) PVDevice GetSpareDisk(_VBUS_ARG PVDevice pArray) { - IAL_ADAPTER_T *pAdapter; - ULONG capacity; + IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; + ULONG capacity = LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); ULONG thiscap, maxcap = MAX_LBA_T; PVDevice pVDevice, pFind = NULL; int i; - pAdapter = (IAL_ADAPTER_T *)pArray->pVBus->OsExt; - capacity = - LongDiv(pArray->VDeviceCapacity, pArray->u.array.bArnMember-1); - for (i = 0;i < MV_SATA_CHANNELS_NUM; i++) { + for(i=0;iVDevices[i]; if(!pVDevice) continue; - thiscap = pArray->vf_format_v2 ? - pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; + thiscap = pArray->vf_format_v2? pVDevice->u.disk.dDeRealCapacity : pVDevice->VDeviceCapacity; /* find the smallest usable spare disk */ if (pVDevice->VDeviceType==VD_SPARE && - pVDevice->u.disk.df_on_line && thiscap < maxcap && - thiscap >= capacity) { - maxcap = pVDevice->VDeviceCapacity; - pFind = pVDevice; + pVDevice->u.disk.df_on_line && + thiscap < maxcap && + thiscap >= capacity) + { + maxcap = pVDevice->VDeviceCapacity; + pFind = pVDevice; } } return pFind; @@ -1137,16 +1101,10 @@ fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer) void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) { -#ifndef SIMULATE - MV_SATA_CHANNEL *pSataChannel; - MV_SATA_ADAPTER *pSataAdapter; - MV_U8 channelIndex; + MV_SATA_CHANNEL *pSataChannel = pDev->mv; + MV_SATA_ADAPTER *pSataAdapter = pSataChannel->mvSataAdapter; + MV_U8 channelIndex = pSataChannel->channelNumber; UCHAR mvMode; - - pSataChannel = pDev->mv; - pSataAdapter = pSataChannel->mvSataAdapter; - channelIndex = pSataChannel->channelNumber; - /* 508x don't use MW-DMA? */ if (NewMode>4 && NewMode<8) NewMode = 4; pDev->bDeModeSetting = NewMode; @@ -1164,25 +1122,26 @@ void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode) mvSataFlushDmaQueue (pSataAdapter, channelIndex, MV_FLUSH_TYPE_NONE); if (mvStorageDevATASetFeatures(pSataAdapter, channelIndex, - MV_ATA_SET_FEATURES_TRANSFER, mvMode, 0, 0, 0) == MV_FALSE) { + MV_ATA_SET_FEATURES_TRANSFER, + mvMode, 0, 0, 0) == MV_FALSE) + { KdPrint(("channel %d: Set Features failed\n", channelIndex)); } /* Enable EDMA */ if (mvSataEnableChannelDma(pSataAdapter, channelIndex) == MV_FALSE) KdPrint(("Failed to enable DMA, channel=%d", channelIndex)); -#endif } #ifdef SUPPORT_ARRAY #define IdeRegisterVDevice fCheckArray -#else +#else void IdeRegisterVDevice(PDevice pDev) { PVDevice pVDev = Map2pVDevice(pDev); pVDev->VDeviceType = pDev->df_atapi? VD_ATAPI : - pDev->df_removable_drive ? VD_REMOVABLE : VD_SINGLE_DISK; + pDev->df_removable_drive? VD_REMOVABLE : VD_SINGLE_DISK; pVDev->vf_online = 1; pVDev->VDeviceCapacity = pDev->dDeRealCapacity; pVDev->pfnSendCommand = pfnSendCommand[pVDev->VDeviceType]; @@ -1190,16 +1149,38 @@ IdeRegisterVDevice(PDevice pDev) } #endif +static __inline PBUS_DMAMAP +dmamap_get(struct IALAdapter * pAdapter) +{ + PBUS_DMAMAP p = pAdapter->pbus_dmamap_list; + if (p) + pAdapter->pbus_dmamap_list = p-> next; + return p; +} + +static __inline void +dmamap_put(PBUS_DMAMAP p) +{ + p->next = p->pAdapter->pbus_dmamap_list; + p->pAdapter->pbus_dmamap_list = p; +} + +/*Since mtx not provide the initialize when declare, so we Final init here to initialize the global mtx*/ +#if __FreeBSD_version >= 500000 +static void hpt_init(void *dummy) +{ + mtx_init(&driver_lock, "hptlock", NULL, MTX_SPIN); +} +SYSINIT(hptinit, SI_SUB_CONFIGURE, SI_ORDER_FIRST, hpt_init, NULL); +#endif + static int num_adapters = 0; static int init_adapter(IAL_ADAPTER_T *pAdapter) { - PCommand pCmd; - pPrivCommand prvCmd; PVBus _vbus_p = &pAdapter->VBus; MV_SATA_ADAPTER *pMvSataAdapter; - PUCHAR PRDTable; - int i, channel, rid, error; + int i, channel, rid; PVDevice pVDev; @@ -1207,10 +1188,11 @@ init_adapter(IAL_ADAPTER_T *pAdapter) pAdapter->next = 0; - if(gIal_Adapter == 0) { + if(gIal_Adapter == 0){ gIal_Adapter = pAdapter; pCurAdapter = gIal_Adapter; - } else { + } + else { pCurAdapter->next = pAdapter; pCurAdapter = pAdapter; } @@ -1221,72 +1203,55 @@ init_adapter(IAL_ADAPTER_T *pAdapter) _vbus_p->OsExt = (void *)pAdapter; pMvSataAdapter->IALData = pAdapter; - if (bus_dma_tag_create(NULL, 1, 0, BUS_SPACE_MAXADDR_32BIT, - BUS_SPACE_MAXADDR, NULL, NULL, BUS_SPACE_MAXSIZE_32BIT, - MV_MAX_SEGMENTS, BUS_SPACE_MAXSIZE_32BIT, 0, NULL, NULL, - &pAdapter->parent_dmat) != 0) { - MV_ERROR("RR182x: Failed to create busdma resources\n"); - unlock_driver(oldspl); - return (ENOMEM); - } - - if (bus_dma_tag_create(pAdapter->parent_dmat, PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - REQUESTS_ARRAY_SIZE, 1, REQUESTS_ARRAY_SIZE, 0, NULL, NULL, - &pAdapter->req_dmat) != 0) { - MV_ERROR("RR182x: Failed to create busdma resources\n"); - error = ENOMEM; - goto unregister; - } - - if (bus_dma_tag_create(pAdapter->parent_dmat, PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - RESPONSES_ARRAY_SIZE, 1, RESPONSES_ARRAY_SIZE, 0, NULL, NULL, - &pAdapter->resp_dmat) != 0) { - MV_ERROR("RR182x: Failed to create busdma resources\n"); - error = ENOMEM; - goto unregister; + if (bus_dma_tag_create(NULL,/* parent */ + 4, /* alignment */ + BUS_SPACE_MAXADDR_32BIT+1, /* boundary */ + BUS_SPACE_MAXADDR, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + PAGE_SIZE * (MAX_SG_DESCRIPTORS-1), /* maxsize */ + MAX_SG_DESCRIPTORS, /* nsegments */ + 0x10000, /* maxsegsize */ + BUS_DMA_WAITOK, /* flags */ +#if __FreeBSD_version>502000 + busdma_lock_mutex, /* lockfunc */ + &driver_lock, /* lockfuncarg */ +#endif + &pAdapter->io_dma_parent /* tag */)) + { + return ENXIO;; } - if (bus_dma_tag_create(pAdapter->parent_dmat, 1, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - MAXBSIZE, MV_MAX_SEGMENTS, MAXBSIZE, 0, busdma_lock_mutex, &Giant, - &pAdapter->buf_dmat) != 0) { - MV_ERROR("RR182x: Failed to create busdma resources\n"); - error = ENOMEM; - goto unregister; - } - if (hptmv_allocate_edma_queues(pAdapter)) { + if (hptmv_allocate_edma_queues(pAdapter)) + { MV_ERROR("RR182x: Failed to allocate memory for EDMA queues\n"); - error = ENOMEM; - goto unregister; + unlock_driver(oldspl); + return ENOMEM; } /* also map EPROM address */ rid = 0x10; - if ((pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, - SYS_RES_MEMORY, &rid, 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, - RF_ACTIVE)) == 0) { + if (!(pAdapter->mem_res = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, &rid, + 0, ~0, MV_SATA_PCI_BAR0_SPACE_SIZE+0x40000, RF_ACTIVE)) + || + !(pMvSataAdapter->adapterIoBaseAddress = rman_get_virtual(pAdapter->mem_res))) + { MV_ERROR("RR182x: Failed to remap memory space\n"); - error = ENXIO; - goto unregister; + hptmv_free_edma_queues(pAdapter); + unlock_driver(oldspl); + return ENXIO; + } + else + { + KdPrint(("RR182x: io base address 0x%p\n", pMvSataAdapter->adapterIoBaseAddress)); } - /* - * This field is opaque. Abuse it so that the bus_space functions - * can get the info that they need when called. - */ - pMvSataAdapter->adapterIoBaseAddress = pAdapter; - pAdapter->mem_bsh = rman_get_bushandle(pAdapter->mem_res); - pAdapter->mem_btag = rman_get_bustag(pAdapter->mem_res); - pMvSataAdapter->adapterId = num_adapters++; /* get the revision ID */ - pMvSataAdapter->pciConfigRevisionId = - pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); + pMvSataAdapter->pciConfigRevisionId = pci_read_config(pAdapter->hpt_dev, PCIR_REVID, 1); pMvSataAdapter->pciConfigDeviceId = pci_get_device(pAdapter->hpt_dev); - + /* init RR182x */ pMvSataAdapter->intCoalThre[0]= 1; pMvSataAdapter->intCoalThre[1]= 1; @@ -1297,11 +1262,15 @@ init_adapter(IAL_ADAPTER_T *pAdapter) pMvSataAdapter->pciInterruptMask = 0xd77fe6ul; pMvSataAdapter->mvSataEventNotify = hptmv_event_notify; - if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) { + if (mvSataInitAdapter(pMvSataAdapter) == MV_FALSE) + { MV_ERROR("RR182x[%d]: core failed to initialize the adapter\n", - pMvSataAdapter->adapterId); - error = ENXIO; - goto unregister; + pMvSataAdapter->adapterId); +unregister: + bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, pAdapter->mem_res); + hptmv_free_edma_queues(pAdapter); + unlock_driver(oldspl); + return ENXIO; } pAdapter->ver_601 = pMvSataAdapter->pcbVersion; @@ -1312,103 +1281,98 @@ init_adapter(IAL_ADAPTER_T *pAdapter) /* setup command blocks */ KdPrint(("Allocate command blocks\n")); _vbus_(pFreeCommands) = 0; - pAdapter->pCommandBlocks = malloc(sizeof(struct _Command) * - MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_ZERO | M_WAITOK); - KdPrint(("pCommandBlocks:%p\n", pAdapter->pCommandBlocks)); - - /* - * Gotta cheat here. The _Command struct only gives us a single - * pointer for private data, but we need to store more than that. - * Of course the pCommand retains no type stability, and FreeCommand - * is hidden in the binary object, so gotta track these on our own - * list. - */ - pAdapter->pPrivateBlocks = malloc(sizeof(struct _privCommand) * - MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_ZERO | M_WAITOK); - TAILQ_INIT(&pAdapter->PrivCmdTQH); - - for (i = 0; i < MAX_COMMAND_BLOCKS_FOR_EACH_VBUS; i++) { - pCmd = &pAdapter->pCommandBlocks[i]; - prvCmd = &pAdapter->pPrivateBlocks[i]; - prvCmd->pAdapter = pAdapter; - if ((error = bus_dmamap_create(pAdapter->buf_dmat, 0, - &prvCmd->buf_map)) == 0) { - FreeCommand(_VBUS_P (pCmd)); - FreePrivCommand(pAdapter, prvCmd); - } else - break; + pAdapter->pCommandBlocks = + malloc(sizeof(struct _Command) * MAX_COMMAND_BLOCKS_FOR_EACH_VBUS, M_DEVBUF, M_NOWAIT); + KdPrint(("pCommandBlocks:%p\n",pAdapter->pCommandBlocks)); + if (!pAdapter->pCommandBlocks) { + MV_ERROR("insufficient memory\n"); + goto unregister; } - /* setup PRD Tables */ - KdPrint(("Allocate PRD Tables\n")); - pAdapter->pFreePRDLink = 0; - - if (bus_dma_tag_create(pAdapter->parent_dmat, PAGE_SIZE, 0, - BUS_SPACE_MAXADDR_32BIT, BUS_SPACE_MAXADDR, NULL, NULL, - PRD_ENTRIES_SIZE * PRD_TABLES_FOR_VBUS, 1, - PRD_ENTRIES_SIZE * PRD_TABLES_FOR_VBUS, 0, NULL, NULL, - &pAdapter->prd_dmat) != 0) { - MV_ERROR("RR182x: Failed to create busdma resources\n"); - error = ENOMEM; - goto unregister; + for (i=0; ipCommandBlocks[i])); } - if (bus_dmamem_alloc(pAdapter->prd_dmat, - (void **)&pAdapter->prdTableAddr, BUS_DMA_WAITOK, - &pAdapter->prd_map) != 0) + /*Set up the bus_dmamap*/ + pAdapter->pbus_dmamap = (PBUS_DMAMAP)malloc (sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM, M_DEVBUF, M_NOWAIT); + if(!pAdapter->pbus_dmamap) { + MV_ERROR("insufficient memory\n"); + free(pAdapter->pCommandBlocks, M_DEVBUF); goto unregister; + } - (void)bus_dmamap_load(pAdapter->prd_dmat, pAdapter->prd_map, - pAdapter->prdTableAddr, PRD_ENTRIES_SIZE * PRD_TABLES_FOR_VBUS, - hptmv_map_req, &pAdapter->prdTableDmaAddr, 0); + memset((void *)pAdapter->pbus_dmamap, 0, sizeof(struct _BUS_DMAMAP) * MAX_QUEUE_COMM); + pAdapter->pbus_dmamap_list = 0; + for (i=0; i < MAX_QUEUE_COMM; i++) { + PBUS_DMAMAP pmap = &(pAdapter->pbus_dmamap[i]); + pmap->pAdapter = pAdapter; + dmamap_put(pmap); + if(bus_dmamap_create(pAdapter->io_dma_parent, 0, &pmap->dma_map)) { + MV_ERROR("Can not allocate dma map\n"); + free(pAdapter->pCommandBlocks, M_DEVBUF); + free(pAdapter->pbus_dmamap, M_DEVBUF); + goto unregister; + } + } + /* setup PRD Tables */ + KdPrint(("Allocate PRD Tables\n")); + pAdapter->pFreePRDLink = 0; + + pAdapter->prdTableAddr = (PUCHAR)contigmalloc( + (PRD_ENTRIES_SIZE*PRD_TABLES_FOR_VBUS + 32), M_DEVBUF, M_NOWAIT, 0, 0xffffffff, PAGE_SIZE, 0ul); + KdPrint(("prdTableAddr:%p\n",pAdapter->prdTableAddr)); if (!pAdapter->prdTableAddr) { MV_ERROR("insufficient PRD Tables\n"); - error = ENOMEM; goto unregister; } - - PRDTable = pAdapter->prdTableAddr; - for (i = 0; i < PRD_TABLES_FOR_VBUS; i++) { - KdPrint(("i= %d, pAdapter->pFreePRDLink= %p\n", i, - pAdapter->pFreePRDLink)); - FreePRDTable(pAdapter, PRDTable); - PRDTable += PRD_ENTRIES_SIZE; + pAdapter->prdTableAlignedAddr = (PUCHAR)(((ULONG_PTR)pAdapter->prdTableAddr + 0x1f) & ~(ULONG_PTR)0x1fL); + { + PUCHAR PRDTable = pAdapter->prdTableAlignedAddr; + for (i=0; ipFreePRDLink=%p\n",i,pAdapter->pFreePRDLink)); */ + FreePRDTable(pAdapter, PRDTable); + PRDTable += PRD_ENTRIES_SIZE; + } } /* enable the adapter interrupts */ /* configure and start the connected channels*/ - for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { + for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) + { pAdapter->mvChannel[channel].online = MV_FALSE; if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) - != MV_TRUE) - continue; - - KdPrint(("RR182x[%d]: channel %d is connected\n", - pMvSataAdapter->adapterId, channel)); - - if (hptmv_init_channel(pAdapter, channel) == 0) { - if (mvSataConfigureChannel(pMvSataAdapter, channel) - == MV_FALSE) { - MV_ERROR("RR182x[%d]: Failed to configure " - "channel %d\n", pMvSataAdapter->adapterId, - channel); - hptmv_free_channel(pAdapter, channel); - continue; - } - if (start_channel(pAdapter, channel)) { - MV_ERROR("RR182x[%d]: Failed to start channel, " - "channel=%d\n", pMvSataAdapter->adapterId, - channel); - hptmv_free_channel(pAdapter, channel); + == MV_TRUE) + { + KdPrint(("RR182x[%d]: channel %d is connected\n", + pMvSataAdapter->adapterId, channel)); + + if (hptmv_init_channel(pAdapter, channel) == 0) + { + if (mvSataConfigureChannel(pMvSataAdapter, channel) == MV_FALSE) + { + MV_ERROR("RR182x[%d]: Failed to configure channel" + " %d\n",pMvSataAdapter->adapterId, channel); + hptmv_free_channel(pAdapter, channel); + } + else + { + if (start_channel(pAdapter, channel)) + { + MV_ERROR("RR182x[%d]: Failed to start channel," + " channel=%d\n",pMvSataAdapter->adapterId, + channel); + hptmv_free_channel(pAdapter, channel); + } + pAdapter->mvChannel[channel].online = MV_TRUE; + /* mvSataChannelSetEdmaLoopBackMode(pMvSataAdapter, + channel, + MV_TRUE);*/ + } } - pAdapter->mvChannel[channel].online = MV_TRUE; -#if 0 - mvSataChannelSetEdmaLoopBackMode( - pMvSataAdapter, channel, MV_TRUE); -#endif } KdPrint(("pAdapter->mvChannel[channel].online:%x, channel:%d\n", pAdapter->mvChannel[channel].online, channel)); @@ -1423,9 +1387,7 @@ init_adapter(IAL_ADAPTER_T *pAdapter) KdPrint(("Initialize Devices\n")); for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { - MV_SATA_CHANNEL *pMvSataChannel; - - pMvSataChannel = pMvSataAdapter->sataChannel[channel]; + MV_SATA_CHANNEL *pMvSataChannel = pMvSataAdapter->sataChannel[channel]; if (pMvSataChannel) { init_vdev_params(pAdapter, channel); IdeRegisterVDevice(&pAdapter->VDevices[channel].u.disk); @@ -1446,84 +1408,85 @@ init_adapter(IAL_ADAPTER_T *pAdapter) #if defined(SUPPORT_ARRAY) && defined(_RAID5N_) init_raid5_memory(_VBUS_P0); _vbus_(r5).enable_write_back = 1; - printf("RR182x: RAID5 write-back %s\n", - _vbus_(r5).enable_write_back? "enabled" : "disabled"); + printf("RR182x: RAID5 write-back %s\n", _vbus_(r5).enable_write_back? "enabled" : "disabled"); #endif mvSataUnmaskAdapterInterrupt(pMvSataAdapter); unlock_driver(oldspl); return 0; - -unregister: - if (pAdapter->mem_res != 0) - bus_release_resource(pAdapter->hpt_dev, SYS_RES_MEMORY, rid, - pAdapter->mem_res); - - hptmv_free_edma_queues(pAdapter); - - if (pAdapter->resp_dmat != NULL) - bus_dma_tag_destroy(pAdapter->resp_dmat); - if (pAdapter->req_dmat != NULL) - bus_dma_tag_destroy(pAdapter->req_dmat); - if (pAdapter->buf_dmat != NULL) - bus_dma_tag_destroy(pAdapter->buf_dmat); - if (pAdapter->parent_dmat != NULL) - bus_dma_tag_destroy(pAdapter->parent_dmat); - - unlock_driver(oldspl); - return error; } int MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) { - IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; + IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)pMvSataAdapter->IALData; mvSataDisableChannelDma(pMvSataAdapter, channel); - /* Flush pending commands */ mvSataFlushDmaQueue (pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); /* Software reset channel */ - if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == - MV_FALSE) { + if (mvStorageDevATASoftResetDevice(pMvSataAdapter, channel) == MV_FALSE) + { MV_ERROR("RR182x [%d,%d]: failed to perform Software reset\n", - pMvSataAdapter->adapterId, channel); + pMvSataAdapter->adapterId, channel); + hptmv_free_channel(pAdapter, channel); return -1; } /* Hardware reset channel */ - if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) { - MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA " - "channel\n", pMvSataAdapter->adapterId, channel); + if (mvSataChannelHardReset(pMvSataAdapter, channel)== MV_FALSE) + { + MV_ERROR("RR182x [%d,%d] Failed to Hard reser the SATA channel\n", + pMvSataAdapter->adapterId, channel); hptmv_free_channel(pAdapter, channel); return -1; } - if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == - MV_FALSE) { - MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n", - pMvSataAdapter->adapterId, channel); + if (mvSataIsStorageDeviceConnected(pMvSataAdapter, channel) == MV_FALSE) + { + MV_ERROR("RR182x [%d,%d] Failed to Connect Device\n", + pMvSataAdapter->adapterId, channel); hptmv_free_channel(pAdapter, channel); return -1; - } else { + }else + { + MV_ERROR("channel %d: perform recalibrate command", channel); + if (!mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, + MV_NON_UDMA_PROTOCOL_NON_DATA, + MV_FALSE, + NULL, /* pBuffer*/ + 0, /* count */ + 0, /*features*/ + /* sectorCount */ + 0, + 0, /* lbaLow */ + 0, /* lbaMid */ + /* lbaHigh */ + 0, + 0, /* device */ + /* command */ + 0x10)) + MV_ERROR("channel %d: recalibrate failed", channel); + /* Set transfer mode */ if((mvStorageDevATASetFeatures(pMvSataAdapter, channel, - MV_ATA_SET_FEATURES_TRANSFER, MV_ATA_TRANSFER_PIO_SLOW, 0, - 0, 0) == MV_FALSE) || - (mvStorageDevATASetFeatures(pMvSataAdapter, channel, - MV_ATA_SET_FEATURES_TRANSFER, - pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) - == MV_FALSE) || (mvStorageDevATASetFeatures(pMvSataAdapter, - channel, MV_ATA_SET_FEATURES_TRANSFER, - pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, - 0, 0) == MV_FALSE)) { + MV_ATA_SET_FEATURES_TRANSFER, + MV_ATA_TRANSFER_PIO_SLOW, 0, 0, 0) == MV_FALSE) || + (mvStorageDevATASetFeatures(pMvSataAdapter, channel, + MV_ATA_SET_FEATURES_TRANSFER, + pAdapter->mvChannel[channel].maxPioModeSupported, 0, 0, 0) == MV_FALSE) || + (mvStorageDevATASetFeatures(pMvSataAdapter, channel, + MV_ATA_SET_FEATURES_TRANSFER, + pAdapter->mvChannel[channel].maxUltraDmaModeSupported, 0, 0, 0) == MV_FALSE) ) + { MV_ERROR("channel %d: Set Features failed", channel); hptmv_free_channel(pAdapter, channel); return -1; } /* Enable EDMA */ - if (mvSataEnableChannelDma(pMvSataAdapter, channel)==MV_FALSE) { + if (mvSataEnableChannelDma(pMvSataAdapter, channel) == MV_FALSE) + { MV_ERROR("Failed to enable DMA, channel=%d", channel); hptmv_free_channel(pAdapter, channel); return -1; @@ -1535,31 +1498,23 @@ MvSataResetChannel(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channel) static int fResetActiveCommands(PVBus _vbus_p) { - MV_SATA_ADAPTER *pMvSataAdapter; + MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; MV_U8 channel; - int rtn = 0; - - pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { - if (pMvSataAdapter->sataChannel[channel] && - pMvSataAdapter->sataChannel[channel]->outstandingCommands) - if (MvSataResetChannel(pMvSataAdapter,channel) == -1) - rtn = -1; + if (pMvSataAdapter->sataChannel[channel] && pMvSataAdapter->sataChannel[channel]->outstandingCommands) + MvSataResetChannel(pMvSataAdapter,channel); } - HPT_ASSERT(rtn==0); return 0; } -void -fCompleteAllCommandsSynchronously(PVBus _vbus_p) +void fCompleteAllCommandsSynchronously(PVBus _vbus_p) { UINT cont; ULONG ticks = 0; MV_U8 channel; - MV_SATA_ADAPTER *pMvSataAdapter; + MV_SATA_ADAPTER *pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; MV_SATA_CHANNEL *pMvSataChannel; - pMvSataAdapter = &((IAL_ADAPTER_T *)_vbus_p->OsExt)->mvSataAdapter; do { check_cmds: cont = 0; @@ -1568,21 +1523,19 @@ check_cmds: dataxfer_poll(); xor_poll(); #endif - for (channel = 0; channel < MV_SATA_CHANNELS_NUM; channel++) { + for (channel=0;channel< MV_SATA_CHANNELS_NUM;channel++) { pMvSataChannel = pMvSataAdapter->sataChannel[channel]; - if (pMvSataChannel && - pMvSataChannel->outstandingCommands) { + if (pMvSataChannel && pMvSataChannel->outstandingCommands) + { while (pMvSataChannel->outstandingCommands) { - if (!mvSataInterruptServiceRoutine( - pMvSataAdapter)) { + if (!mvSataInterruptServiceRoutine(pMvSataAdapter)) { StallExec(1000); if (ticks++ > 3000) { - MvSataResetChannel( - pMvSataAdapter, - channel); + MvSataResetChannel(pMvSataAdapter,channel); goto check_cmds; } - } else + } + else ticks = 0; } cont = 1; @@ -1611,24 +1564,29 @@ fResetVBus(_VBUS_ARG0) KdPrint(("fMvResetBus() done")); } +/*No rescan function*/ void fRescanAllDevice(_VBUS_ARG0) { } static MV_BOOLEAN -CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelNum, - MV_COMPLETION_TYPE comp_type, MV_VOID_PTR commandId, MV_U16 responseFlags, - MV_U32 timeStamp, MV_STORAGE_DEVICE_REGISTERS *registerStruct) +CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, + MV_U8 channelNum, + MV_COMPLETION_TYPE comp_type, + MV_VOID_PTR commandId, + MV_U16 responseFlags, + MV_U32 timeStamp, + MV_STORAGE_DEVICE_REGISTERS *registerStruct) { PCommand pCmd = (PCommand) commandId; _VBUS_INST(pCmd->pVDevice->pVBus) if (pCmd->uScratch.sata_param.prdAddr) - FreePRDTable(pMvSataAdapter->IALData, - pCmd->uScratch.sata_param.prdAddr); + FreePRDTable(pMvSataAdapter->IALData,pCmd->uScratch.sata_param.prdAddr); - switch (comp_type) { + switch (comp_type) + { case MV_COMPLETION_TYPE_NORMAL: pCmd->Result = RETURN_SUCCESS; break; @@ -1636,31 +1594,25 @@ CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelNum, pCmd->Result = RETURN_BUS_RESET; break; case MV_COMPLETION_TYPE_ERROR: - MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, " - "flags=%x\n", pMvSataAdapter->adapterId, channelNum, - responseFlags); + MV_ERROR("IAL: COMPLETION ERROR, adapter %d, channel %d, flags=%x\n", + pMvSataAdapter->adapterId, channelNum, responseFlags); if (responseFlags & 4) { - MV_ERROR("ATA regs: error %x, sector count %x, LBA low " - "%x, LBA mid %x, LBA high %x, device %x, " - "status %x\n", registerStruct->errorRegister, - registerStruct->sectorCountRegister, - registerStruct->lbaLowRegister, - registerStruct->lbaMidRegister, - registerStruct->lbaHighRegister, - registerStruct->deviceRegister, - registerStruct->statusRegister); + MV_ERROR("ATA regs: error %x, sector count %x, LBA low %x, LBA mid %x," + " LBA high %x, device %x, status %x\n", + registerStruct->errorRegister, + registerStruct->sectorCountRegister, + registerStruct->lbaLowRegister, + registerStruct->lbaMidRegister, + registerStruct->lbaHighRegister, + registerStruct->deviceRegister, + registerStruct->statusRegister); } - /* - * We can't do handleEdmaError directly here, because - * CommandCompletionCB is called by mv's ISR, if we retry the - * command, than the internel data structure may be destroyed - */ + /*We can't do handleEdmaError directly here, because CommandCompletionCB is called by + * mv's ISR, if we retry the command, than the internel data structure may be destroyed*/ pCmd->uScratch.sata_param.responseFlags = responseFlags; - pCmd->uScratch.sata_param.bIdeStatus = - registerStruct->statusRegister; - pCmd->uScratch.sata_param.errorRegister = - registerStruct->errorRegister; + pCmd->uScratch.sata_param.bIdeStatus = registerStruct->statusRegister; + pCmd->uScratch.sata_param.errorRegister = registerStruct->errorRegister; pCmd->pVDevice->u.disk.QueueLength--; CallAfterReturn(_VBUS_P (DPC_PROC)handleEdmaError,pCmd); return TRUE; @@ -1670,8 +1622,7 @@ CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelNum, return MV_FALSE; } - if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && - pCmd->uScratch.sata_param.cmd_priv > 1) { + if (pCmd->uCmd.Ide.Command == IDE_COMMAND_VERIFY && pCmd->uScratch.sata_param.cmd_priv > 1) { pCmd->uScratch.sata_param.cmd_priv --; return TRUE; } @@ -1683,29 +1634,23 @@ CommandCompletionCB(MV_SATA_ADAPTER *pMvSataAdapter, MV_U8 channelNum, void fDeviceSendCommand(_VBUS_ARG PCommand pCmd) { - MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; + MV_SATA_EDMA_PRD_ENTRY *pPRDTable = 0; MV_SATA_ADAPTER *pMvSataAdapter; MV_SATA_CHANNEL *pMvSataChannel; - IAL_ADAPTER_T *pAdapter; + PVDevice pVDevice = pCmd->pVDevice; + PDevice pDevice = &pVDevice->u.disk; + ULONG Lba = pCmd->uCmd.Ide.Lba; + USHORT nSector = pCmd->uCmd.Ide.nSectors; + MV_QUEUE_COMMAND_RESULT result; MV_QUEUE_COMMAND_INFO commandInfo; - MV_UDMA_COMMAND_PARAMS *pUdmaParams; - MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams; - MV_BOOLEAN is48bit = MV_FALSE; - PVDevice pVDevice; - PDevice pDevice; - ULONG Lba; - USHORT nSector; - MV_U8 channel; - int i=0; - - pVDevice = pCmd->pVDevice; - pDevice = &pVDevice->u.disk; - Lba = pCmd->uCmd.Ide.Lba; - nSector = pCmd->uCmd.Ide.nSectors; - pUdmaParams = &commandInfo.commandParams.udmaCommand; - pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; + MV_UDMA_COMMAND_PARAMS *pUdmaParams = &commandInfo.commandParams.udmaCommand; + MV_NONE_UDMA_COMMAND_PARAMS *pNoUdmaParams = &commandInfo.commandParams.NoneUdmaCommand; + MV_BOOLEAN is48bit = MV_FALSE; + MV_U8 channel; + int i=0; + DECLARE_BUFFER(FPSCAT_GATH, tmpSg); if (!pDevice->df_on_line) { @@ -1719,12 +1664,8 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd) pMvSataChannel = pDevice->mv; pMvSataAdapter = pMvSataChannel->mvSataAdapter; channel = pMvSataChannel->channelNumber; - pAdapter = pMvSataAdapter->IALData; - /* - * Old RAID0 has hidden lba. Remember to clear dDeHiddenLba when - * deleting array! - */ + /* old RAID0 has hidden lba. Remember to clear dDeHiddenLba when delete array! */ Lba += pDevice->dDeHiddenLba; /* check LBA */ if (Lba+nSector-1 > pDevice->dDeRealCapacity) { @@ -1737,7 +1678,8 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd) is48bit = MV_TRUE; } - switch (pCmd->uCmd.Ide.Command) { + switch (pCmd->uCmd.Ide.Command) + { case IDE_COMMAND_READ: case IDE_COMMAND_WRITE: if (pDevice->bDeModeSetting<8) goto pio; @@ -1757,144 +1699,125 @@ fDeviceSendCommand(_VBUS_ARG PCommand pCmd) if (pCmd->pSgTable && pCmd->cf_physical_sg) { FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; - do { - *sg1++=*sg2; - } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); - } else if (!pCmd->pfnBuildSgl || - !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { + do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); + } + else { + if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 0)) { pio: - mvSataDisableChannelDma(pMvSataAdapter, channel); - mvSataFlushDmaQueue(pMvSataAdapter, channel, - MV_FLUSH_TYPE_CALLBACK); - - if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { - FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; - do { - *sg1++=*sg2; - } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); - } else if (!pCmd->pfnBuildSgl || - !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)){ - pCmd->Result = RETURN_NEED_LOGICAL_SG; - goto finish_cmd; - } - - do { - ULONG size; - ULONG_PTR addr = tmpSg->dSgAddress; - - size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; - if (size & 0x1ff) { - pCmd->Result = RETURN_INVALID_REQUEST; - goto finish_cmd; + mvSataDisableChannelDma(pMvSataAdapter, channel); + mvSataFlushDmaQueue(pMvSataAdapter, channel, MV_FLUSH_TYPE_CALLBACK); + + if (pCmd->pSgTable && pCmd->cf_physical_sg==0) { + FPSCAT_GATH sg1=tmpSg, sg2=pCmd->pSgTable; + do { *sg1++=*sg2; } while ((sg2++->wSgFlag & SG_FLAG_EOT)==0); + } + else { + if (!pCmd->pfnBuildSgl || !pCmd->pfnBuildSgl(_VBUS_P pCmd, tmpSg, 1)) { + pCmd->Result = RETURN_NEED_LOGICAL_SG; + goto finish_cmd; + } } - if (mvStorageDevATAExecuteNonUDMACommand( - pMvSataAdapter, channel, - (pCmd->cf_data_out) ? - MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT : - MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, - is48bit, (MV_U16_PTR)addr, - size >> 1, /* count */ - 0, /* features N/A */ - (MV_U16)(size>>9), /*sector count*/ - (MV_U16)((is48bit ? - (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | - (UCHAR)(Lba & 0xFF) ), /*lbalow*/ - (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ - (MV_U16)((Lba >> 16) & 0xFF),/* lbaHig */ - (MV_U8)(0x40 | (is48bit ? 0 : - (UCHAR)(Lba >> 24) & 0xFF )),/* device */ - (MV_U8)(is48bit ? (pCmd->cf_data_in ? - IDE_COMMAND_READ_EXT : - IDE_COMMAND_WRITE_EXT) : - pCmd->uCmd.Ide.Command))==MV_FALSE) { - pCmd->Result = RETURN_IDE_ERROR; - goto finish_cmd; + + do { + ULONG size = tmpSg->wSgSize? tmpSg->wSgSize : 0x10000; + ULONG_PTR addr = tmpSg->dSgAddress; + if (size & 0x1ff) { + pCmd->Result = RETURN_INVALID_REQUEST; + goto finish_cmd; + } + if (mvStorageDevATAExecuteNonUDMACommand(pMvSataAdapter, channel, + (pCmd->cf_data_out)?MV_NON_UDMA_PROTOCOL_PIO_DATA_OUT:MV_NON_UDMA_PROTOCOL_PIO_DATA_IN, + is48bit, + (MV_U16_PTR)addr, + size >> 1, /* count */ + 0, /* features N/A */ + (MV_U16)(size>>9), /*sector count*/ + (MV_U16)( (is48bit? (MV_U16)((Lba >> 16) & 0xFF00) : 0 ) | (UCHAR)(Lba & 0xFF) ), /*lbalow*/ + (MV_U16)((Lba >> 8) & 0xFF), /* lbaMid */ + (MV_U16)((Lba >> 16) & 0xFF),/* lbaHigh */ + (MV_U8)(0x40 | (is48bit ? 0 : (UCHAR)(Lba >> 24) & 0xFF )),/* device */ + (MV_U8)(is48bit ? (pCmd->cf_data_in?IDE_COMMAND_READ_EXT:IDE_COMMAND_WRITE_EXT):pCmd->uCmd.Ide.Command) + )==MV_FALSE) + { + pCmd->Result = RETURN_IDE_ERROR; + goto finish_cmd; + } + Lba += size>>9; + if(Lba & 0xF0000000) is48bit = MV_TRUE; } - Lba += size>>9; - if(Lba & 0xF0000000) is48bit = MV_TRUE; - } - while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); - pCmd->Result = RETURN_SUCCESS; + while ((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); + pCmd->Result = RETURN_SUCCESS; finish_cmd: - mvSataEnableChannelDma(pMvSataAdapter,channel); - CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, - pCmd); - return; + mvSataEnableChannelDma(pMvSataAdapter,channel); + CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); + return; + } } - pPRDTable = AllocatePRDTable(pAdapter); + pPRDTable = (MV_SATA_EDMA_PRD_ENTRY *) AllocatePRDTable(pMvSataAdapter->IALData); KdPrint(("pPRDTable:%p\n",pPRDTable)); if (!pPRDTable) { pCmd->Result = RETURN_DEVICE_BUSY; - CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, - pCmd); + CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); HPT_ASSERT(0); return; } - do { - pPRDTable[i].highBaseAddr = 0; + do{ + pPRDTable[i].highBaseAddr = (sizeof(tmpSg->dSgAddress)>4 ? (MV_U32)(tmpSg->dSgAddress>>32) : 0); pPRDTable[i].flags = (MV_U16)tmpSg->wSgFlag; pPRDTable[i].byteCount = (MV_U16)tmpSg->wSgSize; pPRDTable[i].lowBaseAddr = (MV_U32)tmpSg->dSgAddress; pPRDTable[i].reserved = 0; i++; - } while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); + }while((tmpSg++->wSgFlag & SG_FLAG_EOT)==0); - pUdmaParams->prdLowAddr = pAdapter->prdTableDmaAddr + - ((ULONG)pPRDTable - (ULONG)pAdapter->prdTableAddr); - - if ((pUdmaParams->numOfSectors == 256) && - (pMvSataChannel->lba48Address == MV_FALSE)) { + pUdmaParams->prdLowAddr = (ULONG)fOsPhysicalAddress(pPRDTable); + if ((pUdmaParams->numOfSectors == 256) && (pMvSataChannel->lba48Address == MV_FALSE)) { pUdmaParams->numOfSectors = 0; } pCmd->uScratch.sata_param.prdAddr = (PVOID)pPRDTable; - result = mvSataQueueCommand(pMvSataAdapter, channel, - &commandInfo); + result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); - if (result != MV_QUEUE_COMMAND_RESULT_OK) { + if (result != MV_QUEUE_COMMAND_RESULT_OK) + { queue_failed: - switch (result) { + switch (result) + { case MV_QUEUE_COMMAND_RESULT_BAD_LBA_ADDRESS: - MV_ERROR("IAL Error: Edma Queue command " - "failed. Bad LBA LBA[31:0](0x%08x)\n", - pUdmaParams->lowLBAAddress); + MV_ERROR("IAL Error: Edma Queue command failed. Bad LBA " + "LBA[31:0](0x%08x)\n", pUdmaParams->lowLBAAddress); pCmd->Result = RETURN_IDE_ERROR; break; case MV_QUEUE_COMMAND_RESULT_QUEUED_MODE_DISABLED: - MV_ERROR("IAL Error: Edma Queue command " - "failed. EDMA disabled adapter %d " - "channel %d\n", - pMvSataAdapter->adapterId, channel); + MV_ERROR("IAL Error: Edma Queue command failed. EDMA" + " disabled adapter %d channel %d\n", + pMvSataAdapter->adapterId, channel); mvSataEnableChannelDma(pMvSataAdapter,channel); pCmd->Result = RETURN_IDE_ERROR; break; case MV_QUEUE_COMMAND_RESULT_FULL: - MV_ERROR("IAL Error: Edma Queue command " - "failed. Queue is Full adapter %d " - "channel %d\n", - pMvSataAdapter->adapterId, channel); + MV_ERROR("IAL Error: Edma Queue command failed. Queue is" + " Full adapter %d channel %d\n", + pMvSataAdapter->adapterId, channel); pCmd->Result = RETURN_DEVICE_BUSY; break; case MV_QUEUE_COMMAND_RESULT_BAD_PARAMS: - MV_ERROR("IAL Error: Edma Queue command " - "failed. (Bad Params), pMvSataAdapter:" - " %p, pSataChannel: %p.\n", - pMvSataAdapter, - pMvSataAdapter->sataChannel[channel]); + MV_ERROR("IAL Error: Edma Queue command failed. (Bad " + "Params), pMvSataAdapter: %p, pSataChannel: %p.\n", + pMvSataAdapter, pMvSataAdapter->sataChannel[channel]); pCmd->Result = RETURN_IDE_ERROR; break; default: - MV_ERROR("IAL Error: Bad result value (%d) " - "from queue command\n", result); + MV_ERROR("IAL Error: Bad result value (%d) from queue" + " command\n", result); pCmd->Result = RETURN_IDE_ERROR; } if(pPRDTable) - FreePRDTable(pAdapter, pPRDTable); - CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, - pCmd); + FreePRDTable(pMvSataAdapter->IALData,pPRDTable); + CallAfterReturn(_VBUS_P (DPC_PROC)pCmd->pfnCompletion, pCmd); } pDevice->QueueLength++; return; @@ -1910,40 +1833,35 @@ queue_failed: pCmd->uScratch.sata_param.cmd_priv = 1; if (pMvSataChannel->lba48Address == MV_TRUE){ - pNoUdmaParams->command = - MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; + pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS_EXT; pNoUdmaParams->isEXT = MV_TRUE; - pNoUdmaParams->lbaHigh = - (MV_U16)((Lba & 0xff0000) >> 16); + pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); pNoUdmaParams->lbaLow = - (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); + (MV_U16)(((Lba & 0xff000000) >> 16)| (Lba & 0xff)); pNoUdmaParams->sectorCount = nSector; pNoUdmaParams->device = 0x40; - result = mvSataQueueCommand(pMvSataAdapter, channel, - &commandInfo); - if (result != MV_QUEUE_COMMAND_RESULT_OK) { + result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); + if (result != MV_QUEUE_COMMAND_RESULT_OK){ goto queue_failed; } return; } - pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; - pNoUdmaParams->isEXT = MV_FALSE; - pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); - pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); - pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); - pNoUdmaParams->sectorCount = 0xff & nSector; - pNoUdmaParams->device = (MV_U8)(0x40 | - ((Lba & 0xf000000) >> 24)); - pNoUdmaParams->callBack = CommandCompletionCB; - result = mvSataQueueCommand(pMvSataAdapter, channel, - &commandInfo); - /* - * FIXME: how about the commands already queued? but marvel - * also forgets to consider this - */ - if (result != MV_QUEUE_COMMAND_RESULT_OK){ - goto queue_failed; + else{ + pNoUdmaParams->command = MV_ATA_COMMAND_READ_VERIFY_SECTORS; + pNoUdmaParams->isEXT = MV_FALSE; + pNoUdmaParams->lbaHigh = (MV_U16)((Lba & 0xff0000) >> 16); + pNoUdmaParams->lbaMid = (MV_U16)((Lba & 0xff00) >> 8); + pNoUdmaParams->lbaLow = (MV_U16)(Lba & 0xff); + pNoUdmaParams->sectorCount = 0xff & nSector; + pNoUdmaParams->device = (MV_U8)(0x40 | + ((Lba & 0xf000000) >> 24)); + pNoUdmaParams->callBack = CommandCompletionCB; + result = mvSataQueueCommand(pMvSataAdapter, channel, &commandInfo); + /*FIXME: how about the commands already queued? but marvel also forgets to consider this*/ + if (result != MV_QUEUE_COMMAND_RESULT_OK){ + goto queue_failed; + } } break; default: @@ -1966,7 +1884,8 @@ hpt_probe(device_t dev) #ifdef FOR_DEMO || pci_get_device(dev) == MV_SATA_DEVICE_ID_5080 #endif - )) { + )) + { KdPrintI((CONTROLLER_NAME " found\n")); device_set_desc(dev, CONTROLLER_NAME); return 0; @@ -1983,15 +1902,27 @@ hpt_probe(device_t dev) static int hpt_attach(device_t dev) { - IAL_ADAPTER_T * pAdapter; + IAL_ADAPTER_T * pAdapter = device_get_softc(dev); int rid; union ccb *ccb; struct cam_devq *devq; struct cam_sim *hpt_vsim; - printf("%s Version %s\n", DRIVER_NAME, DRIVER_VERSION); + printf("%s Version %s \n", DRIVER_NAME, DRIVER_VERSION); + + if (!pAdapter) + { + pAdapter = (IAL_ADAPTER_T *)malloc(sizeof (IAL_ADAPTER_T), M_DEVBUF, M_NOWAIT); +#if __FreeBSD_version > 410000 + device_set_softc(dev, (void *)pAdapter); +#else + device_set_driver(dev, (driver_t *)pAdapter); +#endif + } + + if (!pAdapter) return (ENOMEM); + bzero(pAdapter, sizeof(IAL_ADAPTER_T)); - pAdapter = device_get_softc(dev); pAdapter->hpt_dev = dev; rid = init_adapter(pAdapter); @@ -1999,58 +1930,59 @@ hpt_attach(device_t dev) return rid; rid = 0; - if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, - SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL){ + if ((pAdapter->hpt_irq = bus_alloc_resource(pAdapter->hpt_dev, SYS_RES_IRQ, &rid, 0, ~0ul, 1, RF_SHAREABLE | RF_ACTIVE)) == NULL) + { hpt_printk(("can't allocate interrupt\n")); return(ENXIO); } - if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, - hpt_intr, pAdapter, &pAdapter->hpt_intr)) { + if(bus_setup_intr(pAdapter->hpt_dev, pAdapter->hpt_irq, INTR_TYPE_CAM, hpt_intr, pAdapter, &pAdapter->hpt_intr)) + { hpt_printk(("can't set up interrupt\n")); free(pAdapter, M_DEVBUF); return(ENXIO); } -#if 1 - if ((ccb = malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK | M_ZERO)) != NULL) { + + if((ccb = (union ccb *)malloc(sizeof(*ccb), M_DEVBUF, M_WAITOK)) != (union ccb*)NULL) + { + bzero(ccb, sizeof(*ccb)); ccb->ccb_h.pinfo.priority = 1; ccb->ccb_h.pinfo.index = CAM_UNQUEUED_INDEX; - } else { + } + else + { return ENOMEM; } -#endif /* * Create the device queue for our SIM(s). */ - if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) { + if((devq = cam_simq_alloc(8/*MAX_QUEUE_COMM*/)) == NULL) + { KdPrint(("ENXIO\n")); - free(ccb, M_DEVBUF); return ENOMEM; } /* * Construct our SIM entry */ - if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll,__str(PROC_DIR_NAME), - pAdapter, device_get_unit(pAdapter->hpt_dev), /*untagged*/1, - /*tagged*/8, devq)) == NULL) { - free(ccb, M_DEVBUF); + if ((hpt_vsim = cam_sim_alloc(hpt_action, hpt_poll, __str(PROC_DIR_NAME), + pAdapter, device_get_unit(pAdapter->hpt_dev), /*untagged*/1, /*tagged*/8, devq)) == NULL) { cam_simq_free(devq); return ENOMEM; } - if(xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) { - free(ccb, M_DEVBUF); + if(xpt_bus_register(hpt_vsim, 0) != CAM_SUCCESS) + { cam_sim_free(hpt_vsim, /*free devq*/ TRUE); hpt_vsim = NULL; return ENXIO; } if(xpt_create_path(&pAdapter->path, /*periph */ NULL, - cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) - != CAM_REQ_CMP) { - free(ccb, M_DEVBUF); + cam_sim_path(hpt_vsim), CAM_TARGET_WILDCARD, + CAM_LUN_WILDCARD) != CAM_REQ_CMP) + { xpt_bus_deregister(cam_sim_path(hpt_vsim)); cam_sim_free(hpt_vsim, /*free_devq*/TRUE); hpt_vsim = NULL; @@ -2065,14 +1997,14 @@ hpt_attach(device_t dev) xpt_action((union ccb *)ccb); free(ccb, M_DEVBUF); - /* Only do this setup for the first device. */ + /* Register shutdown handler, and start the work thread. */ if (device_get_unit(dev) == 0) { - pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final, - hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT); - if (pAdapter->eh != NULL) + pAdapter->eh = EVENTHANDLER_REGISTER(shutdown_final, + hpt_shutdown, dev, SHUTDOWN_PRI_DEFAULT); + if (pAdapter->eh) launch_worker_thread(); else - printf("hptmv: shutdown event registration failed\n"); + hpt_printk(("shutdown event registration failed\n")); } return 0; @@ -2080,10 +2012,11 @@ hpt_attach(device_t dev) static int hpt_detach(device_t dev) -{ +{ return (EBUSY); } + /*************************************************************** * The poll function is used to simulate the interrupt when * the interrupt subsystem is not functioning. @@ -2103,11 +2036,11 @@ static void hpt_intr(void *arg) { IAL_ADAPTER_T *pAdapter = (IAL_ADAPTER_T *)arg; - intrmask_t oldspl; + intrmask_t oldspl = lock_driver(); - oldspl = lock_driver(); /* KdPrintI(("----- Entering Isr() -----\n")); */ - if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE){ + if (mvSataInterruptServiceRoutine(&pAdapter->mvSataAdapter) == MV_TRUE) + { _VBUS_INST(&pAdapter->VBus) CheckPendingCall(_VBUS_P0); } @@ -2146,56 +2079,55 @@ FlushAdapter(IAL_ADAPTER_T *pAdapter) /* flush all devices */ for (i=0; iVBus.pVDevice[i]; - if (pVDev) - fFlushVDev(pVDev); + if(pVDev) fFlushVDev(pVDev); } } static int hpt_shutdown(device_t dev) { - IAL_ADAPTER_T *pAdapter; - - pAdapter = device_get_softc(dev); - if (pAdapter == NULL) - return (EINVAL); - - EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); - FlushAdapter(pAdapter); - - return 0; + IAL_ADAPTER_T *pAdapter; + + pAdapter = device_get_softc(dev); + if (pAdapter == NULL) + return (EINVAL); + + EVENTHANDLER_DEREGISTER(shutdown_final, pAdapter->eh); + FlushAdapter(pAdapter); + /* give the flush some time to happen, + *otherwise "shutdown -p now" will make file system corrupted */ + DELAY(1000 * 1000 * 5); + return 0; } void Check_Idle_Call(IAL_ADAPTER_T *pAdapter) { - int i = 0; - _VBUS_INST(&pAdapter->VBus) if (mWaitingForIdle(_VBUS_P0)) { CheckIdleCall(_VBUS_P0); #ifdef SUPPORT_ARRAY - for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ + { + int i; PVDevice pArray; - - if ((pArray = ArrayTables(i))->u.array.dArStamp == 0) - continue; - else if (pArray->u.array.rf_auto_rebuild) { - KdPrint(("auto rebuild.\n")); - pArray->u.array.rf_auto_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, - pAdapter, pArray, DUPLICATE); + for(i = 0; i < MAX_ARRAY_PER_VBUS; i++){ + if ((pArray=ArrayTables(i))->u.array.dArStamp==0) + continue; + else if (pArray->u.array.rf_auto_rebuild) { + KdPrint(("auto rebuild.\n")); + pArray->u.array.rf_auto_rebuild = 0; + hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); + } } } #endif } /* launch the awaiting commands blocked by mWaitingForIdle */ - while(pAdapter->pending_Q!= NULL) { + while(pAdapter->pending_Q!= NULL) + { _VBUS_INST(&pAdapter->VBus) - union ccb *ccb = - (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; - + union ccb *ccb = (union ccb *)pAdapter->pending_Q->ccb_h.ccb_ccb_ptr; hpt_free_ccb(&pAdapter->pending_Q, ccb); CallAfterReturn(_VBUS_P (DPC_PROC)OsSendCommand, ccb); } @@ -2204,14 +2136,17 @@ Check_Idle_Call(IAL_ADAPTER_T *pAdapter) static void ccb_done(union ccb *ccb) { - IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *)ccb->ccb_adapter; - KdPrintI(("ccb_done: ccb %p status %x", ccb, ccb->ccb_h.status)); + PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; + IAL_ADAPTER_T * pAdapter = pmap->pAdapter; + KdPrintI(("ccb_done: ccb %p status %x\n", ccb, ccb->ccb_h.status)); + dmamap_put(pmap); xpt_done(ccb); pAdapter->outstandingCommands--; - if (pAdapter->outstandingCommands == 0) { + if (pAdapter->outstandingCommands == 0) + { if(DPC_Request_Nums == 0) Check_Idle_Call(pAdapter); } @@ -2229,124 +2164,130 @@ hpt_action(struct cam_sim *sim, union ccb *ccb) { intrmask_t oldspl; IAL_ADAPTER_T * pAdapter = (IAL_ADAPTER_T *) cam_sim_softc(sim); + PBUS_DMAMAP pmap; _VBUS_INST(&pAdapter->VBus) - - ccb->ccb_adapter = pAdapter; CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("hpt_action\n")); - KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, - ccb->ccb_h.func_code)); + KdPrint(("hpt_action(%lx,%lx{%x})\n", (u_long)sim, (u_long)ccb, ccb->ccb_h.func_code)); - switch (ccb->ccb_h.func_code) { - case XPT_SCSI_IO: /* Execute the requested I/O operation */ - /* ccb->ccb_h.path_id is not our bus id - don't check it */ + switch (ccb->ccb_h.func_code) + { + case XPT_SCSI_IO: /* Execute the requested I/O operation */ + { + /* ccb->ccb_h.path_id is not our bus id - don't check it */ + + if (ccb->ccb_h.target_lun) { + ccb->ccb_h.status = CAM_LUN_INVALID; + xpt_done(ccb); + return; + } + if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || + pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { + ccb->ccb_h.status = CAM_TID_INVALID; + xpt_done(ccb); + return; + } - if (ccb->ccb_h.target_lun) { - ccb->ccb_h.status = CAM_LUN_INVALID; - xpt_done(ccb); - return; - } - if (ccb->ccb_h.target_id >= MAX_VDEVICE_PER_VBUS || - pAdapter->VBus.pVDevice[ccb->ccb_h.target_id]==0) { - ccb->ccb_h.status = CAM_TID_INVALID; - xpt_done(ccb); - return; - } + oldspl = lock_driver(); + if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) + Check_Idle_Call(pAdapter); - oldspl = lock_driver(); - if (pAdapter->outstandingCommands==0 && DPC_Request_Nums==0) - Check_Idle_Call(pAdapter); + pmap = dmamap_get(pAdapter); + HPT_ASSERT(pmap); + ccb->ccb_adapter = pmap; + memset((void *)pmap->psg, 0, sizeof(pmap->psg)); - if (mWaitingForIdle(_VBUS_P0)) - hpt_queue_ccb(&pAdapter->pending_Q, ccb); - else - OsSendCommand(_VBUS_P ccb); - unlock_driver(oldspl); + if (mWaitingForIdle(_VBUS_P0)) + hpt_queue_ccb(&pAdapter->pending_Q, ccb); + else + OsSendCommand(_VBUS_P ccb); + unlock_driver(oldspl); - /* KdPrint(("leave scsiio\n")); */ - break; + /* KdPrint(("leave scsiio\n")); */ + break; + } - case XPT_RESET_BUS: - KdPrint(("reset bus\n")); - oldspl = lock_driver(); - fResetVBus(_VBUS_P0); - unlock_driver(oldspl); - xpt_done(ccb); - break; + case XPT_RESET_BUS: + KdPrint(("reset bus\n")); + oldspl = lock_driver(); + fResetVBus(_VBUS_P0); + unlock_driver(oldspl); + xpt_done(ccb); + break; - case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ - case XPT_EN_LUN: /* Enable LUN as a target */ - case XPT_TARGET_IO: /* Execute target I/O request */ - case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ - case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ - case XPT_ABORT: /* Abort the specified CCB */ - case XPT_TERM_IO: /* Terminate the I/O process */ - /* XXX Implement */ - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; + case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */ + case XPT_EN_LUN: /* Enable LUN as a target */ + case XPT_TARGET_IO: /* Execute target I/O request */ + case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */ + case XPT_CONT_TARGET_IO: /* Continue Host Target I/O Connection*/ + case XPT_ABORT: /* Abort the specified CCB */ + case XPT_TERM_IO: /* Terminate the I/O process */ + /* XXX Implement */ + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; - case XPT_GET_TRAN_SETTINGS: - case XPT_SET_TRAN_SETTINGS: - /* XXX Implement */ - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - xpt_done(ccb); - break; + case XPT_GET_TRAN_SETTINGS: + case XPT_SET_TRAN_SETTINGS: + /* XXX Implement */ + ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; + xpt_done(ccb); + break; - case XPT_CALC_GEOMETRY: - { - struct ccb_calc_geometry *ccg; - u_int32_t size_mb; - u_int32_t secs_per_cylinder; + case XPT_CALC_GEOMETRY: + { + struct ccb_calc_geometry *ccg; + u_int32_t size_mb; + u_int32_t secs_per_cylinder; - ccg = &ccb->ccg; - size_mb = ccg->volume_size / ((1024L*1024L) / ccg->block_size); + ccg = &ccb->ccg; + size_mb = ccg->volume_size / ((1024L * 1024L) / ccg->block_size); - if (size_mb > 1024 ) { - ccg->heads = 255; - ccg->secs_per_track = 63; - } else { - ccg->heads = 64; - ccg->secs_per_track = 32; + if (size_mb > 1024 ) { + ccg->heads = 255; + ccg->secs_per_track = 63; + } else { + ccg->heads = 64; + ccg->secs_per_track = 32; + } + secs_per_cylinder = ccg->heads * ccg->secs_per_track; + ccg->cylinders = ccg->volume_size / secs_per_cylinder; + ccb->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; } - secs_per_cylinder = ccg->heads * ccg->secs_per_track; - ccg->cylinders = ccg->volume_size / secs_per_cylinder; - ccb->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } - - case XPT_PATH_INQ: /* Path routing inquiry */ - { - struct ccb_pathinq *cpi = &ccb->cpi; - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE; - cpi->target_sprt = 0; - /* Not necessary to reset bus */ - cpi->hba_misc = PIM_NOBUSRESET; - cpi->hba_eng_cnt = 0; - - cpi->max_target = MAX_VDEVICE_PER_VBUS; - cpi->max_lun = 0; - cpi->initiator_id = MAX_VDEVICE_PER_VBUS; - - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 3300; - strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); - strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->ccb_h.status = CAM_REQ_CMP; - xpt_done(ccb); - break; - } + case XPT_PATH_INQ: /* Path routing inquiry */ + { + struct ccb_pathinq *cpi = &ccb->cpi; + + cpi->version_num = 1; /* XXX??? */ + cpi->hba_inquiry = PI_SDTR_ABLE; + cpi->target_sprt = 0; + /* Not necessary to reset bus */ + cpi->hba_misc = PIM_NOBUSRESET; + cpi->hba_eng_cnt = 0; + + cpi->max_target = MAX_VDEVICE_PER_VBUS; + cpi->max_lun = 0; + cpi->initiator_id = MAX_VDEVICE_PER_VBUS; + + cpi->bus_id = cam_sim_bus(sim); + cpi->base_transfer_speed = 3300; + strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); + strncpy(cpi->hba_vid, "HPT ", HBA_IDLEN); + strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); + cpi->unit_number = cam_sim_unit(sim); + cpi->ccb_h.status = CAM_REQ_CMP; + xpt_done(ccb); + break; + } - default: - KdPrint(("invalid cmd\n")); - ccb->ccb_h.status = CAM_REQ_INVALID; - xpt_done(ccb); - break; + default: + KdPrint(("invalid cmd\n")); + ccb->ccb_h.status = CAM_REQ_INVALID; + xpt_done(ccb); + break; } /* KdPrint(("leave hpt_action..............\n")); */ } @@ -2373,8 +2314,7 @@ hpt_free_ccb(union ccb **ccb_Q, union ccb *ccb) TempCCB = *ccb_Q; - if(ccb->ccb_h.ccb_ccb_ptr == ccb) - /*it means SCpnt is the last one in CURRCMDs*/ + if(ccb->ccb_h.ccb_ccb_ptr == ccb) /*it means SCpnt is the last one in CURRCMDs*/ *ccb_Q = NULL; else { while(TempCCB->ccb_h.ccb_ccb_ptr != (char *)ccb) @@ -2400,11 +2340,6 @@ static void hpt_worker_thread(void) for(;;) { while (DpcQueue_First!=DpcQueue_Last) { ST_HPT_DPC p; - IAL_ADAPTER_T *pAdapter; - PVDevice pArray; - PVBus _vbus_p; - int i; - oldspl = lock_driver(); p = DpcQueue[DpcQueue_First]; DpcQueue_First++; @@ -2415,10 +2350,7 @@ static void hpt_worker_thread(void) oldspl = lock_driver(); DPC_Request_Nums--; - /* - * since we may have prevented Check_Idle_Call, do it - * here - */ + /* since we may have prevented Check_Idle_Call, do it here */ if (DPC_Request_Nums==0) { if (p.pAdapter->outstandingCommands == 0) { _VBUS_INST(&p.pAdapter->VBus); @@ -2427,37 +2359,54 @@ static void hpt_worker_thread(void) } } unlock_driver(oldspl); - if (SIGISMEMBER(curproc->p_siglist, SIGSTOP) == 0) - continue; - - /* abort rebuilding process. */ - pAdapter = gIal_Adapter; - while (pAdapter != 0) { - _vbus_p = &pAdapter->VBus; - for (i = 0; i < MAX_ARRAY_PER_VBUS;i++){ - if ((pArray=ArrayTables(i))->u.array.dArStamp==0) - continue; - if (pArray->u.array.rf_rebuilding || - pArray->u.array.rf_verifying || - pArray->u.array.rf_initializing) { - pArray->u.array.rf_abort_rebuild = 1; + + /*Schedule out*/ +#if (__FreeBSD_version < 500000) + YIELD_THREAD; +#else + tsleep((caddr_t)hpt_worker_thread, PPAUSE, "sched", 1); +#endif + if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) { + /* abort rebuilding process. */ + IAL_ADAPTER_T *pAdapter; + PVDevice pArray; + PVBus _vbus_p; + int i; + pAdapter = gIal_Adapter; + + while(pAdapter != 0){ + + _vbus_p = &pAdapter->VBus; + + for (i=0;iu.array.dArStamp==0) + continue; + else if (pArray->u.array.rf_rebuilding || + pArray->u.array.rf_verifying || + pArray->u.array.rf_initializing) + { + pArray->u.array.rf_abort_rebuild = 1; + } } + pAdapter = pAdapter->next; } - pAdapter = pAdapter->next; } } +/*Remove this debug option*/ +/* #ifdef DEBUG if (SIGISMEMBER(curproc->p_siglist, SIGSTOP)) - tsleep(hpt_worker_thread, PPAUSE, "hptrdy", 2 * hz); + tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz); #endif -#if (__FreeBSD_version >= 500043) +*/ + #if (__FreeBSD_version >= 500043) kthread_suspend_check(curproc); -#else + #else kproc_suspend_loop(curproc); -#endif - /* wait for something to do */ - tsleep(hpt_worker_thread, PPAUSE, "hptrdy", 2 * hz); + #endif + tsleep((caddr_t)hpt_worker_thread, PPAUSE, "hptrdy", 2*hz); /* wait for something to do */ } } @@ -2468,6 +2417,7 @@ static struct kproc_desc hpt_kp = { &hptdaemonproc }; +/*Start this thread in the hpt_attach, to prevent kernel from loading it without our controller.*/ static void launch_worker_thread(void) { @@ -2484,155 +2434,73 @@ launch_worker_thread(void) for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) if ((pVDev=ArrayTables(i))->u.array.dArStamp==0) continue; - if (pVDev->u.array.rf_need_rebuild && - !pVDev->u.array.rf_rebuilding) { - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, - pAdapTemp, pVDev, - (UCHAR)((pVDev->u.array.CriticalMembers || - pVDev->VDeviceType == VD_RAID_1) ? - DUPLICATE : REBUILD_PARITY)); - } + else{ + if (pVDev->u.array.rf_need_rebuild && !pVDev->u.array.rf_rebuilding) + hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapTemp, pVDev, + (UCHAR)((pVDev->u.array.CriticalMembers || pVDev->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); + } } /* - * hpt_worker_thread needs to be suspended after shutdown sync, when fs - * sync finished. + * hpt_worker_thread needs to be suspended after shutdown sync, when fs sync finished. */ #if (__FreeBSD_version < 500043) - EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, - hptdaemonproc, SHUTDOWN_PRI_FIRST); -#else - EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, - hptdaemonproc, SHUTDOWN_PRI_FIRST); + EVENTHANDLER_REGISTER(shutdown_post_sync, shutdown_kproc, hptdaemonproc, SHUTDOWN_PRI_FIRST); +#else + EVENTHANDLER_REGISTER(shutdown_post_sync, kproc_shutdown, hptdaemonproc, SHUTDOWN_PRI_FIRST); #endif } +/* + *SYSINIT(hptwt, SI_SUB_KTHREAD_IDLE, SI_ORDER_FIRST, launch_worker_thread, NULL); +*/ -#endif /* SUPPORT_ARRAY */ - -/* build sgl with merge function */ -#define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) - -/* XXX */ -/* #define NOTNEIGHBORPAGE(x, y) (max(x, y) - min(x, y) > PAGE_SIZE) */ -#define NOTNEIGHBORPAGE(highvaddr, lowvaddr) \ - ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) - +#endif /********************************************************************************/ -static void -hptmv_buffer_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +int HPTLIBAPI fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) { - FPSCAT_GATH pSg; + union ccb *ccb = (union ccb *)pCmd->pOrgCommand; + bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; int idx; - if (error || nsegs == 0) { - panic("busdma bewm"); - return; - } - - pSg = *(FPSCAT_GATH *)arg; - - for (idx = 0; idx < nsegs; idx++) { - pSg[idx].dSgAddress = (ULONG_PTR)segs[idx].ds_addr; - pSg[idx].wSgSize = segs[idx].ds_len; - pSg[idx].wSgFlag = 0; - } - pSg[idx - 1].wSgFlag = SG_FLAG_EOT; - - return; -} + if(logical) { + if (ccb->ccb_h.flags & CAM_DATA_PHYS) + panic("physical address unsupported"); -static int HPTLIBAPI -fOsBuildSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSg, int logical) -{ - IAL_ADAPTER_T *pAdapter; - pPrivCommand prvCmd; - union ccb *ccb; - struct ccb_hdr *ccb_h; - struct ccb_scsiio *csio; - bus_dma_segment_t *sgList; - int error; - - prvCmd = pCmd->pOrgCommand; - pAdapter = prvCmd->pAdapter; - ccb = prvCmd->ccb; - ccb_h = &ccb->ccb_h; - csio = &ccb->csio; - sgList = (bus_dma_segment_t *)(csio->data_ptr); - - if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_NONE) - return TRUE; - - if ((ccb_h->flags & CAM_SCATTER_VALID) != 0) { - if((ccb_h->flags & CAM_DATA_PHYS) != 0) - panic(KMSG_LEADING "physical address unsupported!"); - - hptmv_buffer_callback(&pSg, sgList, csio->sglist_cnt, 0); - return TRUE; - } - - if (logical) { - if ((ccb_h->flags & CAM_DATA_PHYS) != 0) - panic(KMSG_LEADING "physical address unsupported\n"); - - pSg->dSgAddress = (ULONG_PTR)csio->data_ptr; - pSg->wSgSize = (USHORT)csio->dxfer_len; - pSg->wSgFlag = SG_FLAG_EOT; + if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { + if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) + panic("physical address unsupported"); + + for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { + pSg[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; + pSg[idx].wSgSize = sgList[idx].ds_len; + pSg[idx].wSgFlag = (idx==ccb->csio.sglist_cnt-1)? SG_FLAG_EOT : 0; + } + } + else { + pSg->dSgAddress = (ULONG_PTR)(UCHAR *)ccb->csio.data_ptr; + pSg->wSgSize = ccb->csio.dxfer_len; + pSg->wSgFlag = SG_FLAG_EOT; + } return TRUE; } - - KdPrint(("use sgl (physical) ...........\n")); - - /* - * XXX Hack to make this work with PAE. It will fail under - * heavy load. - */ - error = bus_dmamap_load(pAdapter->buf_dmat, prvCmd->buf_map, - csio->data_ptr, csio->dxfer_len, hptmv_buffer_callback, &pSg, - BUS_DMA_NOWAIT); - - if (error) { - printf("bus_dmamap_load failed error= %d\n", error); - return FALSE; - } - -/*#ifdef DEBUG - do { - int size, i = 0; - KdPrintI(("sg[%d]:0x%lx %d\n", i++, pSg[i].dSgAddress, - pSg[i].wSgSize)); - size = pSg->wSgSize; - if (pSg[i].wSgFlag & SG_FLAG_EOT) - break; - } while (i<17); -#endif*/ - - if ((ccb_h->flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(pAdapter->buf_dmat, prvCmd->buf_map, - BUS_DMASYNC_PREREAD); - } else { - bus_dmamap_sync(pAdapter->buf_dmat, prvCmd->buf_map, - BUS_DMASYNC_PREWRITE); - } - - return TRUE; + + /* since we have provided physical sg, nobody will ask us to build physical sg */ + HPT_ASSERT(0); + return FALSE; } /*******************************************************************************/ ULONG HPTLIBAPI GetStamp(void) { - ULONG stamp; - /* * the system variable, ticks, can't be used since it hasn't yet been active * when our driver starts (ticks==0, it's a invalid stamp value) */ - do { - stamp = random(); - } while (stamp==0); - + ULONG stamp; + do { stamp = random(); } while (stamp==0); return stamp; } @@ -2641,9 +2509,8 @@ static void SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) { int i; - IDENTIFY_DATA2 *pIdentify; - - pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; + IDENTIFY_DATA2 *pIdentify = (IDENTIFY_DATA2*)pVDev->u.disk.mv->identifyDevice; + inquiryData->DeviceType = T_DIRECT; /*DIRECT_ACCESS_DEVICE*/ inquiryData->AdditionalLength = (UCHAR)(sizeof(INQUIRYDATA) - 5); #ifndef SERIAL_CMDS @@ -2655,16 +2522,13 @@ SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) case VD_ATAPI: case VD_REMOVABLE: /* Set the removable bit, if applicable. */ - if ((pVDev->u.disk.df_removable_drive) || - (pIdentify->GeneralConfiguration & 0x80)) + if ((pVDev->u.disk.df_removable_drive) || (pIdentify->GeneralConfiguration & 0x80)) inquiryData->RemovableMedia = 1; /* Fill in vendor identification fields. */ - for (i = 0; i < 16; i += 2) { - inquiryData->VendorId[i] = - ((PUCHAR)pIdentify->ModelNumber)[i + 1]; - inquiryData->VendorId[i+1] = - ((PUCHAR)pIdentify->ModelNumber)[i]; + for (i = 0; i < 20; i += 2) { + inquiryData->VendorId[i] = ((PUCHAR)pIdentify->ModelNumber)[i + 1]; + inquiryData->VendorId[i+1] = ((PUCHAR)pIdentify->ModelNumber)[i]; } @@ -2672,38 +2536,29 @@ SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) for (i = 0; i < 4; i++) inquiryData->ProductId[12+i] = ' '; /* firmware revision */ - for (i = 0; i < 4; i += 2) { - inquiryData->ProductRevisionLevel[i] = - ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; - inquiryData->ProductRevisionLevel[i+1] = - ((PUCHAR)pIdentify->FirmwareRevision)[i]; + for (i = 0; i < 4; i += 2) + { + inquiryData->ProductRevisionLevel[i] = ((PUCHAR)pIdentify->FirmwareRevision)[i+1]; + inquiryData->ProductRevisionLevel[i+1] = ((PUCHAR)pIdentify->FirmwareRevision)[i]; } break; default: memcpy(&inquiryData->VendorId, "RR182x ", 8); #ifdef SUPPORT_ARRAY - switch(pVDev->VDeviceType) { + switch(pVDev->VDeviceType){ case VD_RAID_0: - if ((pVDev->u.array.pMember[0] && - mIsArray(pVDev->u.array.pMember[0])) || - (pVDev->u.array.pMember[1] && - mIsArray(pVDev->u.array.pMember[1]))) - memcpy(&inquiryData->ProductId, - "RAID 1/0 Array ", 16); + if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || + (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) + memcpy(&inquiryData->ProductId, "RAID 1/0 Array ", 16); else - memcpy(&inquiryData->ProductId, - "RAID 0 Array ", 16); + memcpy(&inquiryData->ProductId, "RAID 0 Array ", 16); break; case VD_RAID_1: - if ((pVDev->u.array.pMember[0] && - mIsArray(pVDev->u.array.pMember[0])) || - (pVDev->u.array.pMember[1] && - mIsArray(pVDev->u.array.pMember[1]))) - memcpy(&inquiryData->ProductId, - "RAID 0/1 Array ", 16); + if ((pVDev->u.array.pMember[0] && mIsArray(pVDev->u.array.pMember[0])) || + (pVDev->u.array.pMember[1] && mIsArray(pVDev->u.array.pMember[1]))) + memcpy(&inquiryData->ProductId, "RAID 0/1 Array ", 16); else - memcpy(&inquiryData->ProductId, - "RAID 1 Array ", 16); + memcpy(&inquiryData->ProductId, "RAID 1 Array ", 16); break; case VD_RAID_5: memcpy(&inquiryData->ProductId, "RAID 5 Array ", 16); @@ -2721,28 +2576,64 @@ SetInquiryData(PINQUIRYDATA inquiryData, PVDevice pVDev) static void hpt_timeout(void *arg) { - _VBUS_INST(&((IAL_ADAPTER_T*)((union ccb *)arg)->ccb_adapter)->VBus) - intrmask_t oldspl; - - oldspl = lock_driver(); + _VBUS_INST(&((PBUS_DMAMAP)((union ccb *)arg)->ccb_adapter)->pAdapter->VBus) + intrmask_t oldspl = lock_driver(); fResetVBus(_VBUS_P0); unlock_driver(oldspl); } +static void +hpt_io_dmamap_callback(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + PCommand pCmd = (PCommand)arg; + union ccb *ccb = pCmd->pOrgCommand; + struct ccb_hdr *ccb_h = &ccb->ccb_h; + PBUS_DMAMAP pmap = (PBUS_DMAMAP) ccb->ccb_adapter; + IAL_ADAPTER_T *pAdapter = pmap->pAdapter; + PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; + FPSCAT_GATH psg = pCmd->pSgTable; + int idx; + _VBUS_INST(pVDev->pVBus) + + HPT_ASSERT(pCmd->cf_physical_sg); + + if (error || nsegs == 0) + panic("busdma error"); + + HPT_ASSERT(nsegs<= MAX_SG_DESCRIPTORS); + + for (idx = 0; idx < nsegs; idx++, psg++) { + psg->dSgAddress = (ULONG_PTR)(UCHAR *)segs[idx].ds_addr; + psg->wSgSize = segs[idx].ds_len; + psg->wSgFlag = (idx == nsegs-1)? SG_FLAG_EOT: 0; +/* KdPrint(("psg[%d]:add=%p,size=%x,flag=%x\n", idx, psg->dSgAddress,psg->wSgSize,psg->wSgFlag)); */ + } +/* psg[-1].wSgFlag = SG_FLAG_EOT; */ + + if (pCmd->cf_data_in) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREREAD); + } + else if (pCmd->cf_data_out) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_PREWRITE); + } + + ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); + pVDev->pfnSendCommand(_VBUS_P pCmd); + CheckPendingCall(_VBUS_P0); +} + + + static void HPTLIBAPI OsSendCommand(_VBUS_ARG union ccb *ccb) { - IAL_ADAPTER_T *pAdapter; - struct ccb_hdr *ccb_h; - struct ccb_scsiio *csio; - PVDevice pVDev; - - pAdapter = (IAL_ADAPTER_T *)ccb->ccb_adapter; - ccb_h = &ccb->ccb_h; - csio = &ccb->csio; - pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; + PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; + IAL_ADAPTER_T *pAdapter = pmap->pAdapter; + struct ccb_hdr *ccb_h = &ccb->ccb_h; + struct ccb_scsiio *csio = &ccb->csio; + PVDevice pVDev = pAdapter->VBus.pVDevice[ccb_h->target_id]; - KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", + KdPrintI(("OsSendCommand: ccb %p cdb %x-%x-%x\n", ccb, *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[0], *(ULONG *)&ccb->csio.cdb_io.cdb_bytes[4], @@ -2759,111 +2650,144 @@ OsSendCommand(_VBUS_ARG union ccb *ccb) switch(ccb->csio.cdb_io.cdb_bytes[0]) { - case TEST_UNIT_READY: - case START_STOP_UNIT: - case SYNCHRONIZE_CACHE: - /* FALLTHROUGH */ - ccb->ccb_h.status = CAM_REQ_CMP; - break; - - case INQUIRY: - ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); - SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); - ccb_h->status = CAM_REQ_CMP; - break; - - case READ_CAPACITY: - { - UCHAR swip[4]; - /* Claim 512 byte blocks (big-endian). */ - ((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000; - *(ULONG*)swip = pVDev->VDeviceCapacity - 1; - ((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress = - (swip[0] << 24) | (swip[1] << 16) | (swip[2] << 8) | swip[3]; - ccb_h->status = CAM_REQ_CMP; - break; - } - - case READ_6: - case WRITE_6: - case READ_10: - case WRITE_10: - case 0x13: - case 0x2f: - { - UCHAR Cdb[16]; - UCHAR CdbLength; - _VBUS_INST(pVDev->pVBus) - PCommand pCmd; - - pCmd = AllocateCommand(_VBUS_P0); - HPT_ASSERT(pCmd); - - CdbLength = csio->cdb_len; - if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) { - if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) { - bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); - } else { - KdPrintE(("ERROR!!!\n")); - ccb->ccb_h.status = CAM_REQ_INVALID; - break; - } - } else { - bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); - } - - pCmd->pOrgCommand = AllocPrivCommand(pAdapter); - if (pCmd->pOrgCommand == NULL) - panic("command leak!"); - ((pPrivCommand)(pCmd->pOrgCommand))->ccb = ccb; - pCmd->pVDevice = pVDev; - pCmd->pfnCompletion = fOsCommandDone; - pCmd->pfnBuildSgl = fOsBuildSgl; + case TEST_UNIT_READY: + case START_STOP_UNIT: + case SYNCHRONIZE_CACHE: + /* FALLTHROUGH */ + ccb->ccb_h.status = CAM_REQ_CMP; + break; - switch (Cdb[0]) { - case READ_6: - case WRITE_6: - case 0x13: - pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | - ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; - pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; + case INQUIRY: + ZeroMemory(ccb->csio.data_ptr, ccb->csio.dxfer_len); + SetInquiryData((PINQUIRYDATA)ccb->csio.data_ptr, pVDev); + ccb_h->status = CAM_REQ_CMP; break; - default: - pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | - ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | - ((ULONG)Cdb[2] << 24); - pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | - ((USHORT)Cdb[7]<<8); + + case READ_CAPACITY: + { + UCHAR swip[4]; + /* Claim 512 byte blocks (big-endian). */ + ((PREAD_CAPACITY_DATA)csio->data_ptr)->BytesPerBlock = 0x20000; + *(ULONG*)swip = pVDev->VDeviceCapacity - 1; + ((PREAD_CAPACITY_DATA)csio->data_ptr)->LogicalBlockAddress = + (swip[0] << 24) | (swip[1] << 16) | (swip[2] << 8) | swip[3]; + ccb_h->status = CAM_REQ_CMP; break; } - switch (Cdb[0]) { case READ_6: - case READ_10: - pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; - pCmd->cf_data_in = 1; - break; - case WRITE_6: + case READ_10: case WRITE_10: - pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; - pCmd->cf_data_out = 1; - break; case 0x13: case 0x2f: - pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; - break; - } + { + UCHAR Cdb[16]; + UCHAR CdbLength; + _VBUS_INST(pVDev->pVBus) + PCommand pCmd = AllocateCommand(_VBUS_P0); + HPT_ASSERT(pCmd); + + CdbLength = csio->cdb_len; + if ((ccb->ccb_h.flags & CAM_CDB_POINTER) != 0) + { + if ((ccb->ccb_h.flags & CAM_CDB_PHYS) == 0) + { + bcopy(csio->cdb_io.cdb_ptr, Cdb, CdbLength); + } + else + { + KdPrintE(("ERROR!!!\n")); + ccb->ccb_h.status = CAM_REQ_INVALID; + break; + } + } + else + { + bcopy(csio->cdb_io.cdb_bytes, Cdb, CdbLength); + } - ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); + pCmd->pOrgCommand = ccb; + pCmd->pVDevice = pVDev; + pCmd->pfnCompletion = fOsCommandDone; + pCmd->pfnBuildSgl = fOsBuildSgl; + pCmd->pSgTable = pmap->psg; + + switch (Cdb[0]) + { + case READ_6: + case WRITE_6: + case 0x13: + pCmd->uCmd.Ide.Lba = ((ULONG)Cdb[1] << 16) | ((ULONG)Cdb[2] << 8) | (ULONG)Cdb[3]; + pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[4]; + break; + + default: + pCmd->uCmd.Ide.Lba = (ULONG)Cdb[5] | ((ULONG)Cdb[4] << 8) | ((ULONG)Cdb[3] << 16) | ((ULONG)Cdb[2] << 24); + pCmd->uCmd.Ide.nSectors = (USHORT) Cdb[8] | ((USHORT)Cdb[7]<<8); + break; + } - pVDev->pfnSendCommand(_VBUS_P pCmd); - goto Command_Complished; - } + switch (Cdb[0]) + { + case READ_6: + case READ_10: + pCmd->uCmd.Ide.Command = IDE_COMMAND_READ; + pCmd->cf_data_in = 1; + break; + + case WRITE_6: + case WRITE_10: + pCmd->uCmd.Ide.Command = IDE_COMMAND_WRITE; + pCmd->cf_data_out = 1; + break; + case 0x13: + case 0x2f: + pCmd->uCmd.Ide.Command = IDE_COMMAND_VERIFY; + break; + } +/*///////////////////////// */ + if (ccb->ccb_h.flags & CAM_SCATTER_VALID) { + int idx; + bus_dma_segment_t *sgList = (bus_dma_segment_t *)ccb->csio.data_ptr; + + if (ccb->ccb_h.flags & CAM_SG_LIST_PHYS) + pCmd->cf_physical_sg = 1; - default: - ccb->ccb_h.status = CAM_REQ_INVALID; - break; + for (idx = 0; idx < ccb->csio.sglist_cnt; idx++) { + pCmd->pSgTable[idx].dSgAddress = (ULONG_PTR)(UCHAR *)sgList[idx].ds_addr; + pCmd->pSgTable[idx].wSgSize = sgList[idx].ds_len; + pCmd->pSgTable[idx].wSgFlag= (idx==ccb->csio.sglist_cnt-1)?SG_FLAG_EOT: 0; + } + + ccb->ccb_h.timeout_ch = timeout(hpt_timeout, (caddr_t)ccb, 20*hz); + pVDev->pfnSendCommand(_VBUS_P pCmd); + } + else { + int error; + pCmd->cf_physical_sg = 1; + error = bus_dmamap_load(pAdapter->io_dma_parent, + pmap->dma_map, + ccb->csio.data_ptr, ccb->csio.dxfer_len, + hpt_io_dmamap_callback, pCmd, + BUS_DMA_WAITOK + ); + KdPrint(("bus_dmamap_load return %d\n", error)); + if (error && error!=EINPROGRESS) { + hpt_printk(("bus_dmamap_load error %d\n", error)); + FreeCommand(_VBUS_P pCmd); + ccb->ccb_h.status = CAM_REQ_CMP_ERR; + dmamap_put(pmap); + pAdapter->outstandingCommands--; + xpt_done(ccb); + } + } + goto Command_Complished; + } + + default: + ccb->ccb_h.status = CAM_REQ_INVALID; + break; } ccb_done(ccb); Command_Complished: @@ -2871,18 +2795,14 @@ Command_Complished: return; } -static void HPTLIBAPI +static void HPTLIBAPI fOsCommandDone(_VBUS_ARG PCommand pCmd) { - IAL_ADAPTER_T *pAdapter; - pPrivCommand prvCmd; - union ccb *ccb; - - prvCmd = pCmd->pOrgCommand; - pAdapter = prvCmd->pAdapter; - ccb = prvCmd->ccb; + union ccb *ccb = pCmd->pOrgCommand; + PBUS_DMAMAP pmap = (PBUS_DMAMAP)ccb->ccb_adapter; + IAL_ADAPTER_T *pAdapter = pmap->pAdapter; - KdPrint(("fOsCommandDone(%p, %d)", pCmd, pCmd->Result)); + KdPrint(("fOsCommandDone(pcmd=%p, result=%d)\n", pCmd, pCmd->Result)); untimeout(hpt_timeout, (caddr_t)ccb, ccb->ccb_h.timeout_ch); @@ -2910,16 +2830,15 @@ fOsCommandDone(_VBUS_ARG PCommand pCmd) break; } - if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) { - bus_dmamap_sync(pAdapter->buf_dmat, prvCmd->buf_map, - BUS_DMASYNC_POSTREAD); - } else { - bus_dmamap_sync(pAdapter->buf_dmat, prvCmd->buf_map, - BUS_DMASYNC_POSTWRITE); + if (pCmd->cf_data_in) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTREAD); } - bus_dmamap_unload(pAdapter->buf_dmat, prvCmd->buf_map); + else if (pCmd->cf_data_in) { + bus_dmamap_sync(pAdapter->io_dma_parent, pmap->dma_map, BUS_DMASYNC_POSTWRITE); + } + + bus_dmamap_unload(pAdapter->io_dma_parent, pmap->dma_map); - FreePrivCommand(pAdapter, prvCmd); FreeCommand(_VBUS_P pCmd); ccb_done(ccb); } @@ -2946,53 +2865,44 @@ hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T * pAdapter, void *arg, UCHAR flags) #ifdef _RAID5N_ /* - * Allocate memory above 16M, otherwise we may eat all low memory for ISA - * devices. - * - * Busdma should be used here, not contigmalloc/free. However, this API - * will need to be changed to use it effective. + * Allocate memory above 16M, otherwise we may eat all low memory for ISA devices. + * How about the memory for 5081 request/response array and PRD table? */ void *os_alloc_page(_VBUS_ARG0) { - return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, - 0xffffffff, PAGE_SIZE, 0); + return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); } + void *os_alloc_dma_page(_VBUS_ARG0) { - return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, - 0xffffffff, PAGE_SIZE, 0); + return (void *)contigmalloc(0x1000, M_DEVBUF, M_NOWAIT, 0x1000000, 0xffffffff, PAGE_SIZE, 0ul); } -/* - * The next two are not used right now. - */ void -os_free_page(_VBUS_ARG void *p) -{ - contigfree(p, 0x1000, M_DEVBUF); +os_free_page(_VBUS_ARG void *p) +{ + contigfree(p, 0x1000, M_DEVBUF); } void -os_free_dma_page(_VBUS_ARG void *p) -{ - contigfree(p, 0x1000, M_DEVBUF); +os_free_dma_page(_VBUS_ARG void *p) +{ + contigfree(p, 0x1000, M_DEVBUF); } void DoXor1(ULONG *p0, ULONG *p1, ULONG *p2, UINT nBytes) { UINT i; - for (i = 0; i < nBytes / 4; i++) - *p0++ = *p1++ ^ *p2++; + for (i = 0; i < nBytes / 4; i++) *p0++ = *p1++ ^ *p2++; } void DoXor2(ULONG *p0, ULONG *p2, UINT nBytes) { UINT i; - for (i = 0; i < nBytes / 4; i++) - *p0++ ^= *p2++; + for (i = 0; i < nBytes / 4; i++) *p0++ ^= *p2++; } #endif diff --git a/sys/dev/hptmv/global.h b/sys/dev/hptmv/global.h index 90c62aea90d1..4e6a0d0e668f 100644 --- a/sys/dev/hptmv/global.h +++ b/sys/dev/hptmv/global.h @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -32,11 +32,11 @@ #include #include -#define COMPANY "HighPoint Technologies, Inc." -#define COPYRIGHT "(c) 2000-2004. HighPoint Technologies, Inc." +#define COMPANY "HighPoint Technologies, Inc." +#define COPYRIGHT "(c) 2000-2004. HighPoint Technologies, Inc." #define DRIVER_NAME "RocketRAID 182x SATA Controller driver" -#define CONTROLLER_NAME "RocketRAID 182x SATA Controller" -#define PROC_DIR_NAME hptmv +#define CONTROLLER_NAME "RocketRAID 182x SATA Controller" +#define PROC_DIR_NAME hptmv #define HPT_INTERFACE_VERSION 0x01000003 #define SUPPORT_48BIT_LBA @@ -45,10 +45,8 @@ #define _RAID5N_ #define MAX_QUEUE_COMM 32 #define MAX_SG_DESCRIPTORS 17 -#define MAX_VBUS 2 /* - * One vbus per adapter in mv linux driver, - * MAX_VBUS is defined for share code and can not be 1 - */ +#define MAX_VBUS 2 /*one vbus per adapter in mv linux driver, + MAX_VBUS is defined for share code and can not be 1*/ #define SET_VBUS_FOR_EACH_CONTROLLER #define MAX_MEMBERS 8 @@ -75,42 +73,42 @@ typedef struct _Device { UCHAR busyCount; UCHAR df_tcq_set: 1; - UCHAR df_tcq: 1; /* enable TCQ */ + UCHAR df_tcq: 1; /* enable TCQ */ UCHAR df_ncq_set: 1; - UCHAR df_ncq: 1; /* enable NCQ */ + UCHAR df_ncq: 1; /* enable NCQ */ UCHAR df_write_cache_set: 1; - UCHAR df_write_cache: 1; /* enable write cache */ + UCHAR df_write_cache: 1; /* enable write cache */ UCHAR df_read_ahead_set: 1; - UCHAR df_read_ahead: 1; /* enable read ahead */ - + UCHAR df_read_ahead: 1; /* enable read ahead */ + UCHAR retryCount; UCHAR resetCount; UCHAR pad1; - + UCHAR df_user_mode_set; - UCHAR bDeModeSetting; /* Current Data Transfer mode: 0-4 PIO 0-4 */ - UCHAR bDeUsable_Mode; /* actual maximum data transfer mode */ + UCHAR bDeModeSetting; /* Current Data Transfer mode: 0-4 PIO 0-4 */ + UCHAR bDeUsable_Mode; /* actual maximum data transfer mode */ UCHAR bDeUserSelectMode; - + PVBus pVBus; ULONG dDeRealCapacity; ULONG dDeHiddenLba; ULONG HeadPosition; ULONG QueueLength; MV_SATA_CHANNEL *mv; -} Device, *PDevice; - -typedef struct _SCAT_GATH { - ULONG_PTR dSgAddress; - USHORT wSgSize; - USHORT wSgFlag; +} +Device, *PDevice; + +typedef struct _SCAT_GATH +{ + ULONG_PTR dSgAddress; + USHORT wSgSize; + USHORT wSgFlag; } SCAT_GATH, FAR *FPSCAT_GATH; #define OS_VDEV_EXT -typedef struct _VDevice_Ext { -#if defined(WIN95) && defined(SUPPORT_HOTSWAP) - DCB * pDcb; -#endif +typedef struct _VDevice_Ext +{ UCHAR gui_locked; /* the device is locked by GUI */ UCHAR reserve[3]; } VDevice_Ext, *PVDevice_Ext; @@ -119,21 +117,12 @@ typedef struct _VDevice_Ext { #define SG_FLAG_SKIP 0x4000 #define SG_FLAG_EOT 0x8000 -#if 0 /* MAX_VBUS==1 */ -#define _VBUS_ARG -#define _VBUS_ARG0 void -#define _VBUS_P -#define _VBUS_P0 -#define _VBUS_INST(x) -#define _vbus_(x) x -#else #define _VBUS_ARG0 PVBus _vbus_p #define _VBUS_ARG PVBus _vbus_p, #define _VBUS_P _vbus_p, #define _VBUS_P0 _vbus_p #define _VBUS_INST(x) PVBus _vbus_p = x; #define _vbus_(x) (_vbus_p->x) -#endif /************************************************************************* * arithmetic functions @@ -156,34 +145,36 @@ int HPTLIBAPI os_memcmp(const void *cs, const void *ct, unsigned len); void HPTLIBAPI os_memcpy(void *to, const void *from, unsigned len); void HPTLIBAPI os_memset(void *s, char c, unsigned len); unsigned HPTLIBAPI os_strlen(const char *s); + #ifdef NO_LIBC #define memcmp os_memcmp #define memcpy os_memcpy #define memset os_memset #define strlen os_strlen #elif (__FreeBSD_version <= 410000) -#define memcpy(d, s, len) bcopy((s),(d),(len)) -#define memset(d, s, len) bzero((d),(len)) +#define memcpy(d, s, len) bcopy((s),(d),(len)) +#define memset(d, s, len) bzero((d),(len)) #endif #define ZeroMemory(a, b) memset((char *)a, 0, b) #define MemoryCopy(a,b,c) memcpy((char *)(a), (char *)(b), (UINT)(c)) -#define farMemoryCopy(a,b,c) memcpy((char *)(a), (char *)(b), (UINT)c) +#define farMemoryCopy(a,b,c) memcpy((char *)(a), (char *)(b), (UINT)c) #define StrLen strlen /* * we don't want whole hptintf.h in shared code... * some constants must match that in hptintf.h! */ -enum _driver_events_t { +enum _driver_events_t +{ ET_DEVICE=0, - ET_DEVICE_REMOVED, - ET_DEVICE_PLUGGED, - ET_DEVICE_ERROR, - ET_REBUILD_STARTED, - ET_REBUILD_ABORTED, - ET_REBUILD_FINISHED, - ET_SPARE_TOOK_OVER, - ET_REBUILD_FAILED, + ET_DEVICE_REMOVED, + ET_DEVICE_PLUGGED, + ET_DEVICE_ERROR, + ET_REBUILD_STARTED, + ET_REBUILD_ABORTED, + ET_REBUILD_FINISHED, + ET_SPARE_TOOK_OVER, + ET_REBUILD_FAILED, ET_VERIFY_STARTED, ET_VERIFY_ABORTED, ET_VERIFY_FAILED, @@ -195,13 +186,13 @@ enum _driver_events_t { ET_VERIFY_DATA_ERROR, }; +#define StallExec(x) mvMicroSecondsDelay(x) extern void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param); -#define StallExec(x) mvMicroSecondsDelay(x) -#define fNotifyGUI(WhatHappen, pVDevice) \ - ioctl_ReportEvent(WhatHappen, pVDevice) -#define DECLARE_BUFFER(type, ptr) \ - UCHAR ptr##__buf[512]; \ - type ptr=(type)ptr##__buf +#define fNotifyGUI(WhatHappen, pVDevice) ioctl_ReportEvent(WhatHappen, pVDevice) +#define DECLARE_BUFFER(type, ptr) UCHAR ptr##__buf[512]; type ptr=(type)ptr##__buf + +int HPTLIBAPI fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer); +void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode); #include #include @@ -209,8 +200,10 @@ extern void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param); #include #include -int HPTLIBAPI fDeReadWrite(PDevice pDev, ULONG Lba, UCHAR Cmd, void *tmpBuffer); -void HPTLIBAPI fDeSelectMode(PDevice pDev, UCHAR NewMode); +#if defined(__FreeBSD__) && defined(HPTLIBAPI) +#undef HPTLIBAPI +#define HPTLIBAPI +#endif #ifdef SUPPORT_ARRAY #define ArrayTables(i) ((PVDevice)&_vbus_(_ArrayTables)[i*ARRAY_VDEV_SIZE]) diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c index 19fd2f8362fa..13def6ba9240 100644 --- a/sys/dev/hptmv/gui_lib.c +++ b/sys/dev/hptmv/gui_lib.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -42,6 +42,10 @@ #include #include +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + #include #include #include @@ -59,7 +63,8 @@ static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk); static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo); static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo); -int check_VDevice_valid(PVDevice p) +int +check_VDevice_valid(PVDevice p) { int i; PVDevice pVDevice; @@ -228,7 +233,7 @@ ignore_info: for(i = 0; i < pVDevice->u.array.bArnMember; i++) { - if(pVDevice->u.array.pMember[i] != NULL) + if(pVDevice->u.array.pMember[i] != 0) { pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); pInfo->u.array.nDisk++; @@ -318,7 +323,7 @@ static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) return 0; } -static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) +int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) { ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES)); cap->dwSize = sizeof(DRIVER_CAPABILITIES); @@ -336,9 +341,6 @@ static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1; cap->SupportDedicatedSpare = 0; -#ifdef SUPPORT_HOTSWAP - cap->SupportHotSwap = 1; -#endif #ifdef SUPPORT_ARRAY /* Stripe */ @@ -350,7 +352,7 @@ static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) /* Mirror + Stripe */ #ifdef ARRAY_V2_ONLY cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */ -#else +#else cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */ #endif cap->MaximumArrayMembers[2] = MAX_MEMBERS; @@ -362,16 +364,11 @@ static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) cap->SupportedRAIDTypes[4] = AT_RAID5; cap->MaximumArrayMembers[4] = MAX_MEMBERS; #endif -#if 0 /* don't let GUI create RAID 0/1. */ - /* Stripe + Mirror */ - cap->SupportedRAIDTypes[5] = (AT_RAID1<<4)|AT_RAID0; - cap->MaximumArrayMembers[5] = 4; #endif -#endif /* SUPPORT_ARRAY */ return 0; } -static int hpt_get_controller_count(void) +int hpt_get_controller_count(void) { IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; int iControllerCount = 0; @@ -385,7 +382,7 @@ static int hpt_get_controller_count(void) return iControllerCount; } -static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) +int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) { IAL_ADAPTER_T *pAdapTemp; int iControllerCount = 0; @@ -403,7 +400,7 @@ static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) #endif strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME); #define _set_product_id(x) -#else +#else #define _set_product_id(x) strcpy(pInfo->szProductID, x) #endif _set_product_id("RocketRAID 182x SATA Controller"); @@ -416,7 +413,7 @@ static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) } -static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) +int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) { IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; int i,iControllerCount = 0; @@ -449,7 +446,7 @@ found: } -static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) +int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) { int count = 0; int i,j; @@ -482,11 +479,11 @@ done: return count; } -static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) +int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) { PVDevice pVDevice = ID_TO_VDEV(id); - if((id == HPT_NULL_ID) || check_VDevice_valid(pVDevice)) + if((id == 0) || check_VDevice_valid(pVDevice)) return -1; #ifdef SUPPORT_ARRAY @@ -500,15 +497,12 @@ static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) } #ifdef SUPPORT_ARRAY -static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) +DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) { ULONG Stamp = GetStamp(); int i,j; ULONG capacity = MAX_LBA_T; PVDevice pArray,pChild; -#if MAX_VBUS==1 - PVBus _vbus_p = NULL; -#endif int Loca = -1; for(i = 0; i < pParam->nDisk; i++) @@ -758,9 +752,7 @@ int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) int i; IAL_ADAPTER_T *pAdapter = gIal_Adapter; -#if MAX_VBUS>1 if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2)) return -1; @@ -834,7 +826,7 @@ int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) PVDevice pArray = ID_TO_VDEV(idArray); PVDevice pDisk = ID_TO_VDEV(idDisk); - if((idArray == HPT_NULL_ID) || (idDisk == HPT_NULL_ID)) return -1; + if((idArray == 0) || (idDisk == 0)) return -1; if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1; if(!pArray->u.array.rf_broken) return -1; @@ -864,9 +856,7 @@ int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) else if(pDisk->VDeviceCapacity < Capacity) return -1; -#if MAX_VBUS>1 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif for(i = 0; i < pArray->u.array.bArnMember; i++) if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online) @@ -907,19 +897,16 @@ find: return 0; } -static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) +int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) { PVDevice pVDevice = ID_TO_VDEV(idDisk); DECLARE_BUFFER(PUCHAR, pbuffer); - if(idDisk == HPT_NULL_ID || check_VDevice_valid(pVDevice)) - return -1; + if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) return -1; -#if MAX_VBUS>1 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif UnregisterVDevice(pVDevice); pVDevice->VDeviceType = VD_SPARE; @@ -931,15 +918,13 @@ static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) return 0; } -static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) +int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) { PVDevice pVDevice = ID_TO_VDEV(idDisk); if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; -#if MAX_VBUS>1 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif pVDevice->VDeviceType = VD_SINGLE_DISK; @@ -948,19 +933,17 @@ static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) return 0; } -static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) +int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) { PVDevice pVDevice = ID_TO_VDEV(idArray); - if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) return -1; + if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; if (!mIsArray(pVDevice)) return -1; /* if the pVDevice isn't a top level, return -1; */ if(pVDevice->pParent != NULL) return -1; -#if MAX_VBUS>1 if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} -#endif if (pInfo->ValidFields & AAIF_NAME) { memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME); @@ -978,12 +961,12 @@ static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO return 0; } -static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) +int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) { PVDevice pVDevice = ID_TO_VDEV(idDisk); /* stop buzzer. */ - if(idDisk == HPT_NULL_ID) { + if(idDisk == 0) { #ifndef FOR_DEMO IAL_ADAPTER_T *pAdapter; for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { @@ -1000,9 +983,7 @@ static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO if (mIsArray(pVDevice)) return -1; -#if MAX_VBUS>1 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; -#endif /* if (pInfo->ValidFields & ADIF_MODE) { pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting; @@ -1013,7 +994,7 @@ static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO }*/ return 0; } -#endif /* SUPPORT_ARRAY */ +#endif #ifdef SUPPORT_HPT601 int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) @@ -1257,12 +1238,10 @@ int hpt_default_ioctl(_VBUS_ARG while(pAdapter != 0) { pVBus = &pAdapter->VBus; - for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) + for(i = 0; i < MAX_ARRAY_PER_VBUS; i++) { if(!(pTop = pVBus->pVDevice[i])) continue; -#if MAX_VBUS>1 if (pTop->pVBus!=_vbus_p) return -1; -#endif while (pTop->pParent) pTop = pTop->pParent; if (id==0 && pTop->vf_bootmark) pTop->vf_bootmark = 0; @@ -1277,10 +1256,9 @@ int hpt_default_ioctl(_VBUS_ARG } } break; -#endif /* SUPPORT_ARRAY */ +#endif case HPT_IOCTL_RESCAN_DEVICES: { - fRescanAllDevice(_VBUS_P0); if (nInBufferSize!=0) return -1; if (nOutBufferSize!=0) return -1; fRescanAllDevice(_VBUS_P0); diff --git a/sys/dev/hptmv/hptintf.h b/sys/dev/hptmv/hptintf.h index 9839a6718271..34477a258524 100644 --- a/sys/dev/hptmv/hptintf.h +++ b/sys/dev/hptmv/hptintf.h @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -162,7 +162,7 @@ typedef DWORD DEVICEID; * It would be better if ioctl code are the same on different platforms, * but we must not conflict with system defined ioctl code. ************************************************************************/ -#if defined(LINUX) || defined(__FreeBSD_version) +#if defined(LINUX) || defined(__FreeBSD_version) || defined(_MACOSX_) #define HPT_CTL_CODE(x) (x+0xFF00) #elif defined(_MS_WIN32_) || defined(WIN32) @@ -327,7 +327,6 @@ typedef struct _CHANNEL_INFO { * time represented in DWORD format */ #ifndef __KERNEL__ -#error "BAM" typedef struct _TIME_RECORD { UINT seconds:6; /* 0 - 59 */ UINT minutes:6; /* 0 - 59 */ @@ -399,7 +398,6 @@ typedef struct _HPT_ARRAY_INFO_V2 { * ATA/ATAPI Device identify data without the Reserved4. */ #ifndef __KERNEL__ -#error "BAM" typedef struct _IDENTIFY_DATA2 { USHORT GeneralConfiguration; /* 00 00 */ USHORT NumberOfCylinders; /* 02 1 */ @@ -781,7 +779,7 @@ HPT_IOCTL_PARAM32, *PHPT_IOCTL_PARAM32; * Returns: * interface version. 0 when fail. */ -DWORD hpt_get_version(void); +DWORD hpt_get_version(); /*-------------------------------------------------------------------------- */ @@ -807,7 +805,7 @@ int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap); * Returns: * number of controllers */ -int hpt_get_controller_count(void); +int hpt_get_controller_count(); /*-------------------------------------------------------------------------- */ @@ -1049,7 +1047,7 @@ int hpt_set_device_info_v2(DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo); * Returns: * 0 Success */ -int hpt_rescan_devices(void); +int hpt_rescan_devices(); /*-------------------------------------------------------------------------- */ /* hpt_get_601_info @@ -1210,59 +1208,5 @@ int hpt_remove_devices(DWORD ndev, DEVICEID *pIds); #endif -#if BITS_PER_LONG > 32 -#define VDEV_TO_ID(pVDev) (DEVICEID)(ULONG_PTR)(pVDev) -#define ID_TO_VDEV(id) (PVDevice)(((ULONG_PTR)gIal_Adapter & 0xffffffff00000000) | (id)) -#else -#define VDEV_TO_ID(pVDev) (DEVICEID)(pVDev) -#define ID_TO_VDEV(id) (PVDevice)(id) -#endif - -#define INVALID_DEVICEID (-1) -#define INVALID_STRIPSIZE (-1) - -#define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8)) - -#ifndef MinBlockSizeShift -#define MinBlockSizeShift 5 -#define MaxBlockSizeShift 12 -#endif - -typedef struct _HPT_IOCTL_TRANSFER_PARAM -{ - ULONG nInBufferSize; - ULONG nOutBufferSize; - UCHAR buffer[0]; -}HPT_IOCTL_TRANSFER_PARAM, *PHPT_IOCTL_TRANSFER_PARAM; - -typedef struct _HPT_SET_STATE_PARAM -{ - DEVICEID idArray; - DWORD state; -} HPT_SET_STATE_PARAM, *PHPT_SET_STATE_PARAM; - -typedef struct _HPT_SET_ARRAY_INFO -{ - DEVICEID idArray; - ALTERABLE_ARRAY_INFO Info; -} HPT_SET_ARRAY_INFO, *PHPT_SET_ARRAY_INFO; - -typedef struct _HPT_SET_DEVICE_INFO -{ - DEVICEID idDisk; - ALTERABLE_DEVICE_INFO Info; -} HPT_SET_DEVICE_INFO, *PHPT_SET_DEVICE_INFO; - -typedef struct _HPT_ADD_DISK_TO_ARRAY -{ - DEVICEID idArray; - DEVICEID idDisk; -} HPT_ADD_DISK_TO_ARRAY, *PHPT_ADD_DISK_TO_ARRAY; - -int check_VDevice_valid(PVDevice); -int hpt_default_ioctl(_VBUS_ARG DWORD, PVOID, DWORD, PVOID, DWORD, PDWORD); - -#define HPT_NULL_ID 0 - #pragma pack() #endif diff --git a/sys/dev/hptmv/hptproc.c b/sys/dev/hptmv/hptproc.c index 997183fa2cca..a179e320d55e 100644 --- a/sys/dev/hptmv/hptproc.c +++ b/sys/dev/hptmv/hptproc.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -35,6 +35,10 @@ #include #include +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + #include #include #include @@ -45,13 +49,15 @@ int hpt_rescan_all(void); /***************************************************************************/ static char hptproc_buffer[256]; +extern char DRIVER_VERSION[]; #define FORMAL_HANDLER_ARGS struct sysctl_oid *oidp, void *arg1, int arg2, \ struct sysctl_req *req #define REAL_HANDLER_ARGS oidp, arg1, arg2, req typedef struct sysctl_req HPT_GET_INFO; -static int hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length) +static int +hpt_set_asc_info(IAL_ADAPTER_T *pAdapter, char *buffer,int length) { int orig_length = length+4; PVBus _vbus_p = &pAdapter->VBus; @@ -118,7 +124,7 @@ rebuild: if(pVDev == _vbus_p->pVDevice[i]) { periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId,i); - if (periph != NULL && periph->refcount == 1) + if (periph != NULL && periph->refcount >= 1) { hpt_printk(("Can not use disk used by OS!\n")); return -EINVAL; @@ -138,9 +144,9 @@ loop: unlock_driver(oldspl); return -EINVAL; } - pArray->u.array.rf_auto_rebuild = 0; - pArray->u.array.rf_abort_rebuild = 0; - hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); + pSubArray->u.array.rf_auto_rebuild = 0; + pSubArray->u.array.rf_abort_rebuild = 0; + hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pSubArray, DUPLICATE); unlock_driver(oldspl); break; } @@ -225,7 +231,7 @@ loop: } else #endif -#endif /* SUPPORT_ARRAY */ +#endif if (0) {} /* just to compile */ #if DBGUG else if (length>=9 && strncmp(buffer, "dbglevel ", 9)==0) { @@ -239,7 +245,7 @@ loop: else if (length>=8 && strncmp(buffer, "disable ", 8)==0) { /* TO DO */ } -#endif +#endif return -EINVAL; } @@ -248,7 +254,8 @@ loop: * Since we have only one sysctl node, add adapter ID in the command * line string: e.g. "hpt 0 rebuild start" */ -static int hpt_set_info(int length) +static int +hpt_set_info(int length) { int retval; @@ -256,7 +263,7 @@ static int hpt_set_info(int length) PUCHAR ke_area; int err; DWORD dwRet; - PHPT_IOCTL_PARAM32 piop; + PHPT_IOCTL_PARAM piop; #endif char *buffer = hptproc_buffer; if (length >= 6) { @@ -270,14 +277,14 @@ static int hpt_set_info(int length) return -EINVAL; } #ifdef SUPPORT_IOCTL - piop = (PHPT_IOCTL_PARAM32)buffer; + piop = (PHPT_IOCTL_PARAM)buffer; if (piop->Magic == HPT_IOCTL_MAGIC) { - KdPrintE(("ioctl=%d in=%x len=%d out=%x len=%ld\n", + KdPrintE(("ioctl=%d in=%p len=%d out=%p len=%d\n", piop->dwIoControlCode, piop->lpInBuffer, piop->nInBufferSize, piop->lpOutBuffer, - (u_long)piop->nOutBufferSize)); + piop->nOutBufferSize)); /* * map buffer to kernel. @@ -293,28 +300,22 @@ static int hpt_set_info(int length) return -EINVAL; } - err = 0; if (piop->nInBufferSize) - err = copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize); + copyin((void*)(ULONG_PTR)piop->lpInBuffer, ke_area, piop->nInBufferSize); /* * call kernel handler. */ - if (err==0) - err = Kernel_DeviceIoControl(&gIal_Adapter->VBus, - piop->dwIoControlCode, ke_area, piop->nInBufferSize, - ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet); + err = Kernel_DeviceIoControl(&gIal_Adapter->VBus, + piop->dwIoControlCode, ke_area, piop->nInBufferSize, + ke_area + piop->nInBufferSize, piop->nOutBufferSize, &dwRet); if (err==0) { - if (piop->nOutBufferSize) { - err = copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize); - if (err) KdPrintW(("Kernel_ioctl(): copyout (1) return %d\n", err)); - } + if (piop->nOutBufferSize) + copyout(ke_area + piop->nInBufferSize, (void*)(ULONG_PTR)piop->lpOutBuffer, piop->nOutBufferSize); - if (piop->lpBytesReturned) { - err = copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD)); - if (err) KdPrintW(("Kernel_ioctl(): copyout (2) return %d\n", err)); - } + if (piop->lpBytesReturned) + copyout(&dwRet, (void*)(ULONG_PTR)piop->lpBytesReturned, sizeof(DWORD)); free(ke_area, M_DEVBUF); return length; @@ -335,7 +336,8 @@ static int hpt_set_info(int length) #define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8)) -static void get_disk_name(char *name, PDevice pDev) +static void +get_disk_name(char *name, PDevice pDev) { int i; MV_SATA_CHANNEL *pMvSataChannel = pDev->mv; @@ -346,7 +348,8 @@ static void get_disk_name(char *name, PDevice pDev) name[20] = '\0'; } -static int hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) +static int +hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) { int printfretval; va_list ap; @@ -364,28 +367,38 @@ static int hpt_copy_info(HPT_GET_INFO *pinfo, char *fmt, ...) } } -static void hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan) +static void +hpt_copy_disk_info(HPT_GET_INFO *pinfo, PVDevice pVDev, UINT iChan) { - char name[32], arrayname[16]; - + char name[32], arrayname[16], *status; + get_disk_name(name, &pVDev->u.disk); + + if (!pVDev->u.disk.df_on_line) + status = "Disabled"; + else if (pVDev->VDeviceType==VD_SPARE) + status = "Spare "; + else + status = "Normal "; -#ifdef SUPPORT_ARRAY - if(pVDev->pParent) +#ifdef SUPPORT_ARRAY + if(pVDev->pParent) { memcpy(arrayname, pVDev->pParent->u.array.ArrayName, MAX_ARRAY_NAME); + if (pVDev->pParent->u.array.CriticalMembers & (1<bSerialNumber)) + status = "Degraded"; + } else #endif - arrayname[0]=0; + arrayname[0]=0; hpt_copy_info(pinfo, "Channel %d %s %5dMB %s %s\n", iChan+1, - name, pVDev->VDeviceCapacity>>11, - ((!pVDev->u.disk.df_on_line)? "Disabled" : - ((pVDev->VDeviceType != VD_SPARE)?"Normal ":"Spare ")), arrayname); + name, pVDev->VDeviceCapacity>>11, status, arrayname); } #ifdef SUPPORT_ARRAY -static void hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) +static void +hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) { int i; char *sType=0, *sStatus=0; @@ -438,7 +451,7 @@ static void hpt_copy_array_info(HPT_GET_INFO *pinfo, int nld, PVDevice pArray) if (pTmpArray->u.array.rf_rebuilding) { #ifdef DEBUG sprintf(buf, "Rebuilding %dMB", (pTmpArray->u.array.RebuildSectors>>11)); -#else +#else sprintf(buf, "Rebuilding %d%%", (pTmpArray->u.array.RebuildSectors>>11)*100/((pTmpArray->VDeviceCapacity/(pTmpArray->u.array.bArnMember-1))>>11)); #endif sStatus = buf; @@ -463,7 +476,8 @@ out: } #endif -static int hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) +static int +hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) { PVBus _vbus_p = &pAdapter->VBus; struct cam_periph *periph = NULL; @@ -535,7 +549,8 @@ static int hpt_get_info(IAL_ADAPTER_T *pAdapter, HPT_GET_INFO *pinfo) return 0; } -static inline int hpt_proc_in(FORMAL_HANDLER_ARGS, int *len) +static __inline int +hpt_proc_in(FORMAL_HANDLER_ARGS, int *len) { int i, error=0; @@ -552,7 +567,8 @@ static inline int hpt_proc_in(FORMAL_HANDLER_ARGS, int *len) return (error); } -static int hpt_status(FORMAL_HANDLER_ARGS) +static int +hpt_status(FORMAL_HANDLER_ARGS) { int length, error=0, retval=0; IAL_ADAPTER_T *pAdapter; @@ -598,7 +614,7 @@ out: SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node") \ SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ NULL, 0, hpt_status, "A", "Get/Set " #name " state") -#else +#else #define hptregister_node(name) \ SYSCTL_NODE(, OID_AUTO, name, CTLFLAG_RW, 0, "Get/Set " #name " state root node"); \ SYSCTL_OID(_ ## name, OID_AUTO, status, CTLTYPE_STRING|CTLFLAG_RW, \ diff --git a/sys/dev/hptmv/i386-elf.raid.o.uu b/sys/dev/hptmv/i386-elf.raid.o.uu index f8d041348847..a7462b8f1ef2 100644 --- a/sys/dev/hptmv/i386-elf.raid.o.uu +++ b/sys/dev/hptmv/i386-elf.raid.o.uu @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -25,1322 +25,1359 @@ * * $FreeBSD$ */ -begin 664 hptmvraid.o -M?T5,1@$!`0D```````````$``P`!``````````````#0N````````#0````` -M`"@`#``)`%6)Y5=64X'L%`(``(M]"(M'#(F%\/W__X!_`0"-=\0/A5<%``"` -M?P(`#X1%!0``L0&`3@$$B`Z+1PR)1@@/ML&+5Q"+!(4`````@/D#QT8$```` -M`(E6#(E&-'0<#[8&BP2%`````(!.`02)1CB-9?1;7E_)PXUV`(U"]HV5]/W_ -M_XE&#%)J((M'$(/H"E!7Z/S___^#Q!"!O?3]___S%GA:=;EHD````(V%]/W_ -M_U#H_/___X3`6EEUHHJ%_?W__X/@`H3`=!;&1P@!BH7^_?__.D<)B$<+#X*# -M!```:``"``"-E?3]__]2Z/S___^$P%I9#X5(!```BI6'_O__BD<$B-.#XP&# -MX/R(T8/A`@G8"3]__\/A,S^ -M__\QT@^VG?_]__\YVGTMC8WT_?__@\$0B@$\"`^'K/[__P^VP(L$A0````"% -MP`^$FO[__T*#P1`YVGSC]__^)5TR*A17^__^(1SR*E13^__^(%XN%$/[__XE'#(E? -M!(J-%_[__[@!````T^"(3SYFB4=$#[;2BP25`````(E'-`^V`XL$A0````") -M1SB*A>_]__^(1P.+E>#]__^-A?3]__^)?)-0_D,]@\`L:A!0C4=P4.C\____ -MC87T_?__:@2#P#Q0C8>`````4.C\____C87T_?__:A"#Z(!0C8?$````4.C\ -M____@\0DC87T_?__:D"#P$!0C8>$````4.C\____@\0,Z6;^__\/MH7O_?__ -MBU2#4(72#X5/^___B72#4/Y#/8J5[_W__XA6`P^V`XE>!(L$A0````#I-/S_ -M_VAP`0``C87T_?__:@`%D````%#H_/___X/$#.F8^___#[;`4%?H_/___UM8 -MZ6S[__^-=@"Q`^FV^O__D+$"Z:[Z__^058GE5E.+=0PQVP^V1CPYPWT/B?:+ -M5)Y0A=)T#$,YPWSSC67X6U[)PXC9N`$```#3X&8)1DA6_W4(Z/S___^)PH72 -M6%ETV\8"`X`^"`^4P(I*`<'@`X/A]PG!B$H!B%H#H0P```")0C0/M@:+!(4` -M````B7($B4(XBD8!@^`0A,!T#(/)$(M"3(A*`8E"#(E4GE"*1D:#X/Z#R`J( -M1D;'1DP`````_D8]4FH'Z/S___^`3D8$6U[I9O___Y!5B>575E-7BT4(B47P -MBUT,#[8#@_@�X`0``@_@&#X^+````@_@$?`J*4SPX4SUT-8GVBTL$AG\____ -M@$L!!(!C1OXQ_X32=+^-=@"+=+M0A?9T!8`^`W<*1P^VPCG'?.OKI5;_=?#H -M_/___XI&1H/@!%F$P%YT!(!+1@2*4SSKV(UV`(/X"`^%>____XI#/8I3/#C0 -M='(/ML!`#[;2.=!T#@^W0T3WV"%#3.E8____9HM#2&:%P'1"#[?0,7^O=BE-&B-"#X`*$P'71Z]N*0T:#X/Z`2P$$9H-[2`"(0T9T -MA8/(`HA#1NEZ____@$L!!(![/0)T/HM#4(!C1OV%P'41BT-4QD`#`(E#4,=# -M5`````"`.`-T$(!+1@3'0TP`````Z:7^__]3_W7PZ/S___]86NOC@&-&_NF/ -M_O__C78`58GE5U:+?0A3O@\```"-GV`B``"+0T"%P'0'BT,$A7\G#D%-7Z/S___^*0P&#X`1:A,!9=-O'0S@`````Z])5B>57 -M5E.![`0"``"+=0R*11!6B(7S_?__Z/S___^`/@A9#X3I````BD8\,?\\`'9_ -MC78`BUR^4(7;=&V`.P,/A[,```"*4P&#XO[&0P,`QT-0`````(A3`8"]\_W_ -M_P#'0P0`````QT,X`````'4%@#X&=&QH``(``&H`C97T_?__4NC\____C87T -M_?__4&HP:@"-0SQ0Z/S___^#Q!Q3Z/S___]8BD8\1XGZ.-!WA&C4````:@!6 -MZ/S___^+50B+@EPB``")1@B)LEPB``"#Q`S'1D``````C67T6UY?R<.+1@2% -MP'6-BD8!@^`!"<*(4P'KJHUV``^VA?/]__]0_W2^4/]U".C\____@\0,ZY56 -M_W4(Z/S___]86ND'____C78`58GE5U93@>P,`@``BU4,BP*+6`2)G?#]__^+ -M6B"+4Q2)E>S]__^+M>S]__\/MD`#A?:+?1"+312)A>C]__^-E?3]__\/A+,` -M``!F#[9#$(/@`0^WP#G(#X2@````#[=3+,'B"0^V6RB+C>S]__]FBT$$9H7` -MBS$/M\AU"+D```$`C78`.C]__]T6"G!`<8IPG4=BY7P_?__ -M#[9"/$,YPP^4P`^VP$@/MU)$(S]___KDF;'1_X`@+@!````C67T6UY?R<.-=@!FB4<$9L='!@``B3>#QPCK -MEXM#&(7`B97L_?__=00QP.O345)3_W4(_]"#Q!"%P`^%//___^OGD%6)Y5=6 -M4X/L"(M%"(M0!(E5\(M=#(I0`XI+*#C*BWLD9HMS,'1B.,IS"8M%\`^W0$0! -MQSC*=$F*0RDXPG0Z@'LT`'0D.,IV"SC"

+1?!F`W!$BU409HER"(EZ!(/$ -M"%M>7\G#C78`.,IVW(M-\&8#<43KTXUV`&8#S(`6G47@'L1`'4$QD,1`5/_7\G#_W4(Z/S___^)PXM%\(M$L%") -M1>R)`XE[((I7$(I#$(/B`H/@_0G0B$,0BE<0@^($@^#["="(0Q"*1PJ(0PI3 -M5_]U[.A\_?__QT,<`````,=#&`````!3_W4(BU7L_U(TBTWP@\08BE$\Z7K_ -M__^)]L9'$0)7_W<<_W4(Z/S____I<____XUV`%6)Y8M5#(M*!(I!`<#H`H!B -M`?OWT(M1.(/@`8!A`?O^23V`248!A=)T!(7`=`+)PU'_=0C_TEA:Z_2)]E6) -MY593BT4,BU`@BTH4AR<,QP.OUD(I&`<#H`H/@`0^VP.OFB?95B>575E.#[`B+?0R+7R"+`XLW -MB47PB77LBD\1@/D!=$^*4Q"(T(/@`H3`#X3/````@'L2`'4YBU7PBD)&@^`" -MA,!U+,9#$@$QP(!^`P`/E,"+=()0A?9T$U;H2?___X7`6G5UBP>)1>R*3Q&+ -M=>R0B$L15_]U".C\____#[9.`[C^____T\!F(T,R9HE#,E]FAQ$` -M=03&0Q$!4_]S'/]U".C\____BU7P9HM"%DB#Q`QFA7\G#:C"-1R1J`%#H_/___P^V3@.X`0```-/@9HE# -M,HDW5_]U"/]6-.O1@^($A-(/A&7___]6Z)?^__^%P%EU*8![$0$/A%/___\/ -MMDX#N`$````/MU,RT^`YP@^%//___XI/$>DQ____:C!J`(U')%#H_/___^NI -MB?95B>56BW444XM5#(7VBUT0BTH@=".+00R)`V:+0@C!X`EFB4,$9L=#!@"` -MN`$```"-9?A;7LG#D(M1%(72="V*01"#X`&$P'0CB=&0BP&+402)4P2)`V:+ -M008E`(#__X/#"(/!"&:%P'3BZ[^+01B%P'4$,<#KN5934?]U"/_0ZZ^-=@!5 -MB>575E.+=0R+!@^V2`.X_O___]/`BUX@BWT(9B%#,HI&$3P!=`.(0Q%65^C\ -M____66:#>S(`6'4X@'L1`'4.QD,1`8L+BU%,.U8$="Q3_W,<5^C\____BP-F -MQT`4``"#P!A0:`````!7Z/S___^#Q!B-9?1;7E_)PP^W1@B-!!")04SKR(GV -M58GE5U93BW4,BD81/`&+?0B+7B!T-HA#$597Z/S___]3_W,<5^C\____BP-F -MQT`4``"#P!A0:`````!7Z/S___^-9?1;7E_)PXUV`(!^"B!T&L9#$0&+"XM1 -M3#M6!'6Y#[=&"(T$$(E!3.NMBP/&1A$`BT!4B09J,&H`C48D4.C\____BD80 -M@^#]@\@$B$80QD82`,9&"C"+!E97_U`TZZ"-=@!5B>575HM5%%.+10R%THM] -M$(M(('1"BTD,B0]FBU`(P>()9HE7!&;'1P8`@(L`@'@#`'0-9H72=!@'L#``^$;?___SG/#X1E____BP&+402)5P2)!V:+008E`(#__X/' -M"(/!"&:%P'3BZ4+___^)T&8I\`$Q9HE!!.N^.?)RLV:)<01FQT$&`(#KKHM! -M&(7`=0?___\9#$0&+"XM13#M6!`^%9____P^W1@B- -M!!")04SI6/___XUV`%6)Y5=64XM=#(LSBD9&@^`!A,#'1AP`````=14/MD,* -M@_@"#X3_````@_@"?WY(="S&0Q$&4_]S'/]U".C\____@\0,C4884&@````` -M_W4(Z/S___^-9?1;7E_)PXM#!(E&$&:+0PAFB484_W4(Z/S____&0`H@B<*+ -M0P2)0@1FBT,(@$H0`F:)0@B)6B#'0AP`````QT(8`````(M&4(D"4O]U"/]0 -M-.N7B?:#^`-U@(M#!(E&$&:+0PAFB484#[=#",'@"5!J`/]S#.C\____,?]F -MQT,R`P"#Q`S_=0CH_/___\9`"C")PHM#!(E"!&:+0PAFB4((@$H0!(E:(,=" -M'`````#'0A@`````BT2^4(D"4O]U"$?_4#2#Q`R#_P%^N>D<____BT,$B480 -M9HM#"&:)1A3_=0CH_/___\9`"B")PHM#!(E"!&:+0PAFB4((@$H0`HE:(,=" -M'`````#'0A@`````Z3#___]5B>575E.#[!"+10B+?0R)1?"+-XI&`8/@!(3` -M#X32`0``BD<0@^`@A,!T-&:#?A8`QT8<7!,``(E^('0+C67T6UY?R<.-=@"+ -M5?")?0R)50B-9?1;7E_)Z3?^__^-=@"+1AR%P`^%;0$``&:+1A1FA0`````BTWDBT2.4(7`=!^*0`&#X`2$P'05BD<0@^`$ -MA,!U'(I%[SA%[G04C78`_D7O_T7D@'WO`7;*Z2#_____=?#H_/___VHD5U") -MP^C\____BDWDN`$```#3X&8)1S*)>R#'0QP`````QT,8`````(M5Y(M$EE") -M`U/_=?#_4#2#Q!CKJ(`Y`P^%5O___XM?!(M"6"M95(E%Z(M'!"M"5(M)6'A! -MA=MX.3G8?1^%R<9%[@`/A3G___^#?>@%#X8O____QD7N`>DF____BUWHA=O& -M1>X`=>R#^04/AQ+____KX??;Z\/WV.N[C78`QD7N`.G\_O__C78`C488QT7\GI_/___\9'$0)7_W<<_W7PZ/S____I-/[__XUV -M`%6)Y5=64XMU#(M>!(M]"(!F`?N*0SV*4T9(@\H!A,`/MDX#QT-,`````(A3 -M1HA#/703B-"#X`*$P'0.@^+5AC\____B4-`B5T(C67T6UY?R>G\____ -M4U?_T%A:Z\R%R744BU-0BT-4QD(#`8E#4,9``P")4U2+4P2%TG0*BD(!@^`$ -MA,!TIHM#4(`X`W6>4U?H_/___X7`68G"7W2,Q@`#QD`#`8E8!*$,````B4(T -MH1@```")0CB*0P&#X!"$P'0*BT),@$H!$(E"#,=&!`````"*0T:#X/Z#R`J) -M4U2(0T;^0SU2:@?H_/___^EH____B?95B>575E.![!`"``"+10R+$(M`((MP -M%(7VB97P_?__BTT4B87D_?__QX7L_?__$0```(V5]/W__P^$5@$``&8/MD`0 -M@^`!#[?`.<@/A$,!``"+O>3]__^`?RG_#X2E````9HM&!`^W7RS!XPEFA<`/ -MM\AU!;D```$`.O]__^+O>3]__^*5RB-=@`X -ME>O]__\/A)P```"#Q@AFBT8$*.`#4%;_=1#H_/___[@!````C67T6UY? -MR<-FQT<&`(#KZXM5$(L&B0)FB5H$9L="!@"`Z]B-=@"+?1"+!HM6!(E7!(D' -MBX7P_?__@\<(BD`#B7T0B(7K_?__B[WD_?__BEO]__^+O>3]__^*5RCI-____XUV`(N=Y/W__XM#&(7`B=9U!S'`Z73___]1 -M4E/_=0C_T(/$$(7`#X64_O__Z^2058GEBTT,4XI1*(M%"#A0`XM=$'079HM! -M*F:)0PC'0P0`````BQPDR<.-=@!FBT$L9HE#"(M!)(E#!.OH58GE5U93@^P, -MBWT,9HM'"(M?!(MU"&:)1?**1CPQR83`B$7KQT7L`````'09C78`BU2.4(M" -M##G#7\G#N`$```#3X&:+=S()QHE?)(A/ -M*&:)=S(/MT7RC008.T(,=C*-00''1>P!````B$S(` -M6G47@'L1`'4$QD,1`5/_ -M7\G#_W4(Z/S___^)PXM%\(M$L%")1>R)`XE[((I7$(I#$(/B`H/@_0G0B$,0 -MBE<0@^($@^#["="(0Q"*1PJ(0PI35_]U[.@(_O__QT,<`````,=#&`````!3 -M_W4(BU7L_U(TBTWP@\08BE$\Z7K___^)]L9'$0)7_W<<_W4(Z/S____I<___ -M_XUV`%6)Y8M%#(!@`?N+4`2+0CB`8@'[_DH]@$I&`87`=07)PXUV`%+_=0C_ -MT%A:Z_&)]E6)Y8M-#%.+70B+E(N\+P``A=)T"8L"B82+O"\``(G0BQPDR<.- -M=@!5B>6+51!3BUT(BX23O"\``(M-#(D!B8R3O"\``(L<),G#B?95B>575E.# -M[`B+10P]``@``(M5$+X`$```=T0]``0``+X`"```=S@]``(``+X`!```=RP] -M``$``+X``@``=R`]@````+X``0``=Q2#^$`/A]P```"#^"$9]H/FX(/&0`^O -MUH'"_P\``(E5\,%M\`S_3?"#??#_QT7L``````^$FP```)#_=0CH_/___XG# -M,=*X`!```#'_]_;_1>PYQUES<(UV`('^``@``+@'````=T.!_@`$``"X!@`` -M`'>)GN`O``!J`E=6Z/S]__^-9?1;7E_)PU6)Y593BW4(BQY+@_O_ -M=!EH`!```&H`_W2>!$OH_/___X/$#(/[_W7GC67X6U[)PU6)Y5.+70B+"TF# -M^?]T((M$BP0QTHUV`(,X`'4:0H/`!('Z_P,``';O28/Y_W7@N`$```!;R<,Q -MP.OYD%6)Y6H0:@#_=0CH_/___\G#C78`58GEBTT,BU$,A=)T!HM!"(E""(M! -M"(D0QT$(`````&H`4?]U".A*_?__R<-5B>564XM="(M#,(M-#(7`C7,PB4$, -M=`F+4S"-00R)0@B)<0B)2S!;7LG#D%6)Y5=64XM%#(M8,(7;BWT0BW44=!*) -M]CDSP1W*XM;#(7;=?!J`/]U".C"_/__B3B)<`10B575E.+=0P/ME8FC4+]T?@QVP'" -M.=.+?0A\$VH'5E?H;OS__XUE]%M>7\G#B?;_M)Z<"```5^@7_O__6%H/ME8F -MC4+]T?A#`<(YTWSAZ\R-=@!5B>575E.#[!2*10R+512(1?-FB57PBT4(BY#@ -M+P``#[9-\P^W1?")1>2-0?W1^(T$",'B`P^O1>0YP@^#@P```(M5"('"I"\` -M`(E5X(G/D(M%"(N8I"\``#M=X`^$+`$``(L#BU,$B5`$B0*+0Q")WH7`B1Z) -M7@1T%HM3%(72=`.)0A"+1A")$,=&$`````"+5?!F.5,D#X3W````4_]U".@& -M____6(M%"%J+D.`O``"-1_W1^(T$.,'B`P^O1>0YPG*,:@?_=0CH2OO__XG& -M7U@QP(7V#X2"````BU40B58@BE7SBT7PB%8F#[95\V:)1B2-0OW1^#'_C000 -M.<>)-HEV!,=&&`````!]3V;!;?`##[=5\(E5Z(E%[/]UZ/]U".AY_/__B82^ -MG`@``%F%P%MT,HG[P>,$C1PSC8/$"```4('#1`D``.AJ_?__1U/H8_W__UD[ -M?>Q;?,")\(UE]%M>7\G#3X/__W07_[2^G`@``/]U"$_HA/S__UB#__]:=>EJ -M!U;_=0CHLOK__S'`Z\R)]HI%\SA#)@^%_?[__P^VP(M5$(7`B1N)6P2)4R!T -M%8VS1`D``(G'5NCX_/__@\803UEU\XG8ZY.058GE5U93@^P(BT449HE%\HM5 -M#(M]$`^V2CZ)^-/H)?\#``"+4BR-'(*+,X7V=`V0.7X@=&N+=A2%]G7T#[=% -M\E!7BU4,#[9"/%#_=0CHXOW__X/$$(7`B<9T.XM-#(E('(L#A<")1A1T"(L3 -MC484B4(0BT4,B3.)7A"*6#R(7B8/MD@^T^\QT@^V2#R)^/?Q*--+B%XGC67T -M6XGP7E_)PXM6!(L&B5`$B0*)=@2)-NOEC78`58GE5U93@>RT````BT4,BE`0 -MB-#0Z(G!]]�&)C6#___^+30R+012%P'0+@^(!A-(/A%0"``!J`8V%9/__ -M_U#_=0S_=0B)A5S___^+50S_4AB#Q!"+C5S___]FBT$$#[?09H7`B95$____ -M=0K'A43___\```$`QX5,____`````(M-#(I11(32QX58____``````^$C0$` -M`(M-#(N%6/___XM$@3")A5#___^*B!P*``"(C5?___^*@!T*```XA5?___\/ -MAT8)`=>-=@"+A43___\YA4S_ -M__\/A-(```"+G43___\KG4S___\Y\W8"B?.+A6#___^%P`^$F@```%.+A4S_ -M__^+E5S___\#`E!7Z/S___^#Q`P!G4S___\IWG0$`=_KIXN%2/___V8IA4K_ -M__]T%O^%0/___S'29L>%2/___P@`Z3[___^+E5#___^*@AT*``#^A5?___\X -MA5?___\/AK_^__^+30R*443_A5C___\/ML(YA5C___\/C'/^__]J`/]U#/]U -M"/]5$(UE]%M>7\G#B?935XN%3/___XN-7/___P,!4.EA____B?:#A5S___\( -MBY5<____9HM"!`^WR&:%P(F-1/___W4*QX5$____```!`,>%3/___P````#I -M]O[__XF%7/___^F__?__D%6)Y5=64X/L%(M%"(E%\(M%$(7`BWT,=`3&1Q$+ -MQT7L`````(!_1``/A)\```"+5?"+1?"!PJPO```%I"\``(E5Z(E%Y(UV`(M5 -M[(M,ES"*028QVSC#QX'T"0```````(A%XW-"C78`#[;#P>`$C00(C9#$"``` -MBX#$"```,?:%P'45BT($A+0@R%P'0%O@$```"%]G5(0SI= -MXW+!,<"%P'0WBU7HBT($B1&)2@3_1>R)002)"`^V1T0Y1>P/C'O___^+1?") -M?0R)10B#Q!1;7E_)Z59```")]HM5Y.O'N`$```#KN56)Y5=64X/L&(M=#(M% -M"/^(Y"\``(E%\(NS]`D``(U#"(M(!(M3"(7VB4H$B1&)0`2)0P@/A)8"``"* -M5A"(T(/@((3`#X3R````#[=3)(M%\`6D+P``B57D`U,@B57HBU`$B0.)6`2) -M&HJ#'@H``#P!BS['@_0)````````B5,$=0J`?@H"='<\`708B$81BT7PB74, -MB44(C67T6UY?R>FD/P``BT8$0`^W5T0/K\(Y1>AR&P-73#M5Z'0+BU7PB74, -MB54(Z]&+1>B)1TSK[?]UY/]UZ%?_=?#HYOK__XFP]`D``(E&,(M5\(E%#(E5 -M"(/$$(UE]%M>7\GI50X```^V0R?_M(.<"```Z&7W__^%P%IU',:#'@H```P/ -MMT=$@$]&"O?8(T,@.4=,=@.)1TR*@QX*``#I3?___Y"*1D5`BDY$.,B(1D4/ -MA(H```"+5?"+@N@O``"%P'0)@+L>"@```70(C67T6UY?R<.+4QR+2B2%R746 -MA7\GI_/___U+H(CT``(7`6G0+BU7PBX+H+P``Z]2+ -M0QS_<"B+0QS_<"3_=?#H_/___XM#'(M5\,=`)`````"+@N@O``!(@\0,B8+H -M+P``ZZ&-=@"#X@2$T@^$F0```,9%[P`X3>]S4HM%\(M5\`6D+P``@<*L+P`` -MB47@B57^+7(8PBH,>"@``/`''@_0)````````="Z(1A&+5=R+0@3^ -M1>^)6@2)$XE#!(D8BD7O.D9$7^D`____,?^)^#I#)G(% -MBU7@Z\J)^@^VPL'@!(V$&,0(``!01^@^]O__6(GX.D,F]S -M((UV``^V1>^+7(8PBH,>"@``/`%T`XA&$?Y%[SA-[W+C@'X1`'46:"`E``!6 -M_W7PZ+_Y__^#Q`SIC?[__VH`5O]U\.A$_/__Z^N)]H"['@H```$/A)\```"+ -M1?`%K"\``(M0!(D#B5@$B1J)4P2+D_@)``"%TG55_W,8_W7PZ+WU__^+0QS' -M0Q@`````BW@86H7_674IBU7PB[+L+P``A?8/A"/^__^)T`7L+P``4&@````` -M4NC\____Z7;___^#P!A0:`````#_=?#KZ(J#'@H``(A"$?^S^`D``&A89@`` -M_W7PZ/S____'@_@)````````Z>C]__\Q]HGR.E,F6+ -M10R+`(!X*@!U`LG#QD`J`%!H2#,``/]U".C\____@\0,Z^>058GE5U93@^P( -MBU4,BT(@BP@/MD`)BX2!G`@``(E%\(M"!"M!(,'@"0^W6@B)PL'H#(M]$,'C -M"8'B_P\``(E%[+X`$```*=8YWG8"B=Z+112%P'0\BT7LBTWP`U2!!#G>B1=F -MB7<$=!)FQT<&``#_1>R#QP@I\S'2Z\9FQT<&`("-9?1;7K@!````7\G#C78` -MBTWPBT7L`U2!!%+H_/___XG"6>NYC78`58GE5U93BUT(BD,+`$,*C7,,B?:* -M4PH/MLJ#^1\/AZ4```"X`0```-/@A4,,#Y7`#[;`A7\G##[;ZQD,+`8GVBE,+#[;"C0PX@_D?=R:X`0```-/@A4,,#Y7` -M#[;`AB$8&4E?H_/___UF`?@8!6'06QD8%`HEU#(E]"(UE]%M>7\GI -MW/W__U;HIO[__X7`6G5"@'X$`779BD8(.D,G=-$Z1@EUS`^VP,'@!(T$&(M6 -M#`F01`D``(U>#(V(1`D``(M#!`E!!(M#"`E!"(M##`E!#.N=QD8&`(EU#(E] -M"(UE]%M>7\GK*%6)Y593BUT,BW4(QD,+`,9#"@!3Z#/^__]8B5T,B74(C67X -M6U[)ZP!5B>575E.+70R+,XM6'`^V0PB+?()0_W4(Z/S___^).(![!`&)PEAT -M.X!*$`3&0@HP#[9#"@-&((E"!&8/MD,+9HE""(E:(,="&"`J``#'0AS@*P`` -M4O]U"/]7-(UE]%M>7\G#@$H0`L9""B#KPXGV58GE5U93@^P(,?\QVXUV`(/[ -M'P^'\P```+@!````B-G3X(M5"(4"#Y7`#[;`A<"^`0```'42@_M_=P-#Z]*# -MQ`A;7HGX7\G#C10>@_H?=VB(T;@!````T^"+30B%`0^5P`^VP(7`=`-&Z]V) -M7>R)TXM%[(M-#,'H`X@$N8I%[(/@!XA$N0&Q""C!BT4,B$RX`@^VP3GP#^G\/AEW____KB8UV`(/Z/W<3C4K@N`$```#3 -MX(M-"(5!!.N/D(/Z7W<5C4K`N`$```#3X(M-"(5!".ET____@_I_=Q6-2J"X -M`0```-/@BTT(A4$,Z5K___\QP.E9____D(/[/W<7C4O@N`$```#3X(M-"(5! -M!.D!____B?:#^U]W%XU+P+@!````T^"+50B%0@CIY?[__XGV@_M_=Q6-2Z"X -M`0```-/@BTT(A4$,ZP8`0``BT4,BU@( -M@'L5`(LP#X0"`0``BWL0A?]U"XE#$(UE]%M>7\G#C87T_O__QD,5`%!3Z%?^ -M__^)A>#^__\/MD,4BX2&G`@``(F%Z/[__XM#$`^V0`R+A(:<"```B87<_O__ -MBU4,#[9"#(N$AIP(```Q]ED[M>#^__^)A>3^__];?7`/MH2U]/[__P^VG+7U -M_O__B[W<_O__BU2'!,'C"0':#[:,M?;^__^)E>S^__^+E>3^__^+?(($`=^) -MO?#^__^+E>C^__\#7(($BX7L_O__P>$).=AT+E'_M?#^__]04^C\____@\00 -M1CNUX/[__WR0:@#_=0S_=0CHYP(``.D:____B?915U#H_/___X/$#.O6C78` -MC87T_O__4%/H:_W__XF%X/[__P^V0Q2+A(:<"```B87H_O__BWT,#[9'#(N$ -MAIP(```Q]HF%W/[__SNUX/[__UA:?9@/MI2U]/[__P^VG+7U_O__B[WH_O__ -MBT27!,'C"0^VC+7V_O__`=B)A>S^___!X0F+A=S^__\#7)`$45/_M>S^__]& -MB9WP_O__Z/S___^#Q`P[M>#^__]\I^DZ____B?95B>575E.![!0!``"+10R+ -M&(V%]/[__U"+10R#P`A0Z+#\__^)A>3^__^+50P/MD(8BX2#G`@``(F%Z/[_ -M_P^V0AF+A(.<"```,?:)A>#^__\[M>3^__]86GU5D`^VE+7T_O__#[:$M?7^ -M__^+O>C^__^+7)<$P>`)#[:,M?;^__\!P\'A"8F=[/[__XN]X/[__P-$EP11 -M4%-&B87P_O__Z/S___^#Q`P[M>3^__]\K&H`_W4,_W4(Z&\!``"-9?1;7E_) -MPXUV`%6)Y5=64X'L5`$``(M%#(M8"(LPC87T_O__4%/HZ_O__XF%I/[__P^V -M0Q2+A(:<"```B86P_O__BU4,BE(4,,)P><) -MBH2%]/[__SJ-H_[__XB%K_[__W,C#[;P#[;!BY2%U/[__XM4L@1!`=HZC:/^ -M__^)E(6T_O__P0#6G0+ -MC67T6UY?R<.-=@"+4PB+0A"%P'3KA?;'0A``````QD`%`K(,=0*R`8A0!HE% -M#(E]"(UE]%M>7\GI(O?__XGV58GE5E-3BT4(C5`LBD`I,=N$P(MU#(A%]W0M -MD(/['W\_N`$```"(V=/@A48@=`V`>@4"=22*0@8\`7460P^V1?>#PB0YPWS4 -MN`$```!96U[)P\9&!0*(1@8QP.OPC78`C4O@N`$```#3X(5&'.N^D%6)Y5=6 -M4X/L$(M%"(E%\(MU#("^'PH```#&1BH`=':-1BR)1>2*5BDQ_X32BUWD=!2- -M=@"`>P4!="!'#[;"@\,D.<=\[XM%\(EU#(E%"(UE]%M>7\GI;O+__X![!`-U -M*8M#"(!X%0!T((M0$(72=!G'0!``````QD,%`HJ&'@H``(A#!HI6*>NQQD8J -M`8UE]%M>7\G#C48LB47DBE8IB?8Q_X32QT7H`0```(M=Y,=%[`````!T)Y"* -M0P6$P`^$W0```#P"=#''1>@`````BD8I1XC"#[;`@\,D.<=\VHM%[(7`=;N+ -M?>B%_W2=QH8>"@```>E-____BD,&/`%TSX!^*P`/A(0```"+5AP/MD,(BT2" -M4(I``8/@!(3`=&;'1>@`````#[9#!(/X!L9#!0'&0P8`=YC_)(4`````4_]U -M\.CN]___6%KKA,9#!0+&0P8!4_]U\.A5]?__Z^E3_W7PZ,[Y___KWE/_=?#H -MA_O__^O34_]U\.A$_/__Z\C&1BL!Z\;&0P8!Z4'___^(AAX*``#&AA\*```! -MZ8;^__^04U;HZ?W__X7`6EET'P^V0P2#^`;&0P4!=Q+_)(4<````4_]U\.AJ -M]___65B*0P4\`@^%\/[___]%[.GD_O__QD,%`L9#!@%3_W7PZ,#T___KV%/_ -M=?#H.?G__^O-4_]U\.CR^O__Z\)3_W7PZ*_[___KM\9&*P'KQHUV`%6)Y5=6 -M4X'LB`$``(M%#(NP]`D``(7VBU@"@```,:''PH```#'A_@)```````` -M#X2U````BE80B-"#X""$P`^$+2(```^V1@J#^`(/A$8>``"#^`(/CQ\=``!( -M=!?_=0S_=0CH\?S__S'2C67T6UZ)T%_)PXM%#(I`)C').,&(A7?^__]S1@^V -MP<'@!`-%#(V0Q`@``(N`Q`@``#';A3^__]0 -MZ+WG__]9_W4,Z'#H__^)A8S^__]:QD`$!HM%#,:%S_[__P"*0"8XA<_^__^( -MA73^__\/@S`*``"+50R*6B`$`T4,C9#$ -M"```BX#$"```,+<@R%]G0%N0$```"%R0^$ -MTP````^VA<_^___!X`2+?0P!QXN'Q`@```F%Y/[__XVWQ`@``(M&!`F%Z/[_ -M_XM&"`F%[/[__XM&#`F%\/[__XJ-S_[__XM%##I(*`^$A0```%#HG^?__UG& -M0`0"BI7/_O__B%`(B%`)BY?$"```B5`,BU8$B5`0BU8(B5`4BU8,B5`8BXV, -M_O__*PB#Z2S!^0*)QHT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y -M'P^/!0D``+@!````T^`)1B"+30R*62>*02:(A73^__^-=@#^A<_^__^*A73^ -M__\XA<_^__\/@LC^____=0SH`.?__UK&0`0"B%@(B%@)B<:+A>3^__^)1@R+ -MA>C^__^)1A"+A>S^__^)1A2+A?#^__^)1AB+C8S^__\K#H/I+,'Y`HT$S0`` -M```IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'P^/40@``+@!````T^`)1B"+ -M30R*22@/MM'!X@0#50R-@D0)``"+6`2+<`B(C7/^__^+0`R+BD0)``")G8C^ -M__^)A8#^__^)Q_?1BX7D_O__]],AP2.=Z/[__XFUA/[__XF-U/[__XF=V/[_ -M_XN-\/[__XN=[/[___?6]]`$C97T -M_O__`<(!\(NX1`D``/?7B3J-L$0)``"+7@3WTXE:!(M."/?1B4H(BT8,]]") -M0@PCO>3^__^).B.=Z/[__XE:!".-[/[__XE*"".%\/[__XE"#(M=#/]U#.C* -MY/__@(/*<*-#-&#^1\/CY\%``"X`0```-/@ -MBXV,_O__"4$@#[:%S_[__\'@!(V]]/[__XT$.(L8,=*%VW47BT@$A"(A>"8N%U/[__XE&#(N%V/[_ -M_XE&$(N%W/[__XE&%(N%X/[__XE&&,:%S_[__P#'A=#^__\`````BT4,BD`F -M.(7/_O__B(5T_O__#X,C^O__C78`BU4,BE(H.)7/_O__B)5[_O__='&*C<_^ -M__^+70PZ2R=T8P^VP<'@!(V-]/[__P'!`=B-D,0(``"+@,0(```CA=3^__^) -M`8M:!".=V/[__XE9!(MR"".UW/[__XEQ"(M2#".5X/[__XE1##')A_[__\'C!(VU -M]/[__XA7"8T<,XL#B4<,BT,$B4<0BT,(B4<4BT,,B4<8BX70_O__A(#*<*-%-")T<'A#RG1 -MC0S(@_D?#X^*`@``N`$```#3X`E'((M=#(I;)XB=>O[__XM%#`^VG<_^__^* -M0"B-E?3^___!XP3_=0R-'!.(A7G^___HX>'__U[&0`0$BHUZ_O__B$@8B<:* -MA7G^__^(1AF+`XE&"(M#!(E&#(M#"(E&$(M##(E&%(N-?/[__RL.@^DLP?D" -MC03-`````"G(C03!P>`#*(#*<*-%-")T<'A#RG1 -MC0S(@_D?#X^%`0``N`$```#3X`E&((N5C/[__RLRC4;4P?@"C13%`````"G" -MC130P>(#*<*-%-")T<'A#RG1C0S(@_D?#X\N`0``N`$```#3X(N-C/[__PE! -M((M%#`^VG<_^__^*0">-E?3^___!XP3_=0R-'!.(A7C^___HQ^#__UG&0`0$ -MBHUX_O__B$@8B<:*A<_^__^(1AF+`XE&"(M#!(E&#(M#"(E&$(M##(E&%(N- -M?/[__RL.@^DLP?D"C03-`````"G(C03!P>`#*(# -M*<*-%-")T<'A#RG1C0S(@_D??R&X`0```-/@BXV,_O__"4$@BUT,BELFB)UT -M_O__Z3O]__^#Z2"X`0```-/@B[6,_O__"48,$C87T_O___W4,C1P#Z&??__]9QD`$`8J5S_[__XA0 -M"(A0"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8*P:#Z"S!^`*-%,4`````*<*- -M%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1]_&[@!````T^`)1B"+30R*22:(C73^ -M___IVOK__X/I(+@!````T^`)1AR+70R*6R:(G73^___IO/K__X/I(+@!```` -MT^"+G8S^__\)0QSI6?K__XM=#/]U#.BXWO__@`$`T4,C9#$"```BX#$"```,+0@R%P'0%N0$```"%R74C_H7/_O__BIUT_O__.)W/ -M_O__#X-?]/__BW4,BEXGZYN-=@`/MIW/_O___W4,P>,$`UT,Z&_=__]?QD`$ -M`HJ5S_[__XA0"(A0"8N3Q`@``(E0#(VSQ`@``(M6!(E0$(M6"(E0%(M6#(E0 -M&(M-#(I))HB-=/[__^N(C87D_O__4.AGW/__QH7/_O__`,:%SO[__P!8BT4, -MBD`F.(7/_O__B(5U_O__#X/##```BU4,BEHGB?8XG<_^__]T?0^VA<_^___! -MX`0#10R-D,0(``"+@,0(```QR87`=16+0@2%P'4.BWH(A?]U!XMR#(7V=`6Y -M`0```(7)=$`/MH7/_O__P>`$`T4,C9#$"```BX#$"```"87D_O__BT($"87H -M_O__BT(("87L_O__BT(,"87P_O___H7._O___H7/_O__BHUU_O__.(W/_O__ -M#X)C____#[:%=?[__X/H`P^VE<[^___1^#G"#X[]!@``BWT,B)_8"0``BX7D -M_O__B8?$"0``BX7H_O__B8?("0``BX7L_O__B8?,"0``BX7P_O__B8?0"0`` -MQH?9"0```<>'U`D```````!7Z.S;__^(6`B(6`G&0`0"BY7D_O__B5`,BY7H -M_O__B5`0BY7L_O__B5`4BY7P_O__B5`8B<:)/"3HM-O__XF%J/[__UO&0`0& -MBXVH_O__*PZ#Z2S!^0*-!,T`````*(/*<*-#-&# -M^1\/CR,&``"X`0```-/@"48@BT4,BD`F/`*(A73^__\/AOX"``#&A<_^__\` -M.(7/_O__#X,3\O__C78`BIW/_O__BW4,.EXG#X1E`0``#[;3P>($B?`!T(N8 -M1`D``/?3B9W4_O__C8A$"0``BT$$]]")A=C^__^+00CWT(F%W/[__XM!#(V] -M]/[__R.=Y/[__XT4.O?0B87@_O__B1J+A=C^__\CA>C^__^)0@2+A=S^__\C -MA>S^__^)0@B+A>#^__\CA?#^__^)0@R)\U;HJ=K__X'#Q`D``%[&0`0#B5@( -MB<:*A<_^__^(1@R+E:C^__^)\2L*@^DLP?D"C03-`````"G(C03!P>`#*`$`T4,C9#$"```BX#$"```,+6@R%VW0%N0$```"%R74IBU4,BE(FB)5T_O___H7/_O__BHUT_O__.(W/ -M_O__#X)Q_O__Z7SP__\/MIW/_O__P>,$_W4,`UT,Z)?9__]9QD`$`HJ-S_[_ -M_XA("(A("8N3Q`@``(E0#(VSQ`@``(M6!(E0$(M6"(E0%(M6#(E0&(N-J/[_ -M_RL(@^DLP?D"B<:-!,T`````*(/*<*-#-&#^1]_ -M&[@!````T^`)1B"+70R*6R:(G73^___I3O___X/I(+@!````T^`)1AR+10R* -M0":(A73^___I,/____]U#`^VG<_^___HZMC__UK&0`0!BI7/_O__P>,$B%`( -MB%`)C1P[BQ.)4`R+4P2)4!"+4PB)4!2+4PR)4!@K!H/H+,'X`HT4Q0`````I -MPHT4T,'B`RG"C130B='!X0\IT8T,R(/Y'W\/N`$```#3X`E&(.EP_O__@^D@ -MN`$```#3X`E&'.E>_O__@^D@N`$```#3X(N=J/[__PE#'.D/_O__BUT,_W4, -MZ$W8__^!P\0)``!9QD`$!8E8",9`%`")P8N5J/[__RL*@^DLP?D"B<>-!,T` -M````*(/*<*-#-&#^1\/CYD"``"X`0```-/@BXVH -M_O__"4$@QH7/_O__`(M%#(I`)CB%S_[__XB%=/[__P^#H^[__XJ5S_[__XM- -M##I1)P^$^0```(I'%(J=S_[__P^VT(A<.@Q`#[;3B$<4P>($B<@!T(N(1`D` -M`/?1B8W4_O__C9A$"0``BT,$]]")A=C^__^+0PCWT(F%W/[__XM##(VU]/[_ -M_XT4,B.-Y/[___?0B87@_O__B0J+G=C^__\CG>C^__^)6@2+M=S^__\CM>S^ -M__^)<@B+A>#^__\CA?#^__^)0@PQTH7)=0R%VW4(A?9U!(7`=`6Z`0```(72 -M#X49`0``#[:%S_[__\'@!`-%#(V0Q`@``(N`Q`@``#')A`#*,$C87T_O___W4,C1P#Z-W5__]: -MQD`$`8J5S_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8*P>#Z"S! -M^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1]_#[@!````T^`) -M1R#I:O[__X/I(+@!````T^`)1QSI6/[__X/I(+@!````T^"+G:C^__\)0QSI -M7_W__X/I(+@!````T^`)1ASIU?G___]U#.@WU?__B86D_O__QD`$`8NUI/[_ -M_XA>"(A>"8N%Y/[__XE&#(N%Z/[__XE&$(N%[/[__XE&%(N%\/[__XE&&(M] -M#(I?)XD\).COU/__QD`$`HA8"(A8"8N5Y/[__XE0#(N5Z/[__XE0$(N5[/[_ -M_XE0%(N5\/[__XE0&(G&B3PDZ+?4__^)A:#^__]:QD`$!HN-H/[__RL.@^DL -MP?D"C03-`````"G(C03!P>`#*`$`@2%_W41BW(( -MA?9U"HM:#(7;=`B-=@"Y`0```(7)=1G^A<_^__^*A73^__\XA<_^__]RH^FZ -MZO___HW._O__BIUT_O__BH7._O__C3P8#[:=S_[__\'C!/]U#`-=#.C`T___ -MB86<_O__6<9`!`&*E<_^__^+C9S^__^)^(A1"(A!"8N#Q`@``(E!#(VSQ`@` -M`(M&!(E!$(M&"(E!%(M&#(E!&(M5#(I2)_]U#(B5F_[__^ALT___B864_O__ -M6L9`!`2*C9O^__^+A93^__^)^HA0&8A(&(N#Q`@``(N-E/[__XE!"(M&!(E! -M#(M&"(E!$(M&#(E!%(G+BXVD_O__*PN#Z2S!^0*-!,T`````*(/*<*-#-&#^1\/CY@"``"X`0```-/@"4,@BYV4_O__BQLIG9S^ -M__^+A9S^__^#Z"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B# -M^1\/CS4"``"X`0```-/@B[64_O__"48@BX6@_O__BP`IA93^__^+A93^__^# -MZ"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B#^1\/C\P!``"X -M`0```-/@BY6@_O__"4(@BUT,BELGB)V3_O__#[:=S_[__\'C!/]U#`-=#.@H -MTO__6<9`!`2)QXJ%D_[__XA'&(J5S_[__XA7&8N#Q`@``(E'"(VSQ`@``(M& -M!(E'#(M&"(E'$(M&#(E'%(N-I/[__RL/@^DLP?D"C03-`````"G(C03!P>`# -M*(#*<*-%-")T<'A#RG1C0S(@_D?#X_#````N`$` -M``#3X(N=H/[__PE#(`^VG<_^___!XP3_=0P#70SH5='__UK&0`0"BI7/_O__ -MB%`(B%`)BY/$"```B5`,C;/$"```BU8$B5`0BU8(B5`4BU8,B5`8BXV@_O__ -M*PB#Z2S!^0*)QHT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'W\; -MN`$```#3X`E&((M-#(I))HB-=/[__^G2_/__@^D@N`$```#3X`E&'(M=#(I; -M)HB==/[__^FT_/__@^D@N`$```#3X(NUH/[__PE&'.DU____@^D@N`$```#3 -MX`E''.G>_O__@^D@N`$```#3X(N-H/[__PE!'.DL_O__@^D@N`$```#3X(N] -ME/[__PE''.G#_?__@^D@N`$```#3X`E#'.E@_?__@^D@N`$```#3X`E&'.G, -M^___BW4,BEXGZ=?S__^-G>3^__]3Z&;/__]9BTT,,?8/MU$D,?^#_A\/A^<# -M``"Y(````"GQ.=%V`HG1@_D@#X3&`P``N`$```#3X$B)\=/@"0.X(````"GP -M.<)V$(U4%N`Q]D>)^(/#!#P#=KB+50R*4BB`^@B(E7/^__\/A'0#``"+=0R* -MG7/^__^(GM@)``#&AMD)```!BX7D_O__B8;$"0``BX7H_O__B8;("0``BX7L -M_O__B8;,"0``BX7P_O__B8;0"0``QX;4"0```````%;H8\___XF%R/[__UK& -M0`0"B[W(_O__B%\(B%\)BX7D_O__B4<,BX7H_O__B4<0BX7L_O__B4<4BX7P -M_O__B4<8BT4,BD`F/`*)_HB%=/[__P^&:`$``,:%S_[__P`XA<_^__\/@\_E -M__^+70R!P\0)``")G<3^__^*A<_^__^+50PZ0B@/A.0```!2Z-C.__]9QD`$ -M`8J-S_[__XA("(A("8N5Y/[__XE0#(N5Z/[__XE0$(N5[/[__XE0%(N5\/[_ -M_XE0&/]U#(G&Z)G.__^)QUK&0`0#BYW$_O__*S>)6`B-3M3!^0**A<_^__^( -M1PR-!,T`````*(/*<*-#-&#^1\/CY4```"X`0`` -M`-/@"4<@BY7(_O__*SJ-1]3!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/ -M*=&-#,B#^1]_.;@!````T^"+C3__X/I(+@!````T^"+M`#*$/*=&-#,B#^1]_,[@!````T^`)1R"+10R*0":(A73^___^A<_^ -M__^*C73^__\XC<_^__\/@D;____I0N/__X/I(+@!````T^`)1QR+50R*4B:( -ME73^___KR(/I(+@!````T^`)1ASI]?[__XM-#(I!)XA!*(B%<_[__^EX_/__ -MQP/_____Z3W\__^#[B#I1OS__[@!````Z57C__^#^`,/A=OB__^-G>3^__]3 -MZ$/+__^+10Q?,?8/MU`D,?^#_A\/A^P```"Y(````"GQ.=%V`HG1@_D@#X3+ -M````N`$```#3X$B)\=/@"0.X(````"GP.<)V$(U4%N`Q]D>)^(/#!#P#=KB+ -M50S_LIP(``#H=,$ -M`UT,C8/$"```4('#1`D``.BLRO__4^BFRO__65O_=0SH6,O__UK&0`0"BI7/ -M_O__B%`(QD`)`(N5Y/[__XE0#(N5Z/[__XE0$(N5[/[__XE0%(N5\/[__XE0 -M&/Z%S_[__XJ-S_[__XM=##I+)G*'Z=GA___'`______I./___X/N(.E!____ -MBUT,BELF,`$`T4,C9#$"```BX#$"```,=N%P'45 -MBT($A+>@R%_W0%NP$```"%VP^%?P,``$$ZC7;^__]RNC'` -MA']`D```````#IW.'__XV=Y/[__U/HN,G__XM%#%DQ -M]@^W4"0Q_X/^'P^'+P,``+D@````*?$YT78"B=&#^2`/A`X#``"X`0```-/@ -M2(GQT^`)`[@@````*?`YPG80C506X#'V1XGX@\,$/`-VN(M5#(I:)XB:V`D` -M`,:"V0D```"+A>3^__^)@L0)``"+A>C^__^)@L@)``"+A>S^__^)@LP)``"+ -MA?#^__^`>B8"B8+0"0``QX+4"0````````^'XP```%*)T^C!R?__@(# -M*<*-%-"(7#$,B='!X0\IT8T,R(/Y'W\GN`$```#3X`E&(/Z%S_[__XJ%S_[_ -M_XM5##I")@^"8O___^G%W___@^D@N`$```#3X`E&'.O4_W4,Z-[(__^)A<#^ -M__]>QD`$`8N-P/[__XA9"(A9"8N%Y/[__XE!#(N%Z/[__XE!$(N%[/[__XE! -M%(N%\/[__XE!&(M=#,:%S_[__P"*6R8XG<_^__^(G73^__\/@U3?__^+=0R! -MQL0)``")M;S^__^*A<_^__^+50PZ0B)6`B-3M3!^0**A<_^__^(1PR-!,T` -M````*(/*<*-#-&#^1\/CXD```"X`0```-/@"4<@ -MBX7`_O__*P>#Z"S!^`*-%,4`````*<*-%-#!X@,IPHT4T(G1P>$/*=&-#,B# -M^1]_,[@!````T^`)1R"+50R*4B:(E73^___^A<_^__^*G73^__\XG<_^__\/ -M@OC^___I.-[__X/I(+@!````T^`)1QR+30R*22:(C73^___KR(/I(+@!```` -MT^`)1QSI;____\<#_____^GU_/__@^X@Z?[\__^X`0```.F"_/__B?:%]@^$ -M<-[__X/B`H32#X1EWO__BT4,BH`<"@``B(7/_O__BTT,BI$="@``.-`/AUT! -M``"0BIW/_O__BW4,.EXG#X0X`0``#[;SB?.-O73____!XP2-'#M3Z`/&__^+ -M10P/MX2P_`D``(M5#%^)A6S^__\/M[2R_@D``#'_@[UL_O__'P^'^PD``+H@ -M````*Y5L_O__.?)V`HGR@_H@#X35"0``B-&X`0```-/@2(J-;/[__]/@"0.X -M(````"N%;/[__SG&=A^+A6S^__^-=##@QX5L_O__`````$>)^H/#!(#Z`W:7 -M#[:5S_[__\'B!(M%#`'0BYA$"0``]].)G>3^__^-B$0)``"+003WT(F%Z/[_ -M_XM!"/?0B87L_O__BT$,]]"-C73___^)A?#^__^-A"KT_O__C10*BSHAWXDX -MB[7H_O__(W($B7`$BYWL_O__(UH(B5@(BXWP_O__(TH,B4@,BU4,BH7/_O__ -M.D(H#X3%"```BUT,BI,="@``_H7/_O__.)7/_O__#X:D_O__@+W-_O__``^% -MMP```(M=#(J;'`H``#C3B)W/_O__#X`B%_W4)BU@,A=MT!XGVN0$` -M``"%R743_H7/_O__.)7/_O__=JWIX-O___]U#`^VG<_^___H`<7__UK&0`0! -MBI7/_O__P>,$B%`(B%`)C1PSBQ.)4`R+4P2)4!"+4PB)4!2+4PR)4!B+30R* -MD1T*``#KI8V%Y/[__U#H`,3__\:%S_[__P"+10R*0"8XA<_^__];B,$/@ZT' -M``"+50R*4BB(E7/^__^*G7/^__\XG<_^__]T0XJ%S_[__XM5##I")W0U#[;` -MP>`$`="-D,0(``"+@,0(```)A>3^__^+0@0)A>C^__^+0@@)A>S^__^+0@P) -MA?#^___^A<_^__\XC<_^__]RH0^VC7/^___!X02-G?3^__^-#!F+,2.UY/[_ -M_XFUU/[__XM9!".=Z/[__XF=V/[__XM1"".5[/[__XF5W/[__XM!#".%\/[_ -M_XF%X/[___?6]]/WTO?0B;7D_O__B9WH_O__B97L_O__B87P_O__(S&)M>3^ -M__\C602)G>C^__\C40B)E>S^__\C00S_=0R)A?#^___HG,/__XF%N/[__UG& -M0`0`BY7D_O__,<"%TG4>B[WH_O__A?]U%(NU[/[__X7V=0J+G?#^__^%VW0% -MN`$```"%P`^$A@4``(M%#(M5#(I`*(B%<_[__XB"V`D``(N%Y/[__XF"Q`D` -M`(N%Z/[__XF"R`D``(N%[/[__XF"S`D``(N%\/[__\:"V0D```'&A<_^__\` -MBDHF.(W/_O__B8+0"0``QX+4"0```````(B-=/[__P^#1`$``(J%<_[__SB% -MS_[__P^$#0$``(J5S_[__XM-##J1'`H```^"K@0``#J1'0H```^'H@0``#I1 -M)P^$F00```^VG<_^___!XP2-M?3^__^-'#.+A>3^__\)`XN%Z/[__PE#!(N% -M[/[__PE#"(N%\/[__PE##/]U#.ANPO__6L9`!`&*E<_^__^(4`B(4`F+$XE0 -M#(M3!(E0$(M3"(E0%(M3#(E0&(M=#/]U#(G&@-!,T`````*(/ -M*<*-#-&#^1\/C\P#``"X`0```-/@"4<@BIW/_O__BW4,.EXG#X0]`P``BU4, -MBE(FB)5T_O___H7/_O__BHUT_O__.(W/_O__#^__^*6B>)@N@)``#&@O$)```` -MQX+L"0```````%+H#L'__XF%L/[__U_&0`0!BXVP_O__B%D(BIVW_O__B%D) -MBX74_O__B4$,BX78_O__B4$0BX7<_O__B4$4BX7@_O__B4$8QH7/_O__`,>% -MT/[__P````"+10R*0"8XA<_^__^(A73^__\/@W37__^*E<_^__^+30PZ42@/ -MA(P!``"*62*A<_^__^(1PB(7PF+A=3^ -M__^)1PR+A=C^__^)1Q"+A=S^__^)1Q2+A>#^__^)1QB+C;C^__\K#X/I+,'Y -M`HT$S0`````IR(T$P<'@`RG(C03!B<+!X@\IPHT,T8/Y'P^/:P$``+@!```` -MT^`)1R"+C=#^__^%R71%BQ$/*=&-#,B#^1\/CPH!``"X`0```-/@"4<@BTT,BDDG -M_W4,BUT,B(VO_O__Z*6___^!P]P)```K.%J-3]3&0`0#B5@(P?D"BIVO_O__ -MB%@,B<:)A=#^__^-!,T`````*(/*<*-#-&#^1\/ -MCXD```"X`0```-/@"48@BX6P_O__*P:#Z"S!^`*-%,4`````*<*-%-#!X@,I -MPHT4T(G1P>$/*=&-#,B#^1]_,[@!````T^`)1B"+10R*0":(A73^___^A<_^ -M__^*C73^__\XC<_^__\/@DK^___IN=7__X/I(+@!````T^`)1AR+50R*4B:( -ME73^___KR(/I(+@!````T^`)1ASI;____X/I(+@!````T^`)1QSI[O[__X/I -M(+@!````T^`)1QSIC?[__XN%N/[__RLXC4?4P?@"C13%`````"G"C130P>(# -M*<*-%-")T<'A#RG1C0S(@_D??QZX`0```-/@BY6X_O__"4(@BDXFB(UT_O__ -MZ8#\__^#Z2"X`0```-/@BYVX_O__"4,`$C808Q`@``%!&Z):Z__^) -M\3I+)EARXHM3'.N(D%/_=0CH(]'__X7`6EETGHM-"(N!K"\``(E8!(D#BT7P -MB4,$B9FL+P``Z7K___^)]E6)Y593BT4(BU@(BX/D+P``A -MR<.-LZPO```YLZPO``!TZ>O`58GE5U93@^P,BT4(BT`(B<>+D*PO``"!QZPO -M```Y^HE%\'02BTT(.4H<#X2D````BQ(Y^G7NBTWPBY&T+P``@<&T+P``.AT$HU:^(M%"#E#''01BQ([5>AU[C'`@\0,6UY?R<,Q]HI#)HGQ.,%S2HA% -M[XGVB?$/ML'!X`2-!!B-B,0(``"+@,0(```Q_X7`=1>+002%P'40BT$(A)]K\!````A?]U%4:)\#I%[W*[,)]E6)Y5=64U.+70B+2R2+10R%R8E%\(M]$(MS -M"'4+4^BA_O__A7\G#C78`BT7PB4,DB7LH_X;H+P`` -MB74(C67T6UY?R>G\____B?95B>564XM=#(I#$83`BW4(=0;&0Q$!L`$\`706 -M/`9T$CP#=`Z*0Q"#X""$P'4$QD,1"_]S+%;H0;C__U/_R<.)=0B-9?A;7LGI_/___XV&["\``%!H```` -M`%;H_/___X/$#.O4D(/`&.OIC78`58GE5U93@>R\````BT4,BU`@BPJ)C4#_ -M__\/MD$\2(F%5/___V:+0@AFB85B____BTI,B8U<____#[9"2HF%4/___P^V -M2DN)C4S___]FBT)2BTH49HF%8/___X7)BW409HM:4`^$;@(``&8/MD(0@^`! -M#[?`.T44#X1:`@``B8U$____BU4,BP(/MD`#,?^)A4C___\QR9`/M\,#A5S_ -M__^)A5C___^+A4C___\YA5#___\/A`8!```/MYU@____P>,)D(N%1/___P^W -M4`2%TG4%N@```0")T"GX.=AW#2G#@X5$____"#'_Z]@!WXN58/___V8IE6+_ -M__\/A*D```#_A5#___^+A4S___\QVSF%4/___P^$A````(N50/___P^V0CPY -MA5#___]T+8N%0/___V:+4$1FBX5B____9CG09HF%8/___P^&2O___V:)E6#_ -M___I/O___XN%3/___X7`="W_C4S___\QP(.]3/___P`/E,")A5#___^+A4#_ -M__]FBU!$#[?"`85<____ZZ:+A53___^)A4S____KR_^%4/___^EQ____9L=& -M_@"`N0$```"-9?1;7HG(7\G#A58/___XG3B94\____P>,)C78`BXU$____#[=1!(72=06Z```!`(G0*?@Y -MV(F%./___W,OBX5$____BPB)T`'Y9BGXB0YFB48$9L=&!@``*YTX____@\8( -M@X5$____"#'_Z["+C43___^+`0'X`=^)!F:)7@1FQT8&``"#Q@@YUW0CBU4, -MBXU8____#[=""`.-//___P-"!#G!#X5%_O__Z?S^__^#P0@Q_XF-1/___^O0 -M9HE>!(/&".E`_____S4$````Z/S___]:Z0K___^+0A@QR87`#X30_O___W44 -MC8UD____45*)C43_____=0C_T(/$$#')A<`/A*W^___I=_W__XUV`%6)Y593 -MBU4,BD(1/`&+=0B+6B!T`XA#$5)6Z/S___^*0TE`B$-)6CI#2%ET!XUE^%M> -MR<.*0Q&$P'4&QD,1`;`!/`%T##P&=`@\`W0$QD,1"U-6_U,<6U[KTXGV58GE -M5U93@^Q(BT4,BE`0BSB(T(/@!(3`#X1#`@``BU4,BEI$A-O'1<``````#X1F -M`0``BT4,BTW`BTR(,(E-O(J!'`H``(A%NXJ!'0H``#A%NP^',@$``(I5NXM- -MO#I1)P^$$0$```^VP@^WE('\"0``#[>T@?X)``#!X`2)5:PQ_XV<",0(``"# -M?:P?#X?%`0``NB`````K5:PY\G8"B?*#^B`/A*,!``"(T;@!````T^!(BDVL -MT^`)`[@@````*T6L.<9V&8M%K(UT,.#'1:P`````1XGZ@\,$@/H#=JD/MD6[ -MB<*+3;S!X@2-E`I$"0``B56T#[>4@?P)``")5:P/M[2!_@D``#'_D(-]K!\/ -MARX!``")^8M5M`^VP8T<@KH@````*U6L.?)V`HGR@_H@#X0``0``B-&X`0`` -M`-/@2(I-K-/@"0.X(````"M%K#G&#X;1````BT6LC70PX,=%K`````!'B?J` -M^@-VG8M-O(J!'0H``/Y%NSA%NP^&U/[__XM-#(I91/]%P`^VPSE%P`^,FO[_ -M_XM%"(N0H"\``(72=%2$V\=%P`````!T-HV0K"\``(M%#(M-P(M,B#"+0@2) -M$8E*!(D(B4$$_T7`QX'T"0```````(M-#`^V040Y1(04L/MH(< -M"@``9HN$@OP)``!FB4%0#[:"'`H``&:+A(+^"0``9HE!4L9!2`#&04D`BT,$ -MBU6\B5,$B1K_1<")0@2)$(M-#`^V040Y1575E.#["B+10R+ -M`(E%\&:+6$0QR6:!^X``9HE=[G8&9L=%[H``BU4,BD(0@^`@A,`/A>T"``"+ -M11"*0!(/MM"+=1"(1=>+!HG6,=+W]HA5ZXM%\`^V4#R+=1"+1@2)UC'2]_:* -M1=Y((?AFBUWN -M9BG#9CM=['8#BUWLBW78]]Z+1>0A_H7`#X2$````QT7D`````&:+5>Z+1?!F -M.U!$MT/'0QBW7P9HM>1&8Y7>YS!\=%Y`$```"+11!F -MBT`09CG89HE%[`^&H?[__V:)7>SIF/[__X!]Z@!T)?Y-ZH!]Z@`/E$7KBUWP -M#[=#1(MU$`%&",=%Y`$```!FBUM$Z[B+11"*0!*(1>KKT_Y%Z^N),<"-9?1; -M7E_)PXM-#(I!1$B(043^P`^$GP```(M="('#K"\``(M]"(E=X(''I"\``(MU -M#`^V1D2+3(8PBD$F,=LXP\>!]`D```````"(1=]S08GV#[;#P>`$C00(C9#$ -M"```BX#$"```,?:%P'45BT($A+0@R%P'0%O@$```"%]G5" -M0SI=WW+!,<"%P'0LBU7@BT($B1&)2@2)"(E!!(M-#(I!1$B(043^P`^%=O__ -M_[C_____Z3W___^+1P2).8E/!.O5N`$```#KOP^W1>Y0BTT0_W$(_W7P_W4( -MZ."N__^)P8/$$(7)N/____\/A`3___^+70S&0T0!B4LPB9GT"0``Z>W^__^0 -M58GEBTT0AG\____D(E%#(E5 -M",GI+/?__U6)Y5=64X/L,(M%#(LXBD"+50P/ -MMUH(9HE=Y(I7/$J(5>8/MD\^#[;2B57(T^@QTHE%U/=UR(E%V`^V3S[3X(E% -MW`^W=T0/KT7(BTW(`UW,#Z_.*<.-1!G_,=+W\8G!#Z_.BT7C78`58GE4XM=#(M# -M+(7`=06+7?S)PU/H_/___S'26(M#+(L$D(7`=!")]L=`$`````"+0!2%P'7R -M0H'Z_P,``';=:@?_+?0A6C8>D -M+P``4XF'I"\``(F'J"\``(V'K"\``(F'K"\``(F'L"\``(V'M"\``(F'M"\` -M`(F'N"\``*$`````P>`,NJNJJJKWXHG3P>L/QX>@+P```````%-H(`H``%># -MPR#H3*;__U-J$%>)QNA!IO__`<:A`````,'@#,'H#E!J1%?H*Z;__X/$)&H( -M:``0``!7`<;H&:;__P'&5T;H_/___X/$$#LU`````*,$````<@B-9?1;7E_) -MPU?H_/___XG"A=)8=.M&BX?<+P``_X?@+P``.S4`````B0*)E]PO``!RUNO, -M58GE5U9348M%"(E%\(MU#(!F`?N+7@0/MDX#N`$```#3X(I31HG!B-"#X`*$ -MP,=#3`````")UP^$YP```&:+0TAFA7\G#4_]U\/_06%H/MGM&Z^*)]HC0@\@%_DL]A,!F -MB4M(QT-,`````(A#1GD&@^!_Z\:0@^"?B$-&4_]U\.C\____B<%?A* -M5@.(40.`20$(Q@$#H0P```")030/MM*A(````(E9!(E,DU")03C'1@0````` -MBD-&@^#^@\@*B$-&_D,]46H'Z/S___]86HM#!(7`=`R-=@")PXM`!(7`=??H -M_/___XE#0(E="(UE]%M>7\GI_/___V:+0TAFA<`/A$O____I$/___XGV58GE -MBU4,2E,QVX/Z_XM-"'0.B?8/M@%*`<-!@_K_=?0/ML-;R<.)]E6)Y593BUT( -M@#L#=D>*4SPQ]H32=!*)]HM,LU"%R7441@^VPCG&?/"`8T;[C67X6U[)PY"* -M4P&*00&#X@&#X/X)T(A!`?]TLU#H_/___UB*4SSKS(E="(UE^%M>R>L!D%6) -MY5=64X'L!`(``(M%",>%\/W__P````"`>#P`C;7T_?__#X0L`@``BW@$A?]T -M#XM'!(7`=`B)O?#]__^)QV@``@``:@!6Z/S___^#Q`PQP(7_QP;S%GA:=`.+ -M1T")1@2+50B`>D0`=`J`3@D"BD)'B$8*BT4(BE!`B-.*AI,```"#XP&#X/R( -MT8/A`@G8"&F`````````#H_/__ -M_VH$C8>`````4(U&/%#H_/___VH0C8?$````4(V&@````%#H_/___X/$)&I` -MC8>$````4(U&0%#H_/___X/$#(N%\/W__X7`=&*+E?#]__^+0@R)1AS'AIP` -M````````B@*(1B"*0CR(1B&+50B*0@.(1B*+E?#]__^*0CZ(1B.*0D:#X`*$ -MP'0$@$XD`8N5\/W__V:+0DAFB48FBT),B48HQX:@`````````(7_=$-HD``` -M`%;H_/___V@``@``5O?8B$8(Z/S____WV%:(AI````!J,(M5"(M"3(/H"E") -MT(/`/%#H_/___XUE]%M>7\G#BU4(B@*(1A#KLXM5".F[_O__,=+I>O[__XGV -M58GEBT4(4X`X`W8;,4(7`=1!##[;".<-\\(UE -M^%M>R<.04.C\____6(I6/.OD@&8!_NOFB?95B>6+30B+40@QP#D,@G0(0(/X -M!W;UR6+10R`8`'[B44(R>G\____D%6)Y5=64X'L -M!`0``(M]"(I7`8C0@^`$A,"-G?3]__^)_G0%@#\"=PB-9?1;7E_)PX/B_8A7 -M`6@``@``:@!3Z/S___^*!X/$##P#=!`\"(MV4`^$@0```(`^`W7P4VH@:@"- -M1CQ0Z/S___^#Q!!F@;O^`0``5:IUL(N+R@$``(7)=!6!>P9,24Q/=$&!NW8! -M``!'4E5"=#6)V,>%\/O__P,```"`N+X!``"`=!"#P!#_C?#[__]Y[.EL____ -MBY#*`0``A=)TYH!/`0+KX(!/`0+I4____XUV`(7V=`MF@W](`0^%% -M\/O__P$````/MD<\.87P^___C;7T^___#XUF____5FH@:@"+E?#[__^+1)=0 -M@\`\4.C\____,=*#Q!"+!)8Q!)-"@_I_?O3_A?#[__\/MD<\.87P^___?,7I -M)O___Y!5B>564XM="(N+2!$``(U!`;HA`@``B=:9]_Z+10R)1,L\BT40B43+ -M0(F32!$``%M>R<.058GE5U93BW4(BX9$$0``.X9($0``="N_(0(``(M6+30B+`87`BU4,=!&+0"2)0B2+`8E0)(D1R<.)]HE2).OUC78` -M58GE5U93BW4,BQ:%THG7="6-=@"+6B0YVG0EBT,DB4(D4_]U"/]3*%@Y^UIT -M"(L&A<")PG7>C67T6UY?R<.)]L<&`````.O958GEBT4(@#@(=`7)PXUV`,GI -M_/___XGV58GE4XM%"(`X"(M=#(M-$(M0"'0+45+_TXM=_,G#B?:+7?S)Z?S_ -M__^-=@!5B>575E-1BE40B%7SBT4(BW@HB@`/MMA35XA%\NC\____:@!35^C\ -M____:@!J`&H`:@!J`U-7Z/S___^#Q#`QTH7`#X2'````,=OW10P```#P#Y7# -MA=L/A(\````QP(!]\R`/E/___XUV`%6)Y8I%"(G"@^(#@^`$P>(- -MA,!T"XV"`"`#`,G#C78`C8(`(`(`Z_-5B>564U"*10QH(*$'`(A%]XMU"+L@ -MH0<`Z/S___]8D`^V1?=0Z*[___\%'`$``(D$)/]V#.C\____A,!:6;H!```` -M>1MH$"<``('#$"<``.C\____@?L_2TP`6';",=*-9?A;B=!>R<.-=@!5B>56 -M4VH`#[9%#%#H6____XG&C4`(B00DBUT(_W,,Z/S___]H&`$``(U&#%#_R<.058GE#[9%#&H`4.@=____@\`,B00DBT4(_W`,Z/S_ -M___)PXGV58GE9H-]%`"+10QU$_=%$````/!U"JD`_P``=`N-=@"X`0```,G# -MD&:%P'4+@WT(`;@!````=.TQP.OI58GE5U934(M=%(M#$(M-"(D!BT,4B4$$ -MBP,QTH7`BWT0B47P=06Z`0````^V1P31X`G"BT4,B[`X`@``A?9FB5$(#X0@ -M`0``@_X"#X07`0``@WL$`71Y9@^V0PX-`!(``&:)00IF#[9#"`T`$P``BU,( -M9HE!#(G09L'H"`T`%```9HE!#HG0)0``_P"!X@````_!Z!#!ZA@-`!4``('* -M0!8``&:)01!FB5$2C5$4BTWPA#"-AP0!``"+<@Q05HM=%.C\____B`.-AP@! -M``!05HE%\.C\____9@^VP&:)0P*-APP!``!05HE%[.C\____9@^VP&:)0P2- -MAQ`!``!05HE%Z.C\____9@^VP(/$(&:)0P:-AQ0!``!05HE%Y.C\____9@^V -MP&:)0PA8@WT0`5IT*8V'&`$``%!6Z/S___^(0PJ-AQP!``!05NC\____B$,+ -MC67T6UY?R<.0C8<@`0``4%:)1=SH_/___XA%XX/(@`^VP%#_==Q6Z/S_____ -M=?!6Z/S____!X`AF"4,"_W7L5NC\____P>`(@\0D9@E#!/]UZ%;H_/___\'@ -M"&8)0P;_=>16Z/S____!X`AF"4,(#[9%XU#_==Q6Z/S___^#Q!SI6____U6) -MY5=64X/L&(M5"`^V=0R+?+(DBT409HE%XHM',(/`,%#_<@SH_/___X/@'XT4 -MQ0`````IPHT$UXV01`(``%F#N$0"```!B57<6W0_C9A8`@``C47D4/]S!%;_ -M=0CH8?[__XU5Y/Z/40D``%)J``^W1>)0_W,<:@%6_W575E.#["B+51`/MD4,BTT(BW2!)(E%T&:+`F:)1=QF -MBT("9HE%WHM"!(E%X&:+1=R#X!^-%,4`````*<*-'-:-@T0"``")1=AFBT7> -MA,#'1=0`````9L=%S@``="YFBT7>)?\```!FB47.QT74`0```&:!3& -M3`D```````#'AC0"````````9HM%WH/@!&:%P(V[6`(```^%D````(.[1`(` -M``%T2_Z.40D``(U%Y%"+1>!0#[=%SE#_=QS_==3_==#_=BC_5QC_==A6Z`@/ -M``"+ODP)``"#Q"2%_W03BX9$"0``A7\G#_W70 -M_W4(Z*40``#_MD0)``!6Z)D1``"#Q!"%P'7::@#_MD0)``!6Z*0%``"#Q`SK -MQXUV`(U%Y%#_=P3_==#_=0CHZOS__X/$$.E6____B?95B>575E-0BUT(BW4, -MBWT0:"P-``#_G\____C78` -M58GE5U93@^PDBT4(BT@,B47PBU4<#[9%#,'@`HE5[(I5$`G"B4WDBT7P#[;* -MBW2()(M%&(7`BWT4QT7@`````(A5ZXE-W'1LA?8/A,X```"-!/T`````"T8D -MBY[<"0``4(M&,(/`)%#_=>3H_/___X/$##G[=":+5=R)5=B-=@"+1A2-!-A0 -M_W780_]U\(/C'^B&_?__@\0,.?MUXXN&3`D``(7`=0?'1>`!````B9[<"0`` -MBT7LAF@!#X3/````BT7P@WA@ -M`0^$K@```(-X9`$/A*0```"#>&@!#X2:````BU7P@WI<`70R#[9=ZU/H]_;_ -M_P4<`0``B00D_W7DZ/S___]97E-J`&H!_W7PBTWP_U$@C67T6UY?R<-J!`^V -M7>M3Z,/V__^-<"B)-"3_=>3H_/___U;_=>3H_/___VH9Z/S___]J`%;_=>3H -M_/___X/$)%;_=>3H_/___VC0!P``Z/S___]3_W7PZ'<&``"#Q!3IM0_W7PZ'<'``!?6.E;____BDWKN``!``#3X%!0_W7PZ%3]__^#Q`SI -M%?___XG8@^`09H7`=5N!XP`!``!FA=L/A%#___^#OC0"```!=!R#/0`````! -M#X4Z____B74(C67T6UY?R>DF#@``QX9,"0```````,>&-`(```````#_==#_ -M==3_=?#H"/O__X/$#.N]_W74_W7PZ,P%``!8BT7P@WAD`5IT'8-X:`%T%P^V -M1>M0:@%J`?]U\(M5\/]2(.G1_O__:@"*3=2X``$``-/@4/]U\.B?_/__@\0, -MZ\^)]E6)Y5,/MD4,P>`""T40BUT(#[;`BTR#)(7)=#"+D40)``"%TG0+@SH! -M=`:#>A`!=`^)10R)70B+'"3)Z>P+``")50R)30B+'"3)ZPB)10SKYHUV`%6) -MY5=64U&+50B*&HM"*(MX#(C8BW(P@^`#B$7SC88@`0``4%>!QAP!``#H_/__ -M_U97@^,$Z/S____`ZP*)Q@^V3?.#XP&X``$``-/@2_?0@>,``/__4('#%``# -M`%-7Z/S___^)\H/$'(32>".)\(/@`83`#X62````BU4,BT(4@_@!=%N#^`%R -M3X/X`G0)D(UE]%M>7\G#@^9@B?`\0'7OBU4,BUH@A=MU$FH`4HGV_W4(Z`P! -M``"#Q`SKTXM%#(/`%%#_=0CH5````(7`6EEUOFH!_W4,Z]=J`.OWC78`@^9` -MB?"$P'0CBT4,@\`44/]U".@H````2%]:==6+50R+O(C78` -M58GE5U93@^P4BUT,C7WD5X/#%/]S!(MU",=%X``````/M@90_W8HZ#3W__^# -MQ!"#?1`!#X3W````5VH`:@#_`/M@90_W8H_U,<_W4,5NBY"```@\0D -M@WT0`0^$L````(N&1`D``(7`="^#>!`!='Z+CC@"``"%R71*#[8&4/]V*.BZ -M"0``BYY$"0``6(7;6G0'BWL0A?]T"XUE]%M>7\G#C78`C4,44%-6Z'T*``"+ -M6PB#Q`R%VW3@BTL0AC\____@\04ZXQ05NCG"@``A:@#_MD0)``!6Z//^__^# -MQ`SKBXGV@ST``````0^%0____U;H<0H``%CI-____XUV`,=%X`$```#'ADP) -M````````Z?/^__^)]E6)Y5=64U.+70B+0RB+>`R+0S")QH/&*%97B47PZ/S_ -M__^#X`1:60^$2`$``&H"5E?H_/___U97Z/S___]HT`<``.C\____#[8#4/]S -M*.C5`0``@\0@QH,\`@```,:#4`D```#&@U$)````QX/8"0```````,>#W`D` -M``````#'@S0"````````QX/4"0``(````#'`C78`B82#5`D``$"#^!]^\XV3 -M1`(``+@?````QP(!````@\(X2'GTBT7PQX-$"0```````,>#2`D```````#' -M@TP)````````@\`(:@!05^C\____BT7P:!@!``"#P`Q05^C\____@\08BT7P -M_W,8@\`04%?H_/___XM#'"4`_/__4(M%\(/`%%!7Z/S___^+1?!J`(/`&%!7 -MZ/S___^#Q"2+1?#_N`$```!?R<-J`E97Z/S___^#Q`SIT/[__XGV -M58GE5U93@^P8BT449HE%XHM%#(7`=6J+70B^'P```)"+NT0"``"%_W51@[M4 -M`@```719BX-<`@``B[MT`@``BY-P`@``B5710:@`/MT7B4%?_=1"+50@/M@)0_W(H_U7<@\0L@\,X3GF?C67T6UY? -MR<.-=@"+@UP"``"+NW@"``"+DW0"``#KI56)Y5=64U`/MG4,B?"#X`2+70B_ -M`P```,#H`B'W@WM<`8A%\P^$D@```(-[8`$/A(@```")^@^VPL'@"(!]\P!T -M<@5T`0,`4/]S#.C\____B<&)\`^VT`^V1!-ZP>`%)>````"!X1____\)P0^V -MA!."````P>`+@>'_Y___)0`8```)R(GZ4`^VPL'@"(!]\P!T&05T`0,`4/]S -M#.C\____@\04C67T6UY?R<,%=`$"`.OED`5T`0(`ZXR0B?H/ML+!X`B`??,` -M=$8%#`$#`%#_575E,/MG4, -MBUT(5NC9[O__B30D4XUX*.BA[___:@17_W,,Z/S___]7_W,,Z/S___]J&>C\ -M____@\0@:@!7_W,,Z/S___]7_W,,Z/S___]64^B0_O__B74,B5T(@\0D3[___C78`58GE5U934,9%\@"0QD7S`(I5\XI%\HTT@H'F_P```%;H -M5^[__XU8*(G'QP0D`@```(M%"%/_<`SH_/___U.+50C_<@SH_/___U;_=0CH -M/O___VH`BT4(4_]P#.C\____@\0H:!\!``!7BU4(_W(,Z/S___]J`(U'!%"+ -M10C_<`SH_/___VH`C4<(4(M5"/]R#.C\____@\0D:@"-1PQ0BT4(_W`,Z/S_ -M__]J`(U'$%"+50C_<@SH_/___VH`C4<44(M%"/]P#.C\____@\0D:@"-1QA0 -MBU4(_W(,Z/S___]J`(U''%"+10C_<`SH_/___VH`C4 -M7\G#B?95B>5H___/#VAL!`$`BT4(_W`,Z/S____)PXGV58GE4XM="(M#!##` -M/0``@%!T(6@L#0``_W,,Z/S___^#R`%0:"P-``#_6+30R+50C' -M00@`````BX)("0``B4$,BX)("0``A-=@"+00R)0@SKQ%6)Y5=64XM=$(L#A<"+?0B+=0QU,VH@C4,$ -M4(U&%%#H_/___XL#@\0,B4805E?H*?___\<&`````/Z'/`(``(UE]%M>7\G# -MD&HDC4,$4(U&%%#H_/____Z'4`D``.O%D%6)Y593BW4,BT80A<"+70AT!OZ+ -M4`D``%93Z!W___^+@]0)```/ME8$B92#5`D``,<&`0```$")@]0)``#^BSP" -M``"-9?A;7LG#B?95B>6*10@\`W82#[;(C4P)`K@!````T^#)PXGV#[;(C4P) -M`>OLC78`58GE5U93#[9]#(GX#[;PBUT(5NC`____"4-4B30DZ,WI__\%'`$` -M`(D$)/]S#.C\____B?F#X0.X``$``-/@@^<$]]!0B?B$P`^5P`^VP$@E``#_ -M_P44``,`4/]S#.C\_____W-4:&0=``#_#-`(```$```!0,<"$T@^5P$@E``#__P44 -M``,`4%?H_/___VH`BT,P@\`(4%?H_/____]U\/]U".AD____@\0@C88<`0`` -M4%?H_/___X/&*,>#0`(```$```!J`597Z/S___^-9?1;7E_)PXGV58GE5U93 -M48MU"`^V10R)1?"+1(8DBU@PBWX,QX`T`@```````(/#*&H"4U?H_/___U-7 -MZ/S___^+5?")50R)=0B#Q!2-9?1;7E_)Z53^__]5B>564XM="(M#*(MP#/]U -M$/]U#%.+@]@)``#!X`4#0Q!0Z%'I__^+D]@)``!"BT,<@^(?B9/8"0``)0#\ -M___!X@4)T/Z#40D``(E%$(M#,(/`%(E%#(EU"(/$$(UE^%M>R>G\____D%6) -MY5-J`&H":@"+70A3Z"7W__]3Z)?U__]3Z/S___^#Q!A(=`>+7?S)PXGV#[8# -MQX-,"0```0```%#_B=!?R<.# -M?@0!#X1&`0``]T80`/\`_W41]T84`/\`_W4(9O=&&`#_=`0QTNO.C8<$`0`` -MB47HC8<(`0``B47DC8<,`0``B47@C8<0`0``B47A3Z/S___\/MD824/]UY%/H_/___P^V1A10_W7@4^C\____@\0D#[9&%E#_ -M==Q3Z/S___\/MD884/]UV%/H_/___P^V1AI0C8<8`0``4%/H_/___X/$)`^V -M1AM0_W7L4^C\____@\0,@SX"=`JZ`0```.DC____C8<@`0``4%/H_/___VID -M:@I74^C\____@\08,=*%P`^$_O[___]U[%/H_/___X/@B5HQTCP(60^%YO[_ -M_\=%\`````"!QP`!``"-=@"+1@@/MQ!2@\`"B48(5U/H_/____]%\(/$#(%] -M\/\```!VW8%N#``!``#I>O___Y`/MD814(V'!`$``%!3B47HZ/S___\/MD83 -M4(V'"`$``%!3B47DZ/S___\/MD854(V'#`$``%!3B47@Z/S___^#Q"0/MD87 -M4(V'$`$``%!3B47((A,`/A!,"``"-@G0!`P!0_W,,Z/S___^)PH'BX````"4`&```P>@+ -MP>H%B%0[>HB$.X(```!&65B)\$<\!W:T4^@6]O__4^CX]___4^@.^/__:@!H -M\`0!`/]S#.C\____:"P-``#_#YS!86@^$<@$``(M#1*G@`P"`=`@E'_S_ -M?XE#1(-[7`$/A#T!``"#>V`!#X0S`0``@WMD`0^$*0$``(-[:`$/A!\!```Q -M]C'_D%=31NCL\___68GQ1X#Y!UAV[O]S1&@`#```_W,,Z/S_____=!"#>V@!=`JZ`0```.D+_O__,?\Q]L=% -M\`````")]O]U\%/H_/___X7`6EEU#+@``0``BDWPT^`)QT:)\/]%\#P'=MM7 -M:`#_``!3Z._I__^#Q`SKLXM#1*D0````#X33_O__@^#OB4-$Z7'!0`````!```` -MR<.058GEQP4``````````,G#D%6)Y593BW4(#[9%#(M#3`D```````#'@S0"````````B5T(C67X6U[)Z>7O__^0C67X -M6S'`7LG#C78`58GEBT4(#[95#(M4D"0QP(72=`PQP(.Z3`D```$/E<#)PXGV -M58GEBD4,B<*#X@.#X`16P>((A,!3BW4(C9H``0,`=0:-F@`!`@!3_W8,Z/S_ -M__^#X`]9@_@!6G0;@_@!<@6#^`-T"3'`C67X6U[)P[@!````Z_*04_]V#.C\ -M____:$`-`P#H_/___U/_=@SH_/___X/@#X/$%.O&58GE5U93@^P4BD4,B$7S -M@^`#B$7GBD7S@^`$P.@"BW4(#[9]\XA%YHM4OB2+1@R)1>PQP(72#X1$`0`` -MBT(P@[I,"0```8E%Z`^$+P$``%=6Z.;A__^+7>AJ!(/#*%/_=>SH_/___U/_ -M=>SH_/___VH9Z/S___^#Q"!J`%/_=>SH_/___U/_=>SH_/___U=6Z,_P__\/ -MMD7GP>`(,?^#Q!R)1>"`?>8`#X0N`0``BT7@!0@!`P!0_W8,Z/S___^)PX/C -M\`^V1>>#RP'!X`B`?>8`4P^$]P````4(`0,`4/]V#.C\____#[9%Y\'@"(/$ -M%(!]Y@`/A,D````%"`$#`%#_=@SH_/___VH9Z/S___\/MD7G@^/PP>`(@'WF -M`%,/A),````%"`$#`%#_=@SH_/___P^V1>?!X`B#Q!B`?>8`=&T%"`$#`%#_ -M=@SH_/___VC0!P``Z/S___\/MEWS4U;H_/___X/$%(7`=1M'@_\##X4M____ -M4U;H?N#__S'`C67T6UY?R<.+1>@%'`$``%#_=>SH_/___X/@P%D\0%]UU5-6 -MZ%/@__^X`0```.O0!0@!`@#KD9`%"`$"`.EH____B?8%"`$"`.DR____B?8% -M"`$"`.D$____B?:+1>`%"`$"`.G-_O__C78`58GE5U934XM5"`^V10R+7((D -M,S!T>E?_=?#H_/___XG"6(M%$(7` -M6752C4;_,+__O__4E?_=?#H_/___[D!````C67T6UZ)R%_)PX'*``$``.O?D,>#.`(` -M``$```"!XL#]___KP(GV,"3`D```$```!14^AQ]?__N`$```"+7?S)PXUV`#'`Z_15B>4/MDT, -M4XM="(M4BR0QP(72=0>+7?S)PXGVQX),"0```````%%3Z,_U__^X`0```.OA -M58GEBT4(4P^V50R+7)`D,<"%VW0A@[M,"0```70>:@!J`O]U$%/HC>W__U/H -M_^O__[@!````BUW\R<.0,<#K]E6)Y8M%"`^V50R+5)`DA=*X_P```'0'#[:" -M/`(``,G#58GE5E.+50@/MD4,BW(,BU2")#')A=)T'(M:,(/#+%-6Z/S___]: -M@WT0`5ET)C')@^`"=0N-9?A;BR<.)]FH`4U;H_/___X/$#+D!````Z^*0 -M,7\G#C78`#[;2P>((A,!T:H'"=`$#`(E5 -M\/]U\(M%"/]P#.C\____B?+!X@6!XN`````E'____PG0B?K!X@LE_^?__X'B -M`!@```G"4O]U\(M5"/]R#.C\____#[;#B?F+50B(C`*"````B?&(3`)Z@\04 -MN`$```#K@I"!PG0!`@#KE%6)Y5=64[\#````BET,(=^#XP3`ZP(/E<`/ML!( -M)0``__\%&``#`%"+=0C_=@SH_/___XGY#[;1C4H8N@$```#3X@G"B=B#X`%( -M)0``__^#XP%2!1@``P!+4('C``#___]V#('#&``#`.C\____4_]V#.C\____ -M@\0575E-6BD4,B$7SBE7S@^`#B$7R@^($#[9% -M\U"+?0C`Z@)7B=;H+.S__XGP@^`!2"4``/__!1@``P!0_W<,Z/S___\/MEWR -MC4L8NO[____3PB'"B?"#X`%()0``__]2!1@``P!0_W<,Z/S___^)\(/@`4@E -M``#__P48``,`4/]W#.C\____B=B)\L'@"(/$)(32=%8%"`$#`%#_=PSH_/__ -M_X/@\(/(`5")\@^V1?+!X`B$TG0L!0@!`P!0_W<,Z/S___\/MD7S4%?HA^O_ -M_X/$'(UE]%M>N`$```!?R<.-=@`%"`$"`.O2D`4(`0(`ZZB058GE5U93@^P( -M#[9]#(M%"(M`#(GZB47P#[;"BU4(BUR")(GZB?B#X@.#X`3!X@B$P(MU$`^$ -M$`$``(V"=`$#`%"+10C_<`SH_/___XE&6%F%VU@/A.D```"+4S")5>R)^@^V -MPE#_=0CH_/___XD&7X7`6@^$O````(N#3`D``(E&+(N#.`(``(E&,(J#/`(` -M`(A&-#'2B?:*1!IJB$0R!$*#^B=V\O]U[/]U\.C\____B48XBT7L@\`04/]U -M\.C\____B48\BT7L@\`44/]U\.C\____B49`BT7L@\`84/]U\.C\____B49$ -MBT7L@\0@@\`<4/]U\.C\____B49(BT7L@\`@4/]U\.C\____B49,BT7L@\`D -M4/]U\.C\____B490BT7L@\`H4/]U\.C\____B494C67T6UZX`0```%_)P\<& -M`````.OKC8)T`0(`Z>O^__^-=@!5B>6#[#"+11")1=2+112)1=R+11AFB47@ -MBT4<9HE%XHM%((E%Y(M%)(E%Z(M%*(U5T(E%[(M%+%*)1?`/MD4,4/]U",=% -MT`````#H_/___\G#B?95B>575E.#[`B*10P/MOB(1?.+10B+=+@DA?:X!``` -M``^$L````(N.3`D``(7)#X1$`0``@+X\`@``'P^$3P$``(N&U`D``$B+G(94 -M"0``B8;4"0``C03=`````"G8C83&1`(``(E%[(A8!(M%$(L0A=(/A<````") -MQX/'!(.^.`(```(/A*(````/MT<,#[=7#E#_=PA2_W8(Z!7:__^)1P2#Q!!( -M=&*`OE`)````=4B+AC0"``"%P'0C_W40_W7L5N@Q[O__5_]U[%;HI_#__X/$ -M&#'`C67T6UY?R<,/MEWS4_]U".AQ[___4_]U".B8[___@\00Z\+_=1#_=>Q6 -MZ//M__^#Q`SKRHM&"(7`=9>+AM0)``")G(94"0``0(F&U`D``+@#````ZZK' -M1P0!````Z7#_____=1#_=>Q6Z+3M__^#Q`R`OCP"```!=82#OC0"```!="G_ -M=>Q6Z,;P__^%P%I9#X5H_____W7L5NCC[?__C78`N`$```#I5/___U?_=0CH -MG>___UM?Z\J0N`(```#I//___XGV58GE5U93@^P4BT4(BT`,:&`=``!0B47D -MZ/S___^+50B)QHM25%DQP(76B57P6W0U]\8```0`#X4=`0``QD7K`,=%X``` -M``#WQO\!``!U(<'N"/Y%Z]'N_T7@@'WK`7;GN`$```"-9?1;7E_)PXUV`#'; -M@'WK``^5PTN!XP``__]J[X'#%``#`%/_=>3H_/___U/_=>3H_/___XE%[/?0 -M@\@04%/_=>3H_/___X/$(#'`@'WK``^5P$@E``#__P4(``,`4/]UY.C\____ -MB<=8QD7J`%H/MDWJNP`!``"X`0```-/CT^")\B-=[(/B`2-%['4$A=)T&O]U -M[%)0B?B#X!]04?]UX/]U".BRWO__@\0S_ -M_X5%\%MU%_Y%ZL'N`L'O"(!]Z@-VF.D1____C78`#[9%ZE#_=>#_=0CH0.'_ -M_X/$#.O4:%@=``#_=>3H_/___XG#]]!0:%@=``#_=>3H_/___VH`4VH`_W4( -MBU4(_U(@@\0DZ:[^__^)]E6)Y6H`BT4(:&0=``#_<`SH_/___[@!````R<-5 -MB>6+10C_<%1H9!T``/]P#.C\____N`$```#)PXUV`%6)Y5=64XM]$#';.?MS -M)HM%#(VP'`$``%;_=0CH_/___X3`6EEY&/]U%$/H_/___SG[6'+C,<"-9?1; -M7E_)PX/@`8/P`0^VP.OMB?95B>53:@"+70B+0S`%(`$``%"+0RC_<`SH_/__ -M_XM#,`4@`0``4(M#*/]P#.C\____BUW\R<.)]E6)Y5-J`HM="(M#,`4@`0`` -M4(M#*/]P#.C\____BT,P!1P!``!0BT,H_W`,Z/S___^+7?S)PXGV58GE5U93 -M4XM5"(M"*(MP##';BT(P@[HT`@```8E%\'1#BWWP@<<@`0``5U;H_/___ZF! -M````6EEU8(GV5U;H_/___ZF!````6EET(HG80V8]MPMW#VCH`P``Z/S___]8 -MZ]J)]C'`C67T6UY?R<-J9&H*_W7P5NC\____BT7P!1P!``!05NC\____@^#! -M@\08/$`/E,`/ML#KS&HRZ[R)]E6)Y5=6BT4(4P^V50R+7)`D,<"%VW1'BT,H -M@[M,"0```8MX#(MS,'0S4^C\____:.$```"-AAP!``!05^C\____:F1H$"<` -M`%97Z/S___^#Q""%P'424^C\____,<"-9?1;7E_)PXGV4^C\____N`$```#K -MZ8UV`%6)Y593BTT(#[95#(M$D20Q]H7`=$=H[````&H`:@!J`&H`:@!J`&@` -M`0``C5@T4VH`:@%24>C\____,?:#Q#2%P'09]H.@````X'0+,G\____,<#)PU6)Y6CO```` -M:@`/MD4@4`^V11Q0#[9%&%`/MD444`^V11!0:@!J`&H`:@`/MD4,4/]U".C\ -M____R<.)]E6)Y5=64X/L'(M%"(E%\(M%$(E%[(M%%(E%Z(M%&(E%Y(M%'(E% -MX(M%(&:)1=Z+121FB47)12@/ -MMT77\GI_/___U6)Y5=64X/L<(M5(&:)5>2+ -M52AFB57$BU4P9HE5I(I5.(M%"(M-)(A5H@^V50R+7)`D9HE-U(M-+&:)3;2+ -M<`R*332+>S!3B$VCZ!G]__]:,=*%P'4*C67T6UZ)T%_)PU/H_/___X-]%`%8 -M#X3'`0``]T7D`/\```^%^@```/=%U`#_```/A>T```#W1<0`_P``#X7@```` -M]T6T`/\```^%TP```(V'!`$``(V7"`$``(E%E(E5D(V/#`$``(V'$`$``(V7 -M%`$``/=%I`#_``")38R)18B)580/A9D````/MD7D4/]UE%;H_/___P^V1=10 -M_W605NC\____#[9%Q%#_=8Q6Z/S___^#Q"0/MD6T4/]UB%;H_/___P^V1:10 -M_W6$5NC\____#[9%HU"-AQ@!``!05NC\____@\0D#[9%HE"-CQP!``!15HE- -MF.C\____BTT0@\0,A0/ML50C8<$`0``4%:)193H_/___XM5U`^VQE"-CP@! -M``!15HE-D.C\____BU7$#[;&4(V/#`$``%%6B4V,Z/S___^+5;2#Q"0/ML90 -MC8\0`0``45:)38CH_/___XM5I`^VQE"-CQ0!``!15HE-A.C\____@\08Z2G^ -M__^)]E6)Y5=64XM="(M#*(MS,(MX#&H&C88@`0``4%?H_/___XM#,`4@`0`` -M4%?H_/___VH*Z/S___]3Z/S___]H]`$``.C\____@\0@:/0!``#H_/___VCT -M`0``Z/S___]H]`$``.C\____,=N#Q`R!QAP!``"05E?H_/___X3`6EFZ`0`` -M`'D6:/0!``!#Z/S___^!^P\G``!9=MHQTHUE]%M>B=!?R<.)]E6)Y5.+70A3 -MZ$O___](6G07:/0!``#H_/___UB)70B+7?S)Z3#___^X`0```(M=_,G#B?95 -MB>564VB@````H0````"+0!@%```$`%"+=0A6Z/S___^[!````(/$#*$````` -MBT`0!0``!`!05NC\____64M8>>>[!0```)"A`````(M`%`4```0`4%;H_/__ -M_UA+6GGGNP0```"A`````(M`$`4```0`4%;H_/___UE+6'GGC67X6U[)PXGV -M58GE4VB`````H0````"+0`P%```$`%"+70A3Z/S___]HL````*$`````BT`8 -M!0``!`!04^C\____BUW\R<.)]E6)Y593BW4(5N@J____:@"A`````(M`"`4` -M``0`4%;H_/___Z$`````BP`%```$`%!6Z/S___^(PU;H@?___P^VVXUE^(G8 -M6U[)PY!5B>575E-H+`T``(M="%/H_/___XG'@\@!4&@L#0``4^C\____:/`$ -M`0!3Z/S___^)QH/@8H/$'&:#^&)T%XGP@\AB#[;`4&CP!`$`4^C\____@\0, -M:```!`!3Z/S___]86E/HA/[__VH'H0````"+0`@%```$`%!3Z/S___]J$:$` -M````BP`%```$`%!3Z/S___]J!:$`````BT`(!0``!`!04^C\____@\0H:A&A -M`````(L`!0``!`!04^C\____4^BM_O__5FCP!`$`4^C\____:/`$`0!3Z/S_ -M__^#Q"17:"P-``!3Z/S___^#Q`R-9?1;7E_)PU6)Y5=64V@L#0``BUT(4^C\ -M____B<>#R`%0:"P-``!3Z/S___]H\`0!`%/H_/___XG&@^!B@\0<9H/X8G07 -MB?"#R&(/ML!0:/`$`0!3Z/S___^#Q`QH```$`%/H_/___UE84^B,_?__:@>A -M`````(M`"`4```0`4%/H_/___VH`H0````"+``4```0`4%/H_/___VH%H0`` -M``"+0`@%```$`%!3Z/S___^#Q"AJ`*$`````BP`%```$`%!3Z/S___]3Z+7] -M__]6:/`$`0!3Z/S___]H\`0!`%/H_/___X/$)%=H+`T``%/H_/___X/$#(UE -M]%M>7\G#58GE4XM="%/H[_S__VH*H0````"+0`@%```$`%!3Z/S___]J`*$` -M````BP`%```$`%!3Z/S___]3Z$;]__^#Q"!H`0`$`%/H_/___X/@`EJ$P%FZ -M_____W0*B="+7?S)PXUV`%/HDOS__VH!H0````"+``4```0`4%/H_/___U/H -M__S__VIDZ/S___]H`0`$`%/H_/___X/@`C'2@\0@A,`/E<)*Z[.058GE5U93 -M@^P(BT4(BU@,BWT,:"P-``!3B?J(5?/H_/___XE%[(/(`5!H+`T``%/H_/__ -M_VCP!`$`4^C\____B<:#X&*#Q!QF@_AB=!>)\(/(8@^VP%!H\`0!`%/H_/__ -M_X/$#&@```0`4^C\____6%J+10B)^HA0>0^V1?-0:`#@!0!3Z/S___]6:/`$ -M`0!3Z/S___]H\`0!`%/H_/___X/$(/]U[&@L#0``4^C\____@\0,C67T6UY? -MR<-5B>6`?1``BU4(BDT,=!VX`0```-/@"$)Y#[9">8E%#(E5",GI_/___XUV -M`+C^____T\`@0GGKX56)Y5=64X/L#&@L#0``BW4(5L9%\P#H_/___XE%Z(/( -M`5!H+`T``%;H_/___VCP!`$`5NC\____B47LBT7L@^!B@\0<9H/X8G08BD7L -M@\AB#[;`4&CP!`$`5NC\____@\0,:```!`!6Z/S___]96V@```0`5NC\____ -MB<-F@?M5JEA:=%)HL````*$`````BT`8!0``!`!05NC\_____W7L:/`$`0!6 -MZ/S___]H\`0!`%;H_/___X/$(/]UZ&@L#0``5NC\____#[9%\X/$#(UE]%M> -M7\G#,?^-=@"%_W@CC5\!D&B@````H0````"+0!@%```$`%!6Z/S___^#Q`Q+ -M=>&!_\@````/CYT```!H```$`%;H_/___XG#:+````"A`````(M`&`4```0` -M4%;H_/___X/$%&:!^U6J=1%'@?_'````?I3I./___XUV`&BP````H0````"+ -M0!@%```$`%!6Z/S___]H```$`%;H_/___X/$%&8]5:H/A03___]6QD7S`>B= -M^O__/#Y;#X7Q_O__5NC*_/__AR<,````````````` -M``````````````0````````````````````````````````````````````` +begin 644 hptmvraid.o +M?T5,1@$!`0D```````````$``P`!``````````````#(O@```````#0````` +M`"@`#``)`%6)Y5=64X'L'`(``(M]"(M'#(F%Y/W__XUWQ+`"@'\!`'4*@'\" +M`1G`@^`"0(@&QT8$`````(!.`02+1PR)1@B+5Q")5@P/M@:+!(4`````B48T +M@#X#=2R-0O:)1@R-E>C]__]2:B"+1Q"#Z`I05^C\____@\00@;WH_?__\Q9X +M6G07D`^V!HL$A0````")1CB`3@$$Z;8$``"#[`AHD````(V-Z/W__U'H_/__ +M_X/$$(3`=<_VA?']__\"="+&1P@!BH7R_?__B$<+.D<)C]__]0Z/S___^#Q!"$P'0>@^P$:'`!``!J`(V% +MZ/W__P60````4.C\____@\00BI5[_O__B-.#XP&*1P2#X/R(T8/A`@G8"P0`=0^+0T`[A>S]__\/A"$!``!"@_H/?M*+O>3]__^+GUPB``"%VW0?BT,( +MB8=<(@``@^P$:-@```!J`%/H_/___XE["(/$$(N%[/W__XE#0(I32H/*`8A3 +M2F8/MH7\_?__@^`!T>"#XOT)PHA32F:+A?[]__]FB4-,BX7<_?__B4-0BH7X +M_?__B`.*A?O]__^(0SX/MLBX`0```-/@9HE#2,=#!`````"+A?3]__^)0PR* +MA?G]__^(0SP/M@.+!(4`````B4,T@^P$:A"-A>C]__^#P"Q0C4-T4.C\____ +M@\0,:@2-A>C]__^#P#Q0C8.$````4.C\____@\0,:A"-A>C]__^#Z(!0C8/( +M````4.C\____@\0,:D"-A>C]__^#P$!0C8.(````4.C\____@\00BY7<_?__ +M.5-0=@.)4U#VA?']__\!=`2`2P$!BHWZ_?__B(WC_?__@+WS_?__`0^&HP$` +M``^VP8M\@U2+A1#^__^)A=S]__^%_P^%/0$``(N5Y/W__XNZ7"(``(7_="6+ +M1PB)@EPB``"#[`1HV````&H`5^C\____BXWD_?__B4\(@\00BX7L_?__B4=` +MBE=*@\H!B%=*9@^VA0S^__^#X`'1X(/B_0G"B%=*9HN%#O[__V:)1TR+A=S] +M__^)1U"*A0G^__^(1SR*A0C^__^(!XE?!(N%!/[__XE'#(J%"_[__XA'/@^V +MR+@!````T^!FB4=(#[8'BP2%`````(E'-`^V`XL$A0````")1SB*E>/]__^( +M5P,/ML*)?(-4_D,]@^P$:A"-A>C]__^#P"Q0C4=T4.C\____@\0,:@2-A>C] +M__^#P#Q0C8>$````4.C\____@\0,:A"-A>C]__^#Z(!0C8?(````4.C\____ +M@\0,:D"-A>C]__^#P$!0C8>(````4.C\____@\00]H7Q_?__`70$@$\!`0^V +MA0K^__^#?(=4`'5?B72'5(J%"O[__XA&`_Y'/8E^!`^V!XL$A0````")1CB+ +MC=S]__\Y3U!V-(E/4.LO#[:%X_W__X-\@U0`=2&)=(-4B5X$_D,]BH7C_?__ +MB$8##[8#BP2%`````(E&.)"-9?1;7E_)PU6)Y593BW4,NP`````/MD8\B<*# +M^``/CJ@```"#?)Y4`'0*0SG:?_3IEP```+@!````B-G3X&8)1DR#[`A6_W4( +MZ/S___^)PH/$$(7`='7&``.(6`.)<`2`/@@/E,#!X`.*2@&#X?<)P8A*`:$, +M````B4(T#[8&BP2%`````(E"./9&`1!T#HC(@\@0B$(!BT),B4(,B52>5(I& +M2H/@_H/("HA&2L=&4`````#^1CV#[`A2:@?H_/___X!.2@2#Q!"-=@"-9?A; +M7LG#D%6)Y5=64X/L#(MU#`^V!H/X!G1\@_@&?PN#^`0/C%(!``#K$(/X"`^$ +MNP```.E"`0``B?:*1CTZ1CP/A30!``"`3@$$@&9*_K\`````@'X\``^$'0$` +M`)"+7+Y4A=MT((`[`W8;@^P(4_]U".C\____@\00]D-*!'0&@$Y*!(GV1P^V +M1CPY^'_/Z>8```")]H!.`02`?CT"=0J`9DK^Z=$```"0@&9*_8-^5`!U$8M& +M6,9``P")1E3'1E@`````BT94@#@#=1&#[`A6_W4(Z/S___^#Q!")]H!.2@3' +M1E``````Z8P```"*1CTZ1CQU'(!.`02*1DJ#X/Z(1DIF@WY,`'1D@\@"B$9* +MZUP/MD8]0`^V5CPYT'5/9H-^3`!T(;D`````#[=&3(G"J`%U"4&)T-/XJ`%T +M]X-\CE0`=1_K!O9&2@)U%X!.`02`3DH$@^P(5O]U".C\____@\00QT90```` +M`(UV``^W1DCWV"%&4(UV`(-^!`!U&O9&2@1T%.C\____B49`@^P,5NC\____ +M@\00C67T6UY?R<-5B>575E.#[`R+?0B^`````(UV`(T$=HT$P(VT``="&#>P0`=1N#[`A35^C\____@\00]D,!!'0(QT,X`````)!&@_X/?L:- +M9?1;7E_)PXGV58GE5U93@>PH`@``BWT,BD40B(7G_?__5^C\____@\00@#\( +M=1*#[`A7_W4(Z/S___^#Q!"-=@"^`````(!_/``/AL4```"0@WRW5``/A*T` +M``"+1+=4@#@#=B"#[`0/MH7G_?__4/]TMU3_=0CH_/___X/$$.F%````D(M< +MMU3&0P,`QT,$`````,=#4`````"`8P'^QT,X`````("]Y_W__P!U#H`_!G4) +M@W\$`'0RC78`@^P$:``"``!J`(V5Z/W__U+H_/___XV%Z/W__U!J,&H`C4,\ +M4.C\____@\0@ZQ&*5P&#X@&*0P&#X/X)T(A#`8/L#%/H_/___X/$$$:)\CA7 +M/`^'//___X/L!&C8````:@!7Z/S___^+50B+@EPB``")1PB)NEPB``#'1T`` +M````@\00C67T6UY?R<-5B>575E.![!P"``"+50R+?1"+312+`HM8!(F=Y/W_ +M_XM:((M3%(F5X/W__P^V0`.)A=S]__^-E>C]__^#O>#]__\`=`QF#[9#$(/@ +M`3G(=2:)E>#]__^#>Q@`=!!14E/_=0C_4QB#Q!"%P'4*N`````#IE@````^W +M0RS!X`D/MG,HB?:+E>#]__^+&KD```$`9H-Z!`!T!`^W2@2)PCG(=@*)RCNU +MW/W__W409HE7!&;'1P8``(D?@\<(D"G1`=,IT'4A1HN5Y/W__P^V0CPYQG4% +MO@````"+E>3]__\/MT)(P>`)AP8`@'0+@\,(B9W@_?__ +MZX)FQT?^`("X`0```(UE]%M>7\G#C78`58GE5U93BT4(BTT,BW@$BW$DBE`# +M9HM9,#A1*'4*#[=!+@'&ZPV)]CA1*'8&#[='2`'&.%$H=01F`UDL.%$I=0=F +M`UDJC78`@'DT`'0..%$H575E.#[`B+?0QFBW<(9L=%\@``BT4(#[9( +M/HM?!-/K9L=',```QDR+50@/MDH^T^")1R0/ +MMDH\B=BZ`````/?QB%A$!=`:*0A&(0Q&#[`A25NC\ +M____@\009H-[,@!U&H![$0!U!,9#$0&#[`13_W,<5NC\____@\00C67X6U[) +MPU6)Y5=64X/L#(M]#(L'B47P]D`!!'49QD<1`H/L!%?_=QS_=0CH_/___^G) +M````D%?_=?#H;_[__X/$"&:#?S(`=1G&1Q$"@^P$5_]W'/]U".C\____Z9T` +M``"0O@````"+5?"`>CP`#X2*````B?8/MTS_ +M4C2#Q!"-=@!&BTWP#[9!/#GP#X]X____C67T6UY?R<-5B>6#[`B+50R+2@2* +M00'`Z`*#\`&#X`&`8@'[@&$!^_Y)/8!)2@&#>3@`=!.%P'4/@^P(4?]U"/]1 +M.(/$$(GVR<.)]E6)Y593BUT0BW44BT4,BU`@BTH4A>>Z`0```(G0C67X6U[)PY!5B>564XMU"`^V!H/H +M!(/X`7=!NP````"`?CP`="^)]H-\GE0`=!.#[`S_=)Y4Z,W___^#Q!"%P'4* +MN`````#K'(UV`$,/MD8\.=A_T[@!````ZPF*1@'`Z`*#X`&-9?A;7LG#58GE +M5U93@^P,BW4,BUX@BSN+!HE%\(!^$0$/A-````#V0Q`"=':`>Q(`#X7````` +M]D=*`@^%M@```,9#$@&`>`,!&<"#X`2+1#A4B47PA0BD81B$,1@^P(5O]U".C\____BT7P#[9(`[C^____T\!F +M(4,R@\009H-[,@!U/H![$0!U!,9#$0&#[`13_W,<_W4(Z/S___]F_T\6@\00 +M9H-_%@!U%XM''(7`=!"#[`C_=R#_=0C_T(/$$(GVC67T6UY?R<-5B>53@^P$ +MBU4,BUT0BTT4BT(@A!0` +M=";V0!`!=""+2!20BP&+402)`XE3!(/#"(U!!H/!"&:#.`!YY^L9D+H````` +M@W@8`'0245-0_W4(_U`8B<+K!;H!````B="+7?S)PU6)Y5=64X/L#(M]"(MU +M#(M>((L&#[9(`[C^____T\!F(4,R@'X1`70&BD81B$,1@^P(5E?H_/___X/$ +M$&:#>S(`=4F`>Q$`=1?&0Q$!BPN+45`[5@1U"0^W1@@!T(E!4(/L!%/_575E.#[`R+?0B+=0R+7B"`?A$!=`B*1A&(0Q'K7(!^"B!U/L9&$0"+`XM` +M6(D&@^P$:C!J`(U&)%#H_/___\9&$@#&1@HPBD80@^#]@\@$B$80@\0(BP96 +M5_]0-.M.C78`QD,1`8L+BU%0.U8$=0H/MT8(`=")05"0@^P(5E?H_/___X/$ +M#%/_!0`=";V0!`!=""+2!20BP&+402)`XE3!(/# +M"(U!!H/!"&:#.`!YY^LUD+H`````@W@8``^$D@```%%74/]U"/]0&(/$$+H` +M````AL.9HEQ!&;'008`@.L]B?:)^8GVN@```0!F@WD$`'0$#[=1!(M= +M#(L#@'@#`'01.?)V$0$QB=!F*?!FB4$$ZPLY\G.^@\$(*=9UR8M5#(L"@'@# +M`'0B.<]T'HGVBP&+402)!XE7!(/'"(U!!H/!"&:#.`!YYXUV`+H!````B="- +M9?1;7E_)PY!5B>575E.#[`R+?0B+=0R+7B"`?A$!=`B*1A&(0Q'K<(L&@'@# +M`'4LQD81`(L#BT!8B0:#[`1J,&H`C48D4.C\____QD82`(/$"(L&5E?_4#3K +M<)"#[`0/MT8(P>`)4`-##%#_575E.#[`R+?0B+ +M70R+,\=&'`````#V1DH!#X5:`0``#[9#"H/X`@^$^0```(/X`G\0@_@!#X27 +M````Z3H!``")]H/X`P^%+P$``(M#!(E&$&:+0PAFB484@^P$#[=#",'@"5!J +M`/]S#.C\____9L=#,@,`QT7P`````(/$$(/L#%?H_/___XG"QD`*,(M#!(E" +M!&:+0PAFB4((@$H0!(E:(,="'`````#'0A@`````BTWPBT2.5(D"@\0(4E?_ +M4#2#Q!#_1?"#??`!?K'IO````(M#!(E&$&:+0PAFB484@^P,5^C\____B<+& +M0`H@BT,$B4($9HM#"&:)0@B`2A`"B5H@QT(<`````,="&`````"+1E2)`H/$ +M"%)7_U`T@\00ZVJ)]HM#!(E&$&:+0PAFB484@^P,5^C\____B<+&0`H@BT,$ +MB4($9HM#"&:)0@B`2A`"B5H@QT(<`````,="&`````"+1E2)`H/$"%)7_U`T +M@\00ZQ:)]L9#$0:#[`13_W,<5^C\____@\00@^P$C4884&@`````5^C\____ +MC67T6UY?R<.)]E6)Y5=64X/L'(M]#(LW]D8!!'48QD<1`H/L!%?_=QS_=0CH +M_/___^E\`0``]D<0('0JQT80+WV(-]Y`!Y`_==Y#M%Y'T4QD7S`(7)=3>#?>@%=C'&1?,!ZRO&1?,`@WWH +M`'4%@_D%=QS&1?,!ZQ:)]H!^3@`/E$7SBD7SB$9.ZP3&1?,`9L=',@``LP`/ +MML.#?(94`'1FBT2&5/9``01T7/9'$`1U!3A=\W51@^P,_W4(Z/S___^)1>R# +MQ`QJ)%=0Z/S___\/MLNX`0```-/@9@E',HM5[(EZ(,="'`````#'0A@````` +MBT2.5(D"@\0(4O]U"/]0-(/$$(GV0X#[`7:*B?:-9?1;7E_)PU6)Y593BTT( +MBW4,BUX$#[96`X!F`?N`2TH!QT-0`````/Y+/8![/0!U!H!C`?OK&(I#2J@" +M=!&#X-6(0TJ%TG4'@&,!^XUV`/9#`01U&H-[.``/A,P```"#[`A34?]3.(/$ +M$.F\````A=)U%(M35,9"`P&+0UC&0`,`B4-4B5-8@WL$`'0)BT,$]D`!!'1M +MBT-4@#@#=66#[`A34>C\____B<*#Q!"%P'12Q@`#QD`#`8E8!*$,````B4(T +MH1@```")0CCV0P$0=`J`2@$0BT),B4(,QT8$`````(E36(I#2H/@_H/("HA# +M2OY#/8/L"%)J!^C\____@\00D(-[!`!T"XGVBUL$@WL$`'7WBT-`B4-$Z/S_ +M__^)0T"#[`Q3Z/S___^-9?A;7LG#D%6)Y5=64X'L+`(``(M%#(M-%(L0B97D +M_?__BT`@B874_?__BU@4QX7@_?__$0```(V5Z/W__X7;=`QF#[9`$(/@`3G( +M=2J)TXNUU/W__X-^&`!T$%%25O]U"/]6&(/$$(7`=0RX`````.D``0``B?:+ +MO=3]__^`?RG_#X33````#[=/+,'A";X```$`9H-[!`!T!`^W#]__\Y\7>YBY7D_?__BD(#B[W4_?__.DP8`@'4-9L='!@"`N`$```#K,XM%$&;'0`8``(/`"(E%$(/#"/^-X/W_ +M_X/L!(N%X/W__\'@`U!3_W40Z/S___^X`0```(UE]%M>7\G#B?95B>6+50R+ +M31"+10B*0`,Z0BAU$&:+0BQFB4$(BT(DB4$$ZP]FBT(J9HE!",=!!`````#) +MPXUV`%6)Y5=64X/L"(M]"(MU#(M>!&:+1@AFB47RQT7L`````+D`````@'\\ +M`'1\BU2/5#E:#'9GB5XDB$XHN`$```#3X&:+?C()QV:)?C(/MT7R`=@[0@QV +M-<=%[`$```"-00&(1BE!BT7LT^")P8GX" +M7\G#D%6)Y593BW4(BU4,BUH@BP(/MD@#N/[____3P&8A0S*`>A$!=`:*0A&( +M0Q&#[`A25NC\____@\009H-[,@!U&H![$0!U!,9#$0&#[`13_W,<5NC\____ +M@\00C67X6U[)PU6)Y5=64X/L#(M]#(L'B47P]D`!!'49QD<1`H/L!%?_=QS_ +M=0CH_/___^G)````D%?_=?#HL_[__X/$"&:#?S(`=1G&1Q$"@^P$5_]W'/]U +M".C\____Z9T```"0O@````"+5?"`>CP`#X2*````B?8/MTS_4C2#Q!"-=@!&BTWP#[9!/#GP#X]X____C67T6UY?R<-5B>6# +M[`B+10R+4`2`8`'[@&(!^_Y*/8!*2@&#>C@`=`^#[`A2_W4(_U(X@\00B?;) +MPXGV58GE4XM="(M-#(N4B_PO``"%TG0)BP*)A(O\+P``B=!;R<.058GE4XM= +M"(M-#(M5$(N$D_PO``")`8F,D_PO``!;R<-5B>575E.#[`R+10R[`(```#T` +M0```=V%FNP!`/0`@``!W5F:[`"`]`!```'=+9KL`$#T`"```=T!FNP`(/0`$ +M``!W-6:[``0]``(``'P`````N`````"!^P`0 +M```/A]8```#_3?"#??#_#X3&````D(/L#/]U".C\____B<;_1>R_`````(/$ +M$+@`$```N@````#W\X/X``^&BP```(UV`+@*````@?L`0```=U>P"8'[`"`` +M`'=-L`B!^P`0``!W0[`'@?L`"```=SFP!H'[``0``'564XMU"(M=#+@`````.9XH,```R<.-=@!5B>564XM="(MU#(L.28/Y_W0?D(M4 +MC@2+@R0P``")`HF3)#```/^#*#```$F#^?]UXFH"5E/HN?W__XUE^%M>R<.) +M]E6)Y593BW4(BQY+@_O_=!R#[`1H`!```&H`_W2>!.C\____@\002X/[_W7D +MC67X6U[)PY!5B>53BUT(BPM)@_G_=">+1(L$N@````"#.`!T![@`````ZQ=" +M@\`$@?K_`P``=NA)@_G_==FX`0```%O)PXGV58GE@^P,:A!J`/]U".C\____ +MR<-5B>6+30R#>0P`=`F+40R+00B)0@B+40B+00R)`L=!"`````!J`%'_=0CH +M^?S__\G#C78`58GE4XM5"(M-#(U:,(M",(E!#(7`=`F+4C"-00R)0@B)60B) +M"UO)PU6)Y5=64XM]$(MU%(M%#(M8,(7;=!F)]CDSP1V![@`````ZR.+ +M6PR%VW7I:@#_=0CH;_S__XG#B3B)<`10_W4,Z(____^)V(UE]%M>7\G#D%6) +MY5.+30B*42D/MMJ-!-T`````*=B-7($L0HA1*8D+QD,%`,9#!@#&0P<`B=A; +MR<.-=@!5B>575E.+?0B+=0R[``````^V5B:-0OW1^`'"@_H`?B.-=@#_M)ZL +M!P``5^@?_O__@\0(0P^V5B:-0OW1^`'".=I_X&H'5E?H]_O__XUE]%M>7\G# +MC78`58GE5U93@^P@/ME7SC4+]T?@!PHE5[/]U +MZ/]U".CQ^___B82^K`<``(/$"(7`=3-/@___=!F0_[2^K`<``/]U".@Y_/__ +M@\0(3X/__W7H:@=6_W4(Z!GZ__^X`````.LQB?:#[`R)^\'C!`'SC8/4!P`` +M4.B^_/__@<-4"```B1PDZ+#\__^#Q!!'.7WL?X>)\(UE]%M>7\G#D%6)Y5=6 +M4X/L#(M]$(M%%&:)1?*+50P/MDH^B?C3Z"7_`P``BU(LC1R"BS.%]G0@D#E^ +M('43BU8$BP:)4`2)`HDVB78$B?#K:XMV%(7V=>$/MT7R4%>+50P/MD(\4/]U +M".B'_?__B<:#Q!"%P'1#BTT,B4@)@^V2#Z)^-/HBTT,#[91/(G1N@````#W\2C32XA>)XGPC67T6UY? +MR<.058GE5U93@>S,````BT4,BE`0B-#0Z(/P`8G!@^$!B8U4____BT4,@W@4 +M`'0%]L(!=""-E5C___^)E5#___]J`5+_=0S_=0B+30S_41B#Q!#K#(M%#(M` +M%(F%4/___\>%./___P```0"+E5#___]F@WH$`'0*#[=*!(F-./___\>%0/__ +M_P````#'A4S___\`````BT4,@'A$``^$W`$``(N53/___XM-#(M4D3")E43_ +M__^*BBP)``"(C4O___\XBBT)```/@I@!``"*A4O___^+E43___\X0B@##[?`B84T____ +M@^('9HF5//___P^WPHG"P>()N`@```!F*X4\____9HF%//___V:+A3[___]F +M.84\____=@=FB84\____#[>%//___XG&P>8)#[:%2____XN-1/___XN$@:P' +M``")UXN--/___P-\B`20BX4X____.85`____=3*#A5#___\(QX4X____```! +M`(N54/___V:#>@0`=`H/MTH$B8TX____QX5`____`````(N=./___RN=0/__ +M_SGS=@*)\X.]5/___P!T(8/L!%.+A4#___^+E5#___\#`E!7Z/S___^#Q!#K +M'XUV`(/L!%-7BX5`____BXU0____`P%0Z/S___^#Q!`!G4#___\IWG0'`=_I +M5____XN%//___V8IA3[___]T&?^%-/___[H`````9L>%//___P@`Z>O^___^ +MA4O___^*E4O___^+C43___\XD2T)```/@VC^____A4S___^+50P/MD)$.X5, +M____#X\D_O__@^P$:@#_=0S_=0C_51"-9?1;7E_)PXGV58GE5U93@^P,@WT0 +M`'0'BT4,QD`1"\=%\`````"+50R`>D0`#X3!````BT4(!>PO``")1>R+50B! +MPN0O``")5>B-=@"+1?"+50R+7((PQX,$"0```````(G?L0"`>R8`=D&)]@^V +MP<'@!`'XC9#4!P``O@````"#N-0'````=12#>@0`=0Z#>@@`=0B#>@P`=`>) +M]KX!````A?9U(4$X3R9WP;@`````AB+0@2)6@2)$XE#!(D8_T7PBU4,#[9"1#M%\`^/6?___X/L +M"/]U#/]U".AC/P``C67T6UY?R<.-=@!5B>575E.#[!R+70R+LP0)``"+10C_ +MB"PP``"-0PB+2`2+4PB)2@2)$8E#"(E`!(7V#X11`@``]D80(`^$^P```(L^ +M#[=#)`-#((E%[&:+4R1FB57JQX,$"0```````(M%"`7D+P``BU`$B5@$B0.) +M4P2)&H"[+@D```%U1(!^"@)U-0^V0R?_M(.L!P``Z'7W__^#Q`2%P'4>QH,N +M"0``#(!/2@H/MT=(]]@C0R`Y1U!V!8E'4(GV@+LN"0```70:BH,N"0``B$81 +M@^P(5O]U".B"/@``Z5D#```/MT=(BU8$0@^OPCM%['8K#[=%ZE#_=>Q7_W4( +MZ+#Z__^)L`0)``")1C"#Q`A0_W4(Z*L/``#I'@,```^W1T@#1U`[1>QU!HM% +M[(E'4(/L"%;_=0CH)#X``.G[`@``C78`BD9%0(A&13I&1`^%=`(``/9&$`0/ +MA,H```#&1?,`@'Y$``^&J````(M5"('"Y"\``(E5X(M%"`7L+P``B472-A!#4!P``4.B%]O__@\001XGXBU7D.$(F=]>+5>"+0@2) +M6@2)$XE#!(D8ZQJ0BH,N"0``B$81BU7#"`D```````"#[`A3 +M_W4(Z,X-``"#Q!#IR@```(M%"`7D+P``BU`$B5@$B0.)4P2)&NM7C78`BT4( +M!>PO``"+4`2)6`2)`XE3!(D:@[L("0```'0VBY,("0``BH,N"0``B$(1@^P$ +M_[,("0``:!1F``#_=0CH_/___\>#"`D```````#IT@```(GV_W,8_W4(Z.WT +M___'0Q@`````BT,<@\0(@W@8`'09@^P$@\`84&@`````_W4(Z/S___^#Q!#K +M)8M5"(.Z-#````!T&8/L!(G0!30P``!0:`````!2Z/S___^#Q!"+10B#N#`P +M````=&B`NRX)```!=5^+0QR#>"0`=#V#[`Q0Z-TY``"#Q!"%P'4M@^P$BT,< +M_W`HBT,<_W`D_W4(Z/S___^+0QS'0"0`````BU4(_XHP,```@\00BT4(@[@P +M,````'0-@^P,4.C\____@\00D(UE]%M>7\G#58GE@^P(BT4,BP"`>"H`=!O& +M0"H`@^P$4&@4-0``_W4(Z/S___^#Q!"-=@#)PXGV58GE5U93@^P,BU4,BWT0 +MBT(@BP@/MD`)BX2!K`<``(E%\(M"!"M!(,'@"0^W<@C!Y@F)PH'B_P\``,'H +M#(E%[+@`$```B<,ITSGS=@*)\X-]%`!T#XM%[(M-\`-4@03K&XUV`(/L#(M% +M[(M-\`-4@012Z/S___^#Q!")PHD79HE?!#GS=!5FQT<&``"#QPC_1>PIWKH` +M````ZZ5FQT<&`("X`0```(UE]%M>7\G#B?95B>575E.+50B*0@H"0@N(0@J- +M6@R^`0```.L3@'H*`'D*N`````#I\@```/Y""@^V2@J#^1]W$(GPT^"%0@P/ +ME<`/ML#K39"#^3]W$X/I((GPT^"%0P0/E<`/ML#K-9"#^5]W$X/I0(GPT^"% +M0P@/E<`/ML#K'9"X`````(/Y?W<2@^E@B?#3X(5##`^5P`^VP(GVA@P/MEH*O@$```#K!8GV_D(+#[9""XT,`X/Y'W<1B?#3X(5"#`^5P`^V +MP.M.B?:#^3]W$X/I((GPT^"%1P0/E<`/ML#K-9"#^5]W$H/I0(GPT^"%1P@/ +ME<`/ML#K';@`````@_E_=Q.#Z6")\-/@A4<,#Y7`#[;`C78`A0@'L$`75"BD,(.$8G=#HX +M0PEU-0^VR(G(P>`$C8PP5`@``(US#(L!"T,,B0&+000+1@2)002+00@+1@B) +M00B+00P+1@R)00R0QD,%`H/L"%-7Z%[]__^-9?1;7E_)PXGV58GE4X/L!(M= +M#,9#"P#&0PH`4^@<_O__@^P$4_]U".@(````BUW\R<.-=@!5B>575E.#[!B+ +M70R+,XM6'`^V0PB+?()4_W4(Z/S___^)PHDX@\00@'L$`74*@$@0`L9`"B#K +M"(!($`3&0`HP#[9#"@-&((E"!&8/MD,+9HE"",="&"@K``")6B#'0AS\+``` +M@^P(4O]U"/]7-(UE]%M>7\G#B?95B>575E.#[`B+?0R^`````,=%\`````"+ +M10B)1>SK$X-]\']V"HGPZ4R%0@@/E<`/ML#K(+@`````@_I_=Q:-2J"P`=/@BU7L +MA4(,#Y7`#[;`C78`A<`/A&S___^[`0```(M5".L#B?9#BTWP`=F#^1]W$;@! +M````T^"%`@^5P`^VP.M4@_D_=Q>#Z2"X`0```-/@A4($#Y7`#[;`ZSJ)]H/Y +M7W<7@^E`N`$```#3X(5""`^5P`^VP.L>B?:X`````(/Y?W<2@^E@L`'3X(5" +M#`^5P`^VP(GVA(T(/@!XA$MP&Q""C!B$RW +M`@^VP3G88)BH2=Z/[__XB%T_[__P^V +MT(G(B[W8_O__`T27!(F%X/[__XN%U/[__XM\D`0!SXF]M/[__XF]Y/[__XN% +MW/[__XM\D`0!SSF]X/[__W4D@^P$5O^UM/[__XG(B[7<_O__`T26!%#H_/__ +M_X/$$.LJC78`5O^UY/[___^UX/[__P^VA=/^__^+O=S^__\#3(<$4>C\____ +M@\000SN=S/[__P^,0/___^FM````C78`C87H_O__4%/H'_W__XF%S/[__P^V +M0Q2+A(:L!P``B87<_O__BU4,#[9"#(N$AJP'``")A=C^__^[`````(/$"#N= +MS/[__WUB#[:$G>G^__^)P<'A"0^VA)WJ_O__B<;!Y@D/MI2=Z/[__XG(B[W< +M_O__`T27!(F%X/[__XG(B[W8_O__`T27!(F%Y/[__X/L!%90_[7@_O__Z/S_ +M__^#Q!!#.YW,_O__?)Z#[`1J`/]U#/]U".AJ`@``C67T6UY?R<.)]E6)Y5=6 +M4X'L+`$``(M%#(L8C87H_O__4(M%#(/`"%#H1/S__XF%V/[__XM5#`^V0AB+ +MA(.L!P``B87<_O__#[9"&8N$@ZP'``")A=3^__^^`````(/$"#NUV/[__WU= +MD`^VA+7I_O__P>`)#[:,M>K^___!X0D/MIRUZ/[__XG"B[W<_O__`U2?!(F5 +MX/[__XN5U/[__P-$F@2)A>3^__^#[`114/^UX/[__^C\____@\001CNUV/[_ +M_WRD@^P$:@#_=0S_=0CHE`$``(UE]%M>7\G#58GE5U93@>Q\`0``BT4,BS"+ +M6`B-A>C^__]04^AS^___B864_O__#[9#%(N$AJP'``")A:3^__^Q`(/$"(M5 +M#(!Z%`!V)(I:%(UV``^VP8M]#`^V5`<,BY26K`<``(F4A% +MF/[__P````"+A93^__\YA9C^__\/C>X```")]HN5F/[__P^VA)7I_O__BC^__^(C9_^__^Q`(M=#(![%`!V,0^V +MM9_^__^*0Q2(A8?^__\/ML&+E(7(_O__BURR!(T4'XF4A:C^__]!.(V'_O__ +M=]\/MI6?_O__B?B+C:3^__\#1)$$.86H_O__=2"#[`3_M:#^____M:S^__^) +M^`-$D010Z/S___^#Q!#K+/^UH/[___^UK/[___^UJ/[__P^VA9_^__^+G:3^ +M__\#?(,$5^C\____@\00_X68_O__B[V4_O__.;V8_O__#XP4____@^P$:@#_ +M=0S_=0CH"````(UE]%M>7\G#58GE5U93@^P4BWT(BUT,BW40QD,%`H/^`1G` +M@^#U@\`,B$,&4U?HC?;__X/$$(![!`-U,(M#"(M0$(72=";'0!``````QD(% +M`H/^`1G`@^#U@\`,B$(&@^P(4E?H5_;__X/$$(UE]%M>7\G#58GE5E.+70B+ +M=0P/MDX'A`4"=`FX`````.LK +MB?:`>`8!=!+&1@4"BD`&B$8&N`````#K$I`/MHQ+O08``(7)=;BX`0```%M> +MR<.-=@!5B>575E.#[!R+?0S&1RH`@+\O"0```'1[O@````"-7RR`?RD`=$F0 +M@'L%`74V@'L$`W4EBT,(@'@5`'0<@W@0`'06QT`0`````,9#!0**ARX)``"( +M0P;K"\9'*@'I]P$``(GV1H/#'`^V1RDY\'^X@^P(5_]U".@L\?__Z=@!``"* +M0P:(ARX)``#&AR\)```!ZX:0QT7P`````,=%[`$```"^`````(U?+(!_*0`/ +MA'P!``"`>P4`#X66````4U?HT_[__X/$"(7`='S&0P4!BT4(B47HB=H/MD,$ +M@_@&=V?_)(4`````@^P(4_]UZ.B<]___@\00ZT^#[`A3_W7HZ*OY__^#Q!#K +M/H/L"%/_=>CHMOO__X/$$.LM@^P(4_]UZ.AY_/__@\00ZQS&1RL!QD(%`L9" +M!@&#[`A2_W7HZ*#T__^#Q!"0@'L%`G4,_T7PC78`@'L%`G0.QT7L`````.FZ +M````B?:`>P8!#X2N````@'\K``^$!?___XM''`^V4PB+1)!4]D`!!`^$B``` +M`,=%[`````#&0P4!QD,&`(M%"(E%Y(G:#[9#!(/X!G=O_R2%'````(/L"%/_ +M=>3HS/;__X/$$.M7@^P(4_]UY.C;^/__@\00ZT:#[`A3_W7DZ.;Z__^#Q!#K +M-8/L"%/_=>3HJ?O__X/$$.LDQDP`=!7&ARX) +M```!@^P(5_]U".A5[___ZP3&1RH!C67T6UY?R<.-=@!5B>575E.![&P!``"+ +M10R+6!R+N`0)``#&A;'^__\`A?]U,0^W0"2+30R+42`!T%!24_]U".C"Y___ +MBW4,B488@\00N/____^#?A@`#X09*P``B?:+10C_@"PP``"+10R#P`B+50B! +MPO0O``"+2@2)0@2+=0R)5@B)2`2)`6:#>TP`=$#V0TH!=0B+0U`[1B!W)[X` +M````#[=#3(G"J`%U#HUV`$:)T(GQT_BH`73UB?.+10R(6"CK+HM5#,9"*`CK +M)8GV]D-*`G06BT-0BTT,.T$@=PN*02>(02CK"HUV`(M=#,9#*`B+=0S&1BD` +MQH:\!@```,9&*P#&ABX)````QH8O"0```,>&"`D```````"%_P^$7Q,``/9' +M$"`/A&D)```/MD<*@_@"#X2&!0``@_@"?PZ#^`$/A$0!``#I%2H``(/X`P^% +M#"H``(/L#(V=V/[__U/H,>;__X/$$+\`````BT4,#[=P)+,`@_\?=U(/ML.- +ME(78_O__B;VL_O__N2`````I^3GQ=@*)\8/Y('4(QP+_____ZQ*X`0```-/@ +M2(J-K/[__]/@"0*X(````"GX.?!S%(UT/N"_`````.L#@^\@0X#[`W:@@^P, +MBUT,_[.L!P``Z#OE___&A;/^__\`@\00@'LF``^&9RD``(/L#`^VG;/^___! +MXP0#70R-@]0'``!0Z'_E__^!PU0(``")'"3H<>7__X/$$/]U#.@JYO__@\0$ +MQD`$`HJ5L_[__XA0",9`"0"+E=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+ +ME>3^__^)4!C^A;/^__^*C;/^__^+70PX2R8/AWO____IW2@``+@!````ZTV+ +M=0RQ`(!^)@!V/0^VP<'@!`'PC9#4!P``NP````"#N-0'````=1*#>@0`=0R# +M>@@`=0:#>@P`=`6[`0```(7;=;=!.$XF=\.X`````(7`=!B+=0R)O@@)``#' +MA@0)````````Z8T1``"#[`R-G=C^__]3Z)+D__^#Q!"_`````(M%#`^W<"2S +M`(/_'W=2#[;#C92%V/[__XF]J/[__[D@````*?DY\78"B?&#^2!U",<"____ +M_^L2N`$```#3X$B*C:C^___3X`D"N"`````I^#GP*(B>Z`@``,:&Z0@```&+A=C^ +M__^)AM0(``"+A=S^__^)AM@(``"+A>#^__^)AMP(``"+A>3^__^)AN`(``#' +MAN0(````````5NB#Y/__@\0$QD`$`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0 +M$(N5X/[__XE0%(N5Y/[__XE0&(G'@'XF`@^'5`$``(GS@B8`#X;1)@``BHVS_O__BUT,.$LH#X2H````4^BQX___ +M@\0$QD`$`8J5L_[__XA0"(A0"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0 +M%(N5Y/[__XE0&(N-P/[__XI1%`^VRHJ=L_[__XNUP/[__XA<#@Q"B%84BQ[^ +M@[P&```/MK.\!@``*=B#Z"S!^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J( +ME'.\!@``B[W`_O__BD<'B(1SO08``(GPB$<'_H6S_O__BI6S_O__BTT,.%$F +M#X#^__^)4!2+E>3^__^)4!B)A<3^____=0SH=>+_ +M_X/$!,9`!`.+G:3^__^)6`B*E;/^__^(4`R)A<#^__^+&/Z#O`8```^VL[P& +M``"+E<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`(A'.]!@``B?.(60>+'_Z#O`8```^VL[P&``")RBG:@^HL +MP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(I'!XB$<[T&``") +M\(A'!_Z%L_[__XJ5L_[__XM-##A1)@^'U/[__^FI)```N`$```#K4HMU#+$` +M@'XF`'9"C78`#[;!P>`$`?"-D-0'``"[`````(.XU`<```!U%(-Z!`!U#H-Z +M"`!U"(-Z#`!T!XGVNP$```"%VW6R03A.)G?!N`````"%P'08BUT,B;L("0`` +MQX,$"0```````.E4#0``@^P,C9W8_O__4^A9X/__@\00OP````"+10P/MW`D +MLP"#_Q]W4@^VPXV4A=C^__^)O:#^__^Y(````"GY.?%V`HGQ@_D@=0C'`O__ +M___K$K@!````T^!(BHV@_O__T^`)`K@@````*?@Y\',4C70^X+\`````ZP.# +M[R!#@/L#=J"+70R*0R>(@^@(``#&@^D(````BX78_O__B8/4"```BX7<_O__ +MB8/8"```BX7@_O__B8/<"```BX7D_O__B8/@"```QX/D"````````(![)@(/ +MAP`!``"+70R!P]0(``#_=0SH1.#__X/$!,9`!`6)6`C&0!0`B87`_O__QH6S +M_O__`(MU#(!^)@`/AB0C``#_=0SH%.#__X/$!,9`!`&*E;/^__^(4`B(4`F+ +ME=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B+C<#^__^*410/ +MMLJ*G;/^__^+M<#^__^(7`X,0HA6%(L>_H.\!@``#[:SO`8``"G8@^@LP?@" +MC13`C130C130C130B='!X0\!RHT4T/?:B)1SO`8``(N]P/[__XI'!XB$<[T& +M``")\(A'!_Z%L_[__XJ5L_[__XM-##A1)@^'/O___^E=(@``BW4,BEXG5NA) +MW___@\0$QD`$`8A8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5 +MY/[__XE0&(F%O/[__\:%L_[__P"`?B8`#X8)(@``B?>!Q]0(``"*A;/^__^+ +M50PX0B__^#Q`3&0`0!BHVS_O__B$@(B$@)BY78_O__B5`, +MBY7<_O__B5`0BY7@_O__B5`4BY7D_O__B5`8B87$_O___W4,Z)S>__^#Q`3& +M0`0#B7@(BIVS_O__B%@,B87`_O__BQC^@[P&```/MK.\!@``BY7$_O__*=J# +MZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD(' +MB(1SO08``(GQB$H'BQK^@[P&```/MK.\!@``BY6\_O__*=J#ZBS!^@*-!-*- +M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD('B(1SO08``(GQ +MB$H'_H6S_O__BIVS_O__BW4,.%XF#X?0_O__Z#`D```^WO)X."0``O@````"0@_H?=U>)\0^VP8N-G/[__XT<@8F5F/[_ +M_[D@````*=$Y^78"B?F#^2!U"<<#_____^L3D+@!````T^!(BHV8_O__T^`) +M`[@@````*=`Y^',6C7P7X+H`````ZP.#ZB!&B?.`^P-VF0^VG;/^__^)VHG8 +MP>`$BW4,C9PP5`@``(L+]]&)C=C^__^+0P3WT(F%W/[__XM#"/?0B87@_O__ +MBT,,]]")A>3^__^)UL'F!(V<->C^__^-E#5H____(PJ)"XM"!".%W/[__XE# +M!(M""".%X/[__XE#"(M"#".%Y/[__XE##(J%L_[__XM5##A"*'4MN@````"# +M.P!U$H-[!`!U#(-["`!U!H-[#`!T!;H!````A=)T",:%L?[__P&0_H6S_O__ +MBHVS_O__BUT,.(LM"0``#X-Y_O__@+VQ_O__``^$9`<``(/L#(V%V/[__U#H +M+=O__\:%L_[__P"#Q!"+=0R`?B8`=G>)]HJ%L_[__XM5##A"*'13.$(G=$X/ +MMM#!X@0#50R-BM0'``"+A=C^__\+@M0'``")A=C^__^+A=S^__\+002)A=S^ +M__^+A>#^__\+00B)A>#^__^+A>3^__\+00R)A>3^___^A;/^__^*C;/^__^+ +M70PX2R9WBXMU#`^V?BC!YP2-G#WH_O__B[78_O__(S.)M#^__\C4PB)E=#^__^+A>3^__\C0PR)A=3^___WUHFUV/[_ +M__?1B8W<_O__]]*)E>#^___WT(F%Y/[__R,SB;78_O__(TL$B8W<_O__(U,( +MB97@_O__(T,,B87D_O___W4,Z-#:__^#Q`3&0`0`B86T_O__N`````"#O=C^ +M__\`=1N#O=S^__\`=1*#O>#^__\`=0F#O>3^__\`=`6X`0```(7`#X0\`@`` +MBWT,BD'Y`@```````#&A;/^__\`@'\F``^& +MI@(``(J%L_[__XM5##A"*`^$KP$``#B"+`D``'<-.((M"0``<@4X0B=U1_]U +M#.@`VO__@\0$QD`$`8J-L_[__XA("(A("8N5V/[__XE0#(N5W/[__XE0$(N5 +MX/[__XE0%(N5Y/[__XE0&(F%Q/[__^MW#[:-L_[__\'A!(V<#>C^__^+A=C^ +M__\+`XD#BX7<_O__"T,$B4,$BX7@_O__"T,(B4,(BX7D_O__"T,,B4,,_W4, +MZ'K9__^#Q`3&0`0!BI6S_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+4PR) +M4!B)A<3^__^+70R!P]0(``#_=0SH.=G__X/$!,9`!`.)6`B*C;/^__^(2`R) +MA<#^__^+&/Z#O`8```^VL[P&``"+E<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$ +MPHG!P>$/`(A'.]!@``B?"(1P>*E;/^ +M__^+30PX42=U4XNUM/[__XL>_H.\!@``#[:SO`8``(GZ*=J#ZBS!^@*-!-*- +M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``B[VT_O__BD<'B(1SO08``(GP +MB$<'_H6S_O__BI6S_O__BTT,.%$F#XC^__^Z`````(,X`'42@W@$`'4,@W@(`'4&@W@,`'0%N@$` +M``"%TG1##[:%L_[__\'@!(VC^____=0SHR]?__X/$!,9`!`&*C;/^__^( +M2`B(2`F+$XE0#(M3!(E0$(M3"(E0%(M3#(E0&/Z%L_[__XJ=L_[__XMU##A> +M)@^'3/___[@`````@[W(_O__`'4;@[W,_O__`'42@[W0_O__`'4)@[W4_O__ +M`'0%N`$```"%P`^$6QH``(M%#(I`*(B%E_[__XM5#(B"``D``(N%R/[__XF" +M[`@``(N%S/[__XF"\`@``(N%T/[__XF"]`@``(N%U/[__XF"^`@``,:"`0D` +M``#'@OP(````````BEHG4NCTUO__@\0$QD`$`8A8"(J-E_[__XA("8N5R/[_ +M_XE0#(N5S/[__XE0$(N5T/[__XE0%(N5U/[__XE0&(F%O/[__\>%N/[__P`` +M``#&A;/^__\`BUT,@'LF``^&H1D``(J%L_[__XM5##A"*`^$S`$``#A")P^$ +MPP$``(I:)U+H==;__X/$!,9`!`&*C;/^__^(2`B(6`F+E$/`(A'.]!@``B?"(1P>#O;C^__\`=$N+'_Z#O`8```^VL[P&``"+ +ME;C^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`(A'.]!@``B?*(5P>+70R!P^P(``"+30R*22>(C9;^____=0SH=M7__X/$ +M!,9`!`.)6`B*G9;^__^(6`R)A<#^__^)A;C^__^+&/Z#O`8```^VL[P&``"+ +ME<3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`(A'.]!@``B?"(1P>+'_Z#O`8```^VL[P&``"+E;S^__\IVH/J +M+,'Z`HT$THT$PHT$PHT$PHG!P>$/`(A'.]!@`` +MB?*(5P?^A;/^__^*C;/^__^+70PX2R8/APK^___IIA<``(GVBT4,BH`L"0`` +MB(6S_O__BU4,.((M"0``#X*&%P``B?:*C;/^__^+70PX2R=T=@^VP<'@!(V$ +M!>C^__^Z`````(,X`'43@W@$`'4-@W@(`'4'@W@,`'0&D+H!````A=)T0P^V +MA;/^___!X`2-G`7H_O___W4,Z"+4__^#Q`3&0`0!BI6S_O__B%`(B%`)BQ.) +M4`R+4P2)4!"+4PB)4!2+4PR)4!C^A;/^__^*C;/^__^+70PXBRT)```/@V'_ +M___IX!8``(MU#(!^*``$`="- +MD-0'``"Y`````(.XU`<```!U$H-Z!`!U#(-Z"`!U!H-Z#`!T!;D!````A)@^'2/___P^VE;+^__^+?0P/MD$/`(A'.]!@``B?"( +M1P>+50R`>B8"#X?6`@``B=.!P]0(``!2Z-/1__^#Q`3&0`0%B5@(QD`4`(F% +MP/[__XN-M/[__XL9_H.\!@``#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*- +M!,*)P<'A#P'(C03"]]B(A'.\!@``B[VT_O__BD<'B(1SO08``(GPB$<'QH6S +M_O__`(M5#(!Z)@`/AF`4``"*C;/^__^+70PX2R`$C9P%Z/[___]U#.AST/__@\0$QD`$`8J5L_[__XA0"(A0"8L3B5`, +MBU,$B5`0BU,(B5`4BU,,B5`8BXW`_O__BQG^@[P&```/MK.\!@``*=B#Z"S! +M^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'.\!@``B[W`_O__BD<'B(1S +MO08``(GPB$<'#[:%L_[__\'@!(M5#(V$$-0'``"Z`````(,X`'42@W@$`'4, +M@W@(`'4&@W@,`'0%N@$```"%T@^$DP````^VG;/^__^)V,'@!(M-#(V<"-0' +M``!1Z)_/__^#Q`3&0`0"BI6S_O__B%`(B%`)BQ.)4`R+4P2)4!"+4PB)4!2+ +M4PR)4!B)QXL8_H.\!@``#[:SO`8``(N5M/[__RG:@^HLP?H"C032C03"C03" +MC03"B<'!X0\!R(T$PO?8B(1SO`8``(I'!XB$<[T&``")\8A/!_Z%L_[__XJ= +ML_[__XMU##A>)@^'N/W__^D3$@``QH6S_O__`(M]#(!_)@`/AO\1``"-=@"* +MA;/^__^+50PX0B-B%0(``"+D%0(``#WTHF5R/[_ +M_XM!!/?0B87,_O__BT$(]]")A=#^__^+00SWT(F%U/[__XV,/>C^__\CE=C^ +M__^)$8N%W/[__R.%S/[__XE!!(N%X/[__R.%T/[__XE!"(N%Y/[__R.%U/[_ +M_XE!#(M=#('#U`@``/]U#.A7SO__@\0$QD`$`XE8"(J-L_[__XA(#(F%P/[_ +M_XNUM/[__XL>_H.\!@``#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*-!,*) +MP<'A#P'(C03"]]B(A'.\!@``BY6T_O__BD('B(1SO08``(GQB$H'C80]Z/[_ +M_[H`````@S@`=1*#>`0`=0R#>`@`=0:#>`P`=`6Z`0```(72#X24````#[:% +ML_[__\'@!(VC^____=0SHHLW__X/$!,9`!`&*E;/^__^(4`B(4`F+$XE0 +M#(M3!(E0$(M3"(E0%(M3#(E0&(N-P/[__XL9_H.\!@``#[:SO`8``"G8@^@L +MP?@"C13`C130C130C130B='!X0\!RHT4T/?:B)1SO`8``(N]P/[__XI'!XB$ +M<[T&``")\(A'!P^VA;/^___!X`2+50R-A!#4!P``N@````"#.`!U$H-X!`!U +M#(-X"`!U!H-X#`!T!;H!````A=(/A)8````/MIVS_O__B=C!X`2+30R-G`C4 +M!P``4>C.S/__@\0$QD`$`HJ5L_[__XA0"(A0"8L3B5`,BU,$B5`0BU,(B5`4 +MBU,,B5`8B<>+&/Z#O`8```^VL[P&``"+E;3^__\IVH/J+,'Z`HT$THT$PHT$ +MPHT$PHG!P>$/`(A'.]!@``B?&(3P>-=@#^A;/^ +M__^*G;/^__^+=0PX7B8/ATC]___I/P\``(M]#(I?)U?H*\S__\9`!`&(6`B( +M6`F+E=C^__^)4`R+E=S^__^)4!"+E>#^__^)4!2+E>3^__^)4!B)A;S^__^* +M7R>)/"3H[,O__X/$!,9`!`*(6`B(6`F+E=C^__^)4`R+E=S^__^)4!"+E>#^ +M__^)4!2+E>3^__^)4!B)Q_]U#.BQR___@\0$QD`$!HF%M/[__XL?_H.\!@`` +M#[:SO`8``(G"*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\ +M!@``BD<'B(1SO08``(GPB$<'QH6S_O__`(M5#(!Z)@`/AE$.``"0BHVS_O__ +MBUT,.$LG#X1J`P``#[;!P>`$`=B-D-0'``"Y`````(.XU`<```!U$H-Z!`!U +M#(-Z"`!U!H-Z#`!T!;D!````A,K__\9`!`2*E97^__^(4!B)\8A(&8L3B5`( +MBU,$B5`,BU,(B5`0BU,,B5`4B87`_O__BQC^@[P&```/MK.\!@``BY6\_O__ +M*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__ +MBD('B(1SO08``(GQB$H'BQK^@[P&```/MK.\!@``BY7$_O__*=J#ZBS!^@*- +M!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY7`_O__BD('B(1SO08` +M`(GQB$H'B[6T_O__BQ[^@[P&```/MK.\!@``BY7`_O__*=J#ZBS!^@*-!-*- +M!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``BY6T_O__BD('B(1SO08``(GQ +MB$H'BUT,BELGB)V4_O__BW4,C9PWU`<``(DT).@RR?__QD`$!(J5E/[__XA0 +M&(J-L_[__XA(&8L3B5`(BU,$B5`,BU,(B5`0BU,,B5`4B87`_O__BQC^@[P& +M```/MK.\!@``BY6\_O__*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03" +M]]B(A'.\!@``BY7`_O__BD('B(1SO08``(GQB$H'B[6T_O__BQ[^@[P&```/ +MMK.\!@``BY7`_O__*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B( +MA'.\!@``BY6T_O__BD('B(1SO08``(GQB$H'BUT,C;P?U`<``(D<).A%R/__ +M@\0$QD`$`HJ5L_[__XA0"(A0"8L7B5`,BU<$B5`0BU<(B5`4BU<,B5`8B<>+ +M&/Z#O`8```^VL[P&``"+E;3^__\IVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/ +M`(A'.]!@``B?&(3P>)]OZ%L_[__XJ=L_[__XMU +M##A>)@^';/S__^FW"@``C78`BWT,BD@0`=0R#>@@`=0:#>@P`=`6Y`0```(7)=$@KQ___@\0$QD`$`HJ5L_[__XA0"(A0"8L3B5`,BU,$B5`0BU,( +MB5`4BU,,B5`8D/Z%L_[__XJ-L_[__XM=##A+)@^'7/___^GK"0``@^P,C878 +M_O__4.@0QO__@\00_W4,Z,G&__^#Q`3&0`0&B86T_O__QH6S_O__`(MU#(!^ +M)@`/AE0!``"*A;/^__^+50PX0B`$BUT,C908U`<``(N%V/[__PL"B878_O__BX7<_O__"T($B87< +M_O__BX7@_O__"T((B87@_O__BX7D_O__"T(,B87D_O__BH6S_O__.$,H#X2- +M````B+&/Z#O`8```^VL[P&``"+E;3^__\I +MVH/J+,'Z`HT$THT$PHT$PHT$PHG!P>$/`(A'.] +M!@``B?.(7P>0_H6S_O__BH6S_O__BU4,.$(F#X>L_O__BTT,BEDG4>A(Q?__ +M@\0$QD`$`HA8"(A8"8N5V/[__XE0#(N5W/[__XE0$(N5X/[__XE0%(N5Y/[_ +M_XE0&(G'BQC^@[P&```/MK.\!@``BY6T_O__*=J#ZBS!^@*-!-*-!,*-!,*- +M!,*)P<'A#P'(C03"]]B(A'.\!@``BD<'B(1SO08``(GSB%\'BW4,#[9>*(G> +MB=C!X`2+?0R-G#A4"```BP/WT(F%R/[__XM3!/?2B97,_O__BTL(]]&)C=#^ +M__^+6PSWTR.%V/[__XF%R/[__XN]W/[__R'ZB97,_O__BY7@_O__(=&)C=#^ +M__^+A>3^__\APXF=U/[__\'F!(M-#(VT#E0(``"+C=C^__\C#HF-V/[__R-^ +M!(F]W/[__R-6"(F5X/[__R-&#(F%Y/[__[@`````A$/`(A'.]!@``B?"(1P?IM0$``)"*E;/^__^+30PX42#^__^) +M00B+00PCA>3^__^)00Q3Z)'"__^#Q`3&0`0#B[60_O__B7`(BI6S_O__B%`, +MB87`_O__BXVT_O__BQG^@[P&```/MK.\!@``B<(IVH/J+,'Z`HT$THT$PHT$ +MPHT$PHG!P>$/`(A'.]!@``B?&(2@>- +MA#WH_O__N@````"#.`!U$H-X!`!U#(-X"`!U!H-X#`!T!;H!````A=(/A)<` +M```/MH6S_O__P>`$C9P%Z/[___]U#.C6P?__@\0$QD`$`8J5L_[__XA0"(A0 +M"8L3B5`,BU,$B5`0BU,(B5`4BU,,B5`8BXW`_O__BQG^@[P&```/MK.\!@`` +M*=B#Z"S!^`*-%,"-%-"-%-"-%-")T<'A#P'*C130]]J(E'.\!@``B[W`_O__ +MBD<'B(1SO08``(GPB$<'C78`_H6S_O__BI6S_O__BTT,.%$F#X>P_?__N``` +M``"#O%N/[__P````#&A;/^__\` +M@'XF``^&M`,``(J%L_[__XM5##A"*`^$B@,``#A")P^$@0,```^VP,'@!(V< +M!>C^__\!T(V(U`<``(N5R/[__R.0U`<``(D3BX7,_O__(T$$B4,$BX70_O__ +M(T$(B4,(BX74_O__(T$,B4,,N`````"#.P!U$H-[!`!U#(-["`!U!H-[#`!T +M!;@!````A<`/A!$#``"+30R*22B(C8_^__\/MH6S_O__P>`$C9P%Z/[___]U +M#.C\O___@\0$QD`$`8J5L_[__XA0"(J-C_[__XA("8L3B5`,BU,$B5`0BU,( +MB5`4BU,,B5`8B87$_O__@[VX_O__`'11BQC^@[P&```/MK.\!@``BY6X_O__ +M*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'(C03"]]B(A'.\!@``B[W$_O__ +MBD<'B(1SO08``(GPB$<'BU4,BE(GB)6._O__BTT,BDDHB(V-_O__#[:]L_[_ +M_\'G!(VC^____=0SH.[___X/$!,9`!`2*E8[^__^(4!B*C8W^__^(2!F+ +M$XE0"(M3!(E0#(M3"(E0$(M3#(E0%(F%P/[__XF%N/[__XL8_H.\!@``#[:S +MO`8``(N5O/[__RG:@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1S +MO`8``(N5P/[__XI"!XB$<[T&``")\8A*!XL:_H.\!@``#[:SO`8``(N5Q/[_ +M_RG:@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(N5P/[_ +M_XI"!XB$<[T&``")\8A*!XNUM/[__XL>_H.\!@``#[:SO`8``(N5P/[__RG: +M@^HLP?H"C032C03"C03"C03"B<'!X0\!R(T$PO?8B(1SO`8``(N5M/[__XI" +M!XB$<[T&``")\8A*!XM=#(I;)XB=C/[__XVC^____=0SHZ[W__X/$!,9` +M!`2*E8S^__^(4!B*C;/^__^(2!F+$XE0"(M3!(E0#(M3"(E0$(M3#(E0%(F% +MP/[__XL8_H.\!@``#[:SO`8``(N5O/[__RG:@^HLP?H"C032C03"C03"C03" +MB<'!X0\!R(T$PO?8B(1SO`8``(N]P/[__XI'!XB$<[T&``")\(A'!XN5M/[_ +M_XL:_H.\!@``#[:SO`8``(GZ*=J#ZBS!^@*-!-*-!,*-!,*-!,*)P<'A#P'( +MC03"]]B(A'.\!@``BXVT_O__BD$'B(1SO08``(GSB%D'D/Z%L_[__XJ%L_[_ +M_XM5##A")@^'3/S__X/L"/]U#/]U".@VTO__N`````"-9?1;7E_)PY!5B>57 +M5E.#[`R+10B#N"PP```##XPO``"+50@Y@NPO```/A/L```")1>R+ +MBNPO``")3?"-=@"+7?"+`XE%\(M3!(L#B5`$B0*)&XE;!(M#'/9``00/A8@` +M``")W[X`````@'LF`'8FC78`@^P,B?(/ML+!X`2-A#C4!P``4.B0N___@\00 +M1HGQ.$\F=]V+50B!PN0O``"+30B+@>0O``")6`2)`XE3!(F9Y"\``(M#'(-X +M)`!T8(/L!/]P*(M#'/]P)%'H_/___XM#',=`)`````"+10C_B#`P``"#Q!#K +M-HGV@^P(4_]U".B8T___@\00A7\G#58GE4X/L!(M%"(M8"(.[ +M+#````!U#HV#["\``#F#["\``'0S@^P,4^C\____B1PDZ/S___^)'"3H_/__ +M_X/$$(.[+#````!UVXV#["\``#F#["\``'7-N`````"+7?S)PXUV`%6)Y5=6 +M4X/L!(M%"(M`"(E%\(N(["\```7L+P``.<@/A($```"-=@"+50@Y41QU:(G/ +MLP"`>28`=D&)]@^VP\'@!`'XC9#4!P``O@````"#N-0'````=12#>@0`=0Z# +M>@@`=0B#>@P`=`>)]KX!````A?9U&4,X7R9WP;@`````A"8`=D&)\@^VPL'@!`'8C9#4!P``OP````"# +MN-0'````=1*#>@0`=0R#>@@`=0:#>@P`=`6_`0```(7_=1A&B?`X0R9WO[@` +M````A +M7\G#D%6)Y5=64X/L#(M="(M]$(MS"(-[)`!U#5/HGO[__X/$!(7`=0N#[`A7 +M5O]5#.L9D(M%#(E#)(E[*/^&,#```(/L#%;H_/___XUE]%M>7\G#58GE5E.+ +M=0B+70R`>Q$`=03&0Q$!@'L1`709@'L1!G03@'L1`W0-]D,0('4'QD,1"XUV +M`/]S+%;HQ[C__XD<)/]S'%;H_/___XL#@\00@W@8`'08@^P$@\`84&@````` +M5NC\____@\00ZUV0@[XT,````'0KC8;D+P``.8;D+P``=!V#[`2-AC0P``!0 +M:`````!6Z/S___^#Q!#K*XUV`(&^*#```/\```!W'(V&Y"\``#F&Y"\``'4. +M@^P,5NC\____@\00B?:-9?A;7LG#D%6)Y5=64X'LS````(M]$(M%#(M0((L* +MB8TT____#[9!/$B)A4C___]FBTH(9HF-5O___XM"3(F%4/___P^V2DJ)C43_ +M__\/MD)+B85`____9HM*4F:)C53___]FBUI0@WH4`'0-9@^V0A"#X`$[111U +M.+D`````@WH8``^$?P(``(V%6/___XF%./____]U%%!2_W4(_U(8@\00N0`` +M``"%P`^$6`(``.L)BU(4B94X____O@````"+50R+`@^V0`.)A3S___^Y```` +M``^WPP.%4/___XF%3/___XN%//___SF%1/___P^%%P$``(7)=%*+A4S___\I +MR(G#P>,)=$.#?10`=`>A`````.L1@^P,_S4`````Z/S___^#Q!")!V;'1P8` +M`('[`!````^&OP```&;'1P0`$(/'"('K`!```'6]#[>=5/___\'C"8UV`(N- +M./___P^W402%TG4%N@```0")T"GP.=AR,8GPBXTX____`P&)!V:)7P1FQT<& +M``"#QP@!WCG6=4:^`````(/!"(F-./___^LVB?:)\(N-./___P,!B0>)T&8I +M\&:)1P1FQT<&``"#QPB)T"GP*<.#P0B)C3C___^^`````.N`#[>-5/___P.- +M3/___XM5#`^W0@@#0@0YR`^$!@$``.M/9HE?!(/'".E&____C78``=[K/`^W +MG53____!XPF)]HN%./___P^W4`2%TG4%N@```0")T"GP.=AWU8G0*?`IPX.% +M./___PB^`````.O1D(N55/___V8IE5;___\/A*(```"[`````/^%1/___XN% +M0/___SF%1/___W4(_X5$____B?:+E33___\/MD(\.X5$____=4*#O4#___\` +M=`C_C4#____K#(N%2/___XF%0/___X.]0/___P`/E,`/ML")A43___^+E33_ +M__\/MT)(`850____B?:+A33___]FBT!(9HF%5/___V:+E5;___]F.=`/AN/] +M__]FB954____Z=?]__]FQT?^`("Y`0```(G(C67T6UY?R<.)]E6)Y593BW4( +MBU4,BUH@@'H1`70&BD(1B$,1@^P(4E;H_/___XI#24"(0TF#Q!`Z0TAU+8![ +M$0!U!,9#$0&`>Q$!=!"`>Q$&=`J`>Q$#=`3&0Q$+@^P(4U;_4QR#Q!")]HUE +M^%M>R<.058GE5U93@^PLBT4,BP")1>R+50SV0A`$#X3T`0``QT7P`````(!Z +M1``/A'L!``"+3?"+70R+3(LPB4WHBIDL"0``B%WG.)DM"0``#X)&`0``C78` +MBD7GBU7H.$(G#X0?`0``#[;`B<+!X@2+3>B-E`K4!P``B57@#[>4@0P)```/ +MM[2!#@D``+\`````C78`@_H?=U.)^P^VPXM-X(T<@8E5W+D@````*=$Y\78" +MB?&#^2!U"\<#_____^L2C78`N`$```#3X$B*3=S3X`D#N"`````IT#GP)^X#[`W:=#[9%YXG"P>`$BTWHC80(5`@``(E% +MV`^WG)$,"0``#[>TD0X)``"_`````(GV@_L?=U.)^@^VPHM-V(T4@8E=U+D@ +M````*=DY\78"B?&#^2!U"\<"_____^L2C78`N`$```#3X$B*3=33X`D"N"`` +M```IV#GP)^#P#=I[^1>>*5>>+3>@XD2T) +M```/@[W^____1?"+70P/MD-$.T7P#X^%_O__BT4(@[C@+P````^$/@,``,=% +M\`````"+50R`>D0`=#6)PH'"["\``(M-\(M=#(M,BS#'@00)````````BT($ +MB4H$B1&)002)"/]%\`^V0T0[1?!_TX/L"/]U#/]U".BO^?__Z1T#``"+70SV +M0Q`"#X39`@``BT4(!3@P``")1="+?0B!QU@P``"+5>SV0DH##X6X`@``@^P$ +M:A!J`%?H_/___\=%\`````"#Q!"`>T0`#X3_````BTWPBUT,BTR+,(E-Z(G. +ML0"`?B8`=D8/ML'!X`0!\(V0U`<``+L`````@[C4!P```'42@WH$`'4,@WH( +M`'4&@WH,`'0%NP$```"%VW0)N`$```#K#8GV03A.)G>ZN`````"%P`^%+0(` +M`(M%Z(J`+`D``(A%YXM5Z#B"+0D``')KBDWGBUWH.$LG=$\/MM%F@SQ7`'4? +M#[>$DPP)```#0R"+3=")!)%FBX23#@D``&:)!%?K)@^V5>>+7>AFBX23#`D` +M`&8#0R!F`X23#@D``(M-T&8K!)%FB017_D7GBEWGBT7H.)@M"0``B#??``=4J)PHM`((M=#(E# +M3(J"+`D``(A#2HI")XA#2P^V@BP)``!FBX2"#`D``&:)0U`/MH(L"0``9HN$ +M@@X)``!FB4-2QD-(`,9#20#K0XM%Z(M0((M=##M33'8UBUWL#[=#2/?8(<*+ +M70PC0TPYPG4@BT7H#[:0+`D``&:+0U*+7>AF`X23#@D``(M5#&:)0E*+002+ +M7>B)602)"XE#!(D8_T7PBU4,#[9"1#M%\`^//?___XM-"(.Y-#````!T&8/L +M!(G(!30P``!0:`````!1Z/S___^#Q!#&1><`BUWL@'L\``^&J`````^V=>=F +M@SQW`'14BT7LBURP5(/L#/]U".C\____BU4,_D)(QD`*(&:+%'=FB5`(BTW0 +MBQ2QB5`$@$@0`L=`&.1F``#'0!SP:0``B1B+50R)4""#Q`A0_W4(_U,T@\00 +M_D7GBDWGBUWL.$L\=Y/K.8GVQT7P`````(M%#(!X1`!T)X/L"(M5\(M-#/]T +MD3#_=0CH`\C__X/$$/]%\(M=#`^V0T0[1?!_V8UE]%M>7\G#D%6)Y5=64X/L +M/(M%#(L`B47PQT7D`````&:+4$AFB57J9H'Z@`!V!F;'1>J``(M-#/9!$"!T +M2`^W1>I0BUT0_W,(_W7P_W4(Z(RR__^)1>2#Q!"X_____X-]Y``/A#,#``"+ +M10S&0$0!BU7DB5`PB8($"0``N`````#I%@,``(M-$`^V41*+`8G3N@````#W +M\XA5XXM%\`^V4#R+002)T;H`````]_&+71"*0Q(HT(A%XCA%XX!=X_^+1?!F +MBU!(C4+_9HM+#"'!B==F*<]F.7L0QFBUWJ9BG#9CG[=@*)^XMUU"-U[(-]W``/A%X!``#' +M1=P`````9HM5ZHM%\&8Y4$AV+KH`````BTT,#[9!1(G!@_@`?AN-=@"+10R+ +M1)`PB47D.7`@#X0A`0``0CG1?^C_==A6_W7P_W4(Z$6Q__^)1>2#Q!"%P`^% +MRP```(M5#/Y*1(!Z1/\/A*\```"+3` +M!`D```````")QK$`@'@F`'8_#[;!P>`$`?"-D-0'``"[`````(.XU`<```!U +M%(-Z!`!U#H-Z"`!U"(-Z#`!T!XGVNP$```"%VW4D03A.)G?!N`````"%P'0< +MBU70BT($BTWDB4H$B1&)002)".L7N`$```#KX(M'!(M=Y(E?!(D[B4,$B1B+ +M10S^2$2`>$3_#X5:____N/_____I*@$``(GVBU4,BE)$B%7##[;*BU7DBT4, +MB52(,(I%PT"+30R(042)B@0)``#&@BP)```(QH(M"0````^V5>.+1>QF*?"+ +M3>1FB821#`D``&:)G)$."0``BD7C.($L"0``=@:(@2P)``"*5>.+3>0XD2T) +M``!S!HB1+0D``(M%$&8I6!!F*=]T$@^WPP%%[,=%W`$```#I'/[__XM5$&:# +M>A``#X2!````N0````#^1>.*7>(X7>-U`_Y%XXI%XXM5\#A"/'4R@'WB`'0% +M_DWBZPF+71"*6Q*(7>*`?>(`#Y1%XXM5\`^W0DB+71`!0PC'1=P!````ZQ1F +MBU7JBT7P9CE02'8'QT7<`0```(M=$&:+>Q"+1?!F.WA(#X9O_?__9HMX2.EF +M_?__N`````"-9?1;7E_)PU6)Y8/L"(M5"(M%#(-]$`!T&L9`$0N#[`10:!1F +M``!2Z/S___^#Q!#K#XGV@^P(4%+H]O;__X/$$,G#D%6)Y5=64X/L3(MU#(L^ +M]D*C_ +M_XE'+,<$)``0``!J`%#H_/___X/$$(UV`(I&$*@@#X6U````J`9U&<9&$0&# +M[`16_W8<_W4(Z/S____IP0$``)#V1A`$="J#?R0`="2#[`3_=RC_=R3_=0CH +M_/___\=')`````"+10C_B#`P``"#Q!"+5@2)5=1FBT8(9HE%V(I'/$B(1=H/ +MMD\^B=#3Z(E%R`^V7=JZ`````/?SB47,#[9//M/@B470#[='2`^OPXE%M`^W +M3=@#3@0/KUW0*=F-3`'_B53@^P$BUT,@WLL`'1.@^P, +M4^C\____N@````"#Q!"-=@"+0RR+!)"%P'00B?;'0!``````BT`4A`,NJNJJJKWXHG3P>L/4V@P +M"0``5^CDI?__B<:#Q`R#PR!3:A!7Z-.E__\!QH/$#*$`````P>`,P>@.4&I$ +M5^BZI?__`<:#Q`QJ"&@`$```5^BHI?__`<:)/"3H_/___Z,`````@\001CLU +M`````',QD(/L#%?H_/___XG"@\00A7\G#58GE5U93@^P,BWT(BW4,BUX$#[9.`[@!```` +MB<+3XH!F`?O'0U``````]D-*`G0,9H-[3`!T$NL*C78`9H-[3`!T+6:%4TQU +M)V8)4TR`8P'[@WLX`'0-@^P(4U?_4SB#Q!")]H!C2A_ILP```(UV`(I#2F:) +M4TS^2SW'0U``````@\@%B$-*A,!Y#8/@?XA#2NF*````B?:`8TJ?@^P(4U?H +M_/___XG"@\00AP0`=`R-=@"+6P2#>P0`=??H_/___XE#0(/L#%/H_/___XGVC67T6UY?R<-5 +MB>53BTT(NP````"+50Q*@_K_=`^-=@`/M@$!PT%*@_K_=?0/ML-;R<.)]E6) +MY593BW4(@#X#=D:[`````(!^/`!T-8-\GE0`="6+3)Y4BE8!@^(!BD$!@^#^ +M"="(00&#[`S_=)Y4Z/S___^#Q!"00P^V1CPYV'_+@&9*^^L)@^P,5N@(```` +MC67X6U[)PY!5B>575E.![!P"``#'A>3]__\`````C;7H_?__BT4(@'@\``^$ +M.@(``(MX!(7_=`^#?P0`=`F)O>3]__^+?P2#[`1H``(``&H`5NC\____QP;S +M%GA:@\00N`````"%_W0#BT=`B48$BU4(@'I$`'0*@$X)`HI"1XA&"HM%"(I0 +M0(C3@^,!BH:3````@^#\B-�()V`G(B-.#XP2#X/.(T8/A"`G8"3]__\!&<"#P`*(1@N%_P^$N@```(M'#(E&#,>&E``````` +M``"*!XA&$(I'/(A&$8.]Y/W__P!T"XN5Y/W__XI"`^L)BU4(BD(#C78`B$82 +MBD<^B$83]D=*`G0$@$X4`6:+1TQFB486BT=0B488QX:8`````````(/L!&H0 +MC4=T4(U&+%#H_/___X/$#&H$C8>$````4(U&/%#H_/___X/$#&H0C8?(```` +M4(V&@````%#H_/___X/$#&I`C8>(````4(U&0%#H_/___X/$$(.]Y/W__P!T +M7HN5Y/W__XM"#(E&',>&G`````````"*`HA&((I"/(A&(8M5"(I"`XA&(HN5 +MY/W__XI"/HA&(_9"2@)T!(!.)`&+E>3]__]FBT),9HE&)HM"4(E&*,>&H``` +M``````"%_W4+BU4(B@*(1A"-=@!HD````%;H_/____?8B$8(:``"``!6Z/S_ +M___WV(B&D````%9J,(M5"(M"3(/H"E")T(/`/%#H_/___XUE]%M>7\G#D%6) +MY8M-"(G(@#D#=B^X`````(!Y/`!T$`^V43R#?(%4`'4,0#G"?_2X`````.L- +M@^P,_W2!5.C\____D,G#B?95B>564XMU"(`^`W8ONP````"`?CP`="B#?)Y4 +M`'01@^P,_W2>5.C\____@\00B?9##[9&/#G8?]_K!9"`9@'^C67X6U[)PY!5 +MB>6+30B+40BX`````(GV.0R"=0O'!((`````ZPB)]D"#^`=VZLG#58GEBT4, +M@&`!^U#H_/___\G#B?95B>575E.![!P$``"+?0B-M>C]__^)^XI'`:@$#X09 +M`0``@#\"#X80`0``@^#]B$%Y/O__P$````/MD<\@_@!?EI3 +M:B!J`(N5Y/O__XM$EU2#P#Q0Z/S___^Z`````(/$$(L$EC,$DXD$ED*#^G]^ +M\?^%Y/O__P^V1SP[A>3[__]_O^L7D(`[`W6/5FH@:@"-0SQ0Z/S___^#Q!!F +M@;[^`0``5:IU7H.^R@$```!T&X%^!DQ)3$]T#(&^=@$``$=254)U!H!/`0+K +M.L>%Y/O__P````"+A>3[___!X`0!\("XO@$``(!U#8.XR@$```!T!(!/`0+_ +MA>3[__^#O>3[__\#?M"-9?1;7E_)PY!5B>564XM-"(N92!$``(U#`;XA`@`` +MF??^B=:+10R)1-D\BY%($0``BT40B4310(FQ2!$``%M>R<.-=@!5B>575E.# +M[`R+=0B+AD01```[AD@1``!T-K\A`@``D(N&1!$``(M,QCR+7,9`0)GW_XF6 +M1!$``(/L"%-6_]&#Q!"+AD01```[AD@1``!UT(UE]%M>7\G#58GE5E.+30B+ +MF5@B``"-0P&^(0(``)GW_HG6BT4,B8393!$``(N16"(``(M%$(F$T5`1``") +ML5@B``!;7LG#D%6)Y5=64X/L#(M="(N#5"(``#N#6"(``'16B?:+@U0B``"+ +MM,-,$0``B[S#4!$``$"Z(0(``(G1F??YB9-4(@``@[LL,````'0.@^P,4^C\ +M____@\00B?:#[`A74__6@\00BX-4(@``.X-8(@``=:R-9?1;7E_)PU6)Y5.# +M[`2+50BX`````(-Z.`!T%XM:.(L#B4(X@^P$:E1J`%/H_/___XG8BUW\R<.- +M=@!5B>6+30B+50R+03B)`HE1.,G#D%6)Y8M-"(M5#(,Y`'02BP&+0"2)0B2+ +M`8E0).L&C78`B5(DB1')PY!5B>575E.#[`R+=0R#/@!T-8L^D(L&BU@D.=AU +M"\<&`````.L+C78`BQ:+0R2)0B2#[`A3_W4(_U,H@\00.?MT!8,^`'7.C67T +M6UY?R<.)]E6)Y8/L"(M%"(`X"'4.@^P,4.C\____@\00B?;)PXGV58GE4X/L +M!(M%"(M=#(M-$(M0"(`X"'40@^P$45-0Z/S____K"HUV`(/L"%%2_].+7?S) +MPU6)Y5=64X/L%(M%"(I5$(A5\XMX*(H`B$7R#[;84U?H_/___X/$#&H`4U?H +M_/___X/$#&H`:@!J`&H`:@-35^C\____@\0@N@````"%P`^$F````/=%#``` +M`/`/E<`/MLB#[`R%R704N"0```"`??,@=`VX-````.L&B?8/MD7S4+A````` +MA564X/L'(MU"(I%#(A%]V@@H0<` +MZ/S___^[(*$'`(/$$)"#[`@/MD7W4.BC____!1P!``")!"3_=@SH_/___X/$ +M$(3`>`BX`0```.LDD(/L#&@0)P``Z/S___^#Q!"!PQ`G``"!^S]+3`!VMK@` +M````C67X6U[)PXGV58GE5E.+70B#[`1J``^V10Q0Z$'___^)QHU`"(D$)/]S +M#.C\____@\0,:!@!``"-1@Q0_W,,Z/S___^#Q!"-9?A;7LG#C78`58GE@^P, +M:@`/MD4,4.C^_O__@\`,B00DBT4(_W`,Z/S____)PXUV`%6)Y8M%#&:#?10` +M=1/W11````#P=0JI`/\``'0+C78`N`$```#K&9!FA`)P6:)2PB+10R#N#@"````=`^#N#@"```"#X5&`0`` +MB?:#?@0!#X7&````9@^V1@^`S!%FB0*#P@)F#[9&#H#,$6:)`H/"`@^V1P3! +MX`,E^````(#,$F:)`H/"`F8/MD8+@,P39HD"@\("9@^V1@B`S!-FB0*#P@)F +M#[9&#(#,%&:)`H/"`F8/MD8)@,P49HD"@\("9@^V1@V`S!5FB0*#P@)F#[9& +M"H#,%6:)`H/"`F;'`D`6@\("@SX`=1FP8(M-#(.Y.`(```(/A((!``"P)NE[ +M`0``L&&+30R#N3@"```"#X1I`0``L#;I8@$``(GV9@^V1@Z`S!%FB0*#P@(/ +MMD<$P>`#)?@```"`S!)FB0*#P@)F#[9&"(#,$V:)`H/"`F8/MD8)@,P49HD" +M@\("9@^V1@J`S!5FB0*#P@*+1@@E````#\'H&`U`%@``9HD"@\("@SX!&<"# +MX/N#Z#3I[0```)"#?@0!#X6&````9@^V1@^`S!)FB0*#P@)F#[9&#H#,$F:) +M`H/"`F8/MD8+@,P39HD"@\("9@^V1@B`S!-FB0*#P@)F#[9&#(#,%&:)`H/" +M`F8/MD8)@,P49HD"@\("9@^V1@V`S!5FB0*#P@)F#[9&"H#,%6:)`H/"`F;' +M`D`6@\("@SX!&<"#X/"#P#7K79!F#[9&#H#,$F:)`H/"`F8/MD8(@,P39HD" +M@\("9@^V1@F`S!1FB0*#P@)F#[9&"H#,%6:)`H/"`HM&""4````/P>@8#4`6 +M``!FB0*#P@*#/@$9P(/@_H/H-HUV`&8/ML`-`)?__V:)`EM>7\G#C78`58GE +M5U93@^PDBU4(BUT4BW(,#[9%#(M$@B2+>#"-AP0!``!05NC\____B`.#Q`B- +MAP@!``")1?!05NC\____9@^VP&:)0P*#Q`B-APP!``")1>Q05NC\____9@^V +MP&:)0P2#Q`B-AQ`!``")1>A05NC\____9@^VP&:)0P:#Q`B-AQ0!``")1>10 +M5NC\____9@^VP&:)0PB#Q!"#?1`!#X6+````@^P(C8<@`0``B47<4%;H_/__ +M_XA%XX/$#(/(@`^VP%#_==Q6Z/S___^#Q`C_=?!6Z/S____!X`AF"4,"@\0( +M_W7L5NC\____P>`(9@E#!(/$"/]UZ%;H_/___\'@"&8)0P:#Q`C_=>16Z/S_ +M___!X`AF"4,(@\0,#[9%XU#_==Q6Z/S___^#Q!")]H/L"(V'&`$``%!6Z/S_ +M__^(0PJ#Q`B-AQP!``!05NC\____B$,+C67T6UY?R<.)]E6)Y5=64X/L-(M% +M$&:)1=8/ME4,B570BT4(BWR0)(M',(/`,%"+50C_<@SH_/___X/@'XT4Q0`` +M```IPHVTUT0"``"#Q!"#/@%T08U>%(U%V%#_575E.#[#R+51"*10R(1<_'1<@`````#[;`BTT(BW2!)&;'1<8``&:+ +M`F:)1="-3=!FBT("9HE!`HM"!(E!!&:+1=")PX/C'XT$W0`````IV(V&-`(```````"->Q2-1=!FBT`"J`1T&HU%V%#_=P0/MD7/4/]U".A:_?__ +M@\00C78`@SL!#X23````_HY1"0``@^P$C4784(U%T(M`!%`/MT7&4/]W'/]U +MR`^V1<^)1564XM="(/L +M"&@L#0``_W,,Z/S___^)QH/$#(/(`5!H+`T``/]S#.C\____@\0(:"P-``#_ +MW`D``(/L!(M%%,'@`PM& +M)%"+1C"#P"10_W7LZ/S___^#Q!`[711T(P^V??.#[`2+1A2-!-A05_]U".B) +M_?__0X/C'X/$$#M=%'7A@[Y,"0```'4'QT7H`0```(F>W`D``(-]'`!U"H-] +MZ``/A`,"``"#[`@/MD7S4.AF]___@\`(B47DB00D_W7LZ/S___^)QX/$#`^W +MV(G8]]!0_W7D_W7LZ/S___^#Q!#VPP@/A!@!``"%]G04QX9,"0```````,>& +M-`(```````"+30B#>60!=`:#>6@!=1J#[`2X``$``(I-\]/@4%#_=0CH,_[_ +M_X/$$(M%"(-X8`%T#(-X9`%T!H-X:`%U%8/L"`^V1?-0_W4(Z#,)``"#Q!#K +M>HM5"(-Z7`%T!H-Z8`%U:X/L!&H$#[9=\U/HJ/;__XUP*(DT)/]U[.C\____ +M@\0(5O]U[.C\____QP0D&0```.C\____@\0,:@!6_W7LZ/S___^#Q`A6_W7L +MZ/S____'!"30!P``Z/S___^#Q`A3_W4(Z(`'``"#Q!"0@^P(#[9=\U/H/_;_ +M_P4<`0``B00D_W7LZ/S___^#Q!!3:@!J`?]U"(M-"/]1(.FI````]\<0```` +M=%&#[`@/MD7S4/]U".@Q!P``@\00BT4(@WAD`70&@WAH`74;@^P$:@"X``$` +M`(I-\]/@4/]U".@7_?__@\00#[9%\U!J`6H!_W4(BU4(_U(@ZU`/M\?VQ`%T +M2(.^-`(```%U*,>&3`D```````#'AC0"````````@^P$4`^V1?-0_W4(Z-KZ +M__^#Q!"#/0`````!=0Z#[`Q6Z'4/``"#Q!")]HUE]%M>7\G#58GE4X/L!(M= +M"`^V10S!X`(+11`/MM"+3),DAA`!=!&#[`@/ML!04^AP#0``ZPZ) +M]H/L"%)1Z`H```")]HM=_,G#C78`58GE5U93@^PDBU4(BT(HBW`,BUHPB@J# +MX0.)SP^V`H/@!,'H`HA%V(V#(`$``%!6Z/S___^#Q`B!PQP!``!35NC\____ +MB,.#Q`RX``$``(GYT^#WT%"`?=@!&<`E``#__P44``,`4%;H_/___X/$$(3; +M#X@0`0``]L,!=!>#[`1J`?]U#/]U".C'`0``Z?8```")]HM5#(M"%(/X`70M +M@_@!"``=1.#[`1J`%#_=0CH``$` +M`(/$$.LO@^P(BT4,@\`44/]U".@E````@\00A575E.#[!R+=0B_ +M`````(M=#(/#%(U%V%#_#-`(` +M``````#'@]0)```@````N@````")E)-4"0``0H/Z'W[SN@````")]HT$U0`` +M```IT,>$PT0"```!````0H/Z'W[FQX-$"0```````,>#2`D```````#'@TP) +M````````@^P$:@"+1?"#P`A05^C\____@\0,:!@!``"+1?"#P`Q05^C\____ +M@\0,_W,8BT7P@\`04%?H_/___X/$#(M#'"4`_/__4(M%\(/`%%!7Z/S___^# +MQ`QJ`(M%\(/`&%!7Z/S___^#Q`S_575E.#["R+=0B+111FB476@WT,``^%F@```+L`````B?:-!-T````` +M*=B-!,:#N$0"````=72#N%0"```!=1J+D%P"``"+N'@"``"+@'0"``")1=#K +M)(UV`(T$W0`````IV(T$QHN07`(``(NX=`(``(N`<`(``(E%T(U%V%!2#[8& +M4/]V*.CR\O__@\0,C4784&H`#[=%UE!7_W40#[8&4/]V*/]5T(/$($.#^Q\/ +MCFW___^-9?1;7E_)PY!5B>575E.#[!R+70@/MG4,B?"#X`3!Z`*(1=B_`P`` +M`"'W@WM<`70&@WM@`75K@^P(B?H/ML*)PL'B"(V"#`$``(!]V`!T"8V"#`$# +M`.L&D`4```(`4/]S#.C\____B<&#X?R#R0&#Q`Q1B?H/ML*)PL'B"(V"#`$` +M`(!]V`!T"(V"#`$#`.L%!0```@!0_W,,Z/S___^#Q!"#[`B)^@^VPHG"P>(( +MC8)T`0``@'W8`'0*C8)T`0,`ZP>)]@4```(`4/]S#.C\____B<&`X1^)\@^V +MP@^V5!AZP>(%@>+@````"=&`Y>575E.#[`R+70@/MG4,5NB"[?__@^P$C7@H5E/H9>[_ +M_X/$#&H$5_]S#.C\____@\0(5_]S#.C\____QP0D&0```.C\____@\0,:@!7 +M_W,,Z/S___^#Q`A7_W,,Z/S___^#Q`A64^A;_O__@\0(5E/HR>W__XUE]%M> +M7\G#D%6)Y5=64X/L#,9%\@#&1?,`C78`BD7RBE7SC1R"#[;;4^CR[/__B<=J +M`HUP*%:+10C_<`SH_/___X/$"%:+50C_<@SH_/___X/$"%/_=0CH+/___X/$ +M#&H`5HM%"/]P#.C\____@\0,:!\!``!7BU4(_W(,Z/S___^#Q`QJ`(U'!%"+ +M10C_<`SH_/___X/$#&H`C4<(4(M5"/]R#.C\____@\0,:@"-1PQ0BT4(_W`, +MZ/S___^#Q`QJ`(U'$%"+50C_<@SH_/___X/$#&H`C4<44(M%"/]P#.C\____ +M@\0,:@"-1QA0BU4(_W(,Z/S___^#Q`QJ`(U''%"+10C_<`SH_/___X/$#&H` +MC46+50B+30S'00@`````BX)("0``B4$,@[I( +M"0```'0)BX)("0``B4@(B8I("0``@[I$"0```'4&B8I$"0``R<.)]E6)Y5.+ +M70B+30R#>0@`=1B+00R)@T@)``"%P'04QT`(`````.L+B?:+40B+00R)0@R# +M>0P`=1F+00B)@T0)``"%P'05QT`,`````.L,C78`BU$,BT$(B4((QT$(```` +M`,=!#`````!;R<.)]E6)Y5=64X/L#(M]"(MU#(M=$(,[`'49@^P$:B"-0P10 +MC4844.C\____@\00ZQV)]H/L!&HDC4,$4(U&%%#H_/____Z'4`D``(/$$(L# +MB4805E?H^?[__\<&`````/Z'/`(``(UE]%M>7\G#D%6)Y593BUT(BW4,@WX0 +M`'0&_HM0"0``5E/H"O___XN#U`D```^V5@2)E(-4"0``0(F#U`D``,<&`0`` +M`/Z+/`(``(UE^%M>R<.-=@!5B>6*10@\`W82#[;(C4P)`K@!````T^#K$(GV +M#[;(C4P)`;@!````T^#)PU6)Y593BW4(#[9=#%/HPO___X/L!`E&5%/H`NC_ +M_P4<`0``B00D_W8,Z/S___^#Q`R)V8/A`[@``0``T^#WT%"#XP3!^P*#^P$9 +MP"4``/__!10``P!0_W8,Z/S___^#Q`S_=E1H9!T``/]V#.C\____@\0(:&0= +M``#_=@SH_/___XUE^%M>R<-5B>53@^P$BUT(#[9%#%#H./____?0(T-4B4-4 +M4&AD'0``_W,,Z/S___^+7?S)PY!5B>575E.#[!"*70R+10B+0`R)1?`/MM.+ +M10B+=)`DBWXPQX8T`@```0```(/B!,'J`HG9@^$#N`$!``#3X/?04(#Z`1G` +M)0``__\%%``#`%#_=?#H_/___X/$#&H`BT8P@\`(4/]U\.C\____@\0(#[;; +M4_]U".A4____@\0(C8<<`0``4/]U\.C\____QX9``@```0```(/$#&H!@\575E.#[!"+10B+>`P/MG4,BT2P)(M8 +M,,>`-`(```````!J`H/#*%-7Z/S___^#Q`A35^C\____@\0(5O]U".A._O__ +MC67T6UY?R<.)]E6)Y593BUT(BT,HBW`,_W40_W4,4XN#V`D``,'@!0-#$%#H +MF>?__XN3V`D``$*#XA^)D]@)``#^@U$)``"#Q`R+0QPE`/S__\'B!0G04(M# +M,(/`%%!6Z/S___^-9?A;7LG#B?95B>53@^P$BUT(:@!J`FH`4^A:]O__B1PD +MZ)[T__^)'"3H_/___X/$$(/X`74>QX-,"0```0```(/L"`^V`U#_575E.#[!2+50B+?0R#QQ2+0BB+<`R+6C"-@QP! +M``!05NC\____)<$```"#Q!"Z`````(/X0`^%T@$``(-_!`%U<(/L!`^V1Q%0 +MC8,$`0``4%;H_/___X/$#`^V1Q-0C8,(`0``4%;H_/___X/$#`^V1Q50C8,, +M`0``4%;H_/___X/$#`^V1Q=0C8,0`0``4%;H_/___X/$#`^V1QE0C8,4`0`` +M4%;H_/___X/$$.LTB?9F]T<0`/]U(&;W1Q(`_W489O='%`#_=1!F]T<6`/]U +M"&;W1Q@`_W0*N@````#I*@$``(/L!`^V1Q!0C8,$`0``4%;H_/___X/$#`^V +M1Q)0C8,(`0``4%;H_/___X/$#`^V1Q10C8,,`0``4%;H_/___X/$#`^V1Q90 +MC8,0`0``4%;H_/___X/$#`^V1QA0C8,4`0``4%;H_/___X/$#`^V1QI0C8,8 +M`0``4%;H_/___X/$#`^V1QM0C8,<`0``4%;H_/___X/$$(,_`@^%A````(/L +M"(V#(`$``%!6Z/S___]J9&H*4U;H_/___X/$(+H`````A7\G#B?95B>575E.#[!"+=0C'1E0`````:@!H9!T``/]V#.C\ +M____QT9<`````,=&8`````#'1F0`````QT9H`````,=&;`````#'1G`````` +MQT9T`````,9&>`&#Q!"X`````(-^(``/A',"``"X`````&:!?@:!4`^%8@(` +M``^V5@6#^@$/A%4"``"#^@%_!H72=`GK&8/Z`G0+ZQ+'1F`!````ZQ#'1F0! +M````ZP?'1F@!````LP"#[`@/MM.)T(/@`\'@"(V(=`$``/;"!'0'!70!`P#K +M!HV!```"`%#_=@SH_/___P^VRXG"@>+@````P>H%B%0Q>B4`&```P>@+B(0Q +M@@```(/$$$.`^P=VIX/L#%;H8O7__XDT).AJ]___B30DZ(+W__^#Q`QJ`&CP +M!`$`_W8,Z/S___^#Q`AH+`T``/]V#.C\____B<>#Y_Z#Q`Q7:"P-``#_=@SH +M_/___X/$"&@`#0``_W8,Z/S___^#Q!"H,'0YBT9$J>`#`(!T""4?_/]_B49$ +M@WY<`702@WY@`70,@WYD`70&@WYH`743BT9$J!!T#(/@[XE&1.L$@V9$S[,` +M@^P(#[;#4%;H__+__X/$$$.`^P=VZH/L!/]V1&@`#```_W8,Z/S___^#Q`S_ +M=DAH*`P``/]V#.C\____@\0,_W9,:%P=``#_=@SH_/___[,`@\00@^P$#[;# +M_W2&$(#[`1G`)0``__\%#``#`%#_=@SH_/___X/$#`^VP_]TAAB`^P$9P"4` +M`/__!1```P!0_W8,Z/S___^#Q!!#@/L!=K/'1E15JP8`LP")]H/L"`^VPU!6 +MZ,OA__^#Q!!#@/L'=NJ#[`QH4,,``.C\____@\00@WYD`70&@WYH`75$OP`` +M``"S`(UV`(/L"`^VPXE%\%!6Z/S___^#Q!"%P'4+9K@``8I-\-/@"<=#@/L' +M=MB#[`17:`#_``!6Z/WG__^#Q!"X`0```)"-9?1;7E_)PU6)Y8/L#&H`:&0= +M``"+10C_<`SH_/___[@!````R<.058GEQP4``````0```,G#D%6)Y<<%```` +M``````#)PY!5B>564XMU"(I5#`^VPHM[__XUE^%M>R<.)]E6) +MY0^V50R+10B+5)`DN`````"%TG0-@[I,"0```0^5P`^VP,G#B?95B>564XMU +M"(I%#(G"@^(#B='!X0B-D0`!``"H!'0)C9D``0,`ZP>0C9H```(`@^P(4_]V +M#.C\____@^`/@\00@_@!=`^#^`%R0H/X`W0UZSN-=@"#[`A3_W8,Z/S____' +M!"1`#0,`Z/S___^#Q`A3_W8,Z/S___^#X`^#Q!"#^`-U"9"X`0```.L&D+@` +M````C67X6U[)PU6)Y5=64X/L+(M]"(I%#(A%\X/@`XA%YP^V5?.)T(/@!(G& +MP>X"BU27)(M/#(E-[+@`````A=(/A!\"``"+0C")1>BX`````(.Z3`D```$/ +MA`<"``"#[`@/ME7SB57<4E?HYM___X/$#&H$BUWH@\,H4_]U[.C\____@\0( +M4_]U[.C\____QP0D&0```.C\____@\0,:@!3_W7LZ/S___^#Q`A3_W7LZ/S_ +M__^#Q`C_==Q7Z-3O___'1>``````@\00#[9%YXG!P>$(B4W4@<$(`0``B4W8 +MP>`(B470@^P(BU74C8((`0,`B?&$R74)BU78C8(```(`4/]W#.C\____B<.# +MX_"#RP&#Q`Q3BT70C9`(`0``C8`(`0,`B?&$R74&C8(```(`4/]W#.C\____ +M@\0(#[9%YXG"P>((C8((`0``B?&$R70+C8((`0,`ZPB-=@`%```"`%#_=PSH +M_/___\<$)!D```#H_/___X/C\(/$#%,/MD7GB<+!X@B-@@@!``")\83)=`J- +M@@@!`P#K!XGV!0```@!0_W<,Z/S___^#Q`@/MD7GB<+!X@B-@@@!``")\83) +M=`J-@@@!`P#K!XGV!0```@!0_W<,Z/S____'!"30!P``Z/S___^#Q`@/MEWS +M4U?H_/___X/$$(7`=1[_1>"#?>`##X7=_O__@^P(4U?H^MW__[@`````ZTN# +M[`B+1>@%'`$``%#_=>SH_/___R7`````@\00@_A`=!6#[`@/MD7S4%?HQ-W_ +M_[@`````ZQ6#[`@/MD7S4%?HK]W__[@!````B?:-9?1;7E_)PU6)Y5=64X/L +M#(M5"`^V=10/MD4,BUR")+D`````A=L/A(L```"+4@R)5?"+>S"Y`````(.[ +M3`D```%T=(/L"%?_=?#H_/___XG"@\00@WT0`'4IC4;_N0`````\'W=1QX,X +M`@```````(/BP(GQ#[;!2`G"@,X"ZQ.-=@#'@S@"```!````@>+`_?__@WL, +M`74&@,X!ZP20@.;^@^P$4E?_=?#H_/___[D!````C78`B" +M3`D```$```"#[`@/ML%04^B2]/__N`$```"+7?S)PU6)Y5.#[`2+70B*50P/ +MML*Y`````(-\@R0`="`/MM*+1),DQX!,"0```````(/L"%)3Z`7U__^Y`0`` +M`(G(BUW\R<.058GE4X/L!`^V50R+10B+7)`DN`````"%VW0HN`````"#NTP) +M```!=!IJ`&H"_W404^CFZ___B1PDZ"KJ__^X`0```(M=_,G#58GE#[95#(M% +M"(M4D"2X_P```(72=`564XM5"(MR#`^V10R+1((DN@`` +M``"%P'18BU@P@^P(C4,L4%;H_/___X/$$(-]$`%U'[H`````J`)U-H/L!&H" +MC4,L4%;H_/___X/$$.L=B?:Z`````*@"=!>#[`1J`(U#+%!6Z/S___^#Q!"Z +M`0```(G0C67X6U[)PXUV`%6)Y5=64X/L#(I=#`^V=1`/MGT4B-J#X@.)V(/@ +M!,'H`O?&^````'4(]\?\````=`NX`````.F)````D`^VTHG1P>$(C9%T`0`` +MA,!T#H'!=`$#`(E-\.L,C78`@<(```(`B57P@^P(_W7PBT4(_W`,Z/S___\D +M'XGRP>(%@>+@````"="`Y.>)^L'B"X'B`!@```G0@\0,4/]U\(M5"/]R#.C\ +M____#[;#B?F+50B(C!""````B?&(3!!Z@\00N`$```"-9?1;7E_)PU6)Y5=6 +M4X/L%(MU"(I=#+\#````(=^#XP3!ZP*`^P$9P"4``/__!1@``P!0_W8,Z/S_ +M__^)^0^VT8U*&+H!````T^()T(/$#%"`^P$9P"4``/__!1@``P!0_W8,Z/S_ +M__^#Q`B`^P$9P"4``/__!1@``P!0_W8,Z/S___^#Q!"X`0```(UE]%M>7\G# +M58GE5U93@^P4BW4(#[9]#(GX@^`#B$7SB?@/MM")T(/@!(G#P>L"4E;H;NK_ +M_X/$"(#[`1G`)0``__\%&``#`%#_=@SH_/___P^V3?.#P1BZ_O___]/"(="# +MQ`Q0@/L!&<`E``#__P48``,`4/]V#.C\____@\0(@/L!&<`E``#__P48``,` +M4/]V#.C\____@\0(#[9%\XG"P>((C8((`0``A-MT"HV""`$#`.L'B?8%```" +M`%#_=@SH_/___X/@\(/(`8/$#%`/MD7SB<+!X@B-@@@!``"$VW0)C8((`0,` +MZP:0!0```@!0_W8,Z/S___^#Q`B)^@^VPE!6Z)OI__^#Q!"X`0```(UE]%M> +M7\G#C78`58GE5U93@^P4BWT(BW40BD4,B$7SBT<,B47L#[9%\XM$(C9%T`0``J`1T"(V!=`$#`.L&C8(```(`4/]W#.C\____B498@\00 +MA=MU$,<&`````+@!````Z?\```"+0S")1>B#[`@/MD7S4%?H_/___XD&@\00 +MN`$```"#/@`/A-@```"+@TP)``")1BR+@S@"``")1C"*@SP"``"(1C2Z```` +M`)"*1!-JB$06!$*#^B=V\H/L"/]UZ/]U[.C\____B48X@\0(BT7H@\`04/]U +M[.C\____B48\@\0(BT7H@\`44/]U[.C\____B49`@\0(BT7H@\`84/]U[.C\ +M____B49$@\0(BT7H@\`<4/]U[.C\____B49(@\0(BT7H@\`@4/]U[.C\____ +MB49,@\0(BT7H@\`D4/]U[.C\____B490@\0(BT7H@\`H4/]U[.C\____B494 +MN`$```"-9?1;7E_)PY!5B>6#[#S'1<@`````BT40B47,BT44B474BT489HE% +MV(M%'&:)1=J+12")1=R+122)1>"+12B)1>2+12R)1>B-1575E.#[`R*10R(1?,/ML"+50B+=((DN`0```"%]@^$BP$` +M`+@!````@[Y,"0````^$>0$``+@"````@+X\`@``'P^$9P$``(N&U`D``$B) +MAM0)``"+O(94"0``C03]`````"GXC83&1`(``(E%[(GZB%`$BT40@S@`#X7. +M````B<.#PP2#OC@"```"=0S'0P0!````ZT>-=@`/MT,,#[=3#E#_Q6Z&WL__^#Q`R+11"#P`10_W7L5NCZ +M[O__@\00ZW&0@^P$_W40_W7L5NA%[/__@\00ZUR#[`3_=1#_=>Q6Z#'L__^# +MQ!"`OCP"```!=4&#OC0"```!=1.#[`@/MD7S4/]U".A<[O__@\00@^P(_W7L +M5NA5[___@\00AS__[@!````ZP>)]K@`````C67T6UY?R<.- +M=@!5B>575E.#["2+10B+0`R)1>1H8!T``%#H_/___XG&BU4(BU)4B57P@\00 +MN`````"%U@^$9P$``/?&```$`'0X@^P(:%@=``#_=>3H_/___XG#@\0,]]!0 +M:%@=``#_=>3H_/___VH`4VH`_W4(BU4(_U(@@\0@B?;&1>L`]\;_`0``#X0` +M`0``@'WK`1G;@>,``/__@<,4``,`@^P$:N]3_W7DZ/S___^#Q`A3_W7DZ/S_ +M__^)QX/$#/?0@\@04%/_=>3H_/___X/$"(!]ZP$9P"4``/__!0@``P!0_W7D +MZ/S___^)1>"S`(/$$`^V1>N)1=B0#[;+N``!``#3X"'XB47LN`$```#3X(GR +M@^(!(?AU!(72="&#[`174E"+1>"#X!]0#[;#4`^V1>M0_W4(Z'?;__^#Q""# +M?>P`=#:+5=B)5=R)T,'@`@G8#[;`4.@XZ___@\0$A47P=!B#[`0/ML-0_W7< +M_W4(Z`+>__^#Q!"-=@#![@+!;>`(0X#[`P^&;____^L$D,'N"-'N_D7K@'WK +M`0^&XO[__[@!````C67T6UY?R<.058GE@^P,:@!H9!T``(M%"/]P#.C\____ +MN`$```#)PY!5B>6#[`R+10C_<%1H9!T``/]P#.C\____N`$```#)PU6)Y5=6 +M4X/L#(MU$(M]%+L`````.?-S.8/L"(M%#`4<`0``4/]U".C\____@\00A,!X +M#:@!#Y3`#[;`ZQF-=@"#[`Q7Z/S___^#Q!!#.?-RQ[@`````C67T6UY?R<.) +M]E6)Y5.#[`B+70AJ`(M#,`4@`0``4(M#*/]P#.C\____@\0(BT,P!2`!``!0 +MBT,H_W`,Z/S___^+7?S)PU6)Y5.#[`B+70AJ`HM#,`4@`0``4(M#*/]P#.C\ +M____@\0(BT,P!1P!``!0BT,H_W`,Z/S___^+7?S)PU6)Y5=64X/L#(MU"(M& +M*(M`#(E%\(M^,+L`````N`````"#OC0"```!#X2M````@^P(C8<@`0``4/]U +M\.C\____@\00J(%T$(/L#&HRZ/S___^#Q!"-=@"#[`B-AR`!``!0_W7PZ/S_ +M__^#Q!"H@70XB=A#9CVW"WX```` +M`(.Z3`D```%T"8/L#%+H_/___\G#D%6)Y8/L%&CO````:@`/MD4@4`^V11Q0 +M#[9%&%`/MD444`^V11!0:@!J`&H`:@`/MD4,4/]U".C\____R<.-=@!5B>57 +M5E.#[`R*10R(1?.+32!FB4WPBT4D9HE%[HM-*&:)3>R+?2R+=3"*732*13B( +M1>L/MD7SN@````"+30B#?($D`'0^@^P,#[9%ZU`/ML-0#[?&4`^WQU`/MT7L +M4`^W1>Y0#[=%\%#_=1S_=1C_=13_=1`/MD7S4/]U".C\____B<*)T(UE]%M> +M7\G#B?95B>575E.#['B+10B+52!FB578BTTD9HE-R(M5*&:)5;B+32QFB4VH +MBU4P9HE5F(I--(A-EXI5.(A5E@^V50R+7)`DBW`,BWLP4^BA_/__@\00N@`` +M``"%P`^$K0(``(/L#%/H_/___X/$$(-]%`%U>X/L!(M-V`^VQ5"-AP0!``!0 +M5NC\____@\0,BU7(#[;&4(V'"`$``%!6Z/S___^#Q`R+3;@/ML50C8<,`0`` +M4%;H_/___X/$#(M5J`^VQE"-AQ`!``!05NC\____@\0,BTV8#[;%4(V'%`$` +M`%!6Z/S___^#Q!#K/8UV`/=%V`#_``!U)_=%R`#_``!U'O=%N`#_``!U%?=% +MJ`#_``!U#/=%F`#_``!T#8UV`+H`````Z>8!``"#[`0/MD784(V'!`$``%!6 +MZ/S___^#Q`P/MD7(4(V'"`$``%!6Z/S___^#Q`P/MD6X4(V'#`$``%!6Z/S_ +M__^#Q`P/MD6H4(V'$`$``%!6Z/S___^#Q`P/MD684(V'%`$``%!6Z/S___^# +MQ`P/MD674(V'&`$``%!6Z/S___^#Q`P/MD664(V''`$``%!6Z/S___^#Q!"# +M?1``=3MJ9&CPN@0`5U;H_/___X/$$(7`=1.#[`Q3Z/S___^Z`````.DB`0`` +M@^P,4^C\____N@$```#I#P$``&ID:/"Z!`!75NC\____@\00A<```"#[`B-AQP!``!05NC\____@\00J`AU$X/L#%/H_/__ +M_[H`````Z;T```#'19``````BT4<.4607\G#B?95B>575E.#[!"+70B+ +M0RB+<`R+>S!J!HV'(`$``%!6Z/S___^#Q`B+0S`%(`$``%!6Z/S____'!"0* +M````Z/S___^)'"3H_/___\<$)/0!``#H_/___\<$)/0!``#H_/___\<$)/0! +M``#H_/___\<$)/0!``#H_/___[L`````@\00B?:#[`B-AQP!``!05NC\____ +M@\00A,!X";@!````ZR")]H/L#&CT`0``Z/S___^#Q!!#@?L/)P``=L>X```` +M`(UE]%M>7\G#B?95B>53@^P0BUT(4^@D____@\00N@$```"#^`%T%X/L#&CT +M`0``Z/S___^)'"3H`O___XG"B="+7?S)PY!5B>564XMU"(/L!&B@````H00` +M``"+0!@%```$`%!6Z/S___^[`````(/$$(/L"*$$````BT`0!0``!`!05NC\ +M____@\000X/[!'[@NP````"-=@"#[`BA!````(M`%`4```0`4%;H_/___X/$ +M$$.#^P5^X+L`````C78`@^P(H00```"+0!`%```$`%!6Z/S___^#Q!!#@_L$ +M?N"-9?A;7LG#D%6)Y5.#[`B+70AH@````*$$````BT`,!0``!`!04^C\____ +M@\0,:+````"A!````(M`&`4```0`4%/H_/___XM=_,G#58GE5E.+=0B#[`Q6 +MZ`?___^#Q`QJ`*$$````BT`(!0``!`!05NC\____@\0(H00```"+``4```0` +M4%;H_/___XC#B30DZ'+___\/MMN)V(UE^%M>R<.)]E6)Y5=64X/L%(M="&@L +M#0``4^C\____B<>#Q`R#R`%0:"P-``!3Z/S___^#Q`AH\`0!`%/H_/___XG& +M@^!B@\00@_AB=!J#[`2)\(/(8@^VP%!H\`0!`%/H_/___X/$$(/L"&@```0` +M4^C\____B1PDZ$K^__^#Q`QJ!Z$$````BT`(!0``!`!04^C\____@\0,:A&A +M!````(L`!0``!`!04^C\____@\0,:@6A!````(M`"`4```0`4%/H_/___X/$ +M#&H1H00```"+``4```0`4%/H_/___XD<).B$_O__@\0,5FCP!`$`4^C\____ +M@\0(:/`$`0!3Z/S___^#Q`Q7:"P-``!3Z/S___^#Q!"-9?1;7E_)PY!5B>57 +M5E.#[!2+70AH+`T``%/H_/___XG'@\0,@\@!4&@L#0``4^C\____@\0(:/`$ +M`0!3Z/S___^)QH/@8H/$$(/X8G0:@^P$B?"#R&(/ML!0:/`$`0!3Z/S___^# +MQ!"#[`AH```$`%/H_/___XD<).@R_?__@\0,:@>A!````(M`"`4```0`4%/H +M_/___X/$#&H`H00```"+``4```0`4%/H_/___X/$#&H%H00```"+0`@%```$ +M`%!3Z/S___^#Q`QJ`*$$````BP`%```$`%!3Z/S___^)'"3H;/W__X/$#%9H +M\`0!`%/H_/___X/$"&CP!`$`4^C\____@\0,5V@L#0``4^C\____@\00C67T +M6UY?R<.058GE4X/L$(M="%/H@/S__X/$#&H*H00```"+0`@%```$`%!3Z/S_ +M__^#Q`QJ`*$$````BP`%```$`%!3Z/S___^)'"3HZ_S__X/$"&@!``0`4^C\ +M____@\00NO____^H`G50@^P,4^@D_/__@\0,:@&A!````(L`!0``!`!04^C\ +M____B1PDZ*C\___'!"1D````Z/S___^#Q`AH`0`$`%/H_/___]'H@^`!@\00 +M@_@!&=*)T(M=_,G#B?95B>575E.#[!2+?0B*10R(1?.+7PQH+`T``%/H_/__ +M_XE%[(/$#(/(`5!H+`T``%/H_/___X/$"&CP!`$`4^C\____B<:#X&*#Q!"# +M^&)T&H/L!(GP@\AB#[;`4&CP!`$`4^C\____@\00@^P(:```!`!3Z/S___^# +MQ`R*1?.(1WD/ML!0:`#@!0!3Z/S___^#Q`Q6:/`$`0!3Z/S___^#Q`AH\`0! +M`%/H_/___X/$#/]U[&@L#0``4^C\____@\00C67T6UY?R<.-=@!5B>6#[`B+ +M50B*30R`?1``=`ZX`0```-/@"$)YZPR)]KC^____T\`@0GF#[`@/MD)Y4%+H +M_/___\G#B?95B>575E.#[!2+?0C&1?,`:"P-``!7Z/S___^)1>B#Q`R#R`%0 +M:"P-``!7Z/S___^#Q`AH\`0!`%?H_/___XE%[(/@8H/$$(/X8G0;@^P$BD7L +M@\AB#[;`4&CP!`$`5^C\____@\00@^P(:```!`!7Z/S___^#Q`AH```$`%?H +M_/___X/$$&8]5:H/A?4```"^`````(UV`+L`````.?-_)XUV`(/L!&B@```` +MH00```"+0!@%```$`%!7Z/S___^#Q!!#.?-^W('^R````'X0@^P,:@'H_/__ +M_X/$$(UV`(/L"&@```0`5^C\____B<.#Q`QHL````*$$````BT`8!0``!`!0 +M5^C\____@\009H'[5:IU%$:!_L<````/CG7___]F@?M5JG1;@^P$:+````"A +M!````(M`&`4```0`4%?H_/___X/$"&@```0`5^C\____@\009CU5JG4HQD7S +M`8/L#%?H2OK__X/$$#P^=12#[`Q7Z,+\__^#Q!"%P'4$QD7S`H/L!&BP```` +MH00```"+0!@%```$`%!7Z/S___^#Q`S_=>QH\`0!`%?H_/___X/$"&CP!`$` +M5^C\____@\0,_W7H:"P-``!7Z/S___^#Q!`/MD7SC67T6UY?R<-5B>564XMU +M"+L`````C78`QP4$````B````(/L#%;H_?W__X/$$(3`=2/'!00```"D```` +M@^P,5NCC_?__@\00A,!U"4.!^^<#``!^PP^VP(UE^%M>R<,````````````` +M``````````````````````0````````````````````````````````````` M```````````````````````````````````````````````````````````` M```````````````````````````````````````````````````````````` -M`````````0```````0`!``$``@`!``,``0`$``$`!0`!``8``0````$``"`! -M``!``0``8`$``(`!``"@`0``P`$`DC0``(4T``"%-```I30``+`T``"[-``` -MQC0``"``!,```` -M`@`!`*L```!4'@``,`````(``0"S````A!X``#L````"``$`O@```,`>```1 -M`````@`!`,8```#4'@``+`````(``0#8`````!\``"L````"``$`YP```"P? -M``!0`````@`!`/(```!\'P``.`````(``0#_````M!\``%$````"``$`"P$` -M``@@``#+`0```@`!`!@!``#4(0``L0````(``0`E`0``B"(``)<"```"``$` -M+P$``"`E``#P`````@`!`#X!``!89@``M0````(``0!)`0``$"8``.@#```" -M``$`50$``&0U``#W+0```@`!`&,!``#$9```.@$```(``0!O`0``^"D``"<` -M```"``$`>0$``$@S```9`@```@`!`(L!```@*@``I0````(``0"<`0``R"H` -M`!8!```"``$`J0$``.`K``"<`````@`!`+8!``"D+```;@````(``0##`0`` -M?"P``"@````"``$`S@$``!0M``!E`0```@`!`-D!``!\+@``P@$```(``0#E -M`0``;#(``&H````"``$`\P$``$`P``#%`````@`!```"```(,0``8@$```(` -M`0`-`@``V#(``&\````"``$``````````````````P`&`!X"```09P``#0,` -M``(``0`N`@``(&H``%H````"``$`10(``'QJ```\!0```@`!`%`"``"X;P`` -M8P,```(``0!<`@``'',``#0````"``$`;`(``&!X``!V`@```@`!`'D"``#@ -M?P``*`````(``0"*`@``=(```#\````"``$`GP(``+2````B`````@`!`+(" -M``#8@```/`````(``0"_`@``%($``+4"```"``$`U0(``,R#```\`0```@`! -M`.P"```(A0``E`````(``0`$`P``?)4``$H````"``$`$@,``)R%``!.`0`` -M`@`!`"4#``!,EP``4`````(``0`T`P``3)@```0"```"``$`2`,``&R,``!& -M`0```@`!`%L#``#LA@``D0````(``0!J`P``@(<``-("```"``$`?@,``-R/ -M```7`0```@`!`(P#``#TD```;0````(``0">`P``!)@``$8````"``$`JP,` -M`%2*``!1`````@`!`,$#``"`E@``+@````(``0#8`P``J(H``!X!```"``$` -MZP,``,B+``"A`````@`!`/L#``"PE@``F@````(``0`(!```G)<``&<````" -M``$`&P0``+2-``"&`0```@`!`"P$```\CP``H`````(``0`Z!```9)$``.8! -M```"``$`2P0``$R3```:`````@`!`&0$``!HDP``#0$```(``0![!```>)0` -M`#X````"``$`D`0``+B4``!D`````@`!`*0$``````7P```!(``0`'!@``Z`<``%`````2``$`&@8``'![ -M```3````$@`!`"@&```X"```(0$``!(``0`U!@``3'L``"$````2``$`1P8` -M`%QU``!8````$@`!`%(&``!<"0``(P$``!(``0!E!@``_`L``%<````2``$` -M=@8``"!^```3````$@`!`((&``#,?```,P```!(``0"2!@``5`P``.T````2 -M``$`I`8``/1]```K````$@`!`+0&``!$#0``.@```!(``0#'!@``@`T``'4` -M```2``$`V08``%`.``!.`0``$@`!`.\&``"@#P``@0```!(``0`,!P``)!`` -M`(8````2``$`(`<``%Q^``!(````$@`!`"X'``"L$```H0```!(``0!%!P`` -M4!$``$8!```2``$`70<``)@2``#!````$@`!`','`````````````!````!] -M!P``R!0```D"```2``$`CP<``#1^```E````$@`!`*`'``#4%@``(@$``!(` -M`0"S!P``^!<``+\!```2``$`Q`<``*@:``!7````$@`!`-0'````&P``[0`` -M`!(``0#E!P``\!L``"X````2``$`]P<````````$````$0`#``<(```````` -M`````!`````5"```7&,```H!```2``$`*`@`````````````$````#L(```` -M`````````!````!""``````````````0````20@``&AD``!<````$@`!`%4( -M`````````````!````!W"```B'T``&D````2``$`A0@```!F``!6````$@`! -M`)<(``!0P``0@```!(``0`1"0``A'L``$)X``.D!```2``$`?@L``&2@``"L````$@`!`),+``#$ -MH0``(````!(``0"J"P``Y*$``%\````2``$`RPL``$2B``"X````$@`!`.4+ -M``#\H@``AP```!(``0#^"P``A*,``/,````2``$`%@P``'BD``!5`0``$@`! -M`"T,``#0I0``4@```!(``0!$#```)*8``)H!```2``$`5PP``,"G``".`0`` -M$@`!`'4,``!0J0``'````!(``0"0#```;*D``!T````2``$`K0P``-BI```V -M````$@`!`,<,```0J@``-@```!(``0#B#```Z*H``'4````2``$`_PP``&"K -M``!_````$@`!`!T-``#@JP``*````!(``0`\#0``X*P``+8"```2``$`4@T` -M`(BQ``#X````$@`!`%D-``"`L@``^````!(``0!A#0``(+0``+P````2``$` -M;PT``-RT```X````$@`!``!R86ED+F,`4W1R:7!E1V5T0V]M;6%N9`!3=')I -M<&53<&QI=$-O;6UA;F0`27-61&5V3VYL:6YE`$1O0V]N=')O;$-M9`!*0D]$ -M1V5T0V]M;6%N9`!*0D]$4W!L:71#;VUM86YD`%]?:'!T7V%L;&]C`%]?:'!T -M7V9R964`9V%R8F%G95]A9&1R`&EN:71?:&5A<%]B;&]C:P!C8E]A;&QO8P!C -M8E]FF5R;P!C9E]I;FET`')E;6]V95]R86YG -M95]L;V-K`&%D9%]R86YG95]L;V-K`&QO8VM?&9E0!T87-K7V1O;F4`&]R -M7W1A&]R7W1A&]R;E]T87-K -M`&-H96-K7V1E<&5N9&5N8WD`9&ER96-T7W)E861?0!M=E-A=&%);FET061A<'1E<@!C:&5C:U]P&5C=71E3F]N541-04-O -M;6UA;F0`0F5E<$]N`$)E97!/9F8`00```%B``"&!``` -M`6,``+0$```"9P``S`0```)G``#D!````F<``/\$```"9P``-P4```%C``!4 -M!0```F8``&8%```":```O@4```)J``#E!0```6(``/(%```!8P``,`8```)K -M``"1!@```FT``-0&```";```7P<```)I``#4!P```FD``!\(```";```,@@` -M``%P``!2"````G(``*((```!<```O`@```)F``#0"````F0``-D(```";@`` -M\0@```)F``!`"0```G$``$X)```"0``!PT```%U```.#0```70``#@-```"=P``R`X```)V``#X#@```G<``#(/ -M```"9@``F`\```)F``!1$````G8``'@0```"=P``B1````%_``"/$````G<` -M`,@0```"=@``TA````)W``#C$````7\``.D0```"=P``+!$```)F``"T$@`` -M`G8``+X2```"=P``SQ(```%_``#5$@```G<````3```"9@``)!,```*#``"9 -M$P```G<``*43```!?P``K1,```)W``#+$P```GD``.T3```!@```]!,```%] -M```I%````F8``#P4```">0``7A0```%^``!E%````7T``)84```">0``N!0` -M``&"``"_%````8$``/P4```!`@``Z14```)Y``#T%0```F<```P6```!?``` -M$Q8```%[``"F%@```80``,@6```"=P``1!<```)M``"6%P```FH``*T7```! -M8@``M1<```%C``#M%P```FL```T9```"9P``U!H```)V``#Q&@```G<``&P; -M```">0``LQL```&(``"Z&P```8<``.0;```"=P``]!P```*,``!Q'@```F8` -M`,L>```"9@``/"0```)G``#")P```G<``+PH```!`@``1"D```%_``!**0`` -M`G<``%@I```!?P``<2D```$"``!Y*0```G<```XJ```!`@``%BH```)W``"\ -M*@```HX``/HK```"=@``OBP```)Y``#N+````0(``/4L```!`@``:"\```*/ -M``"0+P```I```"HP```"D```X3````*0```7,@```H\``&$R```"D```@30` -M``$N```%-0```2X``/5C```"=P``AF0```*-``",9````I(``))D```"DP`` -MF68```)W``#X9@```7\``/YF```"=P``[F@```$#``#9:0```0,``-YI```" -MC@``.VH```)V```&;0```F8``.1N```">0``#&\```$"```3;P```0(``#)O -M```!?P``.F\```)W```V````F8``,=Y```"9P``V7D` -M``)G``#N>0```F<```-Z```"9P``@7H```)E``"1>@```F4``+%Z```"9``` -M.GL```*;``##>P```F8``.I[```"9```GWP```)D``#J?0```I(``!=^```" -M9@``!G\```*B```/?P```J,``"!_```"I```IG\```*E``"R?P```J8``"*` -M```"J```/H````*I``!9@````J@``)2````"J@``I8````*J``#0@````JH` -M`/*#```"J0``!(0```*I```$```"J0``_(0```*L```NA0```JT```6'```"K0``&8<```*J -M```FAP```JT``#.'```"K0``2H<```*J``!7AP```JT``.R'```"J@``78@` -M``*M``!QB````JH``/6(```"J0``)XD```*J```PB0```JT``#>)```"J``` -M0HD```*J``!.B0```JT``%B)```"J```Q(D```&K``#4B@```JD``-Z*```" -MJ0``"(L```*J```BC````JX``$R,```"KP``3HT```*M``!5C0```J@``(*- -M```!JP``THT```*M``#FC0```JH``.V-```"K0``]XT```*H``"9C@```JH` -M`*N.```"J@``OHX```*J``#4C@```JH``...```"J@``]HX```*J```%CP`` -M`JH``!B/```"J@``+H\```*J```HD````JT``'F0```"J@``L)````*M``#5 -MD````JH``!J1```"J@``(Y$```*M```JD0```J@``#B1```"J@``09$```*M -M``"=D0```JH``*F1```"K0``P)$```*J``#4D0```JH``.61```"J@``]I$` -M``*J```*D@```JH``!N2```"J@``+)(```*J``!`D@```JH``%&2```"J@`` -M8I(```*J``!VD@```JH``(>2```"J@``FY(```*J``#2D@```JH``..2```" -MJ@``])(```*J```+DP```JH``!>3```"K0``+I,```*J``!@DP```JH``(23 -M```"K0``E9,```*J``"EDP```JT``+B3```"J@``QY,```*J``#9DP```JH` -M`.N3```"J@``^I,```*J```,E````JH``!N4```"J@``*I0```*J```\E``` -M`JH``$N4```"J@``6I0```*J``!LE````JH``#R5```"9P``;Y4```)G```? -ME@```JD``$^6```"J@``7Y8```*J``"EE@```JH``/Z6```"J@``#9<```*J -M```HEP```JD``#Z7```"J@``>9<```*J``"`EP```JT``!^8```"L```<)@` -M``*I``#KF````JP``/F8```"K```!YD```*L```8F0```JP``":9```"K``` -M.)D```*L``!)F0```JP``&B9```"J0``:```"K```+YH```*L``!$F@```JP``&R: -M```"J@``=)H```*S``````"K0``8YX```*H``!LG@```JT``-N>```"J@``Y)X```*M -M``#KG@```J@``/F>```"J@```I\```*M```SGP```JT``%N?```"J@``?9\` -M``*M``"$GP```J@``*>?```"J@``Q9\```*M``#/GP```J@``-J?```"IP`` -M#:````*I``"7H````JT``-R@```"J@``!J(```*M```IH@```JH``)VB```" -MK0``T*(```*J```KHP```JT``&:C```"J@``;Z,```*M``#%HP```JT``.^C -M```"J@``"*0```*M```DI````JT``$:D```"J@``P*0```*M``#AI````K0` -M`"6E```"K0``-Z4```*M``!)I0```JT``%NE```"K0``<*4```*M``""I0`` -M`JT``)2E```"K0``IJ4```*M```S```"K``` -MGK,```$$``"LLP```JP``,"S```"J0``Y;,```$$``#SLP```JP```"T```" -MJ```"[0```*I```^M````JT``%"T```"J@``6[0```*M``!]M````JX``(NT -M```"K0``I;0```*L``"QM````JH``+RT```"K0``S;0```*J```KM0```JT` -M`#VU```"J@``2+4```*M``!OM0```JX``'VU```"K0``BK4```*O``"?M0`` -M`00``*ZU```"K```O+4```*J``#'M0```JT``-BU```"J@``_K4```$$```- -MM@```JP``"JV```"KP``-K8```$$``!%M@```JP``&JV```!!```>;8```*L -M``"$M@```J\``,.V```"J```W[8```$$``#CM@```0,``/2V```!!```^+8` -M``$#``"C!@```FX``+@6```"A0``5A<```)N``"8)P```HT``%)F```"C0`` -M[&8```*-```_8<```*J``![E@```JT``/^7```"J@```*P```*P``#```.`````&$``!``````94``&`````!<```9`````%P``!H```` -M`7```&P````!<```<`````&*``!T`````7H``'@````!A@``@`````&6```` -M`````0(```0````!`@``"`````$"```,`````0(``!`````!`@``%`````$" -M```8`````0(``!P````!`@``(`````$"```D`````0(``"@````!`@``+``` -5``$"```P`````0(``#0````!`@`` +M`````````````````0```````0`!``$``@`!``,``0`$``$`!0`!``8``0`` +M``$``"`!``!``0``8`$``(`!``"@`0``P`$`1#8``/PU``#\-0``#38``!XV +M```O-@``0#8``!0W``#,-@``S#8``-TV``#N-@``_S8``!`W````1T-#.B`H +M1TY5*2`S+C0N,B!;1G)E94)31%T@,C`P-#`W,C@``"YS>6UT86(`+G-T```^`````@`!`+X````$'P``%``` +M``(``0#&````&!\``#$````"``$`V````$P?```H`````@`!`.<```!T'P`` +M4P````(``0#R````R!\``#$````"``$`_P```/P?``!5`````@`!``L!``!4 +M(```$P(```(``0`8`0``:"(``+L````"``$`)0$``"0C``"2`@```@`!`"\! +M``"X)0```0$```(``0`^`0``%&8``,\````"``$`20$``+PF```\!````@`! +M`%4!``!X-P```@``Y&8```H#```" +M``$`+@(``/!I``!G`````@`!`$4"``!8:@``-P4```(``0!0`@``D&\``)P# +M```"``$`7`(``"QS```[`````@`!`&P"``#$>```:P(```(``0!Y`@``D(`` +M`"P````"``$`B@(``#B!``!%`````@`!`)\"``"`@0``)0````(``0"R`@`` +MJ($``$(````"``$`OP(``.R!``"1`@```@`!`-4"``"`A```7@$```(``0#L +M`@``X(4``)0````"``$`!`,``/B7``!)`````@`!`!(#``!TA@``7`$```(` +M`0`E`P``W)D``$X````"``$`-`,``.2:```:`@```@`!`$@#``#TC0``6`$` +M``(``0!;`P``T(<``)$````"``$`:@,``&2(``#$`@```@`!`'X#``#XD@`` +M?P````(``0"0`P``P)$``#4!```"``$`G@,``)":``!1`````@`!`*L#```H +MBP``=0````(``0#!`P``^)@``"\````"``$`V`,``*"+``"0`0```@`!`.L# +M```PC0``P0````(``0#[`P``*)D``+$````"``$`"`0``"R:``!B`````@`! +M`!L$``!,CP``L0$```(``0`L!````)$``+\````"``$`.@0``'B3```.`@`` +M`@`!`$L$``"(E0``'0````(``0!D!```J)4``#$!```"``$`>P0``-R6``!" +M`````@`!`)`$```@EP``:@````(``0"D!```C)<``&L````"``$`KP0``$28 +M```L`````@`!`,$$``!PF```B`````(``0#7!```>*X``.0````"``$`[P0` +M`*"T``#*`````@`!`/P$``"(````'`````$``P`&!0``I````!P````!``,` +M$`4``*BU``"C`````@`!`!D%```$````!`````$`!0`A!0``3+8``$0````" +M``$`*04``)"V``!6`````@`!`#0%```8N0``N@````(``0`\!0``W+H``.`! +M```"``$``````````````````P`(`%0%````````6`4``!(``0!@!0``(``` +M`"0````1``,`;P4`````````````$````'P%``!@````)````!$``P",!0`` +M-'@``"H````2``$`E04`````````````$````*,%`````````````!````"M +M!0`````````````0````MP4``%@%``#+````$@`!`,$%`````````````!`` +M``#.!0`````````````0````X`4``"0&``"<`0``$@`!`/`%```````````` +M`!````#Y!0``8'@``&,````2``$`!P8``,`'``!6````$@`!`!H&``#@>P`` +M$@```!(``0`H!@``&`@``$`!```2``$`-08``+A[```H````$@`!`$<&``"L +M=0``8P```!(``0!2!@``6`D``!4!```2``$`908``.@+``!@````$@`!`'8& +M``"X?@``$P```!(``0""!@``.'T``#D````2``$`D@8``$@,`````0``$@`! +M`*0&``"$?@``,0```!(``0"T!@``2`T``$(````2``$`QP8``(P-``!O```` +M$@`!`-D&``!@#@``9`$``!(``0#O!@``Q`\``(`````2``$`#`<``$00``"4 +M````$@`!`"`'``#T?@``3@```!(``0`N!P``V!```+<````2``$`10<``)`1 +M```_`0``$@`!`%T'``#0$@``RP```!(``0!S!P`````````````0````?0<` +M`$@5``"P`0``$@`!`(\'``#,?@``)P```!(``0"@!P``^!8``"L!```2``$` +MLP<``"08``!V`0``$@`!`,0'``"(&@``8````!(``0#4!P``Z!H````!```2 +M``$`Y0<``.@;```R````$@`!`/<'````````!````!$``P`'"``````````` +M```0````%0@``.QB```P`0``$@`!`"@(`````````````!`````["``````` +M```````0````0@@`````````````$````$D(```<9```80```!(``0!5"``` +M```````````0````=P@```Q^``!X````$@`!`(4(``#$90``4````!(``0"7 +M"```:',``$0"```2``$`J0@```QW```H`0``$@`!`+P(```0=@``_````!(` +M`0#."``````````````0````X`@`````````````$````/,(```P>P``/@`` +M`!(``0`""0``<'L``$<````2``$`$0D``/1[``!#`0``$@`!`"`)``!T?0`` +M6````!(``0`Q"0``S'T``#\````2``$`/@D``$1_```>````$@`!`$D)``!D +M?P``-````!(``0!9"0``F'\``/8````2``$`90D``*"D``!#````$@`!`'T) +M``#DI```2````!(``0"1"0``N+```#T````2``$`K`D``/BP``".````$@`! +M`-$)``!4I```3````!(``0#H"0``O(```'H````2``$`_PD````````````` +M$````!,*`````````````!`````D"@`````````````0````-PH``(0````$ +M````$0`#`$H*`````````````!````!<"@`````````````0````;@H````` +M````````$````(`*`````````````!````"1"@``;+4``#L````2``$`H`H` +M`*"M``!>````$@`!`+H*````G0``Y`(``!(``0#,"@``G*```)@````2``$` +MZPH``.2?```?````$@`!``$+```$H```#P```!(``0`3"P``%*````\````2 +M``$`)@L``"2@``!.````$@`!`#T+``!TH```)@```!(``0!1"P``-*$``&0" +M```2``$`:`L``)BC``"Z````$@`!`'T+```LI0``(````!(``0"4"P``3*4` +M`'T````2``$`M0L``,RE``#,````$@`!`,\+``"8I@``C````!(``0#H"P`` +M)*<``!$!```2``$```P``#BH``!O`0``$@`!`!<,``"HJ0``4@```!(``0`N +M#```_*D``+D!```2``$`00P``+BK``"G`0``$@`!`%\,``!@K0``'P```!(` +M`0!Z#```@*T``"`````2``$`EPP```"N```\````$@`!`+$,```\K@``/``` +M`!(``0#,#```7*\``)`````2``$`Z0P``.RO``"5````$@`!``<-``"$L``` +M,P```!(``0`F#0``B+$``!8#```2``$`/`T``.BV```7`0``$@`!`$,-```` +MN```%P$``!(``0!+#0``U+D``,D````2``$`60T``*"Z```Z````$@`!`&8- +M``"\O```5P```!(``0``&]R,E]T87-K`&1O7WAO&9E49O5-T +M871E`$=E=%-T86UP`%-Y;F-!4EN9F\`0VAE8VM!4-R:71I8V%L +M`&9/6YC`&UV4F5A9%=R:71E`&UV4V%T841I&5C=71E3F]N541-04-O;6UA;F0`0F5E<$]N`$)E97!/9F8`%@```GD``*T6```":```R!8```%\``#/%@```7L` +M`)47```":@``K1<```%B``"U%P```60``.P7```":P``#!@```)M```8&``` +M`FX``(D9```":```N1H```)V``#:&@```G<```X;```"=P``.AL```)W``!K +M&P```GD``+(;```!B```N1L```&'```7'0```HP``*\>```"9P``$A\```)G +M```()0```F@``"DE```":```%RD```$"```#*@```0(```LJ```"=P``1BH` +M``%_``!.*@```G<``&\J```!?P``=2H```)W``"]*@```G<``.@J```"C0`` +M$BL```$"```:*P```G<``)LK```"C@``&2T```)V``#M+0```GD``"8N```! +M`@``,"X```$"``#4,````H\````Q```"D```MC$```*/``",,@```H\``-LS +M```"CP``"30```*0``#X-0```2X``,@V```!+@``MF,```)W``!%9````HT` +M`$UD```"D@``560```*3```(9@```HT``%EF```"=P``<&8```%_``!V9@`` +M`G<``*)F```!?P``J&8```)W``#39@```HT``.MG```!!```]F<```$$``#[ +M9P```HX``!!J```"=@``H6P```)G``#!;@```7\``,=N```"=P``^&X```)Y +M```>;P```0(``"5O```!`@``1W,```$"``!-````FX``)QX```";@``#WD```)G```M>@`` +M`F@``$)Z```":```6GH```)H``!O>@```F@``/-Z```"90```WL```)E```C +M>P```F,``&=[```"F@``EWL```*;``#L>P```G(``#%\```"9P``@'P```)C +M``"_?````F,``%M^```"D@``JGX```)G``!7?P```I$``(-_```"E```N'\` +M``*B``#$?P```J,``-A_```"I```90```*J +M``"-E````JH``*&4```"J@``M90```*J``#,E````JH```*5```"J@``%I4` +M``*J```JE0```JH``#Z5```"J@``4)4```*M``!JE0```JH``)^5```"J@`` +MRI4```*M``#>E0```JH``/&5```"K0``!Y8```*J```9E@```JH``"N6```" +MJ@``0)8```*J``!2E@```JH``&26```"J@``=I8```*J``"(E@```JH``)J6 +M```"J@``K)8```*J``"^E@```JH``-"6```"J@``L9<```)H``#*EP```F@` +M`)J8```"J0``RI@```*J``#=F````JH``.V8```"K0``'ID```*J``!]F0`` +M`JH``)&9```"J@``LID```*I``#-F0```JH```B:```"J@``$IH```*M``"# +MF@```JH``+*:```"L```")L```*I```YFP```JP``$Z;```"K```8YL```*L +M``!XFP```JP``(V;```"K```VYL```*L``#PFP```JP```6<```"K```&IP` +M``*L```OG````JP``$2<```"K```69P```*L``!UG````JD``("<```"L0`` +MG)P```*I``#3G````JX``!Z=```"J@``WYT```*M```TG@```JH``$2>```" +MK0``6IX```*J``!JG@```JT``-F>```"J@``[)X```*J``#_G@```JH``":? +M```"J@``2)\```*J``!_GP```J@``*B?```"LP``^)\```*J```)H````:L` +M`!F@```!JP``TJ````*M``#XH````JT```2A```"J```$*$```*M``"JH0`` +M`JH``+:A```"K0``PJ$```*H``#0H0```JH``-RA```"K0``,:(```*M``!A +MH@```JH``)*B```"K0``GJ(```*H``#2H@```JH```*C```"K0``#J,```*H +M```IP```JT``!*H```" +MJ@``@J@```*M``"PJ````K,```"I```"K0``%:D```*M```JJ0```JT``#^I +M```"K0``5*D```*M``!IJ0```JT``'ZI```"K0``DZD```*M``#TJ0```L(` +M`-&K```"K0``!*P```*M```9K````JH``%RL```"J@``:*P```*M``!\K``` +M`JH``)BL```"K0``=*T```*J``"5K0```JH``,BM```"J0``Y:T```*H```< +MK@```JP``#.N```"J0``6*X```*L``!OK@```JD``+6N```"J0``QJX```*H +M``#>K@```JD``/VN```"LP``$:\```*H```JKP```K$``#RO```"J0``E:\` +M``+'``"JKP```JP``+BO```"L0``R*\```+&``#9KP```L8``"ZP```"I0`` +ML;````*P``#OL````J4``':Q```"RP``[+$```+'```,L@```JP``".R```" +MK```.K(```*L``!1L@```JP``&BR```"K```O[(```*L``#4L@```JP``.FR +M```"K```_K(```*L```3LP```JP``"BS```"K```/;,```*L``!4LP```K$` +M`&2S```"Q@``=[,```+&``"/LP```K$``)^S```"Q@``N;,```*I``#)LP`` +M`L8``/^S```"L0``&+0```*O```^M````JX``%JT```"L0``:K0```+&``!Z +MM````L8``(JT```"Q@``P+0```*L``#2M````JD``-ZT```"J```YK0```+& +M``#RM````J@``/ZT```"J```"K4```*H```6M0```J@``#"U```"J0``3;4` +M``*H``"2M0```J@``+FU```!!```R+4```*L``#8M0```00``.>U```"J0`` +M`+8```$$```/M@```JD``"BV```!!```-[8```*I``!+8```$$``"'M@```JP``*>V```!!```MK8```*L``"^M@```00``,RV +M```"J0``^[8```*M```/MP```JH``!VW```"K0``0;<```*N``!2MP```JT` +M`&2W```!!```<[<```*L``!]MP```00``(NW```"K```E;<```$$``"DMP`` +M`JP``*ZW```!!```O+<```*L``#3MP```JH``.&W```"K0``\+<```*J```3 +MN````JT``">X```"J@``-;@```*M``!9N````JX``&JX```"K0``?+@```$$ +M``"+N````JP``)6X```!!```H[@```*L``"MN````00``+RX```"K```QK@` +M``$$``#4N````JP``.NX```"J@``^;@```*M```(N0```JH``"ZY```!!``` +M/;D```*L``!'N0```00``%6Y```"K```:[D```*I``"*N0```00``)BY```" +MK```K+D```*H``"ZN0```JD``/"Y```"K0``!;H```*J```3N@```JT``#>Z +M```"K@``2+H```*M``!@N@```JP``&^Z```"J@``?;H```*M``".N@```JH` +M`-2Z```"S@``\[H```*M```(NP```JH``!:[```"K0``/+L```*N``!-NP`` +M`JT``%N[```"KP``B;L```$$``"8NP```JP``+*[```"J```QKL```*O``#5 +MNP```00``.2[```"K```#[P```$$```>O````JP``"R\```"KP``:KP```$$ +M``!YO````JP``(J\```"J@``F+P```*M``"IO````JH``,Z\```!!```TKP` +M``$#``#HO````00``.R\```!`P``(`````&9```D`````9D``"@````!F0`` +M+`````&9```P`````8D``#0````!>```.`````&$``!``````94``&`````! +M<```9`````%P``!H`````7```&P````!<```<`````&*``!T`````7H``'@` +M```!A@``@`````&6`````````0(```0````!`@``"`````$"```,`````0(` +M`!`````!`@``%`````$"```8`````0(``!P````!`@``(`````$"```D```` +D`0(``"@````!`@``+`````$"```P`````0(``#0````!`@`` ` end diff --git a/sys/dev/hptmv/ioctl.c b/sys/dev/hptmv/ioctl.c index c75c98fd1942..5c3796a68d4b 100644 --- a/sys/dev/hptmv/ioctl.c +++ b/sys/dev/hptmv/ioctl.c @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -33,6 +33,17 @@ #include #include +#if (__FreeBSD_version < 500000) +#include +#include +#include +#include +#endif + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif + #include #include #include @@ -60,7 +71,8 @@ static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical); -static void get_disk_location(PDevice pDev, int *controller, int *channel) +static void +get_disk_location(PDevice pDev, int *controller, int *channel) { IAL_ADAPTER_T *pAdapTemp; int i, j; @@ -75,7 +87,8 @@ static void get_disk_location(PDevice pDev, int *controller, int *channel) } } -static int event_queue_add(PHPT_EVENT pEvent) +static int +event_queue_add(PHPT_EVENT pEvent) { int p; p = (event_queue_tail + 1) % MAX_EVENTS; @@ -88,7 +101,8 @@ static int event_queue_add(PHPT_EVENT pEvent) return 0; } -static int event_queue_remove(PHPT_EVENT pEvent) +static int +event_queue_remove(PHPT_EVENT pEvent) { if (event_queue_head != event_queue_tail) { @@ -100,7 +114,8 @@ static int event_queue_remove(PHPT_EVENT pEvent) return -1; } -void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param) +void HPTLIBAPI +ioctl_ReportEvent(UCHAR event, PVOID param) { HPT_EVENT e; ZeroMemory(&e, sizeof(e)); @@ -142,14 +157,15 @@ void HPTLIBAPI ioctl_ReportEvent(UCHAR event, PVOID param) } } -static int hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) +static int +hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) { PVDevice pArray = ID_TO_VDEV(id); BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; int i; PVDevice pa; - if((id== HPT_NULL_ID) || check_VDevice_valid(pArray)) + if ((id==0) || check_VDevice_valid(pArray)) return -1; if(!mIsArray(pArray)) return -1; @@ -176,7 +192,8 @@ static int hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) /* just to prevent driver from sending more commands */ static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} -static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter) +intrmask_t +lock_driver_idle(IAL_ADAPTER_T *pAdapter) { intrmask_t oldspl; _VBUS_INST(&pAdapter->VBus) @@ -185,6 +202,12 @@ static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter) KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); unlock_driver(oldspl); +/*Schedule out*/ +#if (__FreeBSD_version < 500000) + YIELD_THREAD; +#else + tsleep(lock_driver_idle, PPAUSE, "switch", 1); +#endif oldspl = lock_driver(); } CheckIdleCall(_VBUS_P0); @@ -218,7 +241,7 @@ int Kernel_DeviceIoControl(_VBUS_ARG pArray = ID_TO_VDEV(idArray); - if((idArray == HPT_NULL_ID) || check_VDevice_valid(pArray)) + if((idArray == 0) || check_VDevice_valid(pArray)) return -1; if(!mIsArray(pArray)) @@ -231,7 +254,7 @@ int Kernel_DeviceIoControl(_VBUS_ARG if(pArray == _vbus_p->pVDevice[i]) { periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); - if (periph != NULL && periph->refcount == 1) + if (periph != NULL && periph->refcount >= 1) { hpt_printk(("Can not delete a mounted device.\n")); return -1; @@ -388,7 +411,7 @@ int Kernel_DeviceIoControl(_VBUS_ARG { PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; - if(pArray->u.array.rf_rebuilding == HPT_NULL_ID) + if(pArray->u.array.rf_rebuilding == 0) { DWORD timeout = 0; oldspl = lock_driver(); @@ -417,7 +440,8 @@ int Kernel_DeviceIoControl(_VBUS_ARG return 0; } -static int hpt_get_event(PHPT_EVENT pEvent) +static int +hpt_get_event(PHPT_EVENT pEvent) { intrmask_t oldspl = lock_driver(); int ret = event_queue_remove(pEvent); @@ -425,7 +449,8 @@ static int hpt_get_event(PHPT_EVENT pEvent) return ret; } -static int hpt_set_array_state(DEVICEID idArray, DWORD state) +static int +hpt_set_array_state(DEVICEID idArray, DWORD state) { IAL_ADAPTER_T *pAdapter; PVDevice pVDevice = ID_TO_VDEV(idArray); @@ -433,8 +458,7 @@ static int hpt_set_array_state(DEVICEID idArray, DWORD state) DWORD timeout = 0; intrmask_t oldspl; - if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) - return -1; + if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; if(!mIsArray(pVDevice)) return -1; if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; @@ -474,7 +498,7 @@ static int hpt_set_array_state(DEVICEID idArray, DWORD state) case MIRROR_REBUILD_ABORT: { for(i = 0; i < pVDevice->u.array.bArnMember; i++) { - if(pVDevice->u.array.pMember[i] != NULL && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) + if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); } @@ -585,7 +609,8 @@ static int hpt_set_array_state(DEVICEID idArray, DWORD state) return 0; } -static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) +int HPTLIBAPI +R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) { ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) @@ -648,13 +673,15 @@ static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, } static int End_Job=0; -static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd) +void HPTLIBAPI +thread_io_done(_VBUS_ARG PCommand pCmd) { End_Job = 1; wakeup((caddr_t)pCmd); } -void hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) +void +hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) { DWORD timeout = 0; ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); @@ -714,7 +741,9 @@ retry_cmd: #define MAX_REBUILD_SECTORS 0x40 /* take care for discontinuous buffer in R1ControlSgl */ + unlock_driver(oldspl); buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); + oldspl = lock_driver(); if(!buffer) { FreeCommand(_VBUS_P pCmd); hpt_printk(("can't allocate rebuild buffer\n")); @@ -783,11 +812,9 @@ retry_cmd: result = pCmd->Result; FreeCommand(_VBUS_P pCmd); - if (buffer) { - free(buffer, M_DEVBUF); - /* beware of goto retry_cmd below */ - buffer = NULL; - } + unlock_driver(oldspl); + if (buffer) free(buffer, M_DEVBUF); + oldspl = lock_driver(); KdPrintI(("cmd finished %d", result)); switch(result) @@ -918,6 +945,12 @@ fail: /* put this to have driver stop processing system commands quickly */ if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); unlock_driver(oldspl); + /*Schedule out*/ +#if (__FreeBSD_version < 500000) + YIELD_THREAD; +#else + tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1); +#endif oldspl = lock_driver(); } diff --git a/sys/dev/hptmv/mv.c b/sys/dev/hptmv/mv.c index 474b3d5ddb23..f9f41ffb75da 100644 --- a/sys/dev/hptmv/mv.c +++ b/sys/dev/hptmv/mv.c @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -27,51 +27,68 @@ */ #include #include + +#include #include +#include +#include + +#if __FreeBSD_version >= 500043 +#include +#endif + +#if (__FreeBSD_version < 500043) +#include +#endif -#include -#include -#include +#if (__FreeBSD_version < 500000) +#include +#endif + +#ifndef __KERNEL__ +#define __KERNEL__ +#endif #include #include #include #include + void HPTLIBAPI MV_REG_WRITE_BYTE(MV_BUS_ADDR_T base, MV_U32 offset, MV_U8 val) -{ - mv_reg_write_byte(base, offset, val); +{ + writeb((void *)((ULONG_PTR)base + offset), val); } void HPTLIBAPI MV_REG_WRITE_WORD(MV_BUS_ADDR_T base, MV_U32 offset, MV_U16 val) -{ - mv_reg_write_word(base, offset, val); +{ + writew((void *)((ULONG_PTR)base + offset), val); } void HPTLIBAPI MV_REG_WRITE_DWORD(MV_BUS_ADDR_T base, MV_U32 offset, MV_U32 val) { - mv_reg_write_dword(base, offset, val); + writel((void *)((ULONG_PTR)base + offset), val); } -MV_U8 -HPTLIBAPI MV_REG_READ_BYTE(MV_BUS_ADDR_T base, MV_U32 offset) +MV_U8 HPTLIBAPI +MV_REG_READ_BYTE(MV_BUS_ADDR_T base, MV_U32 offset) { - return (mv_reg_read_byte(base, offset)); + return readb((void *)((ULONG_PTR)base + offset)); } -MV_U16 -HPTLIBAPI MV_REG_READ_WORD(MV_BUS_ADDR_T base, MV_U32 offset) +MV_U16 HPTLIBAPI +MV_REG_READ_WORD(MV_BUS_ADDR_T base, MV_U32 offset) { - return (mv_reg_read_word(base, offset)); + return readw((void *)((ULONG_PTR)base + offset)); } -MV_U32 -HPTLIBAPI MV_REG_READ_DWORD(MV_BUS_ADDR_T base, MV_U32 offset) +MV_U32 HPTLIBAPI +MV_REG_READ_DWORD(MV_BUS_ADDR_T base, MV_U32 offset) { - return (mv_reg_read_dword(base, offset)); + return readl((void *)((ULONG_PTR)base + offset)); } int HPTLIBAPI @@ -86,29 +103,26 @@ os_memcpy(void *to, const void *from, unsigned len) memcpy(to, from, len); } -void -HPTLIBAPI os_memset(void *s, char c, unsigned len) +void HPTLIBAPI +os_memset(void *s, char c, unsigned len) { memset(s, c, len); } -unsigned -HPTLIBAPI os_strlen(const char *s) +unsigned HPTLIBAPI +os_strlen(const char *s) { return strlen(s); } -void HPTLIBAPI mvMicroSecondsDelay(MV_U32 msecs) +void HPTLIBAPI +mvMicroSecondsDelay(MV_U32 msecs) { DELAY(msecs); } -/* - * XXX - * - * The binary raid.obj requires this function! - */ -ULONG_PTR HPTLIBAPI fOsPhysicalAddress(void *addr) +ULONG_PTR HPTLIBAPI +fOsPhysicalAddress(void *addr) { return (ULONG_PTR)(vtophys(addr)); } diff --git a/sys/dev/hptmv/mvOs.h b/sys/dev/hptmv/mvOs.h index 2c0a5f4b1c66..ef78c94644f5 100644 --- a/sys/dev/hptmv/mvOs.h +++ b/sys/dev/hptmv/mvOs.h @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -28,19 +28,6 @@ #ifndef __INCmvOsBsdh #define __INCmvOsBsdh -/* Taken out of the Makefile magic */ -#define __KERNEL__ 1 -#define KERNEL 1 -#define _KERNEL 1 -#define _FREEBSD_ 1 - -/* - * This binary object core for this driver is only for x86, so this constant - * will not change. - */ -#define BITS_PER_LONG 32 -#define DRIVER_VERSION "1.1" - #if DBG #define MV_DEBUG_LOG #endif @@ -49,22 +36,24 @@ #define ENABLE_WRITE_CACHE /* Typedefs */ -#define HPTLIBAPI __attribute__((regparm(0))) +/*#define HPTLIBAPI __attribute__((regparm(0))) */ +#define HPTLIBAPI #define FAR +#define SS_SEG #ifdef FASTCALL #undef FASTCALL #endif #define FASTCALL HPTLIBAPI #define PASCAL HPTLIBAPI -typedef u_short USHORT; -typedef u_char UCHAR; -typedef u_char *PUCHAR; -typedef u_short *PUSHORT; -typedef u_char BOOLEAN; -typedef u_short WORD; -typedef u_int UINT, BOOL; -typedef u_char BYTE; +typedef unsigned short USHORT; +typedef unsigned char UCHAR; +typedef unsigned char *PUCHAR; +typedef unsigned short *PUSHORT; +typedef unsigned char BOOLEAN; +typedef unsigned short WORD; +typedef unsigned int UINT, BOOL; +typedef unsigned char BYTE; typedef void *PVOID, *LPVOID; typedef void *ADDRESS; @@ -72,23 +61,28 @@ typedef int LONG; typedef unsigned int ULONG, *PULONG, LBA_T; typedef unsigned int DWORD, *LPDWORD, *PDWORD; typedef unsigned long ULONG_PTR, UINT_PTR, BUS_ADDR; +typedef unsigned long long HPT_U64; typedef enum mvBoolean{MV_FALSE, MV_TRUE} MV_BOOLEAN; #define FALSE 0 #define TRUE 1 +#ifndef NULL +#define NULL 0 +#endif + /* System dependant typedefs */ -typedef void MV_VOID; -typedef uint32_t MV_U32; -typedef uint16_t MV_U16; -typedef uint8_t MV_U8; -typedef void *MV_VOID_PTR; -typedef MV_U32 *MV_U32_PTR; -typedef MV_U16 *MV_U16_PTR; -typedef MV_U8 *MV_U8_PTR; -typedef char *MV_CHAR_PTR; -typedef void *MV_BUS_ADDR_T; +typedef void MV_VOID; +typedef unsigned int MV_U32; +typedef unsigned short MV_U16; +typedef unsigned char MV_U8; +typedef void *MV_VOID_PTR; +typedef MV_U32 *MV_U32_PTR; +typedef MV_U16 *MV_U16_PTR; +typedef MV_U8 *MV_U8_PTR; +typedef char *MV_CHAR_PTR; +typedef void *MV_BUS_ADDR_T; /* System dependent macro for flushing CPU write cache */ #define MV_CPU_WRITE_BUFFER_FLUSH() @@ -101,12 +95,9 @@ typedef void *MV_BUS_ADDR_T; #define MV_LE32_TO_CPU(x) (x) /* System dependent register read / write in byte/word/dword variants */ -extern void HPTLIBAPI MV_REG_WRITE_BYTE(MV_BUS_ADDR_T base, MV_U32 offset, - MV_U8 val); -extern void HPTLIBAPI MV_REG_WRITE_WORD(MV_BUS_ADDR_T base, MV_U32 offset, - MV_U16 val); -extern void HPTLIBAPI MV_REG_WRITE_DWORD(MV_BUS_ADDR_T base, MV_U32 offset, - MV_U32 val); +extern void HPTLIBAPI MV_REG_WRITE_BYTE(MV_BUS_ADDR_T base, MV_U32 offset, MV_U8 val); +extern void HPTLIBAPI MV_REG_WRITE_WORD(MV_BUS_ADDR_T base, MV_U32 offset, MV_U16 val); +extern void HPTLIBAPI MV_REG_WRITE_DWORD(MV_BUS_ADDR_T base, MV_U32 offset, MV_U32 val); extern MV_U8 HPTLIBAPI MV_REG_READ_BYTE(MV_BUS_ADDR_T base, MV_U32 offset); extern MV_U16 HPTLIBAPI MV_REG_READ_WORD(MV_BUS_ADDR_T base, MV_U32 offset); extern MV_U32 HPTLIBAPI MV_REG_READ_DWORD(MV_BUS_ADDR_T base, MV_U32 offset); @@ -121,25 +112,9 @@ typedef struct mvOsSemaphore ULONG_PTR HPTLIBAPI fOsPhysicalAddress(void *addr); /* Semaphore init, take and release */ -static __inline int -mvOsSemInit(MV_OS_SEMAPHORE *p) -{ - return (MV_TRUE); -} - -static __inline int -mvOsSemTake(MV_OS_SEMAPHORE *p) -{ - return (MV_TRUE); -} - -static __inline int -mvOsSemRelease(MV_OS_SEMAPHORE *p) -{ - return (MV_TRUE); -} - -#define MV_MAX_SEGMENTS 255 +#define mvOsSemInit(p) (MV_TRUE) +#define mvOsSemTake(p) (MV_TRUE) +#define mvOsSemRelease(p) (MV_TRUE) /* Delay function in micro seconds resolution */ void HPTLIBAPI mvMicroSecondsDelay(MV_U32); @@ -148,7 +123,7 @@ void HPTLIBAPI mvMicroSecondsDelay(MV_U32); #ifdef MV_DEBUG_LOG int mvLogMsg(MV_U8, MV_CHAR_PTR, ...); #define _mvLogMsg(x) mvLogMsg x -#else +#else #define mvLogMsg(x...) #define _mvLogMsg(x) #endif @@ -156,16 +131,17 @@ int mvLogMsg(MV_U8, MV_CHAR_PTR, ...); /************************************************************************* * Debug support *************************************************************************/ -#ifdef DEBUG -#define HPT_ASSERT(x) \ - KASSERT((x), ("ASSERT fail at %s line %d", __FILE__, __LINE__)) - +#if DEBUG +#define HPT_ASSERT(x) do { if (!(x)) { \ + printf("ASSERT fail at %s line %d", __FILE__, __LINE__); \ + while (1); \ + }} while (0) extern int hpt_dbg_level; #define KdPrintI(_x_) do{ if (hpt_dbg_level>2) printf _x_; }while(0) #define KdPrintW(_x_) do{ if (hpt_dbg_level>1) printf _x_; }while(0) #define KdPrintE(_x_) do{ if (hpt_dbg_level>0) printf _x_; }while(0) #define KdPrint(x) KdPrintI(x) -#else +#else #define HPT_ASSERT(x) #define KdPrint(x) #define KdPrintI(x) @@ -173,4 +149,4 @@ extern int hpt_dbg_level; #define KdPrintE(x) #endif -#endif /* __INCmvOsBsdh */ +#endif diff --git a/sys/dev/hptmv/mvSata.h b/sys/dev/hptmv/mvSata.h index 4a5c75c81d60..bf77fbfcb234 100644 --- a/sys/dev/hptmv/mvSata.h +++ b/sys/dev/hptmv/mvSata.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 MARVELL SEMICONDUCTOR ISRAEL, LTD. + * Copyright (c) 2004-2005 MARVELL SEMICONDUCTOR ISRAEL, LTD. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/hptmv/mvStorageDev.h b/sys/dev/hptmv/mvStorageDev.h index 5d533fedb866..48aad93651f9 100644 --- a/sys/dev/hptmv/mvStorageDev.h +++ b/sys/dev/hptmv/mvStorageDev.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 MARVELL SEMICONDUCTOR ISRAEL, LTD. + * Copyright (c) 2004-2005 MARVELL SEMICONDUCTOR ISRAEL, LTD. * All rights reserved. * * Redistribution and use in source and binary forms, with or without diff --git a/sys/dev/hptmv/osbsd.h b/sys/dev/hptmv/osbsd.h index d81229ec8754..a07f51dbc8d7 100644 --- a/sys/dev/hptmv/osbsd.h +++ b/sys/dev/hptmv/osbsd.h @@ -1,5 +1,5 @@ -/*- - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. +/* + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -31,10 +31,24 @@ #include #include #include +#include +#if (__FreeBSD_version < 500043) +#include +#include +#endif + +#include +#include +#include + +#if (__FreeBSD_version < 600030) +#include +#endif #include #include #include + #include #include @@ -43,15 +57,19 @@ #include #include #include +#include + #include #include + + extern intrmask_t lock_driver(void); extern void unlock_driver(intrmask_t spl); typedef struct { - UCHAR status; /* 0 nonbootable; 80h bootable */ + UCHAR status; /* 0 nonbootable; 80h bootable */ UCHAR start_head; USHORT start_sector; UCHAR type; @@ -98,8 +116,8 @@ typedef struct _READ_CAPACITY_DATA { /****************************************/ /* Bits for HD_ERROR */ -#define NM_ERR 0x02 /* media present */ -#define ABRT_ERR 0x04 /* Command aborted */ +#define NM_ERR 0x02 /* media present */ +#define ABRT_ERR 0x04 /* Command aborted */ #define MCR_ERR 0x08 /* media change request */ #define IDNF_ERR 0x10 /* ID field not found */ #define MC_ERR 0x20 /* media changed */ @@ -107,213 +125,195 @@ typedef struct _READ_CAPACITY_DATA { #define WP_ERR 0x40 /* write protect */ #define ICRC_ERR 0x80 /* new meaning: CRC error during transfer */ -#define REQUESTS_ARRAY_SIZE (9 * MV_EDMA_REQUEST_QUEUE_SIZE) /* 9 K bytes */ -#define RESPONSES_ARRAY_SIZE (12*MV_EDMA_RESPONSE_QUEUE_SIZE) /* 3 K bytes */ +#define REQUESTS_ARRAY_SIZE (9 * MV_EDMA_REQUEST_QUEUE_SIZE) /* 9 K bytes */ +#define RESPONSES_ARRAY_SIZE (12 * MV_EDMA_RESPONSE_QUEUE_SIZE) /* 3 K bytes */ -#define PRD_ENTRIES_PER_CMD (MAX_SG_DESCRIPTORS+1) -#define PRD_ENTRIES_SIZE (MV_EDMA_PRD_ENTRY_SIZE*PRD_ENTRIES_PER_CMD) -#define PRD_TABLES_FOR_VBUS (MV_SATA_CHANNELS_NUM*MV_EDMA_QUEUE_LENGTH) +#define PRD_ENTRIES_PER_CMD (MAX_SG_DESCRIPTORS+1) +#define PRD_ENTRIES_SIZE (MV_EDMA_PRD_ENTRY_SIZE*PRD_ENTRIES_PER_CMD) +#define PRD_TABLES_FOR_VBUS (MV_SATA_CHANNELS_NUM*MV_EDMA_QUEUE_LENGTH) -typedef enum _SataEvent { - SATA_EVENT_NO_CHANGE = 0, +typedef enum _SataEvent +{ + SATA_EVENT_NO_CHANGE = 0, SATA_EVENT_CHANNEL_CONNECTED, SATA_EVENT_CHANNEL_DISCONNECTED } SATA_EVENT; typedef ULONG_PTR dma_addr_t; -typedef struct _MV_CHANNEL { +typedef struct _MV_CHANNEL +{ unsigned int maxUltraDmaModeSupported; unsigned int maxDmaModeSupported; unsigned int maxPioModeSupported; - MV_BOOLEAN online; + MV_BOOLEAN online; } MV_CHANNEL; -struct _privCommand; +typedef struct _BUS_DMAMAP +{ struct _BUS_DMAMAP *next; + struct IALAdapter *pAdapter; + bus_dmamap_t dma_map; + SCAT_GATH psg[MAX_SG_DESCRIPTORS]; +} BUS_DMAMAP, *PBUS_DMAMAP; -typedef struct IALAdapter { +typedef struct IALAdapter +{ struct cam_path *path; - device_t hpt_dev; /* bus device */ - struct resource *hpt_irq; /* interrupt */ - void *hpt_intr; /* interrupt handle */ + + bus_dma_tag_t io_dma_parent; /* I/O buffer DMA tag */ + PBUS_DMAMAP pbus_dmamap_list; + PBUS_DMAMAP pbus_dmamap; + + device_t hpt_dev; /* bus device */ + struct resource *hpt_irq; /* interrupt */ struct resource *mem_res; - bus_space_handle_t mem_bsh; - bus_space_tag_t mem_btag; - bus_dma_tag_t parent_dmat; - bus_dma_tag_t req_dmat; - bus_dmamap_t req_map; - bus_dma_tag_t resp_dmat; - bus_dmamap_t resp_map; - bus_dma_tag_t prd_dmat; - bus_dmamap_t prd_map; - bus_dma_tag_t buf_dmat; - - struct IALAdapter *next; - - MV_SATA_ADAPTER mvSataAdapter; - MV_CHANNEL mvChannel[MV_SATA_CHANNELS_NUM]; - MV_U8 *requestsArrayBaseAddr; - MV_U8 *requestsArrayBaseAlignedAddr; - dma_addr_t requestsArrayBaseDmaAddr; - dma_addr_t requestsArrayBaseDmaAlignedAddr; - MV_U8 *responsesArrayBaseAddr; - MV_U8 *responsesArrayBaseAlignedAddr; - dma_addr_t responsesArrayBaseDmaAddr; - dma_addr_t responsesArrayBaseDmaAlignedAddr; - SATA_EVENT sataEvents[MV_SATA_CHANNELS_NUM]; + void *hpt_intr; /* interrupt handle */ + struct IALAdapter *next; + + MV_SATA_ADAPTER mvSataAdapter; + MV_CHANNEL mvChannel[MV_SATA_CHANNELS_NUM]; + MV_U8 *requestsArrayBaseAddr; + MV_U8 *requestsArrayBaseAlignedAddr; + dma_addr_t requestsArrayBaseDmaAddr; + dma_addr_t requestsArrayBaseDmaAlignedAddr; + MV_U8 *responsesArrayBaseAddr; + MV_U8 *responsesArrayBaseAlignedAddr; + dma_addr_t responsesArrayBaseDmaAddr; + dma_addr_t responsesArrayBaseDmaAlignedAddr; + SATA_EVENT sataEvents[MV_SATA_CHANNELS_NUM]; struct callout_handle event_timer_connect; struct callout_handle event_timer_disconnect; - struct _VBus VBus; - struct _VDevice VDevices[MV_SATA_CHANNELS_NUM]; - PCommand pCommandBlocks; - struct _privCommand *pPrivateBlocks; - TAILQ_HEAD(, _privCommand) PrivCmdTQH; - PUCHAR prdTableAddr; - ULONG prdTableDmaAddr; - void* pFreePRDLink; + struct _VBus VBus; + struct _VDevice VDevices[MV_SATA_CHANNELS_NUM]; + PCommand pCommandBlocks; + PUCHAR prdTableAddr; + PUCHAR prdTableAlignedAddr; + void* pFreePRDLink; - union ccb *pending_Q; + union ccb *pending_Q; - MV_U8 outstandingCommands; + MV_U8 outstandingCommands; - UCHAR status; - UCHAR ver_601; - UCHAR beeping; + UCHAR status; + UCHAR ver_601; + UCHAR beeping; eventhandler_tag eh; -} IAL_ADAPTER_T; - -typedef struct _privCommand { - TAILQ_ENTRY(_privCommand) PrivEntry; - IAL_ADAPTER_T *pAdapter; - union ccb *ccb; - bus_dmamap_t buf_map; -} *pPrivCommand; +} +IAL_ADAPTER_T; extern IAL_ADAPTER_T *gIal_Adapter; /*entry.c*/ typedef void (*HPT_DPC)(IAL_ADAPTER_T *,void*,UCHAR); + int hpt_queue_dpc(HPT_DPC dpc, IAL_ADAPTER_T *pAdapter, void *arg, UCHAR flags); -void hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, - UCHAR flags); +void hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags); void Check_Idle_Call(IAL_ADAPTER_T *pAdapter); -int Kernel_DeviceIoControl(_VBUS_ARG DWORD dwIoControlCode, PVOID lpInBuffer, - DWORD nInBufferSize, PVOID lpOutBuffer, DWORD nOutBufferSize, - PDWORD lpBytesReturned); void fRescanAllDevice(_VBUS_ARG0); int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk); +int Kernel_DeviceIoControl(_VBUS_ARG + DWORD dwIoControlCode, /* operation control code */ + PVOID lpInBuffer, /* input data buffer */ + DWORD nInBufferSize, /* size of input data buffer */ + PVOID lpOutBuffer, /* output data buffer */ + DWORD nOutBufferSize, /* size of output data buffer */ + PDWORD lpBytesReturned /* byte count */ + ); + #define __str_direct(x) #x #define __str(x) __str_direct(x) #define KMSG_LEADING __str(PROC_DIR_NAME) ": " -#define hpt_printk(_x_) do { \ - printf(KMSG_LEADING); \ - printf _x_ ; \ -} while (0) +#define hpt_printk(_x_) do { printf(KMSG_LEADING); printf _x_ ; } while (0) #define DUPLICATE 0 #define INITIALIZE 1 #define REBUILD_PARITY 2 #define VERIFY 3 -/**********************************************************/ +/***********************************************************/ + static __inline struct cam_periph * hpt_get_periph(int path_id,int target_id) { - struct cam_periph *periph = NULL; - struct cam_path *path; - int status; + struct cam_periph *periph = NULL; + struct cam_path *path; + int status; - status = xpt_create_path(&path, NULL, path_id, target_id, 0); - if (status == CAM_REQ_CMP) { - periph = cam_periph_find(path, NULL); + status = xpt_create_path(&path, NULL, path_id, target_id, 0); + if (status == CAM_REQ_CMP) { + periph = cam_periph_find(path, "da"); xpt_free_path(path); - if (periph != NULL) { - if (strncmp(periph->periph_name, "da", 2)) - periph = NULL; - } - } + + } return periph; } -static __inline void -FreePrivCommand(IAL_ADAPTER_T *pAdapter, pPrivCommand prvCmd) -{ - TAILQ_INSERT_TAIL(&pAdapter->PrivCmdTQH, prvCmd, PrivEntry); -} +#if (__FreeBSD_version < 500000) +#define YIELD_THREAD yield(curproc, 0) +#endif -static __inline pPrivCommand -AllocPrivCommand(IAL_ADAPTER_T *pAdapter) -{ - pPrivCommand prvCmd; +#ifdef __i386__ +#define BITS_PER_LONG 32 +#define VDEV_TO_ID(pVDev) (DEVICEID)(pVDev) +#define ID_TO_VDEV(id) (PVDevice)(id) +#else /*Only support x86_64(AMD64 and EM64T)*/ +#define BITS_PER_LONG 64 +#define VDEV_TO_ID(pVDev) (DEVICEID)(ULONG_PTR)(pVDev) +#define ID_TO_VDEV(id) (PVDevice)(((ULONG_PTR)gIal_Adapter & 0xffffffff00000000) | (id)) +#endif - prvCmd = TAILQ_FIRST(&pAdapter->PrivCmdTQH); - if (prvCmd == NULL) - return NULL; +#define INVALID_DEVICEID (-1) +#define INVALID_STRIPSIZE (-1) - TAILQ_REMOVE(&pAdapter->PrivCmdTQH, prvCmd, PrivEntry); - return (prvCmd); -} +#define shortswap(w) ((WORD)((w)>>8 | ((w) & 0xFF)<<8)) -static __inline void -mv_reg_write_byte(MV_BUS_ADDR_T base, MV_U32 offset, MV_U8 val) -{ - IAL_ADAPTER_T *pAdapter; - - pAdapter = base; - bus_space_write_1(pAdapter->mem_btag, pAdapter->mem_bsh, offset, val); -} +#ifndef MinBlockSizeShift +#define MinBlockSizeShift 5 +#define MaxBlockSizeShift 12 +#endif -static __inline void -mv_reg_write_word(MV_BUS_ADDR_T base, MV_U32 offset, MV_U16 val) +#pragma pack(1) +typedef struct _HPT_IOCTL_TRANSFER_PARAM { - IAL_ADAPTER_T *pAdapter; - - pAdapter = base; - bus_space_write_2(pAdapter->mem_btag, pAdapter->mem_bsh, offset, val); -} + ULONG nInBufferSize; + ULONG nOutBufferSize; + UCHAR buffer[0]; +}HPT_IOCTL_TRANSFER_PARAM, *PHPT_IOCTL_TRANSFER_PARAM; -static __inline void -mv_reg_write_dword(MV_BUS_ADDR_T base, MV_U32 offset, MV_U32 val) +typedef struct _HPT_SET_STATE_PARAM { - IAL_ADAPTER_T *pAdapter; + DEVICEID idArray; + DWORD state; +} HPT_SET_STATE_PARAM, *PHPT_SET_STATE_PARAM; - pAdapter = base; - bus_space_write_4(pAdapter->mem_btag, pAdapter->mem_bsh, offset, val); -} - -static __inline MV_U8 -mv_reg_read_byte(MV_BUS_ADDR_T base, MV_U32 offset) +typedef struct _HPT_SET_ARRAY_INFO { - IAL_ADAPTER_T *pAdapter; - - pAdapter = base; - return (bus_space_read_1(pAdapter->mem_btag, pAdapter->mem_bsh, - offset)); -} + DEVICEID idArray; + ALTERABLE_ARRAY_INFO Info; +} HPT_SET_ARRAY_INFO, *PHPT_SET_ARRAY_INFO; -static __inline MV_U16 -mv_reg_read_word(MV_BUS_ADDR_T base, MV_U32 offset) +typedef struct _HPT_SET_DEVICE_INFO { - IAL_ADAPTER_T *pAdapter; - - pAdapter = base; - return (bus_space_read_2(pAdapter->mem_btag, pAdapter->mem_bsh, - offset)); -} + DEVICEID idDisk; + ALTERABLE_DEVICE_INFO Info; +} HPT_SET_DEVICE_INFO, *PHPT_SET_DEVICE_INFO; -static __inline MV_U32 -mv_reg_read_dword(MV_BUS_ADDR_T base, MV_U32 offset) +typedef struct _HPT_ADD_DISK_TO_ARRAY { - IAL_ADAPTER_T *pAdapter; - - pAdapter = base; - return (bus_space_read_4(pAdapter->mem_btag, pAdapter->mem_bsh, - offset)); -} + DEVICEID idArray; + DEVICEID idDisk; +} HPT_ADD_DISK_TO_ARRAY, *PHPT_ADD_DISK_TO_ARRAY; + +int check_VDevice_valid(PVDevice); +int hpt_default_ioctl(_VBUS_ARG DWORD, PVOID, DWORD, PVOID, DWORD, PDWORD); + +#define HPT_NULL_ID 0 + +#pragma pack() #endif diff --git a/sys/dev/hptmv/raid5n.h b/sys/dev/hptmv/raid5n.h index 07101c8f2650..135177a9bbbc 100644 --- a/sys/dev/hptmv/raid5n.h +++ b/sys/dev/hptmv/raid5n.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -110,12 +110,15 @@ struct r5_global_data { PUCHAR page_base_virt; PUCHAR page_current; #endif - struct free_heap_block *free_heap_slots[8]; + struct free_heap_block *free_heap_slots[10]; struct free_page *free_pages; UINT num_free_pages; UINT active_stripes; UINT num_flushing; PCommand cache_wait_list; + + LBA_T __start[MAX_MEMBERS]; + USHORT __sectors[MAX_MEMBERS]; }; diff --git a/sys/dev/hptmv/readme.txt b/sys/dev/hptmv/readme.txt index df03e97efe81..6d21e98c98b8 100644 --- a/sys/dev/hptmv/readme.txt +++ b/sys/dev/hptmv/readme.txt @@ -1,10 +1,14 @@ RocketRAID 182x Driver for FreeBSD -Copyright (C) 2003-2004 HighPoint Technologies, Inc. All rights reserved. +Copyright (C) 2004-2005 HighPoint Technologies, Inc. All rights reserved. $FreeBSD$ ############################################################################# Revision History: + v1.12 2005-6-10 + Fix over 4G memory support on amd64. + Fix disk flush problem. + v1.1 2004-9-23 Fix activity LED problem. Cleanup diagnostic code. @@ -36,22 +40,124 @@ Revision History: PRODUCT, INCLUDING THE COSTS OF REPAIRING, REPLACING, OR RECOVERING SUCH HARDWARE, OR DATA. -2. Build the driver ---------------------- + +2. Rebuild the kernel with RR182x support +-------------------------------------------- + 1) Install kernel source package and building tools. - 2) Extract the driver files to somewhere. + 2) Extract the driver files under the kernel source tree: + + # cd /usr/src/sys/ + # tar xvzf /your/path/to/rr182x-opensource-v1.12-bsd.tgz + + 3) Update the kernel configuration file to include the HighPoint source. + Assume the configure file is GENERIC, and new kernel configure file is + MYKERNEL: + + # cd i386/conf (or amd64/conf for AMD64) + # cp GENERIC MYKERNEL + + 4) Edit MYKERNEL, and add the following line under "RAID controllers + interfaced to the SCSI subsystem": + + device hptmv #HighPoint RocketRAID 182x - 3) Run "make" to build the driver. + 5) For i386 system, edit /usr/src/sys/conf/files.i386 and append the lines + shown below: + hptmvraid.o optional hptmv \ + dependency "$S/dev/hptmv/i386-elf.raid.o.uu" \ + compile-with "uudecode < $S/dev/hptmv/i386-elf.raid.o.uu" \ + no-implicit-rule + + dev/hptmv/gui_lib.c optional hptmv + dev/hptmv/hptproc.c optional hptmv + dev/hptmv/ioctl.c optional hptmv + dev/hptmv/entry.c optional hptmv + dev/hptmv/mv.c optional hptmv + + For amd64 system, edit /usr/src/sys/conf/files.amd64 and append the lines + shown below: + + hptmvraid.o optional hptmv \ + dependency "$S/dev/hptmv/amd64-elf.raid.o.uu" \ + compile-with "uudecode < $S/dev/hptmv/amd64-elf.raid.o.uu" \ + no-implicit-rule + + dev/hptmv/gui_lib.c optional hptmv + dev/hptmv/hptproc.c optional hptmv + dev/hptmv/ioctl.c optional hptmv + dev/hptmv/entry.c optional hptmv + dev/hptmv/mv.c optional hptmv + + Note FreeBSD 5.3/5.4 i386 already have a built-in RR182x driver, you should + replace the old configuration lines with the lines listed above. + + + 6) Rebuild and install the kernel: + + a) for FreeBSD 5.x-i386: -3. Using the driver ---------------------- - 1) Copy the driver module to /modules/ (FreeBSD 4.x) or /boot/kernel/ - (FreeBSD 5.x). - - 2) The driver can't be loaded by kldload command on a running system. - Please load the driver during system booting stage. e.g: + # cd /usr/src/sys/i386/conf/ + # /usr/sbin/config MYKERNEL + # cd ../compile/MYKERNEL/ + # make depend + # make + # make install + + b) for FreeBSD 5.x-amd64: + + # cd /usr/src/sys/amd64/conf/ + # /usr/sbin/config MYKERNEL + # cd ../compile/MYKERNEL/ + # make depend + # make + # make install + + c) for FreeBSD 4.x: + + # cd /usr/src/sys/i386/conf/ + # /usr/sbin/config MYKERNEL + # cd ../../compile/MYKERNEL/ + # make depend + # make + # make install + + If the driver was previously configured as an auto-loaded module by + /boot/defaults/loader.conf, please remove the entry hptmv_load="YES" + from loader.conf to prevent the driver from being loaded twice. + + 7) Reboot from the new kernel. + + +3. Build/Load the driver as a kernel module +------------------------------------------------ + + 1) Install kernel source package and building tools. + + 2) Extract the driver files under the kernel source tree: + + # cd /usr/src/sys/ + # tar xvzf /your/path/to/rr182x-opensource-v1.12-bsd.tgz + + + 4) Build the driver module: + + # cd modules/hptmv + # make + + 5) Copy the driver module to the kernel module directory + + For FreeBSD 4.x: + + # cp hptmv.ko /modules/ + + For FreeBSD 5.x: + + # cp hptmv.ko /boot/kernel/ + + 6) Reboot and load the driver under loader prompt. e.g: BTX loader 1.00 BTX version is 1.01 Console: internal video/keyboard @@ -71,11 +177,18 @@ Revision History: Type '?' for a list of commands, 'help' for more detailed help. ok load hptmv /modules/hptmv.ko text=0xf571 data=0x2c8+0x254 - ok autoboot + ok boot + + For FreeBSD 5.x, you can select 6 on the boot menu to get a loader prompt. - Please refer to the installation guide in HighPoint FreeBSD driver release - package for more information. - + 7) You can add a below line into /boot/defaults/loader.conf to load the + driver automatically: + + hptmv_load="YES" + + Please refer to the installation guide in HighPoint FreeBSD driver release + package for more information. + ############################################################################# Technical support and service diff --git a/sys/dev/hptmv/vdevice.h b/sys/dev/hptmv/vdevice.h index c9a613618548..8d06f1032109 100644 --- a/sys/dev/hptmv/vdevice.h +++ b/sys/dev/hptmv/vdevice.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003-2004 HighPoint Technologies, Inc. + * Copyright (c) 2004-2005 HighPoint Technologies, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -250,8 +250,8 @@ struct fdisk_partition_table UCHAR endhead; /* ending head number */ UCHAR endsect; /* ending sector number */ UCHAR endcyl; /* also a 10 bit nmbr, with same high 2 bit trick */ - UINT relsect; /* first sector relative to start of disk */ - UINT numsect; /* number of sectors in partition */ + ULONG relsect; /* first sector relative to start of disk */ + ULONG numsect; /* number of sectors in partition */ }; typedef struct _Master_Boot_Record diff --git a/sys/modules/Makefile b/sys/modules/Makefile index 42a2a4689dfb..e747dd476d43 100644 --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -434,6 +434,7 @@ _digi= digi _drm= drm _em= em _ext2fs= ext2fs +_hptmv= hptmv _i2c= i2c _ichwd= ichwd _ida= ida diff --git a/sys/modules/hptmv/Makefile b/sys/modules/hptmv/Makefile index 29c2e25a28c7..05ceac7bb1f6 100644 --- a/sys/modules/hptmv/Makefile +++ b/sys/modules/hptmv/Makefile @@ -1,6 +1,6 @@ # # Makefile for RR182x FreeBSD driver -# Copyright (c) 2003-2004 HighPoint Technologies, Inc. All rights reserved +# Copyright (c) 2004-2005 HighPoint Technologies, Inc. All rights reserved # # $FreeBSD$ @@ -10,12 +10,17 @@ HPTMV= ${.CURDIR}/../../dev/hptmv KMOD= hptmv SRCS= opt_scsi.h opt_cam.h SRCS+= bus_if.h device_if.h pci_if.h -SRCS+= mv.c entry.c -SRCS+= ioctl.c hptproc.c gui_lib.c +SRCS+= mv.c entry.c ioctl.c hptproc.c gui_lib.c OBJS+= hptmvraid.o -hptmvraid.o: ${HPTMV}/i386-elf.raid.o.uu - uudecode -p < ${HPTMV}/i386-elf.raid.o.uu > ${.TARGET} +.if $(MACHINE_ARCH) == "amd64" +HPTMV_RAID_O = amd64-elf.raid.o.uu +.else +HPTMV_RAID_O = i386-elf.raid.o.uu +.endif + +hptmvraid.o: ${HPTMV}/$(HPTMV_RAID_O) + uudecode -p < ${HPTMV}/$(HPTMV_RAID_O) > ${.TARGET} # # Debug Options: @@ -42,6 +47,6 @@ DEBUGOPT += -DDEBUG_LEVEL=1 DEBUGOPT += -DFOR_DEMO .endif -CFLAGS+= ${DEBUGOPT} - +CFLAGS = ${DEBUGOPT} + .include -- cgit v1.3