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