]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hptmv/gui_lib.c
This commit was generated by cvs2svn to compensate for changes in r147455,
[FreeBSD/FreeBSD.git] / sys / dev / hptmv / gui_lib.c
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 }