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