/* * Copyright (c) 2004-2005 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$ */ /* * 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 #ifndef __KERNEL__ #define __KERNEL__ #endif #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 int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo); static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam); static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 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); static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo); int check_VDevice_valid(PVDevice p) { int i; PVDevice pVDevice; PVBus _vbus_p; IAL_ADAPTER_T *pAdapter = gIal_Adapter; while(pAdapter != NULL) { 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 != NULL) { _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 UCHAR get_vdev_type(PVDevice pVDevice) { switch (pVDevice->VDeviceType) { case VD_RAID_0: return AT_RAID0; case VD_RAID_1: return AT_RAID1; case VD_JBOD: return AT_JBOD; case VD_RAID_5: return AT_RAID5; default: return AT_UNKNOWN; } } static DWORD get_array_flag(PVDevice pVDevice) { int i; DWORD f = 0; /* The array is disabled */ if(!pVDevice->vf_online) { f |= ARRAY_FLAG_DISABLED; /* Ignore other info */ return f; } /* array need synchronizing */ if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create) f |= ARRAY_FLAG_NEEDBUILDING; /* array is in rebuilding process */ if(pVDevice->u.array.rf_rebuilding) f |= ARRAY_FLAG_REBUILDING; /* array is being verified */ if(pVDevice->u.array.rf_verifying) f |= ARRAY_FLAG_VERIFYING; /* array is being initialized */ if(pVDevice->u.array.rf_initializing) f |= ARRAY_FLAG_INITIALIZING; /* broken but may still working */ if(pVDevice->u.array.rf_broken) f |= ARRAY_FLAG_BROKEN; /* array has a active partition */ if(pVDevice->vf_bootable) f |= ARRAY_FLAG_BOOTDISK; /* a newly created array */ if(pVDevice->u.array.rf_newly_created) f |= ARRAY_FLAG_NEWLY_CREATED; /* array has boot mark set */ if(pVDevice->vf_bootmark) f |= ARRAY_FLAG_BOOTMARK; /* auto-rebuild should start */ if(pVDevice->u.array.rf_auto_rebuild) f |= 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) f |= ARRAY_FLAG_NEEDBUILDING; /* array is in rebuilding process */ if(pMember->u.array.rf_rebuilding) f |= ARRAY_FLAG_REBUILDING; /* array is being verified */ if(pMember->u.array.rf_verifying) f |= ARRAY_FLAG_VERIFYING; /* array is being initialized */ if(pMember->u.array.rf_initializing) f |= ARRAY_FLAG_INITIALIZING; /* broken but may still working */ if(pMember->u.array.rf_broken) f |= ARRAY_FLAG_BROKEN; /* a newly created array */ if(pMember->u.array.rf_newly_created) f |= ARRAY_FLAG_NEWLY_CREATED; /* auto-rebuild should start */ if(pMember->u.array.rf_auto_rebuild) f |= ARRAY_FLAG_NEED_AUTOREBUILD; } return f; } static DWORD calc_rebuild_progress(PVDevice pVDevice) { int i; DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 / (ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10; 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; /* for RAID1/0 case */ if (pMember->u.array.rf_rebuilding || pMember->u.array.rf_verifying || pMember->u.array.rf_initializing) { DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 / (ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10; if (result==0 || result>percent) result = percent; } } if (result>10000) result = 10000; return result; } static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo) { int i; memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME); pArrayInfo->ArrayType = get_vdev_type(pVDevice); pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors; pArrayInfo->Flags = get_array_flag(pVDevice); pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice); pArrayInfo->nDisk = 0; for(i = 0; i < pVDevice->u.array.bArnMember; i++) if(pVDevice->u.array.pMember[i] != NULL) pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); for(i=pArrayInfo->nDisk; iMembers[i] = INVALID_DEVICEID; } static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo) { int i; memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN); pArrayInfo->ArrayType = get_vdev_type(pVDevice); pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors; pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0; pArrayInfo->Flags = get_array_flag(pVDevice); pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice); pArrayInfo->nDisk = 0; for(i = 0; i < pVDevice->u.array.bArnMember; i++) if(pVDevice->u.array.pMember[i] != NULL) pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); for(i=pArrayInfo->nDisk; iMembers[i] = INVALID_DEVICEID; } #endif static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo) { MV_SATA_ADAPTER *pSataAdapter; MV_SATA_CHANNEL *pSataChannel; IAL_ADAPTER_T *pAdapter; MV_CHANNEL *channelInfo; char *p; int i; /* device location */ pSataChannel = pVDevice->u.disk.mv; if(pSataChannel == NULL) return -1; pDiskInfo->TargetId = 0; pSataAdapter = pSataChannel->mvSataAdapter; if(pSataAdapter == NULL) return -1; pAdapter = pSataAdapter->IALData; pDiskInfo->PathId = pSataChannel->channelNumber; pDiskInfo->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) pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode; else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2) pDiskInfo->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'))) pDiskInfo->DeviceModeSetting = 15; else pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting; } pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode; pDiskInfo->DeviceType = PDT_HARDDISK; pDiskInfo->Flags = 0x0; /* device is disabled */ if(!pVDevice->u.disk.df_on_line) pDiskInfo->Flags |= DEVICE_FLAG_DISABLED; /* disk has a active partition */ if(pVDevice->vf_bootable) pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK; /* disk has boot mark set */ if(pVDevice->vf_bootmark) pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK; pDiskInfo->Flags |= DEVICE_FLAG_SATA; /* is a spare disk */ if(pVDevice->VDeviceType == VD_SPARE) pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE; memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2)); p = (char *)&pDiskInfo->IdentifyData.ModelNumber; for (i = 0; i < 20; i++) ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]); p[39] = '\0'; channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber]; pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported; pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled; pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported; pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled; pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0; pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED; pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) && (pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100)); pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING; return 0; } 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_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 #endif return 0; } int hpt_get_controller_count(void) { IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; int iControllerCount = 0; while(pAdapTemp != NULL) { iControllerCount++; pAdapTemp = pAdapTemp->next; } return iControllerCount; } 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 18xx SATA Controller"); pInfo->NumBuses = 8; pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150; return 0; } } return -1; } int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) { IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; int i,iControllerCount = 0; while(pAdapTemp != NULL) { 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; } 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; } int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) { PVDevice pVDevice = ID_TO_VDEV(id); if((id == 0) || check_VDevice_valid(pVDevice)) return -1; #ifdef SUPPORT_ARRAY if (mIsArray(pVDevice)) { pInfo->Type = LDT_ARRAY; pInfo->Capacity = pVDevice->VDeviceCapacity; pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); get_array_info(pVDevice, &pInfo->u.array); return 0; } #endif pInfo->Type = LDT_DEVICE; pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID; /* report real capacity to be compatible with old arrays */ pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity; return get_disk_info(pVDevice, &pInfo->u.device); } int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo) { PVDevice pVDevice = ID_TO_VDEV(id); if((id == 0) || check_VDevice_valid(pVDevice)) return -1; #ifdef SUPPORT_ARRAY if (mIsArray(pVDevice)) { pInfo->Type = LDT_ARRAY; pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity; pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0; pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); get_array_info_v2(pVDevice, &pInfo->u.array); return 0; } #endif pInfo->Type = LDT_DEVICE; pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID; /* report real capacity to be compatible with old arrays */ pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity; pInfo->Capacity.hi32 = 0; return get_disk_info(pVDevice, &pInfo->u.device); } #ifdef SUPPORT_ARRAY DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam) { ULONG Stamp = GetStamp(); int i,j; LBA_T capacity = MAX_LBA_T; PVDevice pArray,pChild; int Loca = -1; if (pParam->nDisk > MAX_MEMBERS) return INVALID_DEVICEID; /* check in verify_vd 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; } */ _vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus; 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 = rounddown2(capacity, pArray->u.array.bStripeWitch) * (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; } DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) { CREATE_ARRAY_PARAMS_V2 param2; param2.ArrayType = pParam->ArrayType; param2.nDisk = pParam->nDisk; param2.BlockSizeShift = pParam->BlockSizeShift; param2.CreateFlags = pParam->CreateFlags; param2.CreateTime = pParam->CreateTime; memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName)); memcpy(param2.Description, pParam->Description, sizeof(param2.Description)); memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager)); param2.Capacity.lo32 = param2.Capacity.hi32 = 0; memcpy(param2.Members, pParam->Members, sizeof(pParam->Members)); return hpt_create_array_v2(_VBUS_P ¶m2); } #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 (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 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; LBA_T Capacity; PVDevice pArray = ID_TO_VDEV(idArray); PVDevice pDisk = ID_TO_VDEV(idDisk); 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; 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 (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} for(i = 0; i < pArray->u.array.bArnMember; i++) if((pArray->u.array.pMember[i] == 0) || !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; } int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) { PVDevice pVDevice = ID_TO_VDEV(idDisk); DECLARE_BUFFER(PUCHAR, pbuffer); if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) return -1; if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 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; } 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 (pVDevice->u.disk.pVBus!=_vbus_p) return -1; pVDevice->VDeviceType = VD_SINGLE_DISK; SyncArrayInfo(pVDevice); RegisterVDevice(pVDevice); return 0; } int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) { PVDevice pVDevice = ID_TO_VDEV(idArray); 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 (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 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); if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; if (mIsArray(pVDevice)) return -1; if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; /* TODO */ return 0; } static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo) { PVDevice pVDevice = ID_TO_VDEV(idDisk); int sync = 0; if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1; if (mIsArray(pVDevice)) return -1; if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 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); sync = 1; } if (pInfo->ValidFields & ADIF_TCQ) { if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) { pVDevice->u.disk.df_tcq_set = 1; pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0; sync = 1; } } if (pInfo->ValidFields & ADIF_NCQ) { if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) { pVDevice->u.disk.df_ncq_set = 1; pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0; sync = 1; } } if (pInfo->ValidFields & ADIF_WRITE_CACHE) { if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) { pVDevice->u.disk.df_write_cache_set = 1; pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0; sync = 1; } } if (pInfo->ValidFields & ADIF_READ_AHEAD) { if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) { pVDevice->u.disk.df_read_ahead_set = 1; pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0; sync = 1; } } if (sync) SyncArrayInfo(pVDevice); 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; case HPT_IOCTL_GET_DEVICE_INFO_V2: { DEVICEID id; PLOGICAL_DEVICE_INFO_V2 pInfo; if (nInBufferSize!=sizeof(DEVICEID)) return -1; if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1; id = *(DWORD *)lpInBuffer; if (id == INVALID_DEVICEID) return -1; pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer; memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2)); if (hpt_get_device_info_v2(id, pInfo)!=0) return -1; } break; #ifdef SUPPORT_ARRAY case HPT_IOCTL_CREATE_ARRAY: { if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1; if (nOutBufferSize!=sizeof(DEVICEID)) return -1; *(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer); if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID) return -1; } break; case HPT_IOCTL_CREATE_ARRAY_V2: { if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1; if (nOutBufferSize!=sizeof(DEVICEID)) return -1; *(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer); if (*(DEVICEID *)lpOutBuffer == 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_DEVICE_INFO_V2: { DEVICEID idDisk; PALTERABLE_DEVICE_INFO_V2 pInfo; if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1; if (nOutBufferSize!=0) return -1; idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk; pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info; if(hpt_set_device_info_v2(_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_VDEVICE_PER_VBUS; i++) { if(!(pTop = pVBus->pVDevice[i])) continue; if (pTop->pVBus!=_vbus_p) return -1; 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; 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 (nOutBufferSizenext) if (iControllerCount++==id) break; if (!pAdapTemp) return -1; if (nOutBufferSize < 4) return -1; *(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB; return 0; } case HPT_IOCTL_EPROM_IO: { DWORD id = ((DWORD*)lpInBuffer)[0]; DWORD offset = ((DWORD*)lpInBuffer)[1]; DWORD direction = ((DWORD*)lpInBuffer)[2]; DWORD length = ((DWORD*)lpInBuffer)[3]; IAL_ADAPTER_T *pAdapTemp; int iControllerCount = 0; for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) if (iControllerCount++==id) break; if (!pAdapTemp) return -1; if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) || nOutBufferSize < (direction? 0 : length)) return -1; if (direction == 0) /* read */ sx508x_flash_access(&pAdapTemp->mvSataAdapter, offset, lpOutBuffer, length, 1); else sx508x_flash_access(&pAdapTemp->mvSataAdapter, offset, (char *)lpInBuffer + 16, length, 0); return 0; } break; default: return -1; } if (lpBytesReturned) *lpBytesReturned = nOutBufferSize; return 0; }