xref: /dflybsd-src/sys/dev/raid/hptmv/gui_lib.c (revision 35878b555b34ba9ef289f7767aa29d02df2cde48)
1*35878b55SSascha Wildner /*
2*35878b55SSascha Wildner  * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
3*35878b55SSascha Wildner  * All rights reserved.
4*35878b55SSascha Wildner  *
5*35878b55SSascha Wildner  * Redistribution and use in source and binary forms, with or without
6*35878b55SSascha Wildner  * modification, are permitted provided that the following conditions
7*35878b55SSascha Wildner  * are met:
8*35878b55SSascha Wildner  * 1. Redistributions of source code must retain the above copyright
9*35878b55SSascha Wildner  *    notice, this list of conditions and the following disclaimer.
10*35878b55SSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
11*35878b55SSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
12*35878b55SSascha Wildner  *    documentation and/or other materials provided with the distribution.
13*35878b55SSascha Wildner  *
14*35878b55SSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15*35878b55SSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16*35878b55SSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17*35878b55SSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18*35878b55SSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19*35878b55SSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20*35878b55SSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21*35878b55SSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22*35878b55SSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23*35878b55SSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24*35878b55SSascha Wildner  * SUCH DAMAGE.
25*35878b55SSascha Wildner  *
26*35878b55SSascha Wildner  * $FreeBSD: src/sys/dev/hptmv/gui_lib.c,v 1.6 2009/04/07 16:38:25 delphij Exp $
27*35878b55SSascha Wildner  */
28*35878b55SSascha Wildner /*
29*35878b55SSascha Wildner  * gui_lib.c
30*35878b55SSascha Wildner  * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved.
31*35878b55SSascha Wildner  *
32*35878b55SSascha Wildner  *  Platform independent ioctl interface implementation.
33*35878b55SSascha Wildner  *  The platform dependent part may reuse this function and/or use it own
34*35878b55SSascha Wildner  *  implementation for each ioctl function.
35*35878b55SSascha Wildner  *
36*35878b55SSascha Wildner  *  This implementation doesn't use any synchronization; the caller must
37*35878b55SSascha Wildner  *  assure the proper context when calling these functions.
38*35878b55SSascha Wildner  */
39*35878b55SSascha Wildner 
40*35878b55SSascha Wildner #include <sys/param.h>
41*35878b55SSascha Wildner #include <sys/systm.h>
42*35878b55SSascha Wildner #include <sys/kernel.h>
43*35878b55SSascha Wildner #include <sys/malloc.h>
44*35878b55SSascha Wildner 
45*35878b55SSascha Wildner #ifndef __KERNEL__
46*35878b55SSascha Wildner #define __KERNEL__
47*35878b55SSascha Wildner #endif
48*35878b55SSascha Wildner 
49*35878b55SSascha Wildner #include <dev/raid/hptmv/global.h>
50*35878b55SSascha Wildner #include <dev/raid/hptmv/hptintf.h>
51*35878b55SSascha Wildner #include <dev/raid/hptmv/osbsd.h>
52*35878b55SSascha Wildner #include <dev/raid/hptmv/access601.h>
53*35878b55SSascha Wildner 
54*35878b55SSascha Wildner static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
55*35878b55SSascha Wildner static int hpt_get_controller_count(void);
56*35878b55SSascha Wildner static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
57*35878b55SSascha Wildner static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
58*35878b55SSascha Wildner static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
59*35878b55SSascha Wildner static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
60*35878b55SSascha Wildner static int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo);
61*35878b55SSascha Wildner static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
62*35878b55SSascha Wildner static DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam);
63*35878b55SSascha Wildner static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
64*35878b55SSascha Wildner static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
65*35878b55SSascha Wildner static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
66*35878b55SSascha Wildner static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
67*35878b55SSascha Wildner static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo);
68*35878b55SSascha Wildner 
69*35878b55SSascha Wildner int
70*35878b55SSascha Wildner check_VDevice_valid(PVDevice p)
71*35878b55SSascha Wildner {
72*35878b55SSascha Wildner 	int i;
73*35878b55SSascha Wildner 	PVDevice pVDevice;
74*35878b55SSascha Wildner 	PVBus    _vbus_p;
75*35878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
76*35878b55SSascha Wildner 
77*35878b55SSascha Wildner 	while(pAdapter != 0)
78*35878b55SSascha Wildner 	{
79*35878b55SSascha Wildner 		for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
80*35878b55SSascha Wildner 			if(&(pAdapter->VDevices[i]) == p)  return 0;
81*35878b55SSascha Wildner 		pAdapter = pAdapter->next;
82*35878b55SSascha Wildner 	}
83*35878b55SSascha Wildner 
84*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
85*35878b55SSascha Wildner 	pAdapter = gIal_Adapter;
86*35878b55SSascha Wildner 	while(pAdapter != 0)
87*35878b55SSascha Wildner 	{
88*35878b55SSascha Wildner 		_vbus_p = &pAdapter->VBus;
89*35878b55SSascha Wildner 		for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
90*35878b55SSascha Wildner 		{
91*35878b55SSascha Wildner 			pVDevice=ArrayTables(i);
92*35878b55SSascha Wildner 			if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
93*35878b55SSascha Wildner 				return 0;
94*35878b55SSascha Wildner 		}
95*35878b55SSascha Wildner 		pAdapter = pAdapter->next;
96*35878b55SSascha Wildner 	}
97*35878b55SSascha Wildner #endif
98*35878b55SSascha Wildner 
99*35878b55SSascha Wildner 	return -1;
100*35878b55SSascha Wildner }
101*35878b55SSascha Wildner 
102*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
103*35878b55SSascha Wildner 
104*35878b55SSascha Wildner static UCHAR get_vdev_type(PVDevice pVDevice)
105*35878b55SSascha Wildner 	{
106*35878b55SSascha Wildner 	switch (pVDevice->VDeviceType) {
107*35878b55SSascha Wildner 		case VD_RAID_0: return AT_RAID0;
108*35878b55SSascha Wildner 		case VD_RAID_1: return AT_RAID1;
109*35878b55SSascha Wildner 		case VD_JBOD:   return AT_JBOD;
110*35878b55SSascha Wildner 		case VD_RAID_5: return AT_RAID5;
111*35878b55SSascha Wildner 		default:        return AT_UNKNOWN;
112*35878b55SSascha Wildner 	}
113*35878b55SSascha Wildner 	}
114*35878b55SSascha Wildner 
115*35878b55SSascha Wildner static DWORD get_array_flag(PVDevice pVDevice)
116*35878b55SSascha Wildner {
117*35878b55SSascha Wildner 	int i;
118*35878b55SSascha Wildner 	DWORD f = 0;
119*35878b55SSascha Wildner 
120*35878b55SSascha Wildner 	/* The array is disabled */
121*35878b55SSascha Wildner 	if(!pVDevice->vf_online)	{
122*35878b55SSascha Wildner 		f |= ARRAY_FLAG_DISABLED;
123*35878b55SSascha Wildner 		/* Ignore other info */
124*35878b55SSascha Wildner 		return f;
125*35878b55SSascha Wildner 	}
126*35878b55SSascha Wildner 
127*35878b55SSascha Wildner 	/* array need synchronizing */
128*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
129*35878b55SSascha Wildner 		f |= ARRAY_FLAG_NEEDBUILDING;
130*35878b55SSascha Wildner 
131*35878b55SSascha Wildner 	/* array is in rebuilding process */
132*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_rebuilding)
133*35878b55SSascha Wildner 		f |= ARRAY_FLAG_REBUILDING;
134*35878b55SSascha Wildner 
135*35878b55SSascha Wildner 	/* array is being verified */
136*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_verifying)
137*35878b55SSascha Wildner 		f |= ARRAY_FLAG_VERIFYING;
138*35878b55SSascha Wildner 
139*35878b55SSascha Wildner 	/* array is being initialized */
140*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_initializing)
141*35878b55SSascha Wildner 		f |= ARRAY_FLAG_INITIALIZING;
142*35878b55SSascha Wildner 
143*35878b55SSascha Wildner 	/* broken but may still working */
144*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_broken)
145*35878b55SSascha Wildner 		f |= ARRAY_FLAG_BROKEN;
146*35878b55SSascha Wildner 
147*35878b55SSascha Wildner 	/* array has a active partition */
148*35878b55SSascha Wildner 	if(pVDevice->vf_bootable)
149*35878b55SSascha Wildner 		f |= ARRAY_FLAG_BOOTDISK;
150*35878b55SSascha Wildner 
151*35878b55SSascha Wildner 	/* a newly created array */
152*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_newly_created)
153*35878b55SSascha Wildner 		f |= ARRAY_FLAG_NEWLY_CREATED;
154*35878b55SSascha Wildner 
155*35878b55SSascha Wildner 	/* array has boot mark set */
156*35878b55SSascha Wildner 	if(pVDevice->vf_bootmark)
157*35878b55SSascha Wildner 		f |= ARRAY_FLAG_BOOTMARK;
158*35878b55SSascha Wildner 
159*35878b55SSascha Wildner 	/* auto-rebuild should start */
160*35878b55SSascha Wildner 	if(pVDevice->u.array.rf_auto_rebuild)
161*35878b55SSascha Wildner 		f |= ARRAY_FLAG_NEED_AUTOREBUILD;
162*35878b55SSascha Wildner 
163*35878b55SSascha Wildner 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
164*35878b55SSascha Wildner 	{
165*35878b55SSascha Wildner 		PVDevice pMember = pVDevice->u.array.pMember[i];
166*35878b55SSascha Wildner 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
167*35878b55SSascha Wildner 			continue;
168*35878b55SSascha Wildner 
169*35878b55SSascha Wildner 		/* array need synchronizing */
170*35878b55SSascha Wildner 		if(pMember->u.array.rf_need_rebuild &&
171*35878b55SSascha Wildner 		   !pMember->u.array.rf_duplicate_and_create)
172*35878b55SSascha Wildner 			f |= ARRAY_FLAG_NEEDBUILDING;
173*35878b55SSascha Wildner 
174*35878b55SSascha Wildner 		/* array is in rebuilding process */
175*35878b55SSascha Wildner 		if(pMember->u.array.rf_rebuilding)
176*35878b55SSascha Wildner 			f |= ARRAY_FLAG_REBUILDING;
177*35878b55SSascha Wildner 
178*35878b55SSascha Wildner 		/* array is being verified */
179*35878b55SSascha Wildner 		if(pMember->u.array.rf_verifying)
180*35878b55SSascha Wildner 			f |= ARRAY_FLAG_VERIFYING;
181*35878b55SSascha Wildner 
182*35878b55SSascha Wildner 		/* array is being initialized */
183*35878b55SSascha Wildner 		if(pMember->u.array.rf_initializing)
184*35878b55SSascha Wildner 			f |= ARRAY_FLAG_INITIALIZING;
185*35878b55SSascha Wildner 
186*35878b55SSascha Wildner 		/* broken but may still working */
187*35878b55SSascha Wildner 		if(pMember->u.array.rf_broken)
188*35878b55SSascha Wildner 			f |= ARRAY_FLAG_BROKEN;
189*35878b55SSascha Wildner 
190*35878b55SSascha Wildner 		/* a newly created array */
191*35878b55SSascha Wildner 		if(pMember->u.array.rf_newly_created)
192*35878b55SSascha Wildner 			f |= ARRAY_FLAG_NEWLY_CREATED;
193*35878b55SSascha Wildner 
194*35878b55SSascha Wildner 		/* auto-rebuild should start */
195*35878b55SSascha Wildner 		if(pMember->u.array.rf_auto_rebuild)
196*35878b55SSascha Wildner 			f |= ARRAY_FLAG_NEED_AUTOREBUILD;
197*35878b55SSascha Wildner 	}
198*35878b55SSascha Wildner 
199*35878b55SSascha Wildner 	return f;
200*35878b55SSascha Wildner }
201*35878b55SSascha Wildner 
202*35878b55SSascha Wildner static DWORD calc_rebuild_progress(PVDevice pVDevice)
203*35878b55SSascha Wildner {
204*35878b55SSascha Wildner 	int i;
205*35878b55SSascha Wildner 	DWORD result = ((ULONG)(pVDevice->u.array.RebuildSectors>>11)*1000 /
206*35878b55SSascha Wildner 		(ULONG)(pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
207*35878b55SSascha Wildner 
208*35878b55SSascha Wildner 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
209*35878b55SSascha Wildner 	{
210*35878b55SSascha Wildner 		PVDevice pMember = pVDevice->u.array.pMember[i];
211*35878b55SSascha Wildner 		if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
212*35878b55SSascha Wildner 			continue;
213*35878b55SSascha Wildner 
214*35878b55SSascha Wildner 		/* for RAID1/0 case */
215*35878b55SSascha Wildner 		if (pMember->u.array.rf_rebuilding ||
216*35878b55SSascha Wildner 			pMember->u.array.rf_verifying ||
217*35878b55SSascha Wildner 			pMember->u.array.rf_initializing)
218*35878b55SSascha Wildner 		{
219*35878b55SSascha Wildner 			DWORD percent = ((ULONG)(pMember->u.array.RebuildSectors>>11)*1000 /
220*35878b55SSascha Wildner 				(ULONG)(pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
221*35878b55SSascha Wildner 			if (result==0 || result>percent)
222*35878b55SSascha Wildner 				result = percent;
223*35878b55SSascha Wildner 		}
224*35878b55SSascha Wildner 		}
225*35878b55SSascha Wildner 
226*35878b55SSascha Wildner 	if (result>10000) result = 10000;
227*35878b55SSascha Wildner 	return result;
228*35878b55SSascha Wildner 	}
229*35878b55SSascha Wildner 
230*35878b55SSascha Wildner static void get_array_info(PVDevice pVDevice, PHPT_ARRAY_INFO pArrayInfo)
231*35878b55SSascha Wildner {
232*35878b55SSascha Wildner 	int	i;
233*35878b55SSascha Wildner 
234*35878b55SSascha Wildner 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
235*35878b55SSascha Wildner 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
236*35878b55SSascha Wildner 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
237*35878b55SSascha Wildner 	pArrayInfo->RebuiltSectors = pVDevice->u.array.RebuildSectors;
238*35878b55SSascha Wildner 	pArrayInfo->Flags = get_array_flag(pVDevice);
239*35878b55SSascha Wildner 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
240*35878b55SSascha Wildner 
241*35878b55SSascha Wildner 	pArrayInfo->nDisk = 0;
242*35878b55SSascha Wildner 
243*35878b55SSascha Wildner 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
244*35878b55SSascha Wildner 		if(pVDevice->u.array.pMember[i] != NULL)
245*35878b55SSascha Wildner 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
246*35878b55SSascha Wildner 
247*35878b55SSascha Wildner 	for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS; i++)
248*35878b55SSascha Wildner 		pArrayInfo->Members[i] = INVALID_DEVICEID;
249*35878b55SSascha Wildner 	}
250*35878b55SSascha Wildner 
251*35878b55SSascha Wildner static void get_array_info_v2(PVDevice pVDevice, PHPT_ARRAY_INFO_V2 pArrayInfo)
252*35878b55SSascha Wildner {
253*35878b55SSascha Wildner 	int	i;
254*35878b55SSascha Wildner 
255*35878b55SSascha Wildner 	memcpy(pArrayInfo->Name, pVDevice->u.array.ArrayName, MAX_ARRAYNAME_LEN);
256*35878b55SSascha Wildner 	pArrayInfo->ArrayType = get_vdev_type(pVDevice);
257*35878b55SSascha Wildner 	pArrayInfo->BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
258*35878b55SSascha Wildner 	pArrayInfo->RebuiltSectors.lo32 = pVDevice->u.array.RebuildSectors;
259*35878b55SSascha Wildner 	pArrayInfo->RebuiltSectors.hi32 = sizeof(LBA_T)>4? (pVDevice->u.array.RebuildSectors>>32) : 0;
260*35878b55SSascha Wildner 	pArrayInfo->Flags = get_array_flag(pVDevice);
261*35878b55SSascha Wildner 	pArrayInfo->RebuildingProgress = calc_rebuild_progress(pVDevice);
262*35878b55SSascha Wildner 
263*35878b55SSascha Wildner 	pArrayInfo->nDisk = 0;
264*35878b55SSascha Wildner 
265*35878b55SSascha Wildner 	for(i = 0; i < pVDevice->u.array.bArnMember; i++)
266*35878b55SSascha Wildner 		if(pVDevice->u.array.pMember[i] != NULL)
267*35878b55SSascha Wildner 			pArrayInfo->Members[pArrayInfo->nDisk++] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
268*35878b55SSascha Wildner 
269*35878b55SSascha Wildner 	for(i=pArrayInfo->nDisk; i<MAX_ARRAY_MEMBERS_V2; i++)
270*35878b55SSascha Wildner 		pArrayInfo->Members[i] = INVALID_DEVICEID;
271*35878b55SSascha Wildner }
272*35878b55SSascha Wildner #endif
273*35878b55SSascha Wildner 
274*35878b55SSascha Wildner static int get_disk_info(PVDevice pVDevice, PDEVICE_INFO pDiskInfo)
275*35878b55SSascha Wildner {
276*35878b55SSascha Wildner 	MV_SATA_ADAPTER *pSataAdapter;
277*35878b55SSascha Wildner 	MV_SATA_CHANNEL *pSataChannel;
278*35878b55SSascha Wildner 	IAL_ADAPTER_T   *pAdapter;
279*35878b55SSascha Wildner 	MV_CHANNEL		*channelInfo;
280*35878b55SSascha Wildner 	char *p;
281*35878b55SSascha Wildner 	int i;
282*35878b55SSascha Wildner 
283*35878b55SSascha Wildner 	/* device location */
284*35878b55SSascha Wildner 	pSataChannel = pVDevice->u.disk.mv;
285*35878b55SSascha Wildner 	if(pSataChannel == NULL)	return -1;
286*35878b55SSascha Wildner 	pDiskInfo->TargetId = 0;
287*35878b55SSascha Wildner 	pSataAdapter = pSataChannel->mvSataAdapter;
288*35878b55SSascha Wildner 	if(pSataAdapter == NULL)	return -1;
289*35878b55SSascha Wildner 
290*35878b55SSascha Wildner 	pAdapter = pSataAdapter->IALData;
291*35878b55SSascha Wildner 
292*35878b55SSascha Wildner 	pDiskInfo->PathId = pSataChannel->channelNumber;
293*35878b55SSascha Wildner 	pDiskInfo->ControllerId = (UCHAR)pSataAdapter->adapterId;
294*35878b55SSascha Wildner 
295*35878b55SSascha Wildner /*GUI uses DeviceModeSetting to display to users
296*35878b55SSascha Wildner (1) if users select a mode, GUI/BIOS should display that mode.
297*35878b55SSascha Wildner (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
298*35878b55SSascha Wildner (3) display real mode if case (1)&&(2) not satisfied.
299*35878b55SSascha Wildner */
300*35878b55SSascha Wildner 	if (pVDevice->u.disk.df_user_mode_set)
301*35878b55SSascha Wildner 		pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
302*35878b55SSascha Wildner 	else if (((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability) & 3)==2)
303*35878b55SSascha Wildner 		pDiskInfo->DeviceModeSetting = 15;
304*35878b55SSascha Wildner 	else {
305*35878b55SSascha Wildner 		p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
306*35878b55SSascha Wildner 		if (*(WORD*)p==(0x5354) /*'ST'*/ &&
307*35878b55SSascha Wildner 			(*(WORD*)(p+8)==(0x4153)/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
308*35878b55SSascha Wildner 			pDiskInfo->DeviceModeSetting = 15;
309*35878b55SSascha Wildner 		else
310*35878b55SSascha Wildner 			pDiskInfo->DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
311*35878b55SSascha Wildner 	}
312*35878b55SSascha Wildner 
313*35878b55SSascha Wildner 	pDiskInfo->UsableMode = pVDevice->u.disk.bDeUsable_Mode;
314*35878b55SSascha Wildner 
315*35878b55SSascha Wildner 	pDiskInfo->DeviceType = PDT_HARDDISK;
316*35878b55SSascha Wildner 
317*35878b55SSascha Wildner 	pDiskInfo->Flags = 0x0;
318*35878b55SSascha Wildner 
319*35878b55SSascha Wildner 	/* device is disabled */
320*35878b55SSascha Wildner 	if(!pVDevice->u.disk.df_on_line)
321*35878b55SSascha Wildner 		pDiskInfo->Flags |= DEVICE_FLAG_DISABLED;
322*35878b55SSascha Wildner 
323*35878b55SSascha Wildner 	/* disk has a active partition */
324*35878b55SSascha Wildner 	if(pVDevice->vf_bootable)
325*35878b55SSascha Wildner 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTDISK;
326*35878b55SSascha Wildner 
327*35878b55SSascha Wildner 	/* disk has boot mark set */
328*35878b55SSascha Wildner 	if(pVDevice->vf_bootmark)
329*35878b55SSascha Wildner 		pDiskInfo->Flags |= DEVICE_FLAG_BOOTMARK;
330*35878b55SSascha Wildner 
331*35878b55SSascha Wildner 	pDiskInfo->Flags |= DEVICE_FLAG_SATA;
332*35878b55SSascha Wildner 
333*35878b55SSascha Wildner 	/* is a spare disk */
334*35878b55SSascha Wildner 	if(pVDevice->VDeviceType == VD_SPARE)
335*35878b55SSascha Wildner 		pDiskInfo->Flags |= DEVICE_FLAG_IS_SPARE;
336*35878b55SSascha Wildner 
337*35878b55SSascha Wildner 	memcpy(&(pDiskInfo->IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
338*35878b55SSascha Wildner 	p = (char *)&pDiskInfo->IdentifyData.ModelNumber;
339*35878b55SSascha Wildner 	for (i = 0; i < 20; i++)
340*35878b55SSascha Wildner 		((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
341*35878b55SSascha Wildner 	p[39] = '\0';
342*35878b55SSascha Wildner 
343*35878b55SSascha Wildner 	channelInfo = &pAdapter->mvChannel[pSataChannel->channelNumber];
344*35878b55SSascha Wildner 	pDiskInfo->ReadAheadSupported = channelInfo->readAheadSupported;
345*35878b55SSascha Wildner 	pDiskInfo->ReadAheadEnabled = channelInfo->readAheadEnabled;
346*35878b55SSascha Wildner 	pDiskInfo->WriteCacheSupported = channelInfo->writeCacheSupported;
347*35878b55SSascha Wildner 	pDiskInfo->WriteCacheEnabled = channelInfo->writeCacheEnabled;
348*35878b55SSascha Wildner 	pDiskInfo->TCQSupported = (pSataChannel->identifyDevice[IDEN_SUPPORTED_COMMANDS2] & (0x2))!=0;
349*35878b55SSascha Wildner 	pDiskInfo->TCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_QUEUED;
350*35878b55SSascha Wildner 	pDiskInfo->NCQSupported = MV_SATA_GEN_2(pSataAdapter) &&
351*35878b55SSascha Wildner 		(pSataChannel->identifyDevice[IDEN_SATA_CAPABILITIES] & (0x0100));
352*35878b55SSascha Wildner 	pDiskInfo->NCQEnabled = pSataChannel->queuedDMA==MV_EDMA_MODE_NATIVE_QUEUING;
353*35878b55SSascha Wildner 	return 0;
354*35878b55SSascha Wildner }
355*35878b55SSascha Wildner 
356*35878b55SSascha Wildner int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
357*35878b55SSascha Wildner {
358*35878b55SSascha Wildner 	ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
359*35878b55SSascha Wildner 	cap->dwSize = sizeof(DRIVER_CAPABILITIES);
360*35878b55SSascha Wildner 	cap->MaximumControllers = MAX_VBUS;
361*35878b55SSascha Wildner 
362*35878b55SSascha Wildner 	/* cap->SupportCrossControllerRAID = 0; */
363*35878b55SSascha Wildner 	/* take care for various OSes! */
364*35878b55SSascha Wildner 	cap->SupportCrossControllerRAID = 0;
365*35878b55SSascha Wildner 
366*35878b55SSascha Wildner 
367*35878b55SSascha Wildner 	cap->MinimumBlockSizeShift = MinBlockSizeShift;
368*35878b55SSascha Wildner 	cap->MaximumBlockSizeShift = MaxBlockSizeShift;
369*35878b55SSascha Wildner 	cap->SupportDiskModeSetting = 0;
370*35878b55SSascha Wildner 	cap->SupportSparePool = 1;
371*35878b55SSascha Wildner 	cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
372*35878b55SSascha Wildner 	cap->SupportDedicatedSpare = 0;
373*35878b55SSascha Wildner 
374*35878b55SSascha Wildner 
375*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
376*35878b55SSascha Wildner 	/* Stripe */
377*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[0] = AT_RAID0;
378*35878b55SSascha Wildner 	cap->MaximumArrayMembers[0] = MAX_MEMBERS;
379*35878b55SSascha Wildner 	/* Mirror */
380*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[1] = AT_RAID1;
381*35878b55SSascha Wildner 	cap->MaximumArrayMembers[1] = 2;
382*35878b55SSascha Wildner 	/* Mirror + Stripe */
383*35878b55SSascha Wildner #ifdef ARRAY_V2_ONLY
384*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
385*35878b55SSascha Wildner #else
386*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
387*35878b55SSascha Wildner #endif
388*35878b55SSascha Wildner 	cap->MaximumArrayMembers[2] = MAX_MEMBERS;
389*35878b55SSascha Wildner 	/* Jbod */
390*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[3] = AT_JBOD;
391*35878b55SSascha Wildner 	cap->MaximumArrayMembers[3] = MAX_MEMBERS;
392*35878b55SSascha Wildner 	/* RAID5 */
393*35878b55SSascha Wildner #if SUPPORT_RAID5
394*35878b55SSascha Wildner 	cap->SupportedRAIDTypes[4] = AT_RAID5;
395*35878b55SSascha Wildner 	cap->MaximumArrayMembers[4] = MAX_MEMBERS;
396*35878b55SSascha Wildner #endif
397*35878b55SSascha Wildner #endif
398*35878b55SSascha Wildner 	return 0;
399*35878b55SSascha Wildner }
400*35878b55SSascha Wildner 
401*35878b55SSascha Wildner int hpt_get_controller_count(void)
402*35878b55SSascha Wildner {
403*35878b55SSascha Wildner 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
404*35878b55SSascha Wildner 	int iControllerCount = 0;
405*35878b55SSascha Wildner 
406*35878b55SSascha Wildner 	while(pAdapTemp != 0)
407*35878b55SSascha Wildner 	{
408*35878b55SSascha Wildner 		iControllerCount++;
409*35878b55SSascha Wildner 		pAdapTemp = pAdapTemp->next;
410*35878b55SSascha Wildner 	}
411*35878b55SSascha Wildner 
412*35878b55SSascha Wildner 	return iControllerCount;
413*35878b55SSascha Wildner }
414*35878b55SSascha Wildner 
415*35878b55SSascha Wildner int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
416*35878b55SSascha Wildner {
417*35878b55SSascha Wildner 	IAL_ADAPTER_T    *pAdapTemp;
418*35878b55SSascha Wildner 	int iControllerCount = 0;
419*35878b55SSascha Wildner 
420*35878b55SSascha Wildner 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
421*35878b55SSascha Wildner 		if (iControllerCount++==id) {
422*35878b55SSascha Wildner 			pInfo->InterruptLevel = 0;
423*35878b55SSascha Wildner 			pInfo->ChipType = 0;
424*35878b55SSascha Wildner 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
425*35878b55SSascha Wildner 			strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
426*35878b55SSascha Wildner #ifdef GUI_CONTROLLER_NAME
427*35878b55SSascha Wildner #ifdef FORCE_ATA150_DISPLAY
428*35878b55SSascha Wildner 			/* show "Bus Type: ATA/150" in GUI for SATA controllers */
429*35878b55SSascha Wildner 			pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
430*35878b55SSascha Wildner #endif
431*35878b55SSascha Wildner 			strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
432*35878b55SSascha Wildner #define _set_product_id(x)
433*35878b55SSascha Wildner #else
434*35878b55SSascha Wildner #define _set_product_id(x) strcpy(pInfo->szProductID, x)
435*35878b55SSascha Wildner #endif
436*35878b55SSascha Wildner 			_set_product_id("RocketRAID 18xx SATA Controller");
437*35878b55SSascha Wildner 			pInfo->NumBuses = 8;
438*35878b55SSascha Wildner 			pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
439*35878b55SSascha Wildner 			return 0;
440*35878b55SSascha Wildner 		}
441*35878b55SSascha Wildner 	}
442*35878b55SSascha Wildner 	return -1;
443*35878b55SSascha Wildner }
444*35878b55SSascha Wildner 
445*35878b55SSascha Wildner 
446*35878b55SSascha Wildner int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
447*35878b55SSascha Wildner {
448*35878b55SSascha Wildner 	IAL_ADAPTER_T    *pAdapTemp = gIal_Adapter;
449*35878b55SSascha Wildner 	int i,iControllerCount = 0;
450*35878b55SSascha Wildner 
451*35878b55SSascha Wildner 	while(pAdapTemp != 0)
452*35878b55SSascha Wildner 	{
453*35878b55SSascha Wildner 		if (iControllerCount++==id)
454*35878b55SSascha Wildner 			goto found;
455*35878b55SSascha Wildner 		pAdapTemp = pAdapTemp->next;
456*35878b55SSascha Wildner 	}
457*35878b55SSascha Wildner 	return -1;
458*35878b55SSascha Wildner 
459*35878b55SSascha Wildner found:
460*35878b55SSascha Wildner 
461*35878b55SSascha Wildner 	pInfo->IoPort = 0;
462*35878b55SSascha Wildner 	pInfo->ControlPort = 0;
463*35878b55SSascha Wildner 
464*35878b55SSascha Wildner 	for (i=0; i<2 ;i++)
465*35878b55SSascha Wildner 	{
466*35878b55SSascha Wildner 		pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
467*35878b55SSascha Wildner 	}
468*35878b55SSascha Wildner 
469*35878b55SSascha Wildner 	if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
470*35878b55SSascha Wildner 		pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
471*35878b55SSascha Wildner 	else
472*35878b55SSascha Wildner 		pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
473*35878b55SSascha Wildner 
474*35878b55SSascha Wildner 	return 0;
475*35878b55SSascha Wildner 
476*35878b55SSascha Wildner 
477*35878b55SSascha Wildner }
478*35878b55SSascha Wildner 
479*35878b55SSascha Wildner int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
480*35878b55SSascha Wildner {
481*35878b55SSascha Wildner 	int count = 0;
482*35878b55SSascha Wildner 	int	i,j;
483*35878b55SSascha Wildner 	PVDevice pPhysical, pLogical;
484*35878b55SSascha Wildner 	IAL_ADAPTER_T    *pAdapTemp;
485*35878b55SSascha Wildner 
486*35878b55SSascha Wildner 	for(i = 0; i < nMaxCount; i++)
487*35878b55SSascha Wildner 		pIds[i] = INVALID_DEVICEID;
488*35878b55SSascha Wildner 
489*35878b55SSascha Wildner 	/* append the arrays not registered on VBus */
490*35878b55SSascha Wildner 	for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
491*35878b55SSascha Wildner 		for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
492*35878b55SSascha Wildner 		{
493*35878b55SSascha Wildner 			pPhysical = &pAdapTemp->VDevices[i];
494*35878b55SSascha Wildner 			pLogical = pPhysical;
495*35878b55SSascha Wildner 
496*35878b55SSascha Wildner 			while (pLogical->pParent) pLogical = pLogical->pParent;
497*35878b55SSascha Wildner 			if (pLogical->VDeviceType==VD_SPARE)
498*35878b55SSascha Wildner 				continue;
499*35878b55SSascha Wildner 
500*35878b55SSascha Wildner 			for (j=0; j<count; j++)
501*35878b55SSascha Wildner 				if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
502*35878b55SSascha Wildner 			pIds[count++] = VDEV_TO_ID(pLogical);
503*35878b55SSascha Wildner 			if (count>=nMaxCount) goto done;
504*35878b55SSascha Wildner 			next:;
505*35878b55SSascha Wildner 		}
506*35878b55SSascha Wildner 	}
507*35878b55SSascha Wildner 
508*35878b55SSascha Wildner done:
509*35878b55SSascha Wildner 	return count;
510*35878b55SSascha Wildner }
511*35878b55SSascha Wildner 
512*35878b55SSascha Wildner int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
513*35878b55SSascha Wildner {
514*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(id);
515*35878b55SSascha Wildner 
516*35878b55SSascha Wildner 	if((id == 0) || check_VDevice_valid(pVDevice))
517*35878b55SSascha Wildner 		return -1;
518*35878b55SSascha Wildner 
519*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
520*35878b55SSascha Wildner 	if (mIsArray(pVDevice)) {
521*35878b55SSascha Wildner 		pInfo->Type = LDT_ARRAY;
522*35878b55SSascha Wildner 		pInfo->Capacity = pVDevice->VDeviceCapacity;
523*35878b55SSascha Wildner 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
524*35878b55SSascha Wildner 		get_array_info(pVDevice, &pInfo->u.array);
525*35878b55SSascha Wildner 		return 0;
526*35878b55SSascha Wildner 	}
527*35878b55SSascha Wildner #endif
528*35878b55SSascha Wildner 
529*35878b55SSascha Wildner 	pInfo->Type = LDT_DEVICE;
530*35878b55SSascha Wildner 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
531*35878b55SSascha Wildner 	/* report real capacity to be compatible with old arrays */
532*35878b55SSascha Wildner 	pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
533*35878b55SSascha Wildner 	return get_disk_info(pVDevice, &pInfo->u.device);
534*35878b55SSascha Wildner }
535*35878b55SSascha Wildner 
536*35878b55SSascha Wildner int hpt_get_device_info_v2(DEVICEID id, PLOGICAL_DEVICE_INFO_V2 pInfo)
537*35878b55SSascha Wildner {
538*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(id);
539*35878b55SSascha Wildner 
540*35878b55SSascha Wildner 	if((id == 0) || check_VDevice_valid(pVDevice))
541*35878b55SSascha Wildner 		return -1;
542*35878b55SSascha Wildner 
543*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
544*35878b55SSascha Wildner 	if (mIsArray(pVDevice)) {
545*35878b55SSascha Wildner 		pInfo->Type = LDT_ARRAY;
546*35878b55SSascha Wildner 		pInfo->Capacity.lo32 = pVDevice->VDeviceCapacity;
547*35878b55SSascha Wildner 		pInfo->Capacity.hi32 = sizeof(LBA_T)>4? (pVDevice->VDeviceCapacity>>32) : 0;
548*35878b55SSascha Wildner 		pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
549*35878b55SSascha Wildner 		get_array_info_v2(pVDevice, &pInfo->u.array);
550*35878b55SSascha Wildner 	return 0;
551*35878b55SSascha Wildner }
552*35878b55SSascha Wildner #endif
553*35878b55SSascha Wildner 
554*35878b55SSascha Wildner 	pInfo->Type = LDT_DEVICE;
555*35878b55SSascha Wildner 	pInfo->ParentArray = pVDevice->pParent? VDEV_TO_ID(pVDevice->pParent) : INVALID_DEVICEID;
556*35878b55SSascha Wildner 	/* report real capacity to be compatible with old arrays */
557*35878b55SSascha Wildner 	pInfo->Capacity.lo32 = pVDevice->u.disk.dDeRealCapacity;
558*35878b55SSascha Wildner 	pInfo->Capacity.hi32 = 0;
559*35878b55SSascha Wildner 	return get_disk_info(pVDevice, &pInfo->u.device);
560*35878b55SSascha Wildner }
561*35878b55SSascha Wildner 
562*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
563*35878b55SSascha Wildner DEVICEID hpt_create_array_v2(_VBUS_ARG PCREATE_ARRAY_PARAMS_V2 pParam)
564*35878b55SSascha Wildner {
565*35878b55SSascha Wildner 	ULONG Stamp = GetStamp();
566*35878b55SSascha Wildner 	int	i,j;
567*35878b55SSascha Wildner 	LBA_T  capacity = MAX_LBA_T;
568*35878b55SSascha Wildner 	PVDevice pArray,pChild;
569*35878b55SSascha Wildner 	int		Loca = -1;
570*35878b55SSascha Wildner 
571*35878b55SSascha Wildner 	if (pParam->nDisk > MAX_MEMBERS)
572*35878b55SSascha Wildner 		return INVALID_DEVICEID;
573*35878b55SSascha Wildner /* check in verify_vd
574*35878b55SSascha Wildner 	for(i = 0; i < pParam->nDisk; i++)
575*35878b55SSascha Wildner 	{
576*35878b55SSascha Wildner 		PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
577*35878b55SSascha Wildner 		if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
578*35878b55SSascha Wildner 		if (mIsArray(pVDev)) return INVALID_DEVICEID;
579*35878b55SSascha Wildner 		if (!pVDev->vf_online) return INVALID_DEVICEID;
580*35878b55SSascha Wildner 		if (!_vbus_p)
581*35878b55SSascha Wildner 			_vbus_p = pVDev->u.disk.pVBus;
582*35878b55SSascha Wildner 		else if (_vbus_p != pVDev->u.disk.pVBus)
583*35878b55SSascha Wildner 			return INVALID_DEVICEID;
584*35878b55SSascha Wildner 	}
585*35878b55SSascha Wildner */
586*35878b55SSascha Wildner 	_vbus_p = (ID_TO_VDEV(pParam->Members[0]))->u.disk.pVBus;
587*35878b55SSascha Wildner 	if (!_vbus_p) return INVALID_DEVICEID;
588*35878b55SSascha Wildner 
589*35878b55SSascha Wildner 	mArGetArrayTable(pArray);
590*35878b55SSascha Wildner 	if(!pArray)	return INVALID_DEVICEID;
591*35878b55SSascha Wildner 
592*35878b55SSascha Wildner 	switch (pParam->ArrayType)
593*35878b55SSascha Wildner 	{
594*35878b55SSascha Wildner 		case AT_JBOD:
595*35878b55SSascha Wildner 			pArray->VDeviceType = VD_JBOD;
596*35878b55SSascha Wildner 			goto simple;
597*35878b55SSascha Wildner 
598*35878b55SSascha Wildner 		case AT_RAID0:
599*35878b55SSascha Wildner 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
600*35878b55SSascha Wildner 				goto error;
601*35878b55SSascha Wildner 			pArray->VDeviceType = VD_RAID_0;
602*35878b55SSascha Wildner 			goto simple;
603*35878b55SSascha Wildner 
604*35878b55SSascha Wildner 		case AT_RAID5:
605*35878b55SSascha Wildner 			if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
606*35878b55SSascha Wildner 				goto error;
607*35878b55SSascha Wildner 			pArray->VDeviceType = VD_RAID_5;
608*35878b55SSascha Wildner 			/* only "no build" R5 is not critical after creation. */
609*35878b55SSascha Wildner 			if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
610*35878b55SSascha Wildner 				pArray->u.array.rf_need_rebuild = 1;
611*35878b55SSascha Wildner 			goto simple;
612*35878b55SSascha Wildner 
613*35878b55SSascha Wildner 		case AT_RAID1:
614*35878b55SSascha Wildner 			if(pParam->nDisk <= 2)
615*35878b55SSascha Wildner 			{
616*35878b55SSascha Wildner 				pArray->VDeviceType = VD_RAID_1;
617*35878b55SSascha Wildner simple:
618*35878b55SSascha Wildner 				pArray->u.array.bArnMember = pParam->nDisk;
619*35878b55SSascha Wildner 				pArray->u.array.bArRealnMember = pParam->nDisk;
620*35878b55SSascha Wildner 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
621*35878b55SSascha Wildner 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
622*35878b55SSascha Wildner 				pArray->u.array.dArStamp = Stamp;
623*35878b55SSascha Wildner 
624*35878b55SSascha Wildner 				pArray->u.array.rf_need_sync = 1;
625*35878b55SSascha Wildner 				pArray->u.array.rf_newly_created = 1;
626*35878b55SSascha Wildner 
627*35878b55SSascha Wildner 				if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
628*35878b55SSascha Wildner 					(pArray->VDeviceType == VD_RAID_1))
629*35878b55SSascha Wildner 				{
630*35878b55SSascha Wildner 					pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
631*35878b55SSascha Wildner 					pArray->u.array.rf_need_rebuild = 1;
632*35878b55SSascha Wildner 					pArray->u.array.rf_auto_rebuild = 1;
633*35878b55SSascha Wildner 					pArray->u.array.rf_duplicate_and_create = 1;
634*35878b55SSascha Wildner 
635*35878b55SSascha Wildner 					for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
636*35878b55SSascha Wildner 						if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
637*35878b55SSascha Wildner 							Loca = i;
638*35878b55SSascha Wildner 				}
639*35878b55SSascha Wildner 
640*35878b55SSascha Wildner 				pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
641*35878b55SSascha Wildner 
642*35878b55SSascha Wildner 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
643*35878b55SSascha Wildner 
644*35878b55SSascha Wildner 				for(i = 0; i < pParam->nDisk; i++)
645*35878b55SSascha Wildner 				{
646*35878b55SSascha Wildner 					pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
647*35878b55SSascha Wildner 					pArray->u.array.pMember[i]->bSerialNumber = i;
648*35878b55SSascha Wildner 					pArray->u.array.pMember[i]->pParent = pArray;
649*35878b55SSascha Wildner 
650*35878b55SSascha Wildner 					/* don't unregister source disk for duplicate RAID1 */
651*35878b55SSascha Wildner 					if (i ||
652*35878b55SSascha Wildner 						pArray->VDeviceType!=VD_RAID_1 ||
653*35878b55SSascha Wildner 						(pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
654*35878b55SSascha Wildner 						UnregisterVDevice(pArray->u.array.pMember[i]);
655*35878b55SSascha Wildner 
656*35878b55SSascha Wildner 					if(pArray->VDeviceType == VD_RAID_5)
657*35878b55SSascha Wildner 						pArray->u.array.pMember[i]->vf_cache_disk = 1;
658*35878b55SSascha Wildner 				}
659*35878b55SSascha Wildner 			}
660*35878b55SSascha Wildner 			else
661*35878b55SSascha Wildner 			{
662*35878b55SSascha Wildner 				for(i = 0; i < (pParam->nDisk / 2); i++)
663*35878b55SSascha Wildner 				{
664*35878b55SSascha Wildner 					mArGetArrayTable(pChild);
665*35878b55SSascha Wildner 					pChild->VDeviceType = VD_RAID_1;
666*35878b55SSascha Wildner 
667*35878b55SSascha Wildner 					pChild->u.array.bArnMember = 2;
668*35878b55SSascha Wildner 					pChild->u.array.bArRealnMember = 2;
669*35878b55SSascha Wildner 					pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
670*35878b55SSascha Wildner 					pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
671*35878b55SSascha Wildner 					pChild->u.array.dArStamp = Stamp;
672*35878b55SSascha Wildner 
673*35878b55SSascha Wildner 					pChild->u.array.rf_need_sync = 1;
674*35878b55SSascha Wildner 					pChild->u.array.rf_newly_created = 1;
675*35878b55SSascha Wildner 
676*35878b55SSascha Wildner 					pChild->u.array.RebuildSectors = MAX_LBA_T;
677*35878b55SSascha Wildner 
678*35878b55SSascha Wildner 					memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
679*35878b55SSascha Wildner 
680*35878b55SSascha Wildner 					for(j = 0; j < 2; j++)
681*35878b55SSascha Wildner 					{
682*35878b55SSascha Wildner 						pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
683*35878b55SSascha Wildner 						pChild->u.array.pMember[j]->bSerialNumber = j;
684*35878b55SSascha Wildner 						pChild->u.array.pMember[j]->pParent = pChild;
685*35878b55SSascha Wildner 						pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
686*35878b55SSascha Wildner 						UnregisterVDevice(pChild->u.array.pMember[j]);
687*35878b55SSascha Wildner 					}
688*35878b55SSascha Wildner 
689*35878b55SSascha Wildner 					pArray->u.array.pMember[i] = pChild;
690*35878b55SSascha Wildner 
691*35878b55SSascha Wildner 					pChild->vf_online = 1;
692*35878b55SSascha Wildner 					pChild->bSerialNumber = i;
693*35878b55SSascha Wildner 					pChild->pParent = pArray;
694*35878b55SSascha Wildner 					pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
695*35878b55SSascha Wildner 						pChild->u.array.pMember[1]->VDeviceCapacity);
696*35878b55SSascha Wildner 
697*35878b55SSascha Wildner 					pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
698*35878b55SSascha Wildner 					pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
699*35878b55SSascha Wildner 				}
700*35878b55SSascha Wildner 
701*35878b55SSascha Wildner 				pArray->VDeviceType = VD_RAID_0;
702*35878b55SSascha Wildner 
703*35878b55SSascha Wildner 				pArray->u.array.bArnMember = pParam->nDisk / 2;
704*35878b55SSascha Wildner 				pArray->u.array.bArRealnMember = pParam->nDisk / 2;
705*35878b55SSascha Wildner 				pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
706*35878b55SSascha Wildner 				pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
707*35878b55SSascha Wildner 				pArray->u.array.dArStamp = Stamp;
708*35878b55SSascha Wildner 
709*35878b55SSascha Wildner 				pArray->u.array.rf_need_sync = 1;
710*35878b55SSascha Wildner 				pArray->u.array.rf_newly_created = 1;
711*35878b55SSascha Wildner 
712*35878b55SSascha Wildner 				memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
713*35878b55SSascha Wildner 			}
714*35878b55SSascha Wildner 			break;
715*35878b55SSascha Wildner 
716*35878b55SSascha Wildner 		default:
717*35878b55SSascha Wildner 			goto error;
718*35878b55SSascha Wildner 	}
719*35878b55SSascha Wildner 
720*35878b55SSascha Wildner 	for(i = 0; i < pArray->u.array.bArnMember; i++)
721*35878b55SSascha Wildner 		pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
722*35878b55SSascha Wildner 
723*35878b55SSascha Wildner 	if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
724*35878b55SSascha Wildner 		(pArray->VDeviceType == VD_RAID_1))
725*35878b55SSascha Wildner 	{
726*35878b55SSascha Wildner 		pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
727*35878b55SSascha Wildner 		pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
728*35878b55SSascha Wildner 		pArray->u.array.pMember[0]->vf_bootable = 0;
729*35878b55SSascha Wildner 		pArray->u.array.pMember[0]->vf_bootmark = 0;
730*35878b55SSascha Wildner 		if (Loca>=0) {
731*35878b55SSascha Wildner 			_vbus_p->pVDevice[Loca] = pArray;
732*35878b55SSascha Wildner 			/* to comfort OS */
733*35878b55SSascha Wildner 			pArray->u.array.rf_duplicate_and_created = 1;
734*35878b55SSascha Wildner 			pArray->pVBus = _vbus_p;
735*35878b55SSascha Wildner 		}
736*35878b55SSascha Wildner 	}
737*35878b55SSascha Wildner 	else {
738*35878b55SSascha Wildner 		UCHAR TempBuffer[512];
739*35878b55SSascha Wildner 		ZeroMemory(TempBuffer, 512);
740*35878b55SSascha Wildner 		for(i = 0; i < pParam->nDisk; i++)
741*35878b55SSascha Wildner 		{
742*35878b55SSascha Wildner 			PVDevice	pDisk = ID_TO_VDEV(pParam->Members[i]);
743*35878b55SSascha Wildner 			pDisk->vf_bootmark = pDisk->vf_bootable = 0;
744*35878b55SSascha Wildner 			fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
745*35878b55SSascha Wildner 		}
746*35878b55SSascha Wildner 	}
747*35878b55SSascha Wildner 
748*35878b55SSascha Wildner 	pArray->vf_online = 1;
749*35878b55SSascha Wildner 	pArray->pParent = NULL;
750*35878b55SSascha Wildner 
751*35878b55SSascha Wildner 	switch(pArray->VDeviceType)
752*35878b55SSascha Wildner 	{
753*35878b55SSascha Wildner 		case VD_RAID_0:
754*35878b55SSascha Wildner 			for(i = 0; i < pArray->u.array.bArnMember; i++)
755*35878b55SSascha Wildner 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
756*35878b55SSascha Wildner 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
757*35878b55SSascha Wildner #ifdef ARRAY_V2_ONLY
758*35878b55SSascha Wildner 			capacity -= 10;
759*35878b55SSascha Wildner #endif
760*35878b55SSascha Wildner 			capacity &= ~(pArray->u.array.bStripeWitch - 1);
761*35878b55SSascha Wildner 			/* shrink member capacity for RAID 1/0 */
762*35878b55SSascha Wildner 			for(i = 0; i < pArray->u.array.bArnMember; i++)
763*35878b55SSascha Wildner 				if (mIsArray(pArray->u.array.pMember[i]))
764*35878b55SSascha Wildner 					pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
765*35878b55SSascha Wildner 			pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
766*35878b55SSascha Wildner 			break;
767*35878b55SSascha Wildner 
768*35878b55SSascha Wildner 		case VD_RAID_1:
769*35878b55SSascha Wildner 			pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
770*35878b55SSascha Wildner 						pArray->u.array.pMember[1]->VDeviceCapacity);
771*35878b55SSascha Wildner 			break;
772*35878b55SSascha Wildner 
773*35878b55SSascha Wildner 		case VD_JBOD:
774*35878b55SSascha Wildner 			for(i = 0; i < pArray->u.array.bArnMember; i++)
775*35878b55SSascha Wildner 				pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
776*35878b55SSascha Wildner #ifdef ARRAY_V2_ONLY
777*35878b55SSascha Wildner 				-10
778*35878b55SSascha Wildner #endif
779*35878b55SSascha Wildner 				;
780*35878b55SSascha Wildner 			break;
781*35878b55SSascha Wildner 
782*35878b55SSascha Wildner 		case VD_RAID_5:
783*35878b55SSascha Wildner 			for(i = 0; i < pArray->u.array.bArnMember; i++)
784*35878b55SSascha Wildner 				if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
785*35878b55SSascha Wildner 					capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
786*35878b55SSascha Wildner 			pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1))
787*35878b55SSascha Wildner 				* (pArray->u.array.bArnMember - 1);
788*35878b55SSascha Wildner 			break;
789*35878b55SSascha Wildner 
790*35878b55SSascha Wildner 		default:
791*35878b55SSascha Wildner 			goto error;
792*35878b55SSascha Wildner 	}
793*35878b55SSascha Wildner 
794*35878b55SSascha Wildner 	pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
795*35878b55SSascha Wildner 	pArray->pfnDeviceFailed = fOsDiskFailed;
796*35878b55SSascha Wildner 	SyncArrayInfo(pArray);
797*35878b55SSascha Wildner 
798*35878b55SSascha Wildner 	if (!pArray->u.array.rf_duplicate_and_created)
799*35878b55SSascha Wildner 		RegisterVDevice(pArray);
800*35878b55SSascha Wildner 	return VDEV_TO_ID(pArray);
801*35878b55SSascha Wildner 
802*35878b55SSascha Wildner error:
803*35878b55SSascha Wildner 	for(i = 0; i < pArray->u.array.bArnMember; i++)
804*35878b55SSascha Wildner 	{
805*35878b55SSascha Wildner 		pChild = pArray->u.array.pMember[i];
806*35878b55SSascha Wildner 		if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
807*35878b55SSascha Wildner 			mArFreeArrayTable(pChild);
808*35878b55SSascha Wildner 	}
809*35878b55SSascha Wildner 	mArFreeArrayTable(pArray);
810*35878b55SSascha Wildner 	return INVALID_DEVICEID;
811*35878b55SSascha Wildner }
812*35878b55SSascha Wildner 
813*35878b55SSascha Wildner DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
814*35878b55SSascha Wildner {
815*35878b55SSascha Wildner 	CREATE_ARRAY_PARAMS_V2 param2;
816*35878b55SSascha Wildner 	param2.ArrayType = pParam->ArrayType;
817*35878b55SSascha Wildner 	param2.nDisk = pParam->nDisk;
818*35878b55SSascha Wildner 	param2.BlockSizeShift = pParam->BlockSizeShift;
819*35878b55SSascha Wildner 	param2.CreateFlags = pParam->CreateFlags;
820*35878b55SSascha Wildner 	param2.CreateTime = pParam->CreateTime;
821*35878b55SSascha Wildner 	memcpy(param2.ArrayName, pParam->ArrayName, sizeof(param2.ArrayName));
822*35878b55SSascha Wildner 	memcpy(param2.Description, pParam->Description, sizeof(param2.Description));
823*35878b55SSascha Wildner 	memcpy(param2.CreateManager, pParam->CreateManager, sizeof(param2.CreateManager));
824*35878b55SSascha Wildner 	param2.Capacity.lo32 = param2.Capacity.hi32 = 0;
825*35878b55SSascha Wildner 	memcpy(param2.Members, pParam->Members, sizeof(pParam->Members));
826*35878b55SSascha Wildner 	return hpt_create_array_v2(_VBUS_P &param2);
827*35878b55SSascha Wildner }
828*35878b55SSascha Wildner 
829*35878b55SSascha Wildner #ifdef SUPPORT_OLD_ARRAY
830*35878b55SSascha Wildner /* this is only for old RAID 0/1 */
831*35878b55SSascha Wildner int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
832*35878b55SSascha Wildner {
833*35878b55SSascha Wildner 	PVDevice pArray1 = ID_TO_VDEV(idArray);
834*35878b55SSascha Wildner 	PVDevice pArray2 = 0;
835*35878b55SSascha Wildner 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
836*35878b55SSascha Wildner 	int	i;
837*35878b55SSascha Wildner 	IAL_ADAPTER_T *pAdapter = gIal_Adapter;
838*35878b55SSascha Wildner 
839*35878b55SSascha Wildner 	if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
840*35878b55SSascha Wildner 
841*35878b55SSascha Wildner 	if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
842*35878b55SSascha Wildner 		return -1;
843*35878b55SSascha Wildner 
844*35878b55SSascha Wildner 	pArray2 = pArray1->u.array.pMember[1];
845*35878b55SSascha Wildner 	if(pArray2 == NULL)	{
846*35878b55SSascha Wildner 		/* create a Stripe */
847*35878b55SSascha Wildner 		mArGetArrayTable(pArray2);
848*35878b55SSascha Wildner 		pArray2->VDeviceType = VD_RAID_0;
849*35878b55SSascha Wildner 		pArray2->u.array.dArStamp = GetStamp();
850*35878b55SSascha Wildner 		pArray2->vf_format_v2 = 1;
851*35878b55SSascha Wildner 		pArray2->u.array.rf_broken = 1;
852*35878b55SSascha Wildner 		pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
853*35878b55SSascha Wildner 		pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
854*35878b55SSascha Wildner 		pArray2->u.array.bArnMember = 2;
855*35878b55SSascha Wildner 		pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
856*35878b55SSascha Wildner 		pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
857*35878b55SSascha Wildner 		pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
858*35878b55SSascha Wildner 		memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);
859*35878b55SSascha Wildner 		pArray2->pParent = pArray1;
860*35878b55SSascha Wildner 		pArray2->bSerialNumber = 1;
861*35878b55SSascha Wildner 		pArray1->u.array.pMember[1] = pArray2;
862*35878b55SSascha Wildner 		pArray1->u.array.bArRealnMember++;
863*35878b55SSascha Wildner 	}
864*35878b55SSascha Wildner 
865*35878b55SSascha Wildner 	for(i = 0; i < pArray2->u.array.bArnMember; i++)
866*35878b55SSascha Wildner 		if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
867*35878b55SSascha Wildner 		{
868*35878b55SSascha Wildner 			if(pArray2->u.array.pMember[i] != NULL)
869*35878b55SSascha Wildner 				pArray2->u.array.pMember[i]->pParent = NULL;
870*35878b55SSascha Wildner 			pArray2->u.array.pMember[i] = pDisk;
871*35878b55SSascha Wildner 			goto find;
872*35878b55SSascha Wildner 		}
873*35878b55SSascha Wildner 	return -1;
874*35878b55SSascha Wildner 
875*35878b55SSascha Wildner find:
876*35878b55SSascha Wildner 	UnregisterVDevice(pDisk);
877*35878b55SSascha Wildner 	pDisk->VDeviceType = VD_SINGLE_DISK;
878*35878b55SSascha Wildner 	pDisk->bSerialNumber = i;
879*35878b55SSascha Wildner 	pDisk->pParent = pArray2;
880*35878b55SSascha Wildner 	pDisk->vf_format_v2 = 1;
881*35878b55SSascha Wildner 	pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
882*35878b55SSascha Wildner 	pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
883*35878b55SSascha Wildner 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
884*35878b55SSascha Wildner 
885*35878b55SSascha Wildner 	pArray2->u.array.bArRealnMember++;
886*35878b55SSascha Wildner 	if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){
887*35878b55SSascha Wildner 		pArray2->vf_online = 1;
888*35878b55SSascha Wildner 		pArray2->u.array.rf_broken = 0;
889*35878b55SSascha Wildner 	}
890*35878b55SSascha Wildner 
891*35878b55SSascha Wildner 	if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
892*35878b55SSascha Wildner 		pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
893*35878b55SSascha Wildner 		pArray1->u.array.rf_broken = 0;
894*35878b55SSascha Wildner 		pArray1->u.array.rf_need_rebuild = 1;
895*35878b55SSascha Wildner 		pArray1->u.array.rf_auto_rebuild = 1;
896*35878b55SSascha Wildner 
897*35878b55SSascha Wildner 	}
898*35878b55SSascha Wildner 	pArray1->u.array.RebuildSectors = 0;
899*35878b55SSascha Wildner 	pArray1->u.array.dArStamp = GetStamp();
900*35878b55SSascha Wildner 	SyncArrayInfo(pArray1);
901*35878b55SSascha Wildner 	return 1;
902*35878b55SSascha Wildner }
903*35878b55SSascha Wildner #endif
904*35878b55SSascha Wildner 
905*35878b55SSascha Wildner int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
906*35878b55SSascha Wildner {
907*35878b55SSascha Wildner 	int	i;
908*35878b55SSascha Wildner 
909*35878b55SSascha Wildner 	LBA_T Capacity;
910*35878b55SSascha Wildner 	PVDevice pArray = ID_TO_VDEV(idArray);
911*35878b55SSascha Wildner 	PVDevice pDisk	= ID_TO_VDEV(idDisk);
912*35878b55SSascha Wildner 
913*35878b55SSascha Wildner 	if((idArray == 0) || (idDisk == 0))	return -1;
914*35878b55SSascha Wildner 	if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk))	return -1;
915*35878b55SSascha Wildner 	if(!pArray->u.array.rf_broken)	return -1;
916*35878b55SSascha Wildner 
917*35878b55SSascha Wildner 	if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
918*35878b55SSascha Wildner 		return -1;
919*35878b55SSascha Wildner 	if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
920*35878b55SSascha Wildner 		return -1;
921*35878b55SSascha Wildner 
922*35878b55SSascha Wildner #ifdef SUPPORT_OLD_ARRAY
923*35878b55SSascha Wildner 	/* RAID 0 + 1 */
924*35878b55SSascha Wildner 	if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 &&
925*35878b55SSascha Wildner 		pArray->u.array.pMember[0] &&
926*35878b55SSascha Wildner 		mIsArray(pArray->u.array.pMember[0]))
927*35878b55SSascha Wildner 	{
928*35878b55SSascha Wildner 		if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
929*35878b55SSascha Wildner 			return 0;
930*35878b55SSascha Wildner 		else
931*35878b55SSascha Wildner 			return -1;
932*35878b55SSascha Wildner 	}
933*35878b55SSascha Wildner #endif
934*35878b55SSascha Wildner 
935*35878b55SSascha Wildner 	Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
936*35878b55SSascha Wildner 
937*35878b55SSascha Wildner 	if (pArray->vf_format_v2) {
938*35878b55SSascha Wildner 		if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
939*35878b55SSascha Wildner 	}
940*35878b55SSascha Wildner 	else
941*35878b55SSascha Wildner 		if(pDisk->VDeviceCapacity < Capacity) return -1;
942*35878b55SSascha Wildner 
943*35878b55SSascha Wildner 	if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
944*35878b55SSascha Wildner 
945*35878b55SSascha Wildner 	for(i = 0; i < pArray->u.array.bArnMember; i++)
946*35878b55SSascha Wildner 		if((pArray->u.array.pMember[i] == 0) || !pArray->u.array.pMember[i]->vf_online)
947*35878b55SSascha Wildner 		{
948*35878b55SSascha Wildner 			if(pArray->u.array.pMember[i] != NULL)
949*35878b55SSascha Wildner 				pArray->u.array.pMember[i]->pParent = NULL;
950*35878b55SSascha Wildner 			pArray->u.array.pMember[i] = pDisk;
951*35878b55SSascha Wildner 			goto find;
952*35878b55SSascha Wildner 		}
953*35878b55SSascha Wildner 	return -1;
954*35878b55SSascha Wildner 
955*35878b55SSascha Wildner find:
956*35878b55SSascha Wildner 	UnregisterVDevice(pDisk);
957*35878b55SSascha Wildner 	pDisk->VDeviceType = VD_SINGLE_DISK;
958*35878b55SSascha Wildner 	pDisk->bSerialNumber = i;
959*35878b55SSascha Wildner 	pDisk->pParent = pArray;
960*35878b55SSascha Wildner 	if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
961*35878b55SSascha Wildner 	pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
962*35878b55SSascha Wildner 	if (pArray->vf_format_v2) {
963*35878b55SSascha Wildner 		pDisk->vf_format_v2 = 1;
964*35878b55SSascha Wildner 		pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
965*35878b55SSascha Wildner 	}
966*35878b55SSascha Wildner 
967*35878b55SSascha Wildner 	pArray->u.array.bArRealnMember++;
968*35878b55SSascha Wildner 	if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
969*35878b55SSascha Wildner 	{
970*35878b55SSascha Wildner 		pArray->u.array.rf_need_rebuild = 1;
971*35878b55SSascha Wildner 		pArray->u.array.RebuildSectors = 0;
972*35878b55SSascha Wildner 		pArray->u.array.rf_auto_rebuild = 1;
973*35878b55SSascha Wildner 		pArray->u.array.rf_broken = 0;
974*35878b55SSascha Wildner 	}
975*35878b55SSascha Wildner 	pArray->u.array.RebuildSectors = 0;
976*35878b55SSascha Wildner 
977*35878b55SSascha Wildner 	/* sync the whole array */
978*35878b55SSascha Wildner 	while (pArray->pParent) pArray = pArray->pParent;
979*35878b55SSascha Wildner 	pArray->u.array.dArStamp = GetStamp();
980*35878b55SSascha Wildner 	SyncArrayInfo(pArray);
981*35878b55SSascha Wildner 	return 0;
982*35878b55SSascha Wildner }
983*35878b55SSascha Wildner 
984*35878b55SSascha Wildner int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
985*35878b55SSascha Wildner {
986*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
987*35878b55SSascha Wildner 	DECLARE_BUFFER(PUCHAR, pbuffer);
988*35878b55SSascha Wildner 
989*35878b55SSascha Wildner 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
990*35878b55SSascha Wildner 	if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
991*35878b55SSascha Wildner 		return -1;
992*35878b55SSascha Wildner 
993*35878b55SSascha Wildner 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
994*35878b55SSascha Wildner 
995*35878b55SSascha Wildner 	UnregisterVDevice(pVDevice);
996*35878b55SSascha Wildner 	pVDevice->VDeviceType = VD_SPARE;
997*35878b55SSascha Wildner 	pVDevice->vf_bootmark = 0;
998*35878b55SSascha Wildner 
999*35878b55SSascha Wildner 	ZeroMemory((char *)pbuffer, 512);
1000*35878b55SSascha Wildner 	fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
1001*35878b55SSascha Wildner 	SyncArrayInfo(pVDevice);
1002*35878b55SSascha Wildner 	return 0;
1003*35878b55SSascha Wildner }
1004*35878b55SSascha Wildner 
1005*35878b55SSascha Wildner int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
1006*35878b55SSascha Wildner {
1007*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1008*35878b55SSascha Wildner 
1009*35878b55SSascha Wildner 	if(idDisk == 0 || check_VDevice_valid(pVDevice))	return -1;
1010*35878b55SSascha Wildner 
1011*35878b55SSascha Wildner 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1012*35878b55SSascha Wildner 
1013*35878b55SSascha Wildner 	pVDevice->VDeviceType = VD_SINGLE_DISK;
1014*35878b55SSascha Wildner 
1015*35878b55SSascha Wildner 	SyncArrayInfo(pVDevice);
1016*35878b55SSascha Wildner 	RegisterVDevice(pVDevice);
1017*35878b55SSascha Wildner 	return 0;
1018*35878b55SSascha Wildner }
1019*35878b55SSascha Wildner 
1020*35878b55SSascha Wildner int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
1021*35878b55SSascha Wildner {
1022*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(idArray);
1023*35878b55SSascha Wildner 
1024*35878b55SSascha Wildner 	if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
1025*35878b55SSascha Wildner 	if (!mIsArray(pVDevice)) return -1;
1026*35878b55SSascha Wildner 
1027*35878b55SSascha Wildner 	/* if the pVDevice isn't a top level, return -1; */
1028*35878b55SSascha Wildner 	if(pVDevice->pParent != NULL) return -1;
1029*35878b55SSascha Wildner 
1030*35878b55SSascha Wildner 	if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
1031*35878b55SSascha Wildner 
1032*35878b55SSascha Wildner 	if (pInfo->ValidFields & AAIF_NAME) {
1033*35878b55SSascha Wildner 		memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
1034*35878b55SSascha Wildner 		memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
1035*35878b55SSascha Wildner 		pVDevice->u.array.rf_need_sync = 1;
1036*35878b55SSascha Wildner 	}
1037*35878b55SSascha Wildner 
1038*35878b55SSascha Wildner 	if (pInfo->ValidFields & AAIF_DESCRIPTION) {
1039*35878b55SSascha Wildner 		memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
1040*35878b55SSascha Wildner 		pVDevice->u.array.rf_need_sync = 1;
1041*35878b55SSascha Wildner 	}
1042*35878b55SSascha Wildner 
1043*35878b55SSascha Wildner 	if (pVDevice->u.array.rf_need_sync)
1044*35878b55SSascha Wildner 		SyncArrayInfo(pVDevice);
1045*35878b55SSascha Wildner 	return 0;
1046*35878b55SSascha Wildner }
1047*35878b55SSascha Wildner 
1048*35878b55SSascha Wildner static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
1049*35878b55SSascha Wildner {
1050*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1051*35878b55SSascha Wildner 
1052*35878b55SSascha Wildner 	if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
1053*35878b55SSascha Wildner 	if (mIsArray(pVDevice))
1054*35878b55SSascha Wildner 		return -1;
1055*35878b55SSascha Wildner 
1056*35878b55SSascha Wildner 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1057*35878b55SSascha Wildner 
1058*35878b55SSascha Wildner 	/* TODO */
1059*35878b55SSascha Wildner 		return 0;
1060*35878b55SSascha Wildner 	}
1061*35878b55SSascha Wildner 
1062*35878b55SSascha Wildner static int hpt_set_device_info_v2(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO_V2 pInfo)
1063*35878b55SSascha Wildner {
1064*35878b55SSascha Wildner 	PVDevice pVDevice = ID_TO_VDEV(idDisk);
1065*35878b55SSascha Wildner 	int sync = 0;
1066*35878b55SSascha Wildner 
1067*35878b55SSascha Wildner 	if(idDisk==0 || check_VDevice_valid(pVDevice)) return -1;
1068*35878b55SSascha Wildner 	if (mIsArray(pVDevice))
1069*35878b55SSascha Wildner 		return -1;
1070*35878b55SSascha Wildner 
1071*35878b55SSascha Wildner 	if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1072*35878b55SSascha Wildner 
1073*35878b55SSascha Wildner 	if (pInfo->ValidFields & ADIF_MODE) {
1074*35878b55SSascha Wildner 		pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
1075*35878b55SSascha Wildner 		pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
1076*35878b55SSascha Wildner 		pVDevice->u.disk.df_user_mode_set = 1;
1077*35878b55SSascha Wildner 		fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
1078*35878b55SSascha Wildner 		sync = 1;
1079*35878b55SSascha Wildner }
1080*35878b55SSascha Wildner 
1081*35878b55SSascha Wildner 	if (pInfo->ValidFields & ADIF_TCQ) {
1082*35878b55SSascha Wildner 		if (fDeSetTCQ(&pVDevice->u.disk, pInfo->TCQEnabled, 0)) {
1083*35878b55SSascha Wildner 			pVDevice->u.disk.df_tcq_set = 1;
1084*35878b55SSascha Wildner 			pVDevice->u.disk.df_tcq = pInfo->TCQEnabled!=0;
1085*35878b55SSascha Wildner 			sync = 1;
1086*35878b55SSascha Wildner }
1087*35878b55SSascha Wildner 	}
1088*35878b55SSascha Wildner 
1089*35878b55SSascha Wildner 	if (pInfo->ValidFields & ADIF_NCQ) {
1090*35878b55SSascha Wildner 		if (fDeSetNCQ(&pVDevice->u.disk, pInfo->NCQEnabled, 0)) {
1091*35878b55SSascha Wildner 			pVDevice->u.disk.df_ncq_set = 1;
1092*35878b55SSascha Wildner 			pVDevice->u.disk.df_ncq = pInfo->NCQEnabled!=0;
1093*35878b55SSascha Wildner 			sync = 1;
1094*35878b55SSascha Wildner 	}
1095*35878b55SSascha Wildner 	}
1096*35878b55SSascha Wildner 
1097*35878b55SSascha Wildner 	if (pInfo->ValidFields & ADIF_WRITE_CACHE) {
1098*35878b55SSascha Wildner 		if (fDeSetWriteCache(&pVDevice->u.disk, pInfo->WriteCacheEnabled)) {
1099*35878b55SSascha Wildner 			pVDevice->u.disk.df_write_cache_set = 1;
1100*35878b55SSascha Wildner 			pVDevice->u.disk.df_write_cache = pInfo->WriteCacheEnabled!=0;
1101*35878b55SSascha Wildner 			sync = 1;
1102*35878b55SSascha Wildner 	}
1103*35878b55SSascha Wildner 	}
1104*35878b55SSascha Wildner 
1105*35878b55SSascha Wildner 	if (pInfo->ValidFields & ADIF_READ_AHEAD) {
1106*35878b55SSascha Wildner 		if (fDeSetReadAhead(&pVDevice->u.disk, pInfo->ReadAheadEnabled)) {
1107*35878b55SSascha Wildner 			pVDevice->u.disk.df_read_ahead_set = 1;
1108*35878b55SSascha Wildner 			pVDevice->u.disk.df_read_ahead = pInfo->ReadAheadEnabled!=0;
1109*35878b55SSascha Wildner 			sync = 1;
1110*35878b55SSascha Wildner 		}
1111*35878b55SSascha Wildner 	}
1112*35878b55SSascha Wildner 
1113*35878b55SSascha Wildner 	if (sync)
1114*35878b55SSascha Wildner 		SyncArrayInfo(pVDevice);
1115*35878b55SSascha Wildner 	return 0;
1116*35878b55SSascha Wildner }
1117*35878b55SSascha Wildner 
1118*35878b55SSascha Wildner #endif
1119*35878b55SSascha Wildner 
1120*35878b55SSascha Wildner /* hpt_default_ioctl()
1121*35878b55SSascha Wildner  *  This is a default implementation. The platform dependent part
1122*35878b55SSascha Wildner  *  may reuse this function and/or use it own implementation for
1123*35878b55SSascha Wildner  *  each ioctl function.
1124*35878b55SSascha Wildner  */
1125*35878b55SSascha Wildner int hpt_default_ioctl(_VBUS_ARG
1126*35878b55SSascha Wildner 							DWORD dwIoControlCode,       	/* operation control code */
1127*35878b55SSascha Wildner 							PVOID lpInBuffer,            	/* input data buffer */
1128*35878b55SSascha Wildner 							DWORD nInBufferSize,         	/* size of input data buffer */
1129*35878b55SSascha Wildner 							PVOID lpOutBuffer,           	/* output data buffer */
1130*35878b55SSascha Wildner 							DWORD nOutBufferSize,        	/* size of output data buffer */
1131*35878b55SSascha Wildner 							PDWORD lpBytesReturned      	/* byte count */
1132*35878b55SSascha Wildner 					)
1133*35878b55SSascha Wildner {
1134*35878b55SSascha Wildner 	switch(dwIoControlCode)	{
1135*35878b55SSascha Wildner 
1136*35878b55SSascha Wildner 	case HPT_IOCTL_GET_VERSION:
1137*35878b55SSascha Wildner 
1138*35878b55SSascha Wildner 		if (nInBufferSize != 0) return -1;
1139*35878b55SSascha Wildner 		if (nOutBufferSize != sizeof(DWORD)) return -1;
1140*35878b55SSascha Wildner 		*((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
1141*35878b55SSascha Wildner 		break;
1142*35878b55SSascha Wildner 
1143*35878b55SSascha Wildner 	case HPT_IOCTL_GET_CONTROLLER_COUNT:
1144*35878b55SSascha Wildner 
1145*35878b55SSascha Wildner 		if (nOutBufferSize!=sizeof(DWORD)) return -1;
1146*35878b55SSascha Wildner 		*(PDWORD)lpOutBuffer = hpt_get_controller_count();
1147*35878b55SSascha Wildner 		break;
1148*35878b55SSascha Wildner 
1149*35878b55SSascha Wildner 	case HPT_IOCTL_GET_CONTROLLER_INFO:
1150*35878b55SSascha Wildner 		{
1151*35878b55SSascha Wildner 			int id;
1152*35878b55SSascha Wildner 			PCONTROLLER_INFO pInfo;
1153*35878b55SSascha Wildner 
1154*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DWORD)) return -1;
1155*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
1156*35878b55SSascha Wildner 
1157*35878b55SSascha Wildner 			id = *(DWORD *)lpInBuffer;
1158*35878b55SSascha Wildner 			pInfo = (PCONTROLLER_INFO)lpOutBuffer;
1159*35878b55SSascha Wildner 			if (hpt_get_controller_info(id, pInfo)!=0)
1160*35878b55SSascha Wildner 				return -1;
1161*35878b55SSascha Wildner 		}
1162*35878b55SSascha Wildner 		break;
1163*35878b55SSascha Wildner 
1164*35878b55SSascha Wildner 	case HPT_IOCTL_GET_CHANNEL_INFO:
1165*35878b55SSascha Wildner 		{
1166*35878b55SSascha Wildner 			int id, bus;
1167*35878b55SSascha Wildner 			PCHANNEL_INFO pInfo;
1168*35878b55SSascha Wildner 
1169*35878b55SSascha Wildner 			if (nInBufferSize!=8) return -1;
1170*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
1171*35878b55SSascha Wildner 
1172*35878b55SSascha Wildner 			id = *(DWORD *)lpInBuffer;
1173*35878b55SSascha Wildner 			bus = ((DWORD *)lpInBuffer)[1];
1174*35878b55SSascha Wildner 			pInfo = (PCHANNEL_INFO)lpOutBuffer;
1175*35878b55SSascha Wildner 
1176*35878b55SSascha Wildner 			if (hpt_get_channel_info(id, bus, pInfo)!=0)
1177*35878b55SSascha Wildner 				return -1;
1178*35878b55SSascha Wildner 		}
1179*35878b55SSascha Wildner 		break;
1180*35878b55SSascha Wildner 
1181*35878b55SSascha Wildner 	case HPT_IOCTL_GET_LOGICAL_DEVICES:
1182*35878b55SSascha Wildner 		{
1183*35878b55SSascha Wildner 			DWORD nMax;
1184*35878b55SSascha Wildner 			DEVICEID *pIds;
1185*35878b55SSascha Wildner 
1186*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DWORD)) return -1;
1187*35878b55SSascha Wildner 			nMax = *(DWORD *)lpInBuffer;
1188*35878b55SSascha Wildner 			if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
1189*35878b55SSascha Wildner 
1190*35878b55SSascha Wildner 			pIds = ((DEVICEID *)lpOutBuffer)+1;
1191*35878b55SSascha Wildner 			*(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
1192*35878b55SSascha Wildner 		}
1193*35878b55SSascha Wildner 		break;
1194*35878b55SSascha Wildner 
1195*35878b55SSascha Wildner 	case HPT_IOCTL_GET_DEVICE_INFO:
1196*35878b55SSascha Wildner 		{
1197*35878b55SSascha Wildner 			DEVICEID id;
1198*35878b55SSascha Wildner 			PLOGICAL_DEVICE_INFO pInfo;
1199*35878b55SSascha Wildner 
1200*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1201*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
1202*35878b55SSascha Wildner 
1203*35878b55SSascha Wildner 			id = *(DWORD *)lpInBuffer;
1204*35878b55SSascha Wildner 			if (id == INVALID_DEVICEID)	return -1;
1205*35878b55SSascha Wildner 
1206*35878b55SSascha Wildner 			pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
1207*35878b55SSascha Wildner 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
1208*35878b55SSascha Wildner 
1209*35878b55SSascha Wildner 			if (hpt_get_device_info(id, pInfo)!=0)
1210*35878b55SSascha Wildner 				return -1;
1211*35878b55SSascha Wildner 		}
1212*35878b55SSascha Wildner 		break;
1213*35878b55SSascha Wildner 
1214*35878b55SSascha Wildner 	case HPT_IOCTL_GET_DEVICE_INFO_V2:
1215*35878b55SSascha Wildner 		{
1216*35878b55SSascha Wildner 			DEVICEID id;
1217*35878b55SSascha Wildner 			PLOGICAL_DEVICE_INFO_V2 pInfo;
1218*35878b55SSascha Wildner 
1219*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1220*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO_V2)) return -1;
1221*35878b55SSascha Wildner 
1222*35878b55SSascha Wildner 			id = *(DWORD *)lpInBuffer;
1223*35878b55SSascha Wildner 			if (id == INVALID_DEVICEID)	return -1;
1224*35878b55SSascha Wildner 
1225*35878b55SSascha Wildner 			pInfo = (PLOGICAL_DEVICE_INFO_V2)lpOutBuffer;
1226*35878b55SSascha Wildner 			memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO_V2));
1227*35878b55SSascha Wildner 
1228*35878b55SSascha Wildner 			if (hpt_get_device_info_v2(id, pInfo)!=0)
1229*35878b55SSascha Wildner 				return -1;
1230*35878b55SSascha Wildner 		}
1231*35878b55SSascha Wildner 		break;
1232*35878b55SSascha Wildner 
1233*35878b55SSascha Wildner #ifdef SUPPORT_ARRAY
1234*35878b55SSascha Wildner 	case HPT_IOCTL_CREATE_ARRAY:
1235*35878b55SSascha Wildner 		{
1236*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
1237*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1238*35878b55SSascha Wildner 
1239*35878b55SSascha Wildner 			*(DEVICEID *)lpOutBuffer = hpt_create_array(_VBUS_P (PCREATE_ARRAY_PARAMS)lpInBuffer);
1240*35878b55SSascha Wildner 
1241*35878b55SSascha Wildner 			if(*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
1242*35878b55SSascha Wildner 				return -1;
1243*35878b55SSascha Wildner 		}
1244*35878b55SSascha Wildner 		break;
1245*35878b55SSascha Wildner 
1246*35878b55SSascha Wildner 	case HPT_IOCTL_CREATE_ARRAY_V2:
1247*35878b55SSascha Wildner 		{
1248*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS_V2)) return -1;
1249*35878b55SSascha Wildner 			if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1250*35878b55SSascha Wildner 
1251*35878b55SSascha Wildner 			*(DEVICEID *)lpOutBuffer = hpt_create_array_v2(_VBUS_P (PCREATE_ARRAY_PARAMS_V2)lpInBuffer);
1252*35878b55SSascha Wildner 
1253*35878b55SSascha Wildner 			if (*(DEVICEID *)lpOutBuffer == INVALID_DEVICEID)
1254*35878b55SSascha Wildner 				return -1;
1255*35878b55SSascha Wildner 		}
1256*35878b55SSascha Wildner 		break;
1257*35878b55SSascha Wildner 
1258*35878b55SSascha Wildner 	case HPT_IOCTL_SET_ARRAY_INFO:
1259*35878b55SSascha Wildner 		{
1260*35878b55SSascha Wildner 			DEVICEID idArray;
1261*35878b55SSascha Wildner 			PALTERABLE_ARRAY_INFO pInfo;
1262*35878b55SSascha Wildner 
1263*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
1264*35878b55SSascha Wildner 			if (nOutBufferSize!=0) return -1;
1265*35878b55SSascha Wildner 
1266*35878b55SSascha Wildner 			idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
1267*35878b55SSascha Wildner 			pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
1268*35878b55SSascha Wildner 
1269*35878b55SSascha Wildner 			if(hpt_set_array_info(_VBUS_P idArray,  pInfo))
1270*35878b55SSascha Wildner 				return -1;
1271*35878b55SSascha Wildner 		}
1272*35878b55SSascha Wildner 		break;
1273*35878b55SSascha Wildner 
1274*35878b55SSascha Wildner 	case HPT_IOCTL_SET_DEVICE_INFO:
1275*35878b55SSascha Wildner 		{
1276*35878b55SSascha Wildner 			DEVICEID idDisk;
1277*35878b55SSascha Wildner 			PALTERABLE_DEVICE_INFO pInfo;
1278*35878b55SSascha Wildner 
1279*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
1280*35878b55SSascha Wildner 			if (nOutBufferSize!=0) return -1;
1281*35878b55SSascha Wildner 
1282*35878b55SSascha Wildner 			idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
1283*35878b55SSascha Wildner 			pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
1284*35878b55SSascha Wildner 			if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
1285*35878b55SSascha Wildner 				return -1;
1286*35878b55SSascha Wildner 		}
1287*35878b55SSascha Wildner 		break;
1288*35878b55SSascha Wildner 
1289*35878b55SSascha Wildner 	case HPT_IOCTL_SET_DEVICE_INFO_V2:
1290*35878b55SSascha Wildner 		{
1291*35878b55SSascha Wildner 			DEVICEID idDisk;
1292*35878b55SSascha Wildner 			PALTERABLE_DEVICE_INFO_V2 pInfo;
1293*35878b55SSascha Wildner 
1294*35878b55SSascha Wildner 			if (nInBufferSize < sizeof(HPT_SET_DEVICE_INFO_V2)) return -1;
1295*35878b55SSascha Wildner 			if (nOutBufferSize!=0) return -1;
1296*35878b55SSascha Wildner 
1297*35878b55SSascha Wildner 			idDisk = ((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk;
1298*35878b55SSascha Wildner 			pInfo = &((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->Info;
1299*35878b55SSascha Wildner 			if(hpt_set_device_info_v2(_VBUS_P idDisk, pInfo) != 0)
1300*35878b55SSascha Wildner 				return -1;
1301*35878b55SSascha Wildner 		}
1302*35878b55SSascha Wildner 		break;
1303*35878b55SSascha Wildner 
1304*35878b55SSascha Wildner 	case HPT_IOCTL_SET_BOOT_MARK:
1305*35878b55SSascha Wildner 		{
1306*35878b55SSascha Wildner 			DEVICEID id;
1307*35878b55SSascha Wildner 			PVDevice pTop;
1308*35878b55SSascha Wildner 			int i;
1309*35878b55SSascha Wildner 			IAL_ADAPTER_T *pAdapter = gIal_Adapter;
1310*35878b55SSascha Wildner 			PVBus pVBus;
1311*35878b55SSascha Wildner 
1312*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1313*35878b55SSascha Wildner 			id = *(DEVICEID *)lpInBuffer;
1314*35878b55SSascha Wildner 			while(pAdapter != 0)
1315*35878b55SSascha Wildner 			{
1316*35878b55SSascha Wildner 				pVBus = &pAdapter->VBus;
1317*35878b55SSascha Wildner 				for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
1318*35878b55SSascha Wildner 				{
1319*35878b55SSascha Wildner 					if(!(pTop = pVBus->pVDevice[i])) continue;
1320*35878b55SSascha Wildner 					if (pTop->pVBus!=_vbus_p) return -1;
1321*35878b55SSascha Wildner 					while (pTop->pParent) pTop = pTop->pParent;
1322*35878b55SSascha Wildner 					if (id==0 && pTop->vf_bootmark)
1323*35878b55SSascha Wildner 						pTop->vf_bootmark = 0;
1324*35878b55SSascha Wildner 					else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
1325*35878b55SSascha Wildner 						pTop->vf_bootmark = 1;
1326*35878b55SSascha Wildner 					else
1327*35878b55SSascha Wildner 						continue;
1328*35878b55SSascha Wildner 					SyncArrayInfo(pTop);
1329*35878b55SSascha Wildner 					break;
1330*35878b55SSascha Wildner 				}
1331*35878b55SSascha Wildner 				pAdapter = pAdapter->next;
1332*35878b55SSascha Wildner 			}
1333*35878b55SSascha Wildner 		}
1334*35878b55SSascha Wildner 		break;
1335*35878b55SSascha Wildner 
1336*35878b55SSascha Wildner 	case HPT_IOCTL_ADD_SPARE_DISK:
1337*35878b55SSascha Wildner 		{
1338*35878b55SSascha Wildner 			DEVICEID id;
1339*35878b55SSascha Wildner 
1340*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1341*35878b55SSascha Wildner 			if (nOutBufferSize!=0) return -1;
1342*35878b55SSascha Wildner 
1343*35878b55SSascha Wildner 			id = *(DEVICEID *)lpInBuffer;
1344*35878b55SSascha Wildner 
1345*35878b55SSascha Wildner 			if(hpt_add_spare_disk(_VBUS_P id))
1346*35878b55SSascha Wildner 				return -1;
1347*35878b55SSascha Wildner 		}
1348*35878b55SSascha Wildner 		break;
1349*35878b55SSascha Wildner 
1350*35878b55SSascha Wildner 	case HPT_IOCTL_REMOVE_SPARE_DISK:
1351*35878b55SSascha Wildner 		{
1352*35878b55SSascha Wildner 			DEVICEID id;
1353*35878b55SSascha Wildner 
1354*35878b55SSascha Wildner 			if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1355*35878b55SSascha Wildner 			if (nOutBufferSize!=0) return -1;
1356*35878b55SSascha Wildner 
1357*35878b55SSascha Wildner 			id = *(DEVICEID *)lpInBuffer;
1358*35878b55SSascha Wildner 
1359*35878b55SSascha Wildner 			if(hpt_remove_spare_disk(_VBUS_P id))
1360*35878b55SSascha Wildner 				return -1;
1361*35878b55SSascha Wildner 		}
1362*35878b55SSascha Wildner 		break;
1363*35878b55SSascha Wildner 
1364*35878b55SSascha Wildner 	case HPT_IOCTL_ADD_DISK_TO_ARRAY:
1365*35878b55SSascha Wildner 		{
1366*35878b55SSascha Wildner 			DEVICEID id1,id2;
1367*35878b55SSascha Wildner 			id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
1368*35878b55SSascha Wildner 			id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
1369*35878b55SSascha Wildner 
1370*35878b55SSascha Wildner 			if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
1371*35878b55SSascha Wildner 			if (nOutBufferSize != 0) return -1;
1372*35878b55SSascha Wildner 
1373*35878b55SSascha Wildner 			if(hpt_add_disk_to_array(_VBUS_P id1, id2))
1374*35878b55SSascha Wildner 				return -1;
1375*35878b55SSascha Wildner 		}
1376*35878b55SSascha Wildner 		break;
1377*35878b55SSascha Wildner #endif
1378*35878b55SSascha Wildner 	case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
1379*35878b55SSascha Wildner 		{
1380*35878b55SSascha Wildner 			PDRIVER_CAPABILITIES cap;
1381*35878b55SSascha Wildner 			if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
1382*35878b55SSascha Wildner 			cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
1383*35878b55SSascha Wildner 
1384*35878b55SSascha Wildner 			if(hpt_get_driver_capabilities(cap))
1385*35878b55SSascha Wildner 				return -1;
1386*35878b55SSascha Wildner 		}
1387*35878b55SSascha Wildner 		break;
1388*35878b55SSascha Wildner 
1389*35878b55SSascha Wildner 	case HPT_IOCTL_GET_CONTROLLER_VENID:
1390*35878b55SSascha Wildner 		{
1391*35878b55SSascha Wildner 			DWORD id = ((DWORD*)lpInBuffer)[0];
1392*35878b55SSascha Wildner 			IAL_ADAPTER_T *pAdapTemp;
1393*35878b55SSascha Wildner 			int iControllerCount = 0;
1394*35878b55SSascha Wildner 
1395*35878b55SSascha Wildner 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
1396*35878b55SSascha Wildner 				if (iControllerCount++==id)
1397*35878b55SSascha Wildner 					break;
1398*35878b55SSascha Wildner 
1399*35878b55SSascha Wildner 			if (!pAdapTemp)
1400*35878b55SSascha Wildner 				return -1;
1401*35878b55SSascha Wildner 
1402*35878b55SSascha Wildner 			if (nOutBufferSize < 4)
1403*35878b55SSascha Wildner 				return -1;
1404*35878b55SSascha Wildner 
1405*35878b55SSascha Wildner 			*(DWORD*)lpOutBuffer = ((DWORD)pAdapTemp->mvSataAdapter.pciConfigDeviceId << 16) | 0x11AB;
1406*35878b55SSascha Wildner 			return 0;
1407*35878b55SSascha Wildner 		}
1408*35878b55SSascha Wildner 
1409*35878b55SSascha Wildner 	case HPT_IOCTL_EPROM_IO:
1410*35878b55SSascha Wildner 		{
1411*35878b55SSascha Wildner 			DWORD id           = ((DWORD*)lpInBuffer)[0];
1412*35878b55SSascha Wildner 			DWORD offset	   = ((DWORD*)lpInBuffer)[1];
1413*35878b55SSascha Wildner 			DWORD direction    = ((DWORD*)lpInBuffer)[2];
1414*35878b55SSascha Wildner 			DWORD length	   = ((DWORD*)lpInBuffer)[3];
1415*35878b55SSascha Wildner 			IAL_ADAPTER_T *pAdapTemp;
1416*35878b55SSascha Wildner 			int iControllerCount = 0;
1417*35878b55SSascha Wildner 
1418*35878b55SSascha Wildner 			for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next)
1419*35878b55SSascha Wildner 				if (iControllerCount++==id)
1420*35878b55SSascha Wildner 					break;
1421*35878b55SSascha Wildner 
1422*35878b55SSascha Wildner 			if (!pAdapTemp)
1423*35878b55SSascha Wildner 				return -1;
1424*35878b55SSascha Wildner 
1425*35878b55SSascha Wildner 			if (nInBufferSize < sizeof(DWORD) * 4 + (direction? length : 0) ||
1426*35878b55SSascha Wildner 				nOutBufferSize < (direction? 0 : length))
1427*35878b55SSascha Wildner 				return -1;
1428*35878b55SSascha Wildner 
1429*35878b55SSascha Wildner 			if (direction == 0) /* read */
1430*35878b55SSascha Wildner 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
1431*35878b55SSascha Wildner 					offset, lpOutBuffer, length, 1);
1432*35878b55SSascha Wildner 			else
1433*35878b55SSascha Wildner 				sx508x_flash_access(&pAdapTemp->mvSataAdapter,
1434*35878b55SSascha Wildner 					offset, (char *)lpInBuffer + 16, length, 0);
1435*35878b55SSascha Wildner 
1436*35878b55SSascha Wildner 			return 0;
1437*35878b55SSascha Wildner 		}
1438*35878b55SSascha Wildner 		break;
1439*35878b55SSascha Wildner 
1440*35878b55SSascha Wildner 	default:
1441*35878b55SSascha Wildner 		return -1;
1442*35878b55SSascha Wildner 	}
1443*35878b55SSascha Wildner 
1444*35878b55SSascha Wildner 	if (lpBytesReturned)
1445*35878b55SSascha Wildner 		*lpBytesReturned = nOutBufferSize;
1446*35878b55SSascha Wildner 	return 0;
1447*35878b55SSascha Wildner }
1448