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