2 * Copyright (c) 2004-2005 HighPoint Technologies, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * Copyright (c) 2002-2004 HighPoint Technologies, Inc. All rights reserved.
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.
36 * This implementation doesn't use any synchronization; the caller must
37 * assure the proper context when calling these functions.
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/kernel.h>
43 #include <sys/malloc.h>
49 #include <dev/hptmv/global.h>
50 #include <dev/hptmv/hptintf.h>
51 #include <dev/hptmv/osbsd.h>
52 #include <dev/hptmv/access601.h>
54 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
55 static int hpt_get_controller_count(void);
56 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
57 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
58 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
59 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
60 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
61 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
62 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
63 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
64 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
67 check_VDevice_valid(PVDevice p)
72 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
76 for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
77 if(&(pAdapter->VDevices[i]) == p) return 0;
78 pAdapter = pAdapter->next;
82 pAdapter = gIal_Adapter;
85 _vbus_p = &pAdapter->VBus;
86 for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
88 pVDevice=ArrayTables(i);
89 if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
92 pAdapter = pAdapter->next;
100 static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
104 pInfo->Type = LDT_ARRAY;
105 pInfo->Capacity = pVDevice->VDeviceCapacity;
106 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
108 memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
110 switch( pVDevice->VDeviceType )
113 pInfo->u.array.ArrayType = AT_RAID0;
116 pInfo->u.array.ArrayType = AT_RAID1;
119 pInfo->u.array.ArrayType = AT_JBOD;
122 pInfo->u.array.ArrayType = AT_RAID5;
125 pInfo->u.array.ArrayType = AT_UNKNOWN;
128 pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
130 pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors;
132 /* The array is disabled */
133 if(!pVDevice->vf_online) {
134 pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED;
138 /* array need synchronizing */
139 if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
140 pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
142 pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 /
143 (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
145 /* array is in rebuilding process */
146 if(pVDevice->u.array.rf_rebuilding)
147 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
149 /* array is being verified */
150 if(pVDevice->u.array.rf_verifying)
151 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
153 /* array is being initialized */
154 if(pVDevice->u.array.rf_initializing)
155 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
157 /* broken but may still working */
158 if(pVDevice->u.array.rf_broken)
159 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
161 /* array has a active partition */
162 if(pVDevice->vf_bootable)
163 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK;
165 /* a newly created array */
166 if(pVDevice->u.array.rf_newly_created)
167 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
169 /* array has boot mark set */
170 if(pVDevice->vf_bootmark)
171 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK;
173 /* auto-rebuild should start */
174 if(pVDevice->u.array.rf_auto_rebuild)
175 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
177 for(i = 0; i < pVDevice->u.array.bArnMember; i++)
179 PVDevice pMember = pVDevice->u.array.pMember[i];
180 if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
183 /* array need synchronizing */
184 if(pMember->u.array.rf_need_rebuild &&
185 !pMember->u.array.rf_duplicate_and_create)
186 pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
188 /* array is in rebuilding process */
189 if(pMember->u.array.rf_rebuilding)
190 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
192 /* array is being verified */
193 if(pMember->u.array.rf_verifying)
194 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
196 /* array is being initialized */
197 if(pMember->u.array.rf_initializing)
198 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
200 /* broken but may still working */
201 if(pMember->u.array.rf_broken)
202 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
204 /* a newly created array */
205 if(pMember->u.array.rf_newly_created)
206 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
208 /* auto-rebuild should start */
209 if(pMember->u.array.rf_auto_rebuild)
210 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
212 /* for RAID1/0 case */
213 if (pMember->u.array.rf_rebuilding ||
214 pMember->u.array.rf_verifying ||
215 pMember->u.array.rf_initializing)
217 DWORD percent = ((pMember->u.array.RebuildSectors>>11)*1000 /
218 (pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
219 if (pInfo->u.array.RebuildingProgress==0 ||
220 pInfo->u.array.RebuildingProgress>percent)
221 pInfo->u.array.RebuildingProgress = percent;
225 if (pInfo->u.array.RebuildingProgress>10000)
226 pInfo->u.array.RebuildingProgress = 10000;
230 pInfo->u.array.nDisk = 0;
231 for(i=0; i<MAX_ARRAY_MEMBERS; i++)
232 pInfo->u.array.Members[i] = INVALID_DEVICEID;
234 for(i = 0; i < pVDevice->u.array.bArnMember; i++)
236 if(pVDevice->u.array.pMember[i] != 0)
238 pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
239 pInfo->u.array.nDisk++;
245 static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
247 MV_SATA_ADAPTER *pSataAdapter;
248 MV_SATA_CHANNEL *pSataChannel;
249 IAL_ADAPTER_T *pAdapter;
253 pInfo->Type = LDT_DEVICE;
255 if (pVDevice->pParent)
256 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
258 pInfo->ParentArray = INVALID_DEVICEID;
260 /* report real capacity to be compatible with old arrays */
261 pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
263 /* device location */
264 pSataChannel = pVDevice->u.disk.mv;
265 if(pSataChannel == NULL) return -1;
266 pInfo->u.device.TargetId = 0;
267 pSataAdapter = pSataChannel->mvSataAdapter;
268 if(pSataAdapter == NULL) return -1;
270 pAdapter = pSataAdapter->IALData;
272 pInfo->u.device.PathId = pSataChannel->channelNumber;
273 pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId;
275 /*GUI uses DeviceModeSetting to display to users
276 (1) if users select a mode, GUI/BIOS should display that mode.
277 (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
278 (3) display real mode if case (1)&&(2) not satisfied.
280 if (pVDevice->u.disk.df_user_mode_set)
281 pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
282 else if ((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability & 3)==2)
283 pInfo->u.device.DeviceModeSetting = 15;
285 p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
286 if (*(WORD*)p==0x5354 /*'ST'*/ &&
287 (*(WORD*)(p+8)==0x4153/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
288 pInfo->u.device.DeviceModeSetting = 15;
290 pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
293 pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode;
295 pInfo->u.device.DeviceType = PDT_HARDDISK;
297 pInfo->u.device.Flags = 0x0;
299 /* device is disabled */
300 if(!pVDevice->u.disk.df_on_line)
301 pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED;
303 /* disk has a active partition */
304 if(pVDevice->vf_bootable)
305 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK;
307 /* disk has boot mark set */
308 if(pVDevice->vf_bootmark)
309 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK;
311 pInfo->u.device.Flags |= DEVICE_FLAG_SATA;
313 /* is a spare disk */
314 if(pVDevice->VDeviceType == VD_SPARE)
315 pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE;
317 memcpy(&(pInfo->u.device.IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
318 p = (char *)&pInfo->u.device.IdentifyData.ModelNumber;
319 for (i = 0; i < 20; i++)
320 ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
326 int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
328 ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
329 cap->dwSize = sizeof(DRIVER_CAPABILITIES);
330 cap->MaximumControllers = MAX_VBUS;
332 /* cap->SupportCrossControllerRAID = 0; */
333 /* take care for various OSes! */
334 cap->SupportCrossControllerRAID = 0;
337 cap->MinimumBlockSizeShift = MinBlockSizeShift;
338 cap->MaximumBlockSizeShift = MaxBlockSizeShift;
339 cap->SupportDiskModeSetting = 0;
340 cap->SupportSparePool = 1;
341 cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
342 cap->SupportDedicatedSpare = 0;
347 cap->SupportedRAIDTypes[0] = AT_RAID0;
348 cap->MaximumArrayMembers[0] = MAX_MEMBERS;
350 cap->SupportedRAIDTypes[1] = AT_RAID1;
351 cap->MaximumArrayMembers[1] = 2;
352 /* Mirror + Stripe */
354 cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
356 cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
358 cap->MaximumArrayMembers[2] = MAX_MEMBERS;
360 cap->SupportedRAIDTypes[3] = AT_JBOD;
361 cap->MaximumArrayMembers[3] = MAX_MEMBERS;
364 cap->SupportedRAIDTypes[4] = AT_RAID5;
365 cap->MaximumArrayMembers[4] = MAX_MEMBERS;
371 int hpt_get_controller_count(void)
373 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter;
374 int iControllerCount = 0;
376 while(pAdapTemp != 0)
379 pAdapTemp = pAdapTemp->next;
382 return iControllerCount;
385 int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
387 IAL_ADAPTER_T *pAdapTemp;
388 int iControllerCount = 0;
390 for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
391 if (iControllerCount++==id) {
392 pInfo->InterruptLevel = 0;
394 pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
395 strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
396 #ifdef GUI_CONTROLLER_NAME
397 #ifdef FORCE_ATA150_DISPLAY
398 /* show "Bus Type: ATA/150" in GUI for SATA controllers */
399 pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
401 strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
402 #define _set_product_id(x)
404 #define _set_product_id(x) strcpy(pInfo->szProductID, x)
406 _set_product_id("RocketRAID 182x SATA Controller");
408 pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
416 int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
418 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter;
419 int i,iControllerCount = 0;
421 while(pAdapTemp != 0)
423 if (iControllerCount++==id)
425 pAdapTemp = pAdapTemp->next;
432 pInfo->ControlPort = 0;
436 pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
439 if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
440 pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
442 pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
449 int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
453 PVDevice pPhysical, pLogical;
454 IAL_ADAPTER_T *pAdapTemp;
456 for(i = 0; i < nMaxCount; i++)
457 pIds[i] = INVALID_DEVICEID;
459 /* append the arrays not registered on VBus */
460 for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
461 for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
463 pPhysical = &pAdapTemp->VDevices[i];
464 pLogical = pPhysical;
466 while (pLogical->pParent) pLogical = pLogical->pParent;
467 if (pLogical->VDeviceType==VD_SPARE)
470 for (j=0; j<count; j++)
471 if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
472 pIds[count++] = VDEV_TO_ID(pLogical);
473 if (count>=nMaxCount) goto done;
482 int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
484 PVDevice pVDevice = ID_TO_VDEV(id);
486 if((id == 0) || check_VDevice_valid(pVDevice))
490 if (mIsArray(pVDevice))
491 get_array_info(pVDevice, pInfo);
494 return get_disk_info(pVDevice, pInfo);
500 DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
502 ULONG Stamp = GetStamp();
504 ULONG capacity = MAX_LBA_T;
505 PVDevice pArray,pChild;
508 for(i = 0; i < pParam->nDisk; i++)
510 PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
511 if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
512 if (mIsArray(pVDev)) return INVALID_DEVICEID;
513 if (!pVDev->vf_online) return INVALID_DEVICEID;
515 _vbus_p = pVDev->u.disk.pVBus;
516 else if (_vbus_p != pVDev->u.disk.pVBus)
517 return INVALID_DEVICEID;
519 if (!_vbus_p) return INVALID_DEVICEID;
521 mArGetArrayTable(pArray);
522 if(!pArray) return INVALID_DEVICEID;
524 switch (pParam->ArrayType)
527 pArray->VDeviceType = VD_JBOD;
531 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
533 pArray->VDeviceType = VD_RAID_0;
537 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
539 pArray->VDeviceType = VD_RAID_5;
540 /* only "no build" R5 is not critical after creation. */
541 if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
542 pArray->u.array.rf_need_rebuild = 1;
546 if(pParam->nDisk <= 2)
548 pArray->VDeviceType = VD_RAID_1;
550 pArray->u.array.bArnMember = pParam->nDisk;
551 pArray->u.array.bArRealnMember = pParam->nDisk;
552 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
553 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
554 pArray->u.array.dArStamp = Stamp;
556 pArray->u.array.rf_need_sync = 1;
557 pArray->u.array.rf_newly_created = 1;
559 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
560 (pArray->VDeviceType == VD_RAID_1))
562 pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
563 pArray->u.array.rf_need_rebuild = 1;
564 pArray->u.array.rf_auto_rebuild = 1;
565 pArray->u.array.rf_duplicate_and_create = 1;
567 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
568 if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
572 pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
574 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
576 for(i = 0; i < pParam->nDisk; i++)
578 pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
579 pArray->u.array.pMember[i]->bSerialNumber = i;
580 pArray->u.array.pMember[i]->pParent = pArray;
582 /* don't unregister source disk for duplicate RAID1 */
584 pArray->VDeviceType!=VD_RAID_1 ||
585 (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
586 UnregisterVDevice(pArray->u.array.pMember[i]);
588 if(pArray->VDeviceType == VD_RAID_5)
589 pArray->u.array.pMember[i]->vf_cache_disk = 1;
594 for(i = 0; i < (pParam->nDisk / 2); i++)
596 mArGetArrayTable(pChild);
597 pChild->VDeviceType = VD_RAID_1;
599 pChild->u.array.bArnMember = 2;
600 pChild->u.array.bArRealnMember = 2;
601 pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
602 pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
603 pChild->u.array.dArStamp = Stamp;
605 pChild->u.array.rf_need_sync = 1;
606 pChild->u.array.rf_newly_created = 1;
608 pChild->u.array.RebuildSectors = MAX_LBA_T;
610 memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
612 for(j = 0; j < 2; j++)
614 pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
615 pChild->u.array.pMember[j]->bSerialNumber = j;
616 pChild->u.array.pMember[j]->pParent = pChild;
617 pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
618 UnregisterVDevice(pChild->u.array.pMember[j]);
621 pArray->u.array.pMember[i] = pChild;
623 pChild->vf_online = 1;
624 pChild->bSerialNumber = i;
625 pChild->pParent = pArray;
626 pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
627 pChild->u.array.pMember[1]->VDeviceCapacity);
629 pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
630 pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
633 pArray->VDeviceType = VD_RAID_0;
635 pArray->u.array.bArnMember = pParam->nDisk / 2;
636 pArray->u.array.bArRealnMember = pParam->nDisk / 2;
637 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
638 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
639 pArray->u.array.dArStamp = Stamp;
641 pArray->u.array.rf_need_sync = 1;
642 pArray->u.array.rf_newly_created = 1;
644 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
652 for(i = 0; i < pArray->u.array.bArnMember; i++)
653 pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
655 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
656 (pArray->VDeviceType == VD_RAID_1))
658 pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
659 pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
660 pArray->u.array.pMember[0]->vf_bootable = 0;
661 pArray->u.array.pMember[0]->vf_bootmark = 0;
663 _vbus_p->pVDevice[Loca] = pArray;
665 pArray->u.array.rf_duplicate_and_created = 1;
666 pArray->pVBus = _vbus_p;
670 UCHAR TempBuffer[512];
671 ZeroMemory(TempBuffer, 512);
672 for(i = 0; i < pParam->nDisk; i++)
674 PVDevice pDisk = ID_TO_VDEV(pParam->Members[i]);
675 pDisk->vf_bootmark = pDisk->vf_bootable = 0;
676 fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
680 pArray->vf_online = 1;
681 pArray->pParent = NULL;
683 switch(pArray->VDeviceType)
686 for(i = 0; i < pArray->u.array.bArnMember; i++)
687 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
688 capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
692 capacity &= ~(pArray->u.array.bStripeWitch - 1);
693 /* shrink member capacity for RAID 1/0 */
694 for(i = 0; i < pArray->u.array.bArnMember; i++)
695 if (mIsArray(pArray->u.array.pMember[i]))
696 pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
697 pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
701 pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
702 pArray->u.array.pMember[1]->VDeviceCapacity);
706 for(i = 0; i < pArray->u.array.bArnMember; i++)
707 pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
715 for(i = 0; i < pArray->u.array.bArnMember; i++)
716 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
717 capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
718 pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1))
719 * (pArray->u.array.bArnMember - 1);
726 pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
727 pArray->pfnDeviceFailed = fOsDiskFailed;
728 SyncArrayInfo(pArray);
730 if (!pArray->u.array.rf_duplicate_and_created)
731 RegisterVDevice(pArray);
732 return VDEV_TO_ID(pArray);
735 for(i = 0; i < pArray->u.array.bArnMember; i++)
737 pChild = pArray->u.array.pMember[i];
738 if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
739 mArFreeArrayTable(pChild);
741 mArFreeArrayTable(pArray);
742 return INVALID_DEVICEID;
745 #ifdef SUPPORT_OLD_ARRAY
746 /* this is only for old RAID 0/1 */
747 int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
749 PVDevice pArray1 = ID_TO_VDEV(idArray);
750 PVDevice pArray2 = 0;
751 PVDevice pDisk = ID_TO_VDEV(idDisk);
753 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
755 if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
757 if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
760 pArray2 = pArray1->u.array.pMember[1];
761 if(pArray2 == NULL) {
762 /* create a Stripe */
763 mArGetArrayTable(pArray2);
764 pArray2->VDeviceType = VD_RAID_0;
765 pArray2->u.array.dArStamp = GetStamp();
766 pArray2->vf_format_v2 = 1;
767 pArray2->u.array.rf_broken = 1;
768 pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
769 pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
770 pArray2->u.array.bArnMember = 2;
771 pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
772 pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
773 pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
774 memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);
775 pArray2->pParent = pArray1;
776 pArray2->bSerialNumber = 1;
777 pArray1->u.array.pMember[1] = pArray2;
778 pArray1->u.array.bArRealnMember++;
781 for(i = 0; i < pArray2->u.array.bArnMember; i++)
782 if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
784 if(pArray2->u.array.pMember[i] != NULL)
785 pArray2->u.array.pMember[i]->pParent = NULL;
786 pArray2->u.array.pMember[i] = pDisk;
792 UnregisterVDevice(pDisk);
793 pDisk->VDeviceType = VD_SINGLE_DISK;
794 pDisk->bSerialNumber = i;
795 pDisk->pParent = pArray2;
796 pDisk->vf_format_v2 = 1;
797 pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
798 pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
799 pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
801 pArray2->u.array.bArRealnMember++;
802 if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){
803 pArray2->vf_online = 1;
804 pArray2->u.array.rf_broken = 0;
807 if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
808 pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
809 pArray1->u.array.rf_broken = 0;
810 pArray1->u.array.rf_need_rebuild = 1;
811 pArray1->u.array.rf_auto_rebuild = 1;
814 pArray1->u.array.RebuildSectors = 0;
815 pArray1->u.array.dArStamp = GetStamp();
816 SyncArrayInfo(pArray1);
821 int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
826 PVDevice pArray = ID_TO_VDEV(idArray);
827 PVDevice pDisk = ID_TO_VDEV(idDisk);
829 if((idArray == 0) || (idDisk == 0)) return -1;
830 if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1;
831 if(!pArray->u.array.rf_broken) return -1;
833 if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
835 if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
838 #ifdef SUPPORT_OLD_ARRAY
840 if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 &&
841 pArray->u.array.pMember[0] &&
842 mIsArray(pArray->u.array.pMember[0]))
844 if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
851 Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
853 if (pArray->vf_format_v2) {
854 if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
857 if(pDisk->VDeviceCapacity < Capacity) return -1;
859 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
861 for(i = 0; i < pArray->u.array.bArnMember; i++)
862 if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online)
864 if(pArray->u.array.pMember[i] != NULL)
865 pArray->u.array.pMember[i]->pParent = NULL;
866 pArray->u.array.pMember[i] = pDisk;
872 UnregisterVDevice(pDisk);
873 pDisk->VDeviceType = VD_SINGLE_DISK;
874 pDisk->bSerialNumber = i;
875 pDisk->pParent = pArray;
876 if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
877 pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
878 if (pArray->vf_format_v2) {
879 pDisk->vf_format_v2 = 1;
880 pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
883 pArray->u.array.bArRealnMember++;
884 if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
886 pArray->u.array.rf_need_rebuild = 1;
887 pArray->u.array.RebuildSectors = 0;
888 pArray->u.array.rf_auto_rebuild = 1;
889 pArray->u.array.rf_broken = 0;
891 pArray->u.array.RebuildSectors = 0;
893 /* sync the whole array */
894 while (pArray->pParent) pArray = pArray->pParent;
895 pArray->u.array.dArStamp = GetStamp();
896 SyncArrayInfo(pArray);
900 int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
902 PVDevice pVDevice = ID_TO_VDEV(idDisk);
903 DECLARE_BUFFER(PUCHAR, pbuffer);
905 if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
906 if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
909 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
911 UnregisterVDevice(pVDevice);
912 pVDevice->VDeviceType = VD_SPARE;
913 pVDevice->vf_bootmark = 0;
915 ZeroMemory((char *)pbuffer, 512);
916 fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
917 SyncArrayInfo(pVDevice);
921 int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
923 PVDevice pVDevice = ID_TO_VDEV(idDisk);
925 if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
927 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
929 pVDevice->VDeviceType = VD_SINGLE_DISK;
931 SyncArrayInfo(pVDevice);
932 RegisterVDevice(pVDevice);
936 int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
938 PVDevice pVDevice = ID_TO_VDEV(idArray);
940 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1;
941 if (!mIsArray(pVDevice)) return -1;
943 /* if the pVDevice isn't a top level, return -1; */
944 if(pVDevice->pParent != NULL) return -1;
946 if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
948 if (pInfo->ValidFields & AAIF_NAME) {
949 memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
950 memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
951 pVDevice->u.array.rf_need_sync = 1;
954 if (pInfo->ValidFields & AAIF_DESCRIPTION) {
955 memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
956 pVDevice->u.array.rf_need_sync = 1;
959 if (pVDevice->u.array.rf_need_sync)
960 SyncArrayInfo(pVDevice);
964 int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
966 PVDevice pVDevice = ID_TO_VDEV(idDisk);
971 IAL_ADAPTER_T *pAdapter;
972 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
973 if (pAdapter->beeping) {
974 pAdapter->beeping = 0;
975 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
982 if (check_VDevice_valid(pVDevice)) return -1;
983 if (mIsArray(pVDevice))
986 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
988 /* if (pInfo->ValidFields & ADIF_MODE) {
989 pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
990 pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
991 pVDevice->u.disk.df_user_mode_set = 1;
992 fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
993 SyncArrayInfo(pVDevice);
999 #ifdef SUPPORT_HPT601
1000 int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
1002 PVDevice pVDevice = ID_TO_VDEV(idDisk);
1003 PChannel pChan = pVDevice->u.disk.pChannel;
1004 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
1006 if(!pVDevice->u.disk.df_with_601) return -1;
1008 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
1009 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
1011 BeginAccess601(IoPort);
1013 mSetBlockCount(IoPort, 0);
1014 pInfo->DeviceId = InWord(&IoPort->Data);
1016 mSetBlockCount(IoPort, 0x14);
1017 pInfo->Temperature = InWord(&IoPort->Data);
1019 mSetBlockCount(IoPort, 0xA);
1020 pInfo->FanStatus = InWord(&IoPort->Data);
1022 mSetBlockCount(IoPort, 7);
1023 pInfo->BeeperControl = InWord(&IoPort->Data);
1025 mSetBlockCount(IoPort, 3);
1026 pInfo->LED1Control = InWord(&IoPort->Data);
1028 mSetBlockCount(IoPort, 5);
1029 pInfo->LED2Control = InWord(&IoPort->Data);
1031 mSetBlockCount(IoPort, 0x18);
1032 pInfo->PowerStatus = InWord(&IoPort->Data);
1034 EndAccess601(IoPort);
1035 pInfo->ValidFields = 0x7F;
1036 /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/
1040 int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
1042 PVDevice pVDevice = ID_TO_VDEV(idDisk);
1043 PChannel pChan = pVDevice->u.disk.pChannel;
1044 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
1046 if(!pVDevice->u.disk.df_with_601) return -1;
1048 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
1049 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
1051 BeginAccess601(IoPort);
1053 if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) {
1054 mSetBlockCount(IoPort, 1);
1055 OutWord(&IoPort->Data, pInfo->Temperature);
1058 if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) {
1059 mSetBlockCount(IoPort, 0xA);
1060 OutWord(&IoPort->Data, pInfo->FanStatus);
1063 if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) {
1064 mSetBlockCount(IoPort, 7);
1065 OutWord(&IoPort->Data, pInfo->BeeperControl);
1068 if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) {
1069 mSetBlockCount(IoPort, 3);
1070 OutWord(&IoPort->Data, pInfo->LED1Control);
1073 if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) {
1074 mSetBlockCount(IoPort, 5);
1075 OutWord(&IoPort->Data, pInfo->LED2Control);
1078 EndAccess601(IoPort);
1084 /* hpt_default_ioctl()
1085 * This is a default implementation. The platform dependent part
1086 * may reuse this function and/or use it own implementation for
1087 * each ioctl function.
1089 int hpt_default_ioctl(_VBUS_ARG
1090 DWORD dwIoControlCode, /* operation control code */
1091 PVOID lpInBuffer, /* input data buffer */
1092 DWORD nInBufferSize, /* size of input data buffer */
1093 PVOID lpOutBuffer, /* output data buffer */
1094 DWORD nOutBufferSize, /* size of output data buffer */
1095 PDWORD lpBytesReturned /* byte count */
1098 switch(dwIoControlCode) {
1100 case HPT_IOCTL_GET_VERSION:
1102 if (nInBufferSize != 0) return -1;
1103 if (nOutBufferSize != sizeof(DWORD)) return -1;
1104 *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
1107 case HPT_IOCTL_GET_CONTROLLER_COUNT:
1109 if (nOutBufferSize!=sizeof(DWORD)) return -1;
1110 *(PDWORD)lpOutBuffer = hpt_get_controller_count();
1113 case HPT_IOCTL_GET_CONTROLLER_INFO:
1116 PCONTROLLER_INFO pInfo;
1118 if (nInBufferSize!=sizeof(DWORD)) return -1;
1119 if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
1121 id = *(DWORD *)lpInBuffer;
1122 pInfo = (PCONTROLLER_INFO)lpOutBuffer;
1123 if (hpt_get_controller_info(id, pInfo)!=0)
1128 case HPT_IOCTL_GET_CHANNEL_INFO:
1131 PCHANNEL_INFO pInfo;
1133 if (nInBufferSize!=8) return -1;
1134 if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
1136 id = *(DWORD *)lpInBuffer;
1137 bus = ((DWORD *)lpInBuffer)[1];
1138 pInfo = (PCHANNEL_INFO)lpOutBuffer;
1140 if (hpt_get_channel_info(id, bus, pInfo)!=0)
1145 case HPT_IOCTL_GET_LOGICAL_DEVICES:
1150 if (nInBufferSize!=sizeof(DWORD)) return -1;
1151 nMax = *(DWORD *)lpInBuffer;
1152 if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
1154 pIds = ((DEVICEID *)lpOutBuffer)+1;
1155 *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
1159 case HPT_IOCTL_GET_DEVICE_INFO:
1162 PLOGICAL_DEVICE_INFO pInfo;
1164 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1165 if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
1167 id = *(DWORD *)lpInBuffer;
1168 if (id == INVALID_DEVICEID) return -1;
1170 pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
1171 memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
1173 if (hpt_get_device_info(id, pInfo)!=0)
1178 #ifdef SUPPORT_ARRAY
1179 case HPT_IOCTL_CREATE_ARRAY:
1181 CREATE_ARRAY_PARAMS *pParam;
1184 if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
1185 if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1187 pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer;
1189 id = hpt_create_array(_VBUS_P pParam);
1190 *(DEVICEID *)lpOutBuffer = id;
1192 if(id == (DEVICEID)INVALID_DEVICEID)
1197 case HPT_IOCTL_SET_ARRAY_INFO:
1200 PALTERABLE_ARRAY_INFO pInfo;
1202 if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
1203 if (nOutBufferSize!=0) return -1;
1205 idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
1206 pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
1208 if(hpt_set_array_info(_VBUS_P idArray, pInfo))
1213 case HPT_IOCTL_SET_DEVICE_INFO:
1216 PALTERABLE_DEVICE_INFO pInfo;
1218 if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
1219 if (nOutBufferSize!=0) return -1;
1221 idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
1222 pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
1223 if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
1228 case HPT_IOCTL_SET_BOOT_MARK:
1233 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
1236 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1237 id = *(DEVICEID *)lpInBuffer;
1238 while(pAdapter != 0)
1240 pVBus = &pAdapter->VBus;
1241 for(i = 0; i < MAX_ARRAY_PER_VBUS; i++)
1243 if(!(pTop = pVBus->pVDevice[i])) continue;
1244 if (pTop->pVBus!=_vbus_p) return -1;
1245 while (pTop->pParent) pTop = pTop->pParent;
1246 if (id==0 && pTop->vf_bootmark)
1247 pTop->vf_bootmark = 0;
1248 else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
1249 pTop->vf_bootmark = 1;
1252 SyncArrayInfo(pTop);
1255 pAdapter = pAdapter->next;
1260 case HPT_IOCTL_RESCAN_DEVICES:
1262 if (nInBufferSize!=0) return -1;
1263 if (nOutBufferSize!=0) return -1;
1264 fRescanAllDevice(_VBUS_P0);
1268 #ifdef SUPPORT_ARRAY
1269 case HPT_IOCTL_ADD_SPARE_DISK:
1273 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1274 if (nOutBufferSize!=0) return -1;
1276 id = *(DEVICEID *)lpInBuffer;
1278 if(hpt_add_spare_disk(_VBUS_P id))
1283 case HPT_IOCTL_REMOVE_SPARE_DISK:
1287 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1288 if (nOutBufferSize!=0) return -1;
1290 id = *(DEVICEID *)lpInBuffer;
1292 if(hpt_remove_spare_disk(_VBUS_P id))
1297 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
1300 id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
1301 id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
1303 if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
1304 if (nOutBufferSize != 0) return -1;
1306 if(hpt_add_disk_to_array(_VBUS_P id1, id2))
1311 case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
1313 PDRIVER_CAPABILITIES cap;
1314 if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
1315 cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
1317 if(hpt_get_driver_capabilities(cap))
1322 #ifdef SUPPORT_HPT601
1323 case HPT_IOCTL_GET_601_INFO:
1328 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1329 if (nOutBufferSize!=sizeof(HPT601_INFO)) return -1;
1331 id = *(DWORD *)lpInBuffer;
1332 if (id == INVALID_DEVICEID) return -1;
1334 pInfo = (PHPT601_INFO)lpOutBuffer;
1335 memset(pInfo, 0, sizeof(HPT601_INFO));
1337 if (hpt_get_601_info(id, pInfo)!=0)
1342 case HPT_IOCTL_SET_601_INFO:
1347 if (nInBufferSize!=sizeof(HPT_SET_601_INFO)) return -1;
1348 if (nOutBufferSize!=0) return -1;
1350 id = ((PHPT_SET_601_INFO)lpInBuffer)->idDisk;
1351 pInfo = &((PHPT_SET_601_INFO)lpInBuffer)->Info;
1352 if(hpt_set_601_info(id, pInfo) != 0)
1361 if (lpBytesReturned)
1362 *lpBytesReturned = nOutBufferSize;