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