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