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