xref: /freebsd-src/sys/dev/hptmv/gui_lib.c (revision 95ee2897e98f5d444f26ed2334cc7c439f9c16c6)
1718cf2ccSPedro F. Giffuni /*-
2*4d846d26SWarner Losh  * SPDX-License-Identifier: BSD-2-Clause
3718cf2ccSPedro F. Giffuni  *
4d2bd3ab9SScott Long  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
51713e81bSScott Long  * All rights reserved.
61713e81bSScott Long  *
71713e81bSScott Long  * Redistribution and use in source and binary forms, with or without
81713e81bSScott Long  * modification, are permitted provided that the following conditions
91713e81bSScott Long  * are met:
101713e81bSScott Long  * 1. Redistributions of source code must retain the above copyright
111713e81bSScott Long  *    notice, this list of conditions and the following disclaimer.
121713e81bSScott Long  * 2. Redistributions in binary form must reproduce the above copyright
131713e81bSScott Long  *    notice, this list of conditions and the following disclaimer in the
141713e81bSScott Long  *    documentation and/or other materials provided with the distribution.
151713e81bSScott Long  *
161713e81bSScott Long  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
171713e81bSScott Long  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
181713e81bSScott Long  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
191713e81bSScott Long  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
201713e81bSScott Long  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
211713e81bSScott Long  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
221713e81bSScott Long  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
231713e81bSScott Long  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
241713e81bSScott Long  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
251713e81bSScott Long  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
261713e81bSScott Long  * SUCH DAMAGE.
271713e81bSScott Long  */
281713e81bSScott Long /*
291713e81bSScott Long  * gui_lib.c
301713e81bSScott Long  * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved.
311713e81bSScott Long  *
321713e81bSScott Long  *  Platform independent ioctl interface implementation.
331713e81bSScott Long  *  The platform dependent part may reuse this function and/or use it own
341713e81bSScott Long  *  implementation for each ioctl function.
351713e81bSScott Long  *
361713e81bSScott Long  *  This implementation doesn't use any synchronization; the caller must
371713e81bSScott Long  *  assure the proper context when calling these functions.
381713e81bSScott Long  */
391713e81bSScott Long 
401713e81bSScott Long #include <sys/param.h>
411713e81bSScott Long #include <sys/systm.h>
421713e81bSScott Long #include <sys/kernel.h>
431713e81bSScott Long #include <sys/malloc.h>
441713e81bSScott Long 
45d2bd3ab9SScott Long #ifndef __KERNEL__
46d2bd3ab9SScott Long #define __KERNEL__
47d2bd3ab9SScott Long #endif
48d2bd3ab9SScott Long 
491713e81bSScott Long #include <dev/hptmv/global.h>
501713e81bSScott Long #include <dev/hptmv/hptintf.h>
511713e81bSScott Long #include <dev/hptmv/osbsd.h>
52f7f3900bSScott Long #include <dev/hptmv/access601.h>
531713e81bSScott Long 
541713e81bSScott Long static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
551713e81bSScott Long static int hpt_get_controller_count(void);
561713e81bSScott Long static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
571713e81bSScott Long static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
581713e81bSScott Long static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
591713e81bSScott Long static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
6064470755SXin LI static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo);
611713e81bSScott Long static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
6264470755SXin LI static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam);
631713e81bSScott Long static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
641713e81bSScott Long static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
651713e81bSScott Long static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
661713e81bSScott Long static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
6764470755SXin LI static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo);
681713e81bSScott Long 
69d2bd3ab9SScott Long int
check_VDevice_valid(PVDevice p)70d2bd3ab9SScott Long check_VDevice_valid(PVDevice p)
711713e81bSScott Long {
721713e81bSScott Long 	int i;
731713e81bSScott Long 	PVDevice pVDevice;
741713e81bSScott Long 	PVBus    _vbus_p;
751713e81bSScott Long 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
761713e81bSScott Long 
774d24901aSPedro F. Giffuni 	while(pAdapter != NULL)
781713e81bSScott Long 	{
791713e81bSScott Long 		for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
801713e81bSScott Long 			if(&(pAdapter->VDevices[i]) == p)  return 0;
811713e81bSScott Long 		pAdapter = pAdapter->next;
821713e81bSScott Long 	}
831713e81bSScott Long 
841713e81bSScott Long #ifdef SUPPORT_ARRAY
851713e81bSScott Long 	pAdapter = gIal_Adapter;
864d24901aSPedro F. Giffuni 	while(pAdapter != NULL)
871713e81bSScott Long 	{
881713e81bSScott Long 		_vbus_p = &pAdapter->VBus;
891713e81bSScott Long 		for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
901713e81bSScott Long 		{
911713e81bSScott Long 			pVDevice=ArrayTables(i);
921713e81bSScott Long 			if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
931713e81bSScott Long 				return 0;
941713e81bSScott Long 		}
951713e81bSScott Long 		pAdapter = pAdapter->next;
961713e81bSScott Long 	}
971713e81bSScott Long #endif
981713e81bSScott Long 
991713e81bSScott Long 	return -1;
1001713e81bSScott Long }
1011713e81bSScott Long 
1021713e81bSScott Long #ifdef SUPPORT_ARRAY
10364470755SXin LI 
get_vdev_type(PVDevice pVDevice)10464470755SXin LI static UCHAR get_vdev_type(PVDevice pVDevice)
1051713e81bSScott Long 	{
10664470755SXin LI 	switch (pVDevice->VDeviceType) {
10764470755SXin LI 		case VD_RAID_0: return AT_RAID0;
10864470755SXin LI 		case VD_RAID_1: return AT_RAID1;
10964470755SXin LI 		case VD_JBOD:   return AT_JBOD;
11064470755SXin LI 		case VD_RAID_5: return AT_RAID5;
11164470755SXin LI 		default:        return AT_UNKNOWN;
11264470755SXin LI 	}
1131713e81bSScott Long 	}
1141713e81bSScott Long 
get_array_flag(PVDevice pVDevice)11564470755SXin LI static DWORD get_array_flag(PVDevice pVDevice)
11664470755SXin LI {
11764470755SXin LI 	int i;
11864470755SXin LI 	DWORD f = 0;
1191713e81bSScott Long 
1201713e81bSScott Long 	/* The array is disabled */
1211713e81bSScott Long 	if(!pVDevice->vf_online)	{
12264470755SXin LI 		f |= ARRAY_FLAG_DISABLED;
12364470755SXin LI 		/* Ignore other info */
12464470755SXin LI 		return f;
1251713e81bSScott Long 	}
1261713e81bSScott Long 
1271713e81bSScott Long 	/* array need synchronizing */
1281713e81bSScott Long 	if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
12964470755SXin LI 		f |= ARRAY_FLAG_NEEDBUILDING;
1301713e81bSScott Long 
1311713e81bSScott Long 	/* array is in rebuilding process */
1321713e81bSScott Long 	if(pVDevice->u.array.rf_rebuilding)
13364470755SXin LI 		f |= ARRAY_FLAG_REBUILDING;
1341713e81bSScott Long 
1351713e81bSScott Long 	/* array is being verified */
1361713e81bSScott Long 	if(pVDevice->u.array.rf_verifying)
13764470755SXin LI 		f |= ARRAY_FLAG_VERIFYING;
1381713e81bSScott Long 
1391713e81bSScott Long 	/* array is being initialized */
1401713e81bSScott Long 	if(pVDevice->u.array.rf_initializing)
14164470755SXin LI 		f |= ARRAY_FLAG_INITIALIZING;
1421713e81bSScott Long 
1431713e81bSScott Long 	/* broken but may still working */
1441713e81bSScott Long 	if(pVDevice->u.array.rf_broken)
14564470755SXin LI 		f |= ARRAY_FLAG_BROKEN;
1461713e81bSScott Long 
1471713e81bSScott Long 	/* array has a active partition */
1481713e81bSScott Long 	if(pVDevice->vf_bootable)
14964470755SXin LI 		f |= ARRAY_FLAG_BOOTDISK;
1501713e81bSScott Long 
1511713e81bSScott Long 	/* a newly created array */
1521713e81bSScott Long 	if(pVDevice->u.array.rf_newly_created)
15364470755SXin LI 		f |= ARRAY_FLAG_NEWLY_CREATED;
1541713e81bSScott Long 
1551713e81bSScott Long 	/* array has boot mark set */
1561713e81bSScott Long 	if(pVDevice->vf_bootmark)
15764470755SXin LI 		f |= ARRAY_FLAG_BOOTMARK;
1581713e81bSScott Long 
1591713e81bSScott Long 	/* auto-rebuild should start */
1601713e81bSScott Long 	if(pVDevice->u.array.rf_auto_rebuild)
16164470755SXin LI 		f |= ARRAY_FLAG_NEED_AUTOREBUILD;
1621713e81bSScott Long 
1631713e81bSScott Long 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
1641713e81bSScott Long 	{
1651713e81bSScott Long 		PVDevice pMember = pVDevice->u.array.pMember[i];
1661713e81bSScott Long 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
1671713e81bSScott Long 			continue;
1681713e81bSScott Long 
1691713e81bSScott Long 		/* array need synchronizing */
1701713e81bSScott Long 		if(pMember->u.array.rf_need_rebuild &&
1711713e81bSScott Long 		   !pMember->u.array.rf_duplicate_and_create)
17264470755SXin LI 			f |= ARRAY_FLAG_NEEDBUILDING;
1731713e81bSScott Long 
1741713e81bSScott Long 		/* array is in rebuilding process */
1751713e81bSScott Long 		if(pMember->u.array.rf_rebuilding)
17664470755SXin LI 			f |= ARRAY_FLAG_REBUILDING;
1771713e81bSScott Long 
1781713e81bSScott Long 		/* array is being verified */
1791713e81bSScott Long 		if(pMember->u.array.rf_verifying)
18064470755SXin LI 			f |= ARRAY_FLAG_VERIFYING;
1811713e81bSScott Long 
1821713e81bSScott Long 		/* array is being initialized */
1831713e81bSScott Long 		if(pMember->u.array.rf_initializing)
18464470755SXin LI 			f |= ARRAY_FLAG_INITIALIZING;
1851713e81bSScott Long 
1861713e81bSScott Long 		/* broken but may still working */
1871713e81bSScott Long 		if(pMember->u.array.rf_broken)
18864470755SXin LI 			f |= ARRAY_FLAG_BROKEN;
1891713e81bSScott Long 
1901713e81bSScott Long 		/* a newly created array */
1911713e81bSScott Long 		if(pMember->u.array.rf_newly_created)
19264470755SXin LI 			f |= ARRAY_FLAG_NEWLY_CREATED;
1931713e81bSScott Long 
1941713e81bSScott Long 		/* auto-rebuild should start */
1951713e81bSScott Long 		if(pMember->u.array.rf_auto_rebuild)
19664470755SXin LI 			f |= ARRAY_FLAG_NEED_AUTOREBUILD;
19764470755SXin LI 	}
19864470755SXin LI 
19964470755SXin LI 	return f;
20064470755SXin LI }
20164470755SXin LI 
calc_rebuild_progress(PVDevice pVDevice)20264470755SXin LI static DWORD calc_rebuild_progress(PVDevice pVDevice)
20364470755SXin LI {
20464470755SXin LI 	int i;
20564470755SXin LI 	DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 /
20664470755SXin LI 		(ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
20764470755SXin LI 
20864470755SXin LI 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
20964470755SXin LI 	{
21064470755SXin LI 		PVDevice pMember = pVDevice->u.array.pMember[i];
21164470755SXin LI 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
21264470755SXin LI 			continue;
2131713e81bSScott Long 
2141713e81bSScott Long 		/* for RAID1/0 case */
2151713e81bSScott Long 		if (pMember->u.array.rf_rebuilding ||
2161713e81bSScott Long 			pMember->u.array.rf_verifying ||
2171713e81bSScott Long 			pMember->u.array.rf_initializing)
2181713e81bSScott Long 		{
21964470755SXin LI 			DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 /
22064470755SXin LI 				(ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
22164470755SXin LI 			if (result==0 || result>percent)
22264470755SXin LI 				result = percent;
2231713e81bSScott Long 		}
2241713e81bSScott Long 		}
2251713e81bSScott Long 
22664470755SXin LI 	if (result>10000) result = 10000;
22764470755SXin LI 	return result;
22864470755SXin LI 	}
2291713e81bSScott Long 
get_array_info(PVDevice pVDevice,PHPT_ARRAY_INFO pArrayInfo)23064470755SXin LI static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
23164470755SXin LI {
23264470755SXin LI 	int	i;
2331713e81bSScott Long 
23464470755SXin LI 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
23564470755SXin LI 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
23664470755SXin LI 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
23764470755SXin LI 	pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors;
23864470755SXin LI 	pArrayInfo->Flags = get_array_flag(pVDevice);
23964470755SXin LI 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
24064470755SXin LI 
24164470755SXin LI 	pArrayInfo->nDisk = 0;
2421713e81bSScott Long 
2431713e81bSScott Long 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
24464470755SXin LI 		if(pVDevice->u.array.pMember[i] != NULL)
24564470755SXin LI 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
24664470755SXin LI 
24764470755SXin LI 	for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++)
24864470755SXin LI 		pArrayInfo->Members[i] = INVALID_DEVICEID;
2491713e81bSScott Long 	}
25064470755SXin LI 
get_array_info_v2(PVDevice pVDevice,PHPT_ARRAY_INFO_V2 pArrayInfo)25164470755SXin LI static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
25264470755SXin LI {
25364470755SXin LI 	int	i;
25464470755SXin LI 
25564470755SXin LI 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN);
25664470755SXin LI 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
25764470755SXin LI 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
25864470755SXin LI 	pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors;
25964470755SXin LI 	pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0;
26064470755SXin LI 	pArrayInfo->Flags = get_array_flag(pVDevice);
26164470755SXin LI 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
26264470755SXin LI 
26364470755SXin LI 	pArrayInfo->nDisk = 0;
26464470755SXin LI 
26564470755SXin LI 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
26664470755SXin LI 		if(pVDevice->u.array.pMember[i] != NULL)
26764470755SXin LI 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
26864470755SXin LI 
26964470755SXin LI 	for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++)
27064470755SXin LI 		pArrayInfo->Members[i] = INVALID_DEVICEID;
2711713e81bSScott Long }
2721713e81bSScott Long #endif
2731713e81bSScott Long 
get_disk_info(PVDevice pVDevice,PDEVICE_INFO pDiskInfo)27464470755SXin LI static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo)
2751713e81bSScott Long {
2761713e81bSScott Long 	MV_SATA_ADAPTER *pSataAdapter;
2771713e81bSScott Long 	MV_SATA_CHANNEL *pSataChannel;
2781713e81bSScott Long 	IAL_ADAPTER_T   *pAdapter;
27964470755SXin LI 	MV_CHANNEL		*channelInfo;
2801713e81bSScott Long 	char *p;
2811713e81bSScott Long 	int i;
2821713e81bSScott Long 
2831713e81bSScott Long 	/* device location */
2841713e81bSScott Long 	pSataChannel = pVDevice->u.disk.mv;
2851713e81bSScott Long 	if(pSataChannel == NULL)	return -1;
28664470755SXin LI 	pDiskInfo->TargetId = 0;
2871713e81bSScott Long 	pSataAdapter = pSataChannel->mvSataAdapter;
2881713e81bSScott Long 	if(pSataAdapter == NULL)	return -1;
2891713e81bSScott Long 
2901713e81bSScott Long 	pAdapter = pSataAdapter->IALData;
2911713e81bSScott Long 
29264470755SXin LI 	pDiskInfo->PathId = pSataChannel->channelNumber;
29364470755SXin LI 	pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId;
2941713e81bSScott Long 
2951713e81bSScott Long /*GUI uses DeviceModeSetting to display to users
2961713e81bSScott Long (1) if users select a mode, GUI/BIOS should display that mode.
2971713e81bSScott Long (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
2981713e81bSScott Long (3) display real mode if case (1)&&(2) not satisfied.
2991713e81bSScott Long */
3001713e81bSScott Long 	if (pVDevice->u.disk.df_user_mode_set)
30164470755SXin LI 		pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
30264470755SXin LI 	else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2)
30364470755SXin LI 		pDiskInfo->DeviceModeSetting = 15;
3041713e81bSScott Long 	else {
3051713e81bSScott Long 		p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
30664470755SXin LI 		if (*(WORD*)p==(0x5354) /*'ST'*/ &&
30764470755SXin LI 			(*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
30864470755SXin LI 			pDiskInfo->DeviceModeSetting = 15;
3091713e81bSScott Long 		else
31064470755SXin LI 			pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
3111713e81bSScott Long 	}
3121713e81bSScott Long 
31364470755SXin LI 	pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode;
3141713e81bSScott Long 
31564470755SXin LI 	pDiskInfo->DeviceType = PDT_HARDDISK;
3161713e81bSScott Long 
31764470755SXin LI 	pDiskInfo->Flags = 0x0;
3181713e81bSScott Long 
3191713e81bSScott Long 	/* device is disabled */
3201713e81bSScott Long 	if(!pVDevice->u.disk.df_on_line)
32164470755SXin LI 		pDiskInfo->Flags |= DEVICE_FLAG_DISABLED;
3221713e81bSScott Long 
3231713e81bSScott Long 	/* disk has a active partition */
3241713e81bSScott Long 	if(pVDevice->vf_bootable)
32564470755SXin LI 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK;
3261713e81bSScott Long 
3271713e81bSScott Long 	/* disk has boot mark set */
3281713e81bSScott Long 	if(pVDevice->vf_bootmark)
32964470755SXin LI 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK;
3301713e81bSScott Long 
33164470755SXin LI 	pDiskInfo->Flags |= DEVICE_FLAG_SATA;
3321713e81bSScott Long 
3331713e81bSScott Long 	/* is a spare disk */
3341713e81bSScott Long 	if(pVDevice->VDeviceType == VD_SPARE)
33564470755SXin LI 		pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE;
3361713e81bSScott Long 
33764470755SXin LI 	memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
33864470755SXin LI 	p = (char *)&pDiskInfo->IdentifyData.ModelNumber;
3391713e81bSScott Long 	for (i = 0; i < 20; i++)
3401713e81bSScott Long 		((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
3411713e81bSScott Long 	p[39] = '\0';
3421713e81bSScott Long 
34364470755SXin LI 	channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber];
34464470755SXin LI 	pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported;
34564470755SXin LI 	pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled;
34664470755SXin LI 	pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported;
34764470755SXin LI 	pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled;
34864470755SXin LI 	pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0;
34964470755SXin LI 	pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED;
35064470755SXin LI 	pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) &&
35164470755SXin LI 		(pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100));
35264470755SXin LI 	pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING;
3531713e81bSScott Long 	return 0;
3541713e81bSScott Long }
3551713e81bSScott Long 
hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)356d2bd3ab9SScott Long int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
3571713e81bSScott Long {
3581713e81bSScott Long 	ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
3591713e81bSScott Long 	cap->dwSize = sizeof(DRIVER_CAPABILITIES);
3601713e81bSScott Long 	cap->MaximumControllers = MAX_VBUS;
3611713e81bSScott Long 
3621713e81bSScott Long 	/* cap->SupportCrossControllerRAID = 0; */
3631713e81bSScott Long 	/* take care for various OSes! */
3641713e81bSScott Long 	cap->SupportCrossControllerRAID = 0;
3651713e81bSScott Long 
3661713e81bSScott Long 
3671713e81bSScott Long 	cap->MinimumBlockSizeShift = MinBlockSizeShift;
3681713e81bSScott Long 	cap->MaximumBlockSizeShift = MaxBlockSizeShift;
3691713e81bSScott Long 	cap->SupportDiskModeSetting = 0;
3701713e81bSScott Long 	cap->SupportSparePool = 1;
3711713e81bSScott Long 	cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
3721713e81bSScott Long 	cap->SupportDedicatedSpare = 0;
3731713e81bSScott Long 
3741713e81bSScott Long 
3751713e81bSScott Long #ifdef SUPPORT_ARRAY
3761713e81bSScott Long 	/* Stripe */
3771713e81bSScott Long 	cap->SupportedRAIDTypes[0] = AT_RAID0;
3781713e81bSScott Long 	cap->MaximumArrayMembers[0] = MAX_MEMBERS;
3791713e81bSScott Long 	/* Mirror */
3801713e81bSScott Long 	cap->SupportedRAIDTypes[1] = AT_RAID1;
3811713e81bSScott Long 	cap->MaximumArrayMembers[1] = 2;
3821713e81bSScott Long 	/* Mirror + Stripe */
3831713e81bSScott Long #ifdef ARRAY_V2_ONLY
3841713e81bSScott Long 	cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
3851713e81bSScott Long #else
3861713e81bSScott Long 	cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
3871713e81bSScott Long #endif
3881713e81bSScott Long 	cap->MaximumArrayMembers[2] = MAX_MEMBERS;
3891713e81bSScott Long 	/* Jbod */
3901713e81bSScott Long 	cap->SupportedRAIDTypes[3] = AT_JBOD;
3911713e81bSScott Long 	cap->MaximumArrayMembers[3] = MAX_MEMBERS;
3921713e81bSScott Long 	/* RAID5 */
3931713e81bSScott Long #if SUPPORT_RAID5
3941713e81bSScott Long 	cap->SupportedRAIDTypes[4] = AT_RAID5;
3951713e81bSScott Long 	cap->MaximumArrayMembers[4] = MAX_MEMBERS;
3961713e81bSScott Long #endif
3971713e81bSScott Long #endif
3981713e81bSScott Long 	return 0;
3991713e81bSScott Long }
4001713e81bSScott Long 
hpt_get_controller_count(void)401d2bd3ab9SScott Long int hpt_get_controller_count(void)
4021713e81bSScott Long {
4031713e81bSScott Long 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
4041713e81bSScott Long 	int iControllerCount = 0;
4051713e81bSScott Long 
4064d24901aSPedro F. Giffuni 	while(pAdapTemp != NULL)
4071713e81bSScott Long 	{
4081713e81bSScott Long 		iControllerCount++;
4091713e81bSScott Long 		pAdapTemp = pAdapTemp->next;
4101713e81bSScott Long 	}
4111713e81bSScott Long 
4121713e81bSScott Long 	return iControllerCount;
4131713e81bSScott Long }
4141713e81bSScott Long 
hpt_get_controller_info(int id,PCONTROLLER_INFO pInfo)415d2bd3ab9SScott Long int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
4161713e81bSScott Long {
4171713e81bSScott Long 	IAL_ADAPTER_T    *pAdapTemp;
4181713e81bSScott Long 	int iControllerCount = 0;
4191713e81bSScott Long 
4201713e81bSScott Long 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
4211713e81bSScott Long 		if (iControllerCount++==id) {
4221713e81bSScott Long 			pInfo->InterruptLevel = 0;
4231713e81bSScott Long 			pInfo->ChipType = 0;
4241713e81bSScott Long 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
4251713e81bSScott Long 			strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
4261713e81bSScott Long #ifdef GUI_CONTROLLER_NAME
4271713e81bSScott Long #ifdef FORCE_ATA150_DISPLAY
4281713e81bSScott Long 			/* show "Bus Type: ATA/150" in GUI for SATA controllers */
4291713e81bSScott Long 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
4301713e81bSScott Long #endif
4311713e81bSScott Long 			strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
4321713e81bSScott Long #define _set_product_id(x)
4331713e81bSScott Long #else
4341713e81bSScott Long #define _set_product_id(x) strcpy(pInfo->szProductID, x)
4351713e81bSScott Long #endif
43664470755SXin LI 			_set_product_id("RocketRAID 18xx SATA Controller");
4371713e81bSScott Long 			pInfo->NumBuses = 8;
4381713e81bSScott Long 			pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
4391713e81bSScott Long 			return 0;
4401713e81bSScott Long 		}
4411713e81bSScott Long 	}
4421713e81bSScott Long 	return -1;
4431713e81bSScott Long }
4441713e81bSScott Long 
4451713e81bSScott Long 
hpt_get_channel_info(int id,int bus,PCHANNEL_INFO pInfo)446d2bd3ab9SScott Long int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
4471713e81bSScott Long {
4481713e81bSScott Long 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
4491713e81bSScott Long 	int i,iControllerCount = 0;
4501713e81bSScott Long 
4514d24901aSPedro F. Giffuni 	while(pAdapTemp != NULL)
4521713e81bSScott Long 	{
4531713e81bSScott Long 		if (iControllerCount++==id)
4541713e81bSScott Long 			goto found;
4551713e81bSScott Long 		pAdapTemp = pAdapTemp->next;
4561713e81bSScott Long 	}
4571713e81bSScott Long 	return -1;
4581713e81bSScott Long 
4591713e81bSScott Long found:
4601713e81bSScott Long 
4611713e81bSScott Long 	pInfo->IoPort = 0;
4621713e81bSScott Long 	pInfo->ControlPort = 0;
4631713e81bSScott Long 
4641713e81bSScott Long 	for (i=0; i<2 ;i++)
4651713e81bSScott Long 	{
4661713e81bSScott Long 		pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
4671713e81bSScott Long 	}
4681713e81bSScott Long 
4691713e81bSScott Long 	if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
4701713e81bSScott Long 		pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
4711713e81bSScott Long 	else
4721713e81bSScott Long 		pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
4731713e81bSScott Long 
4741713e81bSScott Long 	return 0;
4751713e81bSScott Long 
4761713e81bSScott Long 
4771713e81bSScott Long }
4781713e81bSScott Long 
hpt_get_logical_devices(DEVICEID * pIds,int nMaxCount)479d2bd3ab9SScott Long int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
4801713e81bSScott Long {
4811713e81bSScott Long 	int count = 0;
4821713e81bSScott Long 	int	i,j;
4831713e81bSScott Long 	PVDevice pPhysical, pLogical;
4841713e81bSScott Long 	IAL_ADAPTER_T    *pAdapTemp;
4851713e81bSScott Long 
4861713e81bSScott Long 	for(i = 0; i < nMaxCount; i++)
4871713e81bSScott Long 		pIds[i] = INVALID_DEVICEID;
4881713e81bSScott Long 
4891713e81bSScott Long 	/* append the arrays not registered on VBus */
4901713e81bSScott Long 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
4911713e81bSScott Long 		for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
4921713e81bSScott Long 		{
4931713e81bSScott Long 			pPhysical = &pAdapTemp->VDevices[i];
4941713e81bSScott Long 			pLogical = pPhysical;
4951713e81bSScott Long 
4961713e81bSScott Long 			while (pLogical->pParent) pLogical = pLogical->pParent;
4971713e81bSScott Long 			if (pLogical->VDeviceType==VD_SPARE)
4981713e81bSScott Long 				continue;
4991713e81bSScott Long 
5001713e81bSScott Long 			for (j=0; j<count; j++)
5011713e81bSScott Long 				if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
5021713e81bSScott Long 			pIds[count++] = VDEV_TO_ID(pLogical);
5031713e81bSScott Long 			if (count>=nMaxCount) goto done;
5041713e81bSScott Long 			next:;
5051713e81bSScott Long 		}
5061713e81bSScott Long 	}
5071713e81bSScott Long 
5081713e81bSScott Long done:
5091713e81bSScott Long 	return count;
5101713e81bSScott Long }
5111713e81bSScott Long 
hpt_get_device_info(DEVICEID id,PLOGICAL_DEVICE_INFO pInfo)512d2bd3ab9SScott Long int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
5131713e81bSScott Long {
5141713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(id);
5151713e81bSScott Long 
516d2bd3ab9SScott Long 	if((id == 0) || check_VDevice_valid(pVDevice))
5171713e81bSScott Long 		return -1;
5181713e81bSScott Long 
5191713e81bSScott Long #ifdef SUPPORT_ARRAY
52064470755SXin LI 	if (mIsArray(pVDevice)) {
52164470755SXin LI 		pInfo->Type = LDT_ARRAY;
52264470755SXin LI 		pInfo->Capacity = pVDevice->VDeviceCapacity;
52364470755SXin LI 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
52464470755SXin LI 		get_array_info(pVDevice, &pInfo->u.array);
5251713e81bSScott Long 		return 0;
5261713e81bSScott Long 	}
52764470755SXin LI #endif
52864470755SXin LI 
52964470755SXin LI 	pInfo->Type = LDT_DEVICE;
53064470755SXin LI 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
53164470755SXin LI 	/* report real capacity to be compatible with old arrays */
53264470755SXin LI 	pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
53364470755SXin LI 	return get_disk_info(pVDevice, &pInfo->u.device);
53464470755SXin LI }
53564470755SXin LI 
hpt_get_device_info_v2(DEVICEID id,PLOGICAL_DEVICE_INFO_V2 pInfo)53664470755SXin LI int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo)
53764470755SXin LI {
53864470755SXin LI 	PVDevice pVDevice = ID_TO_VDEV(id);
53964470755SXin LI 
54064470755SXin LI 	if((id == 0) || check_VDevice_valid(pVDevice))
54164470755SXin LI 		return -1;
54264470755SXin LI 
54364470755SXin LI #ifdef SUPPORT_ARRAY
54464470755SXin LI 	if (mIsArray(pVDevice)) {
54564470755SXin LI 		pInfo->Type = LDT_ARRAY;
54664470755SXin LI 		pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity;
54764470755SXin LI 		pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0;
54864470755SXin LI 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
54964470755SXin LI 		get_array_info_v2(pVDevice, &pInfo->u.array);
55064470755SXin LI 	return 0;
55164470755SXin LI }
55264470755SXin LI #endif
55364470755SXin LI 
55464470755SXin LI 	pInfo->Type = LDT_DEVICE;
55564470755SXin LI 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
55664470755SXin LI 	/* report real capacity to be compatible with old arrays */
55764470755SXin LI 	pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity;
55864470755SXin LI 	pInfo->Capacity.hi32 = 0;
55964470755SXin LI 	return get_disk_info(pVDevice, &pInfo->u.device);
56064470755SXin LI }
5611713e81bSScott Long 
5621713e81bSScott Long #ifdef SUPPORT_ARRAY
hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)56364470755SXin LI DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)
5641713e81bSScott Long {
5651713e81bSScott Long 	ULONG Stamp = GetStamp();
5661713e81bSScott Long 	int	i,j;
56764470755SXin LI 	LBA_T  capacity = MAX_LBA_T;
5681713e81bSScott Long 	PVDevice pArray,pChild;
5691713e81bSScott Long 	int		Loca = -1;
5701713e81bSScott Long 
57164470755SXin LI 	if (pParam->nDisk > MAX_MEMBERS)
57264470755SXin LI 		return INVALID_DEVICEID;
57364470755SXin LI /* check in verify_vd
5741713e81bSScott Long 	for(i = 0; i < pParam->nDisk; i++)
5751713e81bSScott Long 	{
5761713e81bSScott Long 		PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
5771713e81bSScott Long 		if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
5781713e81bSScott Long 		if (mIsArray(pVDev)) return INVALID_DEVICEID;
5791713e81bSScott Long 		if (!pVDev->vf_online) return INVALID_DEVICEID;
5801713e81bSScott Long 		if (!_vbus_p)
5811713e81bSScott Long 			_vbus_p = pVDev->u.disk.pVBus;
5821713e81bSScott Long 		else if (_vbus_p != pVDev->u.disk.pVBus)
5831713e81bSScott Long 			return INVALID_DEVICEID;
5841713e81bSScott Long 	}
58564470755SXin LI */
58664470755SXin LI 	_vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus;
5871713e81bSScott Long 	if (!_vbus_p) return INVALID_DEVICEID;
5881713e81bSScott Long 
5891713e81bSScott Long 	mArGetArrayTable(pArray);
5901713e81bSScott Long 	if(!pArray)	return INVALID_DEVICEID;
5911713e81bSScott Long 
5921713e81bSScott Long 	switch (pParam->ArrayType)
5931713e81bSScott Long 	{
5941713e81bSScott Long 		case AT_JBOD:
5951713e81bSScott Long 			pArray->VDeviceType = VD_JBOD;
5961713e81bSScott Long 			goto simple;
5971713e81bSScott Long 
5981713e81bSScott Long 		case AT_RAID0:
5991713e81bSScott Long 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
6001713e81bSScott Long 				goto error;
6011713e81bSScott Long 			pArray->VDeviceType = VD_RAID_0;
6021713e81bSScott Long 			goto simple;
6031713e81bSScott Long 
6041713e81bSScott Long 		case AT_RAID5:
6051713e81bSScott Long 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
6061713e81bSScott Long 				goto error;
6071713e81bSScott Long 			pArray->VDeviceType = VD_RAID_5;
6081713e81bSScott Long 			/* only "no build" R5 is not critical after creation. */
6091713e81bSScott Long 			if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
6101713e81bSScott Long 				pArray->u.array.rf_need_rebuild = 1;
6111713e81bSScott Long 			goto simple;
6121713e81bSScott Long 
6131713e81bSScott Long 		case AT_RAID1:
6141713e81bSScott Long 			if(pParam->nDisk <= 2)
6151713e81bSScott Long 			{
6161713e81bSScott Long 				pArray->VDeviceType = VD_RAID_1;
6171713e81bSScott Long simple:
6181713e81bSScott Long 				pArray->u.array.bArnMember = pParam->nDisk;
6191713e81bSScott Long 				pArray->u.array.bArRealnMember = pParam->nDisk;
6201713e81bSScott Long 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
6211713e81bSScott Long 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
6221713e81bSScott Long 				pArray->u.array.dArStamp = Stamp;
6231713e81bSScott Long 
6241713e81bSScott Long 				pArray->u.array.rf_need_sync = 1;
6251713e81bSScott Long 				pArray->u.array.rf_newly_created = 1;
6261713e81bSScott Long 
6271713e81bSScott Long 				if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
6281713e81bSScott Long 					(pArray->VDeviceType == VD_RAID_1))
6291713e81bSScott Long 				{
6301713e81bSScott Long 					pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
6311713e81bSScott Long 					pArray->u.array.rf_need_rebuild = 1;
6321713e81bSScott Long 					pArray->u.array.rf_auto_rebuild = 1;
6331713e81bSScott Long 					pArray->u.array.rf_duplicate_and_create = 1;
6341713e81bSScott Long 
6351713e81bSScott Long 					for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
6361713e81bSScott Long 						if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
6371713e81bSScott Long 							Loca = i;
6381713e81bSScott Long 				}
6391713e81bSScott Long 
6401713e81bSScott Long 				pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
6411713e81bSScott Long 
6421713e81bSScott Long 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
6431713e81bSScott Long 
6441713e81bSScott Long 				for(i = 0; i < pParam->nDisk; i++)
6451713e81bSScott Long 				{
6461713e81bSScott Long 					pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
6471713e81bSScott Long 					pArray->u.array.pMember[i]->bSerialNumber = i;
6481713e81bSScott Long 					pArray->u.array.pMember[i]->pParent = pArray;
6491713e81bSScott Long 
6501713e81bSScott Long 					/* don't unregister source disk for duplicate RAID1 */
6511713e81bSScott Long 					if (i ||
6521713e81bSScott Long 						pArray->VDeviceType!=VD_RAID_1 ||
6531713e81bSScott Long 						(pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
6541713e81bSScott Long 						UnregisterVDevice(pArray->u.array.pMember[i]);
6551713e81bSScott Long 
6561713e81bSScott Long 					if(pArray->VDeviceType == VD_RAID_5)
6571713e81bSScott Long 						pArray->u.array.pMember[i]->vf_cache_disk = 1;
6581713e81bSScott Long 				}
6591713e81bSScott Long 			}
6601713e81bSScott Long 			else
6611713e81bSScott Long 			{
6621713e81bSScott Long 				for(i = 0; i < (pParam->nDisk / 2); i++)
6631713e81bSScott Long 				{
6641713e81bSScott Long 					mArGetArrayTable(pChild);
6651713e81bSScott Long 					pChild->VDeviceType = VD_RAID_1;
6661713e81bSScott Long 
6671713e81bSScott Long 					pChild->u.array.bArnMember = 2;
6681713e81bSScott Long 					pChild->u.array.bArRealnMember = 2;
6691713e81bSScott Long 					pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
6701713e81bSScott Long 					pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
6711713e81bSScott Long 					pChild->u.array.dArStamp = Stamp;
6721713e81bSScott Long 
6731713e81bSScott Long 					pChild->u.array.rf_need_sync = 1;
6741713e81bSScott Long 					pChild->u.array.rf_newly_created = 1;
6751713e81bSScott Long 
6761713e81bSScott Long 					pChild->u.array.RebuildSectors = MAX_LBA_T;
6771713e81bSScott Long 
6781713e81bSScott Long 					memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
6791713e81bSScott Long 
6801713e81bSScott Long 					for(j = 0; j < 2; j++)
6811713e81bSScott Long 					{
6821713e81bSScott Long 						pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
6831713e81bSScott Long 						pChild->u.array.pMember[j]->bSerialNumber = j;
6841713e81bSScott Long 						pChild->u.array.pMember[j]->pParent = pChild;
6851713e81bSScott Long 						pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
6861713e81bSScott Long 						UnregisterVDevice(pChild->u.array.pMember[j]);
6871713e81bSScott Long 					}
6881713e81bSScott Long 
6891713e81bSScott Long 					pArray->u.array.pMember[i] = pChild;
6901713e81bSScott Long 
6911713e81bSScott Long 					pChild->vf_online = 1;
6921713e81bSScott Long 					pChild->bSerialNumber = i;
6931713e81bSScott Long 					pChild->pParent = pArray;
6941713e81bSScott Long 					pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
6951713e81bSScott Long 						pChild->u.array.pMember[1]->VDeviceCapacity);
6961713e81bSScott Long 
6971713e81bSScott Long 					pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
6981713e81bSScott Long 					pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
6991713e81bSScott Long 				}
7001713e81bSScott Long 
7011713e81bSScott Long 				pArray->VDeviceType = VD_RAID_0;
7021713e81bSScott Long 
7031713e81bSScott Long 				pArray->u.array.bArnMember = pParam->nDisk / 2;
7041713e81bSScott Long 				pArray->u.array.bArRealnMember = pParam->nDisk / 2;
7051713e81bSScott Long 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
7061713e81bSScott Long 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
7071713e81bSScott Long 				pArray->u.array.dArStamp = Stamp;
7081713e81bSScott Long 
7091713e81bSScott Long 				pArray->u.array.rf_need_sync = 1;
7101713e81bSScott Long 				pArray->u.array.rf_newly_created = 1;
7111713e81bSScott Long 
7121713e81bSScott Long 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
7131713e81bSScott Long 			}
7141713e81bSScott Long 			break;
7151713e81bSScott Long 
7161713e81bSScott Long 		default:
7171713e81bSScott Long 			goto error;
7181713e81bSScott Long 	}
7191713e81bSScott Long 
7201713e81bSScott Long 	for(i = 0; i < pArray->u.array.bArnMember; i++)
7211713e81bSScott Long 		pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
7221713e81bSScott Long 
7231713e81bSScott Long 	if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
7241713e81bSScott Long 		(pArray->VDeviceType == VD_RAID_1))
7251713e81bSScott Long 	{
7261713e81bSScott Long 		pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
7271713e81bSScott Long 		pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
7281713e81bSScott Long 		pArray->u.array.pMember[0]->vf_bootable = 0;
7291713e81bSScott Long 		pArray->u.array.pMember[0]->vf_bootmark = 0;
7301713e81bSScott Long 		if (Loca>=0) {
7311713e81bSScott Long 			_vbus_p->pVDevice[Loca] = pArray;
7321713e81bSScott Long 			/* to comfort OS */
7331713e81bSScott Long 			pArray->u.array.rf_duplicate_and_created = 1;
7341713e81bSScott Long 			pArray->pVBus = _vbus_p;
7351713e81bSScott Long 		}
7361713e81bSScott Long 	}
7371713e81bSScott Long 	else {
7381713e81bSScott Long 		UCHAR TempBuffer[512];
7391713e81bSScott Long 		ZeroMemory(TempBuffer, 512);
7401713e81bSScott Long 		for(i = 0; i < pParam->nDisk; i++)
7411713e81bSScott Long 		{
7421713e81bSScott Long 			PVDevice	pDisk = ID_TO_VDEV(pParam->Members[i]);
7431713e81bSScott Long 			pDisk->vf_bootmark = pDisk->vf_bootable = 0;
7441713e81bSScott Long 			fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
7451713e81bSScott Long 		}
7461713e81bSScott Long 	}
7471713e81bSScott Long 
7481713e81bSScott Long 	pArray->vf_online = 1;
7491713e81bSScott Long 	pArray->pParent = NULL;
7501713e81bSScott Long 
7511713e81bSScott Long 	switch(pArray->VDeviceType)
7521713e81bSScott Long 	{
7531713e81bSScott Long 		case VD_RAID_0:
7541713e81bSScott Long 			for(i = 0; i < pArray->u.array.bArnMember; i++)
7551713e81bSScott Long 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
7561713e81bSScott Long 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
7571713e81bSScott Long #ifdef ARRAY_V2_ONLY
7581713e81bSScott Long 			capacity -= 10;
7591713e81bSScott Long #endif
7601713e81bSScott Long 			capacity &= ~(pArray->u.array.bStripeWitch - 1);
7611713e81bSScott Long 			/* shrink member capacity for RAID 1/0 */
7621713e81bSScott Long 			for(i = 0; i < pArray->u.array.bArnMember; i++)
7631713e81bSScott Long 				if (mIsArray(pArray->u.array.pMember[i]))
7641713e81bSScott Long 					pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
7651713e81bSScott Long 			pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
7661713e81bSScott Long 			break;
7671713e81bSScott Long 
7681713e81bSScott Long 		case VD_RAID_1:
7691713e81bSScott Long 			pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
7701713e81bSScott Long 						pArray->u.array.pMember[1]->VDeviceCapacity);
7711713e81bSScott Long 			break;
7721713e81bSScott Long 
7731713e81bSScott Long 		case VD_JBOD:
7741713e81bSScott Long 			for(i = 0; i < pArray->u.array.bArnMember; i++)
7751713e81bSScott Long 				pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
7761713e81bSScott Long #ifdef ARRAY_V2_ONLY
7771713e81bSScott Long 				-10
7781713e81bSScott Long #endif
7791713e81bSScott Long 				;
7801713e81bSScott Long 			break;
7811713e81bSScott Long 
7821713e81bSScott Long 		case VD_RAID_5:
7831713e81bSScott Long 			for(i = 0; i < pArray->u.array.bArnMember; i++)
7841713e81bSScott Long 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
7851713e81bSScott Long 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
786d9c9c81cSPedro F. Giffuni 			pArray->VDeviceCapacity = rounddown2(capacity, pArray->u.array.bStripeWitch) *
787d9c9c81cSPedro F. Giffuni 			    (pArray->u.array.bArnMember - 1);
7881713e81bSScott Long 			break;
7891713e81bSScott Long 
7901713e81bSScott Long 		default:
7911713e81bSScott Long 			goto error;
7921713e81bSScott Long 	}
7931713e81bSScott Long 
7941713e81bSScott Long 	pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
7951713e81bSScott Long 	pArray->pfnDeviceFailed = fOsDiskFailed;
7961713e81bSScott Long 	SyncArrayInfo(pArray);
7971713e81bSScott Long 
7981713e81bSScott Long 	if (!pArray->u.array.rf_duplicate_and_created)
7991713e81bSScott Long 		RegisterVDevice(pArray);
8001713e81bSScott Long 	return VDEV_TO_ID(pArray);
8011713e81bSScott Long 
8021713e81bSScott Long error:
8031713e81bSScott Long 	for(i = 0; i < pArray->u.array.bArnMember; i++)
8041713e81bSScott Long 	{
8051713e81bSScott Long 		pChild = pArray->u.array.pMember[i];
8061713e81bSScott Long 		if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
8071713e81bSScott Long 			mArFreeArrayTable(pChild);
8081713e81bSScott Long 	}
8091713e81bSScott Long 	mArFreeArrayTable(pArray);
8101713e81bSScott Long 	return INVALID_DEVICEID;
8111713e81bSScott Long }
8121713e81bSScott Long 
hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)81364470755SXin LI DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
81464470755SXin LI {
81564470755SXin LI 	CREATE_ARRAY_PARAMS_V2 param2;
81664470755SXin LI 	param2.ArrayType = pParam->ArrayType;
81764470755SXin LI 	param2.nDisk = pParam->nDisk;
81864470755SXin LI 	param2.BlockSizeShift = pParam->BlockSizeShift;
81964470755SXin LI 	param2.CreateFlags = pParam->CreateFlags;
82064470755SXin LI 	param2.CreateTime = pParam->CreateTime;
82164470755SXin LI 	memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName));
82264470755SXin LI 	memcpy(param2.Description, pParam->Description, sizeof(param2.Description));
82364470755SXin LI 	memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager));
82464470755SXin LI 	param2.Capacity.lo32 = param2.Capacity.hi32 = 0;
82564470755SXin LI 	memcpy(param2.Members, pParam->Members, sizeof(pParam->Members));
82664470755SXin LI 	return hpt_create_array_v2(_VBUS_P &param2);
82764470755SXin LI }
82864470755SXin LI 
8291713e81bSScott Long #ifdef SUPPORT_OLD_ARRAY
8301713e81bSScott Long /* this is only for old RAID 0/1 */
old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray,DEVICEID idDisk)8311713e81bSScott Long int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
8321713e81bSScott Long {
8331713e81bSScott Long 	PVDevice pArray1 = ID_TO_VDEV(idArray);
8341713e81bSScott Long 	PVDevice pArray2 = 0;
8351713e81bSScott Long 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
8361713e81bSScott Long 	int	i;
8371713e81bSScott Long 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
8381713e81bSScott Long 
8391713e81bSScott Long 	if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
8401713e81bSScott Long 
8411713e81bSScott Long 	if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
8421713e81bSScott Long 		return -1;
8431713e81bSScott Long 
8441713e81bSScott Long 	pArray2 = pArray1->u.array.pMember[1];
8451713e81bSScott Long 	if(pArray2 == NULL)	{
8461713e81bSScott Long 		/* create a Stripe */
8471713e81bSScott Long 		mArGetArrayTable(pArray2);
8481713e81bSScott Long 		pArray2->VDeviceType = VD_RAID_0;
8491713e81bSScott Long 		pArray2->u.array.dArStamp = GetStamp();
8501713e81bSScott Long 		pArray2->vf_format_v2 = 1;
8511713e81bSScott Long 		pArray2->u.array.rf_broken = 1;
8521713e81bSScott Long 		pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
8531713e81bSScott Long 		pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
8541713e81bSScott Long 		pArray2->u.array.bArnMember = 2;
8551713e81bSScott Long 		pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
8561713e81bSScott Long 		pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
8571713e81bSScott Long 		pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
8581713e81bSScott Long 		memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);
8591713e81bSScott Long 		pArray2->pParent = pArray1;
8601713e81bSScott Long 		pArray2->bSerialNumber = 1;
8611713e81bSScott Long 		pArray1->u.array.pMember[1] = pArray2;
8621713e81bSScott Long 		pArray1->u.array.bArRealnMember++;
8631713e81bSScott Long 	}
8641713e81bSScott Long 
8651713e81bSScott Long 	for(i = 0; i < pArray2->u.array.bArnMember; i++)
8661713e81bSScott Long 		if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
8671713e81bSScott Long 		{
8681713e81bSScott Long 			if(pArray2->u.array.pMember[i] != NULL)
8691713e81bSScott Long 				pArray2->u.array.pMember[i]->pParent = NULL;
8701713e81bSScott Long 			pArray2->u.array.pMember[i] = pDisk;
8711713e81bSScott Long 			goto find;
8721713e81bSScott Long 		}
8731713e81bSScott Long 	return -1;
8741713e81bSScott Long 
8751713e81bSScott Long find:
8761713e81bSScott Long 	UnregisterVDevice(pDisk);
8771713e81bSScott Long 	pDisk->VDeviceType = VD_SINGLE_DISK;
8781713e81bSScott Long 	pDisk->bSerialNumber = i;
8791713e81bSScott Long 	pDisk->pParent = pArray2;
8801713e81bSScott Long 	pDisk->vf_format_v2 = 1;
8811713e81bSScott Long 	pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
8821713e81bSScott Long 	pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
8831713e81bSScott Long 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
8841713e81bSScott Long 
8851713e81bSScott Long 	pArray2->u.array.bArRealnMember++;
8861713e81bSScott Long 	if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){
8871713e81bSScott Long 		pArray2->vf_online = 1;
8881713e81bSScott Long 		pArray2->u.array.rf_broken = 0;
8891713e81bSScott Long 	}
8901713e81bSScott Long 
8911713e81bSScott Long 	if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
8921713e81bSScott Long 		pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
8931713e81bSScott Long 		pArray1->u.array.rf_broken = 0;
8941713e81bSScott Long 		pArray1->u.array.rf_need_rebuild = 1;
8951713e81bSScott Long 		pArray1->u.array.rf_auto_rebuild = 1;
8961713e81bSScott Long 
8971713e81bSScott Long 	}
8981713e81bSScott Long 	pArray1->u.array.RebuildSectors = 0;
8991713e81bSScott Long 	pArray1->u.array.dArStamp = GetStamp();
9001713e81bSScott Long 	SyncArrayInfo(pArray1);
9011713e81bSScott Long 	return 1;
9021713e81bSScott Long }
9031713e81bSScott Long #endif
9041713e81bSScott Long 
hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray,DEVICEID idDisk)9051713e81bSScott Long int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
9061713e81bSScott Long {
9071713e81bSScott Long 	int	i;
9081713e81bSScott Long 
90964470755SXin LI 	LBA_T Capacity;
9101713e81bSScott Long 	PVDevice pArray = ID_TO_VDEV(idArray);
9111713e81bSScott Long 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
9121713e81bSScott Long 
913d2bd3ab9SScott Long 	if((idArray == 0) || (idDisk == 0))	return -1;
9141713e81bSScott Long 	if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk))	return -1;
9151713e81bSScott Long 	if(!pArray->u.array.rf_broken)	return -1;
9161713e81bSScott Long 
9171713e81bSScott Long 	if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
9181713e81bSScott Long 		return -1;
9191713e81bSScott Long 	if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
9201713e81bSScott Long 		return -1;
9211713e81bSScott Long 
9221713e81bSScott Long #ifdef SUPPORT_OLD_ARRAY
9231713e81bSScott Long 	/* RAID 0 + 1 */
9241713e81bSScott Long 	if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 &&
9251713e81bSScott Long 		pArray->u.array.pMember[0] &&
9261713e81bSScott Long 		mIsArray(pArray->u.array.pMember[0]))
9271713e81bSScott Long 	{
9281713e81bSScott Long 		if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
9291713e81bSScott Long 			return 0;
9301713e81bSScott Long 		else
9311713e81bSScott Long 			return -1;
9321713e81bSScott Long 	}
9331713e81bSScott Long #endif
9341713e81bSScott Long 
9351713e81bSScott Long 	Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
9361713e81bSScott Long 
9371713e81bSScott Long 	if (pArray->vf_format_v2) {
9381713e81bSScott Long 		if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
9391713e81bSScott Long 	}
9401713e81bSScott Long 	else
9411713e81bSScott Long 		if(pDisk->VDeviceCapacity < Capacity) return -1;
9421713e81bSScott Long 
9431713e81bSScott Long 	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
9441713e81bSScott Long 
9451713e81bSScott Long 	for(i = 0; i < pArray->u.array.bArnMember; i++)
94664470755SXin LI 		if((pArray->u.array.pMember[i] == 0) || !pArray->u.array.pMember[i]->vf_online)
9471713e81bSScott Long 		{
9481713e81bSScott Long 			if(pArray->u.array.pMember[i] != NULL)
9491713e81bSScott Long 				pArray->u.array.pMember[i]->pParent = NULL;
9501713e81bSScott Long 			pArray->u.array.pMember[i] = pDisk;
9511713e81bSScott Long 			goto find;
9521713e81bSScott Long 		}
9531713e81bSScott Long 	return -1;
9541713e81bSScott Long 
9551713e81bSScott Long find:
9561713e81bSScott Long 	UnregisterVDevice(pDisk);
9571713e81bSScott Long 	pDisk->VDeviceType = VD_SINGLE_DISK;
9581713e81bSScott Long 	pDisk->bSerialNumber = i;
9591713e81bSScott Long 	pDisk->pParent = pArray;
9601713e81bSScott Long 	if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
9611713e81bSScott Long 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
9621713e81bSScott Long 	if (pArray->vf_format_v2) {
9631713e81bSScott Long 		pDisk->vf_format_v2 = 1;
9641713e81bSScott Long 		pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
9651713e81bSScott Long 	}
9661713e81bSScott Long 
9671713e81bSScott Long 	pArray->u.array.bArRealnMember++;
9681713e81bSScott Long 	if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
9691713e81bSScott Long 	{
9701713e81bSScott Long 		pArray->u.array.rf_need_rebuild = 1;
9711713e81bSScott Long 		pArray->u.array.RebuildSectors = 0;
9721713e81bSScott Long 		pArray->u.array.rf_auto_rebuild = 1;
9731713e81bSScott Long 		pArray->u.array.rf_broken = 0;
9741713e81bSScott Long 	}
9751713e81bSScott Long 	pArray->u.array.RebuildSectors = 0;
9761713e81bSScott Long 
9771713e81bSScott Long 	/* sync the whole array */
9781713e81bSScott Long 	while (pArray->pParent) pArray = pArray->pParent;
9791713e81bSScott Long 	pArray->u.array.dArStamp = GetStamp();
9801713e81bSScott Long 	SyncArrayInfo(pArray);
9811713e81bSScott Long 	return 0;
9821713e81bSScott Long }
9831713e81bSScott Long 
hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)984d2bd3ab9SScott Long int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
9851713e81bSScott Long {
9861713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
9871713e81bSScott Long 	DECLARE_BUFFER(PUCHAR, pbuffer);
9881713e81bSScott Long 
989d2bd3ab9SScott Long 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
9901713e81bSScott Long 	if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
9911713e81bSScott Long 		return -1;
9921713e81bSScott Long 
9931713e81bSScott Long 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
9941713e81bSScott Long 
9951713e81bSScott Long 	UnregisterVDevice(pVDevice);
9961713e81bSScott Long 	pVDevice->VDeviceType = VD_SPARE;
9971713e81bSScott Long 	pVDevice->vf_bootmark = 0;
9981713e81bSScott Long 
9991713e81bSScott Long 	ZeroMemory((char *)pbuffer, 512);
10001713e81bSScott Long 	fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
10011713e81bSScott Long 	SyncArrayInfo(pVDevice);
10021713e81bSScott Long 	return 0;
10031713e81bSScott Long }
10041713e81bSScott Long 
hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)1005d2bd3ab9SScott Long int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
10061713e81bSScott Long {
10071713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
10081713e81bSScott Long 
10091713e81bSScott Long 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
10101713e81bSScott Long 
10111713e81bSScott Long 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
10121713e81bSScott Long 
10131713e81bSScott Long 	pVDevice->VDeviceType = VD_SINGLE_DISK;
10141713e81bSScott Long 
10151713e81bSScott Long 	SyncArrayInfo(pVDevice);
10161713e81bSScott Long 	RegisterVDevice(pVDevice);
10171713e81bSScott Long 	return 0;
10181713e81bSScott Long }
10191713e81bSScott Long 
hpt_set_array_info(_VBUS_ARG DEVICEID idArray,PALTERABLE_ARRAY_INFO pInfo)1020d2bd3ab9SScott Long int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
10211713e81bSScott Long {
10221713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idArray);
10231713e81bSScott Long 
1024d2bd3ab9SScott Long 	if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
10251713e81bSScott Long 	if (!mIsArray(pVDevice)) return -1;
10261713e81bSScott Long 
10271713e81bSScott Long 	/* if the pVDevice isn't a top level, return -1; */
10281713e81bSScott Long 	if(pVDevice->pParent != NULL) return -1;
10291713e81bSScott Long 
10301713e81bSScott Long 	if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
10311713e81bSScott Long 
10321713e81bSScott Long 	if (pInfo->ValidFields & AAIF_NAME) {
10331713e81bSScott Long 		memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
10341713e81bSScott Long 		memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
10351713e81bSScott Long 		pVDevice->u.array.rf_need_sync = 1;
10361713e81bSScott Long 	}
10371713e81bSScott Long 
10381713e81bSScott Long 	if (pInfo->ValidFields & AAIF_DESCRIPTION) {
10391713e81bSScott Long 		memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
10401713e81bSScott Long 		pVDevice->u.array.rf_need_sync = 1;
10411713e81bSScott Long 	}
10421713e81bSScott Long 
10431713e81bSScott Long 	if (pVDevice->u.array.rf_need_sync)
10441713e81bSScott Long 		SyncArrayInfo(pVDevice);
10451713e81bSScott Long 	return 0;
10461713e81bSScott Long }
10471713e81bSScott Long 
hpt_set_device_info(_VBUS_ARG DEVICEID idDisk,PALTERABLE_DEVICE_INFO pInfo)104864470755SXin LI static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
10491713e81bSScott Long {
10501713e81bSScott Long 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
10511713e81bSScott Long 
105264470755SXin LI 	if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
10531713e81bSScott Long 	if (mIsArray(pVDevice))
10541713e81bSScott Long 		return -1;
10551713e81bSScott Long 
10561713e81bSScott Long 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
10571713e81bSScott Long 
105864470755SXin LI 	/* TODO */
105964470755SXin LI 		return 0;
106064470755SXin LI 	}
106164470755SXin LI 
hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk,PALTERABLE_DEVICE_INFO_V2 pInfo)106264470755SXin LI static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo)
106364470755SXin LI {
106464470755SXin LI 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
106564470755SXin LI 	int sync = 0;
106664470755SXin LI 
106764470755SXin LI 	if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1;
106864470755SXin LI 	if (mIsArray(pVDevice))
106964470755SXin LI 		return -1;
107064470755SXin LI 
107164470755SXin LI 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
107264470755SXin LI 
107364470755SXin LI 	if (pInfo->ValidFields & ADIF_MODE) {
10741713e81bSScott Long 		pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
10751713e81bSScott Long 		pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
10761713e81bSScott Long 		pVDevice->u.disk.df_user_mode_set = 1;
10771713e81bSScott Long 		fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
107864470755SXin LI 		sync = 1;
107964470755SXin LI }
108064470755SXin LI 
108164470755SXin LI 	if (pInfo->ValidFields & ADIF_TCQ) {
108264470755SXin LI 		if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) {
108364470755SXin LI 			pVDevice->u.disk.df_tcq_set = 1;
108464470755SXin LI 			pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0;
108564470755SXin LI 			sync = 1;
108664470755SXin LI }
108764470755SXin LI 	}
108864470755SXin LI 
108964470755SXin LI 	if (pInfo->ValidFields & ADIF_NCQ) {
109064470755SXin LI 		if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) {
109164470755SXin LI 			pVDevice->u.disk.df_ncq_set = 1;
109264470755SXin LI 			pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0;
109364470755SXin LI 			sync = 1;
109464470755SXin LI 	}
109564470755SXin LI 	}
109664470755SXin LI 
109764470755SXin LI 	if (pInfo->ValidFields & ADIF_WRITE_CACHE) {
109864470755SXin LI 		if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) {
109964470755SXin LI 			pVDevice->u.disk.df_write_cache_set = 1;
110064470755SXin LI 			pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0;
110164470755SXin LI 			sync = 1;
110264470755SXin LI 	}
110364470755SXin LI 	}
110464470755SXin LI 
110564470755SXin LI 	if (pInfo->ValidFields & ADIF_READ_AHEAD) {
110664470755SXin LI 		if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) {
110764470755SXin LI 			pVDevice->u.disk.df_read_ahead_set = 1;
110864470755SXin LI 			pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0;
110964470755SXin LI 			sync = 1;
111064470755SXin LI 		}
111164470755SXin LI 	}
111264470755SXin LI 
111364470755SXin LI 	if (sync)
11141713e81bSScott Long 		SyncArrayInfo(pVDevice);
11151713e81bSScott Long 	return 0;
11161713e81bSScott Long }
11171713e81bSScott Long 
11181713e81bSScott Long #endif
11191713e81bSScott Long 
11201713e81bSScott Long /* hpt_default_ioctl()
11211713e81bSScott Long  *  This is a default implementation. The platform dependent part
11221713e81bSScott Long  *  may reuse this function and/or use it own implementation for
11231713e81bSScott Long  *  each ioctl function.
11241713e81bSScott Long  */
hpt_default_ioctl(_VBUS_ARG DWORD dwIoControlCode,PVOID lpInBuffer,DWORD nInBufferSize,PVOID lpOutBuffer,DWORD nOutBufferSize,PDWORD lpBytesReturned)11251713e81bSScott Long int hpt_default_ioctl(_VBUS_ARG
11261713e81bSScott Long 							DWORD dwIoControlCode,       	/* operation control code */
11271713e81bSScott Long 							PVOID lpInBuffer,            	/* input data buffer */
11281713e81bSScott Long 							DWORD nInBufferSize,         	/* size of input data buffer */
11291713e81bSScott Long 							PVOID lpOutBuffer,           	/* output data buffer */
11301713e81bSScott Long 							DWORD nOutBufferSize,        	/* size of output data buffer */
11311713e81bSScott Long 							PDWORD lpBytesReturned      	/* byte count */
11321713e81bSScott Long 					)
11331713e81bSScott Long {
11341713e81bSScott Long 	switch(dwIoControlCode)	{
11351713e81bSScott Long 
11361713e81bSScott Long 	case HPT_IOCTL_GET_VERSION:
11371713e81bSScott Long 
11381713e81bSScott Long 		if (nInBufferSize != 0) return -1;
11391713e81bSScott Long 		if (nOutBufferSize != sizeof(DWORD)) return -1;
11401713e81bSScott Long 		*((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
11411713e81bSScott Long 		break;
11421713e81bSScott Long 
11431713e81bSScott Long 	case HPT_IOCTL_GET_CONTROLLER_COUNT:
11441713e81bSScott Long 
11451713e81bSScott Long 		if (nOutBufferSize!=sizeof(DWORD)) return -1;
11461713e81bSScott Long 		*(PDWORD)lpOutBuffer = hpt_get_controller_count();
11471713e81bSScott Long 		break;
11481713e81bSScott Long 
11491713e81bSScott Long 	case HPT_IOCTL_GET_CONTROLLER_INFO:
11501713e81bSScott Long 		{
11511713e81bSScott Long 			int id;
11521713e81bSScott Long 			PCONTROLLER_INFO pInfo;
11531713e81bSScott Long 
11541713e81bSScott Long 			if (nInBufferSize!=sizeof(DWORD)) return -1;
11551713e81bSScott Long 			if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
11561713e81bSScott Long 
11571713e81bSScott Long 			id = *(DWORD *)lpInBuffer;
11581713e81bSScott Long 			pInfo = (PCONTROLLER_INFO)lpOutBuffer;
11591713e81bSScott Long 			if (hpt_get_controller_info(id, pInfo)!=0)
11601713e81bSScott Long 				return -1;
11611713e81bSScott Long 		}
11621713e81bSScott Long 		break;
11631713e81bSScott Long 
11641713e81bSScott Long 	case HPT_IOCTL_GET_CHANNEL_INFO:
11651713e81bSScott Long 		{
11661713e81bSScott Long 			int id, bus;
11671713e81bSScott Long 			PCHANNEL_INFO pInfo;
11681713e81bSScott Long 
11691713e81bSScott Long 			if (nInBufferSize!=8) return -1;
11701713e81bSScott Long 			if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
11711713e81bSScott Long 
11721713e81bSScott Long 			id = *(DWORD *)lpInBuffer;
11731713e81bSScott Long 			bus = ((DWORD *)lpInBuffer)[1];
11741713e81bSScott Long 			pInfo = (PCHANNEL_INFO)lpOutBuffer;
11751713e81bSScott Long 
11761713e81bSScott Long 			if (hpt_get_channel_info(id, bus, pInfo)!=0)
11771713e81bSScott Long 				return -1;
11781713e81bSScott Long 		}
11791713e81bSScott Long 		break;
11801713e81bSScott Long 
11811713e81bSScott Long 	case HPT_IOCTL_GET_LOGICAL_DEVICES:
11821713e81bSScott Long 		{
11831713e81bSScott Long 			DWORD nMax;
11841713e81bSScott Long 			DEVICEID *pIds;
11851713e81bSScott Long 
11861713e81bSScott Long 			if (nInBufferSize!=sizeof(DWORD)) return -1;
11871713e81bSScott Long 			nMax = *(DWORD *)lpInBuffer;
11881713e81bSScott Long 			if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
11891713e81bSScott Long 
11901713e81bSScott Long 			pIds = ((DEVICEID *)lpOutBuffer)+1;
11911713e81bSScott Long 			*(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
11921713e81bSScott Long 		}
11931713e81bSScott Long 		break;
11941713e81bSScott Long 
11951713e81bSScott Long 	case HPT_IOCTL_GET_DEVICE_INFO:
11961713e81bSScott Long 		{
11971713e81bSScott Long 			DEVICEID id;
11981713e81bSScott Long 			PLOGICAL_DEVICE_INFO pInfo;
11991713e81bSScott Long 
12001713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
12011713e81bSScott Long 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
12021713e81bSScott Long 
12031713e81bSScott Long 			id = *(DWORD *)lpInBuffer;
12041713e81bSScott Long 			if (id == INVALID_DEVICEID)	return -1;
12051713e81bSScott Long 
12061713e81bSScott Long 			pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
12071713e81bSScott Long 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
12081713e81bSScott Long 
12091713e81bSScott Long 			if (hpt_get_device_info(id, pInfo)!=0)
12101713e81bSScott Long 				return -1;
12111713e81bSScott Long 		}
12121713e81bSScott Long 		break;
12131713e81bSScott Long 
121464470755SXin LI 	case HPT_IOCTL_GET_DEVICE_INFO_V2:
121564470755SXin LI 		{
121664470755SXin LI 			DEVICEID id;
121764470755SXin LI 			PLOGICAL_DEVICE_INFO_V2 pInfo;
121864470755SXin LI 
121964470755SXin LI 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
122064470755SXin LI 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1;
122164470755SXin LI 
122264470755SXin LI 			id = *(DWORD *)lpInBuffer;
122364470755SXin LI 			if (id == INVALID_DEVICEID)	return -1;
122464470755SXin LI 
122564470755SXin LI 			pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer;
122664470755SXin LI 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2));
122764470755SXin LI 
122864470755SXin LI 			if (hpt_get_device_info_v2(id, pInfo)!=0)
122964470755SXin LI 				return -1;
123064470755SXin LI 		}
123164470755SXin LI 		break;
123264470755SXin LI 
12331713e81bSScott Long #ifdef SUPPORT_ARRAY
12341713e81bSScott Long 	case HPT_IOCTL_CREATE_ARRAY:
12351713e81bSScott Long 		{
12361713e81bSScott Long 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
12371713e81bSScott Long 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
12381713e81bSScott Long 
123964470755SXin LI 			*(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer);
12401713e81bSScott Long 
124164470755SXin LI 			if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
124264470755SXin LI 				return -1;
124364470755SXin LI 		}
124464470755SXin LI 		break;
12451713e81bSScott Long 
124664470755SXin LI 	case HPT_IOCTL_CREATE_ARRAY_V2:
124764470755SXin LI 		{
124864470755SXin LI 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1;
124964470755SXin LI 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
125064470755SXin LI 
125164470755SXin LI 			*(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer);
125264470755SXin LI 
125364470755SXin LI 			if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
12541713e81bSScott Long 				return -1;
12551713e81bSScott Long 		}
12561713e81bSScott Long 		break;
12571713e81bSScott Long 
12581713e81bSScott Long 	case HPT_IOCTL_SET_ARRAY_INFO:
12591713e81bSScott Long 		{
12601713e81bSScott Long 			DEVICEID idArray;
12611713e81bSScott Long 			PALTERABLE_ARRAY_INFO pInfo;
12621713e81bSScott Long 
12631713e81bSScott Long 			if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
12641713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
12651713e81bSScott Long 
12661713e81bSScott Long 			idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
12671713e81bSScott Long 			pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
12681713e81bSScott Long 
12691713e81bSScott Long 			if(hpt_set_array_info(_VBUS_P idArray,  pInfo))
12701713e81bSScott Long 				return -1;
12711713e81bSScott Long 		}
12721713e81bSScott Long 		break;
12731713e81bSScott Long 
12741713e81bSScott Long 	case HPT_IOCTL_SET_DEVICE_INFO:
12751713e81bSScott Long 		{
12761713e81bSScott Long 			DEVICEID idDisk;
12771713e81bSScott Long 			PALTERABLE_DEVICE_INFO pInfo;
12781713e81bSScott Long 
12791713e81bSScott Long 			if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
12801713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
12811713e81bSScott Long 
12821713e81bSScott Long 			idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
12831713e81bSScott Long 			pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
12841713e81bSScott Long 			if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
12851713e81bSScott Long 				return -1;
12861713e81bSScott Long 		}
12871713e81bSScott Long 		break;
12881713e81bSScott Long 
128964470755SXin LI 	case HPT_IOCTL_SET_DEVICE_INFO_V2:
129064470755SXin LI 		{
129164470755SXin LI 			DEVICEID idDisk;
129264470755SXin LI 			PALTERABLE_DEVICE_INFO_V2 pInfo;
129364470755SXin LI 
129464470755SXin LI 			if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1;
129564470755SXin LI 			if (nOutBufferSize!=0) return -1;
129664470755SXin LI 
129764470755SXin LI 			idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk;
129864470755SXin LI 			pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info;
129964470755SXin LI 			if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0)
130064470755SXin LI 				return -1;
130164470755SXin LI 		}
130264470755SXin LI 		break;
130364470755SXin LI 
13041713e81bSScott Long 	case HPT_IOCTL_SET_BOOT_MARK:
13051713e81bSScott Long 		{
13061713e81bSScott Long 			DEVICEID id;
13071713e81bSScott Long 			PVDevice pTop;
13081713e81bSScott Long 			int i;
13091713e81bSScott Long 			IAL_ADAPTER_T *pAdapter = gIal_Adapter;
13101713e81bSScott Long 			PVBus pVBus;
13111713e81bSScott Long 
13121713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
13131713e81bSScott Long 			id = *(DEVICEID *)lpInBuffer;
13141713e81bSScott Long 			while(pAdapter != 0)
13151713e81bSScott Long 			{
13161713e81bSScott Long 				pVBus = &pAdapter->VBus;
131764470755SXin LI 				for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
13181713e81bSScott Long 				{
13191713e81bSScott Long 					if(!(pTop = pVBus->pVDevice[i])) continue;
13201713e81bSScott Long 					if (pTop->pVBus!=_vbus_p) return -1;
13211713e81bSScott Long 					while (pTop->pParent) pTop = pTop->pParent;
13221713e81bSScott Long 					if (id==0 && pTop->vf_bootmark)
13231713e81bSScott Long 						pTop->vf_bootmark = 0;
13241713e81bSScott Long 					else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
13251713e81bSScott Long 						pTop->vf_bootmark = 1;
13261713e81bSScott Long 					else
13271713e81bSScott Long 						continue;
13281713e81bSScott Long 					SyncArrayInfo(pTop);
13291713e81bSScott Long 					break;
13301713e81bSScott Long 				}
13311713e81bSScott Long 				pAdapter = pAdapter->next;
13321713e81bSScott Long 			}
13331713e81bSScott Long 		}
13341713e81bSScott Long 		break;
13351713e81bSScott Long 
13361713e81bSScott Long 	case HPT_IOCTL_ADD_SPARE_DISK:
13371713e81bSScott Long 		{
13381713e81bSScott Long 			DEVICEID id;
13391713e81bSScott Long 
13401713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
13411713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
13421713e81bSScott Long 
13431713e81bSScott Long 			id = *(DEVICEID *)lpInBuffer;
13441713e81bSScott Long 
13451713e81bSScott Long 			if(hpt_add_spare_disk(_VBUS_P id))
13461713e81bSScott Long 				return -1;
13471713e81bSScott Long 		}
13481713e81bSScott Long 		break;
13491713e81bSScott Long 
13501713e81bSScott Long 	case HPT_IOCTL_REMOVE_SPARE_DISK:
13511713e81bSScott Long 		{
13521713e81bSScott Long 			DEVICEID id;
13531713e81bSScott Long 
13541713e81bSScott Long 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
13551713e81bSScott Long 			if (nOutBufferSize!=0) return -1;
13561713e81bSScott Long 
13571713e81bSScott Long 			id = *(DEVICEID *)lpInBuffer;
13581713e81bSScott Long 
13591713e81bSScott Long 			if(hpt_remove_spare_disk(_VBUS_P id))
13601713e81bSScott Long 				return -1;
13611713e81bSScott Long 		}
13621713e81bSScott Long 		break;
13631713e81bSScott Long 
13641713e81bSScott Long 	case HPT_IOCTL_ADD_DISK_TO_ARRAY:
13651713e81bSScott Long 		{
13661713e81bSScott Long 			DEVICEID id1,id2;
13671713e81bSScott Long 			id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
13681713e81bSScott Long 			id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
13691713e81bSScott Long 
13701713e81bSScott Long 			if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
13711713e81bSScott Long 			if (nOutBufferSize != 0) return -1;
13721713e81bSScott Long 
13731713e81bSScott Long 			if(hpt_add_disk_to_array(_VBUS_P id1, id2))
13741713e81bSScott Long 				return -1;
13751713e81bSScott Long 		}
13761713e81bSScott Long 		break;
13771713e81bSScott Long #endif
13781713e81bSScott Long 	case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
13791713e81bSScott Long 		{
13801713e81bSScott Long 			PDRIVER_CAPABILITIES cap;
13811713e81bSScott Long 			if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
13821713e81bSScott Long 			cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
13831713e81bSScott Long 
13841713e81bSScott Long 			if(hpt_get_driver_capabilities(cap))
13851713e81bSScott Long 				return -1;
13861713e81bSScott Long 		}
13871713e81bSScott Long 		break;
13881713e81bSScott Long 
138964470755SXin LI 	case HPT_IOCTL_GET_CONTROLLER_VENID:
13901713e81bSScott Long 		{
139164470755SXin LI 			DWORD id = ((DWORD*)lpInBuffer)[0];
139264470755SXin LI 			IAL_ADAPTER_T *pAdapTemp;
139364470755SXin LI 			int iControllerCount = 0;
13941713e81bSScott Long 
139564470755SXin LI 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
139664470755SXin LI 				if (iControllerCount++==id)
139764470755SXin LI 					break;
13981713e81bSScott Long 
139964470755SXin LI 			if (!pAdapTemp)
14001713e81bSScott Long 				return -1;
140164470755SXin LI 
140264470755SXin LI 			if (nOutBufferSize < 4)
140364470755SXin LI 				return -1;
140464470755SXin LI 
140564470755SXin LI 			*(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB;
140664470755SXin LI 			return 0;
140764470755SXin LI 		}
140864470755SXin LI 
140964470755SXin LI 	case HPT_IOCTL_EPROM_IO:
141064470755SXin LI 		{
141164470755SXin LI 			DWORD id           = ((DWORD*)lpInBuffer)[0];
141264470755SXin LI 			DWORD offset	   = ((DWORD*)lpInBuffer)[1];
141364470755SXin LI 			DWORD direction    = ((DWORD*)lpInBuffer)[2];
141464470755SXin LI 			DWORD length	   = ((DWORD*)lpInBuffer)[3];
141564470755SXin LI 			IAL_ADAPTER_T *pAdapTemp;
141664470755SXin LI 			int iControllerCount = 0;
141764470755SXin LI 
141864470755SXin LI 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
141964470755SXin LI 				if (iControllerCount++==id)
142064470755SXin LI 					break;
142164470755SXin LI 
142264470755SXin LI 			if (!pAdapTemp)
142364470755SXin LI 				return -1;
142464470755SXin LI 
142564470755SXin LI 			if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) ||
142664470755SXin LI 				nOutBufferSize < (direction? 0 : length))
142764470755SXin LI 				return -1;
142864470755SXin LI 
142964470755SXin LI 			if (direction == 0) /* read */
143064470755SXin LI 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
143164470755SXin LI 					offset, lpOutBuffer, length, 1);
143264470755SXin LI 			else
143364470755SXin LI 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
143464470755SXin LI 					offset, (char *)lpInBuffer + 16, length, 0);
143564470755SXin LI 
143664470755SXin LI 			return 0;
14371713e81bSScott Long 		}
14381713e81bSScott Long 		break;
14391713e81bSScott Long 
14401713e81bSScott Long 	default:
14411713e81bSScott Long 		return -1;
14421713e81bSScott Long 	}
14431713e81bSScott Long 
14441713e81bSScott Long 	if (lpBytesReturned)
14451713e81bSScott Long 		*lpBytesReturned = nOutBufferSize;
14461713e81bSScott Long 	return 0;
14471713e81bSScott Long }
1448