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 * ioctl.c ioctl interface implementation 30 */ 31 #include <sys/param.h> 32 #include <sys/systm.h> 33 #include <sys/kernel.h> 34 #include <sys/malloc.h> 35 36 #if (__FreeBSD_version < 500000) 37 #include <sys/proc.h> 38 #include <sys/kthread.h> 39 #include <sys/wait.h> 40 #include <sys/sysproto.h> 41 #endif 42 43 #ifndef __KERNEL__ 44 #define __KERNEL__ 45 #endif 46 47 #include <dev/hptmv/global.h> 48 #include <dev/hptmv/hptintf.h> 49 #include <dev/hptmv/osbsd.h> 50 #include <dev/hptmv/access601.h> 51 52 #pragma pack(1) 53 54 typedef struct _HPT_REBUILD_PARAM 55 { 56 DEVICEID idMirror; 57 DWORD Lba; 58 UCHAR nSector; 59 } HPT_REBUILD_PARAM, *PHPT_REBUILD_PARAM; 60 61 #pragma pack() 62 63 #define MAX_EVENTS 10 64 static HPT_EVENT hpt_event_queue[MAX_EVENTS]; 65 static int event_queue_head=0, event_queue_tail=0; 66 67 static int hpt_get_event(PHPT_EVENT pEvent); 68 static int hpt_set_array_state(DEVICEID idArray, DWORD state); 69 static intrmask_t lock_driver_idle(IAL_ADAPTER_T *pAdapter); 70 static void HPTLIBAPI thread_io_done(_VBUS_ARG PCommand pCmd); 71 static int HPTLIBAPI R1ControlSgl(_VBUS_ARG PCommand pCmd, 72 FPSCAT_GATH pSgTable, int logical); 73 74 static void 75 get_disk_location(PDevice pDev, int *controller, int *channel) 76 { 77 IAL_ADAPTER_T *pAdapTemp; 78 int i, j; 79 80 *controller = *channel = 0; 81 82 for (i=1, pAdapTemp = gIal_Adapter; pAdapTemp; pAdapTemp = pAdapTemp->next, i++) { 83 for (j=0; j<MV_SATA_CHANNELS_NUM; j++) { 84 if (pDev == &pAdapTemp->VDevices[j].u.disk) { 85 *controller = i; 86 *channel = j; 87 return; 88 } 89 } 90 } 91 } 92 93 static int 94 event_queue_add(PHPT_EVENT pEvent) 95 { 96 int p; 97 p = (event_queue_tail + 1) % MAX_EVENTS; 98 if (p==event_queue_head) 99 { 100 return -1; 101 } 102 hpt_event_queue[event_queue_tail] = *pEvent; 103 event_queue_tail = p; 104 return 0; 105 } 106 107 static int 108 event_queue_remove(PHPT_EVENT pEvent) 109 { 110 if (event_queue_head != event_queue_tail) 111 { 112 *pEvent = hpt_event_queue[event_queue_head]; 113 event_queue_head++; 114 event_queue_head %= MAX_EVENTS; 115 return 0; 116 } 117 return -1; 118 } 119 120 void HPTLIBAPI 121 ioctl_ReportEvent(UCHAR event, PVOID param) 122 { 123 HPT_EVENT e; 124 ZeroMemory(&e, sizeof(e)); 125 e.EventType = event; 126 switch(event) 127 { 128 case ET_INITIALIZE_ABORTED: 129 case ET_INITIALIZE_FAILED: 130 memcpy(e.Data, ((PVDevice)param)->u.array.ArrayName, MAX_ARRAY_NAME); 131 case ET_INITIALIZE_STARTED: 132 case ET_INITIALIZE_FINISHED: 133 134 case ET_REBUILD_STARTED: 135 case ET_REBUILD_ABORTED: 136 case ET_REBUILD_FAILED: 137 case ET_REBUILD_FINISHED: 138 139 case ET_VERIFY_STARTED: 140 case ET_VERIFY_ABORTED: 141 case ET_VERIFY_FAILED: 142 case ET_VERIFY_FINISHED: 143 case ET_VERIFY_DATA_ERROR: 144 145 case ET_SPARE_TOOK_OVER: 146 case ET_DEVICE_REMOVED: 147 case ET_DEVICE_PLUGGED: 148 case ET_DEVICE_ERROR: 149 e.DeviceID = VDEV_TO_ID((PVDevice)param); 150 break; 151 152 default: 153 break; 154 } 155 event_queue_add(&e); 156 if (event==ET_DEVICE_REMOVED) { 157 int controller, channel; 158 get_disk_location(&((PVDevice)param)->u.disk, &controller, &channel); 159 hpt_printk(("Device removed: controller %d channel %d\n", controller, channel)); 160 } 161 } 162 163 static int 164 hpt_delete_array(_VBUS_ARG DEVICEID id, DWORD options) 165 { 166 PVDevice pArray = ID_TO_VDEV(id); 167 BOOLEAN del_block0 = (options & DAF_KEEP_DATA_IF_POSSIBLE)?0:1; 168 int i; 169 PVDevice pa; 170 171 if ((id==0) || check_VDevice_valid(pArray)) 172 return -1; 173 174 if(!mIsArray(pArray)) return -1; 175 176 if (pArray->u.array.rf_rebuilding || pArray->u.array.rf_verifying || 177 pArray->u.array.rf_initializing) 178 return -1; 179 180 for(i=0; i<pArray->u.array.bArnMember; i++) { 181 pa = pArray->u.array.pMember[i]; 182 if (pa && mIsArray(pa)) { 183 if (pa->u.array.rf_rebuilding || pa->u.array.rf_verifying || 184 pa->u.array.rf_initializing) 185 return -1; 186 } 187 } 188 189 if (pArray->pVBus!=_vbus_p) { HPT_ASSERT(0); return -1;} 190 fDeleteArray(_VBUS_P pArray, del_block0); 191 return 0; 192 193 } 194 195 /* just to prevent driver from sending more commands */ 196 static void HPTLIBAPI nothing(_VBUS_ARG void *notused){} 197 198 intrmask_t 199 lock_driver_idle(IAL_ADAPTER_T *pAdapter) 200 { 201 intrmask_t oldspl; 202 _VBUS_INST(&pAdapter->VBus) 203 oldspl = lock_driver(); 204 while (pAdapter->outstandingCommands) { 205 KdPrint(("outstandingCommands is %d, wait..\n", pAdapter->outstandingCommands)); 206 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 207 unlock_driver(oldspl); 208 /*Schedule out*/ 209 #if (__FreeBSD_version < 500000) 210 YIELD_THREAD; 211 #else 212 #if (__FreeBSD_version > 700033) 213 pause("switch", 1); 214 #else 215 tsleep(lock_driver_idle, PPAUSE, "switch", 1); 216 #endif 217 #endif 218 oldspl = lock_driver(); 219 } 220 CheckIdleCall(_VBUS_P0); 221 return oldspl; 222 } 223 224 int Kernel_DeviceIoControl(_VBUS_ARG 225 DWORD dwIoControlCode, /* operation control code */ 226 PVOID lpInBuffer, /* input data buffer */ 227 DWORD nInBufferSize, /* size of input data buffer */ 228 PVOID lpOutBuffer, /* output data buffer */ 229 DWORD nOutBufferSize, /* size of output data buffer */ 230 PDWORD lpBytesReturned /* byte count */ 231 ) 232 { 233 IAL_ADAPTER_T *pAdapter; 234 235 switch(dwIoControlCode) { 236 case HPT_IOCTL_DELETE_ARRAY: 237 { 238 DEVICEID idArray; 239 int iSuccess; 240 int i; 241 PVDevice pArray; 242 PVBus _vbus_p; 243 struct cam_periph *periph = NULL; 244 245 if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 246 if (nOutBufferSize!=sizeof(int)) return -1; 247 idArray = *(DEVICEID *)lpInBuffer; 248 249 pArray = ID_TO_VDEV(idArray); 250 251 if((idArray == 0) || check_VDevice_valid(pArray)) 252 return -1; 253 254 if(!mIsArray(pArray)) 255 return -1; 256 257 _vbus_p=pArray->pVBus; 258 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 259 260 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 261 if(pArray == _vbus_p->pVDevice[i]) 262 { 263 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 264 if (periph != NULL && periph->refcount >= 1) 265 { 266 hpt_printk(("Can not delete a mounted device.\n")); 267 return -1; 268 } 269 } 270 /* the Mounted Disk isn't delete */ 271 } 272 273 iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 274 275 *(int*)lpOutBuffer = iSuccess; 276 277 if(iSuccess != 0) 278 return -1; 279 break; 280 } 281 282 case HPT_IOCTL_GET_EVENT: 283 { 284 PHPT_EVENT pInfo; 285 286 if (nInBufferSize!=0) return -1; 287 if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 288 289 pInfo = (PHPT_EVENT)lpOutBuffer; 290 291 if (hpt_get_event(pInfo)!=0) 292 return -1; 293 } 294 break; 295 296 case HPT_IOCTL_SET_ARRAY_STATE: 297 { 298 DEVICEID idArray; 299 DWORD state; 300 301 if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 302 if (nOutBufferSize!=0) return -1; 303 304 idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 305 state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 306 307 if(hpt_set_array_state(idArray, state)!=0) 308 return -1; 309 } 310 break; 311 312 case HPT_IOCTL_RESCAN_DEVICES: 313 { 314 if (nInBufferSize!=0) return -1; 315 if (nOutBufferSize!=0) return -1; 316 317 #ifndef FOR_DEMO 318 /* stop buzzer if user perform rescan */ 319 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 320 if (pAdapter->beeping) { 321 pAdapter->beeping = 0; 322 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 323 } 324 } 325 #endif 326 } 327 break; 328 329 default: 330 { 331 PVDevice pVDev; 332 #ifdef SUPPORT_ARRAY 333 intrmask_t oldspl; 334 #endif 335 switch(dwIoControlCode) { 336 /* read-only ioctl functions can be called directly. */ 337 case HPT_IOCTL_GET_VERSION: 338 case HPT_IOCTL_GET_CONTROLLER_IDS: 339 case HPT_IOCTL_GET_CONTROLLER_COUNT: 340 case HPT_IOCTL_GET_CONTROLLER_INFO: 341 case HPT_IOCTL_GET_CHANNEL_INFO: 342 case HPT_IOCTL_GET_LOGICAL_DEVICES: 343 case HPT_IOCTL_GET_DEVICE_INFO: 344 case HPT_IOCTL_GET_DEVICE_INFO_V2: 345 case HPT_IOCTL_GET_EVENT: 346 case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 347 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 348 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 349 break; 350 351 default: 352 /* 353 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 354 * wrong for second controller. 355 */ 356 switch(dwIoControlCode) { 357 case HPT_IOCTL_CREATE_ARRAY: 358 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 359 case HPT_IOCTL_CREATE_ARRAY_V2: 360 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->Members[0]); break; 361 case HPT_IOCTL_SET_ARRAY_INFO: 362 pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 363 case HPT_IOCTL_SET_DEVICE_INFO: 364 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 365 case HPT_IOCTL_SET_DEVICE_INFO_V2: 366 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO_V2)lpInBuffer)->idDisk); break; 367 case HPT_IOCTL_SET_BOOT_MARK: 368 case HPT_IOCTL_ADD_SPARE_DISK: 369 case HPT_IOCTL_REMOVE_SPARE_DISK: 370 pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 371 case HPT_IOCTL_ADD_DISK_TO_ARRAY: 372 pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 373 default: 374 pVDev = 0; 375 } 376 377 if (pVDev && !check_VDevice_valid(pVDev)){ 378 _vbus_p = pVDev->pVBus; 379 380 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 381 /* 382 * create_array, and other functions can't be executed while channel is 383 * perform I/O commands. Wait until driver is idle. 384 */ 385 oldspl = lock_driver_idle(pAdapter); 386 if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 387 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 388 unlock_driver(oldspl); 389 return -1; 390 } 391 unlock_driver(oldspl); 392 } 393 else 394 return -1; 395 break; 396 } 397 398 #ifdef SUPPORT_ARRAY 399 switch(dwIoControlCode) 400 { 401 case HPT_IOCTL_CREATE_ARRAY: 402 { 403 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 404 oldspl = lock_driver(); 405 if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 406 { 407 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 408 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 409 } 410 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 411 { 412 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 413 } 414 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 415 { 416 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 417 } 418 unlock_driver(oldspl); 419 break; 420 } 421 422 423 case HPT_IOCTL_CREATE_ARRAY_V2: 424 { 425 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 426 oldspl = lock_driver(); 427 if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) { 428 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 429 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 430 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) { 431 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 432 } else if(((PCREATE_ARRAY_PARAMS_V2)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) { 433 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 434 } 435 unlock_driver(oldspl); 436 break; 437 } 438 case HPT_IOCTL_ADD_DISK_TO_ARRAY: 439 { 440 PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 441 pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 442 if(pArray->u.array.rf_rebuilding == 0) 443 { 444 DWORD timeout = 0; 445 oldspl = lock_driver(); 446 pArray->u.array.rf_auto_rebuild = 0; 447 pArray->u.array.rf_abort_rebuild = 0; 448 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 449 unlock_driver(oldspl); 450 while (!pArray->u.array.rf_rebuilding) 451 { 452 #if (__FreeBSD_version > 700033) 453 pause("pause", 1); 454 #else 455 tsleep((caddr_t)Kernel_DeviceIoControl, PPAUSE, "pause", 1); 456 #endif 457 if ( timeout >= hz*3) 458 break; 459 timeout ++; 460 } 461 } 462 break; 463 } 464 } 465 #endif 466 return 0; 467 } 468 } 469 470 if (lpBytesReturned) 471 *lpBytesReturned = nOutBufferSize; 472 return 0; 473 } 474 475 static int 476 hpt_get_event(PHPT_EVENT pEvent) 477 { 478 intrmask_t oldspl = lock_driver(); 479 int ret = event_queue_remove(pEvent); 480 unlock_driver(oldspl); 481 return ret; 482 } 483 484 static int 485 hpt_set_array_state(DEVICEID idArray, DWORD state) 486 { 487 IAL_ADAPTER_T *pAdapter; 488 PVDevice pVDevice = ID_TO_VDEV(idArray); 489 int i; 490 DWORD timeout = 0; 491 intrmask_t oldspl; 492 493 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 494 if(!mIsArray(pVDevice)) 495 return -1; 496 if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; 497 498 pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; 499 500 switch(state) 501 { 502 case MIRROR_REBUILD_START: 503 { 504 if (pVDevice->u.array.rf_rebuilding || 505 pVDevice->u.array.rf_verifying || 506 pVDevice->u.array.rf_initializing) 507 return -1; 508 509 oldspl = lock_driver(); 510 511 pVDevice->u.array.rf_auto_rebuild = 0; 512 pVDevice->u.array.rf_abort_rebuild = 0; 513 514 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 515 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 516 517 unlock_driver(oldspl); 518 519 while (!pVDevice->u.array.rf_rebuilding) 520 { 521 #if (__FreeBSD_version > 700033) 522 pause("pause", 1); 523 #else 524 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 525 #endif 526 if ( timeout >= hz*20) 527 break; 528 timeout ++; 529 } 530 } 531 532 break; 533 534 case MIRROR_REBUILD_ABORT: 535 { 536 for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 537 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 538 hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 539 } 540 541 if(pVDevice->u.array.rf_rebuilding != 1) 542 return -1; 543 544 oldspl = lock_driver(); 545 pVDevice->u.array.rf_abort_rebuild = 1; 546 unlock_driver(oldspl); 547 548 while (pVDevice->u.array.rf_abort_rebuild) 549 { 550 #if (__FreeBSD_version > 700033) 551 pause("pause", 1); 552 #else 553 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 554 #endif 555 if ( timeout >= hz*20) 556 break; 557 timeout ++; 558 } 559 } 560 break; 561 562 case AS_VERIFY_START: 563 { 564 /*if(pVDevice->u.array.rf_verifying) 565 return -1;*/ 566 if (pVDevice->u.array.rf_rebuilding || 567 pVDevice->u.array.rf_verifying || 568 pVDevice->u.array.rf_initializing) 569 return -1; 570 571 oldspl = lock_driver(); 572 pVDevice->u.array.RebuildSectors = 0; 573 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 574 unlock_driver(oldspl); 575 576 while (!pVDevice->u.array.rf_verifying) 577 { 578 #if (__FreeBSD_version > 700033) 579 pause("pause", 1); 580 #else 581 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 582 #endif 583 if ( timeout >= hz*20) 584 break; 585 timeout ++; 586 } 587 } 588 break; 589 590 case AS_VERIFY_ABORT: 591 { 592 if(pVDevice->u.array.rf_verifying != 1) 593 return -1; 594 595 oldspl = lock_driver(); 596 pVDevice->u.array.rf_abort_rebuild = 1; 597 unlock_driver(oldspl); 598 599 while (pVDevice->u.array.rf_abort_rebuild) 600 { 601 #if (__FreeBSD_version > 700033) 602 pause("pause", 1); 603 #else 604 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 605 #endif 606 if ( timeout >= hz*80) 607 break; 608 timeout ++; 609 } 610 } 611 break; 612 613 case AS_INITIALIZE_START: 614 { 615 if (pVDevice->u.array.rf_rebuilding || 616 pVDevice->u.array.rf_verifying || 617 pVDevice->u.array.rf_initializing) 618 return -1; 619 620 oldspl = lock_driver(); 621 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 622 unlock_driver(oldspl); 623 624 while (!pVDevice->u.array.rf_initializing) 625 { 626 #if (__FreeBSD_version > 700033) 627 pause("pause", 1); 628 #else 629 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 630 #endif 631 if ( timeout >= hz*80) 632 break; 633 timeout ++; 634 } 635 } 636 break; 637 638 case AS_INITIALIZE_ABORT: 639 { 640 if(pVDevice->u.array.rf_initializing != 1) 641 return -1; 642 643 oldspl = lock_driver(); 644 pVDevice->u.array.rf_abort_rebuild = 1; 645 unlock_driver(oldspl); 646 647 while (pVDevice->u.array.rf_abort_rebuild) 648 { 649 #if (__FreeBSD_version > 700033) 650 pause("pause", 1); 651 #else 652 tsleep((caddr_t)hpt_set_array_state, PPAUSE, "pause", 1); 653 #endif 654 if ( timeout >= hz*80) 655 break; 656 timeout ++; 657 } 658 } 659 break; 660 661 default: 662 return -1; 663 } 664 665 return 0; 666 } 667 668 int HPTLIBAPI 669 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 670 { 671 ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 672 if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 673 bufferSize<<=1; 674 if (logical) { 675 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 676 pSgTable->wSgSize = (USHORT)bufferSize; 677 pSgTable->wSgFlag = SG_FLAG_EOT; 678 } 679 else { 680 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 681 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 682 ULONG length; 683 int idx = 0; 684 685 v = pCmd->uCmd.R1Control.Buffer; 686 dataPointer = (ADDRESS)fOsPhysicalAddress(v); 687 688 if ((ULONG_PTR)dataPointer & 0x1) 689 return FALSE; 690 691 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 692 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 693 694 do { 695 if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 696 697 pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 698 currvaddr = v; 699 currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 700 701 702 do { 703 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 704 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 705 706 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 707 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 708 709 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 710 nextvaddr = nextpage; 711 break; 712 } 713 714 currvaddr = nextvaddr; 715 currphypage = nextphypage; 716 }while (1); 717 718 length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 719 v = nextvaddr; 720 bufferSize -= length; 721 722 pSgTable[idx].wSgSize = (USHORT)length; 723 pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 724 idx++; 725 726 }while (bufferSize); 727 } 728 return 1; 729 } 730 731 static int End_Job=0; 732 void HPTLIBAPI 733 thread_io_done(_VBUS_ARG PCommand pCmd) 734 { 735 End_Job = 1; 736 wakeup((caddr_t)pCmd); 737 } 738 739 void 740 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 741 { 742 DWORD timeout = 0; 743 ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 744 PCommand pCmd; 745 UINT result; 746 int needsync=0, retry=0, needdelete=0; 747 void *buffer = 0; 748 intrmask_t oldspl; 749 750 _VBUS_INST(&pAdapter->VBus) 751 752 if (pArray->u.array.rf_broken==1 || 753 pArray->u.array.RebuildSectors>=capacity) 754 return; 755 756 oldspl = lock_driver(); 757 758 switch(flags) 759 { 760 case DUPLICATE: 761 case REBUILD_PARITY: 762 if(pArray->u.array.rf_rebuilding == 0) 763 { 764 pArray->u.array.rf_rebuilding = 1; 765 hpt_printk(("Rebuilding started.\n")); 766 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 767 } 768 break; 769 770 case INITIALIZE: 771 if(pArray->u.array.rf_initializing == 0) 772 { 773 pArray->u.array.rf_initializing = 1; 774 hpt_printk(("Initializing started.\n")); 775 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 776 } 777 break; 778 779 case VERIFY: 780 if(pArray->u.array.rf_verifying == 0) 781 { 782 pArray->u.array.rf_verifying = 1; 783 hpt_printk(("Verifying started.\n")); 784 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 785 } 786 break; 787 } 788 789 retry_cmd: 790 pCmd = AllocateCommand(_VBUS_P0); 791 HPT_ASSERT(pCmd); 792 pCmd->cf_control = 1; 793 End_Job = 0; 794 795 if (pArray->VDeviceType==VD_RAID_1) 796 { 797 #define MAX_REBUILD_SECTORS 0x40 798 799 /* take care for discontinuous buffer in R1ControlSgl */ 800 unlock_driver(oldspl); 801 buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 802 oldspl = lock_driver(); 803 if(!buffer) { 804 FreeCommand(_VBUS_P pCmd); 805 hpt_printk(("can't allocate rebuild buffer\n")); 806 goto fail; 807 } 808 switch(flags) 809 { 810 case DUPLICATE: 811 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 812 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 813 break; 814 815 case VERIFY: 816 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; 817 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; 818 break; 819 820 case INITIALIZE: 821 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 822 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 823 break; 824 } 825 826 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; 827 828 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) 829 pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; 830 831 pCmd->uCmd.R1Control.Buffer = buffer; 832 pCmd->pfnBuildSgl = R1ControlSgl; 833 } 834 else if (pArray->VDeviceType==VD_RAID_5) 835 { 836 switch(flags) 837 { 838 case DUPLICATE: 839 case REBUILD_PARITY: 840 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; 841 case VERIFY: 842 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; 843 case INITIALIZE: 844 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; 845 } 846 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; 847 } 848 else 849 HPT_ASSERT(0); 850 851 pCmd->pVDevice = pArray; 852 pCmd->pfnCompletion = thread_io_done; 853 pArray->pfnSendCommand(_VBUS_P pCmd); 854 CheckPendingCall(_VBUS_P0); 855 856 if (!End_Job) { 857 unlock_driver(oldspl); 858 while (!End_Job) { 859 tsleep((caddr_t)pCmd, PPAUSE, "pause", hz); 860 if (timeout++>60) break; 861 } 862 oldspl = lock_driver(); 863 if (!End_Job) { 864 hpt_printk(("timeout, reset\n")); 865 fResetVBus(_VBUS_P0); 866 } 867 } 868 869 result = pCmd->Result; 870 FreeCommand(_VBUS_P pCmd); 871 unlock_driver(oldspl); 872 if (buffer) free(buffer, M_DEVBUF); 873 oldspl = lock_driver(); 874 KdPrintI(("cmd finished %d", result)); 875 876 switch(result) 877 { 878 case RETURN_SUCCESS: 879 if (!pArray->u.array.rf_abort_rebuild) 880 { 881 if(pArray->u.array.RebuildSectors < capacity) 882 { 883 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 884 } 885 else 886 { 887 switch (flags) 888 { 889 case DUPLICATE: 890 case REBUILD_PARITY: 891 needsync = 1; 892 pArray->u.array.rf_rebuilding = 0; 893 pArray->u.array.rf_need_rebuild = 0; 894 pArray->u.array.CriticalMembers = 0; 895 pArray->u.array.RebuildSectors = MAX_LBA_T; 896 pArray->u.array.rf_duplicate_and_create = 0; 897 hpt_printk(("Rebuilding finished.\n")); 898 ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 899 break; 900 case INITIALIZE: 901 needsync = 1; 902 pArray->u.array.rf_initializing = 0; 903 pArray->u.array.rf_need_rebuild = 0; 904 pArray->u.array.RebuildSectors = MAX_LBA_T; 905 hpt_printk(("Initializing finished.\n")); 906 ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 907 break; 908 case VERIFY: 909 pArray->u.array.rf_verifying = 0; 910 hpt_printk(("Verifying finished.\n")); 911 ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 912 break; 913 } 914 } 915 } 916 else 917 { 918 pArray->u.array.rf_abort_rebuild = 0; 919 if (pArray->u.array.rf_rebuilding) 920 { 921 hpt_printk(("Abort rebuilding.\n")); 922 pArray->u.array.rf_rebuilding = 0; 923 pArray->u.array.rf_duplicate_and_create = 0; 924 ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 925 } 926 else if (pArray->u.array.rf_verifying) 927 { 928 hpt_printk(("Abort verifying.\n")); 929 pArray->u.array.rf_verifying = 0; 930 ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 931 } 932 else if (pArray->u.array.rf_initializing) 933 { 934 hpt_printk(("Abort initializing.\n")); 935 pArray->u.array.rf_initializing = 0; 936 ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 937 } 938 needdelete=1; 939 } 940 break; 941 942 case RETURN_DATA_ERROR: 943 if (flags==VERIFY) 944 { 945 needsync = 1; 946 pArray->u.array.rf_verifying = 0; 947 pArray->u.array.rf_need_rebuild = 1; 948 hpt_printk(("Verifying failed: found inconsistency\n")); 949 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 950 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 951 952 if (!pArray->vf_online || pArray->u.array.rf_broken) break; 953 954 pArray->u.array.rf_auto_rebuild = 0; 955 pArray->u.array.rf_abort_rebuild = 0; 956 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 957 (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 958 } 959 break; 960 961 default: 962 hpt_printk(("command failed with error %d\n", result)); 963 if (++retry<3) 964 { 965 hpt_printk(("retry (%d)\n", retry)); 966 goto retry_cmd; 967 } 968 fail: 969 pArray->u.array.rf_abort_rebuild = 0; 970 switch (flags) 971 { 972 case DUPLICATE: 973 case REBUILD_PARITY: 974 needsync = 1; 975 pArray->u.array.rf_rebuilding = 0; 976 pArray->u.array.rf_duplicate_and_create = 0; 977 hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 978 ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 979 break; 980 981 case INITIALIZE: 982 needsync = 1; 983 pArray->u.array.rf_initializing = 0; 984 hpt_printk(("Initializing failed.\n")); 985 ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 986 break; 987 988 case VERIFY: 989 needsync = 1; 990 pArray->u.array.rf_verifying = 0; 991 hpt_printk(("Verifying failed.\n")); 992 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 993 break; 994 } 995 needdelete=1; 996 } 997 998 while (pAdapter->outstandingCommands) 999 { 1000 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 1001 /* put this to have driver stop processing system commands quickly */ 1002 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 1003 unlock_driver(oldspl); 1004 /*Schedule out*/ 1005 #if (__FreeBSD_version < 500000) 1006 YIELD_THREAD; 1007 #else 1008 #if (__FreeBSD_version > 700033) 1009 pause("switch", 1); 1010 #else 1011 tsleep(hpt_rebuild_data_block, PPAUSE, "switch", 1); 1012 #endif 1013 #endif 1014 oldspl = lock_driver(); 1015 } 1016 1017 if (needsync) SyncArrayInfo(pArray); 1018 if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 1019 fDeleteArray(_VBUS_P pArray, TRUE); 1020 1021 Check_Idle_Call(pAdapter); 1022 unlock_driver(oldspl); 1023 } 1024