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