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