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 pause("switch", 1); 213 #endif 214 oldspl = lock_driver(); 215 } 216 CheckIdleCall(_VBUS_P0); 217 return oldspl; 218 } 219 220 int Kernel_DeviceIoControl(_VBUS_ARG 221 DWORD dwIoControlCode, /* operation control code */ 222 PVOID lpInBuffer, /* input data buffer */ 223 DWORD nInBufferSize, /* size of input data buffer */ 224 PVOID lpOutBuffer, /* output data buffer */ 225 DWORD nOutBufferSize, /* size of output data buffer */ 226 PDWORD lpBytesReturned /* byte count */ 227 ) 228 { 229 IAL_ADAPTER_T *pAdapter; 230 231 switch(dwIoControlCode) { 232 case HPT_IOCTL_DELETE_ARRAY: 233 { 234 DEVICEID idArray; 235 int iSuccess; 236 int i; 237 PVDevice pArray; 238 PVBus _vbus_p; 239 struct cam_periph *periph = NULL; 240 241 if (nInBufferSize!=sizeof(DEVICEID)+sizeof(DWORD)) return -1; 242 if (nOutBufferSize!=sizeof(int)) return -1; 243 idArray = *(DEVICEID *)lpInBuffer; 244 245 pArray = ID_TO_VDEV(idArray); 246 247 if((idArray == 0) || check_VDevice_valid(pArray)) 248 return -1; 249 250 if(!mIsArray(pArray)) 251 return -1; 252 253 _vbus_p=pArray->pVBus; 254 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 255 256 for(i = 0; i < MAX_VDEVICE_PER_VBUS; i++) { 257 if(pArray == _vbus_p->pVDevice[i]) 258 { 259 periph = hpt_get_periph(pAdapter->mvSataAdapter.adapterId, i); 260 if (periph != NULL && periph->refcount >= 1) 261 { 262 hpt_printk(("Can not delete a mounted device.\n")); 263 return -1; 264 } 265 } 266 /* the Mounted Disk isn't delete */ 267 } 268 269 iSuccess = hpt_delete_array(_VBUS_P idArray, *(DWORD*)((DEVICEID *)lpInBuffer+1)); 270 271 *(int*)lpOutBuffer = iSuccess; 272 273 if(iSuccess != 0) 274 return -1; 275 break; 276 } 277 278 case HPT_IOCTL_GET_EVENT: 279 { 280 PHPT_EVENT pInfo; 281 282 if (nInBufferSize!=0) return -1; 283 if (nOutBufferSize!=sizeof(HPT_EVENT)) return -1; 284 285 pInfo = (PHPT_EVENT)lpOutBuffer; 286 287 if (hpt_get_event(pInfo)!=0) 288 return -1; 289 } 290 break; 291 292 case HPT_IOCTL_SET_ARRAY_STATE: 293 { 294 DEVICEID idArray; 295 DWORD state; 296 297 if (nInBufferSize!=sizeof(HPT_SET_STATE_PARAM)) return -1; 298 if (nOutBufferSize!=0) return -1; 299 300 idArray = ((PHPT_SET_STATE_PARAM)lpInBuffer)->idArray; 301 state = ((PHPT_SET_STATE_PARAM)lpInBuffer)->state; 302 303 if(hpt_set_array_state(idArray, state)!=0) 304 return -1; 305 } 306 break; 307 308 case HPT_IOCTL_RESCAN_DEVICES: 309 { 310 if (nInBufferSize!=0) return -1; 311 if (nOutBufferSize!=0) return -1; 312 313 #ifndef FOR_DEMO 314 /* stop buzzer if user perform rescan */ 315 for (pAdapter=gIal_Adapter; pAdapter; pAdapter=pAdapter->next) { 316 if (pAdapter->beeping) { 317 pAdapter->beeping = 0; 318 BeepOff(pAdapter->mvSataAdapter.adapterIoBaseAddress); 319 } 320 } 321 #endif 322 } 323 break; 324 325 default: 326 { 327 PVDevice pVDev; 328 #ifdef SUPPORT_ARRAY 329 intrmask_t oldspl; 330 #endif 331 switch(dwIoControlCode) { 332 /* read-only ioctl functions can be called directly. */ 333 case HPT_IOCTL_GET_VERSION: 334 case HPT_IOCTL_GET_CONTROLLER_IDS: 335 case HPT_IOCTL_GET_CONTROLLER_COUNT: 336 case HPT_IOCTL_GET_CONTROLLER_INFO: 337 case HPT_IOCTL_GET_CHANNEL_INFO: 338 case HPT_IOCTL_GET_LOGICAL_DEVICES: 339 case HPT_IOCTL_GET_DEVICE_INFO: 340 case HPT_IOCTL_GET_EVENT: 341 case HPT_IOCTL_GET_DRIVER_CAPABILITIES: 342 if(hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 343 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) return -1; 344 break; 345 346 default: 347 /* 348 * GUI always use /proc/scsi/hptmv/0, so the _vbus_p param will be 349 * wrong for second controller. 350 */ 351 switch(dwIoControlCode) { 352 case HPT_IOCTL_CREATE_ARRAY: 353 pVDev = ID_TO_VDEV(((PCREATE_ARRAY_PARAMS)lpInBuffer)->Members[0]); break; 354 case HPT_IOCTL_SET_ARRAY_INFO: 355 pVDev = ID_TO_VDEV(((PHPT_SET_ARRAY_INFO)lpInBuffer)->idArray); break; 356 case HPT_IOCTL_SET_DEVICE_INFO: 357 pVDev = ID_TO_VDEV(((PHPT_SET_DEVICE_INFO)lpInBuffer)->idDisk); break; 358 case HPT_IOCTL_SET_BOOT_MARK: 359 case HPT_IOCTL_ADD_SPARE_DISK: 360 case HPT_IOCTL_REMOVE_SPARE_DISK: 361 pVDev = ID_TO_VDEV(*(DEVICEID *)lpInBuffer); break; 362 case HPT_IOCTL_ADD_DISK_TO_ARRAY: 363 pVDev = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); break; 364 default: 365 pVDev = 0; 366 } 367 368 if (pVDev && !check_VDevice_valid(pVDev)){ 369 _vbus_p = pVDev->pVBus; 370 371 pAdapter = (IAL_ADAPTER_T *)_vbus_p->OsExt; 372 /* 373 * create_array, and other functions can't be executed while channel is 374 * perform I/O commands. Wait until driver is idle. 375 */ 376 oldspl = lock_driver_idle(pAdapter); 377 if (hpt_default_ioctl(_VBUS_P dwIoControlCode, lpInBuffer, nInBufferSize, 378 lpOutBuffer, nOutBufferSize, lpBytesReturned) == -1) { 379 unlock_driver(oldspl); 380 return -1; 381 } 382 unlock_driver(oldspl); 383 } 384 else 385 return -1; 386 break; 387 } 388 389 #ifdef SUPPORT_ARRAY 390 switch(dwIoControlCode) 391 { 392 case HPT_IOCTL_CREATE_ARRAY: 393 { 394 pAdapter=(IAL_ADAPTER_T *)(ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->pVBus->OsExt; 395 oldspl = lock_driver(); 396 if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_AND_DUPLICATE) 397 { 398 (ID_TO_VDEV(*(DEVICEID *)lpOutBuffer))->u.array.rf_auto_rebuild = 0; 399 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), DUPLICATE); 400 } 401 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_ZERO_INIT) 402 { 403 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), INITIALIZE); 404 } 405 else if(((PCREATE_ARRAY_PARAMS)lpInBuffer)->CreateFlags & CAF_CREATE_R5_BUILD_PARITY) 406 { 407 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, ID_TO_VDEV(*(DEVICEID *)lpOutBuffer), REBUILD_PARITY); 408 } 409 unlock_driver(oldspl); 410 break; 411 } 412 413 case HPT_IOCTL_ADD_DISK_TO_ARRAY: 414 { 415 PVDevice pArray = ID_TO_VDEV(((PHPT_ADD_DISK_TO_ARRAY)lpInBuffer)->idArray); 416 pAdapter=(IAL_ADAPTER_T *)pArray->pVBus->OsExt; 417 if(pArray->u.array.rf_rebuilding == 0) 418 { 419 DWORD timeout = 0; 420 oldspl = lock_driver(); 421 pArray->u.array.rf_auto_rebuild = 0; 422 pArray->u.array.rf_abort_rebuild = 0; 423 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, DUPLICATE); 424 unlock_driver(oldspl); 425 while (!pArray->u.array.rf_rebuilding) 426 { 427 pause("pause", 1); 428 if ( timeout >= hz*3) 429 break; 430 timeout ++; 431 } 432 } 433 break; 434 } 435 } 436 #endif 437 return 0; 438 } 439 } 440 441 if (lpBytesReturned) 442 *lpBytesReturned = nOutBufferSize; 443 return 0; 444 } 445 446 static int 447 hpt_get_event(PHPT_EVENT pEvent) 448 { 449 intrmask_t oldspl = lock_driver(); 450 int ret = event_queue_remove(pEvent); 451 unlock_driver(oldspl); 452 return ret; 453 } 454 455 static int 456 hpt_set_array_state(DEVICEID idArray, DWORD state) 457 { 458 IAL_ADAPTER_T *pAdapter; 459 PVDevice pVDevice = ID_TO_VDEV(idArray); 460 int i; 461 DWORD timeout = 0; 462 intrmask_t oldspl; 463 464 if(idArray == 0 || check_VDevice_valid(pVDevice)) return -1; 465 if(!mIsArray(pVDevice)) 466 return -1; 467 if(!pVDevice->vf_online || pVDevice->u.array.rf_broken) return -1; 468 469 pAdapter=(IAL_ADAPTER_T *)pVDevice->pVBus->OsExt; 470 471 switch(state) 472 { 473 case MIRROR_REBUILD_START: 474 { 475 if (pVDevice->u.array.rf_rebuilding || 476 pVDevice->u.array.rf_verifying || 477 pVDevice->u.array.rf_initializing) 478 return -1; 479 480 oldspl = lock_driver(); 481 482 pVDevice->u.array.rf_auto_rebuild = 0; 483 pVDevice->u.array.rf_abort_rebuild = 0; 484 485 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, 486 (UCHAR)((pVDevice->u.array.CriticalMembers || pVDevice->VDeviceType == VD_RAID_1)? DUPLICATE : REBUILD_PARITY)); 487 488 unlock_driver(oldspl); 489 490 while (!pVDevice->u.array.rf_rebuilding) 491 { 492 pause("pause", 1); 493 if ( timeout >= hz*20) 494 break; 495 timeout ++; 496 } 497 } 498 499 break; 500 501 case MIRROR_REBUILD_ABORT: 502 { 503 for(i = 0; i < pVDevice->u.array.bArnMember; i++) { 504 if(pVDevice->u.array.pMember[i] != 0 && pVDevice->u.array.pMember[i]->VDeviceType == VD_RAID_1) 505 hpt_set_array_state(VDEV_TO_ID(pVDevice->u.array.pMember[i]), state); 506 } 507 508 if(pVDevice->u.array.rf_rebuilding != 1) 509 return -1; 510 511 oldspl = lock_driver(); 512 pVDevice->u.array.rf_abort_rebuild = 1; 513 unlock_driver(oldspl); 514 515 while (pVDevice->u.array.rf_abort_rebuild) 516 { 517 pause("pause", 1); 518 if ( timeout >= hz*20) 519 break; 520 timeout ++; 521 } 522 } 523 break; 524 525 case AS_VERIFY_START: 526 { 527 /*if(pVDevice->u.array.rf_verifying) 528 return -1;*/ 529 if (pVDevice->u.array.rf_rebuilding || 530 pVDevice->u.array.rf_verifying || 531 pVDevice->u.array.rf_initializing) 532 return -1; 533 534 oldspl = lock_driver(); 535 pVDevice->u.array.RebuildSectors = 0; 536 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 537 unlock_driver(oldspl); 538 539 while (!pVDevice->u.array.rf_verifying) 540 { 541 pause("pause", 1); 542 if ( timeout >= hz*20) 543 break; 544 timeout ++; 545 } 546 } 547 break; 548 549 case AS_VERIFY_ABORT: 550 { 551 if(pVDevice->u.array.rf_verifying != 1) 552 return -1; 553 554 oldspl = lock_driver(); 555 pVDevice->u.array.rf_abort_rebuild = 1; 556 unlock_driver(oldspl); 557 558 while (pVDevice->u.array.rf_abort_rebuild) 559 { 560 pause("pause", 1); 561 if ( timeout >= hz*80) 562 break; 563 timeout ++; 564 } 565 } 566 break; 567 568 case AS_INITIALIZE_START: 569 { 570 if (pVDevice->u.array.rf_rebuilding || 571 pVDevice->u.array.rf_verifying || 572 pVDevice->u.array.rf_initializing) 573 return -1; 574 575 oldspl = lock_driver(); 576 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pVDevice, VERIFY); 577 unlock_driver(oldspl); 578 579 while (!pVDevice->u.array.rf_initializing) 580 { 581 pause("pause", 1); 582 if ( timeout >= hz*80) 583 break; 584 timeout ++; 585 } 586 } 587 break; 588 589 case AS_INITIALIZE_ABORT: 590 { 591 if(pVDevice->u.array.rf_initializing != 1) 592 return -1; 593 594 oldspl = lock_driver(); 595 pVDevice->u.array.rf_abort_rebuild = 1; 596 unlock_driver(oldspl); 597 598 while (pVDevice->u.array.rf_abort_rebuild) 599 { 600 pause("pause", 1); 601 if ( timeout >= hz*80) 602 break; 603 timeout ++; 604 } 605 } 606 break; 607 608 default: 609 return -1; 610 } 611 612 return 0; 613 } 614 615 int HPTLIBAPI 616 R1ControlSgl(_VBUS_ARG PCommand pCmd, FPSCAT_GATH pSgTable, int logical) 617 { 618 ULONG bufferSize = SECTOR_TO_BYTE(pCmd->uCmd.R1Control.nSectors); 619 if (pCmd->uCmd.R1Control.Command==CTRL_CMD_VERIFY) 620 bufferSize<<=1; 621 if (logical) { 622 pSgTable->dSgAddress = (ULONG_PTR)pCmd->uCmd.R1Control.Buffer; 623 pSgTable->wSgSize = (USHORT)bufferSize; 624 pSgTable->wSgFlag = SG_FLAG_EOT; 625 } 626 else { 627 /* build physical SG table for pCmd->uCmd.R1Control.Buffer */ 628 ADDRESS dataPointer, v, nextpage, currvaddr, nextvaddr, currphypage, nextphypage; 629 ULONG length; 630 int idx = 0; 631 632 v = pCmd->uCmd.R1Control.Buffer; 633 dataPointer = (ADDRESS)fOsPhysicalAddress(v); 634 635 if ((ULONG_PTR)dataPointer & 0x1) 636 return FALSE; 637 638 #define ON64KBOUNDARY(x) (((ULONG_PTR)(x) & 0xFFFF) == 0) 639 #define NOTNEIGHBORPAGE(highvaddr, lowvaddr) ((ULONG_PTR)(highvaddr) - (ULONG_PTR)(lowvaddr) != PAGE_SIZE) 640 641 do { 642 if (idx >= MAX_SG_DESCRIPTORS) return FALSE; 643 644 pSgTable[idx].dSgAddress = fOsPhysicalAddress(v); 645 currvaddr = v; 646 currphypage = (ADDRESS)fOsPhysicalAddress((void*)trunc_page((ULONG_PTR)currvaddr)); 647 648 649 do { 650 nextpage = (ADDRESS)trunc_page(((ULONG_PTR)currvaddr + PAGE_SIZE)); 651 nextvaddr = (ADDRESS)MIN(((ULONG_PTR)v + bufferSize), (ULONG_PTR)(nextpage)); 652 653 if (nextvaddr == (ADDRESS)((ULONG_PTR)v + bufferSize)) break; 654 nextphypage = (ADDRESS)fOsPhysicalAddress(nextpage); 655 656 if (NOTNEIGHBORPAGE(nextphypage, currphypage) || ON64KBOUNDARY(nextphypage)) { 657 nextvaddr = nextpage; 658 break; 659 } 660 661 currvaddr = nextvaddr; 662 currphypage = nextphypage; 663 }while (1); 664 665 length = (ULONG_PTR)nextvaddr - (ULONG_PTR)v; 666 v = nextvaddr; 667 bufferSize -= length; 668 669 pSgTable[idx].wSgSize = (USHORT)length; 670 pSgTable[idx].wSgFlag = (bufferSize)? 0 : SG_FLAG_EOT; 671 idx++; 672 673 }while (bufferSize); 674 } 675 return 1; 676 } 677 678 static int End_Job=0; 679 void HPTLIBAPI 680 thread_io_done(_VBUS_ARG PCommand pCmd) 681 { 682 End_Job = 1; 683 wakeup((caddr_t)pCmd); 684 } 685 686 void 687 hpt_rebuild_data_block(IAL_ADAPTER_T *pAdapter, PVDevice pArray, UCHAR flags) 688 { 689 DWORD timeout = 0; 690 ULONG capacity = pArray->VDeviceCapacity / (pArray->u.array.bArnMember-1); 691 PCommand pCmd; 692 UINT result; 693 int needsync=0, retry=0, needdelete=0; 694 void *buffer = 0; 695 intrmask_t oldspl; 696 697 _VBUS_INST(&pAdapter->VBus) 698 699 if (pArray->u.array.rf_broken==1 || 700 pArray->u.array.RebuildSectors>=capacity) 701 return; 702 703 oldspl = lock_driver(); 704 705 switch(flags) 706 { 707 case DUPLICATE: 708 case REBUILD_PARITY: 709 if(pArray->u.array.rf_rebuilding == 0) 710 { 711 pArray->u.array.rf_rebuilding = 1; 712 hpt_printk(("Rebuilding started.\n")); 713 ioctl_ReportEvent(ET_REBUILD_STARTED, pArray); 714 } 715 break; 716 717 case INITIALIZE: 718 if(pArray->u.array.rf_initializing == 0) 719 { 720 pArray->u.array.rf_initializing = 1; 721 hpt_printk(("Initializing started.\n")); 722 ioctl_ReportEvent(ET_INITIALIZE_STARTED, pArray); 723 } 724 break; 725 726 case VERIFY: 727 if(pArray->u.array.rf_verifying == 0) 728 { 729 pArray->u.array.rf_verifying = 1; 730 hpt_printk(("Verifying started.\n")); 731 ioctl_ReportEvent(ET_VERIFY_STARTED, pArray); 732 } 733 break; 734 } 735 736 retry_cmd: 737 pCmd = AllocateCommand(_VBUS_P0); 738 HPT_ASSERT(pCmd); 739 pCmd->cf_control = 1; 740 End_Job = 0; 741 742 if (pArray->VDeviceType==VD_RAID_1) 743 { 744 #define MAX_REBUILD_SECTORS 0x40 745 746 /* take care for discontinuous buffer in R1ControlSgl */ 747 unlock_driver(oldspl); 748 buffer = malloc(SECTOR_TO_BYTE(MAX_REBUILD_SECTORS), M_DEVBUF, M_NOWAIT); 749 oldspl = lock_driver(); 750 if(!buffer) { 751 FreeCommand(_VBUS_P pCmd); 752 hpt_printk(("can't allocate rebuild buffer\n")); 753 goto fail; 754 } 755 switch(flags) 756 { 757 case DUPLICATE: 758 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 759 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 760 break; 761 762 case VERIFY: 763 pCmd->uCmd.R1Control.Command = CTRL_CMD_VERIFY; 764 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS/2; 765 break; 766 767 case INITIALIZE: 768 pCmd->uCmd.R1Control.Command = CTRL_CMD_REBUILD; 769 pCmd->uCmd.R1Control.nSectors = MAX_REBUILD_SECTORS; 770 break; 771 } 772 773 pCmd->uCmd.R1Control.Lba = pArray->u.array.RebuildSectors; 774 775 if (capacity - pArray->u.array.RebuildSectors < pCmd->uCmd.R1Control.nSectors) 776 pCmd->uCmd.R1Control.nSectors = capacity - pArray->u.array.RebuildSectors; 777 778 pCmd->uCmd.R1Control.Buffer = buffer; 779 pCmd->pfnBuildSgl = R1ControlSgl; 780 } 781 else if (pArray->VDeviceType==VD_RAID_5) 782 { 783 switch(flags) 784 { 785 case DUPLICATE: 786 case REBUILD_PARITY: 787 pCmd->uCmd.R5Control.Command = CTRL_CMD_REBUILD; break; 788 case VERIFY: 789 pCmd->uCmd.R5Control.Command = CTRL_CMD_VERIFY; break; 790 case INITIALIZE: 791 pCmd->uCmd.R5Control.Command = CTRL_CMD_INIT; break; 792 } 793 pCmd->uCmd.R5Control.StripeLine=pArray->u.array.RebuildSectors>>pArray->u.array.bArBlockSizeShift; 794 } 795 else 796 HPT_ASSERT(0); 797 798 pCmd->pVDevice = pArray; 799 pCmd->pfnCompletion = thread_io_done; 800 pArray->pfnSendCommand(_VBUS_P pCmd); 801 CheckPendingCall(_VBUS_P0); 802 803 if (!End_Job) { 804 unlock_driver(oldspl); 805 while (!End_Job) { 806 tsleep((caddr_t)pCmd, PPAUSE, "pause", hz); 807 if (timeout++>60) break; 808 } 809 oldspl = lock_driver(); 810 if (!End_Job) { 811 hpt_printk(("timeout, reset\n")); 812 fResetVBus(_VBUS_P0); 813 } 814 } 815 816 result = pCmd->Result; 817 FreeCommand(_VBUS_P pCmd); 818 unlock_driver(oldspl); 819 if (buffer) free(buffer, M_DEVBUF); 820 oldspl = lock_driver(); 821 KdPrintI(("cmd finished %d", result)); 822 823 switch(result) 824 { 825 case RETURN_SUCCESS: 826 if (!pArray->u.array.rf_abort_rebuild) 827 { 828 if(pArray->u.array.RebuildSectors < capacity) 829 { 830 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, flags); 831 } 832 else 833 { 834 switch (flags) 835 { 836 case DUPLICATE: 837 case REBUILD_PARITY: 838 needsync = 1; 839 pArray->u.array.rf_rebuilding = 0; 840 pArray->u.array.rf_need_rebuild = 0; 841 pArray->u.array.CriticalMembers = 0; 842 pArray->u.array.RebuildSectors = MAX_LBA_T; 843 pArray->u.array.rf_duplicate_and_create = 0; 844 hpt_printk(("Rebuilding finished.\n")); 845 ioctl_ReportEvent(ET_REBUILD_FINISHED, pArray); 846 break; 847 case INITIALIZE: 848 needsync = 1; 849 pArray->u.array.rf_initializing = 0; 850 pArray->u.array.rf_need_rebuild = 0; 851 pArray->u.array.RebuildSectors = MAX_LBA_T; 852 hpt_printk(("Initializing finished.\n")); 853 ioctl_ReportEvent(ET_INITIALIZE_FINISHED, pArray); 854 break; 855 case VERIFY: 856 pArray->u.array.rf_verifying = 0; 857 hpt_printk(("Verifying finished.\n")); 858 ioctl_ReportEvent(ET_VERIFY_FINISHED, pArray); 859 break; 860 } 861 } 862 } 863 else 864 { 865 pArray->u.array.rf_abort_rebuild = 0; 866 if (pArray->u.array.rf_rebuilding) 867 { 868 hpt_printk(("Abort rebuilding.\n")); 869 pArray->u.array.rf_rebuilding = 0; 870 pArray->u.array.rf_duplicate_and_create = 0; 871 ioctl_ReportEvent(ET_REBUILD_ABORTED, pArray); 872 } 873 else if (pArray->u.array.rf_verifying) 874 { 875 hpt_printk(("Abort verifying.\n")); 876 pArray->u.array.rf_verifying = 0; 877 ioctl_ReportEvent(ET_VERIFY_ABORTED, pArray); 878 } 879 else if (pArray->u.array.rf_initializing) 880 { 881 hpt_printk(("Abort initializing.\n")); 882 pArray->u.array.rf_initializing = 0; 883 ioctl_ReportEvent(ET_INITIALIZE_ABORTED, pArray); 884 } 885 needdelete=1; 886 } 887 break; 888 889 case RETURN_DATA_ERROR: 890 if (flags==VERIFY) 891 { 892 needsync = 1; 893 pArray->u.array.rf_verifying = 0; 894 pArray->u.array.rf_need_rebuild = 1; 895 hpt_printk(("Verifying failed: found inconsistency\n")); 896 ioctl_ReportEvent(ET_VERIFY_DATA_ERROR, pArray); 897 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 898 899 if (!pArray->vf_online || pArray->u.array.rf_broken) break; 900 901 pArray->u.array.rf_auto_rebuild = 0; 902 pArray->u.array.rf_abort_rebuild = 0; 903 hpt_queue_dpc((HPT_DPC)hpt_rebuild_data_block, pAdapter, pArray, 904 (pArray->VDeviceType == VD_RAID_1) ? DUPLICATE : REBUILD_PARITY); 905 } 906 break; 907 908 default: 909 hpt_printk(("command failed with error %d\n", result)); 910 if (++retry<3) 911 { 912 hpt_printk(("retry (%d)\n", retry)); 913 goto retry_cmd; 914 } 915 fail: 916 pArray->u.array.rf_abort_rebuild = 0; 917 switch (flags) 918 { 919 case DUPLICATE: 920 case REBUILD_PARITY: 921 needsync = 1; 922 pArray->u.array.rf_rebuilding = 0; 923 pArray->u.array.rf_duplicate_and_create = 0; 924 hpt_printk(((flags==DUPLICATE)? "Duplicating failed.\n":"Rebuilding failed.\n")); 925 ioctl_ReportEvent(ET_REBUILD_FAILED, pArray); 926 break; 927 928 case INITIALIZE: 929 needsync = 1; 930 pArray->u.array.rf_initializing = 0; 931 hpt_printk(("Initializing failed.\n")); 932 ioctl_ReportEvent(ET_INITIALIZE_FAILED, pArray); 933 break; 934 935 case VERIFY: 936 needsync = 1; 937 pArray->u.array.rf_verifying = 0; 938 hpt_printk(("Verifying failed.\n")); 939 ioctl_ReportEvent(ET_VERIFY_FAILED, pArray); 940 break; 941 } 942 needdelete=1; 943 } 944 945 while (pAdapter->outstandingCommands) 946 { 947 KdPrintI(("currcmds is %d, wait..\n", pAdapter->outstandingCommands)); 948 /* put this to have driver stop processing system commands quickly */ 949 if (!mWaitingForIdle(_VBUS_P0)) CallWhenIdle(_VBUS_P nothing, 0); 950 unlock_driver(oldspl); 951 /*Schedule out*/ 952 #if (__FreeBSD_version < 500000) 953 YIELD_THREAD; 954 #else 955 pause("switch", 1); 956 #endif 957 oldspl = lock_driver(); 958 } 959 960 if (needsync) SyncArrayInfo(pArray); 961 if(needdelete && (pArray->u.array.rf_duplicate_must_done || (flags == INITIALIZE))) 962 fDeleteArray(_VBUS_P pArray, TRUE); 963 964 Check_Idle_Call(pAdapter); 965 unlock_driver(oldspl); 966 } 967