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