135878b55SSascha Wildner /* 235878b55SSascha Wildner * Copyright (c) 2004-2005 HighPoint Technologies, Inc. 335878b55SSascha Wildner * All rights reserved. 435878b55SSascha Wildner * 535878b55SSascha Wildner * Redistribution and use in source and binary forms, with or without 635878b55SSascha Wildner * modification, are permitted provided that the following conditions 735878b55SSascha Wildner * are met: 835878b55SSascha Wildner * 1. Redistributions of source code must retain the above copyright 935878b55SSascha Wildner * notice, this list of conditions and the following disclaimer. 1035878b55SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright 1135878b55SSascha Wildner * notice, this list of conditions and the following disclaimer in the 1235878b55SSascha Wildner * documentation and/or other materials provided with the distribution. 1335878b55SSascha Wildner * 1435878b55SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 1535878b55SSascha Wildner * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 1635878b55SSascha Wildner * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 1735878b55SSascha Wildner * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 1835878b55SSascha Wildner * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 1935878b55SSascha Wildner * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2035878b55SSascha Wildner * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2135878b55SSascha Wildner * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2235878b55SSascha Wildner * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2335878b55SSascha Wildner * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2435878b55SSascha Wildner * SUCH DAMAGE. 2535878b55SSascha Wildner * 2635878b55SSascha Wildner * $FreeBSD: src/sys/dev/hptmv/gui_lib.c,v 1.6 2009/04/07 16:38:25 delphij Exp $ 2735878b55SSascha Wildner */ 2835878b55SSascha Wildner /* 2935878b55SSascha Wildner * gui_lib.c 3035878b55SSascha Wildner * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved. 3135878b55SSascha Wildner * 3235878b55SSascha Wildner * Platform independent ioctl interface implementation. 3335878b55SSascha Wildner * The platform dependent part may reuse this function and/or use it own 3435878b55SSascha Wildner * implementation for each ioctl function. 3535878b55SSascha Wildner * 3635878b55SSascha Wildner * This implementation doesn't use any synchronization; the caller must 3735878b55SSascha Wildner * assure the proper context when calling these functions. 3835878b55SSascha Wildner */ 3935878b55SSascha Wildner 4035878b55SSascha Wildner #include <sys/param.h> 4135878b55SSascha Wildner #include <sys/systm.h> 4235878b55SSascha Wildner #include <sys/kernel.h> 4335878b55SSascha Wildner #include <sys/malloc.h> 4435878b55SSascha Wildner 4535878b55SSascha Wildner #ifndef __KERNEL__ 4635878b55SSascha Wildner #define __KERNEL__ 4735878b55SSascha Wildner #endif 4835878b55SSascha Wildner 4935878b55SSascha Wildner #include <dev/raid/hptmv/global.h> 5035878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h> 5135878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h> 5235878b55SSascha Wildner #include <dev/raid/hptmv/access601.h> 5335878b55SSascha Wildner 5435878b55SSascha Wildner static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap); 5535878b55SSascha Wildner static int hpt_get_controller_count(void); 5635878b55SSascha Wildner static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo); 5735878b55SSascha Wildner static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo); 5835878b55SSascha Wildner static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount); 5935878b55SSascha Wildner static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo); 6035878b55SSascha Wildner static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo); 6135878b55SSascha Wildner static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam); 6235878b55SSascha Wildner static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam); 6335878b55SSascha Wildner static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk); 6435878b55SSascha Wildner static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk); 6535878b55SSascha Wildner static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo); 6635878b55SSascha Wildner static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo); 6735878b55SSascha Wildner static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo); 6835878b55SSascha Wildner 6935878b55SSascha Wildner int 7035878b55SSascha Wildner check_VDevice_valid(PVDevice p) 7135878b55SSascha Wildner { 7235878b55SSascha Wildner int i; 7335878b55SSascha Wildner PVDevice pVDevice; 7435878b55SSascha Wildner PVBus _vbus_p; 7535878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = gIal_Adapter; 7635878b55SSascha Wildner 774090d6ffSSascha Wildner while(pAdapter != NULL) 7835878b55SSascha Wildner { 7935878b55SSascha Wildner for (i = 0; i < MV_SATA_CHANNELS_NUM; i++) 8035878b55SSascha Wildner if(&(pAdapter->VDevices[i]) == p) return 0; 8135878b55SSascha Wildner pAdapter = pAdapter->next; 8235878b55SSascha Wildner } 8335878b55SSascha Wildner 8435878b55SSascha Wildner #ifdef SUPPORT_ARRAY 8535878b55SSascha Wildner pAdapter = gIal_Adapter; 864090d6ffSSascha Wildner while(pAdapter != NULL) 8735878b55SSascha Wildner { 8835878b55SSascha Wildner _vbus_p = &pAdapter->VBus; 8935878b55SSascha Wildner for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 9035878b55SSascha Wildner { 9135878b55SSascha Wildner pVDevice=ArrayTables(i); 9235878b55SSascha Wildner if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p)) 9335878b55SSascha Wildner return 0; 9435878b55SSascha Wildner } 9535878b55SSascha Wildner pAdapter = pAdapter->next; 9635878b55SSascha Wildner } 9735878b55SSascha Wildner #endif 9835878b55SSascha Wildner 9935878b55SSascha Wildner return -1; 10035878b55SSascha Wildner } 10135878b55SSascha Wildner 10235878b55SSascha Wildner #ifdef SUPPORT_ARRAY 10335878b55SSascha Wildner 10435878b55SSascha Wildner static UCHAR get_vdev_type(PVDevice pVDevice) 10535878b55SSascha Wildner { 10635878b55SSascha Wildner switch (pVDevice->VDeviceType) { 10735878b55SSascha Wildner case VD_RAID_0: return AT_RAID0; 10835878b55SSascha Wildner case VD_RAID_1: return AT_RAID1; 10935878b55SSascha Wildner case VD_JBOD: return AT_JBOD; 11035878b55SSascha Wildner case VD_RAID_5: return AT_RAID5; 11135878b55SSascha Wildner default: return AT_UNKNOWN; 11235878b55SSascha Wildner } 11335878b55SSascha Wildner } 11435878b55SSascha Wildner 11535878b55SSascha Wildner static DWORD get_array_flag(PVDevice pVDevice) 11635878b55SSascha Wildner { 11735878b55SSascha Wildner int i; 11835878b55SSascha Wildner DWORD f = 0; 11935878b55SSascha Wildner 12035878b55SSascha Wildner /* The array is disabled */ 12135878b55SSascha Wildner if(!pVDevice->vf_online) { 12235878b55SSascha Wildner f |= ARRAY_FLAG_DISABLED; 12335878b55SSascha Wildner /* Ignore other info */ 12435878b55SSascha Wildner return f; 12535878b55SSascha Wildner } 12635878b55SSascha Wildner 12735878b55SSascha Wildner /* array need synchronizing */ 12835878b55SSascha Wildner if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create) 12935878b55SSascha Wildner f |= ARRAY_FLAG_NEEDBUILDING; 13035878b55SSascha Wildner 13135878b55SSascha Wildner /* array is in rebuilding process */ 13235878b55SSascha Wildner if(pVDevice->u.array.rf_rebuilding) 13335878b55SSascha Wildner f |= ARRAY_FLAG_REBUILDING; 13435878b55SSascha Wildner 13535878b55SSascha Wildner /* array is being verified */ 13635878b55SSascha Wildner if(pVDevice->u.array.rf_verifying) 13735878b55SSascha Wildner f |= ARRAY_FLAG_VERIFYING; 13835878b55SSascha Wildner 13935878b55SSascha Wildner /* array is being initialized */ 14035878b55SSascha Wildner if(pVDevice->u.array.rf_initializing) 14135878b55SSascha Wildner f |= ARRAY_FLAG_INITIALIZING; 14235878b55SSascha Wildner 14335878b55SSascha Wildner /* broken but may still working */ 14435878b55SSascha Wildner if(pVDevice->u.array.rf_broken) 14535878b55SSascha Wildner f |= ARRAY_FLAG_BROKEN; 14635878b55SSascha Wildner 14735878b55SSascha Wildner /* array has a active partition */ 14835878b55SSascha Wildner if(pVDevice->vf_bootable) 14935878b55SSascha Wildner f |= ARRAY_FLAG_BOOTDISK; 15035878b55SSascha Wildner 15135878b55SSascha Wildner /* a newly created array */ 15235878b55SSascha Wildner if(pVDevice->u.array.rf_newly_created) 15335878b55SSascha Wildner f |= ARRAY_FLAG_NEWLY_CREATED; 15435878b55SSascha Wildner 15535878b55SSascha Wildner /* array has boot mark set */ 15635878b55SSascha Wildner if(pVDevice->vf_bootmark) 15735878b55SSascha Wildner f |= ARRAY_FLAG_BOOTMARK; 15835878b55SSascha Wildner 15935878b55SSascha Wildner /* auto-rebuild should start */ 16035878b55SSascha Wildner if(pVDevice->u.array.rf_auto_rebuild) 16135878b55SSascha Wildner f |= ARRAY_FLAG_NEED_AUTOREBUILD; 16235878b55SSascha Wildner 16335878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) 16435878b55SSascha Wildner { 16535878b55SSascha Wildner PVDevice pMember = pVDevice->u.array.pMember[i]; 16635878b55SSascha Wildner if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK)) 16735878b55SSascha Wildner continue; 16835878b55SSascha Wildner 16935878b55SSascha Wildner /* array need synchronizing */ 17035878b55SSascha Wildner if(pMember->u.array.rf_need_rebuild && 17135878b55SSascha Wildner !pMember->u.array.rf_duplicate_and_create) 17235878b55SSascha Wildner f |= ARRAY_FLAG_NEEDBUILDING; 17335878b55SSascha Wildner 17435878b55SSascha Wildner /* array is in rebuilding process */ 17535878b55SSascha Wildner if(pMember->u.array.rf_rebuilding) 17635878b55SSascha Wildner f |= ARRAY_FLAG_REBUILDING; 17735878b55SSascha Wildner 17835878b55SSascha Wildner /* array is being verified */ 17935878b55SSascha Wildner if(pMember->u.array.rf_verifying) 18035878b55SSascha Wildner f |= ARRAY_FLAG_VERIFYING; 18135878b55SSascha Wildner 18235878b55SSascha Wildner /* array is being initialized */ 18335878b55SSascha Wildner if(pMember->u.array.rf_initializing) 18435878b55SSascha Wildner f |= ARRAY_FLAG_INITIALIZING; 18535878b55SSascha Wildner 18635878b55SSascha Wildner /* broken but may still working */ 18735878b55SSascha Wildner if(pMember->u.array.rf_broken) 18835878b55SSascha Wildner f |= ARRAY_FLAG_BROKEN; 18935878b55SSascha Wildner 19035878b55SSascha Wildner /* a newly created array */ 19135878b55SSascha Wildner if(pMember->u.array.rf_newly_created) 19235878b55SSascha Wildner f |= ARRAY_FLAG_NEWLY_CREATED; 19335878b55SSascha Wildner 19435878b55SSascha Wildner /* auto-rebuild should start */ 19535878b55SSascha Wildner if(pMember->u.array.rf_auto_rebuild) 19635878b55SSascha Wildner f |= ARRAY_FLAG_NEED_AUTOREBUILD; 19735878b55SSascha Wildner } 19835878b55SSascha Wildner 19935878b55SSascha Wildner return f; 20035878b55SSascha Wildner } 20135878b55SSascha Wildner 20235878b55SSascha Wildner static DWORD calc_rebuild_progress(PVDevice pVDevice) 20335878b55SSascha Wildner { 20435878b55SSascha Wildner int i; 20535878b55SSascha Wildner DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 / 20635878b55SSascha Wildner (ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10; 20735878b55SSascha Wildner 20835878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) 20935878b55SSascha Wildner { 21035878b55SSascha Wildner PVDevice pMember = pVDevice->u.array.pMember[i]; 21135878b55SSascha Wildner if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK)) 21235878b55SSascha Wildner continue; 21335878b55SSascha Wildner 21435878b55SSascha Wildner /* for RAID1/0 case */ 21535878b55SSascha Wildner if (pMember->u.array.rf_rebuilding || 21635878b55SSascha Wildner pMember->u.array.rf_verifying || 21735878b55SSascha Wildner pMember->u.array.rf_initializing) 21835878b55SSascha Wildner { 21935878b55SSascha Wildner DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 / 22035878b55SSascha Wildner (ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10; 22135878b55SSascha Wildner if (result==0 || result>percent) 22235878b55SSascha Wildner result = percent; 22335878b55SSascha Wildner } 22435878b55SSascha Wildner } 22535878b55SSascha Wildner 22635878b55SSascha Wildner if (result>10000) result = 10000; 22735878b55SSascha Wildner return result; 22835878b55SSascha Wildner } 22935878b55SSascha Wildner 23035878b55SSascha Wildner static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo) 23135878b55SSascha Wildner { 23235878b55SSascha Wildner int i; 23335878b55SSascha Wildner 23435878b55SSascha Wildner memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME); 23535878b55SSascha Wildner pArrayInfo->ArrayType = get_vdev_type(pVDevice); 23635878b55SSascha Wildner pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; 23735878b55SSascha Wildner pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors; 23835878b55SSascha Wildner pArrayInfo->Flags = get_array_flag(pVDevice); 23935878b55SSascha Wildner pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice); 24035878b55SSascha Wildner 24135878b55SSascha Wildner pArrayInfo->nDisk = 0; 24235878b55SSascha Wildner 24335878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) 24435878b55SSascha Wildner if(pVDevice->u.array.pMember[i] != NULL) 24535878b55SSascha Wildner pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); 24635878b55SSascha Wildner 24735878b55SSascha Wildner for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++) 24835878b55SSascha Wildner pArrayInfo->Members[i] = INVALID_DEVICEID; 24935878b55SSascha Wildner } 25035878b55SSascha Wildner 25135878b55SSascha Wildner static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo) 25235878b55SSascha Wildner { 25335878b55SSascha Wildner int i; 25435878b55SSascha Wildner 25535878b55SSascha Wildner memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN); 25635878b55SSascha Wildner pArrayInfo->ArrayType = get_vdev_type(pVDevice); 25735878b55SSascha Wildner pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; 25835878b55SSascha Wildner pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors; 25935878b55SSascha Wildner pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0; 26035878b55SSascha Wildner pArrayInfo->Flags = get_array_flag(pVDevice); 26135878b55SSascha Wildner pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice); 26235878b55SSascha Wildner 26335878b55SSascha Wildner pArrayInfo->nDisk = 0; 26435878b55SSascha Wildner 26535878b55SSascha Wildner for(i = 0; i < pVDevice->u.array.bArnMember; i++) 26635878b55SSascha Wildner if(pVDevice->u.array.pMember[i] != NULL) 26735878b55SSascha Wildner pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); 26835878b55SSascha Wildner 26935878b55SSascha Wildner for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++) 27035878b55SSascha Wildner pArrayInfo->Members[i] = INVALID_DEVICEID; 27135878b55SSascha Wildner } 27235878b55SSascha Wildner #endif 27335878b55SSascha Wildner 27435878b55SSascha Wildner static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo) 27535878b55SSascha Wildner { 27635878b55SSascha Wildner MV_SATA_ADAPTER *pSataAdapter; 27735878b55SSascha Wildner MV_SATA_CHANNEL *pSataChannel; 27835878b55SSascha Wildner IAL_ADAPTER_T *pAdapter; 27935878b55SSascha Wildner MV_CHANNEL *channelInfo; 28035878b55SSascha Wildner char *p; 28135878b55SSascha Wildner int i; 28235878b55SSascha Wildner 28335878b55SSascha Wildner /* device location */ 28435878b55SSascha Wildner pSataChannel = pVDevice->u.disk.mv; 28535878b55SSascha Wildner if(pSataChannel == NULL) return -1; 28635878b55SSascha Wildner pDiskInfo->TargetId = 0; 28735878b55SSascha Wildner pSataAdapter = pSataChannel->mvSataAdapter; 28835878b55SSascha Wildner if(pSataAdapter == NULL) return -1; 28935878b55SSascha Wildner 29035878b55SSascha Wildner pAdapter = pSataAdapter->IALData; 29135878b55SSascha Wildner 29235878b55SSascha Wildner pDiskInfo->PathId = pSataChannel->channelNumber; 29335878b55SSascha Wildner pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId; 29435878b55SSascha Wildner 29535878b55SSascha Wildner /*GUI uses DeviceModeSetting to display to users 29635878b55SSascha Wildner (1) if users select a mode, GUI/BIOS should display that mode. 29735878b55SSascha Wildner (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied. 29835878b55SSascha Wildner (3) display real mode if case (1)&&(2) not satisfied. 29935878b55SSascha Wildner */ 30035878b55SSascha Wildner if (pVDevice->u.disk.df_user_mode_set) 30135878b55SSascha Wildner pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode; 30235878b55SSascha Wildner else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2) 30335878b55SSascha Wildner pDiskInfo->DeviceModeSetting = 15; 30435878b55SSascha Wildner else { 30535878b55SSascha Wildner p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber; 30635878b55SSascha Wildner if (*(WORD*)p==(0x5354) /*'ST'*/ && 30735878b55SSascha Wildner (*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S'))) 30835878b55SSascha Wildner pDiskInfo->DeviceModeSetting = 15; 30935878b55SSascha Wildner else 31035878b55SSascha Wildner pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting; 31135878b55SSascha Wildner } 31235878b55SSascha Wildner 31335878b55SSascha Wildner pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode; 31435878b55SSascha Wildner 31535878b55SSascha Wildner pDiskInfo->DeviceType = PDT_HARDDISK; 31635878b55SSascha Wildner 31735878b55SSascha Wildner pDiskInfo->Flags = 0x0; 31835878b55SSascha Wildner 31935878b55SSascha Wildner /* device is disabled */ 32035878b55SSascha Wildner if(!pVDevice->u.disk.df_on_line) 32135878b55SSascha Wildner pDiskInfo->Flags |= DEVICE_FLAG_DISABLED; 32235878b55SSascha Wildner 32335878b55SSascha Wildner /* disk has a active partition */ 32435878b55SSascha Wildner if(pVDevice->vf_bootable) 32535878b55SSascha Wildner pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK; 32635878b55SSascha Wildner 32735878b55SSascha Wildner /* disk has boot mark set */ 32835878b55SSascha Wildner if(pVDevice->vf_bootmark) 32935878b55SSascha Wildner pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK; 33035878b55SSascha Wildner 33135878b55SSascha Wildner pDiskInfo->Flags |= DEVICE_FLAG_SATA; 33235878b55SSascha Wildner 33335878b55SSascha Wildner /* is a spare disk */ 33435878b55SSascha Wildner if(pVDevice->VDeviceType == VD_SPARE) 33535878b55SSascha Wildner pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE; 33635878b55SSascha Wildner 33735878b55SSascha Wildner memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2)); 33835878b55SSascha Wildner p = (char *)&pDiskInfo->IdentifyData.ModelNumber; 33935878b55SSascha Wildner for (i = 0; i < 20; i++) 34035878b55SSascha Wildner ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]); 34135878b55SSascha Wildner p[39] = '\0'; 34235878b55SSascha Wildner 34335878b55SSascha Wildner channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber]; 34435878b55SSascha Wildner pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported; 34535878b55SSascha Wildner pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled; 34635878b55SSascha Wildner pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported; 34735878b55SSascha Wildner pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled; 34835878b55SSascha Wildner pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0; 34935878b55SSascha Wildner pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED; 35035878b55SSascha Wildner pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) && 35135878b55SSascha Wildner (pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100)); 35235878b55SSascha Wildner pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING; 35335878b55SSascha Wildner return 0; 35435878b55SSascha Wildner } 35535878b55SSascha Wildner 356*8406cf70SSascha Wildner static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) 35735878b55SSascha Wildner { 35835878b55SSascha Wildner ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES)); 35935878b55SSascha Wildner cap->dwSize = sizeof(DRIVER_CAPABILITIES); 36035878b55SSascha Wildner cap->MaximumControllers = MAX_VBUS; 36135878b55SSascha Wildner 36235878b55SSascha Wildner /* cap->SupportCrossControllerRAID = 0; */ 36335878b55SSascha Wildner /* take care for various OSes! */ 36435878b55SSascha Wildner cap->SupportCrossControllerRAID = 0; 36535878b55SSascha Wildner 36635878b55SSascha Wildner 36735878b55SSascha Wildner cap->MinimumBlockSizeShift = MinBlockSizeShift; 36835878b55SSascha Wildner cap->MaximumBlockSizeShift = MaxBlockSizeShift; 36935878b55SSascha Wildner cap->SupportDiskModeSetting = 0; 37035878b55SSascha Wildner cap->SupportSparePool = 1; 37135878b55SSascha Wildner cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1; 37235878b55SSascha Wildner cap->SupportDedicatedSpare = 0; 37335878b55SSascha Wildner 37435878b55SSascha Wildner 37535878b55SSascha Wildner #ifdef SUPPORT_ARRAY 37635878b55SSascha Wildner /* Stripe */ 37735878b55SSascha Wildner cap->SupportedRAIDTypes[0] = AT_RAID0; 37835878b55SSascha Wildner cap->MaximumArrayMembers[0] = MAX_MEMBERS; 37935878b55SSascha Wildner /* Mirror */ 38035878b55SSascha Wildner cap->SupportedRAIDTypes[1] = AT_RAID1; 38135878b55SSascha Wildner cap->MaximumArrayMembers[1] = 2; 38235878b55SSascha Wildner /* Mirror + Stripe */ 38335878b55SSascha Wildner #ifdef ARRAY_V2_ONLY 38435878b55SSascha Wildner cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */ 38535878b55SSascha Wildner #else 38635878b55SSascha Wildner cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */ 38735878b55SSascha Wildner #endif 38835878b55SSascha Wildner cap->MaximumArrayMembers[2] = MAX_MEMBERS; 38935878b55SSascha Wildner /* Jbod */ 39035878b55SSascha Wildner cap->SupportedRAIDTypes[3] = AT_JBOD; 39135878b55SSascha Wildner cap->MaximumArrayMembers[3] = MAX_MEMBERS; 39235878b55SSascha Wildner /* RAID5 */ 39335878b55SSascha Wildner #if SUPPORT_RAID5 39435878b55SSascha Wildner cap->SupportedRAIDTypes[4] = AT_RAID5; 39535878b55SSascha Wildner cap->MaximumArrayMembers[4] = MAX_MEMBERS; 39635878b55SSascha Wildner #endif 39735878b55SSascha Wildner #endif 39835878b55SSascha Wildner return 0; 39935878b55SSascha Wildner } 40035878b55SSascha Wildner 401*8406cf70SSascha Wildner static int hpt_get_controller_count(void) 40235878b55SSascha Wildner { 40335878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; 40435878b55SSascha Wildner int iControllerCount = 0; 40535878b55SSascha Wildner 4064090d6ffSSascha Wildner while(pAdapTemp != NULL) 40735878b55SSascha Wildner { 40835878b55SSascha Wildner iControllerCount++; 40935878b55SSascha Wildner pAdapTemp = pAdapTemp->next; 41035878b55SSascha Wildner } 41135878b55SSascha Wildner 41235878b55SSascha Wildner return iControllerCount; 41335878b55SSascha Wildner } 41435878b55SSascha Wildner 415*8406cf70SSascha Wildner static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) 41635878b55SSascha Wildner { 41735878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 41835878b55SSascha Wildner int iControllerCount = 0; 41935878b55SSascha Wildner 42035878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 42135878b55SSascha Wildner if (iControllerCount++==id) { 42235878b55SSascha Wildner pInfo->InterruptLevel = 0; 42335878b55SSascha Wildner pInfo->ChipType = 0; 42435878b55SSascha Wildner pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100; 42535878b55SSascha Wildner strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc."); 42635878b55SSascha Wildner #ifdef GUI_CONTROLLER_NAME 42735878b55SSascha Wildner #ifdef FORCE_ATA150_DISPLAY 42835878b55SSascha Wildner /* show "Bus Type: ATA/150" in GUI for SATA controllers */ 42935878b55SSascha Wildner pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150; 43035878b55SSascha Wildner #endif 43135878b55SSascha Wildner strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME); 43235878b55SSascha Wildner #define _set_product_id(x) 43335878b55SSascha Wildner #else 43435878b55SSascha Wildner #define _set_product_id(x) strcpy(pInfo->szProductID, x) 43535878b55SSascha Wildner #endif 43635878b55SSascha Wildner _set_product_id("RocketRAID 18xx SATA Controller"); 43735878b55SSascha Wildner pInfo->NumBuses = 8; 43835878b55SSascha Wildner pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150; 43935878b55SSascha Wildner return 0; 44035878b55SSascha Wildner } 44135878b55SSascha Wildner } 44235878b55SSascha Wildner return -1; 44335878b55SSascha Wildner } 44435878b55SSascha Wildner 44535878b55SSascha Wildner 446*8406cf70SSascha Wildner static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) 44735878b55SSascha Wildner { 44835878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; 44935878b55SSascha Wildner int i,iControllerCount = 0; 45035878b55SSascha Wildner 4514090d6ffSSascha Wildner while(pAdapTemp != NULL) 45235878b55SSascha Wildner { 45335878b55SSascha Wildner if (iControllerCount++==id) 45435878b55SSascha Wildner goto found; 45535878b55SSascha Wildner pAdapTemp = pAdapTemp->next; 45635878b55SSascha Wildner } 45735878b55SSascha Wildner return -1; 45835878b55SSascha Wildner 45935878b55SSascha Wildner found: 46035878b55SSascha Wildner 46135878b55SSascha Wildner pInfo->IoPort = 0; 46235878b55SSascha Wildner pInfo->ControlPort = 0; 46335878b55SSascha Wildner 46435878b55SSascha Wildner for (i=0; i<2 ;i++) 46535878b55SSascha Wildner { 46635878b55SSascha Wildner pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID; 46735878b55SSascha Wildner } 46835878b55SSascha Wildner 46935878b55SSascha Wildner if (pAdapTemp->mvChannel[bus].online == MV_TRUE) 47035878b55SSascha Wildner pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]); 47135878b55SSascha Wildner else 47235878b55SSascha Wildner pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID; 47335878b55SSascha Wildner 47435878b55SSascha Wildner return 0; 47535878b55SSascha Wildner 47635878b55SSascha Wildner 47735878b55SSascha Wildner } 47835878b55SSascha Wildner 479*8406cf70SSascha Wildner static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 48035878b55SSascha Wildner { 48135878b55SSascha Wildner int count = 0; 48235878b55SSascha Wildner int i,j; 48335878b55SSascha Wildner PVDevice pPhysical, pLogical; 48435878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 48535878b55SSascha Wildner 48635878b55SSascha Wildner for(i = 0; i < nMaxCount; i++) 48735878b55SSascha Wildner pIds[i] = INVALID_DEVICEID; 48835878b55SSascha Wildner 48935878b55SSascha Wildner /* append the arrays not registered on VBus */ 49035878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 49135878b55SSascha Wildner for(i = 0; i < MV_SATA_CHANNELS_NUM; i++) 49235878b55SSascha Wildner { 49335878b55SSascha Wildner pPhysical = &pAdapTemp->VDevices[i]; 49435878b55SSascha Wildner pLogical = pPhysical; 49535878b55SSascha Wildner 49635878b55SSascha Wildner while (pLogical->pParent) pLogical = pLogical->pParent; 49735878b55SSascha Wildner if (pLogical->VDeviceType==VD_SPARE) 49835878b55SSascha Wildner continue; 49935878b55SSascha Wildner 50035878b55SSascha Wildner for (j=0; j<count; j++) 50135878b55SSascha Wildner if (pIds[j]==VDEV_TO_ID(pLogical)) goto next; 50235878b55SSascha Wildner pIds[count++] = VDEV_TO_ID(pLogical); 50335878b55SSascha Wildner if (count>=nMaxCount) goto done; 50435878b55SSascha Wildner next:; 50535878b55SSascha Wildner } 50635878b55SSascha Wildner } 50735878b55SSascha Wildner 50835878b55SSascha Wildner done: 50935878b55SSascha Wildner return count; 51035878b55SSascha Wildner } 51135878b55SSascha Wildner 512*8406cf70SSascha Wildner static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) 51335878b55SSascha Wildner { 51435878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(id); 51535878b55SSascha Wildner 51635878b55SSascha Wildner if((id == 0) || check_VDevice_valid(pVDevice)) 51735878b55SSascha Wildner return -1; 51835878b55SSascha Wildner 51935878b55SSascha Wildner #ifdef SUPPORT_ARRAY 52035878b55SSascha Wildner if (mIsArray(pVDevice)) { 52135878b55SSascha Wildner pInfo->Type = LDT_ARRAY; 52235878b55SSascha Wildner pInfo->Capacity = pVDevice->VDeviceCapacity; 52335878b55SSascha Wildner pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); 52435878b55SSascha Wildner get_array_info(pVDevice, &pInfo->u.array); 52535878b55SSascha Wildner return 0; 52635878b55SSascha Wildner } 52735878b55SSascha Wildner #endif 52835878b55SSascha Wildner 52935878b55SSascha Wildner pInfo->Type = LDT_DEVICE; 53035878b55SSascha Wildner pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID; 53135878b55SSascha Wildner /* report real capacity to be compatible with old arrays */ 53235878b55SSascha Wildner pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity; 53335878b55SSascha Wildner return get_disk_info(pVDevice, &pInfo->u.device); 53435878b55SSascha Wildner } 53535878b55SSascha Wildner 536*8406cf70SSascha Wildner static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo) 53735878b55SSascha Wildner { 53835878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(id); 53935878b55SSascha Wildner 54035878b55SSascha Wildner if((id == 0) || check_VDevice_valid(pVDevice)) 54135878b55SSascha Wildner return -1; 54235878b55SSascha Wildner 54335878b55SSascha Wildner #ifdef SUPPORT_ARRAY 54435878b55SSascha Wildner if (mIsArray(pVDevice)) { 54535878b55SSascha Wildner pInfo->Type = LDT_ARRAY; 54635878b55SSascha Wildner pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity; 54735878b55SSascha Wildner pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0; 54835878b55SSascha Wildner pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); 54935878b55SSascha Wildner get_array_info_v2(pVDevice, &pInfo->u.array); 55035878b55SSascha Wildner return 0; 55135878b55SSascha Wildner } 55235878b55SSascha Wildner #endif 55335878b55SSascha Wildner 55435878b55SSascha Wildner pInfo->Type = LDT_DEVICE; 55535878b55SSascha Wildner pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID; 55635878b55SSascha Wildner /* report real capacity to be compatible with old arrays */ 55735878b55SSascha Wildner pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity; 55835878b55SSascha Wildner pInfo->Capacity.hi32 = 0; 55935878b55SSascha Wildner return get_disk_info(pVDevice, &pInfo->u.device); 56035878b55SSascha Wildner } 56135878b55SSascha Wildner 56235878b55SSascha Wildner #ifdef SUPPORT_ARRAY 563*8406cf70SSascha Wildner static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam) 56435878b55SSascha Wildner { 56535878b55SSascha Wildner ULONG Stamp = GetStamp(); 56635878b55SSascha Wildner int i,j; 56735878b55SSascha Wildner LBA_T capacity = MAX_LBA_T; 56835878b55SSascha Wildner PVDevice pArray,pChild; 56935878b55SSascha Wildner int Loca = -1; 57035878b55SSascha Wildner 57135878b55SSascha Wildner if (pParam->nDisk > MAX_MEMBERS) 57235878b55SSascha Wildner return INVALID_DEVICEID; 57335878b55SSascha Wildner /* check in verify_vd 57435878b55SSascha Wildner for(i = 0; i < pParam->nDisk; i++) 57535878b55SSascha Wildner { 57635878b55SSascha Wildner PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]); 57735878b55SSascha Wildner if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID; 57835878b55SSascha Wildner if (mIsArray(pVDev)) return INVALID_DEVICEID; 57935878b55SSascha Wildner if (!pVDev->vf_online) return INVALID_DEVICEID; 58035878b55SSascha Wildner if (!_vbus_p) 58135878b55SSascha Wildner _vbus_p = pVDev->u.disk.pVBus; 58235878b55SSascha Wildner else if (_vbus_p != pVDev->u.disk.pVBus) 58335878b55SSascha Wildner return INVALID_DEVICEID; 58435878b55SSascha Wildner } 58535878b55SSascha Wildner */ 58635878b55SSascha Wildner _vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus; 58735878b55SSascha Wildner if (!_vbus_p) return INVALID_DEVICEID; 58835878b55SSascha Wildner 58935878b55SSascha Wildner mArGetArrayTable(pArray); 59035878b55SSascha Wildner if(!pArray) return INVALID_DEVICEID; 59135878b55SSascha Wildner 59235878b55SSascha Wildner switch (pParam->ArrayType) 59335878b55SSascha Wildner { 59435878b55SSascha Wildner case AT_JBOD: 59535878b55SSascha Wildner pArray->VDeviceType = VD_JBOD; 59635878b55SSascha Wildner goto simple; 59735878b55SSascha Wildner 59835878b55SSascha Wildner case AT_RAID0: 59935878b55SSascha Wildner if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) 60035878b55SSascha Wildner goto error; 60135878b55SSascha Wildner pArray->VDeviceType = VD_RAID_0; 60235878b55SSascha Wildner goto simple; 60335878b55SSascha Wildner 60435878b55SSascha Wildner case AT_RAID5: 60535878b55SSascha Wildner if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) 60635878b55SSascha Wildner goto error; 60735878b55SSascha Wildner pArray->VDeviceType = VD_RAID_5; 60835878b55SSascha Wildner /* only "no build" R5 is not critical after creation. */ 60935878b55SSascha Wildner if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0) 61035878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 1; 61135878b55SSascha Wildner goto simple; 61235878b55SSascha Wildner 61335878b55SSascha Wildner case AT_RAID1: 61435878b55SSascha Wildner if(pParam->nDisk <= 2) 61535878b55SSascha Wildner { 61635878b55SSascha Wildner pArray->VDeviceType = VD_RAID_1; 61735878b55SSascha Wildner simple: 61835878b55SSascha Wildner pArray->u.array.bArnMember = pParam->nDisk; 61935878b55SSascha Wildner pArray->u.array.bArRealnMember = pParam->nDisk; 62035878b55SSascha Wildner pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; 62135878b55SSascha Wildner pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); 62235878b55SSascha Wildner pArray->u.array.dArStamp = Stamp; 62335878b55SSascha Wildner 62435878b55SSascha Wildner pArray->u.array.rf_need_sync = 1; 62535878b55SSascha Wildner pArray->u.array.rf_newly_created = 1; 62635878b55SSascha Wildner 62735878b55SSascha Wildner if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 62835878b55SSascha Wildner (pArray->VDeviceType == VD_RAID_1)) 62935878b55SSascha Wildner { 63035878b55SSascha Wildner pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */ 63135878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 1; 63235878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 1; 63335878b55SSascha Wildner pArray->u.array.rf_duplicate_and_create = 1; 63435878b55SSascha Wildner 63535878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) 63635878b55SSascha Wildner if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0])) 63735878b55SSascha Wildner Loca = i; 63835878b55SSascha Wildner } 63935878b55SSascha Wildner 64035878b55SSascha Wildner pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T; 64135878b55SSascha Wildner 64235878b55SSascha Wildner memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 64335878b55SSascha Wildner 64435878b55SSascha Wildner for(i = 0; i < pParam->nDisk; i++) 64535878b55SSascha Wildner { 64635878b55SSascha Wildner pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]); 64735878b55SSascha Wildner pArray->u.array.pMember[i]->bSerialNumber = i; 64835878b55SSascha Wildner pArray->u.array.pMember[i]->pParent = pArray; 64935878b55SSascha Wildner 65035878b55SSascha Wildner /* don't unregister source disk for duplicate RAID1 */ 65135878b55SSascha Wildner if (i || 65235878b55SSascha Wildner pArray->VDeviceType!=VD_RAID_1 || 65335878b55SSascha Wildner (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0) 65435878b55SSascha Wildner UnregisterVDevice(pArray->u.array.pMember[i]); 65535878b55SSascha Wildner 65635878b55SSascha Wildner if(pArray->VDeviceType == VD_RAID_5) 65735878b55SSascha Wildner pArray->u.array.pMember[i]->vf_cache_disk = 1; 65835878b55SSascha Wildner } 65935878b55SSascha Wildner } 66035878b55SSascha Wildner else 66135878b55SSascha Wildner { 66235878b55SSascha Wildner for(i = 0; i < (pParam->nDisk / 2); i++) 66335878b55SSascha Wildner { 66435878b55SSascha Wildner mArGetArrayTable(pChild); 66535878b55SSascha Wildner pChild->VDeviceType = VD_RAID_1; 66635878b55SSascha Wildner 66735878b55SSascha Wildner pChild->u.array.bArnMember = 2; 66835878b55SSascha Wildner pChild->u.array.bArRealnMember = 2; 66935878b55SSascha Wildner pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift; 67035878b55SSascha Wildner pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); 67135878b55SSascha Wildner pChild->u.array.dArStamp = Stamp; 67235878b55SSascha Wildner 67335878b55SSascha Wildner pChild->u.array.rf_need_sync = 1; 67435878b55SSascha Wildner pChild->u.array.rf_newly_created = 1; 67535878b55SSascha Wildner 67635878b55SSascha Wildner pChild->u.array.RebuildSectors = MAX_LBA_T; 67735878b55SSascha Wildner 67835878b55SSascha Wildner memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 67935878b55SSascha Wildner 68035878b55SSascha Wildner for(j = 0; j < 2; j++) 68135878b55SSascha Wildner { 68235878b55SSascha Wildner pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]); 68335878b55SSascha Wildner pChild->u.array.pMember[j]->bSerialNumber = j; 68435878b55SSascha Wildner pChild->u.array.pMember[j]->pParent = pChild; 68535878b55SSascha Wildner pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType]; 68635878b55SSascha Wildner UnregisterVDevice(pChild->u.array.pMember[j]); 68735878b55SSascha Wildner } 68835878b55SSascha Wildner 68935878b55SSascha Wildner pArray->u.array.pMember[i] = pChild; 69035878b55SSascha Wildner 69135878b55SSascha Wildner pChild->vf_online = 1; 69235878b55SSascha Wildner pChild->bSerialNumber = i; 69335878b55SSascha Wildner pChild->pParent = pArray; 69435878b55SSascha Wildner pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity, 69535878b55SSascha Wildner pChild->u.array.pMember[1]->VDeviceCapacity); 69635878b55SSascha Wildner 69735878b55SSascha Wildner pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType]; 69835878b55SSascha Wildner pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0]; 69935878b55SSascha Wildner } 70035878b55SSascha Wildner 70135878b55SSascha Wildner pArray->VDeviceType = VD_RAID_0; 70235878b55SSascha Wildner 70335878b55SSascha Wildner pArray->u.array.bArnMember = pParam->nDisk / 2; 70435878b55SSascha Wildner pArray->u.array.bArRealnMember = pParam->nDisk / 2; 70535878b55SSascha Wildner pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift; 70635878b55SSascha Wildner pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift); 70735878b55SSascha Wildner pArray->u.array.dArStamp = Stamp; 70835878b55SSascha Wildner 70935878b55SSascha Wildner pArray->u.array.rf_need_sync = 1; 71035878b55SSascha Wildner pArray->u.array.rf_newly_created = 1; 71135878b55SSascha Wildner 71235878b55SSascha Wildner memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 71335878b55SSascha Wildner } 71435878b55SSascha Wildner break; 71535878b55SSascha Wildner 71635878b55SSascha Wildner default: 71735878b55SSascha Wildner goto error; 71835878b55SSascha Wildner } 71935878b55SSascha Wildner 72035878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 72135878b55SSascha Wildner pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; 72235878b55SSascha Wildner 72335878b55SSascha Wildner if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 72435878b55SSascha Wildner (pArray->VDeviceType == VD_RAID_1)) 72535878b55SSascha Wildner { 72635878b55SSascha Wildner pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark; 72735878b55SSascha Wildner pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable; 72835878b55SSascha Wildner pArray->u.array.pMember[0]->vf_bootable = 0; 72935878b55SSascha Wildner pArray->u.array.pMember[0]->vf_bootmark = 0; 73035878b55SSascha Wildner if (Loca>=0) { 73135878b55SSascha Wildner _vbus_p->pVDevice[Loca] = pArray; 73235878b55SSascha Wildner /* to comfort OS */ 73335878b55SSascha Wildner pArray->u.array.rf_duplicate_and_created = 1; 73435878b55SSascha Wildner pArray->pVBus = _vbus_p; 73535878b55SSascha Wildner } 73635878b55SSascha Wildner } 73735878b55SSascha Wildner else { 73835878b55SSascha Wildner UCHAR TempBuffer[512]; 73935878b55SSascha Wildner ZeroMemory(TempBuffer, 512); 74035878b55SSascha Wildner for(i = 0; i < pParam->nDisk; i++) 74135878b55SSascha Wildner { 74235878b55SSascha Wildner PVDevice pDisk = ID_TO_VDEV(pParam->Members[i]); 74335878b55SSascha Wildner pDisk->vf_bootmark = pDisk->vf_bootable = 0; 74435878b55SSascha Wildner fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer); 74535878b55SSascha Wildner } 74635878b55SSascha Wildner } 74735878b55SSascha Wildner 74835878b55SSascha Wildner pArray->vf_online = 1; 74935878b55SSascha Wildner pArray->pParent = NULL; 75035878b55SSascha Wildner 75135878b55SSascha Wildner switch(pArray->VDeviceType) 75235878b55SSascha Wildner { 75335878b55SSascha Wildner case VD_RAID_0: 75435878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 75535878b55SSascha Wildner if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) 75635878b55SSascha Wildner capacity = pArray->u.array.pMember[i]->VDeviceCapacity; 75735878b55SSascha Wildner #ifdef ARRAY_V2_ONLY 75835878b55SSascha Wildner capacity -= 10; 75935878b55SSascha Wildner #endif 76035878b55SSascha Wildner capacity &= ~(pArray->u.array.bStripeWitch - 1); 76135878b55SSascha Wildner /* shrink member capacity for RAID 1/0 */ 76235878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 76335878b55SSascha Wildner if (mIsArray(pArray->u.array.pMember[i])) 76435878b55SSascha Wildner pArray->u.array.pMember[i]->VDeviceCapacity = capacity; 76535878b55SSascha Wildner pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember; 76635878b55SSascha Wildner break; 76735878b55SSascha Wildner 76835878b55SSascha Wildner case VD_RAID_1: 76935878b55SSascha Wildner pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity, 77035878b55SSascha Wildner pArray->u.array.pMember[1]->VDeviceCapacity); 77135878b55SSascha Wildner break; 77235878b55SSascha Wildner 77335878b55SSascha Wildner case VD_JBOD: 77435878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 77535878b55SSascha Wildner pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity 77635878b55SSascha Wildner #ifdef ARRAY_V2_ONLY 77735878b55SSascha Wildner -10 77835878b55SSascha Wildner #endif 77935878b55SSascha Wildner ; 78035878b55SSascha Wildner break; 78135878b55SSascha Wildner 78235878b55SSascha Wildner case VD_RAID_5: 78335878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 78435878b55SSascha Wildner if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity) 78535878b55SSascha Wildner capacity = pArray->u.array.pMember[i]->VDeviceCapacity; 78635878b55SSascha Wildner pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1)) 78735878b55SSascha Wildner * (pArray->u.array.bArnMember - 1); 78835878b55SSascha Wildner break; 78935878b55SSascha Wildner 79035878b55SSascha Wildner default: 79135878b55SSascha Wildner goto error; 79235878b55SSascha Wildner } 79335878b55SSascha Wildner 79435878b55SSascha Wildner pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType]; 79535878b55SSascha Wildner pArray->pfnDeviceFailed = fOsDiskFailed; 79635878b55SSascha Wildner SyncArrayInfo(pArray); 79735878b55SSascha Wildner 79835878b55SSascha Wildner if (!pArray->u.array.rf_duplicate_and_created) 79935878b55SSascha Wildner RegisterVDevice(pArray); 80035878b55SSascha Wildner return VDEV_TO_ID(pArray); 80135878b55SSascha Wildner 80235878b55SSascha Wildner error: 80335878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 80435878b55SSascha Wildner { 80535878b55SSascha Wildner pChild = pArray->u.array.pMember[i]; 80635878b55SSascha Wildner if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK)) 80735878b55SSascha Wildner mArFreeArrayTable(pChild); 80835878b55SSascha Wildner } 80935878b55SSascha Wildner mArFreeArrayTable(pArray); 81035878b55SSascha Wildner return INVALID_DEVICEID; 81135878b55SSascha Wildner } 81235878b55SSascha Wildner 813*8406cf70SSascha Wildner static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) 81435878b55SSascha Wildner { 81535878b55SSascha Wildner CREATE_ARRAY_PARAMS_V2 param2; 81635878b55SSascha Wildner param2.ArrayType = pParam->ArrayType; 81735878b55SSascha Wildner param2.nDisk = pParam->nDisk; 81835878b55SSascha Wildner param2.BlockSizeShift = pParam->BlockSizeShift; 81935878b55SSascha Wildner param2.CreateFlags = pParam->CreateFlags; 82035878b55SSascha Wildner param2.CreateTime = pParam->CreateTime; 82135878b55SSascha Wildner memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName)); 82235878b55SSascha Wildner memcpy(param2.Description, pParam->Description, sizeof(param2.Description)); 82335878b55SSascha Wildner memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager)); 82435878b55SSascha Wildner param2.Capacity.lo32 = param2.Capacity.hi32 = 0; 82535878b55SSascha Wildner memcpy(param2.Members, pParam->Members, sizeof(pParam->Members)); 82635878b55SSascha Wildner return hpt_create_array_v2(_VBUS_P ¶m2); 82735878b55SSascha Wildner } 82835878b55SSascha Wildner 82935878b55SSascha Wildner #ifdef SUPPORT_OLD_ARRAY 83035878b55SSascha Wildner /* this is only for old RAID 0/1 */ 83135878b55SSascha Wildner int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) 83235878b55SSascha Wildner { 83335878b55SSascha Wildner PVDevice pArray1 = ID_TO_VDEV(idArray); 83435878b55SSascha Wildner PVDevice pArray2 = 0; 83535878b55SSascha Wildner PVDevice pDisk = ID_TO_VDEV(idDisk); 83635878b55SSascha Wildner int i; 83735878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = gIal_Adapter; 83835878b55SSascha Wildner 83935878b55SSascha Wildner if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 84035878b55SSascha Wildner 84135878b55SSascha Wildner if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2)) 84235878b55SSascha Wildner return -1; 84335878b55SSascha Wildner 84435878b55SSascha Wildner pArray2 = pArray1->u.array.pMember[1]; 84535878b55SSascha Wildner if(pArray2 == NULL) { 84635878b55SSascha Wildner /* create a Stripe */ 84735878b55SSascha Wildner mArGetArrayTable(pArray2); 84835878b55SSascha Wildner pArray2->VDeviceType = VD_RAID_0; 84935878b55SSascha Wildner pArray2->u.array.dArStamp = GetStamp(); 85035878b55SSascha Wildner pArray2->vf_format_v2 = 1; 85135878b55SSascha Wildner pArray2->u.array.rf_broken = 1; 85235878b55SSascha Wildner pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift; 85335878b55SSascha Wildner pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift); 85435878b55SSascha Wildner pArray2->u.array.bArnMember = 2; 85535878b55SSascha Wildner pArray2->VDeviceCapacity = pArray1->VDeviceCapacity; 85635878b55SSascha Wildner pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType]; 85735878b55SSascha Wildner pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType]; 85835878b55SSascha Wildner memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME); 85935878b55SSascha Wildner pArray2->pParent = pArray1; 86035878b55SSascha Wildner pArray2->bSerialNumber = 1; 86135878b55SSascha Wildner pArray1->u.array.pMember[1] = pArray2; 86235878b55SSascha Wildner pArray1->u.array.bArRealnMember++; 86335878b55SSascha Wildner } 86435878b55SSascha Wildner 86535878b55SSascha Wildner for(i = 0; i < pArray2->u.array.bArnMember; i++) 86635878b55SSascha Wildner if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online) 86735878b55SSascha Wildner { 86835878b55SSascha Wildner if(pArray2->u.array.pMember[i] != NULL) 86935878b55SSascha Wildner pArray2->u.array.pMember[i]->pParent = NULL; 87035878b55SSascha Wildner pArray2->u.array.pMember[i] = pDisk; 87135878b55SSascha Wildner goto find; 87235878b55SSascha Wildner } 87335878b55SSascha Wildner return -1; 87435878b55SSascha Wildner 87535878b55SSascha Wildner find: 87635878b55SSascha Wildner UnregisterVDevice(pDisk); 87735878b55SSascha Wildner pDisk->VDeviceType = VD_SINGLE_DISK; 87835878b55SSascha Wildner pDisk->bSerialNumber = i; 87935878b55SSascha Wildner pDisk->pParent = pArray2; 88035878b55SSascha Wildner pDisk->vf_format_v2 = 1; 88135878b55SSascha Wildner pDisk->u.disk.dDeHiddenLba = i? 10 : 0; 88235878b55SSascha Wildner pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; 88335878b55SSascha Wildner pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType]; 88435878b55SSascha Wildner 88535878b55SSascha Wildner pArray2->u.array.bArRealnMember++; 88635878b55SSascha Wildner if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){ 88735878b55SSascha Wildner pArray2->vf_online = 1; 88835878b55SSascha Wildner pArray2->u.array.rf_broken = 0; 88935878b55SSascha Wildner } 89035878b55SSascha Wildner 89135878b55SSascha Wildner if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){ 89235878b55SSascha Wildner pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember; 89335878b55SSascha Wildner pArray1->u.array.rf_broken = 0; 89435878b55SSascha Wildner pArray1->u.array.rf_need_rebuild = 1; 89535878b55SSascha Wildner pArray1->u.array.rf_auto_rebuild = 1; 89635878b55SSascha Wildner 89735878b55SSascha Wildner } 89835878b55SSascha Wildner pArray1->u.array.RebuildSectors = 0; 89935878b55SSascha Wildner pArray1->u.array.dArStamp = GetStamp(); 90035878b55SSascha Wildner SyncArrayInfo(pArray1); 90135878b55SSascha Wildner return 1; 90235878b55SSascha Wildner } 90335878b55SSascha Wildner #endif 90435878b55SSascha Wildner 90535878b55SSascha Wildner int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) 90635878b55SSascha Wildner { 90735878b55SSascha Wildner int i; 90835878b55SSascha Wildner 90935878b55SSascha Wildner LBA_T Capacity; 91035878b55SSascha Wildner PVDevice pArray = ID_TO_VDEV(idArray); 91135878b55SSascha Wildner PVDevice pDisk = ID_TO_VDEV(idDisk); 91235878b55SSascha Wildner 91335878b55SSascha Wildner if((idArray == 0) || (idDisk == 0)) return -1; 91435878b55SSascha Wildner if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1; 91535878b55SSascha Wildner if(!pArray->u.array.rf_broken) return -1; 91635878b55SSascha Wildner 91735878b55SSascha Wildner if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) 91835878b55SSascha Wildner return -1; 91935878b55SSascha Wildner if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE)) 92035878b55SSascha Wildner return -1; 92135878b55SSascha Wildner 92235878b55SSascha Wildner #ifdef SUPPORT_OLD_ARRAY 92335878b55SSascha Wildner /* RAID 0 + 1 */ 92435878b55SSascha Wildner if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 && 92535878b55SSascha Wildner pArray->u.array.pMember[0] && 92635878b55SSascha Wildner mIsArray(pArray->u.array.pMember[0])) 92735878b55SSascha Wildner { 92835878b55SSascha Wildner if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk)) 92935878b55SSascha Wildner return 0; 93035878b55SSascha Wildner else 93135878b55SSascha Wildner return -1; 93235878b55SSascha Wildner } 93335878b55SSascha Wildner #endif 93435878b55SSascha Wildner 93535878b55SSascha Wildner Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1); 93635878b55SSascha Wildner 93735878b55SSascha Wildner if (pArray->vf_format_v2) { 93835878b55SSascha Wildner if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1; 93935878b55SSascha Wildner } 94035878b55SSascha Wildner else 94135878b55SSascha Wildner if(pDisk->VDeviceCapacity < Capacity) return -1; 94235878b55SSascha Wildner 94335878b55SSascha Wildner if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 94435878b55SSascha Wildner 94535878b55SSascha Wildner for(i = 0; i < pArray->u.array.bArnMember; i++) 946d8061892SSascha Wildner if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online) 94735878b55SSascha Wildner { 94835878b55SSascha Wildner if(pArray->u.array.pMember[i] != NULL) 94935878b55SSascha Wildner pArray->u.array.pMember[i]->pParent = NULL; 95035878b55SSascha Wildner pArray->u.array.pMember[i] = pDisk; 95135878b55SSascha Wildner goto find; 95235878b55SSascha Wildner } 95335878b55SSascha Wildner return -1; 95435878b55SSascha Wildner 95535878b55SSascha Wildner find: 95635878b55SSascha Wildner UnregisterVDevice(pDisk); 95735878b55SSascha Wildner pDisk->VDeviceType = VD_SINGLE_DISK; 95835878b55SSascha Wildner pDisk->bSerialNumber = i; 95935878b55SSascha Wildner pDisk->pParent = pArray; 96035878b55SSascha Wildner if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1; 96135878b55SSascha Wildner pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; 96235878b55SSascha Wildner if (pArray->vf_format_v2) { 96335878b55SSascha Wildner pDisk->vf_format_v2 = 1; 96435878b55SSascha Wildner pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity; 96535878b55SSascha Wildner } 96635878b55SSascha Wildner 96735878b55SSascha Wildner pArray->u.array.bArRealnMember++; 96835878b55SSascha Wildner if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember) 96935878b55SSascha Wildner { 97035878b55SSascha Wildner pArray->u.array.rf_need_rebuild = 1; 97135878b55SSascha Wildner pArray->u.array.RebuildSectors = 0; 97235878b55SSascha Wildner pArray->u.array.rf_auto_rebuild = 1; 97335878b55SSascha Wildner pArray->u.array.rf_broken = 0; 97435878b55SSascha Wildner } 97535878b55SSascha Wildner pArray->u.array.RebuildSectors = 0; 97635878b55SSascha Wildner 97735878b55SSascha Wildner /* sync the whole array */ 97835878b55SSascha Wildner while (pArray->pParent) pArray = pArray->pParent; 97935878b55SSascha Wildner pArray->u.array.dArStamp = GetStamp(); 98035878b55SSascha Wildner SyncArrayInfo(pArray); 98135878b55SSascha Wildner return 0; 98235878b55SSascha Wildner } 98335878b55SSascha Wildner 984*8406cf70SSascha Wildner static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) 98535878b55SSascha Wildner { 98635878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idDisk); 98735878b55SSascha Wildner DECLARE_BUFFER(PUCHAR, pbuffer); 98835878b55SSascha Wildner 98935878b55SSascha Wildner if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; 99035878b55SSascha Wildner if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) 99135878b55SSascha Wildner return -1; 99235878b55SSascha Wildner 99335878b55SSascha Wildner if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 99435878b55SSascha Wildner 99535878b55SSascha Wildner UnregisterVDevice(pVDevice); 99635878b55SSascha Wildner pVDevice->VDeviceType = VD_SPARE; 99735878b55SSascha Wildner pVDevice->vf_bootmark = 0; 99835878b55SSascha Wildner 99935878b55SSascha Wildner ZeroMemory((char *)pbuffer, 512); 100035878b55SSascha Wildner fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer); 100135878b55SSascha Wildner SyncArrayInfo(pVDevice); 100235878b55SSascha Wildner return 0; 100335878b55SSascha Wildner } 100435878b55SSascha Wildner 1005*8406cf70SSascha Wildner static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) 100635878b55SSascha Wildner { 100735878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idDisk); 100835878b55SSascha Wildner 100935878b55SSascha Wildner if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; 101035878b55SSascha Wildner 101135878b55SSascha Wildner if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 101235878b55SSascha Wildner 101335878b55SSascha Wildner pVDevice->VDeviceType = VD_SINGLE_DISK; 101435878b55SSascha Wildner 101535878b55SSascha Wildner SyncArrayInfo(pVDevice); 101635878b55SSascha Wildner RegisterVDevice(pVDevice); 101735878b55SSascha Wildner return 0; 101835878b55SSascha Wildner } 101935878b55SSascha Wildner 1020*8406cf70SSascha Wildner static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) 102135878b55SSascha Wildner { 102235878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idArray); 102335878b55SSascha Wildner 102435878b55SSascha Wildner if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 102535878b55SSascha Wildner if (!mIsArray(pVDevice)) return -1; 102635878b55SSascha Wildner 102735878b55SSascha Wildner /* if the pVDevice isn't a top level, return -1; */ 102835878b55SSascha Wildner if(pVDevice->pParent != NULL) return -1; 102935878b55SSascha Wildner 103035878b55SSascha Wildner if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 103135878b55SSascha Wildner 103235878b55SSascha Wildner if (pInfo->ValidFields & AAIF_NAME) { 103335878b55SSascha Wildner memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME); 103435878b55SSascha Wildner memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name)); 103535878b55SSascha Wildner pVDevice->u.array.rf_need_sync = 1; 103635878b55SSascha Wildner } 103735878b55SSascha Wildner 103835878b55SSascha Wildner if (pInfo->ValidFields & AAIF_DESCRIPTION) { 103935878b55SSascha Wildner memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description)); 104035878b55SSascha Wildner pVDevice->u.array.rf_need_sync = 1; 104135878b55SSascha Wildner } 104235878b55SSascha Wildner 104335878b55SSascha Wildner if (pVDevice->u.array.rf_need_sync) 104435878b55SSascha Wildner SyncArrayInfo(pVDevice); 104535878b55SSascha Wildner return 0; 104635878b55SSascha Wildner } 104735878b55SSascha Wildner 104835878b55SSascha Wildner static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) 104935878b55SSascha Wildner { 105035878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idDisk); 105135878b55SSascha Wildner 105235878b55SSascha Wildner if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; 105335878b55SSascha Wildner if (mIsArray(pVDevice)) 105435878b55SSascha Wildner return -1; 105535878b55SSascha Wildner 105635878b55SSascha Wildner if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 105735878b55SSascha Wildner 105835878b55SSascha Wildner /* TODO */ 105935878b55SSascha Wildner return 0; 106035878b55SSascha Wildner } 106135878b55SSascha Wildner 106235878b55SSascha Wildner static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo) 106335878b55SSascha Wildner { 106435878b55SSascha Wildner PVDevice pVDevice = ID_TO_VDEV(idDisk); 106535878b55SSascha Wildner int sync = 0; 106635878b55SSascha Wildner 106735878b55SSascha Wildner if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1; 106835878b55SSascha Wildner if (mIsArray(pVDevice)) 106935878b55SSascha Wildner return -1; 107035878b55SSascha Wildner 107135878b55SSascha Wildner if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 107235878b55SSascha Wildner 107335878b55SSascha Wildner if (pInfo->ValidFields & ADIF_MODE) { 107435878b55SSascha Wildner pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting; 107535878b55SSascha Wildner pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting; 107635878b55SSascha Wildner pVDevice->u.disk.df_user_mode_set = 1; 107735878b55SSascha Wildner fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting); 107835878b55SSascha Wildner sync = 1; 107935878b55SSascha Wildner } 108035878b55SSascha Wildner 108135878b55SSascha Wildner if (pInfo->ValidFields & ADIF_TCQ) { 108235878b55SSascha Wildner if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) { 108335878b55SSascha Wildner pVDevice->u.disk.df_tcq_set = 1; 108435878b55SSascha Wildner pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0; 108535878b55SSascha Wildner sync = 1; 108635878b55SSascha Wildner } 108735878b55SSascha Wildner } 108835878b55SSascha Wildner 108935878b55SSascha Wildner if (pInfo->ValidFields & ADIF_NCQ) { 109035878b55SSascha Wildner if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) { 109135878b55SSascha Wildner pVDevice->u.disk.df_ncq_set = 1; 109235878b55SSascha Wildner pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0; 109335878b55SSascha Wildner sync = 1; 109435878b55SSascha Wildner } 109535878b55SSascha Wildner } 109635878b55SSascha Wildner 109735878b55SSascha Wildner if (pInfo->ValidFields & ADIF_WRITE_CACHE) { 109835878b55SSascha Wildner if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) { 109935878b55SSascha Wildner pVDevice->u.disk.df_write_cache_set = 1; 110035878b55SSascha Wildner pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0; 110135878b55SSascha Wildner sync = 1; 110235878b55SSascha Wildner } 110335878b55SSascha Wildner } 110435878b55SSascha Wildner 110535878b55SSascha Wildner if (pInfo->ValidFields & ADIF_READ_AHEAD) { 110635878b55SSascha Wildner if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) { 110735878b55SSascha Wildner pVDevice->u.disk.df_read_ahead_set = 1; 110835878b55SSascha Wildner pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0; 110935878b55SSascha Wildner sync = 1; 111035878b55SSascha Wildner } 111135878b55SSascha Wildner } 111235878b55SSascha Wildner 111335878b55SSascha Wildner if (sync) 111435878b55SSascha Wildner SyncArrayInfo(pVDevice); 111535878b55SSascha Wildner return 0; 111635878b55SSascha Wildner } 111735878b55SSascha Wildner 111835878b55SSascha Wildner #endif 111935878b55SSascha Wildner 112035878b55SSascha Wildner /* hpt_default_ioctl() 112135878b55SSascha Wildner * This is a default implementation. The platform dependent part 112235878b55SSascha Wildner * may reuse this function and/or use it own implementation for 112335878b55SSascha Wildner * each ioctl function. 112435878b55SSascha Wildner */ 112535878b55SSascha Wildner int hpt_default_ioctl(_VBUS_ARG 112635878b55SSascha Wildner DWORD dwIoControlCode, /* operation control code */ 112735878b55SSascha Wildner PVOID lpInBuffer, /* input data buffer */ 112835878b55SSascha Wildner DWORD nInBufferSize, /* size of input data buffer */ 112935878b55SSascha Wildner PVOID lpOutBuffer, /* output data buffer */ 113035878b55SSascha Wildner DWORD nOutBufferSize, /* size of output data buffer */ 113135878b55SSascha Wildner PDWORD lpBytesReturned /* byte count */ 113235878b55SSascha Wildner ) 113335878b55SSascha Wildner { 113435878b55SSascha Wildner switch(dwIoControlCode) { 113535878b55SSascha Wildner 113635878b55SSascha Wildner case HPT_IOCTL_GET_VERSION: 113735878b55SSascha Wildner 113835878b55SSascha Wildner if (nInBufferSize != 0) return -1; 113935878b55SSascha Wildner if (nOutBufferSize != sizeof(DWORD)) return -1; 114035878b55SSascha Wildner *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION; 114135878b55SSascha Wildner break; 114235878b55SSascha Wildner 114335878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_COUNT: 114435878b55SSascha Wildner 114535878b55SSascha Wildner if (nOutBufferSize!=sizeof(DWORD)) return -1; 114635878b55SSascha Wildner *(PDWORD)lpOutBuffer = hpt_get_controller_count(); 114735878b55SSascha Wildner break; 114835878b55SSascha Wildner 114935878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_INFO: 115035878b55SSascha Wildner { 115135878b55SSascha Wildner int id; 115235878b55SSascha Wildner PCONTROLLER_INFO pInfo; 115335878b55SSascha Wildner 115435878b55SSascha Wildner if (nInBufferSize!=sizeof(DWORD)) return -1; 115535878b55SSascha Wildner if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1; 115635878b55SSascha Wildner 115735878b55SSascha Wildner id = *(DWORD *)lpInBuffer; 115835878b55SSascha Wildner pInfo = (PCONTROLLER_INFO)lpOutBuffer; 115935878b55SSascha Wildner if (hpt_get_controller_info(id, pInfo)!=0) 116035878b55SSascha Wildner return -1; 116135878b55SSascha Wildner } 116235878b55SSascha Wildner break; 116335878b55SSascha Wildner 116435878b55SSascha Wildner case HPT_IOCTL_GET_CHANNEL_INFO: 116535878b55SSascha Wildner { 116635878b55SSascha Wildner int id, bus; 116735878b55SSascha Wildner PCHANNEL_INFO pInfo; 116835878b55SSascha Wildner 116935878b55SSascha Wildner if (nInBufferSize!=8) return -1; 117035878b55SSascha Wildner if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1; 117135878b55SSascha Wildner 117235878b55SSascha Wildner id = *(DWORD *)lpInBuffer; 117335878b55SSascha Wildner bus = ((DWORD *)lpInBuffer)[1]; 117435878b55SSascha Wildner pInfo = (PCHANNEL_INFO)lpOutBuffer; 117535878b55SSascha Wildner 117635878b55SSascha Wildner if (hpt_get_channel_info(id, bus, pInfo)!=0) 117735878b55SSascha Wildner return -1; 117835878b55SSascha Wildner } 117935878b55SSascha Wildner break; 118035878b55SSascha Wildner 118135878b55SSascha Wildner case HPT_IOCTL_GET_LOGICAL_DEVICES: 118235878b55SSascha Wildner { 118335878b55SSascha Wildner DWORD nMax; 118435878b55SSascha Wildner DEVICEID *pIds; 118535878b55SSascha Wildner 118635878b55SSascha Wildner if (nInBufferSize!=sizeof(DWORD)) return -1; 118735878b55SSascha Wildner nMax = *(DWORD *)lpInBuffer; 118835878b55SSascha Wildner if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1; 118935878b55SSascha Wildner 119035878b55SSascha Wildner pIds = ((DEVICEID *)lpOutBuffer)+1; 119135878b55SSascha Wildner *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax); 119235878b55SSascha Wildner } 119335878b55SSascha Wildner break; 119435878b55SSascha Wildner 119535878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO: 119635878b55SSascha Wildner { 119735878b55SSascha Wildner DEVICEID id; 119835878b55SSascha Wildner PLOGICAL_DEVICE_INFO pInfo; 119935878b55SSascha Wildner 120035878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)) return -1; 120135878b55SSascha Wildner if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1; 120235878b55SSascha Wildner 120335878b55SSascha Wildner id = *(DWORD *)lpInBuffer; 120435878b55SSascha Wildner if (id == INVALID_DEVICEID) return -1; 120535878b55SSascha Wildner 120635878b55SSascha Wildner pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer; 120735878b55SSascha Wildner memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO)); 120835878b55SSascha Wildner 120935878b55SSascha Wildner if (hpt_get_device_info(id, pInfo)!=0) 121035878b55SSascha Wildner return -1; 121135878b55SSascha Wildner } 121235878b55SSascha Wildner break; 121335878b55SSascha Wildner 121435878b55SSascha Wildner case HPT_IOCTL_GET_DEVICE_INFO_V2: 121535878b55SSascha Wildner { 121635878b55SSascha Wildner DEVICEID id; 121735878b55SSascha Wildner PLOGICAL_DEVICE_INFO_V2 pInfo; 121835878b55SSascha Wildner 121935878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)) return -1; 122035878b55SSascha Wildner if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1; 122135878b55SSascha Wildner 122235878b55SSascha Wildner id = *(DWORD *)lpInBuffer; 122335878b55SSascha Wildner if (id == INVALID_DEVICEID) return -1; 122435878b55SSascha Wildner 122535878b55SSascha Wildner pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer; 122635878b55SSascha Wildner memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2)); 122735878b55SSascha Wildner 122835878b55SSascha Wildner if (hpt_get_device_info_v2(id, pInfo)!=0) 122935878b55SSascha Wildner return -1; 123035878b55SSascha Wildner } 123135878b55SSascha Wildner break; 123235878b55SSascha Wildner 123335878b55SSascha Wildner #ifdef SUPPORT_ARRAY 123435878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY: 123535878b55SSascha Wildner { 123635878b55SSascha Wildner if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1; 123735878b55SSascha Wildner if (nOutBufferSize!=sizeof(DEVICEID)) return -1; 123835878b55SSascha Wildner 123935878b55SSascha Wildner *(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer); 124035878b55SSascha Wildner 124135878b55SSascha Wildner if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID) 124235878b55SSascha Wildner return -1; 124335878b55SSascha Wildner } 124435878b55SSascha Wildner break; 124535878b55SSascha Wildner 124635878b55SSascha Wildner case HPT_IOCTL_CREATE_ARRAY_V2: 124735878b55SSascha Wildner { 124835878b55SSascha Wildner if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1; 124935878b55SSascha Wildner if (nOutBufferSize!=sizeof(DEVICEID)) return -1; 125035878b55SSascha Wildner 125135878b55SSascha Wildner *(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer); 125235878b55SSascha Wildner 125335878b55SSascha Wildner if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID) 125435878b55SSascha Wildner return -1; 125535878b55SSascha Wildner } 125635878b55SSascha Wildner break; 125735878b55SSascha Wildner 125835878b55SSascha Wildner case HPT_IOCTL_SET_ARRAY_INFO: 125935878b55SSascha Wildner { 126035878b55SSascha Wildner DEVICEID idArray; 126135878b55SSascha Wildner PALTERABLE_ARRAY_INFO pInfo; 126235878b55SSascha Wildner 126335878b55SSascha Wildner if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1; 126435878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 126535878b55SSascha Wildner 126635878b55SSascha Wildner idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray; 126735878b55SSascha Wildner pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info; 126835878b55SSascha Wildner 126935878b55SSascha Wildner if(hpt_set_array_info(_VBUS_P idArray, pInfo)) 127035878b55SSascha Wildner return -1; 127135878b55SSascha Wildner } 127235878b55SSascha Wildner break; 127335878b55SSascha Wildner 127435878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO: 127535878b55SSascha Wildner { 127635878b55SSascha Wildner DEVICEID idDisk; 127735878b55SSascha Wildner PALTERABLE_DEVICE_INFO pInfo; 127835878b55SSascha Wildner 127935878b55SSascha Wildner if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1; 128035878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 128135878b55SSascha Wildner 128235878b55SSascha Wildner idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk; 128335878b55SSascha Wildner pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info; 128435878b55SSascha Wildner if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0) 128535878b55SSascha Wildner return -1; 128635878b55SSascha Wildner } 128735878b55SSascha Wildner break; 128835878b55SSascha Wildner 128935878b55SSascha Wildner case HPT_IOCTL_SET_DEVICE_INFO_V2: 129035878b55SSascha Wildner { 129135878b55SSascha Wildner DEVICEID idDisk; 129235878b55SSascha Wildner PALTERABLE_DEVICE_INFO_V2 pInfo; 129335878b55SSascha Wildner 129435878b55SSascha Wildner if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1; 129535878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 129635878b55SSascha Wildner 129735878b55SSascha Wildner idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk; 129835878b55SSascha Wildner pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info; 129935878b55SSascha Wildner if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0) 130035878b55SSascha Wildner return -1; 130135878b55SSascha Wildner } 130235878b55SSascha Wildner break; 130335878b55SSascha Wildner 130435878b55SSascha Wildner case HPT_IOCTL_SET_BOOT_MARK: 130535878b55SSascha Wildner { 130635878b55SSascha Wildner DEVICEID id; 130735878b55SSascha Wildner PVDevice pTop; 130835878b55SSascha Wildner int i; 130935878b55SSascha Wildner IAL_ADAPTER_T *pAdapter = gIal_Adapter; 131035878b55SSascha Wildner PVBus pVBus; 131135878b55SSascha Wildner 131235878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)) return -1; 131335878b55SSascha Wildner id = *(DEVICEID *)lpInBuffer; 1314d8061892SSascha Wildner while(pAdapter != NULL) 131535878b55SSascha Wildner { 131635878b55SSascha Wildner pVBus = &pAdapter->VBus; 131735878b55SSascha Wildner for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) 131835878b55SSascha Wildner { 131935878b55SSascha Wildner if(!(pTop = pVBus->pVDevice[i])) continue; 132035878b55SSascha Wildner if (pTop->pVBus!=_vbus_p) return -1; 132135878b55SSascha Wildner while (pTop->pParent) pTop = pTop->pParent; 132235878b55SSascha Wildner if (id==0 && pTop->vf_bootmark) 132335878b55SSascha Wildner pTop->vf_bootmark = 0; 132435878b55SSascha Wildner else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark) 132535878b55SSascha Wildner pTop->vf_bootmark = 1; 132635878b55SSascha Wildner else 132735878b55SSascha Wildner continue; 132835878b55SSascha Wildner SyncArrayInfo(pTop); 132935878b55SSascha Wildner break; 133035878b55SSascha Wildner } 133135878b55SSascha Wildner pAdapter = pAdapter->next; 133235878b55SSascha Wildner } 133335878b55SSascha Wildner } 133435878b55SSascha Wildner break; 133535878b55SSascha Wildner 133635878b55SSascha Wildner case HPT_IOCTL_ADD_SPARE_DISK: 133735878b55SSascha Wildner { 133835878b55SSascha Wildner DEVICEID id; 133935878b55SSascha Wildner 134035878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)) return -1; 134135878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 134235878b55SSascha Wildner 134335878b55SSascha Wildner id = *(DEVICEID *)lpInBuffer; 134435878b55SSascha Wildner 134535878b55SSascha Wildner if(hpt_add_spare_disk(_VBUS_P id)) 134635878b55SSascha Wildner return -1; 134735878b55SSascha Wildner } 134835878b55SSascha Wildner break; 134935878b55SSascha Wildner 135035878b55SSascha Wildner case HPT_IOCTL_REMOVE_SPARE_DISK: 135135878b55SSascha Wildner { 135235878b55SSascha Wildner DEVICEID id; 135335878b55SSascha Wildner 135435878b55SSascha Wildner if (nInBufferSize!=sizeof(DEVICEID)) return -1; 135535878b55SSascha Wildner if (nOutBufferSize!=0) return -1; 135635878b55SSascha Wildner 135735878b55SSascha Wildner id = *(DEVICEID *)lpInBuffer; 135835878b55SSascha Wildner 135935878b55SSascha Wildner if(hpt_remove_spare_disk(_VBUS_P id)) 136035878b55SSascha Wildner return -1; 136135878b55SSascha Wildner } 136235878b55SSascha Wildner break; 136335878b55SSascha Wildner 136435878b55SSascha Wildner case HPT_IOCTL_ADD_DISK_TO_ARRAY: 136535878b55SSascha Wildner { 136635878b55SSascha Wildner DEVICEID id1,id2; 136735878b55SSascha Wildner id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray; 136835878b55SSascha Wildner id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk; 136935878b55SSascha Wildner 137035878b55SSascha Wildner if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1; 137135878b55SSascha Wildner if (nOutBufferSize != 0) return -1; 137235878b55SSascha Wildner 137335878b55SSascha Wildner if(hpt_add_disk_to_array(_VBUS_P id1, id2)) 137435878b55SSascha Wildner return -1; 137535878b55SSascha Wildner } 137635878b55SSascha Wildner break; 137735878b55SSascha Wildner #endif 137835878b55SSascha Wildner case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 137935878b55SSascha Wildner { 138035878b55SSascha Wildner PDRIVER_CAPABILITIES cap; 138135878b55SSascha Wildner if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1; 138235878b55SSascha Wildner cap = (PDRIVER_CAPABILITIES)lpOutBuffer; 138335878b55SSascha Wildner 138435878b55SSascha Wildner if(hpt_get_driver_capabilities(cap)) 138535878b55SSascha Wildner return -1; 138635878b55SSascha Wildner } 138735878b55SSascha Wildner break; 138835878b55SSascha Wildner 138935878b55SSascha Wildner case HPT_IOCTL_GET_CONTROLLER_VENID: 139035878b55SSascha Wildner { 139135878b55SSascha Wildner DWORD id = ((DWORD*)lpInBuffer)[0]; 139235878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 139335878b55SSascha Wildner int iControllerCount = 0; 139435878b55SSascha Wildner 139535878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) 139635878b55SSascha Wildner if (iControllerCount++==id) 139735878b55SSascha Wildner break; 139835878b55SSascha Wildner 139935878b55SSascha Wildner if (!pAdapTemp) 140035878b55SSascha Wildner return -1; 140135878b55SSascha Wildner 140235878b55SSascha Wildner if (nOutBufferSize < 4) 140335878b55SSascha Wildner return -1; 140435878b55SSascha Wildner 140535878b55SSascha Wildner *(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB; 140635878b55SSascha Wildner return 0; 140735878b55SSascha Wildner } 140835878b55SSascha Wildner 140935878b55SSascha Wildner case HPT_IOCTL_EPROM_IO: 141035878b55SSascha Wildner { 141135878b55SSascha Wildner DWORD id = ((DWORD*)lpInBuffer)[0]; 141235878b55SSascha Wildner DWORD offset = ((DWORD*)lpInBuffer)[1]; 141335878b55SSascha Wildner DWORD direction = ((DWORD*)lpInBuffer)[2]; 141435878b55SSascha Wildner DWORD length = ((DWORD*)lpInBuffer)[3]; 141535878b55SSascha Wildner IAL_ADAPTER_T *pAdapTemp; 141635878b55SSascha Wildner int iControllerCount = 0; 141735878b55SSascha Wildner 141835878b55SSascha Wildner for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) 141935878b55SSascha Wildner if (iControllerCount++==id) 142035878b55SSascha Wildner break; 142135878b55SSascha Wildner 142235878b55SSascha Wildner if (!pAdapTemp) 142335878b55SSascha Wildner return -1; 142435878b55SSascha Wildner 142535878b55SSascha Wildner if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) || 142635878b55SSascha Wildner nOutBufferSize < (direction? 0 : length)) 142735878b55SSascha Wildner return -1; 142835878b55SSascha Wildner 142935878b55SSascha Wildner if (direction == 0) /* read */ 143035878b55SSascha Wildner sx508x_flash_access(&pAdapTemp->mvSataAdapter, 143135878b55SSascha Wildner offset, lpOutBuffer, length, 1); 143235878b55SSascha Wildner else 143335878b55SSascha Wildner sx508x_flash_access(&pAdapTemp->mvSataAdapter, 143435878b55SSascha Wildner offset, (char *)lpInBuffer + 16, length, 0); 143535878b55SSascha Wildner 143635878b55SSascha Wildner return 0; 143735878b55SSascha Wildner } 143835878b55SSascha Wildner break; 143935878b55SSascha Wildner 144035878b55SSascha Wildner default: 144135878b55SSascha Wildner return -1; 144235878b55SSascha Wildner } 144335878b55SSascha Wildner 144435878b55SSascha Wildner if (lpBytesReturned) 144535878b55SSascha Wildner *lpBytesReturned = nOutBufferSize; 144635878b55SSascha Wildner return 0; 144735878b55SSascha Wildner } 1448