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