tw_osl_cam.c revision 172496
10SN/A/* 22362SN/A * Copyright (c) 2004-07 Applied Micro Circuits Corporation. 30SN/A * Copyright (c) 2004-05 Vinod Kashyap. 40SN/A * All rights reserved. 50SN/A * 60SN/A * Redistribution and use in source and binary forms, with or without 72362SN/A * modification, are permitted provided that the following conditions 80SN/A * are met: 92362SN/A * 1. Redistributions of source code must retain the above copyright 100SN/A * notice, this list of conditions and the following disclaimer. 110SN/A * 2. Redistributions in binary form must reproduce the above copyright 120SN/A * notice, this list of conditions and the following disclaimer in the 130SN/A * documentation and/or other materials provided with the distribution. 140SN/A * 150SN/A * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 160SN/A * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 170SN/A * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 180SN/A * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 190SN/A * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 200SN/A * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 212362SN/A * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 222362SN/A * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 232362SN/A * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 240SN/A * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 250SN/A * SUCH DAMAGE. 260SN/A * 270SN/A * $FreeBSD: head/sys/dev/twa/tw_osl_cam.c 172496 2007-10-09 17:43:57Z scottl $ 280SN/A */ 290SN/A 300SN/A/* 310SN/A * AMCC'S 3ware driver for 9000 series storage controllers. 320SN/A * 330SN/A * Author: Vinod Kashyap 340SN/A * Modifications by: Adam Radford 350SN/A * Modifications by: Manjunath Ranganathaiah 360SN/A */ 370SN/A 380SN/A 390SN/A/* 400SN/A * FreeBSD CAM related functions. 4113344Sredestad */ 420SN/A 430SN/A 4413344Sredestad#include <dev/twa/tw_osl_includes.h> 450SN/A 460SN/A#include <cam/cam.h> 470SN/A#include <cam/cam_ccb.h> 480SN/A#include <cam/cam_sim.h> 490SN/A#include <cam/cam_xpt_sim.h> 500SN/A#include <cam/cam_debug.h> 510SN/A#include <cam/cam_periph.h> 520SN/A 530SN/A#include <cam/scsi/scsi_all.h> 540SN/A#include <cam/scsi/scsi_message.h> 550SN/A 560SN/Astatic TW_VOID twa_action(struct cam_sim *sim, union ccb *ccb); 570SN/Astatic TW_VOID twa_poll(struct cam_sim *sim); 580SN/Astatic TW_VOID twa_timeout(TW_VOID *arg); 590SN/Astatic TW_VOID twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); 600SN/A 610SN/Astatic TW_INT32 tw_osli_execute_scsi(struct tw_osli_req_context *req, 620SN/A union ccb *ccb); 630SN/A 640SN/A 650SN/A 660SN/A/* 670SN/A * Function name: tw_osli_cam_attach 680SN/A * Description: Attaches the driver to CAM. 690SN/A * 700SN/A * Input: sc -- ptr to OSL internal ctlr context 710SN/A * Output: None 720SN/A * Return value: 0 -- success 730SN/A * non-zero-- failure 740SN/A */ 750SN/ATW_INT32 760SN/Atw_osli_cam_attach(struct twa_softc *sc) 770SN/A{ 780SN/A struct cam_devq *devq; 790SN/A TW_INT32 error; 800SN/A 810SN/A tw_osli_dbg_dprintf(3, sc, "entered"); 820SN/A 830SN/A /* 840SN/A * Create the device queue for our SIM. 850SN/A */ 860SN/A if ((devq = cam_simq_alloc(TW_OSLI_MAX_NUM_IOS)) == NULL) { 870SN/A tw_osli_printf(sc, "error = %d", 880SN/A TW_CL_SEVERITY_ERROR_STRING, 890SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 900SN/A 0x2100, 910SN/A "Failed to create SIM device queue", 920SN/A ENOMEM); 930SN/A return(ENOMEM); 940SN/A } 950SN/A 960SN/A /* 970SN/A * Create a SIM entry. Though we can support TW_OSLI_MAX_NUM_IOS 980SN/A * simultaneous requests, we claim to be able to handle only 990SN/A * (TW_OSLI_MAX_NUM_IOS - 1), so that we always have a request 1000SN/A * packet available to service ioctls. 1010SN/A */ 1020SN/A tw_osli_dbg_dprintf(3, sc, "Calling cam_sim_alloc"); 1030SN/A sc->sim = cam_sim_alloc(twa_action, twa_poll, "twa", sc, 1040SN/A device_get_unit(sc->bus_dev), sc->sim_lock, 1050SN/A TW_OSLI_MAX_NUM_IOS - 1, 1, devq); 1060SN/A if (sc->sim == NULL) { 1070SN/A cam_simq_free(devq); 1080SN/A tw_osli_printf(sc, "error = %d", 1090SN/A TW_CL_SEVERITY_ERROR_STRING, 1100SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1110SN/A 0x2101, 1120SN/A "Failed to create a SIM entry", 1130SN/A ENOMEM); 1140SN/A return(ENOMEM); 1150SN/A } 1160SN/A 1170SN/A /* 1180SN/A * Register the bus. 1190SN/A */ 1200SN/A tw_osli_dbg_dprintf(3, sc, "Calling xpt_bus_register"); 1210SN/A mtx_lock(sc->sim_lock); 1220SN/A if (xpt_bus_register(sc->sim, sc->bus_dev, 0) != CAM_SUCCESS) { 1230SN/A cam_sim_free(sc->sim, TRUE); 1240SN/A sc->sim = NULL; /* so cam_detach will not try to free it */ 1250SN/A tw_osli_printf(sc, "error = %d", 1260SN/A TW_CL_SEVERITY_ERROR_STRING, 1270SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1280SN/A 0x2102, 1290SN/A "Failed to register the bus", 1300SN/A ENXIO); 1310SN/A mtx_unlock(sc->sim_lock); 1320SN/A return(ENXIO); 1330SN/A } 1340SN/A 1350SN/A tw_osli_dbg_dprintf(3, sc, "Calling xpt_create_path"); 1360SN/A if (xpt_create_path(&sc->path, NULL, 1370SN/A cam_sim_path(sc->sim), 13813216Svtewari CAM_TARGET_WILDCARD, 13913216Svtewari CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 14013216Svtewari xpt_bus_deregister(cam_sim_path (sc->sim)); 14113216Svtewari /* Passing TRUE to cam_sim_free will free the devq as well. */ 14213216Svtewari cam_sim_free(sc->sim, TRUE); 14313216Svtewari tw_osli_printf(sc, "error = %d", 14413216Svtewari TW_CL_SEVERITY_ERROR_STRING, 14513216Svtewari TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 14613216Svtewari 0x2103, 14713216Svtewari "Failed to create path", 14813216Svtewari ENXIO); 14913216Svtewari mtx_unlock(sc->sim_lock); 1500SN/A return(ENXIO); 1510SN/A } 1520SN/A 1530SN/A tw_osli_dbg_dprintf(3, sc, "Calling xpt_setup_ccb"); 1540SN/A mtx_unlock(sc->sim_lock); 1550SN/A 1560SN/A tw_osli_dbg_dprintf(3, sc, "Calling tw_osli_request_bus_scan"); 1570SN/A /* 1580SN/A * Request a bus scan, so that CAM gets to know of 15913344Sredestad * the logical units that we control. 1600SN/A */ 1610SN/A if ((error = tw_osli_request_bus_scan(sc))) 16213344Sredestad tw_osli_printf(sc, "error = %d", 1630SN/A TW_CL_SEVERITY_ERROR_STRING, 1640SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 1650SN/A 0x2104, 1660SN/A "Bus scan request to CAM failed", 16713344Sredestad error); 1680SN/A 1690SN/A tw_osli_dbg_dprintf(3, sc, "exiting"); 1700SN/A return(0); 1710SN/A} 1720SN/A 1730SN/A 1740SN/A 1750SN/A/* 1760SN/A * Function name: tw_osli_cam_detach 1770SN/A * Description: Detaches the driver from CAM. 1780SN/A * 1790SN/A * Input: sc -- ptr to OSL internal ctlr context 1800SN/A * Output: None 1810SN/A * Return value: None 1820SN/A */ 1830SN/ATW_VOID 1840SN/Atw_osli_cam_detach(struct twa_softc *sc) 1850SN/A{ 1860SN/A tw_osli_dbg_dprintf(3, sc, "entered"); 1870SN/A 1880SN/A#ifdef TW_OSLI_DEFERRED_INTR_USED 1890SN/A /* - drain the taskqueue 1900SN/A Ctrl is already went down so, no more enqueuetask will 1910SN/A happen . Don't hold any locks, that task might need. 1920SN/A */ 1930SN/A 1940SN/A taskqueue_drain(taskqueue_fast, &(sc->deferred_intr_callback)); 1950SN/A#endif 1960SN/A mtx_lock(sc->sim_lock); 1970SN/A 1980SN/A if (sc->path) 1990SN/A xpt_free_path(sc->path); 2000SN/A if (sc->sim) { 2010SN/A xpt_bus_deregister(cam_sim_path(sc->sim)); 2020SN/A /* Passing TRUE to cam_sim_free will free the devq as well. */ 2030SN/A cam_sim_free(sc->sim, TRUE); 2040SN/A } 2050SN/A /* It's ok have 1 hold count while destroying the mutex */ 2060SN/A mtx_destroy(sc->sim_lock); 2070SN/A} 2080SN/A 2090SN/A 2100SN/A 2110SN/A/* 2120SN/A * Function name: tw_osli_execute_scsi 2130SN/A * Description: Build a fw cmd, based on a CAM style ccb, and 2140SN/A * send it down. 2150SN/A * 2160SN/A * Input: req -- ptr to OSL internal request context 2170SN/A * ccb -- ptr to CAM style ccb 2180SN/A * Output: None 2190SN/A * Return value: 0 -- success 2200SN/A * non-zero-- failure 2210SN/A */ 2220SN/ATW_INT32 2230SN/Atw_osli_execute_scsi(struct tw_osli_req_context *req, union ccb *ccb) 2240SN/A{ 2250SN/A struct twa_softc *sc = req->ctlr; 2260SN/A struct tw_cl_req_packet *req_pkt; 2270SN/A struct tw_cl_scsi_req_packet *scsi_req; 2280SN/A struct ccb_hdr *ccb_h = &(ccb->ccb_h); 2290SN/A struct ccb_scsiio *csio = &(ccb->csio); 2300SN/A TW_INT32 error; 2310SN/A 2320SN/A tw_osli_dbg_dprintf(10, sc, "SCSI I/O request 0x%x", 2330SN/A csio->cdb_io.cdb_bytes[0]); 2340SN/A 2350SN/A if (ccb_h->target_id >= TW_CL_MAX_NUM_UNITS) { 2360SN/A tw_osli_dbg_dprintf(3, sc, "Invalid target. PTL = %x %x %x", 2370SN/A ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun); 2380SN/A ccb_h->status |= CAM_TID_INVALID; 2390SN/A xpt_done(ccb); 2400SN/A return(1); 2410SN/A } 2420SN/A if (ccb_h->target_lun >= TW_CL_MAX_NUM_LUNS) { 2430SN/A tw_osli_dbg_dprintf(3, sc, "Invalid lun. PTL = %x %x %x", 2440SN/A ccb_h->path_id, ccb_h->target_id, ccb_h->target_lun); 2450SN/A ccb_h->status |= CAM_LUN_INVALID; 2460SN/A xpt_done(ccb); 2470SN/A return(1); 2480SN/A } 2490SN/A 2500SN/A if(ccb_h->flags & CAM_CDB_PHYS) { 2510SN/A tw_osli_printf(sc, "", 2520SN/A TW_CL_SEVERITY_ERROR_STRING, 2530SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 2540SN/A 0x2105, 2550SN/A "Physical CDB address!"); 2560SN/A ccb_h->status = CAM_REQ_CMP_ERR; 2570SN/A xpt_done(ccb); 25811375Ssherman return(1); 25911375Ssherman } 26011375Ssherman 26111375Ssherman /* 26211375Ssherman * We are going to work on this request. Mark it as enqueued (though 2630SN/A * we don't actually queue it...) 2640SN/A */ 2650SN/A ccb_h->status |= CAM_SIM_QUEUED; 2660SN/A 2670SN/A if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 2680SN/A if(ccb_h->flags & CAM_DIR_IN) 2690SN/A req->flags |= TW_OSLI_REQ_FLAGS_DATA_IN; 2700SN/A else 2710SN/A req->flags |= TW_OSLI_REQ_FLAGS_DATA_OUT; 2720SN/A } 2730SN/A 2740SN/A /* Build the CL understood request packet for SCSI cmds. */ 2750SN/A req_pkt = &req->req_pkt; 2760SN/A req_pkt->status = 0; 2770SN/A req_pkt->tw_osl_callback = tw_osl_complete_io; 2780SN/A scsi_req = &(req_pkt->gen_req_pkt.scsi_req); 2790SN/A scsi_req->unit = ccb_h->target_id; 2800SN/A scsi_req->lun = ccb_h->target_lun; 28113216Svtewari scsi_req->sense_len = 0; 28213216Svtewari scsi_req->sense_data = (TW_UINT8 *)(&csio->sense_data); 2830SN/A scsi_req->scsi_status = 0; 28413216Svtewari if(ccb_h->flags & CAM_CDB_POINTER) 28513216Svtewari scsi_req->cdb = csio->cdb_io.cdb_ptr; 28613216Svtewari else 28713216Svtewari scsi_req->cdb = csio->cdb_io.cdb_bytes; 28811375Ssherman scsi_req->cdb_len = csio->cdb_len; 28913216Svtewari 2900SN/A if (!(ccb_h->flags & CAM_DATA_PHYS)) { 2910SN/A /* Virtual data addresses. Need to convert them... */ 29211375Ssherman tw_osli_dbg_dprintf(3, sc, 29311375Ssherman "XPT_SCSI_IO: Single virtual address!"); 29411375Ssherman if (!(ccb_h->flags & CAM_SCATTER_VALID)) { 29511375Ssherman if (csio->dxfer_len > TW_CL_MAX_IO_SIZE) { 29611375Ssherman tw_osli_printf(sc, "size = %d", 29711375Ssherman TW_CL_SEVERITY_ERROR_STRING, 29811375Ssherman TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 29911375Ssherman 0x2106, 3000SN/A "I/O size too big", 30111375Ssherman csio->dxfer_len); 30211375Ssherman ccb_h->status = CAM_REQ_TOO_BIG; 30311375Ssherman xpt_done(ccb); 30411375Ssherman return(1); 30511375Ssherman } 30611375Ssherman 3070SN/A if ((req->length = csio->dxfer_len)) { 3080SN/A req->data = csio->data_ptr; 3090SN/A scsi_req->sgl_entries = 1; 3100SN/A } 3110SN/A } else { 3120SN/A tw_osli_printf(sc, "", 3130SN/A TW_CL_SEVERITY_ERROR_STRING, 3140SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 3150SN/A 0x2107, 3160SN/A "XPT_SCSI_IO: Got SGList"); 3170SN/A ccb_h->status = CAM_REQ_CMP_ERR; 3180SN/A xpt_done(ccb); 3190SN/A return(1); 3200SN/A } 3210SN/A } else { 3220SN/A /* Data addresses are physical. */ 3230SN/A tw_osli_printf(sc, "", 3240SN/A TW_CL_SEVERITY_ERROR_STRING, 3250SN/A TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 3260SN/A 0x2108, 3270SN/A "XPT_SCSI_IO: Physical data addresses"); 3280SN/A ccb_h->status = CAM_REQ_CMP_ERR; 3290SN/A ccb_h->status |= CAM_RELEASE_SIMQ; 3300SN/A ccb_h->status &= ~CAM_SIM_QUEUED; 3310SN/A xpt_done(ccb); 3320SN/A return(1); 3330SN/A } 3340SN/A 3350SN/A ccb_h->timeout_ch = timeout(twa_timeout, req, 3360SN/A (ccb_h->timeout * hz) / 1000); 3370SN/A /* 3380SN/A * twa_map_load_data_callback will fill in the SGL, 3390SN/A * and submit the I/O. 3400SN/A */ 3410SN/A error = tw_osli_map_request(req); 3420SN/A return(error); 3430SN/A} 3440SN/A 3450SN/A 3460SN/A 3470SN/A/* 3480SN/A * Function name: twa_action 3490SN/A * Description: Driver entry point for CAM's use. 3500SN/A * 3510SN/A * Input: sim -- sim corresponding to the ctlr 3520SN/A * ccb -- ptr to CAM request 3530SN/A * Output: None 354 * Return value: None 355 */ 356TW_VOID 357twa_action(struct cam_sim *sim, union ccb *ccb) 358{ 359 struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim); 360 struct ccb_hdr *ccb_h = &(ccb->ccb_h); 361 362 switch (ccb_h->func_code) { 363 case XPT_SCSI_IO: /* SCSI I/O */ 364 { 365 struct tw_osli_req_context *req; 366 367 if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) || 368 ((req = tw_osli_get_request(sc)) == NULL)) { 369 tw_osli_dbg_dprintf(2, sc, 370 "simq frozen/Cannot get request pkt."); 371 /* 372 * Freeze the simq to maintain ccb ordering. The next 373 * ccb that gets completed will unfreeze the simq. 374 */ 375 tw_osli_disallow_new_requests(sc); 376 ccb_h->status |= CAM_REQUEUE_REQ; 377 xpt_done(ccb); 378 break; 379 } 380 req->req_handle.osl_req_ctxt = req; 381 req->orig_req = ccb; 382 if (tw_osli_execute_scsi(req, ccb)) 383 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 384 break; 385 } 386 387 case XPT_ABORT: 388 tw_osli_dbg_dprintf(2, sc, "Abort request."); 389 ccb_h->status = CAM_UA_ABORT; 390 xpt_done(ccb); 391 break; 392 393 case XPT_RESET_BUS: 394 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE, 395 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 396 0x2108, 0x3, TW_CL_SEVERITY_INFO_STRING, 397 "Received Reset Bus request from CAM", 398 " "); 399 400 mtx_unlock(sc->sim_lock); 401 if (tw_cl_reset_ctlr(&sc->ctlr_handle)) { 402 tw_cl_create_event(&(sc->ctlr_handle), TW_CL_TRUE, 403 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 404 0x2109, 0x1, TW_CL_SEVERITY_ERROR_STRING, 405 "Failed to reset bus", 406 " "); 407 ccb_h->status = CAM_REQ_CMP_ERR; 408 } 409 else 410 ccb_h->status = CAM_REQ_CMP; 411 412 mtx_lock(sc->sim_lock); 413 xpt_done(ccb); 414 break; 415 416 case XPT_SET_TRAN_SETTINGS: 417 tw_osli_dbg_dprintf(3, sc, "XPT_SET_TRAN_SETTINGS"); 418 419 /* 420 * This command is not supported, since it's very specific 421 * to SCSI, and we are doing ATA. 422 */ 423 ccb_h->status = CAM_FUNC_NOTAVAIL; 424 xpt_done(ccb); 425 break; 426 427 case XPT_GET_TRAN_SETTINGS: 428 { 429 struct ccb_trans_settings *cts = &ccb->cts; 430 struct ccb_trans_settings_scsi *scsi = 431 &cts->proto_specific.scsi; 432 struct ccb_trans_settings_spi *spi = 433 &cts->xport_specific.spi; 434 435 cts->protocol = PROTO_SCSI; 436 cts->protocol_version = SCSI_REV_2; 437 cts->transport = XPORT_SPI; 438 cts->transport_version = 2; 439 440 spi->valid = CTS_SPI_VALID_DISC; 441 spi->flags = CTS_SPI_FLAGS_DISC_ENB; 442 scsi->valid = CTS_SCSI_VALID_TQ; 443 scsi->flags = CTS_SCSI_FLAGS_TAG_ENB; 444 tw_osli_dbg_dprintf(3, sc, "XPT_GET_TRAN_SETTINGS"); 445 ccb_h->status = CAM_REQ_CMP; 446 xpt_done(ccb); 447 break; 448 } 449 450 case XPT_CALC_GEOMETRY: 451 tw_osli_dbg_dprintf(3, sc, "XPT_CALC_GEOMETRY"); 452 cam_calc_geometry(&ccb->ccg, 1/* extended */); 453 xpt_done(ccb); 454 break; 455 456 case XPT_PATH_INQ: /* Path inquiry -- get twa properties */ 457 { 458 struct ccb_pathinq *path_inq = &ccb->cpi; 459 460 tw_osli_dbg_dprintf(3, sc, "XPT_PATH_INQ request"); 461 462 path_inq->version_num = 1; 463 path_inq->hba_inquiry = 0; 464 path_inq->target_sprt = 0; 465 path_inq->hba_misc = 0; 466 path_inq->hba_eng_cnt = 0; 467 path_inq->max_target = TW_CL_MAX_NUM_UNITS; 468 path_inq->max_lun = TW_CL_MAX_NUM_LUNS - 1; 469 path_inq->unit_number = cam_sim_unit(sim); 470 path_inq->bus_id = cam_sim_bus(sim); 471 path_inq->initiator_id = TW_CL_MAX_NUM_UNITS; 472 path_inq->base_transfer_speed = 100000; 473 strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN); 474 strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN); 475 strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN); 476 path_inq->transport = XPORT_SPI; 477 path_inq->transport_version = 2; 478 path_inq->protocol = PROTO_SCSI; 479 path_inq->protocol_version = SCSI_REV_2; 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_timeout 529 * Description: Driver entry point for being alerted on a request 530 * timing out. 531 * 532 * Input: arg -- ptr to timed out request 533 * Output: None 534 * Return value: None 535 */ 536static TW_VOID 537twa_timeout(TW_VOID *arg) 538{ 539 struct tw_osli_req_context *req = 540 (struct tw_osli_req_context *)arg; 541 542 tw_cl_create_event(&(req->ctlr->ctlr_handle), TW_CL_TRUE, 543 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 544 0x210B, 0x1, TW_CL_SEVERITY_ERROR_STRING, 545 "Request timed out!", 546 "request = %p", req); 547 tw_cl_reset_ctlr(&(req->ctlr->ctlr_handle)); 548} 549 550 551 552/* 553 * Function name: tw_osli_request_bus_scan 554 * Description: Requests CAM for a scan of the bus. 555 * 556 * Input: sc -- ptr to per ctlr structure 557 * Output: None 558 * Return value: 0 -- success 559 * non-zero-- failure 560 */ 561TW_INT32 562tw_osli_request_bus_scan(struct twa_softc *sc) 563{ 564 struct cam_path *path; 565 union ccb *ccb; 566 567 tw_osli_dbg_dprintf(3, sc, "entering"); 568 569 /* If we get here before sc->sim is initialized, return an error. */ 570 if (!(sc->sim)) 571 return(ENXIO); 572 if ((ccb = malloc(sizeof(union ccb), M_TEMP, M_WAITOK)) == NULL) 573 return(ENOMEM); 574 bzero(ccb, sizeof(union ccb)); 575 mtx_lock(sc->sim_lock); 576 if (xpt_create_path(&path, xpt_periph, cam_sim_path(sc->sim), 577 CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 578 free(ccb, M_TEMP); 579 mtx_unlock(sc->sim_lock); 580 return(EIO); 581 } 582 583 /* Release simq at the end of a reset */ 584 if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) { 585 xpt_release_simq(sc->sim, 1); 586 sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN; 587 } 588 589 xpt_setup_ccb(&ccb->ccb_h, path, 5); 590 ccb->ccb_h.func_code = XPT_SCAN_BUS; 591 ccb->ccb_h.cbfcnp = twa_bus_scan_cb; 592 ccb->crcn.flags = CAM_FLAG_NONE; 593 xpt_action(ccb); 594 mtx_unlock(sc->sim_lock); 595 return(0); 596} 597 598 599 600/* 601 * Function name: twa_bus_scan_cb 602 * Description: Callback from CAM on a bus scan request. 603 * 604 * Input: periph -- we don't use this 605 * ccb -- bus scan request ccb that we sent to CAM 606 * Output: None 607 * Return value: None 608 */ 609static TW_VOID 610twa_bus_scan_cb(struct cam_periph *periph, union ccb *ccb) 611{ 612 tw_osli_dbg_printf(3, "entering"); 613 614 if (ccb->ccb_h.status != CAM_REQ_CMP) 615 printf("cam_scan_callback: failure status = %x\n", 616 ccb->ccb_h.status); 617 else 618 tw_osli_dbg_printf(3, "success"); 619 620 xpt_free_path(ccb->ccb_h.path); 621 free(ccb, M_TEMP); 622} 623 624 625 626/* 627 * Function name: tw_osli_allow_new_requests 628 * Description: Sets the appropriate status bits in a ccb such that, 629 * when the ccb is completed by a call to xpt_done, 630 * CAM knows that it's ok to unfreeze the flow of new 631 * requests to this controller, if the flow is frozen. 632 * 633 * Input: sc -- ptr to OSL internal ctlr context 634 * ccb -- ptr to CAM request 635 * Output: None 636 * Return value: None 637 */ 638TW_VOID 639tw_osli_allow_new_requests(struct twa_softc *sc, TW_VOID *ccb) 640{ 641 ((union ccb *)(ccb))->ccb_h.status |= CAM_RELEASE_SIMQ; 642 sc->state &= ~TW_OSLI_CTLR_STATE_SIMQ_FROZEN; 643} 644 645 646 647/* 648 * Function name: tw_osli_disallow_new_requests 649 * Description: Calls the appropriate CAM function, so as to freeze 650 * the flow of new requests from CAM to this controller. 651 * 652 * Input: sc -- ptr to OSL internal ctlr context 653 * Output: None 654 * Return value: None 655 */ 656TW_VOID 657tw_osli_disallow_new_requests(struct twa_softc *sc) 658{ 659 /* Don't double freeze if already frozen */ 660 if ((sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) == 0) { 661 mtx_lock(sc->sim_lock); 662 xpt_freeze_simq(sc->sim, 1); 663 mtx_unlock(sc->sim_lock); 664 sc->state |= TW_OSLI_CTLR_STATE_SIMQ_FROZEN; 665 } 666} 667 668 669 670/* 671 * Function name: tw_osl_ctlr_busy 672 * Description: CL calls this function on cmd queue full or otherwise, 673 * when it is too busy to accept new requests. 674 * 675 * Input: ctlr_handle -- ptr to controller handle 676 * req_handle -- ptr to request handle sent by OSL. 677 * Output: None 678 * Return value: None 679 */ 680TW_VOID 681tw_osl_ctlr_busy(struct tw_cl_ctlr_handle *ctlr_handle, 682 struct tw_cl_req_handle *req_handle) 683{ 684 tw_osli_disallow_new_requests(ctlr_handle->osl_ctlr_ctxt); 685} 686 687 688 689/* 690 * Function name: tw_osl_scan_bus 691 * Description: CL calls this function to request for a bus scan. 692 * 693 * Input: ctlr_handle -- ptr to controller handle 694 * Output: None 695 * Return value: None 696 */ 697TW_VOID 698tw_osl_scan_bus(struct tw_cl_ctlr_handle *ctlr_handle) 699{ 700 struct twa_softc *sc = ctlr_handle->osl_ctlr_ctxt; 701 TW_INT32 error; 702 703 if ((error = tw_osli_request_bus_scan(sc))) 704 tw_osli_printf(sc, "error = %d", 705 TW_CL_SEVERITY_ERROR_STRING, 706 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 707 0x2109, 708 "Bus scan request to CAM failed", 709 error); 710} 711 712 713 714/* 715 * Function name: tw_osl_complete_io 716 * Description: Called to complete CAM scsi requests. 717 * 718 * Input: req_handle -- ptr to request handle 719 * Output: None 720 * Return value: None 721 */ 722TW_VOID 723tw_osl_complete_io(struct tw_cl_req_handle *req_handle) 724{ 725 struct tw_osli_req_context *req = req_handle->osl_req_ctxt; 726 struct tw_cl_req_packet *req_pkt = 727 (struct tw_cl_req_packet *)(&req->req_pkt); 728 struct tw_cl_scsi_req_packet *scsi_req; 729 struct twa_softc *sc = req->ctlr; 730 union ccb *ccb = (union ccb *)(req->orig_req); 731 732 tw_osli_dbg_dprintf(10, sc, "entering"); 733 734 if (req->state != TW_OSLI_REQ_STATE_BUSY) 735 tw_osli_printf(sc, "request = %p, status = %d", 736 TW_CL_SEVERITY_ERROR_STRING, 737 TW_CL_MESSAGE_SOURCE_FREEBSD_DRIVER, 738 0x210A, 739 "Unposted command completed!!", 740 req, req->state); 741 742 /* 743 * Remove request from the busy queue. Just mark it complete. 744 * There's no need to move it into the complete queue as we are 745 * going to be done with it right now. 746 */ 747 req->state = TW_OSLI_REQ_STATE_COMPLETE; 748 tw_osli_req_q_remove_item(req, TW_OSLI_BUSY_Q); 749 750 tw_osli_unmap_request(req); 751 752 untimeout(twa_timeout, req, ccb->ccb_h.timeout_ch); 753 if (req->error_code) { 754 /* This request never got submitted to the firmware. */ 755 if (req->error_code == EBUSY) { 756 /* 757 * Cmd queue is full, or the Common Layer is out of 758 * resources. The simq will already have been frozen 759 * by CL's call to tw_osl_ctlr_busy, and this will 760 * maintain ccb ordering. The next ccb that gets 761 * completed will unfreeze the simq. 762 */ 763 ccb->ccb_h.status |= CAM_REQUEUE_REQ; 764 } 765 else if (req->error_code == EFBIG) 766 ccb->ccb_h.status = CAM_REQ_TOO_BIG; 767 else 768 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 769 } else { 770 scsi_req = &(req_pkt->gen_req_pkt.scsi_req); 771 if (req_pkt->status == TW_CL_ERR_REQ_SUCCESS) 772 ccb->ccb_h.status = CAM_REQ_CMP; 773 else { 774 if (req_pkt->status & TW_CL_ERR_REQ_INVALID_TARGET) 775 ccb->ccb_h.status |= CAM_TID_INVALID; 776 else if (req_pkt->status & TW_CL_ERR_REQ_INVALID_LUN) 777 ccb->ccb_h.status |= CAM_LUN_INVALID; 778 else if (req_pkt->status & TW_CL_ERR_REQ_SCSI_ERROR) 779 ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 780 else if (req_pkt->status & TW_CL_ERR_REQ_BUS_RESET) 781 ccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 782 /* 783 * If none of the above errors occurred, simply 784 * mark completion error. 785 */ 786 if (ccb->ccb_h.status == 0) 787 ccb->ccb_h.status = CAM_REQ_CMP_ERR; 788 789 if (req_pkt->status & TW_CL_ERR_REQ_AUTO_SENSE_VALID) { 790 ccb->csio.sense_len = scsi_req->sense_len; 791 ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 792 } 793 } 794 795 ccb->csio.scsi_status = scsi_req->scsi_status; 796 /* If simq is frozen, unfreeze it. */ 797 if (sc->state & TW_OSLI_CTLR_STATE_SIMQ_FROZEN) 798 tw_osli_allow_new_requests(sc, (TW_VOID *)ccb); 799 } 800 801 ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 802 mtx_lock(sc->sim_lock); 803 xpt_done(ccb); 804 mtx_unlock(sc->sim_lock); 805 if (! req->error_code) 806 /* twa_action will free the request otherwise */ 807 tw_osli_req_q_insert_tail(req, TW_OSLI_FREE_Q); 808} 809 810