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