1 /* 2 * Copyright (c) 2003-2004 HighPoint Technologies, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 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. 13 * 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 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 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 #include <dev/hptmv/global.h> 46 #include <dev/hptmv/hptintf.h> 47 #include <dev/hptmv/osbsd.h> 48 #include <dev/hptmv/access601.h> 49 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); 61 62 int check_VDevice_valid(PVDevice p) 63 { 64 int i; 65 PVDevice pVDevice; 66 PVBus _vbus_p; 67 IAL_ADAPTER_T *pAdapter = gIal_Adapter; 68 69 while(pAdapter != 0) 70 { 71 for (i = 0; i < MV_SATA_CHANNELS_NUM; i++) 72 if(&(pAdapter->VDevices[i]) == p) return 0; 73 pAdapter = pAdapter->next; 74 } 75 76 #ifdef SUPPORT_ARRAY 77 pAdapter = gIal_Adapter; 78 while(pAdapter != 0) 79 { 80 _vbus_p = &pAdapter->VBus; 81 for (i=0;i<MAX_ARRAY_PER_VBUS;i++) 82 { 83 pVDevice=ArrayTables(i); 84 if ((pVDevice->u.array.dArStamp != 0) && (pVDevice == p)) 85 return 0; 86 } 87 pAdapter = pAdapter->next; 88 } 89 #endif 90 91 return -1; 92 } 93 94 #ifdef SUPPORT_ARRAY 95 static void get_array_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) 96 { 97 int i; 98 99 pInfo->Type = LDT_ARRAY; 100 pInfo->Capacity = pVDevice->VDeviceCapacity; 101 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); 102 103 memcpy(pInfo->u.array.Name, pVDevice->u.array.ArrayName, MAX_ARRAY_NAME); 104 105 switch( pVDevice->VDeviceType ) 106 { 107 case VD_RAID_0: 108 pInfo->u.array.ArrayType = AT_RAID0; 109 break; 110 case VD_RAID_1: 111 pInfo->u.array.ArrayType = AT_RAID1; 112 break; 113 case VD_JBOD: 114 pInfo->u.array.ArrayType = AT_JBOD; 115 break; 116 case VD_RAID_5: 117 pInfo->u.array.ArrayType = AT_RAID5; 118 break; 119 default: 120 pInfo->u.array.ArrayType = AT_UNKNOWN; 121 } 122 123 pInfo->u.array.BlockSizeShift = pVDevice->u.array.bArBlockSizeShift; 124 125 pInfo->u.array.RebuiltSectors = pVDevice->u.array.RebuildSectors; 126 127 /* The array is disabled */ 128 if(!pVDevice->vf_online) { 129 pInfo->u.array.Flags |= ARRAY_FLAG_DISABLED; 130 goto ignore_info; 131 } 132 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; 136 137 pInfo->u.array.RebuildingProgress = ((pVDevice->u.array.RebuildSectors>>11)*1000 / 138 (pVDevice->VDeviceCapacity>>11) * (pVDevice->u.array.bArnMember-1)) * 10; 139 140 /* array is in rebuilding process */ 141 if(pVDevice->u.array.rf_rebuilding) 142 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; 143 144 /* array is being verified */ 145 if(pVDevice->u.array.rf_verifying) 146 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; 147 148 /* array is being initialized */ 149 if(pVDevice->u.array.rf_initializing) 150 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; 151 152 /* broken but may still working */ 153 if(pVDevice->u.array.rf_broken) 154 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; 155 156 /* array has a active partition */ 157 if(pVDevice->vf_bootable) 158 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTDISK; 159 160 /* a newly created array */ 161 if(pVDevice->u.array.rf_newly_created) 162 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; 163 164 /* array has boot mark set */ 165 if(pVDevice->vf_bootmark) 166 pInfo->u.array.Flags |= ARRAY_FLAG_BOOTMARK; 167 168 /* auto-rebuild should start */ 169 if(pVDevice->u.array.rf_auto_rebuild) 170 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; 171 172 for(i = 0; i < pVDevice->u.array.bArnMember; i++) 173 { 174 PVDevice pMember = pVDevice->u.array.pMember[i]; 175 if (!pMember || !pMember->vf_online || (pMember->VDeviceType==VD_SINGLE_DISK)) 176 continue; 177 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; 182 183 /* array is in rebuilding process */ 184 if(pMember->u.array.rf_rebuilding) 185 pInfo->u.array.Flags |= ARRAY_FLAG_REBUILDING; 186 187 /* array is being verified */ 188 if(pMember->u.array.rf_verifying) 189 pInfo->u.array.Flags |= ARRAY_FLAG_VERIFYING; 190 191 /* array is being initialized */ 192 if(pMember->u.array.rf_initializing) 193 pInfo->u.array.Flags |= ARRAY_FLAG_INITIALIZING; 194 195 /* broken but may still working */ 196 if(pMember->u.array.rf_broken) 197 pInfo->u.array.Flags |= ARRAY_FLAG_BROKEN; 198 199 /* a newly created array */ 200 if(pMember->u.array.rf_newly_created) 201 pInfo->u.array.Flags |= ARRAY_FLAG_NEWLY_CREATED; 202 203 /* auto-rebuild should start */ 204 if(pMember->u.array.rf_auto_rebuild) 205 pInfo->u.array.Flags |= ARRAY_FLAG_NEED_AUTOREBUILD; 206 207 /* for RAID1/0 case */ 208 if (pMember->u.array.rf_rebuilding || 209 pMember->u.array.rf_verifying || 210 pMember->u.array.rf_initializing) 211 { 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; 217 } 218 } 219 220 if (pInfo->u.array.RebuildingProgress>10000) 221 pInfo->u.array.RebuildingProgress = 10000; 222 223 ignore_info: 224 225 pInfo->u.array.nDisk = 0; 226 for(i=0; i<MAX_ARRAY_MEMBERS; i++) 227 pInfo->u.array.Members[i] = INVALID_DEVICEID; 228 229 for(i = 0; i < pVDevice->u.array.bArnMember; i++) 230 { 231 if(pVDevice->u.array.pMember[i] != NULL) 232 { 233 pInfo->u.array.Members[pInfo->u.array.nDisk] = VDEV_TO_ID(pVDevice->u.array.pMember[i]); 234 pInfo->u.array.nDisk++; 235 } 236 } 237 } 238 #endif 239 240 static int get_disk_info(PVDevice pVDevice, PLOGICAL_DEVICE_INFO pInfo) 241 { 242 MV_SATA_ADAPTER *pSataAdapter; 243 MV_SATA_CHANNEL *pSataChannel; 244 IAL_ADAPTER_T *pAdapter; 245 char *p; 246 int i; 247 248 pInfo->Type = LDT_DEVICE; 249 250 if (pVDevice->pParent) 251 pInfo->ParentArray = VDEV_TO_ID(pVDevice->pParent); 252 else 253 pInfo->ParentArray = INVALID_DEVICEID; 254 255 /* report real capacity to be compatible with old arrays */ 256 pInfo->Capacity = pVDevice->u.disk.dDeRealCapacity; 257 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; 264 265 pAdapter = pSataAdapter->IALData; 266 267 pInfo->u.device.PathId = pSataChannel->channelNumber; 268 pInfo->u.device.ControllerId = (UCHAR)pSataAdapter->adapterId; 269 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. 274 */ 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; 279 else { 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; 284 else 285 pInfo->u.device.DeviceModeSetting = pVDevice->u.disk.bDeModeSetting; 286 } 287 288 pInfo->u.device.UsableMode = pVDevice->u.disk.bDeUsable_Mode; 289 290 pInfo->u.device.DeviceType = PDT_HARDDISK; 291 292 pInfo->u.device.Flags = 0x0; 293 294 /* device is disabled */ 295 if(!pVDevice->u.disk.df_on_line) 296 pInfo->u.device.Flags |= DEVICE_FLAG_DISABLED; 297 298 /* disk has a active partition */ 299 if(pVDevice->vf_bootable) 300 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTDISK; 301 302 /* disk has boot mark set */ 303 if(pVDevice->vf_bootmark) 304 pInfo->u.device.Flags |= DEVICE_FLAG_BOOTMARK; 305 306 pInfo->u.device.Flags |= DEVICE_FLAG_SATA; 307 308 /* is a spare disk */ 309 if(pVDevice->VDeviceType == VD_SPARE) 310 pInfo->u.device.Flags |= DEVICE_FLAG_IS_SPARE; 311 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]); 316 p[39] = '\0'; 317 318 return 0; 319 } 320 321 static int hpt_get_driver_capabilities(PDRIVER_CAPABILITIES cap) 322 { 323 ZeroMemory(cap, sizeof(DRIVER_CAPABILITIES)); 324 cap->dwSize = sizeof(DRIVER_CAPABILITIES); 325 cap->MaximumControllers = MAX_VBUS; 326 327 /* cap->SupportCrossControllerRAID = 0; */ 328 /* take care for various OSes! */ 329 cap->SupportCrossControllerRAID = 0; 330 331 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; 338 339 #ifdef SUPPORT_HOTSWAP 340 cap->SupportHotSwap = 1; 341 #endif 342 343 #ifdef SUPPORT_ARRAY 344 /* Stripe */ 345 cap->SupportedRAIDTypes[0] = AT_RAID0; 346 cap->MaximumArrayMembers[0] = MAX_MEMBERS; 347 /* Mirror */ 348 cap->SupportedRAIDTypes[1] = AT_RAID1; 349 cap->MaximumArrayMembers[1] = 2; 350 /* Mirror + Stripe */ 351 #ifdef ARRAY_V2_ONLY 352 cap->SupportedRAIDTypes[2] = (AT_RAID1<<4)|AT_RAID0; /* RAID0/1 */ 353 #else 354 cap->SupportedRAIDTypes[2] = (AT_RAID0<<4)|AT_RAID1; /* RAID1/0 */ 355 #endif 356 cap->MaximumArrayMembers[2] = MAX_MEMBERS; 357 /* Jbod */ 358 cap->SupportedRAIDTypes[3] = AT_JBOD; 359 cap->MaximumArrayMembers[3] = MAX_MEMBERS; 360 /* RAID5 */ 361 #if SUPPORT_RAID5 362 cap->SupportedRAIDTypes[4] = AT_RAID5; 363 cap->MaximumArrayMembers[4] = MAX_MEMBERS; 364 #endif 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; 369 #endif 370 #endif /* SUPPORT_ARRAY */ 371 return 0; 372 } 373 374 static int hpt_get_controller_count(void) 375 { 376 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; 377 int iControllerCount = 0; 378 379 while(pAdapTemp != 0) 380 { 381 iControllerCount++; 382 pAdapTemp = pAdapTemp->next; 383 } 384 385 return iControllerCount; 386 } 387 388 static int hpt_get_controller_info(int id, PCONTROLLER_INFO pInfo) 389 { 390 IAL_ADAPTER_T *pAdapTemp; 391 int iControllerCount = 0; 392 393 for (pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next) { 394 if (iControllerCount++==id) { 395 pInfo->InterruptLevel = 0; 396 pInfo->ChipType = 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; 403 #endif 404 strcpy(pInfo->szProductID, GUI_CONTROLLER_NAME); 405 #define _set_product_id(x) 406 #else 407 #define _set_product_id(x) strcpy(pInfo->szProductID, x) 408 #endif 409 _set_product_id("RocketRAID 182x SATA Controller"); 410 pInfo->NumBuses = 8; 411 pInfo->ChipFlags |= CHIP_SUPPORT_ULTRA_133|CHIP_SUPPORT_ULTRA_150; 412 return 0; 413 } 414 } 415 return -1; 416 } 417 418 419 static int hpt_get_channel_info(int id, int bus, PCHANNEL_INFO pInfo) 420 { 421 IAL_ADAPTER_T *pAdapTemp = gIal_Adapter; 422 int i,iControllerCount = 0; 423 424 while(pAdapTemp != 0) 425 { 426 if (iControllerCount++==id) 427 goto found; 428 pAdapTemp = pAdapTemp->next; 429 } 430 return -1; 431 432 found: 433 434 pInfo->IoPort = 0; 435 pInfo->ControlPort = 0; 436 437 for (i=0; i<2 ;i++) 438 { 439 pInfo->Devices[i] = (DEVICEID)INVALID_DEVICEID; 440 } 441 442 if (pAdapTemp->mvChannel[bus].online == MV_TRUE) 443 pInfo->Devices[0] = VDEV_TO_ID(&pAdapTemp->VDevices[bus]); 444 else 445 pInfo->Devices[0] = (DEVICEID)INVALID_DEVICEID; 446 447 return 0; 448 449 450 } 451 452 static int hpt_get_logical_devices(DEVICEID * pIds, int nMaxCount) 453 { 454 int count = 0; 455 int i,j; 456 PVDevice pPhysical, pLogical; 457 IAL_ADAPTER_T *pAdapTemp; 458 459 for(i = 0; i < nMaxCount; i++) 460 pIds[i] = INVALID_DEVICEID; 461 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++) 465 { 466 pPhysical = &pAdapTemp->VDevices[i]; 467 pLogical = pPhysical; 468 469 while (pLogical->pParent) pLogical = pLogical->pParent; 470 if (pLogical->VDeviceType==VD_SPARE) 471 continue; 472 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; 477 next:; 478 } 479 } 480 481 done: 482 return count; 483 } 484 485 static int hpt_get_device_info(DEVICEID id, PLOGICAL_DEVICE_INFO pInfo) 486 { 487 PVDevice pVDevice = ID_TO_VDEV(id); 488 489 if((id == HPT_NULL_ID) || check_VDevice_valid(pVDevice)) 490 return -1; 491 492 #ifdef SUPPORT_ARRAY 493 if (mIsArray(pVDevice)) 494 get_array_info(pVDevice, pInfo); 495 else 496 #endif 497 return get_disk_info(pVDevice, pInfo); 498 499 return 0; 500 } 501 502 #ifdef SUPPORT_ARRAY 503 static DEVICEID hpt_create_array(_VBUS_ARG PCREATE_ARRAY_PARAMS pParam) 504 { 505 ULONG Stamp = GetStamp(); 506 int i,j; 507 ULONG capacity = MAX_LBA_T; 508 PVDevice pArray,pChild; 509 #if MAX_VBUS==1 510 PVBus _vbus_p = NULL; 511 #endif 512 int Loca = -1; 513 514 for(i = 0; i < pParam->nDisk; i++) 515 { 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; 520 if (!_vbus_p) 521 _vbus_p = pVDev->u.disk.pVBus; 522 else if (_vbus_p != pVDev->u.disk.pVBus) 523 return INVALID_DEVICEID; 524 } 525 if (!_vbus_p) return INVALID_DEVICEID; 526 527 mArGetArrayTable(pArray); 528 if(!pArray) return INVALID_DEVICEID; 529 530 switch (pParam->ArrayType) 531 { 532 case AT_JBOD: 533 pArray->VDeviceType = VD_JBOD; 534 goto simple; 535 536 case AT_RAID0: 537 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) 538 goto error; 539 pArray->VDeviceType = VD_RAID_0; 540 goto simple; 541 542 case AT_RAID5: 543 if((pParam->BlockSizeShift < MinBlockSizeShift) || (pParam->BlockSizeShift > MaxBlockSizeShift)) 544 goto error; 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; 549 goto simple; 550 551 case AT_RAID1: 552 if(pParam->nDisk <= 2) 553 { 554 pArray->VDeviceType = VD_RAID_1; 555 simple: 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; 561 562 pArray->u.array.rf_need_sync = 1; 563 pArray->u.array.rf_newly_created = 1; 564 565 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 566 (pArray->VDeviceType == VD_RAID_1)) 567 { 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; 572 573 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) 574 if (_vbus_p->pVDevice[i] == ID_TO_VDEV(pParam->Members[0])) 575 Loca = i; 576 } 577 578 pArray->u.array.RebuildSectors = pArray->u.array.rf_need_rebuild? 0 : MAX_LBA_T; 579 580 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 581 582 for(i = 0; i < pParam->nDisk; i++) 583 { 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; 587 588 /* don't unregister source disk for duplicate RAID1 */ 589 if (i || 590 pArray->VDeviceType!=VD_RAID_1 || 591 (pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE)==0) 592 UnregisterVDevice(pArray->u.array.pMember[i]); 593 594 if(pArray->VDeviceType == VD_RAID_5) 595 pArray->u.array.pMember[i]->vf_cache_disk = 1; 596 } 597 } 598 else 599 { 600 for(i = 0; i < (pParam->nDisk / 2); i++) 601 { 602 mArGetArrayTable(pChild); 603 pChild->VDeviceType = VD_RAID_1; 604 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; 610 611 pChild->u.array.rf_need_sync = 1; 612 pChild->u.array.rf_newly_created = 1; 613 614 pChild->u.array.RebuildSectors = MAX_LBA_T; 615 616 memcpy(pChild->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 617 618 for(j = 0; j < 2; j++) 619 { 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]); 625 } 626 627 pArray->u.array.pMember[i] = pChild; 628 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); 634 635 pChild->pfnSendCommand = pfnSendCommand[pChild->VDeviceType]; 636 pChild->pfnDeviceFailed = pfnDeviceFailed[VD_RAID_0]; 637 } 638 639 pArray->VDeviceType = VD_RAID_0; 640 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; 646 647 pArray->u.array.rf_need_sync = 1; 648 pArray->u.array.rf_newly_created = 1; 649 650 memcpy(pArray->u.array.ArrayName, pParam->ArrayName, MAX_ARRAY_NAME); 651 } 652 break; 653 654 default: 655 goto error; 656 } 657 658 for(i = 0; i < pArray->u.array.bArnMember; i++) 659 pArray->u.array.pMember[i]->pfnDeviceFailed = pfnDeviceFailed[pArray->VDeviceType]; 660 661 if ((pParam->CreateFlags & CAF_CREATE_AND_DUPLICATE) && 662 (pArray->VDeviceType == VD_RAID_1)) 663 { 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; 668 if (Loca>=0) { 669 _vbus_p->pVDevice[Loca] = pArray; 670 /* to comfort OS */ 671 pArray->u.array.rf_duplicate_and_created = 1; 672 pArray->pVBus = _vbus_p; 673 } 674 } 675 else { 676 UCHAR TempBuffer[512]; 677 ZeroMemory(TempBuffer, 512); 678 for(i = 0; i < pParam->nDisk; i++) 679 { 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); 683 } 684 } 685 686 pArray->vf_online = 1; 687 pArray->pParent = NULL; 688 689 switch(pArray->VDeviceType) 690 { 691 case VD_RAID_0: 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; 695 #ifdef ARRAY_V2_ONLY 696 capacity -= 10; 697 #endif 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; 704 break; 705 706 case VD_RAID_1: 707 pArray->VDeviceCapacity = MIN(pArray->u.array.pMember[0]->VDeviceCapacity, 708 pArray->u.array.pMember[1]->VDeviceCapacity); 709 break; 710 711 case VD_JBOD: 712 for(i = 0; i < pArray->u.array.bArnMember; i++) 713 pArray->VDeviceCapacity += pArray->u.array.pMember[i]->VDeviceCapacity 714 #ifdef ARRAY_V2_ONLY 715 -10 716 #endif 717 ; 718 break; 719 720 case VD_RAID_5: 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); 726 break; 727 728 default: 729 goto error; 730 } 731 732 pArray->pfnSendCommand = pfnSendCommand[pArray->VDeviceType]; 733 pArray->pfnDeviceFailed = fOsDiskFailed; 734 SyncArrayInfo(pArray); 735 736 if (!pArray->u.array.rf_duplicate_and_created) 737 RegisterVDevice(pArray); 738 return VDEV_TO_ID(pArray); 739 740 error: 741 for(i = 0; i < pArray->u.array.bArnMember; i++) 742 { 743 pChild = pArray->u.array.pMember[i]; 744 if((pChild != NULL) && (pChild->VDeviceType != VD_SINGLE_DISK)) 745 mArFreeArrayTable(pChild); 746 } 747 mArFreeArrayTable(pArray); 748 return INVALID_DEVICEID; 749 } 750 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) 754 { 755 PVDevice pArray1 = ID_TO_VDEV(idArray); 756 PVDevice pArray2 = 0; 757 PVDevice pDisk = ID_TO_VDEV(idDisk); 758 int i; 759 IAL_ADAPTER_T *pAdapter = gIal_Adapter; 760 761 #if MAX_VBUS>1 762 if (pArray1->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 763 #endif 764 765 if(pDisk->u.disk.dDeRealCapacity < (pArray1->VDeviceCapacity / 2)) 766 return -1; 767 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++; 787 } 788 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) 791 { 792 if(pArray2->u.array.pMember[i] != NULL) 793 pArray2->u.array.pMember[i]->pParent = NULL; 794 pArray2->u.array.pMember[i] = pDisk; 795 goto find; 796 } 797 return -1; 798 799 find: 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]; 808 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; 813 } 814 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; 820 821 } 822 pArray1->u.array.RebuildSectors = 0; 823 pArray1->u.array.dArStamp = GetStamp(); 824 SyncArrayInfo(pArray1); 825 return 1; 826 } 827 #endif 828 829 int hpt_add_disk_to_array(_VBUS_ARG DEVICEID idArray, DEVICEID idDisk) 830 { 831 int i; 832 833 ULONG Capacity; 834 PVDevice pArray = ID_TO_VDEV(idArray); 835 PVDevice pDisk = ID_TO_VDEV(idDisk); 836 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; 840 841 if(pArray->VDeviceType != VD_RAID_1 && pArray->VDeviceType != VD_RAID_5) 842 return -1; 843 if((pDisk->VDeviceType != VD_SINGLE_DISK) && (pDisk->VDeviceType != VD_SPARE)) 844 return -1; 845 846 #ifdef SUPPORT_OLD_ARRAY 847 /* RAID 0 + 1 */ 848 if (pArray->vf_format_v2 && pArray->VDeviceType==VD_RAID_1 && 849 pArray->u.array.pMember[0] && 850 mIsArray(pArray->u.array.pMember[0])) 851 { 852 if(old_add_disk_to_raid01(_VBUS_P idArray, idDisk)) 853 return 0; 854 else 855 return -1; 856 } 857 #endif 858 859 Capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember - 1); 860 861 if (pArray->vf_format_v2) { 862 if(pDisk->u.disk.dDeRealCapacity < Capacity) return -1; 863 } 864 else 865 if(pDisk->VDeviceCapacity < Capacity) return -1; 866 867 #if MAX_VBUS>1 868 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 869 #endif 870 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) 873 { 874 if(pArray->u.array.pMember[i] != NULL) 875 pArray->u.array.pMember[i]->pParent = NULL; 876 pArray->u.array.pMember[i] = pDisk; 877 goto find; 878 } 879 return -1; 880 881 find: 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; 891 } 892 893 pArray->u.array.bArRealnMember++; 894 if(pArray->u.array.bArnMember == pArray->u.array.bArRealnMember) 895 { 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; 900 } 901 pArray->u.array.RebuildSectors = 0; 902 903 /* sync the whole array */ 904 while (pArray->pParent) pArray = pArray->pParent; 905 pArray->u.array.dArStamp = GetStamp(); 906 SyncArrayInfo(pArray); 907 return 0; 908 } 909 910 static int hpt_add_spare_disk(_VBUS_ARG DEVICEID idDisk) 911 { 912 PVDevice pVDevice = ID_TO_VDEV(idDisk); 913 DECLARE_BUFFER(PUCHAR, pbuffer); 914 915 if(idDisk == HPT_NULL_ID || check_VDevice_valid(pVDevice)) 916 return -1; 917 if (pVDevice->VDeviceType != VD_SINGLE_DISK || pVDevice->pParent) 918 return -1; 919 920 #if MAX_VBUS>1 921 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 922 #endif 923 924 UnregisterVDevice(pVDevice); 925 pVDevice->VDeviceType = VD_SPARE; 926 pVDevice->vf_bootmark = 0; 927 928 ZeroMemory((char *)pbuffer, 512); 929 fDeReadWrite(&pVDevice->u.disk, 0, IDE_COMMAND_WRITE, pbuffer); 930 SyncArrayInfo(pVDevice); 931 return 0; 932 } 933 934 static int hpt_remove_spare_disk(_VBUS_ARG DEVICEID idDisk) 935 { 936 PVDevice pVDevice = ID_TO_VDEV(idDisk); 937 938 if(idDisk == 0 || check_VDevice_valid(pVDevice)) return -1; 939 940 #if MAX_VBUS>1 941 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 942 #endif 943 944 pVDevice->VDeviceType = VD_SINGLE_DISK; 945 946 SyncArrayInfo(pVDevice); 947 RegisterVDevice(pVDevice); 948 return 0; 949 } 950 951 static int hpt_set_array_info(_VBUS_ARG DEVICEID idArray, PALTERABLE_ARRAY_INFO pInfo) 952 { 953 PVDevice pVDevice = ID_TO_VDEV(idArray); 954 955 if(idArray == HPT_NULL_ID || check_VDevice_valid(pVDevice)) return -1; 956 if (!mIsArray(pVDevice)) return -1; 957 958 /* if the pVDevice isn't a top level, return -1; */ 959 if(pVDevice->pParent != NULL) return -1; 960 961 #if MAX_VBUS>1 962 if (pVDevice->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 963 #endif 964 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; 969 } 970 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; 974 } 975 976 if (pVDevice->u.array.rf_need_sync) 977 SyncArrayInfo(pVDevice); 978 return 0; 979 } 980 981 static int hpt_set_device_info(_VBUS_ARG DEVICEID idDisk, PALTERABLE_DEVICE_INFO pInfo) 982 { 983 PVDevice pVDevice = ID_TO_VDEV(idDisk); 984 985 /* stop buzzer. */ 986 if(idDisk == HPT_NULL_ID) { 987 #ifndef FOR_DEMO 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); 993 } 994 } 995 #endif 996 return 0; 997 } 998 999 if (check_VDevice_valid(pVDevice)) return -1; 1000 if (mIsArray(pVDevice)) 1001 return -1; 1002 1003 #if MAX_VBUS>1 1004 if (pVDevice->u.disk.pVBus!=_vbus_p) return -1; 1005 #endif 1006 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); 1013 }*/ 1014 return 0; 1015 } 1016 #endif /* SUPPORT_ARRAY */ 1017 1018 #ifdef SUPPORT_HPT601 1019 int hpt_get_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) 1020 { 1021 PVDevice pVDevice = ID_TO_VDEV(idDisk); 1022 PChannel pChan = pVDevice->u.disk.pChannel; 1023 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; 1024 1025 if(!pVDevice->u.disk.df_with_601) return -1; 1026 1027 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); 1028 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); 1029 1030 BeginAccess601(IoPort); 1031 1032 mSetBlockCount(IoPort, 0); 1033 pInfo->DeviceId = InWord(&IoPort->Data); 1034 1035 mSetBlockCount(IoPort, 0x14); 1036 pInfo->Temperature = InWord(&IoPort->Data); 1037 1038 mSetBlockCount(IoPort, 0xA); 1039 pInfo->FanStatus = InWord(&IoPort->Data); 1040 1041 mSetBlockCount(IoPort, 7); 1042 pInfo->BeeperControl = InWord(&IoPort->Data); 1043 1044 mSetBlockCount(IoPort, 3); 1045 pInfo->LED1Control = InWord(&IoPort->Data); 1046 1047 mSetBlockCount(IoPort, 5); 1048 pInfo->LED2Control = InWord(&IoPort->Data); 1049 1050 mSetBlockCount(IoPort, 0x18); 1051 pInfo->PowerStatus = InWord(&IoPort->Data); 1052 1053 EndAccess601(IoPort); 1054 pInfo->ValidFields = 0x7F; 1055 /*DEVICEID|TEMPERATURE|FANSTATUS|BEEPERCONTROL|LED1CONTROL|LED2CONTROL|POWERSTATUS*/ 1056 return 0; 1057 } 1058 1059 int hpt_set_601_info(DEVICEID idDisk, PHPT601_INFO pInfo) 1060 { 1061 PVDevice pVDevice = ID_TO_VDEV(idDisk); 1062 PChannel pChan = pVDevice->u.disk.pChannel; 1063 PIDE_REGISTERS_1 IoPort = pChan->BaseIoAddress1; 1064 1065 if(!pVDevice->u.disk.df_with_601) return -1; 1066 1067 mSelectUnit(IoPort, pVDevice->u.disk.bDeUnitId); 1068 pChan->pChipInstance->ftbl.pfnWaitOnBusy(pChan, pVDevice->u.disk.bDeUnitId, 1); 1069 1070 BeginAccess601(IoPort); 1071 1072 if (pInfo->ValidFields & HPT601_INFO_TEMPERATURE) { 1073 mSetBlockCount(IoPort, 1); 1074 OutWord(&IoPort->Data, pInfo->Temperature); 1075 } 1076 1077 if (pInfo->ValidFields & HPT601_INFO_FANSTATUS) { 1078 mSetBlockCount(IoPort, 0xA); 1079 OutWord(&IoPort->Data, pInfo->FanStatus); 1080 } 1081 1082 if (pInfo->ValidFields & HPT601_INFO_BEEPERCONTROL) { 1083 mSetBlockCount(IoPort, 7); 1084 OutWord(&IoPort->Data, pInfo->BeeperControl); 1085 } 1086 1087 if (pInfo->ValidFields & HPT601_INFO_LED1CONTROL) { 1088 mSetBlockCount(IoPort, 3); 1089 OutWord(&IoPort->Data, pInfo->LED1Control); 1090 } 1091 1092 if (pInfo->ValidFields & HPT601_INFO_LED2CONTROL) { 1093 mSetBlockCount(IoPort, 5); 1094 OutWord(&IoPort->Data, pInfo->LED2Control); 1095 } 1096 1097 EndAccess601(IoPort); 1098 1099 return 0; 1100 } 1101 #endif 1102 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. 1107 */ 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 */ 1115 ) 1116 { 1117 switch(dwIoControlCode) { 1118 1119 case HPT_IOCTL_GET_VERSION: 1120 1121 if (nInBufferSize != 0) return -1; 1122 if (nOutBufferSize != sizeof(DWORD)) return -1; 1123 *((DWORD*)lpOutBuffer) = HPT_INTERFACE_VERSION; 1124 break; 1125 1126 case HPT_IOCTL_GET_CONTROLLER_COUNT: 1127 1128 if (nOutBufferSize!=sizeof(DWORD)) return -1; 1129 *(PDWORD)lpOutBuffer = hpt_get_controller_count(); 1130 break; 1131 1132 case HPT_IOCTL_GET_CONTROLLER_INFO: 1133 { 1134 int id; 1135 PCONTROLLER_INFO pInfo; 1136 1137 if (nInBufferSize!=sizeof(DWORD)) return -1; 1138 if (nOutBufferSize!=sizeof(CONTROLLER_INFO)) return -1; 1139 1140 id = *(DWORD *)lpInBuffer; 1141 pInfo = (PCONTROLLER_INFO)lpOutBuffer; 1142 if (hpt_get_controller_info(id, pInfo)!=0) 1143 return -1; 1144 } 1145 break; 1146 1147 case HPT_IOCTL_GET_CHANNEL_INFO: 1148 { 1149 int id, bus; 1150 PCHANNEL_INFO pInfo; 1151 1152 if (nInBufferSize!=8) return -1; 1153 if (nOutBufferSize!=sizeof(CHANNEL_INFO)) return -1; 1154 1155 id = *(DWORD *)lpInBuffer; 1156 bus = ((DWORD *)lpInBuffer)[1]; 1157 pInfo = (PCHANNEL_INFO)lpOutBuffer; 1158 1159 if (hpt_get_channel_info(id, bus, pInfo)!=0) 1160 return -1; 1161 } 1162 break; 1163 1164 case HPT_IOCTL_GET_LOGICAL_DEVICES: 1165 { 1166 DWORD nMax; 1167 DEVICEID *pIds; 1168 1169 if (nInBufferSize!=sizeof(DWORD)) return -1; 1170 nMax = *(DWORD *)lpInBuffer; 1171 if (nOutBufferSize < sizeof(DWORD)+sizeof(DWORD)*nMax) return -1; 1172 1173 pIds = ((DEVICEID *)lpOutBuffer)+1; 1174 *(DWORD*)lpOutBuffer = hpt_get_logical_devices(pIds, nMax); 1175 } 1176 break; 1177 1178 case HPT_IOCTL_GET_DEVICE_INFO: 1179 { 1180 DEVICEID id; 1181 PLOGICAL_DEVICE_INFO pInfo; 1182 1183 if (nInBufferSize!=sizeof(DEVICEID)) return -1; 1184 if (nOutBufferSize!=sizeof(LOGICAL_DEVICE_INFO)) return -1; 1185 1186 id = *(DWORD *)lpInBuffer; 1187 if (id == INVALID_DEVICEID) return -1; 1188 1189 pInfo = (PLOGICAL_DEVICE_INFO)lpOutBuffer; 1190 memset(pInfo, 0, sizeof(LOGICAL_DEVICE_INFO)); 1191 1192 if (hpt_get_device_info(id, pInfo)!=0) 1193 return -1; 1194 } 1195 break; 1196 1197 #ifdef SUPPORT_ARRAY 1198 case HPT_IOCTL_CREATE_ARRAY: 1199 { 1200 CREATE_ARRAY_PARAMS *pParam; 1201 DEVICEID id; 1202 1203 if (nInBufferSize!=sizeof(CREATE_ARRAY_PARAMS)) return -1; 1204 if (nOutBufferSize!=sizeof(DEVICEID)) return -1; 1205 1206 pParam = (PCREATE_ARRAY_PARAMS)lpInBuffer; 1207 1208 id = hpt_create_array(_VBUS_P pParam); 1209 *(DEVICEID *)lpOutBuffer = id; 1210 1211 if(id == (DEVICEID)INVALID_DEVICEID) 1212 return -1; 1213 } 1214 break; 1215 1216 case HPT_IOCTL_SET_ARRAY_INFO: 1217 { 1218 DEVICEID idArray; 1219 PALTERABLE_ARRAY_INFO pInfo; 1220 1221 if (nInBufferSize!=sizeof(HPT_SET_ARRAY_INFO)) return -1; 1222 if (nOutBufferSize!=0) return -1; 1223 1224 idArray = ((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray; 1225 pInfo = &((PHPT_SET_ARRAY_INFO)lpInBuffer)->Info; 1226 1227 if(hpt_set_array_info(_VBUS_P idArray, pInfo)) 1228 return -1; 1229 } 1230 break; 1231 1232 case HPT_IOCTL_SET_DEVICE_INFO: 1233 { 1234 DEVICEID idDisk; 1235 PALTERABLE_DEVICE_INFO pInfo; 1236 1237 if (nInBufferSize!=sizeof(HPT_SET_DEVICE_INFO)) return -1; 1238 if (nOutBufferSize!=0) return -1; 1239 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) 1243 return -1; 1244 } 1245 break; 1246 1247 case HPT_IOCTL_SET_BOOT_MARK: 1248 { 1249 DEVICEID id; 1250 PVDevice pTop; 1251 int i; 1252 IAL_ADAPTER_T *pAdapter = gIal_Adapter; 1253 PVBus pVBus; 1254 1255 if (nInBufferSize!=sizeof(DEVICEID)) return -1; 1256 id = *(DEVICEID *)lpInBuffer; 1257 while(pAdapter != 0) 1258 { 1259 pVBus = &pAdapter->VBus; 1260 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) 1261 { 1262 if(!(pTop = pVBus->pVDevice[i])) continue; 1263 #if MAX_VBUS>1 1264 if (pTop->pVBus!=_vbus_p) return -1; 1265 #endif 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; 1271 else 1272 continue; 1273 SyncArrayInfo(pTop); 1274 break; 1275 } 1276 pAdapter = pAdapter->next; 1277 } 1278 } 1279 break; 1280 #endif /* SUPPORT_ARRAY */ 1281 case HPT_IOCTL_RESCAN_DEVICES: 1282 { 1283 fRescanAllDevice(_VBUS_P0); 1284 if (nInBufferSize!=0) return -1; 1285 if (nOutBufferSize!=0) return -1; 1286 fRescanAllDevice(_VBUS_P0); 1287 } 1288 break; 1289 1290 #ifdef SUPPORT_ARRAY 1291 case HPT_IOCTL_ADD_SPARE_DISK: 1292 { 1293 DEVICEID id; 1294 1295 if (nInBufferSize!=sizeof(DEVICEID)) return -1; 1296 if (nOutBufferSize!=0) return -1; 1297 1298 id = *(DEVICEID *)lpInBuffer; 1299 1300 if(hpt_add_spare_disk(_VBUS_P id)) 1301 return -1; 1302 } 1303 break; 1304 1305 case HPT_IOCTL_REMOVE_SPARE_DISK: 1306 { 1307 DEVICEID id; 1308 1309 if (nInBufferSize!=sizeof(DEVICEID)) return -1; 1310 if (nOutBufferSize!=0) return -1; 1311 1312 id = *(DEVICEID *)lpInBuffer; 1313 1314 if(hpt_remove_spare_disk(_VBUS_P id)) 1315 return -1; 1316 } 1317 break; 1318 1319 case HPT_IOCTL_ADD_DISK_TO_ARRAY: 1320 { 1321 DEVICEID id1,id2; 1322 id1 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray; 1323 id2 = ((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idDisk; 1324 1325 if (nInBufferSize != sizeof(HPT_ADD_DISK_TO_ARRAY)) return -1; 1326 if (nOutBufferSize != 0) return -1; 1327 1328 if(hpt_add_disk_to_array(_VBUS_P id1, id2)) 1329 return -1; 1330 } 1331 break; 1332 #endif 1333 case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 1334 { 1335 PDRIVER_CAPABILITIES cap; 1336 if (nOutBufferSize<sizeof(DRIVER_CAPABILITIES)) return -1; 1337 cap = (PDRIVER_CAPABILITIES)lpOutBuffer; 1338 1339 if(hpt_get_driver_capabilities(cap)) 1340 return -1; 1341 } 1342 break; 1343 1344 #ifdef SUPPORT_HPT601 1345 case HPT_IOCTL_GET_601_INFO: 1346 { 1347 DEVICEID id; 1348 PHPT601_INFO pInfo; 1349 1350 if (nInBufferSize!=sizeof(DEVICEID)) return -1; 1351 if (nOutBufferSize!=sizeof(HPT601_INFO)) return -1; 1352 1353 id = *(DWORD *)lpInBuffer; 1354 if (id == INVALID_DEVICEID) return -1; 1355 1356 pInfo = (PHPT601_INFO)lpOutBuffer; 1357 memset(pInfo, 0, sizeof(HPT601_INFO)); 1358 1359 if (hpt_get_601_info(id, pInfo)!=0) 1360 return -1; 1361 } 1362 break; 1363 1364 case HPT_IOCTL_SET_601_INFO: 1365 { 1366 DEVICEID id; 1367 PHPT601_INFO pInfo; 1368 1369 if (nInBufferSize!=sizeof(HPT_SET_601_INFO)) return -1; 1370 if (nOutBufferSize!=0) return -1; 1371 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) 1375 return -1; 1376 } 1377 break; 1378 #endif 1379 default: 1380 return -1; 1381 } 1382 1383 if (lpBytesReturned) 1384 *lpBytesReturned = nOutBufferSize; 1385 return 0; 1386 } 1387