2 * Copyright (c) 2003-2004 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>
45 #include <dev/hptmv/global.h>
46 #include <dev/hptmv/hptintf.h>
47 #include <dev/hptmv/osbsd.h>
48 #include <dev/hptmv/access601.h>
50 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap);
51 static int hpt_get_controller_count(void);
52 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo);
53 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo);
54 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount);
55 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo);
56 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam);
57 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk);
58 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk);
59 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo);
60 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo);
62 int check_VDevice_valid(PVDevice p)
67 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
71 for (i = 0; i < MV_SATA_CHANNELS_NUM; i++)
72 if(&(pAdapter->VDevices[i]) == p) return 0;
73 pAdapter = pAdapter->next;
77 pAdapter = gIal_Adapter;
80 _vbus_p = &pAdapter->VBus;
81 for (i=0;i<MAX_ARRAY_PER_VBUS;i++)
83 pVDevice=ArrayTables(i);
84 if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p))
87 pAdapter = pAdapter->next;
95 static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
99 pInfo->Type = LDT_ARRAY;
100 pInfo->Capacity = pVDevice->VDeviceCapacity;
101 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
103 memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME);
105 switch( pVDevice->VDeviceType )
108 pInfo->u.array.ArrayType = AT_RAID0;
111 pInfo->u.array.ArrayType = AT_RAID1;
114 pInfo->u.array.ArrayType = AT_JBOD;
117 pInfo->u.array.ArrayType = AT_RAID5;
120 pInfo->u.array.ArrayType = AT_UNKNOWN;
123 pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift;
125 pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors;
127 /* The array is disabled */
128 if(!pVDevice->vf_online) {
129 pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED;
133 /* array need synchronizing */
134 if(pVDevice->u.array.rf_need_rebuild && !pVDevice->u.array.rf_duplicate_and_create)
135 pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
137 pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 /
138 (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10;
140 /* array is in rebuilding process */
141 if(pVDevice->u.array.rf_rebuilding)
142 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
144 /* array is being verified */
145 if(pVDevice->u.array.rf_verifying)
146 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
148 /* array is being initialized */
149 if(pVDevice->u.array.rf_initializing)
150 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
152 /* broken but may still working */
153 if(pVDevice->u.array.rf_broken)
154 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
156 /* array has a active partition */
157 if(pVDevice->vf_bootable)
158 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK;
160 /* a newly created array */
161 if(pVDevice->u.array.rf_newly_created)
162 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
164 /* array has boot mark set */
165 if(pVDevice->vf_bootmark)
166 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK;
168 /* auto-rebuild should start */
169 if(pVDevice->u.array.rf_auto_rebuild)
170 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
172 for(i = 0; i < pVDevice->u.array.bArnMember; i++)
174 PVDevice pMember = pVDevice->u.array.pMember[i];
175 if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK))
178 /* array need synchronizing */
179 if(pMember->u.array.rf_need_rebuild &&
180 !pMember->u.array.rf_duplicate_and_create)
181 pInfo->u.array.Flags |= ARRAY_FLAG_NEEDBUILDING;
183 /* array is in rebuilding process */
184 if(pMember->u.array.rf_rebuilding)
185 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING;
187 /* array is being verified */
188 if(pMember->u.array.rf_verifying)
189 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING;
191 /* array is being initialized */
192 if(pMember->u.array.rf_initializing)
193 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING;
195 /* broken but may still working */
196 if(pMember->u.array.rf_broken)
197 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN;
199 /* a newly created array */
200 if(pMember->u.array.rf_newly_created)
201 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED;
203 /* auto-rebuild should start */
204 if(pMember->u.array.rf_auto_rebuild)
205 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD;
207 /* for RAID1/0 case */
208 if (pMember->u.array.rf_rebuilding ||
209 pMember->u.array.rf_verifying ||
210 pMember->u.array.rf_initializing)
212 DWORD percent = ((pMember->u.array.RebuildSectors>>11)*1000 /
213 (pMember->VDeviceCapacity>>11) * (pMember->u.array.bArnMember-1)) * 10;
214 if (pInfo->u.array.RebuildingProgress==0 ||
215 pInfo->u.array.RebuildingProgress>percent)
216 pInfo->u.array.RebuildingProgress = percent;
220 if (pInfo->u.array.RebuildingProgress>10000)
221 pInfo->u.array.RebuildingProgress = 10000;
225 pInfo->u.array.nDisk = 0;
226 for(i=0; i<MAX_ARRAY_MEMBERS; i++)
227 pInfo->u.array.Members[i] = INVALID_DEVICEID;
229 for(i = 0; i < pVDevice->u.array.bArnMember; i++)
231 if(pVDevice->u.array.pMember[i] != NULL)
233 pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]);
234 pInfo->u.array.nDisk++;
240 static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo)
242 MV_SATA_ADAPTER *pSataAdapter;
243 MV_SATA_CHANNEL *pSataChannel;
244 IAL_ADAPTER_T *pAdapter;
248 pInfo->Type = LDT_DEVICE;
250 if (pVDevice->pParent)
251 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent);
253 pInfo->ParentArray = INVALID_DEVICEID;
255 /* report real capacity to be compatible with old arrays */
256 pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity;
258 /* device location */
259 pSataChannel = pVDevice->u.disk.mv;
260 if(pSataChannel == NULL) return -1;
261 pInfo->u.device.TargetId = 0;
262 pSataAdapter = pSataChannel->mvSataAdapter;
263 if(pSataAdapter == NULL) return -1;
265 pAdapter = pSataAdapter->IALData;
267 pInfo->u.device.PathId = pSataChannel->channelNumber;
268 pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId;
270 /*GUI uses DeviceModeSetting to display to users
271 (1) if users select a mode, GUI/BIOS should display that mode.
272 (2) if SATA/150, GUI/BIOS should display 150 if case (1) isn't satisfied.
273 (3) display real mode if case (1)&&(2) not satisfied.
275 if (pVDevice->u.disk.df_user_mode_set)
276 pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeUserSelectMode;
277 else if ((((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->SataCapability & 3)==2)
278 pInfo->u.device.DeviceModeSetting = 15;
280 p = (char *)&((PIDENTIFY_DATA)pVDevice->u.disk.mv->identifyDevice)->ModelNumber;
281 if (*(WORD*)p==0x5354 /*'ST'*/ &&
282 (*(WORD*)(p+8)==0x4153/*'AS'*/ || (p[8]=='A' && p[11]=='S')))
283 pInfo->u.device.DeviceModeSetting = 15;
285 pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting;
288 pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode;
290 pInfo->u.device.DeviceType = PDT_HARDDISK;
292 pInfo->u.device.Flags = 0x0;
294 /* device is disabled */
295 if(!pVDevice->u.disk.df_on_line)
296 pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED;
298 /* disk has a active partition */
299 if(pVDevice->vf_bootable)
300 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK;
302 /* disk has boot mark set */
303 if(pVDevice->vf_bootmark)
304 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK;
306 pInfo->u.device.Flags |= DEVICE_FLAG_SATA;
308 /* is a spare disk */
309 if(pVDevice->VDeviceType == VD_SPARE)
310 pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE;
312 memcpy(&(pInfo->u.device.IdentifyData), (pSataChannel->identifyDevice), sizeof(IDENTIFY_DATA2));
313 p = (char *)&pInfo->u.device.IdentifyData.ModelNumber;
314 for (i = 0; i < 20; i++)
315 ((WORD*)p)[i] = shortswap(pSataChannel->identifyDevice[IDEN_MODEL_OFFSET+i]);
321 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap)
323 ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES));
324 cap->dwSize = sizeof(DRIVER_CAPABILITIES);
325 cap->MaximumControllers = MAX_VBUS;
327 /* cap->SupportCrossControllerRAID = 0; */
328 /* take care for various OSes! */
329 cap->SupportCrossControllerRAID = 0;
332 cap->MinimumBlockSizeShift = MinBlockSizeShift;
333 cap->MaximumBlockSizeShift = MaxBlockSizeShift;
334 cap->SupportDiskModeSetting = 0;
335 cap->SupportSparePool = 1;
336 cap->MaximumArrayNameLength = MAX_ARRAY_NAME - 1;
337 cap->SupportDedicatedSpare = 0;
339 #ifdef SUPPORT_HOTSWAP
340 cap->SupportHotSwap = 1;
345 cap->SupportedRAIDTypes[0] = AT_RAID0;
346 cap->MaximumArrayMembers[0] = MAX_MEMBERS;
348 cap->SupportedRAIDTypes[1] = AT_RAID1;
349 cap->MaximumArrayMembers[1] = 2;
350 /* Mirror + Stripe */
352 cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */
354 cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */
356 cap->MaximumArrayMembers[2] = MAX_MEMBERS;
358 cap->SupportedRAIDTypes[3] = AT_JBOD;
359 cap->MaximumArrayMembers[3] = MAX_MEMBERS;
362 cap->SupportedRAIDTypes[4] = AT_RAID5;
363 cap->MaximumArrayMembers[4] = MAX_MEMBERS;
365 #if 0 /* don't let GUI create RAID 0/1. */
366 /* Stripe + Mirror */
367 cap->SupportedRAIDTypes[5] = (AT_RAID1<<4)|AT_RAID0;
368 cap->MaximumArrayMembers[5] = 4;
370 #endif /* SUPPORT_ARRAY */
374 static int hpt_get_controller_count(void)
376 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter;
377 int iControllerCount = 0;
379 while(pAdapTemp != 0)
382 pAdapTemp = pAdapTemp->next;
385 return iControllerCount;
388 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo)
390 IAL_ADAPTER_T *pAdapTemp;
391 int iControllerCount = 0;
393 for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
394 if (iControllerCount++==id) {
395 pInfo->InterruptLevel = 0;
397 pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_100;
398 strcpy( pInfo->szVendorID, "HighPoint Technologies, Inc.");
399 #ifdef GUI_CONTROLLER_NAME
400 #ifdef FORCE_ATA150_DISPLAY
401 /* show "Bus Type: ATA/150" in GUI for SATA controllers */
402 pInfo->ChipFlags = CHIP_SUPPORT_ULTRA_150;
404 strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME);
405 #define _set_product_id(x)
407 #define _set_product_id(x) strcpy(pInfo->szProductID, x)
409 _set_product_id("RocketRAID 182x SATA Controller");
411 pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150;
419 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo)
421 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter;
422 int i,iControllerCount = 0;
424 while(pAdapTemp != 0)
426 if (iControllerCount++==id)
428 pAdapTemp = pAdapTemp->next;
435 pInfo->ControlPort = 0;
439 pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID;
442 if (pAdapTemp->mvChannel[bus].online == MV_TRUE)
443 pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]);
445 pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID;
452 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount)
456 PVDevice pPhysical, pLogical;
457 IAL_ADAPTER_T *pAdapTemp;
459 for(i = 0; i < nMaxCount; i++)
460 pIds[i] = INVALID_DEVICEID;
462 /* append the arrays not registered on VBus */
463 for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) {
464 for(i = 0; i < MV_SATA_CHANNELS_NUM; i++)
466 pPhysical = &pAdapTemp->VDevices[i];
467 pLogical = pPhysical;
469 while (pLogical->pParent) pLogical = pLogical->pParent;
470 if (pLogical->VDeviceType==VD_SPARE)
473 for (j=0; j<count; j++)
474 if (pIds[j]==VDEV_TO_ID(pLogical)) goto next;
475 pIds[count++] = VDEV_TO_ID(pLogical);
476 if (count>=nMaxCount) goto done;
485 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo)
487 PVDevice pVDevice = ID_TO_VDEV(id);
489 if((id == HPT_NULL_ID) || check_VDevice_valid(pVDevice))
493 if (mIsArray(pVDevice))
494 get_array_info(pVDevice, pInfo);
497 return get_disk_info(pVDevice, pInfo);
503 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam)
505 ULONG Stamp = GetStamp();
507 ULONG capacity = MAX_LBA_T;
508 PVDevice pArray,pChild;
510 PVBus _vbus_p = NULL;
514 for(i = 0; i < pParam->nDisk; i++)
516 PVDevice pVDev = ID_TO_VDEV(pParam->Members[i]);
517 if (check_VDevice_valid(pVDev)) return INVALID_DEVICEID;
518 if (mIsArray(pVDev)) return INVALID_DEVICEID;
519 if (!pVDev->vf_online) return INVALID_DEVICEID;
521 _vbus_p = pVDev->u.disk.pVBus;
522 else if (_vbus_p != pVDev->u.disk.pVBus)
523 return INVALID_DEVICEID;
525 if (!_vbus_p) return INVALID_DEVICEID;
527 mArGetArrayTable(pArray);
528 if(!pArray) return INVALID_DEVICEID;
530 switch (pParam->ArrayType)
533 pArray->VDeviceType = VD_JBOD;
537 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
539 pArray->VDeviceType = VD_RAID_0;
543 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift))
545 pArray->VDeviceType = VD_RAID_5;
546 /* only "no build" R5 is not critical after creation. */
547 if ((pParam->CreateFlags & CAF_CREATE_R5_NO_BUILD)==0)
548 pArray->u.array.rf_need_rebuild = 1;
552 if(pParam->nDisk <= 2)
554 pArray->VDeviceType = VD_RAID_1;
556 pArray->u.array.bArnMember = pParam->nDisk;
557 pArray->u.array.bArRealnMember = pParam->nDisk;
558 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
559 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
560 pArray->u.array.dArStamp = Stamp;
562 pArray->u.array.rf_need_sync = 1;
563 pArray->u.array.rf_newly_created = 1;
565 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
566 (pArray->VDeviceType == VD_RAID_1))
568 pArray->u.array.rf_newly_created = 0; /* R1 shall still be accessible */
569 pArray->u.array.rf_need_rebuild = 1;
570 pArray->u.array.rf_auto_rebuild = 1;
571 pArray->u.array.rf_duplicate_and_create = 1;
573 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
574 if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0]))
578 pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T;
580 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
582 for(i = 0; i < pParam->nDisk; i++)
584 pArray->u.array.pMember[i] = ID_TO_VDEV(pParam->Members[i]);
585 pArray->u.array.pMember[i]->bSerialNumber = i;
586 pArray->u.array.pMember[i]->pParent = pArray;
588 /* don't unregister source disk for duplicate RAID1 */
590 pArray->VDeviceType!=VD_RAID_1 ||
591 (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0)
592 UnregisterVDevice(pArray->u.array.pMember[i]);
594 if(pArray->VDeviceType == VD_RAID_5)
595 pArray->u.array.pMember[i]->vf_cache_disk = 1;
600 for(i = 0; i < (pParam->nDisk / 2); i++)
602 mArGetArrayTable(pChild);
603 pChild->VDeviceType = VD_RAID_1;
605 pChild->u.array.bArnMember = 2;
606 pChild->u.array.bArRealnMember = 2;
607 pChild->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
608 pChild->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
609 pChild->u.array.dArStamp = Stamp;
611 pChild->u.array.rf_need_sync = 1;
612 pChild->u.array.rf_newly_created = 1;
614 pChild->u.array.RebuildSectors = MAX_LBA_T;
616 memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
618 for(j = 0; j < 2; j++)
620 pChild->u.array.pMember[j] = ID_TO_VDEV(pParam->Members[i*2 + j]);
621 pChild->u.array.pMember[j]->bSerialNumber = j;
622 pChild->u.array.pMember[j]->pParent = pChild;
623 pChild->u.array.pMember[j]->pfnDeviceFailed = pfnDeviceFailed[pChild->VDeviceType];
624 UnregisterVDevice(pChild->u.array.pMember[j]);
627 pArray->u.array.pMember[i] = pChild;
629 pChild->vf_online = 1;
630 pChild->bSerialNumber = i;
631 pChild->pParent = pArray;
632 pChild->VDeviceCapacity = MIN(pChild->u.array.pMember[0]->VDeviceCapacity,
633 pChild->u.array.pMember[1]->VDeviceCapacity);
635 pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType];
636 pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0];
639 pArray->VDeviceType = VD_RAID_0;
641 pArray->u.array.bArnMember = pParam->nDisk / 2;
642 pArray->u.array.bArRealnMember = pParam->nDisk / 2;
643 pArray->u.array.bArBlockSizeShift = pParam->BlockSizeShift;
644 pArray->u.array.bStripeWitch = (1 << pParam->BlockSizeShift);
645 pArray->u.array.dArStamp = Stamp;
647 pArray->u.array.rf_need_sync = 1;
648 pArray->u.array.rf_newly_created = 1;
650 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME);
658 for(i = 0; i < pArray->u.array.bArnMember; i++)
659 pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
661 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) &&
662 (pArray->VDeviceType == VD_RAID_1))
664 pArray->vf_bootmark = pArray->u.array.pMember[0]->vf_bootmark;
665 pArray->vf_bootable = pArray->u.array.pMember[0]->vf_bootable;
666 pArray->u.array.pMember[0]->vf_bootable = 0;
667 pArray->u.array.pMember[0]->vf_bootmark = 0;
669 _vbus_p->pVDevice[Loca] = pArray;
671 pArray->u.array.rf_duplicate_and_created = 1;
672 pArray->pVBus = _vbus_p;
676 UCHAR TempBuffer[512];
677 ZeroMemory(TempBuffer, 512);
678 for(i = 0; i < pParam->nDisk; i++)
680 PVDevice pDisk = ID_TO_VDEV(pParam->Members[i]);
681 pDisk->vf_bootmark = pDisk->vf_bootable = 0;
682 fDeReadWrite(&pDisk->u.disk, 0, IDE_COMMAND_WRITE, TempBuffer);
686 pArray->vf_online = 1;
687 pArray->pParent = NULL;
689 switch(pArray->VDeviceType)
692 for(i = 0; i < pArray->u.array.bArnMember; i++)
693 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
694 capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
698 capacity &= ~(pArray->u.array.bStripeWitch - 1);
699 /* shrink member capacity for RAID 1/0 */
700 for(i = 0; i < pArray->u.array.bArnMember; i++)
701 if (mIsArray(pArray->u.array.pMember[i]))
702 pArray->u.array.pMember[i]->VDeviceCapacity = capacity;
703 pArray->VDeviceCapacity = capacity * pArray->u.array.bArnMember;
707 pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity,
708 pArray->u.array.pMember[1]->VDeviceCapacity);
712 for(i = 0; i < pArray->u.array.bArnMember; i++)
713 pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity
721 for(i = 0; i < pArray->u.array.bArnMember; i++)
722 if(pArray->u.array.pMember[i]->VDeviceCapacity < capacity)
723 capacity = pArray->u.array.pMember[i]->VDeviceCapacity;
724 pArray->VDeviceCapacity = (capacity & ~(pArray->u.array.bStripeWitch - 1))
725 * (pArray->u.array.bArnMember - 1);
732 pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType];
733 pArray->pfnDeviceFailed = fOsDiskFailed;
734 SyncArrayInfo(pArray);
736 if (!pArray->u.array.rf_duplicate_and_created)
737 RegisterVDevice(pArray);
738 return VDEV_TO_ID(pArray);
741 for(i = 0; i < pArray->u.array.bArnMember; i++)
743 pChild = pArray->u.array.pMember[i];
744 if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK))
745 mArFreeArrayTable(pChild);
747 mArFreeArrayTable(pArray);
748 return INVALID_DEVICEID;
751 #ifdef SUPPORT_OLD_ARRAY
752 /* this is only for old RAID 0/1 */
753 int old_add_disk_to_raid01(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
755 PVDevice pArray1 = ID_TO_VDEV(idArray);
756 PVDevice pArray2 = 0;
757 PVDevice pDisk = ID_TO_VDEV(idDisk);
759 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
762 if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
765 if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2))
768 pArray2 = pArray1->u.array.pMember[1];
769 if(pArray2 == NULL) {
770 /* create a Stripe */
771 mArGetArrayTable(pArray2);
772 pArray2->VDeviceType = VD_RAID_0;
773 pArray2->u.array.dArStamp = GetStamp();
774 pArray2->vf_format_v2 = 1;
775 pArray2->u.array.rf_broken = 1;
776 pArray2->u.array.bArBlockSizeShift = pArray1->u.array.bArBlockSizeShift;
777 pArray2->u.array.bStripeWitch = (1 << pArray2->u.array.bArBlockSizeShift);
778 pArray2->u.array.bArnMember = 2;
779 pArray2->VDeviceCapacity = pArray1->VDeviceCapacity;
780 pArray2->pfnSendCommand = pfnSendCommand[pArray2->VDeviceType];
781 pArray2->pfnDeviceFailed = pfnDeviceFailed[pArray1->VDeviceType];
782 memcpy(pArray2->u.array.ArrayName, pArray1->u.array.ArrayName, MAX_ARRAY_NAME);
783 pArray2->pParent = pArray1;
784 pArray2->bSerialNumber = 1;
785 pArray1->u.array.pMember[1] = pArray2;
786 pArray1->u.array.bArRealnMember++;
789 for(i = 0; i < pArray2->u.array.bArnMember; i++)
790 if((pArray2->u.array.pMember[i] == NULL) || !pArray2->u.array.pMember[i]->vf_online)
792 if(pArray2->u.array.pMember[i] != NULL)
793 pArray2->u.array.pMember[i]->pParent = NULL;
794 pArray2->u.array.pMember[i] = pDisk;
800 UnregisterVDevice(pDisk);
801 pDisk->VDeviceType = VD_SINGLE_DISK;
802 pDisk->bSerialNumber = i;
803 pDisk->pParent = pArray2;
804 pDisk->vf_format_v2 = 1;
805 pDisk->u.disk.dDeHiddenLba = i? 10 : 0;
806 pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
807 pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray2->VDeviceType];
809 pArray2->u.array.bArRealnMember++;
810 if(pArray2->u.array.bArnMember == pArray2->u.array.bArRealnMember){
811 pArray2->vf_online = 1;
812 pArray2->u.array.rf_broken = 0;
815 if(pArray1->u.array.pMember[0]->vf_online && pArray1->u.array.pMember[1]->vf_online){
816 pArray1->u.array.bArRealnMember = pArray1->u.array.bArnMember;
817 pArray1->u.array.rf_broken = 0;
818 pArray1->u.array.rf_need_rebuild = 1;
819 pArray1->u.array.rf_auto_rebuild = 1;
822 pArray1->u.array.RebuildSectors = 0;
823 pArray1->u.array.dArStamp = GetStamp();
824 SyncArrayInfo(pArray1);
829 int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk)
834 PVDevice pArray = ID_TO_VDEV(idArray);
835 PVDevice pDisk = ID_TO_VDEV(idDisk);
837 if((idArray == HPT_NULL_ID) || (idDisk == HPT_NULL_ID)) return -1;
838 if(check_VDevice_valid(pArray) || check_VDevice_valid(pDisk)) return -1;
839 if(!pArray->u.array.rf_broken) return -1;
841 if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5)
843 if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE))
846 #ifdef SUPPORT_OLD_ARRAY
848 if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 &&
849 pArray->u.array.pMember[0] &&
850 mIsArray(pArray->u.array.pMember[0]))
852 if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk))
859 Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1);
861 if (pArray->vf_format_v2) {
862 if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1;
865 if(pDisk->VDeviceCapacity < Capacity) return -1;
868 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
871 for(i = 0; i < pArray->u.array.bArnMember; i++)
872 if((pArray->u.array.pMember[i] == NULL) || !pArray->u.array.pMember[i]->vf_online)
874 if(pArray->u.array.pMember[i] != NULL)
875 pArray->u.array.pMember[i]->pParent = NULL;
876 pArray->u.array.pMember[i] = pDisk;
882 UnregisterVDevice(pDisk);
883 pDisk->VDeviceType = VD_SINGLE_DISK;
884 pDisk->bSerialNumber = i;
885 pDisk->pParent = pArray;
886 if (pArray->VDeviceType==VD_RAID_5) pDisk->vf_cache_disk = 1;
887 pDisk->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType];
888 if (pArray->vf_format_v2) {
889 pDisk->vf_format_v2 = 1;
890 pDisk->VDeviceCapacity = pDisk->u.disk.dDeRealCapacity;
893 pArray->u.array.bArRealnMember++;
894 if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember)
896 pArray->u.array.rf_need_rebuild = 1;
897 pArray->u.array.RebuildSectors = 0;
898 pArray->u.array.rf_auto_rebuild = 1;
899 pArray->u.array.rf_broken = 0;
901 pArray->u.array.RebuildSectors = 0;
903 /* sync the whole array */
904 while (pArray->pParent) pArray = pArray->pParent;
905 pArray->u.array.dArStamp = GetStamp();
906 SyncArrayInfo(pArray);
910 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk)
912 PVDevice pVDevice = ID_TO_VDEV(idDisk);
913 DECLARE_BUFFER(PUCHAR, pbuffer);
915 if(idDisk == HPT_NULL_ID || check_VDevice_valid(pVDevice))
917 if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent)
921 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
924 UnregisterVDevice(pVDevice);
925 pVDevice->VDeviceType = VD_SPARE;
926 pVDevice->vf_bootmark = 0;
928 ZeroMemory((char *)pbuffer, 512);
929 fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer);
930 SyncArrayInfo(pVDevice);
934 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk)
936 PVDevice pVDevice = ID_TO_VDEV(idDisk);
938 if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1;
941 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
944 pVDevice->VDeviceType = VD_SINGLE_DISK;
946 SyncArrayInfo(pVDevice);
947 RegisterVDevice(pVDevice);
951 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo)
953 PVDevice pVDevice = ID_TO_VDEV(idArray);
955 if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) return -1;
956 if (!mIsArray(pVDevice)) return -1;
958 /* if the pVDevice isn't a top level, return -1; */
959 if(pVDevice->pParent != NULL) return -1;
962 if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;}
965 if (pInfo->ValidFields & AAIF_NAME) {
966 memset(pVDevice->u.array.ArrayName, 0, MAX_ARRAY_NAME);
967 memcpy(pVDevice->u.array.ArrayName, pInfo->Name, sizeof(pInfo->Name));
968 pVDevice->u.array.rf_need_sync = 1;
971 if (pInfo->ValidFields & AAIF_DESCRIPTION) {
972 memcpy(pVDevice->u.array.Description, pInfo->Description, sizeof(pInfo->Description));
973 pVDevice->u.array.rf_need_sync = 1;
976 if (pVDevice->u.array.rf_need_sync)
977 SyncArrayInfo(pVDevice);
981 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo)
983 PVDevice pVDevice = ID_TO_VDEV(idDisk);
986 if(idDisk == HPT_NULL_ID) {
988 IAL_ADAPTER_T *pAdapter;
989 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) {
990 if (pAdapter->beeping) {
991 pAdapter->beeping = 0;
992 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress);
999 if (check_VDevice_valid(pVDevice)) return -1;
1000 if (mIsArray(pVDevice))
1004 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1;
1007 /* if (pInfo->ValidFields & ADIF_MODE) {
1008 pVDevice->u.disk.bDeModeSetting = pInfo->DeviceModeSetting;
1009 pVDevice->u.disk.bDeUserSelectMode = pInfo->DeviceModeSetting;
1010 pVDevice->u.disk.df_user_mode_set = 1;
1011 fDeSelectMode((PDevice)&(pVDevice->u.disk), (UCHAR)pInfo->DeviceModeSetting);
1012 SyncArrayInfo(pVDevice);
1016 #endif /* SUPPORT_ARRAY */
1018 #ifdef SUPPORT_HPT601
1019 int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
1021 PVDevice pVDevice = ID_TO_VDEV(idDisk);
1022 PChannel pChan = pVDevice->u.disk.pChannel;
1023 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
1025 if(!pVDevice->u.disk.df_with_601) return -1;
1027 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
1028 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
1030 BeginAccess601(IoPort);
1032 mSetBlockCount(IoPort, 0);
1033 pInfo->DeviceId = InWord(&IoPort->Data);
1035 mSetBlockCount(IoPort, 0x14);
1036 pInfo->Temperature = InWord(&IoPort->Data);
1038 mSetBlockCount(IoPort, 0xA);
1039 pInfo->FanStatus = InWord(&IoPort->Data);
1041 mSetBlockCount(IoPort, 7);
1042 pInfo->BeeperControl = InWord(&IoPort->Data);
1044 mSetBlockCount(IoPort, 3);
1045 pInfo->LED1Control = InWord(&IoPort->Data);
1047 mSetBlockCount(IoPort, 5);
1048 pInfo->LED2Control = InWord(&IoPort->Data);
1050 mSetBlockCount(IoPort, 0x18);
1051 pInfo->PowerStatus = InWord(&IoPort->Data);
1053 EndAccess601(IoPort);
1054 pInfo->ValidFields = 0x7F;
1055 /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/
1059 int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo)
1061 PVDevice pVDevice = ID_TO_VDEV(idDisk);
1062 PChannel pChan = pVDevice->u.disk.pChannel;
1063 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1;
1065 if(!pVDevice->u.disk.df_with_601) return -1;
1067 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId);
1068 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1);
1070 BeginAccess601(IoPort);
1072 if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) {
1073 mSetBlockCount(IoPort, 1);
1074 OutWord(&IoPort->Data, pInfo->Temperature);
1077 if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) {
1078 mSetBlockCount(IoPort, 0xA);
1079 OutWord(&IoPort->Data, pInfo->FanStatus);
1082 if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) {
1083 mSetBlockCount(IoPort, 7);
1084 OutWord(&IoPort->Data, pInfo->BeeperControl);
1087 if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) {
1088 mSetBlockCount(IoPort, 3);
1089 OutWord(&IoPort->Data, pInfo->LED1Control);
1092 if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) {
1093 mSetBlockCount(IoPort, 5);
1094 OutWord(&IoPort->Data, pInfo->LED2Control);
1097 EndAccess601(IoPort);
1103 /* hpt_default_ioctl()
1104 * This is a default implementation. The platform dependent part
1105 * may reuse this function and/or use it own implementation for
1106 * each ioctl function.
1108 int hpt_default_ioctl(_VBUS_ARG
1109 DWORD dwIoControlCode, /* operation control code */
1110 PVOID lpInBuffer, /* input data buffer */
1111 DWORD nInBufferSize, /* size of input data buffer */
1112 PVOID lpOutBuffer, /* output data buffer */
1113 DWORD nOutBufferSize, /* size of output data buffer */
1114 PDWORD lpBytesReturned /* byte count */
1117 switch(dwIoControlCode) {
1119 case HPT_IOCTL_GET_VERSION:
1121 if (nInBufferSize != 0) return -1;
1122 if (nOutBufferSize != sizeof(DWORD)) return -1;
1123 *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION;
1126 case HPT_IOCTL_GET_CONTROLLER_COUNT:
1128 if (nOutBufferSize!=sizeof(DWORD)) return -1;
1129 *(PDWORD)lpOutBuffer = hpt_get_controller_count();
1132 case HPT_IOCTL_GET_CONTROLLER_INFO:
1135 PCONTROLLER_INFO pInfo;
1137 if (nInBufferSize!=sizeof(DWORD)) return -1;
1138 if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1;
1140 id = *(DWORD *)lpInBuffer;
1141 pInfo = (PCONTROLLER_INFO)lpOutBuffer;
1142 if (hpt_get_controller_info(id, pInfo)!=0)
1147 case HPT_IOCTL_GET_CHANNEL_INFO:
1150 PCHANNEL_INFO pInfo;
1152 if (nInBufferSize!=8) return -1;
1153 if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1;
1155 id = *(DWORD *)lpInBuffer;
1156 bus = ((DWORD *)lpInBuffer)[1];
1157 pInfo = (PCHANNEL_INFO)lpOutBuffer;
1159 if (hpt_get_channel_info(id, bus, pInfo)!=0)
1164 case HPT_IOCTL_GET_LOGICAL_DEVICES:
1169 if (nInBufferSize!=sizeof(DWORD)) return -1;
1170 nMax = *(DWORD *)lpInBuffer;
1171 if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1;
1173 pIds = ((DEVICEID *)lpOutBuffer)+1;
1174 *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax);
1178 case HPT_IOCTL_GET_DEVICE_INFO:
1181 PLOGICAL_DEVICE_INFO pInfo;
1183 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1184 if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1;
1186 id = *(DWORD *)lpInBuffer;
1187 if (id == INVALID_DEVICEID) return -1;
1189 pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer;
1190 memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO));
1192 if (hpt_get_device_info(id, pInfo)!=0)
1197 #ifdef SUPPORT_ARRAY
1198 case HPT_IOCTL_CREATE_ARRAY:
1200 CREATE_ARRAY_PARAMS *pParam;
1203 if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1;
1204 if (nOutBufferSize!=sizeof(DEVICEID)) return -1;
1206 pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer;
1208 id = hpt_create_array(_VBUS_P pParam);
1209 *(DEVICEID *)lpOutBuffer = id;
1211 if(id == (DEVICEID)INVALID_DEVICEID)
1216 case HPT_IOCTL_SET_ARRAY_INFO:
1219 PALTERABLE_ARRAY_INFO pInfo;
1221 if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1;
1222 if (nOutBufferSize!=0) return -1;
1224 idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray;
1225 pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info;
1227 if(hpt_set_array_info(_VBUS_P idArray, pInfo))
1232 case HPT_IOCTL_SET_DEVICE_INFO:
1235 PALTERABLE_DEVICE_INFO pInfo;
1237 if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1;
1238 if (nOutBufferSize!=0) return -1;
1240 idDisk = ((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk;
1241 pInfo = &((PHPT_SET_DEVICE_INFO)lpInBuffer)->Info;
1242 if(hpt_set_device_info(_VBUS_P idDisk, pInfo) != 0)
1247 case HPT_IOCTL_SET_BOOT_MARK:
1252 IAL_ADAPTER_T *pAdapter = gIal_Adapter;
1255 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1256 id = *(DEVICEID *)lpInBuffer;
1257 while(pAdapter != 0)
1259 pVBus = &pAdapter->VBus;
1260 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++)
1262 if(!(pTop = pVBus->pVDevice[i])) continue;
1264 if (pTop->pVBus!=_vbus_p) return -1;
1266 while (pTop->pParent) pTop = pTop->pParent;
1267 if (id==0 && pTop->vf_bootmark)
1268 pTop->vf_bootmark = 0;
1269 else if (pTop==ID_TO_VDEV(id) && !pTop->vf_bootmark)
1270 pTop->vf_bootmark = 1;
1273 SyncArrayInfo(pTop);
1276 pAdapter = pAdapter->next;
1280 #endif /* SUPPORT_ARRAY */
1281 case HPT_IOCTL_RESCAN_DEVICES:
1283 fRescanAllDevice(_VBUS_P0);
1284 if (nInBufferSize!=0) return -1;
1285 if (nOutBufferSize!=0) return -1;
1286 fRescanAllDevice(_VBUS_P0);
1290 #ifdef SUPPORT_ARRAY
1291 case HPT_IOCTL_ADD_SPARE_DISK:
1295 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1296 if (nOutBufferSize!=0) return -1;
1298 id = *(DEVICEID *)lpInBuffer;
1300 if(hpt_add_spare_disk(_VBUS_P id))
1305 case HPT_IOCTL_REMOVE_SPARE_DISK:
1309 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1310 if (nOutBufferSize!=0) return -1;
1312 id = *(DEVICEID *)lpInBuffer;
1314 if(hpt_remove_spare_disk(_VBUS_P id))
1319 case HPT_IOCTL_ADD_DISK_TO_ARRAY:
1322 id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray;
1323 id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk;
1325 if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1;
1326 if (nOutBufferSize != 0) return -1;
1328 if(hpt_add_disk_to_array(_VBUS_P id1, id2))
1333 case HPT_IOCTL_GET_DRIVER_CAPABILITIES:
1335 PDRIVER_CAPABILITIES cap;
1336 if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1;
1337 cap = (PDRIVER_CAPABILITIES)lpOutBuffer;
1339 if(hpt_get_driver_capabilities(cap))
1344 #ifdef SUPPORT_HPT601
1345 case HPT_IOCTL_GET_601_INFO:
1350 if (nInBufferSize!=sizeof(DEVICEID)) return -1;
1351 if (nOutBufferSize!=sizeof(HPT601_INFO)) return -1;
1353 id = *(DWORD *)lpInBuffer;
1354 if (id == INVALID_DEVICEID) return -1;
1356 pInfo = (PHPT601_INFO)lpOutBuffer;
1357 memset(pInfo, 0, sizeof(HPT601_INFO));
1359 if (hpt_get_601_info(id, pInfo)!=0)
1364 case HPT_IOCTL_SET_601_INFO:
1369 if (nInBufferSize!=sizeof(HPT_SET_601_INFO)) return -1;
1370 if (nOutBufferSize!=0) return -1;
1372 id = ((PHPT_SET_601_INFO)lpInBuffer)->idDisk;
1373 pInfo = &((PHPT_SET_601_INFO)lpInBuffer)->Info;
1374 if(hpt_set_601_info(id, pInfo) != 0)
1383 if (lpBytesReturned)
1384 *lpBytesReturned = nOutBufferSize;