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