]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/hptmv/gui_lib.c
add -n option to suppress clearing the build tree and add -DNO_CLEAN
[FreeBSD/FreeBSD.git] / sys / dev / hptmv / gui_lib.c
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 }