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