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