aboutsummaryrefslogtreecommitdiff
path: root/sys/dev/hptmv/gui_lib.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/hptmv/gui_lib.c')
-rw-r--r--sys/dev/hptmv/gui_lib.c1447
1 files changed, 1447 insertions, 0 deletions
diff --git a/sys/dev/hptmv/gui_lib.c b/sys/dev/hptmv/gui_lib.c
new file mode 100644
index 000000000000..a9feb4a6cac0
--- /dev/null
+++ b/sys/dev/hptmv/gui_lib.c
@@ -0,0 +1,1447 @@
+/*
+ * 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 <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+
+#ifndef __KERNEL__
+#define __KERNEL__
+#endif
+
+#include <dev/hptmv/global.h>
+#include <dev/hptmv/hptintf.h>
+#include <dev/hptmv/osbsd.h>
+#include <dev/hptmv/access601.h>
+
+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 != 0)
+ {
+ for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
+ if(&(pAdapter->VDevices[i]) == p) return 0;
+ pAdapter = pAdapter->next;
+ }
+
+#ifdef SUPPORT_ARRAY
+ pAdapter = gIal_Adapter;
+ while(pAdapter != 0)
+ {
+ _vbus_p = &pAdapter->VBus;
+ for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
+ {
+ pVDevice=ArrayTables(i);
+ if ((pVDevice->u.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; i<MAX_ARRAY_MEMBERS; i++)
+ pArrayInfo->Members[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; i<MAX_ARRAY_MEMBERS_V2; i++)
+ pArrayInfo->Members[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 != 0)
+ {
+ 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 != 0)
+ {
+ if (iControllerCount++==id)
+ goto found;
+ pAdapTemp = pAdapTemp->next;
+ }
+ return -1;
+
+found:
+
+ pInfo->IoPort = 0;
+ pInfo->ControlPort = 0;
+
+ for (i=0; i<2 ;i++)
+ {
+ pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
+ }
+
+ if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
+ pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
+ else
+ pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
+
+ return 0;
+
+
+}
+
+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<count; j++)
+ if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
+ pIds[count++] = VDEV_TO_ID(pLogical);
+ if (count>=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 = (capacity & ~(pArray->u.array.bStripeWitch - 1))
+ * (pArray->u.array.bArnMember - 1);
+ break;
+
+ default:
+ goto error;
+ }
+
+ pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
+ pArray->pfnDeviceFailed = fOsDiskFailed;
+ SyncArrayInfo(pArray);
+
+ if (!pArray->u.array.rf_duplicate_and_created)
+ RegisterVDevice(pArray);
+ return VDEV_TO_ID(pArray);
+
+error:
+ for(i = 0; i < pArray->u.array.bArnMember; i++)
+ {
+ pChild = pArray->u.array.pMember[i];
+ if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
+ mArFreeArrayTable(pChild);
+ }
+ mArFreeArrayTable(pArray);
+ return INVALID_DEVICEID;
+}
+
+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 &param2);
+}
+
+#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 (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
+ cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
+
+ if(hpt_get_driver_capabilities(cap))
+ return -1;
+ }
+ break;
+
+ case HPT_IOCTL_GET_CONTROLLER_VENID:
+ {
+ DWORD id = ((DWORD*)lpInBuffer)[0];
+ IAL_ADAPTER_T *pAdapTemp;
+ int iControllerCount = 0;
+
+ for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
+ 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;
+}