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