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