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