1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause
3 *
4 * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
5 * All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
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 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 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 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 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 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 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 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 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 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 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 ¶m2);
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] == 0) || !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 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 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 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 != 0)
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