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