43 44#include <cam/cam.h> 45#include <cam/cam_ccb.h> 46#include <cam/cam_sim.h> 47#include <cam/cam_xpt_sim.h> 48#include <cam/cam_xpt_periph.h> 49#include <cam/cam_debug.h> 50#include <cam/cam_periph.h> 51 52#include <cam/scsi/scsi_all.h> 53#include <cam/scsi/scsi_message.h> 54 55static TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb); 56static TW_VOID twa_poll(struct cam_sim *sim); 57static TW_VOID twa_async(TW_VOID *callback_arg, TW_UINT32 code, 58 struct cam_path *path, TW_VOID *arg); 59static TW_VOID twa_timeout(TW_VOID *arg); 60static TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); 61 62static TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req, 63 union ccb *ccb); 64 65 66 67/* 68 * Function name: tw_osli_cam_attach 69 * Description: Attaches the driver to CAM. 70 * 71 * Input: sc -- ptr to OSL internal ctlr context 72 * Output: None 73 * Return value: 0 -- success 74 * non-zero-- failure 75 */ 76TW_INT32 77tw_osli_cam_attach(struct twa_softc *sc) 78{ 79 struct cam_devq *devq; 80 struct ccb_setasync csa; 81 TW_INT32 error; 82 83 tw_osli_dbg_dprintf(3, sc, "entered"); 84 85 /* 86 * Create the device queue for our SIM. 87 */ 88 if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) { 89 tw_osli_printf(sc, "error = %d", 90 TW_CL_SEVERITY_ERROR_STRING, 91 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 92 0x2100, 93 "Failed to create SIM device queue", 94 ENOMEM); 95 return(ENOMEM); 96 } 97 98 /* 99 * Create a SIM entry. Though we can support TW_OSLI_MAX_NUM_IOS 100 * simultaneous requests, we claim to be able to handle only 101 * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request 102 * packet available to service ioctls. 103 */ 104 tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc"); 105 sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc, 106 device_get_unit(sc->bus_dev), 107 TW_OSLI_MAX_NUM_IOS - 1, 1, devq); 108 if (sc->sim == NULL) { 109 cam_simq_free(devq); 110 tw_osli_printf(sc, "error = %d", 111 TW_CL_SEVERITY_ERROR_STRING, 112 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 113 0x2101, 114 "Failed to create a SIM entry", 115 ENOMEM); 116 return(ENOMEM); 117 } 118 119 /* 120 * Register the bus. 121 */ 122 tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register"); 123 if (xpt_bus_register(sc->sim, 0) != CAM_SUCCESS) { 124 cam_sim_free(sc->sim, TRUE); 125 sc->sim = NULL; /* so cam_detach will not try to free it */ 126 tw_osli_printf(sc, "error = %d", 127 TW_CL_SEVERITY_ERROR_STRING, 128 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 129 0x2102, 130 "Failed to register the bus", 131 ENXIO); 132 return(ENXIO); 133 } 134 135 tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path"); 136 if (xpt_create_path(&sc->path, NULL, 137 cam_sim_path(sc->sim), 138 CAM_TARGET_WILDCARD, 139 CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 140 xpt_bus_deregister(cam_sim_path (sc->sim)); 141 /* Passing TRUE to cam_sim_free will free the devq as well. */ 142 cam_sim_free(sc->sim, TRUE); 143 tw_osli_printf(sc, "error = %d", 144 TW_CL_SEVERITY_ERROR_STRING, 145 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 146 0x2103, 147 "Failed to create path", 148 ENXIO); 149 return(ENXIO); 150 } 151 152 tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb"); 153 xpt_setup_ccb(&csa.ccb_h, sc->path, 5); 154 csa.ccb_h.func_code = XPT_SASYNC_CB; 155 csa.event_enable = AC_FOUND_DEVICE | AC_LOST_DEVICE; 156 csa.callback = twa_async; 157 csa.callback_arg = sc; 158 xpt_action((union ccb *)&csa); 159 160 tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan"); 161 /* 162 * Request a bus scan, so that CAM gets to know of 163 * the logical units that we control. 164 */ 165 if ((error = tw_osli_request_bus_scan(sc))) 166 tw_osli_printf(sc, "error = %d", 167 TW_CL_SEVERITY_ERROR_STRING, 168 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 169 0x2104, 170 "Bus scan request to CAM failed", 171 error); 172 173 tw_osli_dbg_dprintf(3, sc, "exiting"); 174 return(0); 175} 176 177 178 179/* 180 * Function name: tw_osli_cam_detach 181 * Description: Detaches the driver from CAM. 182 * 183 * Input: sc -- ptr to OSL internal ctlr context 184 * Output: None 185 * Return value: None 186 */ 187TW_VOID 188tw_osli_cam_detach(struct twa_softc *sc) 189{ 190 tw_osli_dbg_dprintf(3, sc, "entered"); 191 192 mtx_lock(&Giant); 193 if (sc->path) 194 xpt_free_path(sc->path); 195 if (sc->sim) { 196 xpt_bus_deregister(cam_sim_path(sc->sim)); 197 /* Passing TRUE to cam_sim_free will free the devq as well. */ 198 cam_sim_free(sc->sim, TRUE); 199 } 200 mtx_unlock(&Giant); 201} 202 203 204 205/* 206 * Function name: tw_osli_execute_scsi 207 * Description: Build a fw cmd, based on a CAM style ccb, and 208 * send it down. 209 * 210 * Input: req -- ptr to OSL internal request context 211 * ccb -- ptr to CAM style ccb 212 * Output: None 213 * Return value: 0 -- success 214 * non-zero-- failure 215 */ 216TW_INT32 217tw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb) 218{ 219 struct twa_softc *sc = req->ctlr; 220 struct tw_cl_req_packet *req_pkt; 221 struct tw_cl_scsi_req_packet *scsi_req; 222 struct ccb_hdr *ccb_h = &(ccb->ccb_h); 223 struct ccb_scsiio *csio = &(ccb->csio); 224 TW_INT32 error; 225 226 tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x", 227 csio->cdb_io.cdb_bytes[0]); 228 229 if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) { 230 tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x", 231 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun); 232 ccb_h->status |= CAM_TID_INVALID; 233 xpt_done(ccb); 234 return(1); 235 } 236 if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) { 237 tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x", 238 ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun); 239 ccb_h->status |= CAM_LUN_INVALID; 240 xpt_done(ccb); 241 return(1); 242 } 243 244 if(ccb_h->flags & CAM_CDB_PHYS) { 245 tw_osli_printf(sc, "", 246 TW_CL_SEVERITY_ERROR_STRING, 247 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 248 0x2105, 249 "Physical CDB address!"); 250 ccb_h->status = CAM_REQ_CMP_ERR; 251 xpt_done(ccb); 252 return(1); 253 } 254 255 /* 256 * We are going to work on this request. Mark it as enqueued (though 257 * we don't actually queue it...) 258 */ 259 ccb_h->status |= CAM_SIM_QUEUED; 260 261 if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 262 if(ccb_h->flags & CAM_DIR_IN) 263 req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN; 264 else 265 req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT; 266 } 267 268 /* Build the CL understood request packet for SCSI cmds. */ 269 req_pkt = &req->req_pkt; 270 req_pkt->status = 0; 271 req_pkt->tw_osl_callback = tw_osl_complete_io; 272 scsi_req = &(req_pkt->gen_req_pkt.scsi_req); 273 scsi_req->unit = ccb_h->target_id; 274 scsi_req->lun = ccb_h->target_lun; 275 scsi_req->sense_len = 0; 276 scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data); 277 scsi_req->scsi_status = 0; 278 if(ccb_h->flags & CAM_CDB_POINTER) 279 scsi_req->cdb = csio->cdb_io.cdb_ptr; 280 else 281 scsi_req->cdb = csio->cdb_io.cdb_bytes; 282 scsi_req->cdb_len = csio->cdb_len; 283 284 if (!(ccb_h->flags & CAM_DATA_PHYS)) { 285 /* Virtual data addresses. Need to convert them... */ 286 tw_osli_dbg_dprintf(3, sc, 287 "XPT_SCSI_IO: Single virtual address!"); 288 if (!(ccb_h->flags & CAM_SCATTER_VALID)) { 289 if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) { 290 tw_osli_printf(sc, "size = %d", 291 TW_CL_SEVERITY_ERROR_STRING, 292 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 293 0x2106, 294 "I/O size too big", 295 csio->dxfer_len); 296 ccb_h->status = CAM_REQ_TOO_BIG; 297 xpt_done(ccb); 298 return(1); 299 } 300 301 if ((req->length = csio->dxfer_len)) { 302 req->data = csio->data_ptr; 303 scsi_req->sgl_entries = 1; 304 } 305 } else { 306 tw_osli_printf(sc, "", 307 TW_CL_SEVERITY_ERROR_STRING, 308 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 309 0x2107, 310 "XPT_SCSI_IO: Got SGList"); 311 ccb_h->status = CAM_REQ_CMP_ERR; 312 xpt_done(ccb); 313 return(1); 314 } 315 } else { 316 /* Data addresses are physical. */ 317 tw_osli_printf(sc, "", 318 TW_CL_SEVERITY_ERROR_STRING, 319 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 320 0x2108, 321 "XPT_SCSI_IO: Physical data addresses"); 322 ccb_h->status = CAM_REQ_CMP_ERR; 323 ccb_h->status |= CAM_RELEASE_SIMQ; 324 ccb_h->status &= ~CAM_SIM_QUEUED; 325 xpt_done(ccb); 326 return(1); 327 } 328 329 ccb_h->timeout_ch = timeout(twa_timeout, req, 330 (ccb_h->timeout * hz) / 1000); 331 /* 332 * twa_map_load_data_callback will fill in the SGL, 333 * and submit the I/O. 334 */ 335 error = tw_osli_map_request(req); 336 return(error); 337} 338 339 340 341/* 342 * Function name: twa_action 343 * Description: Driver entry point for CAM's use. 344 * 345 * Input: sim -- sim corresponding to the ctlr 346 * ccb -- ptr to CAM request 347 * Output: None 348 * Return value: None 349 */ 350TW_VOID 351twa_action(struct cam_sim *sim, union ccb *ccb) 352{ 353 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim); 354 struct ccb_hdr *ccb_h = &(ccb->ccb_h); 355 356 switch (ccb_h->func_code) { 357 case XPT_SCSI_IO: /* SCSI I/O */ 358 { 359 struct tw_osli_req_context *req; 360 361 if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) || 362 ((req = tw_osli_get_request(sc)) == NULL)) { 363 tw_osli_dbg_dprintf(2, sc, 364 "simq frozen/Cannot get request pkt."); 365 /* 366 * Freeze the simq to maintain ccb ordering. The next 367 * ccb that gets completed will unfreeze the simq. 368 */ 369 tw_osli_disallow_new_requests(sc); 370 ccb_h->status |= CAM_REQUEUE_REQ; 371 xpt_done(ccb); 372 break; 373 } 374 req->req_handle.osl_req_ctxt = req; 375 req->orig_req = ccb; 376 if (tw_osli_execute_scsi(req, ccb)) 377 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 378 break; 379 } 380 381 case XPT_ABORT: 382 tw_osli_dbg_dprintf(2, sc, "Abort request."); 383 ccb_h->status = CAM_UA_ABORT; 384 xpt_done(ccb); 385 break; 386 387 case XPT_RESET_BUS: 388 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE, 389 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 390 0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING, 391 "Received Reset Bus request from CAM", 392 " "); 393 394 if (tw_cl_reset_ctlr(&sc->ctlr_handle)) { 395 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE, 396 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 397 0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING, 398 "Failed to reset bus", 399 " "); 400 ccb_h->status = CAM_REQ_CMP_ERR; 401 } 402 else 403 ccb_h->status = CAM_REQ_CMP; 404 405 xpt_done(ccb); 406 break; 407 408 case XPT_SET_TRAN_SETTINGS: 409 tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS"); 410 411 /* 412 * This command is not supported, since it's very specific 413 * to SCSI, and we are doing ATA. 414 */ 415 ccb_h->status = CAM_FUNC_NOTAVAIL; 416 xpt_done(ccb); 417 break; 418 419 case XPT_GET_TRAN_SETTINGS: 420 { 421 struct ccb_trans_settings *cts = &ccb->cts; 422 423 tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS"); 424 cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID); 425 cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 426 ccb_h->status = CAM_REQ_CMP; 427 xpt_done(ccb); 428 break; 429 } 430 431 case XPT_CALC_GEOMETRY: 432 tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY"); 433 cam_calc_geometry(&ccb->ccg, 1/* extended */); 434 xpt_done(ccb); 435 break; 436 437 case XPT_PATH_INQ: /* Path inquiry -- get twa properties */ 438 { 439 struct ccb_pathinq *path_inq = &ccb->cpi; 440 441 tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request"); 442 443 path_inq->version_num = 1; 444 path_inq->hba_inquiry = 0; 445 path_inq->target_sprt = 0; 446 path_inq->hba_misc = 0; 447 path_inq->hba_eng_cnt = 0; 448 path_inq->max_target = TW_CL_MAX_NUM_UNITS; 449 path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1; 450 path_inq->unit_number = cam_sim_unit(sim); 451 path_inq->bus_id = cam_sim_bus(sim); 452 path_inq->initiator_id = 12; 453 path_inq->base_transfer_speed = 100000; 454 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN); 455 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN); 456 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN); 457 ccb_h->status = CAM_REQ_CMP; 458 xpt_done(ccb); 459 break; 460 } 461 462 default: 463 tw_osli_dbg_dprintf(3, sc, "func_code = %x", ccb_h->func_code); 464 ccb_h->status = CAM_REQ_INVALID; 465 xpt_done(ccb); 466 break; 467 } 468} 469 470 471 472/* 473 * Function name: twa_poll 474 * Description: Driver entry point called when interrupts are not 475 * available. 476 * 477 * Input: sim -- sim corresponding to the controller 478 * Output: None 479 * Return value: None 480 */ 481TW_VOID 482twa_poll(struct cam_sim *sim) 483{ 484 struct twa_softc *sc = (struct twa_softc *)(cam_sim_softc(sim)); 485 486 tw_osli_dbg_dprintf(3, sc, "entering; sc = %p", sc); 487 /* 488 * It's been observed that twa_poll can get called (from 489 * dashutdown --> xpt_polled_action) even when interrupts are 490 * active, in which case, the ISR might clear the interrupt, 491 * leaving the call to tw_cl_interrupt below, no way of determining 492 * that the response from firmware is ready, resulting in 493 * tw_cl_deferred_interrupt never getting called. To cover this case, 494 * we will make the call to tw_cl_deferred_interrupt not dependent 495 * on the return value from tw_cl_interrupt. 496 */ 497 tw_cl_interrupt(&(sc->ctlr_handle)); 498 tw_cl_deferred_interrupt(&(sc->ctlr_handle)); 499 tw_osli_dbg_dprintf(3, sc, "exiting; sc = %p", sc); 500} 501 502 503 504/* 505 * Function name: twa_async 506 * Description: Driver entry point for CAM to notify driver of special 507 * events. We don't use this for now. 508 * 509 * Input: callback_arg -- ptr to per ctlr structure 510 * code -- code associated with the event 511 * path -- cam path 512 * arg -- 513 * Output: None 514 * Return value: 0 -- success 515 * non-zero-- failure 516 */ 517TW_VOID 518twa_async(TW_VOID *callback_arg, TW_UINT32 code, 519 struct cam_path *path, TW_VOID *arg) 520{ 521#ifdef TW_OSL_DEBUG 522 struct twa_softc *sc = (struct twa_softc *)callback_arg; 523#endif /* TW_OSL_DEBUG */ 524 525 tw_osli_dbg_dprintf(3, sc, "sc = %p, code = %x, path = %p, arg = %p", 526 sc, code, path, arg); 527} 528 529 530 531/* 532 * Function name: twa_timeout 533 * Description: Driver entry point for being alerted on a request 534 * timing out. 535 * 536 * Input: arg -- ptr to timed out request 537 * Output: None 538 * Return value: None 539 */ 540static TW_VOID 541twa_timeout(TW_VOID *arg) 542{ 543 struct tw_osli_req_context *req = 544 (struct tw_osli_req_context *)arg; 545 546 tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE, 547 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 548 0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING, 549 "Request timed out!", 550 "request = %p", req); 551 tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle)); 552} 553 554 555 556/* 557 * Function name: tw_osli_request_bus_scan 558 * Description: Requests CAM for a scan of the bus. 559 * 560 * Input: sc -- ptr to per ctlr structure 561 * Output: None 562 * Return value: 0 -- success 563 * non-zero-- failure 564 */ 565TW_INT32 566tw_osli_request_bus_scan(struct twa_softc *sc) 567{ 568 struct cam_path *path; 569 union ccb *ccb; 570 571 tw_osli_dbg_dprintf(3, sc, "entering"); 572 573 if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL) 574 return(ENOMEM); 575 bzero(ccb, sizeof(union ccb)); 576 mtx_lock(&Giant); 577 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim), 578 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) 579 return(EIO); 580 581 xpt_setup_ccb(&ccb->ccb_h, path, 5); 582 ccb->ccb_h.func_code = XPT_SCAN_BUS; 583 ccb->ccb_h.cbfcnp = twa_bus_scan_cb; 584 ccb->crcn.flags = CAM_FLAG_NONE; 585 xpt_action(ccb); 586 mtx_unlock(&Giant); 587 return(0); 588} 589 590 591 592/* 593 * Function name: twa_bus_scan_cb 594 * Description: Callback from CAM on a bus scan request. 595 * 596 * Input: periph -- we don't use this 597 * ccb -- bus scan request ccb that we sent to CAM 598 * Output: None 599 * Return value: None 600 */ 601static TW_VOID 602twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb) 603{ 604 tw_osli_dbg_printf(3, "entering"); 605 606 if (ccb->ccb_h.status != CAM_REQ_CMP) 607 printf("cam_scan_callback: failure status = %x\n", 608 ccb->ccb_h.status); 609 else 610 tw_osli_dbg_printf(3, "success"); 611 612 xpt_free_path(ccb->ccb_h.path); 613 free(ccb, M_TEMP); 614} 615 616 617 618/* 619 * Function name: tw_osli_allow_new_requests 620 * Description: Sets the appropriate status bits in a ccb such that, 621 * when the ccb is completed by a call to xpt_done, 622 * CAM knows that it's ok to unfreeze the flow of new 623 * requests to this controller, if the flow is frozen. 624 * 625 * Input: sc -- ptr to OSL internal ctlr context 626 * ccb -- ptr to CAM request 627 * Output: None 628 * Return value: None 629 */ 630TW_VOID 631tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb) 632{ 633 ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ; 634 sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN; 635} 636 637 638 639/* 640 * Function name: tw_osli_disallow_new_requests 641 * Description: Calls the appropriate CAM function, so as to freeze 642 * the flow of new requests from CAM to this controller. 643 * 644 * Input: sc -- ptr to OSL internal ctlr context 645 * Output: None 646 * Return value: None 647 */ 648TW_VOID 649tw_osli_disallow_new_requests(struct twa_softc *sc) 650{ 651 xpt_freeze_simq(sc->sim, 1); 652 sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN; 653} 654 655 656 657/* 658 * Function name: tw_osl_scan_bus 659 * Description: CL calls this function to request for a bus scan. 660 * 661 * Input: ctlr_handle -- ptr to controller handle 662 * Output: None 663 * Return value: None 664 */ 665TW_VOID 666tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle) 667{ 668 struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt; 669 TW_INT32 error; 670 671 if ((error = tw_osli_request_bus_scan(sc))) 672 tw_osli_printf(sc, "error = %d", 673 TW_CL_SEVERITY_ERROR_STRING, 674 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 675 0x2109, 676 "Bus scan request to CAM failed", 677 error); 678} 679 680 681 682/* 683 * Function name: tw_osl_complete_io 684 * Description: Called to complete CAM scsi requests. 685 * 686 * Input: req_handle -- ptr to request handle 687 * Output: None 688 * Return value: None 689 */ 690TW_VOID 691tw_osl_complete_io(struct tw_cl_req_handle *req_handle) 692{ 693 struct tw_osli_req_context *req = req_handle->osl_req_ctxt; 694 struct tw_cl_req_packet *req_pkt = 695 (struct tw_cl_req_packet *)(&req->req_pkt); 696 struct tw_cl_scsi_req_packet *scsi_req; 697 struct twa_softc *sc = req->ctlr; 698 union ccb *ccb = (union ccb *)(req->orig_req); 699 700 tw_osli_dbg_dprintf(10, sc, "entering"); 701 702 if (req->state != TW_OSLI_REQ_STATE_BUSY) 703 tw_osli_printf(sc, "request = %p, status = %d", 704 TW_CL_SEVERITY_ERROR_STRING, 705 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 706 0x210A, 707 "Unposted command completed!!", 708 req, req->state); 709 710 /* 711 * Remove request from the busy queue. Just mark it complete. 712 * There's no need to move it into the complete queue as we are 713 * going to be done with it right now. 714 */ 715 req->state = TW_OSLI_REQ_STATE_COMPLETE; 716 tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q); 717 718 tw_osli_unmap_request(req); 719 720 untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch); 721 if (req->error_code) { 722 /* This request never got submitted to the firmware. */ 723 if (req->error_code == EBUSY) { 724 /* 725 * Cmd queue is full, or common layer is out 726 * of resources. Freeze the simq to maintain 727 * ccb ordering. The next ccb that gets 728 * completed will unfreeze the simq. 729 */ 730 tw_osli_disallow_new_requests(req->ctlr); 731 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 732 } 733 else if (req->error_code == EFBIG) 734 ccb->ccb_h.status = CAM_REQ_TOO_BIG; 735 else 736 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 737 } else { 738 scsi_req = &(req_pkt->gen_req_pkt.scsi_req); 739 if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS) 740 ccb->ccb_h.status = CAM_REQ_CMP; 741 else { 742 if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET) 743 ccb->ccb_h.status |= CAM_TID_INVALID; 744 else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN) 745 ccb->ccb_h.status |= CAM_LUN_INVALID; 746 else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR) 747 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 748 else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET) 749 ccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 750 /* 751 * If none of the above errors occurred, simply 752 * mark completion error. 753 */ 754 if (ccb->ccb_h.status == 0) 755 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 756 757 if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) { 758 ccb->csio.sense_len = scsi_req->sense_len; 759 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 760 } 761 } 762 763 ccb->csio.scsi_status = scsi_req->scsi_status; 764 /* If simq is frozen, unfreeze it. */ 765 if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) 766 tw_osli_allow_new_requests(sc, (TW_VOID *)ccb); 767 } 768 769 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 770 xpt_done(ccb); 771 if (! req->error_code) 772 /* twa_action will free the request otherwise */ 773 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 774} 775
|