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