1226026Sdelphij/* 2226026Sdelphij * Copyright (c) 2010 LSI Corp. 3226026Sdelphij * All rights reserved. 4226026Sdelphij * Author : Manjunath Ranganathaiah <manjunath.ranganathaiah@lsi.com> 5226026Sdelphij * 6226026Sdelphij * Redistribution and use in source and binary forms, with or without 7226026Sdelphij * modification, are permitted provided that the following conditions 8226026Sdelphij * are met: 9226026Sdelphij * 1. Redistributions of source code must retain the above copyright 10226026Sdelphij * notice, this list of conditions and the following disclaimer. 11226026Sdelphij * 2. Redistributions in binary form must reproduce the above copyright 12226026Sdelphij * notice, this list of conditions and the following disclaimer in the 13226026Sdelphij * documentation and/or other materials provided with the distribution. 14226026Sdelphij * 15226026Sdelphij * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16226026Sdelphij * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17226026Sdelphij * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18226026Sdelphij * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19226026Sdelphij * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20226026Sdelphij * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21226026Sdelphij * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22226026Sdelphij * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23226026Sdelphij * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24226026Sdelphij * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25226026Sdelphij * SUCH DAMAGE. 26226026Sdelphij * 27226026Sdelphij * $FreeBSD: stable/10/sys/dev/tws/tws_cam.c 315813 2017-03-23 06:41:13Z mav $ 28226026Sdelphij */ 29226026Sdelphij 30226026Sdelphij#include <dev/tws/tws.h> 31226026Sdelphij#include <dev/tws/tws_services.h> 32226026Sdelphij#include <dev/tws/tws_hdm.h> 33226026Sdelphij#include <dev/tws/tws_user.h> 34226026Sdelphij#include <cam/cam.h> 35226026Sdelphij#include <cam/cam_ccb.h> 36226026Sdelphij#include <cam/cam_sim.h> 37226026Sdelphij#include <cam/cam_xpt_sim.h> 38226026Sdelphij#include <cam/cam_debug.h> 39226026Sdelphij#include <cam/cam_periph.h> 40226026Sdelphij 41226026Sdelphij#include <cam/scsi/scsi_all.h> 42226026Sdelphij#include <cam/scsi/scsi_message.h> 43226026Sdelphij 44226026Sdelphijstatic int tws_cam_depth=(TWS_MAX_REQS - TWS_RESERVED_REQS); 45226026Sdelphijstatic char tws_sev_str[5][8]={"","ERROR","WARNING","INFO","DEBUG"}; 46226026Sdelphij 47226026Sdelphijstatic void tws_action(struct cam_sim *sim, union ccb *ccb); 48226026Sdelphijstatic void tws_poll(struct cam_sim *sim); 49226026Sdelphijstatic void tws_scsi_complete(struct tws_request *req); 50226026Sdelphij 51226026Sdelphij 52226026Sdelphij 53226026Sdelphijvoid tws_unmap_request(struct tws_softc *sc, struct tws_request *req); 54226026Sdelphijint32_t tws_map_request(struct tws_softc *sc, struct tws_request *req); 55226026Sdelphijint tws_bus_scan(struct tws_softc *sc); 56226026Sdelphijint tws_cam_attach(struct tws_softc *sc); 57226026Sdelphijvoid tws_cam_detach(struct tws_softc *sc); 58226026Sdelphijvoid tws_reset(void *arg); 59226026Sdelphij 60226026Sdelphijstatic void tws_reset_cb(void *arg); 61226026Sdelphijstatic void tws_reinit(void *arg); 62226026Sdelphijstatic int32_t tws_execute_scsi(struct tws_softc *sc, union ccb *ccb); 63226026Sdelphijstatic void tws_freeze_simq(struct tws_softc *sc, struct tws_request *req); 64226026Sdelphijstatic void tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs, 65226026Sdelphij int nseg, int error); 66226026Sdelphijstatic void tws_fill_sg_list(struct tws_softc *sc, void *sgl_src, 67226026Sdelphij void *sgl_dest, u_int16_t num_sgl_entries); 68226026Sdelphijstatic void tws_err_complete(struct tws_softc *sc, u_int64_t mfa); 69226026Sdelphijstatic void tws_scsi_err_complete(struct tws_request *req, 70226026Sdelphij struct tws_command_header *hdr); 71226026Sdelphijstatic void tws_passthru_err_complete(struct tws_request *req, 72226026Sdelphij struct tws_command_header *hdr); 73226026Sdelphij 74226026Sdelphij 75226026Sdelphijvoid tws_timeout(void *arg); 76226026Sdelphijstatic void tws_intr_attn_aen(struct tws_softc *sc); 77226026Sdelphijstatic void tws_intr_attn_error(struct tws_softc *sc); 78226026Sdelphijstatic void tws_intr_resp(struct tws_softc *sc); 79226026Sdelphijvoid tws_intr(void *arg); 80226026Sdelphijvoid tws_cmd_complete(struct tws_request *req); 81226026Sdelphijvoid tws_aen_complete(struct tws_request *req); 82226026Sdelphijint tws_send_scsi_cmd(struct tws_softc *sc, int cmd); 83226026Sdelphijvoid tws_getset_param_complete(struct tws_request *req); 84226026Sdelphijint tws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 85226026Sdelphij u_int32_t param_size, void *data); 86226026Sdelphijint tws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 87226026Sdelphij u_int32_t param_size, void *data); 88226026Sdelphij 89226026Sdelphij 90226026Sdelphijextern struct tws_request *tws_get_request(struct tws_softc *sc, 91226026Sdelphij u_int16_t type); 92226026Sdelphijextern void *tws_release_request(struct tws_request *req); 93226026Sdelphijextern int tws_submit_command(struct tws_softc *sc, struct tws_request *req); 94226026Sdelphijextern boolean tws_get_response(struct tws_softc *sc, 95226026Sdelphij u_int16_t *req_id, u_int64_t *mfa); 96226026Sdelphijextern void tws_q_insert_tail(struct tws_softc *sc, struct tws_request *req, 97226026Sdelphij u_int8_t q_type ); 98226026Sdelphijextern struct tws_request * tws_q_remove_request(struct tws_softc *sc, 99226026Sdelphij struct tws_request *req, u_int8_t q_type ); 100226026Sdelphijextern void tws_send_event(struct tws_softc *sc, u_int8_t event); 101226026Sdelphij 102226026Sdelphijextern struct tws_sense * 103226026Sdelphijtws_find_sense_from_mfa(struct tws_softc *sc, u_int64_t mfa); 104226026Sdelphij 105226026Sdelphijextern void tws_fetch_aen(void *arg); 106226026Sdelphijextern void tws_disable_db_intr(struct tws_softc *sc); 107226026Sdelphijextern void tws_enable_db_intr(struct tws_softc *sc); 108226026Sdelphijextern void tws_passthru_complete(struct tws_request *req); 109226026Sdelphijextern void tws_aen_synctime_with_host(struct tws_softc *sc); 110226026Sdelphijextern void tws_circular_aenq_insert(struct tws_softc *sc, 111226026Sdelphij struct tws_circular_q *cq, struct tws_event_packet *aen); 112226026Sdelphijextern int tws_use_32bit_sgls; 113226026Sdelphijextern boolean tws_ctlr_reset(struct tws_softc *sc); 114226026Sdelphijextern struct tws_request * tws_q_remove_tail(struct tws_softc *sc, 115226026Sdelphij u_int8_t q_type ); 116226026Sdelphijextern void tws_turn_off_interrupts(struct tws_softc *sc); 117226026Sdelphijextern void tws_turn_on_interrupts(struct tws_softc *sc); 118226026Sdelphijextern int tws_init_connect(struct tws_softc *sc, u_int16_t mc); 119226026Sdelphijextern void tws_init_obfl_q(struct tws_softc *sc); 120226026Sdelphijextern uint8_t tws_get_state(struct tws_softc *sc); 121226026Sdelphijextern void tws_assert_soft_reset(struct tws_softc *sc); 122226026Sdelphijextern boolean tws_ctlr_ready(struct tws_softc *sc); 123226026Sdelphijextern u_int16_t tws_poll4_response(struct tws_softc *sc, u_int64_t *mfa); 124226026Sdelphijextern int tws_setup_intr(struct tws_softc *sc, int irqs); 125226026Sdelphijextern int tws_teardown_intr(struct tws_softc *sc); 126226026Sdelphij 127226026Sdelphij 128226026Sdelphij 129226026Sdelphijint 130226026Sdelphijtws_cam_attach(struct tws_softc *sc) 131226026Sdelphij{ 132226026Sdelphij struct cam_devq *devq; 133226026Sdelphij 134226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, sc); 135226026Sdelphij /* Create a device queue for sim */ 136226026Sdelphij 137226026Sdelphij /* 138226026Sdelphij * if the user sets cam depth to less than 1 139226026Sdelphij * cam may get confused 140226026Sdelphij */ 141226026Sdelphij if ( tws_cam_depth < 1 ) 142226026Sdelphij tws_cam_depth = 1; 143226026Sdelphij if ( tws_cam_depth > (tws_queue_depth - TWS_RESERVED_REQS) ) 144226026Sdelphij tws_cam_depth = tws_queue_depth - TWS_RESERVED_REQS; 145226026Sdelphij 146226026Sdelphij TWS_TRACE_DEBUG(sc, "depths,ctlr,cam", tws_queue_depth, tws_cam_depth); 147226026Sdelphij 148226026Sdelphij if ((devq = cam_simq_alloc(tws_cam_depth)) == NULL) { 149226026Sdelphij tws_log(sc, CAM_SIMQ_ALLOC); 150226026Sdelphij return(ENOMEM); 151226026Sdelphij } 152226026Sdelphij 153226026Sdelphij /* 154226026Sdelphij * Create a SIM entry. Though we can support tws_cam_depth 155226026Sdelphij * simultaneous requests, we claim to be able to handle only 156226026Sdelphij * (tws_cam_depth), so that we always have reserved requests 157226026Sdelphij * packet available to service ioctls and internal commands. 158226026Sdelphij */ 159226026Sdelphij sc->sim = cam_sim_alloc(tws_action, tws_poll, "tws", sc, 160226026Sdelphij device_get_unit(sc->tws_dev), 161226026Sdelphij#if (__FreeBSD_version >= 700000) 162226026Sdelphij &sc->sim_lock, 163226026Sdelphij#endif 164226026Sdelphij tws_cam_depth, 1, devq); 165226026Sdelphij /* 1, 1, devq); */ 166226026Sdelphij if (sc->sim == NULL) { 167226026Sdelphij cam_simq_free(devq); 168226026Sdelphij tws_log(sc, CAM_SIM_ALLOC); 169226026Sdelphij } 170226026Sdelphij /* Register the bus. */ 171226026Sdelphij mtx_lock(&sc->sim_lock); 172226026Sdelphij if (xpt_bus_register(sc->sim, 173226026Sdelphij#if (__FreeBSD_version >= 700000) 174226026Sdelphij sc->tws_dev, 175226026Sdelphij#endif 176226026Sdelphij 0) != CAM_SUCCESS) { 177226026Sdelphij cam_sim_free(sc->sim, TRUE); /* passing true will free the devq */ 178226026Sdelphij sc->sim = NULL; /* so cam_detach will not try to free it */ 179226026Sdelphij mtx_unlock(&sc->sim_lock); 180226026Sdelphij tws_log(sc, TWS_XPT_BUS_REGISTER); 181226026Sdelphij return(ENXIO); 182226026Sdelphij } 183226026Sdelphij if (xpt_create_path(&sc->path, NULL, cam_sim_path(sc->sim), 184226026Sdelphij CAM_TARGET_WILDCARD, 185226026Sdelphij CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 186226026Sdelphij xpt_bus_deregister(cam_sim_path(sc->sim)); 187226026Sdelphij /* Passing TRUE to cam_sim_free will free the devq as well. */ 188226026Sdelphij cam_sim_free(sc->sim, TRUE); 189226026Sdelphij tws_log(sc, TWS_XPT_CREATE_PATH); 190226026Sdelphij mtx_unlock(&sc->sim_lock); 191226026Sdelphij return(ENXIO); 192226026Sdelphij } 193226026Sdelphij mtx_unlock(&sc->sim_lock); 194226026Sdelphij 195226026Sdelphij return(0); 196226026Sdelphij} 197226026Sdelphij 198226026Sdelphijvoid 199226026Sdelphijtws_cam_detach(struct tws_softc *sc) 200226026Sdelphij{ 201226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 202226026Sdelphij mtx_lock(&sc->sim_lock); 203226026Sdelphij if (sc->path) 204226026Sdelphij xpt_free_path(sc->path); 205226026Sdelphij if (sc->sim) { 206226026Sdelphij xpt_bus_deregister(cam_sim_path(sc->sim)); 207226026Sdelphij cam_sim_free(sc->sim, TRUE); 208226026Sdelphij } 209226026Sdelphij mtx_unlock(&sc->sim_lock); 210226026Sdelphij} 211226026Sdelphij 212226026Sdelphijint 213226026Sdelphijtws_bus_scan(struct tws_softc *sc) 214226026Sdelphij{ 215226026Sdelphij union ccb *ccb; 216226026Sdelphij 217226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", sc, 0); 218226026Sdelphij if (!(sc->sim)) 219226026Sdelphij return(ENXIO); 220248973Smav ccb = xpt_alloc_ccb(); 221248973Smav mtx_lock(&sc->sim_lock); 222249468Smav if (xpt_create_path(&ccb->ccb_h.path, NULL, cam_sim_path(sc->sim), 223226026Sdelphij CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { 224248973Smav mtx_unlock(&sc->sim_lock); 225226026Sdelphij xpt_free_ccb(ccb); 226226026Sdelphij return(EIO); 227226026Sdelphij } 228226026Sdelphij xpt_rescan(ccb); 229248973Smav mtx_unlock(&sc->sim_lock); 230226026Sdelphij return(0); 231226026Sdelphij} 232226026Sdelphij 233226026Sdelphijstatic void 234226026Sdelphijtws_action(struct cam_sim *sim, union ccb *ccb) 235226026Sdelphij{ 236226026Sdelphij struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim); 237226026Sdelphij 238226026Sdelphij 239226026Sdelphij switch( ccb->ccb_h.func_code ) { 240226026Sdelphij case XPT_SCSI_IO: 241226026Sdelphij { 242226026Sdelphij if ( tws_execute_scsi(sc, ccb) ) 243226026Sdelphij TWS_TRACE_DEBUG(sc, "execute scsi failed", 0, 0); 244226026Sdelphij break; 245226026Sdelphij } 246226026Sdelphij case XPT_ABORT: 247226026Sdelphij { 248226026Sdelphij TWS_TRACE_DEBUG(sc, "abort i/o", 0, 0); 249226026Sdelphij ccb->ccb_h.status = CAM_UA_ABORT; 250226026Sdelphij xpt_done(ccb); 251226026Sdelphij break; 252226026Sdelphij } 253226026Sdelphij case XPT_RESET_BUS: 254226026Sdelphij { 255226026Sdelphij TWS_TRACE_DEBUG(sc, "reset bus", sim, ccb); 256226026Sdelphij break; 257226026Sdelphij } 258226026Sdelphij case XPT_SET_TRAN_SETTINGS: 259226026Sdelphij { 260226026Sdelphij TWS_TRACE_DEBUG(sc, "set tran settings", sim, ccb); 261226026Sdelphij ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; 262226026Sdelphij xpt_done(ccb); 263226026Sdelphij 264226026Sdelphij break; 265226026Sdelphij } 266226026Sdelphij case XPT_GET_TRAN_SETTINGS: 267226026Sdelphij { 268226026Sdelphij TWS_TRACE_DEBUG(sc, "get tran settings", sim, ccb); 269226026Sdelphij 270226026Sdelphij#if (__FreeBSD_version >= 700000 ) 271226026Sdelphij ccb->cts.protocol = PROTO_SCSI; 272226026Sdelphij ccb->cts.protocol_version = SCSI_REV_2; 273226026Sdelphij ccb->cts.transport = XPORT_SPI; 274226026Sdelphij ccb->cts.transport_version = 2; 275226026Sdelphij 276226026Sdelphij ccb->cts.xport_specific.spi.valid = CTS_SPI_VALID_DISC; 277226026Sdelphij ccb->cts.xport_specific.spi.flags = CTS_SPI_FLAGS_DISC_ENB; 278226026Sdelphij ccb->cts.proto_specific.scsi.valid = CTS_SCSI_VALID_TQ; 279226026Sdelphij ccb->cts.proto_specific.scsi.flags = CTS_SCSI_FLAGS_TAG_ENB; 280226026Sdelphij#else 281226026Sdelphij ccb->cts.valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID); 282226026Sdelphij ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); 283226026Sdelphij#endif 284226026Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 285226026Sdelphij xpt_done(ccb); 286226026Sdelphij 287226026Sdelphij break; 288226026Sdelphij } 289226026Sdelphij case XPT_CALC_GEOMETRY: 290226026Sdelphij { 291226026Sdelphij TWS_TRACE_DEBUG(sc, "calc geometry(ccb,block-size)", ccb, 292226026Sdelphij ccb->ccg.block_size); 293226026Sdelphij cam_calc_geometry(&ccb->ccg, 1/* extended */); 294226026Sdelphij xpt_done(ccb); 295226026Sdelphij 296226026Sdelphij break; 297226026Sdelphij } 298226026Sdelphij case XPT_PATH_INQ: 299226026Sdelphij { 300226026Sdelphij TWS_TRACE_DEBUG(sc, "path inquiry", sim, ccb); 301226026Sdelphij ccb->cpi.version_num = 1; 302226026Sdelphij ccb->cpi.hba_inquiry = 0; 303226026Sdelphij ccb->cpi.target_sprt = 0; 304226026Sdelphij ccb->cpi.hba_misc = 0; 305226026Sdelphij ccb->cpi.hba_eng_cnt = 0; 306226026Sdelphij ccb->cpi.max_target = TWS_MAX_NUM_UNITS; 307226026Sdelphij ccb->cpi.max_lun = TWS_MAX_NUM_LUNS - 1; 308226026Sdelphij ccb->cpi.unit_number = cam_sim_unit(sim); 309226026Sdelphij ccb->cpi.bus_id = cam_sim_bus(sim); 310226026Sdelphij ccb->cpi.initiator_id = TWS_SCSI_INITIATOR_ID; 311226026Sdelphij ccb->cpi.base_transfer_speed = 6000000; 312315813Smav strlcpy(ccb->cpi.sim_vid, "FreeBSD", SIM_IDLEN); 313315813Smav strlcpy(ccb->cpi.hba_vid, "3ware", HBA_IDLEN); 314315813Smav strlcpy(ccb->cpi.dev_name, cam_sim_name(sim), DEV_IDLEN); 315226026Sdelphij#if (__FreeBSD_version >= 700000 ) 316226026Sdelphij ccb->cpi.transport = XPORT_SPI; 317226026Sdelphij ccb->cpi.transport_version = 2; 318226026Sdelphij ccb->cpi.protocol = PROTO_SCSI; 319226026Sdelphij ccb->cpi.protocol_version = SCSI_REV_2; 320226026Sdelphij ccb->cpi.maxio = TWS_MAX_IO_SIZE; 321226026Sdelphij#endif 322226026Sdelphij ccb->ccb_h.status = CAM_REQ_CMP; 323226026Sdelphij xpt_done(ccb); 324226026Sdelphij 325226026Sdelphij break; 326226026Sdelphij } 327226026Sdelphij default: 328226026Sdelphij TWS_TRACE_DEBUG(sc, "default", sim, ccb); 329226026Sdelphij ccb->ccb_h.status = CAM_REQ_INVALID; 330226026Sdelphij xpt_done(ccb); 331226026Sdelphij break; 332226026Sdelphij } 333226026Sdelphij} 334226026Sdelphij 335226026Sdelphijstatic void 336226026Sdelphijtws_scsi_complete(struct tws_request *req) 337226026Sdelphij{ 338226026Sdelphij struct tws_softc *sc = req->sc; 339226026Sdelphij 340226026Sdelphij mtx_lock(&sc->q_lock); 341226026Sdelphij tws_q_remove_request(sc, req, TWS_BUSY_Q); 342226026Sdelphij mtx_unlock(&sc->q_lock); 343226026Sdelphij 344275977Ssmh callout_stop(&req->timeout); 345226026Sdelphij tws_unmap_request(req->sc, req); 346226026Sdelphij 347226026Sdelphij 348226026Sdelphij req->ccb_ptr->ccb_h.status = CAM_REQ_CMP; 349226026Sdelphij mtx_lock(&sc->sim_lock); 350226026Sdelphij xpt_done(req->ccb_ptr); 351226026Sdelphij mtx_unlock(&sc->sim_lock); 352226026Sdelphij 353226026Sdelphij mtx_lock(&sc->q_lock); 354226026Sdelphij tws_q_insert_tail(sc, req, TWS_FREE_Q); 355226026Sdelphij mtx_unlock(&sc->q_lock); 356226026Sdelphij} 357226026Sdelphij 358226026Sdelphijvoid 359226026Sdelphijtws_getset_param_complete(struct tws_request *req) 360226026Sdelphij{ 361226026Sdelphij struct tws_softc *sc = req->sc; 362226026Sdelphij 363226026Sdelphij TWS_TRACE_DEBUG(sc, "getset complete", req, req->request_id); 364226026Sdelphij 365275977Ssmh callout_stop(&req->timeout); 366226026Sdelphij tws_unmap_request(sc, req); 367226026Sdelphij 368226026Sdelphij free(req->data, M_TWS); 369226026Sdelphij 370226026Sdelphij req->state = TWS_REQ_STATE_FREE; 371226026Sdelphij} 372226026Sdelphij 373226026Sdelphijvoid 374226026Sdelphijtws_aen_complete(struct tws_request *req) 375226026Sdelphij{ 376226026Sdelphij struct tws_softc *sc = req->sc; 377226026Sdelphij struct tws_command_header *sense; 378226026Sdelphij struct tws_event_packet event; 379226026Sdelphij u_int16_t aen_code=0; 380226026Sdelphij 381226026Sdelphij TWS_TRACE_DEBUG(sc, "aen complete", 0, req->request_id); 382226026Sdelphij 383275977Ssmh callout_stop(&req->timeout); 384226026Sdelphij tws_unmap_request(sc, req); 385226026Sdelphij 386226026Sdelphij sense = (struct tws_command_header *)req->data; 387226026Sdelphij 388226026Sdelphij TWS_TRACE_DEBUG(sc,"sense code, key",sense->sense_data[0], 389226026Sdelphij sense->sense_data[2]); 390226026Sdelphij TWS_TRACE_DEBUG(sc,"sense rid, seve",sense->header_desc.request_id, 391226026Sdelphij sense->status_block.res__severity); 392226026Sdelphij TWS_TRACE_DEBUG(sc,"sense srcnum, error",sense->status_block.srcnum, 393226026Sdelphij sense->status_block.error); 394226026Sdelphij TWS_TRACE_DEBUG(sc,"sense shdr, ssense",sense->header_desc.size_header, 395226026Sdelphij sense->header_desc.size_sense); 396226026Sdelphij 397226026Sdelphij aen_code = sense->status_block.error; 398226026Sdelphij 399226026Sdelphij switch ( aen_code ) { 400226026Sdelphij case TWS_AEN_SYNC_TIME_WITH_HOST : 401226026Sdelphij tws_aen_synctime_with_host(sc); 402226026Sdelphij break; 403226026Sdelphij case TWS_AEN_QUEUE_EMPTY : 404226026Sdelphij break; 405226026Sdelphij default : 406226026Sdelphij bzero(&event, sizeof(struct tws_event_packet)); 407226026Sdelphij event.sequence_id = sc->seq_id; 408226026Sdelphij event.time_stamp_sec = (u_int32_t)TWS_LOCAL_TIME; 409226026Sdelphij event.aen_code = sense->status_block.error; 410226026Sdelphij event.severity = sense->status_block.res__severity & 0x7; 411226026Sdelphij event.event_src = TWS_SRC_CTRL_EVENT; 412226026Sdelphij strcpy(event.severity_str, tws_sev_str[event.severity]); 413226026Sdelphij event.retrieved = TWS_AEN_NOT_RETRIEVED; 414226026Sdelphij 415226026Sdelphij bcopy(sense->err_specific_desc, event.parameter_data, 416226026Sdelphij TWS_ERROR_SPECIFIC_DESC_LEN); 417226026Sdelphij event.parameter_data[TWS_ERROR_SPECIFIC_DESC_LEN - 1] = '\0'; 418226026Sdelphij event.parameter_len = (u_int8_t)strlen(event.parameter_data)+1; 419226026Sdelphij 420226026Sdelphij if ( event.parameter_len < TWS_ERROR_SPECIFIC_DESC_LEN ) { 421226026Sdelphij event.parameter_len += ((u_int8_t)strlen(event.parameter_data + 422226026Sdelphij event.parameter_len) + 1); 423226026Sdelphij } 424226026Sdelphij 425226026Sdelphij device_printf(sc->tws_dev, "%s: (0x%02X: 0x%04X): %s: %s\n", 426226026Sdelphij event.severity_str, 427226026Sdelphij event.event_src, 428226026Sdelphij event.aen_code, 429226026Sdelphij event.parameter_data + 430226026Sdelphij (strlen(event.parameter_data) + 1), 431226026Sdelphij event.parameter_data); 432226026Sdelphij 433226026Sdelphij mtx_lock(&sc->gen_lock); 434226026Sdelphij tws_circular_aenq_insert(sc, &sc->aen_q, &event); 435226026Sdelphij sc->seq_id++; 436226026Sdelphij mtx_unlock(&sc->gen_lock); 437226026Sdelphij break; 438226026Sdelphij 439226026Sdelphij } 440226026Sdelphij 441226026Sdelphij free(req->data, M_TWS); 442226026Sdelphij 443226026Sdelphij req->state = TWS_REQ_STATE_FREE; 444226026Sdelphij 445226026Sdelphij if ( aen_code != TWS_AEN_QUEUE_EMPTY ) { 446226026Sdelphij /* timeout(tws_fetch_aen, sc, 1);*/ 447226026Sdelphij sc->stats.num_aens++; 448226026Sdelphij tws_fetch_aen((void *)sc); 449226026Sdelphij } 450226026Sdelphij} 451226026Sdelphij 452226026Sdelphijvoid 453226026Sdelphijtws_cmd_complete(struct tws_request *req) 454226026Sdelphij{ 455226026Sdelphij struct tws_softc *sc = req->sc; 456226026Sdelphij 457275977Ssmh callout_stop(&req->timeout); 458226026Sdelphij tws_unmap_request(sc, req); 459226026Sdelphij} 460226026Sdelphij 461226026Sdelphijstatic void 462226026Sdelphijtws_err_complete(struct tws_softc *sc, u_int64_t mfa) 463226026Sdelphij{ 464226026Sdelphij struct tws_command_header *hdr; 465226026Sdelphij struct tws_sense *sen; 466226026Sdelphij struct tws_request *req; 467226026Sdelphij u_int16_t req_id; 468226026Sdelphij u_int32_t reg, status; 469226026Sdelphij 470226026Sdelphij if ( !mfa ) { 471226026Sdelphij TWS_TRACE_DEBUG(sc, "null mfa", 0, mfa); 472226026Sdelphij return; 473226026Sdelphij } else { 474226026Sdelphij /* lookup the sense */ 475226026Sdelphij sen = tws_find_sense_from_mfa(sc, mfa); 476226026Sdelphij if ( sen == NULL ) { 477226026Sdelphij TWS_TRACE_DEBUG(sc, "found null req", 0, mfa); 478226026Sdelphij return; 479226026Sdelphij } 480226026Sdelphij hdr = sen->hdr; 481226026Sdelphij TWS_TRACE_DEBUG(sc, "sen, hdr", sen, hdr); 482226026Sdelphij req_id = hdr->header_desc.request_id; 483226026Sdelphij req = &sc->reqs[req_id]; 484226026Sdelphij TWS_TRACE_DEBUG(sc, "req, id", req, req_id); 485226026Sdelphij if ( req->error_code != TWS_REQ_RET_SUBMIT_SUCCESS ) 486226026Sdelphij TWS_TRACE_DEBUG(sc, "submit failure?", 0, req->error_code); 487226026Sdelphij } 488226026Sdelphij 489226026Sdelphij switch (req->type) { 490226026Sdelphij case TWS_REQ_TYPE_PASSTHRU : 491226026Sdelphij tws_passthru_err_complete(req, hdr); 492226026Sdelphij break; 493226026Sdelphij case TWS_REQ_TYPE_GETSET_PARAM : 494226026Sdelphij tws_getset_param_complete(req); 495226026Sdelphij break; 496226026Sdelphij case TWS_REQ_TYPE_SCSI_IO : 497226026Sdelphij tws_scsi_err_complete(req, hdr); 498226026Sdelphij break; 499226026Sdelphij 500226026Sdelphij } 501226026Sdelphij 502226026Sdelphij mtx_lock(&sc->io_lock); 503226026Sdelphij hdr->header_desc.size_header = 128; 504226026Sdelphij reg = (u_int32_t)( mfa>>32); 505226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBQPH, reg, 4); 506226026Sdelphij reg = (u_int32_t)(mfa); 507226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBQPL, reg, 4); 508226026Sdelphij 509226026Sdelphij status = tws_read_reg(sc, TWS_I2O0_STATUS, 4); 510226026Sdelphij if ( status & TWS_BIT13 ) { 511226026Sdelphij device_printf(sc->tws_dev, "OBFL Overrun\n"); 512226026Sdelphij sc->obfl_q_overrun = true; 513226026Sdelphij } 514226026Sdelphij mtx_unlock(&sc->io_lock); 515226026Sdelphij} 516226026Sdelphij 517226026Sdelphijstatic void 518226026Sdelphijtws_scsi_err_complete(struct tws_request *req, struct tws_command_header *hdr) 519226026Sdelphij{ 520226026Sdelphij u_int8_t *sense_data; 521226026Sdelphij struct tws_softc *sc = req->sc; 522226026Sdelphij union ccb *ccb = req->ccb_ptr; 523226026Sdelphij 524226026Sdelphij TWS_TRACE_DEBUG(sc, "sbe, cmd_status", hdr->status_block.error, 525226026Sdelphij req->cmd_pkt->cmd.pkt_a.status); 526226026Sdelphij if ( hdr->status_block.error == TWS_ERROR_LOGICAL_UNIT_NOT_SUPPORTED || 527226026Sdelphij hdr->status_block.error == TWS_ERROR_UNIT_OFFLINE ) { 528226026Sdelphij 529226026Sdelphij if ( ccb->ccb_h.target_lun ) { 530226026Sdelphij TWS_TRACE_DEBUG(sc, "invalid lun error",0,0); 531240901Sjimharris ccb->ccb_h.status |= CAM_DEV_NOT_THERE; 532226026Sdelphij } else { 533226026Sdelphij TWS_TRACE_DEBUG(sc, "invalid target error",0,0); 534240901Sjimharris ccb->ccb_h.status |= CAM_SEL_TIMEOUT; 535226026Sdelphij } 536226026Sdelphij 537226026Sdelphij } else { 538226026Sdelphij TWS_TRACE_DEBUG(sc, "scsi status error",0,0); 539226026Sdelphij ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR; 540226026Sdelphij if (((ccb->csio.cdb_io.cdb_bytes[0] == 0x1A) && 541226026Sdelphij (hdr->status_block.error == TWS_ERROR_NOT_SUPPORTED))) { 542226026Sdelphij ccb->ccb_h.status |= CAM_SCSI_STATUS_ERROR | CAM_AUTOSNS_VALID; 543226026Sdelphij TWS_TRACE_DEBUG(sc, "page mode not supported",0,0); 544226026Sdelphij } 545226026Sdelphij } 546226026Sdelphij 547226026Sdelphij /* if there were no error simply mark complete error */ 548226026Sdelphij if (ccb->ccb_h.status == 0) 549226026Sdelphij ccb->ccb_h.status = CAM_REQ_CMP_ERR; 550226026Sdelphij 551226026Sdelphij sense_data = (u_int8_t *)&ccb->csio.sense_data; 552226026Sdelphij if (sense_data) { 553226026Sdelphij memcpy(sense_data, hdr->sense_data, TWS_SENSE_DATA_LENGTH ); 554226026Sdelphij ccb->csio.sense_len = TWS_SENSE_DATA_LENGTH; 555226026Sdelphij ccb->ccb_h.status |= CAM_AUTOSNS_VALID; 556226026Sdelphij } 557226026Sdelphij ccb->csio.scsi_status = req->cmd_pkt->cmd.pkt_a.status; 558226026Sdelphij 559226026Sdelphij ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 560226026Sdelphij mtx_lock(&sc->sim_lock); 561226026Sdelphij xpt_done(ccb); 562226026Sdelphij mtx_unlock(&sc->sim_lock); 563226026Sdelphij 564275977Ssmh callout_stop(&req->timeout); 565226026Sdelphij tws_unmap_request(req->sc, req); 566226026Sdelphij mtx_lock(&sc->q_lock); 567226026Sdelphij tws_q_remove_request(sc, req, TWS_BUSY_Q); 568226026Sdelphij tws_q_insert_tail(sc, req, TWS_FREE_Q); 569226026Sdelphij mtx_unlock(&sc->q_lock); 570226026Sdelphij} 571226026Sdelphij 572226026Sdelphijstatic void 573226026Sdelphijtws_passthru_err_complete(struct tws_request *req, 574226026Sdelphij struct tws_command_header *hdr) 575226026Sdelphij{ 576226026Sdelphij TWS_TRACE_DEBUG(req->sc, "entry", hdr, req->request_id); 577226026Sdelphij req->error_code = hdr->status_block.error; 578226026Sdelphij memcpy(&(req->cmd_pkt->hdr), hdr, sizeof(struct tws_command_header)); 579226026Sdelphij tws_passthru_complete(req); 580226026Sdelphij} 581226026Sdelphij 582226026Sdelphijstatic void 583226026Sdelphijtws_drain_busy_queue(struct tws_softc *sc) 584226026Sdelphij{ 585226026Sdelphij struct tws_request *req; 586226026Sdelphij union ccb *ccb; 587226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 588226026Sdelphij 589226026Sdelphij mtx_lock(&sc->q_lock); 590226026Sdelphij req = tws_q_remove_tail(sc, TWS_BUSY_Q); 591226026Sdelphij mtx_unlock(&sc->q_lock); 592226026Sdelphij while ( req ) { 593226026Sdelphij TWS_TRACE_DEBUG(sc, "moved to TWS_COMPLETE_Q", 0, req->request_id); 594275977Ssmh callout_stop(&req->timeout); 595226026Sdelphij 596226026Sdelphij req->error_code = TWS_REQ_RET_RESET; 597226026Sdelphij ccb = (union ccb *)(req->ccb_ptr); 598226026Sdelphij 599226026Sdelphij ccb->ccb_h.status &= ~CAM_SIM_QUEUED; 600226026Sdelphij ccb->ccb_h.status |= CAM_REQUEUE_REQ; 601226026Sdelphij ccb->ccb_h.status |= CAM_SCSI_BUS_RESET; 602226026Sdelphij 603226026Sdelphij tws_unmap_request(req->sc, req); 604226026Sdelphij 605226026Sdelphij mtx_lock(&sc->sim_lock); 606226026Sdelphij xpt_done(req->ccb_ptr); 607226026Sdelphij mtx_unlock(&sc->sim_lock); 608226026Sdelphij 609226026Sdelphij mtx_lock(&sc->q_lock); 610226026Sdelphij tws_q_insert_tail(sc, req, TWS_FREE_Q); 611226026Sdelphij req = tws_q_remove_tail(sc, TWS_BUSY_Q); 612226026Sdelphij mtx_unlock(&sc->q_lock); 613226026Sdelphij } 614226026Sdelphij} 615226026Sdelphij 616226026Sdelphij 617226026Sdelphijstatic void 618226026Sdelphijtws_drain_reserved_reqs(struct tws_softc *sc) 619226026Sdelphij{ 620226026Sdelphij struct tws_request *r; 621226026Sdelphij 622226026Sdelphij r = &sc->reqs[TWS_REQ_TYPE_AEN_FETCH]; 623226026Sdelphij if ( r->state != TWS_REQ_STATE_FREE ) { 624226026Sdelphij TWS_TRACE_DEBUG(sc, "reset aen req", 0, 0); 625275977Ssmh callout_stop(&r->timeout); 626226026Sdelphij tws_unmap_request(sc, r); 627226026Sdelphij free(r->data, M_TWS); 628226026Sdelphij r->state = TWS_REQ_STATE_FREE; 629226026Sdelphij r->error_code = TWS_REQ_RET_RESET; 630226026Sdelphij } 631226026Sdelphij 632226026Sdelphij r = &sc->reqs[TWS_REQ_TYPE_PASSTHRU]; 633226026Sdelphij if ( r->state == TWS_REQ_STATE_BUSY ) { 634226026Sdelphij TWS_TRACE_DEBUG(sc, "reset passthru req", 0, 0); 635226026Sdelphij r->error_code = TWS_REQ_RET_RESET; 636226026Sdelphij } 637226026Sdelphij 638226026Sdelphij r = &sc->reqs[TWS_REQ_TYPE_GETSET_PARAM]; 639226026Sdelphij if ( r->state != TWS_REQ_STATE_FREE ) { 640226026Sdelphij TWS_TRACE_DEBUG(sc, "reset setparam req", 0, 0); 641275977Ssmh callout_stop(&r->timeout); 642226026Sdelphij tws_unmap_request(sc, r); 643226026Sdelphij free(r->data, M_TWS); 644226026Sdelphij r->state = TWS_REQ_STATE_FREE; 645226026Sdelphij r->error_code = TWS_REQ_RET_RESET; 646226026Sdelphij } 647226026Sdelphij} 648226026Sdelphij 649226026Sdelphijstatic void 650226026Sdelphijtws_drain_response_queue(struct tws_softc *sc) 651226026Sdelphij{ 652226026Sdelphij u_int16_t req_id; 653226026Sdelphij u_int64_t mfa; 654226026Sdelphij while ( tws_get_response(sc, &req_id, &mfa) ); 655226026Sdelphij} 656226026Sdelphij 657226026Sdelphij 658226026Sdelphijstatic int32_t 659226026Sdelphijtws_execute_scsi(struct tws_softc *sc, union ccb *ccb) 660226026Sdelphij{ 661226026Sdelphij struct tws_command_packet *cmd_pkt; 662226026Sdelphij struct tws_request *req; 663226026Sdelphij struct ccb_hdr *ccb_h = &(ccb->ccb_h); 664226026Sdelphij struct ccb_scsiio *csio = &(ccb->csio); 665226026Sdelphij int error; 666226026Sdelphij u_int16_t lun; 667226026Sdelphij 668226026Sdelphij mtx_assert(&sc->sim_lock, MA_OWNED); 669226026Sdelphij if (ccb_h->target_id >= TWS_MAX_NUM_UNITS) { 670226026Sdelphij TWS_TRACE_DEBUG(sc, "traget id too big", ccb_h->target_id, ccb_h->target_lun); 671226026Sdelphij ccb_h->status |= CAM_TID_INVALID; 672226026Sdelphij xpt_done(ccb); 673226026Sdelphij return(0); 674226026Sdelphij } 675226026Sdelphij if (ccb_h->target_lun >= TWS_MAX_NUM_LUNS) { 676226026Sdelphij TWS_TRACE_DEBUG(sc, "target lun 2 big", ccb_h->target_id, ccb_h->target_lun); 677226026Sdelphij ccb_h->status |= CAM_LUN_INVALID; 678226026Sdelphij xpt_done(ccb); 679226026Sdelphij return(0); 680226026Sdelphij } 681226026Sdelphij 682226026Sdelphij if(ccb_h->flags & CAM_CDB_PHYS) { 683226026Sdelphij TWS_TRACE_DEBUG(sc, "cdb phy", ccb_h->target_id, ccb_h->target_lun); 684226026Sdelphij ccb_h->status = CAM_REQ_INVALID; 685226026Sdelphij xpt_done(ccb); 686226026Sdelphij return(0); 687226026Sdelphij } 688226026Sdelphij 689226026Sdelphij /* 690226026Sdelphij * We are going to work on this request. Mark it as enqueued (though 691226026Sdelphij * we don't actually queue it...) 692226026Sdelphij */ 693226026Sdelphij ccb_h->status |= CAM_SIM_QUEUED; 694226026Sdelphij 695226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_SCSI_IO); 696226026Sdelphij if ( !req ) { 697226026Sdelphij TWS_TRACE_DEBUG(sc, "no reqs", ccb_h->target_id, ccb_h->target_lun); 698226026Sdelphij ccb_h->status |= CAM_REQUEUE_REQ; 699226026Sdelphij xpt_done(ccb); 700226026Sdelphij return(0); 701226026Sdelphij } 702226026Sdelphij 703226026Sdelphij if((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 704226026Sdelphij if(ccb_h->flags & CAM_DIR_IN) 705226026Sdelphij req->flags |= TWS_DIR_IN; 706226026Sdelphij if(ccb_h->flags & CAM_DIR_OUT) 707226026Sdelphij req->flags |= TWS_DIR_OUT; 708226026Sdelphij } else { 709226026Sdelphij req->flags = TWS_DIR_NONE; /* no data */ 710226026Sdelphij } 711226026Sdelphij 712226026Sdelphij req->type = TWS_REQ_TYPE_SCSI_IO; 713226026Sdelphij req->cb = tws_scsi_complete; 714226026Sdelphij 715226026Sdelphij cmd_pkt = req->cmd_pkt; 716226026Sdelphij /* cmd_pkt->hdr.header_desc.size_header = 128; */ 717226026Sdelphij cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI; 718226026Sdelphij cmd_pkt->cmd.pkt_a.unit = ccb_h->target_id; 719226026Sdelphij cmd_pkt->cmd.pkt_a.status = 0; 720226026Sdelphij cmd_pkt->cmd.pkt_a.sgl_offset = 16; 721226026Sdelphij 722226026Sdelphij /* lower nibble */ 723226026Sdelphij lun = ccb_h->target_lun & 0XF; 724226026Sdelphij lun = lun << 12; 725226026Sdelphij cmd_pkt->cmd.pkt_a.lun_l4__req_id = lun | req->request_id; 726226026Sdelphij /* upper nibble */ 727226026Sdelphij lun = ccb_h->target_lun & 0XF0; 728226026Sdelphij lun = lun << 8; 729226026Sdelphij cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries = lun; 730226026Sdelphij 731226026Sdelphij#ifdef TWS_DEBUG 732226026Sdelphij if ( csio->cdb_len > 16 ) 733226026Sdelphij TWS_TRACE(sc, "cdb len too big", ccb_h->target_id, csio->cdb_len); 734226026Sdelphij#endif 735226026Sdelphij 736226026Sdelphij if(ccb_h->flags & CAM_CDB_POINTER) 737226026Sdelphij bcopy(csio->cdb_io.cdb_ptr, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len); 738226026Sdelphij else 739226026Sdelphij bcopy(csio->cdb_io.cdb_bytes, cmd_pkt->cmd.pkt_a.cdb, csio->cdb_len); 740226026Sdelphij 741246713Skib req->data = ccb; 742246713Skib req->flags |= TWS_DATA_CCB; 743226026Sdelphij /* save ccb ptr */ 744226026Sdelphij req->ccb_ptr = ccb; 745226026Sdelphij /* 746226026Sdelphij * tws_map_load_data_callback will fill in the SGL, 747226026Sdelphij * and submit the I/O. 748226026Sdelphij */ 749226026Sdelphij sc->stats.scsi_ios++; 750275982Ssmh callout_reset_sbt(&req->timeout, SBT_1MS * ccb->ccb_h.timeout, 0, 751275982Ssmh tws_timeout, req, 0); 752226026Sdelphij error = tws_map_request(sc, req); 753226026Sdelphij return(error); 754226026Sdelphij} 755226026Sdelphij 756226026Sdelphij 757226026Sdelphijint 758226026Sdelphijtws_send_scsi_cmd(struct tws_softc *sc, int cmd) 759226026Sdelphij{ 760226026Sdelphij struct tws_request *req; 761226026Sdelphij struct tws_command_packet *cmd_pkt; 762226026Sdelphij int error; 763226026Sdelphij 764226026Sdelphij TWS_TRACE_DEBUG(sc, "entry",sc, cmd); 765226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_AEN_FETCH); 766226026Sdelphij 767226026Sdelphij if ( req == NULL ) 768226026Sdelphij return(ENOMEM); 769226026Sdelphij 770226026Sdelphij req->cb = tws_aen_complete; 771226026Sdelphij 772226026Sdelphij cmd_pkt = req->cmd_pkt; 773226026Sdelphij cmd_pkt->cmd.pkt_a.res__opcode = TWS_FW_CMD_EXECUTE_SCSI; 774226026Sdelphij cmd_pkt->cmd.pkt_a.status = 0; 775226026Sdelphij cmd_pkt->cmd.pkt_a.unit = 0; 776226026Sdelphij cmd_pkt->cmd.pkt_a.sgl_offset = 16; 777226026Sdelphij cmd_pkt->cmd.pkt_a.lun_l4__req_id = req->request_id; 778226026Sdelphij 779226026Sdelphij cmd_pkt->cmd.pkt_a.cdb[0] = (u_int8_t)cmd; 780226026Sdelphij cmd_pkt->cmd.pkt_a.cdb[4] = 128; 781226026Sdelphij 782226026Sdelphij req->length = TWS_SECTOR_SIZE; 783226026Sdelphij req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT); 784226026Sdelphij if ( req->data == NULL ) 785226026Sdelphij return(ENOMEM); 786226026Sdelphij bzero(req->data, TWS_SECTOR_SIZE); 787226026Sdelphij req->flags = TWS_DIR_IN; 788226026Sdelphij 789275977Ssmh callout_reset(&req->timeout, (TWS_IO_TIMEOUT * hz), tws_timeout, req); 790226026Sdelphij error = tws_map_request(sc, req); 791226026Sdelphij return(error); 792226026Sdelphij 793226026Sdelphij} 794226026Sdelphij 795226026Sdelphijint 796226026Sdelphijtws_set_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 797226026Sdelphij u_int32_t param_size, void *data) 798226026Sdelphij{ 799226026Sdelphij struct tws_request *req; 800226026Sdelphij struct tws_command_packet *cmd_pkt; 801226026Sdelphij union tws_command_giga *cmd; 802226026Sdelphij struct tws_getset_param *param; 803226026Sdelphij int error; 804226026Sdelphij 805226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_GETSET_PARAM); 806226026Sdelphij if ( req == NULL ) { 807226026Sdelphij TWS_TRACE_DEBUG(sc, "null req", 0, 0); 808226026Sdelphij return(ENOMEM); 809226026Sdelphij } 810226026Sdelphij 811226026Sdelphij req->length = TWS_SECTOR_SIZE; 812226026Sdelphij req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT); 813226026Sdelphij if ( req->data == NULL ) 814226026Sdelphij return(ENOMEM); 815226026Sdelphij bzero(req->data, TWS_SECTOR_SIZE); 816226026Sdelphij param = (struct tws_getset_param *)req->data; 817226026Sdelphij 818226026Sdelphij req->cb = tws_getset_param_complete; 819226026Sdelphij req->flags = TWS_DIR_OUT; 820226026Sdelphij cmd_pkt = req->cmd_pkt; 821226026Sdelphij 822226026Sdelphij cmd = &cmd_pkt->cmd.pkt_g; 823226026Sdelphij cmd->param.sgl_off__opcode = 824226026Sdelphij BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_SET_PARAM); 825226026Sdelphij cmd->param.request_id = (u_int8_t)req->request_id; 826226026Sdelphij cmd->param.host_id__unit = 0; 827226026Sdelphij cmd->param.param_count = 1; 828226026Sdelphij cmd->param.size = 2; /* map routine will add sgls */ 829226026Sdelphij 830226026Sdelphij /* Specify which parameter we want to set. */ 831226026Sdelphij param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR); 832226026Sdelphij param->parameter_id = (u_int8_t)(param_id); 833226026Sdelphij param->parameter_size_bytes = (u_int16_t)param_size; 834226026Sdelphij memcpy(param->data, data, param_size); 835226026Sdelphij 836275977Ssmh callout_reset(&req->timeout, (TWS_IOCTL_TIMEOUT * hz), tws_timeout, req); 837226026Sdelphij error = tws_map_request(sc, req); 838226026Sdelphij return(error); 839226026Sdelphij 840226026Sdelphij} 841226026Sdelphij 842226026Sdelphijint 843226026Sdelphijtws_get_param(struct tws_softc *sc, u_int32_t table_id, u_int32_t param_id, 844226026Sdelphij u_int32_t param_size, void *data) 845226026Sdelphij{ 846226026Sdelphij struct tws_request *req; 847226026Sdelphij struct tws_command_packet *cmd_pkt; 848226026Sdelphij union tws_command_giga *cmd; 849226026Sdelphij struct tws_getset_param *param; 850226026Sdelphij u_int16_t reqid; 851226026Sdelphij u_int64_t mfa; 852226026Sdelphij int error = SUCCESS; 853226026Sdelphij 854226026Sdelphij 855226026Sdelphij req = tws_get_request(sc, TWS_REQ_TYPE_GETSET_PARAM); 856226026Sdelphij if ( req == NULL ) { 857226026Sdelphij TWS_TRACE_DEBUG(sc, "null req", 0, 0); 858226026Sdelphij return(FAILURE); 859226026Sdelphij } 860226026Sdelphij 861226026Sdelphij req->length = TWS_SECTOR_SIZE; 862226026Sdelphij req->data = malloc(TWS_SECTOR_SIZE, M_TWS, M_NOWAIT); 863226026Sdelphij if ( req->data == NULL ) 864226026Sdelphij return(FAILURE); 865226026Sdelphij bzero(req->data, TWS_SECTOR_SIZE); 866226026Sdelphij param = (struct tws_getset_param *)req->data; 867226026Sdelphij 868226026Sdelphij req->cb = NULL; 869226026Sdelphij req->flags = TWS_DIR_IN; 870226026Sdelphij cmd_pkt = req->cmd_pkt; 871226026Sdelphij 872226026Sdelphij cmd = &cmd_pkt->cmd.pkt_g; 873226026Sdelphij cmd->param.sgl_off__opcode = 874226026Sdelphij BUILD_SGL_OFF__OPCODE(2, TWS_FW_CMD_GET_PARAM); 875226026Sdelphij cmd->param.request_id = (u_int8_t)req->request_id; 876226026Sdelphij cmd->param.host_id__unit = 0; 877226026Sdelphij cmd->param.param_count = 1; 878226026Sdelphij cmd->param.size = 2; /* map routine will add sgls */ 879226026Sdelphij 880226026Sdelphij /* Specify which parameter we want to set. */ 881226026Sdelphij param->table_id = (table_id | TWS_9K_PARAM_DESCRIPTOR); 882226026Sdelphij param->parameter_id = (u_int8_t)(param_id); 883226026Sdelphij param->parameter_size_bytes = (u_int16_t)param_size; 884226026Sdelphij 885226026Sdelphij error = tws_map_request(sc, req); 886226026Sdelphij if (!error) { 887226026Sdelphij reqid = tws_poll4_response(sc, &mfa); 888226026Sdelphij tws_unmap_request(sc, req); 889226026Sdelphij 890226026Sdelphij if ( reqid == TWS_REQ_TYPE_GETSET_PARAM ) { 891226026Sdelphij memcpy(data, param->data, param_size); 892226026Sdelphij } else { 893226026Sdelphij error = FAILURE; 894226026Sdelphij } 895226026Sdelphij } 896226026Sdelphij 897226026Sdelphij free(req->data, M_TWS); 898226026Sdelphij req->state = TWS_REQ_STATE_FREE; 899226026Sdelphij return(error); 900226026Sdelphij 901226026Sdelphij} 902226026Sdelphij 903226026Sdelphijvoid 904226026Sdelphijtws_unmap_request(struct tws_softc *sc, struct tws_request *req) 905226026Sdelphij{ 906226026Sdelphij if (req->data != NULL) { 907226026Sdelphij if ( req->flags & TWS_DIR_IN ) 908226026Sdelphij bus_dmamap_sync(sc->data_tag, req->dma_map, 909226026Sdelphij BUS_DMASYNC_POSTREAD); 910226026Sdelphij if ( req->flags & TWS_DIR_OUT ) 911226026Sdelphij bus_dmamap_sync(sc->data_tag, req->dma_map, 912226026Sdelphij BUS_DMASYNC_POSTWRITE); 913226026Sdelphij mtx_lock(&sc->io_lock); 914226026Sdelphij bus_dmamap_unload(sc->data_tag, req->dma_map); 915226026Sdelphij mtx_unlock(&sc->io_lock); 916226026Sdelphij } 917226026Sdelphij} 918226026Sdelphij 919226026Sdelphijint32_t 920226026Sdelphijtws_map_request(struct tws_softc *sc, struct tws_request *req) 921226026Sdelphij{ 922226026Sdelphij int32_t error = 0; 923226026Sdelphij 924226026Sdelphij 925226026Sdelphij /* If the command involves data, map that too. */ 926226026Sdelphij if (req->data != NULL) { 927226026Sdelphij int my_flags = ((req->type == TWS_REQ_TYPE_SCSI_IO) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); 928226026Sdelphij 929226026Sdelphij /* 930226026Sdelphij * Map the data buffer into bus space and build the SG list. 931226026Sdelphij */ 932226026Sdelphij mtx_lock(&sc->io_lock); 933246713Skib if (req->flags & TWS_DATA_CCB) 934246713Skib error = bus_dmamap_load_ccb(sc->data_tag, req->dma_map, 935246713Skib req->data, 936246713Skib tws_dmamap_data_load_cbfn, req, 937246713Skib my_flags); 938246713Skib else 939246713Skib error = bus_dmamap_load(sc->data_tag, req->dma_map, 940246713Skib req->data, req->length, 941246713Skib tws_dmamap_data_load_cbfn, req, 942246713Skib my_flags); 943226026Sdelphij mtx_unlock(&sc->io_lock); 944226026Sdelphij 945226026Sdelphij if (error == EINPROGRESS) { 946226026Sdelphij TWS_TRACE(sc, "in progress", 0, error); 947226026Sdelphij tws_freeze_simq(sc, req); 948241753Sdelphij error = 0; // EINPROGRESS is not a fatal error. 949226026Sdelphij } 950226026Sdelphij } else { /* no data involved */ 951226026Sdelphij error = tws_submit_command(sc, req); 952226026Sdelphij } 953226026Sdelphij return(error); 954226026Sdelphij} 955226026Sdelphij 956226026Sdelphij 957226026Sdelphijstatic void 958226026Sdelphijtws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs, 959226026Sdelphij int nseg, int error) 960226026Sdelphij{ 961226026Sdelphij struct tws_request *req = (struct tws_request *)arg; 962226026Sdelphij struct tws_softc *sc = req->sc; 963226026Sdelphij u_int16_t sgls = nseg; 964226026Sdelphij void *sgl_ptr; 965226026Sdelphij struct tws_cmd_generic *gcmd; 966226026Sdelphij 967226026Sdelphij 968241753Sdelphij if ( error ) { 969241753Sdelphij TWS_TRACE(sc, "SOMETHING BAD HAPPENED! error = %d\n", error, 0); 970241753Sdelphij } 971241753Sdelphij 972226026Sdelphij if ( error == EFBIG ) { 973226026Sdelphij TWS_TRACE(sc, "not enough data segs", 0, nseg); 974226026Sdelphij req->error_code = error; 975226026Sdelphij req->ccb_ptr->ccb_h.status = CAM_REQ_TOO_BIG; 976226026Sdelphij return; 977226026Sdelphij } 978226026Sdelphij 979226026Sdelphij if ( req->flags & TWS_DIR_IN ) 980226026Sdelphij bus_dmamap_sync(req->sc->data_tag, req->dma_map, 981226026Sdelphij BUS_DMASYNC_PREREAD); 982226026Sdelphij if ( req->flags & TWS_DIR_OUT ) 983226026Sdelphij bus_dmamap_sync(req->sc->data_tag, req->dma_map, 984226026Sdelphij BUS_DMASYNC_PREWRITE); 985226026Sdelphij if ( segs ) { 986226026Sdelphij if ( (req->type == TWS_REQ_TYPE_PASSTHRU && 987226026Sdelphij GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) != 988226026Sdelphij TWS_FW_CMD_EXECUTE_SCSI) || 989226026Sdelphij req->type == TWS_REQ_TYPE_GETSET_PARAM) { 990226026Sdelphij gcmd = &req->cmd_pkt->cmd.pkt_g.generic; 991226026Sdelphij sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size; 992226026Sdelphij gcmd->size += sgls * 993241753Sdelphij ((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 : 2 ); 994226026Sdelphij tws_fill_sg_list(req->sc, (void *)segs, sgl_ptr, sgls); 995226026Sdelphij 996226026Sdelphij } else { 997226026Sdelphij tws_fill_sg_list(req->sc, (void *)segs, 998241753Sdelphij (void *)&(req->cmd_pkt->cmd.pkt_a.sg_list), sgls); 999226026Sdelphij req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ; 1000226026Sdelphij } 1001226026Sdelphij } 1002226026Sdelphij 1003226026Sdelphij 1004226026Sdelphij req->error_code = tws_submit_command(req->sc, req); 1005226026Sdelphij 1006226026Sdelphij} 1007226026Sdelphij 1008226026Sdelphij 1009226026Sdelphijstatic void 1010226026Sdelphijtws_fill_sg_list(struct tws_softc *sc, void *sgl_src, void *sgl_dest, 1011226026Sdelphij u_int16_t num_sgl_entries) 1012226026Sdelphij{ 1013226026Sdelphij int i; 1014226026Sdelphij 1015226026Sdelphij if ( sc->is64bit ) { 1016226026Sdelphij struct tws_sg_desc64 *sgl_s = (struct tws_sg_desc64 *)sgl_src; 1017226026Sdelphij 1018226026Sdelphij if ( !tws_use_32bit_sgls ) { 1019226026Sdelphij struct tws_sg_desc64 *sgl_d = (struct tws_sg_desc64 *)sgl_dest; 1020226026Sdelphij if ( num_sgl_entries > TWS_MAX_64BIT_SG_ELEMENTS ) 1021226026Sdelphij TWS_TRACE(sc, "64bit sg overflow", num_sgl_entries, 0); 1022226026Sdelphij for (i = 0; i < num_sgl_entries; i++) { 1023226026Sdelphij sgl_d[i].address = sgl_s->address; 1024226026Sdelphij sgl_d[i].length = sgl_s->length; 1025226026Sdelphij sgl_d[i].flag = 0; 1026226026Sdelphij sgl_d[i].reserved = 0; 1027226026Sdelphij sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) + 1028226026Sdelphij sizeof(bus_dma_segment_t)); 1029226026Sdelphij } 1030226026Sdelphij } else { 1031226026Sdelphij struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest; 1032226026Sdelphij if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS ) 1033226026Sdelphij TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0); 1034226026Sdelphij for (i = 0; i < num_sgl_entries; i++) { 1035226026Sdelphij sgl_d[i].address = sgl_s->address; 1036226026Sdelphij sgl_d[i].length = sgl_s->length; 1037226026Sdelphij sgl_d[i].flag = 0; 1038226026Sdelphij sgl_s = (struct tws_sg_desc64 *) (((u_int8_t *)sgl_s) + 1039226026Sdelphij sizeof(bus_dma_segment_t)); 1040226026Sdelphij } 1041226026Sdelphij } 1042226026Sdelphij } else { 1043226026Sdelphij struct tws_sg_desc32 *sgl_s = (struct tws_sg_desc32 *)sgl_src; 1044226026Sdelphij struct tws_sg_desc32 *sgl_d = (struct tws_sg_desc32 *)sgl_dest; 1045226026Sdelphij 1046226026Sdelphij if ( num_sgl_entries > TWS_MAX_32BIT_SG_ELEMENTS ) 1047226026Sdelphij TWS_TRACE(sc, "32bit sg overflow", num_sgl_entries, 0); 1048226026Sdelphij 1049226026Sdelphij 1050226026Sdelphij for (i = 0; i < num_sgl_entries; i++) { 1051226026Sdelphij sgl_d[i].address = sgl_s[i].address; 1052226026Sdelphij sgl_d[i].length = sgl_s[i].length; 1053226026Sdelphij sgl_d[i].flag = 0; 1054226026Sdelphij } 1055226026Sdelphij } 1056226026Sdelphij} 1057226026Sdelphij 1058226026Sdelphij 1059226026Sdelphijvoid 1060226026Sdelphijtws_intr(void *arg) 1061226026Sdelphij{ 1062226026Sdelphij struct tws_softc *sc = (struct tws_softc *)arg; 1063226026Sdelphij u_int32_t histat=0, db=0; 1064226026Sdelphij 1065226026Sdelphij if (!(sc)) { 1066226026Sdelphij device_printf(sc->tws_dev, "null softc!!!\n"); 1067226026Sdelphij return; 1068226026Sdelphij } 1069226026Sdelphij 1070226026Sdelphij if ( tws_get_state(sc) == TWS_RESET ) { 1071226026Sdelphij return; 1072226026Sdelphij } 1073226026Sdelphij 1074226026Sdelphij if ( tws_get_state(sc) != TWS_ONLINE ) { 1075226026Sdelphij return; 1076226026Sdelphij } 1077226026Sdelphij 1078226026Sdelphij sc->stats.num_intrs++; 1079226026Sdelphij histat = tws_read_reg(sc, TWS_I2O0_HISTAT, 4); 1080226026Sdelphij if ( histat & TWS_BIT2 ) { 1081226026Sdelphij TWS_TRACE_DEBUG(sc, "door bell :)", histat, TWS_I2O0_HISTAT); 1082226026Sdelphij db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1083226026Sdelphij if ( db & TWS_BIT21 ) { 1084226026Sdelphij tws_intr_attn_error(sc); 1085226026Sdelphij return; 1086226026Sdelphij } 1087226026Sdelphij if ( db & TWS_BIT18 ) { 1088226026Sdelphij tws_intr_attn_aen(sc); 1089226026Sdelphij } 1090226026Sdelphij } 1091226026Sdelphij 1092226026Sdelphij if ( histat & TWS_BIT3 ) { 1093226026Sdelphij tws_intr_resp(sc); 1094226026Sdelphij } 1095226026Sdelphij} 1096226026Sdelphij 1097226026Sdelphijstatic void 1098226026Sdelphijtws_intr_attn_aen(struct tws_softc *sc) 1099226026Sdelphij{ 1100226026Sdelphij u_int32_t db=0; 1101226026Sdelphij 1102226026Sdelphij /* maskoff db intrs untill all the aens are fetched */ 1103226026Sdelphij /* tws_disable_db_intr(sc); */ 1104226026Sdelphij tws_fetch_aen((void *)sc); 1105226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBDBC, TWS_BIT18, 4); 1106226026Sdelphij db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1107226026Sdelphij 1108226026Sdelphij} 1109226026Sdelphij 1110226026Sdelphijstatic void 1111226026Sdelphijtws_intr_attn_error(struct tws_softc *sc) 1112226026Sdelphij{ 1113226026Sdelphij u_int32_t db=0; 1114226026Sdelphij 1115226026Sdelphij TWS_TRACE(sc, "attn error", 0, 0); 1116226026Sdelphij tws_write_reg(sc, TWS_I2O0_HOBDBC, ~0, 4); 1117226026Sdelphij db = tws_read_reg(sc, TWS_I2O0_IOBDB, 4); 1118226026Sdelphij device_printf(sc->tws_dev, "Micro controller error.\n"); 1119226026Sdelphij tws_reset(sc); 1120226026Sdelphij} 1121226026Sdelphij 1122226026Sdelphijstatic void 1123226026Sdelphijtws_intr_resp(struct tws_softc *sc) 1124226026Sdelphij{ 1125226026Sdelphij u_int16_t req_id; 1126226026Sdelphij u_int64_t mfa; 1127226026Sdelphij 1128226026Sdelphij while ( tws_get_response(sc, &req_id, &mfa) ) { 1129226026Sdelphij sc->stats.reqs_out++; 1130226026Sdelphij if ( req_id == TWS_INVALID_REQID ) { 1131226026Sdelphij TWS_TRACE_DEBUG(sc, "invalid req_id", mfa, req_id); 1132226026Sdelphij sc->stats.reqs_errored++; 1133226026Sdelphij tws_err_complete(sc, mfa); 1134226026Sdelphij continue; 1135226026Sdelphij } 1136226026Sdelphij sc->reqs[req_id].cb(&sc->reqs[req_id]); 1137226026Sdelphij } 1138226026Sdelphij 1139226026Sdelphij} 1140226026Sdelphij 1141226026Sdelphij 1142226026Sdelphijstatic void 1143226026Sdelphijtws_poll(struct cam_sim *sim) 1144226026Sdelphij{ 1145226026Sdelphij struct tws_softc *sc = (struct tws_softc *)cam_sim_softc(sim); 1146226026Sdelphij TWS_TRACE_DEBUG(sc, "entry", 0, 0); 1147226026Sdelphij tws_intr((void *) sc); 1148226026Sdelphij} 1149226026Sdelphij 1150226026Sdelphijvoid 1151226026Sdelphijtws_timeout(void *arg) 1152226026Sdelphij{ 1153226026Sdelphij struct tws_request *req = (struct tws_request *)arg; 1154226026Sdelphij struct tws_softc *sc = req->sc; 1155226026Sdelphij 1156226026Sdelphij 1157226026Sdelphij if ( req->error_code == TWS_REQ_RET_RESET ) { 1158226026Sdelphij return; 1159226026Sdelphij } 1160226026Sdelphij 1161226026Sdelphij mtx_lock(&sc->gen_lock); 1162226026Sdelphij if ( req->error_code == TWS_REQ_RET_RESET ) { 1163226026Sdelphij mtx_unlock(&sc->gen_lock); 1164226026Sdelphij return; 1165226026Sdelphij } 1166226026Sdelphij 1167226026Sdelphij if ( tws_get_state(sc) == TWS_RESET ) { 1168226026Sdelphij mtx_unlock(&sc->gen_lock); 1169226026Sdelphij return; 1170226026Sdelphij } 1171226026Sdelphij 1172226026Sdelphij xpt_freeze_simq(sc->sim, 1); 1173226026Sdelphij 1174226026Sdelphij tws_send_event(sc, TWS_RESET_START); 1175226026Sdelphij 1176226026Sdelphij if (req->type == TWS_REQ_TYPE_SCSI_IO) { 1177226026Sdelphij device_printf(sc->tws_dev, "I/O Request timed out... Resetting controller\n"); 1178226026Sdelphij } else if (req->type == TWS_REQ_TYPE_PASSTHRU) { 1179226026Sdelphij device_printf(sc->tws_dev, "IOCTL Request timed out... Resetting controller\n"); 1180226026Sdelphij } else { 1181226026Sdelphij device_printf(sc->tws_dev, "Internal Request timed out... Resetting controller\n"); 1182226026Sdelphij } 1183226026Sdelphij 1184226026Sdelphij tws_assert_soft_reset(sc); 1185226026Sdelphij tws_turn_off_interrupts(sc); 1186226026Sdelphij tws_reset_cb( (void*) sc ); 1187226026Sdelphij tws_reinit( (void*) sc ); 1188226026Sdelphij 1189226026Sdelphij// device_printf(sc->tws_dev, "Controller Reset complete!\n"); 1190226026Sdelphij tws_send_event(sc, TWS_RESET_COMPLETE); 1191226026Sdelphij mtx_unlock(&sc->gen_lock); 1192226026Sdelphij 1193226026Sdelphij xpt_release_simq(sc->sim, 1); 1194226026Sdelphij} 1195226026Sdelphij 1196226026Sdelphijvoid 1197226026Sdelphijtws_reset(void *arg) 1198226026Sdelphij{ 1199226026Sdelphij struct tws_softc *sc = (struct tws_softc *)arg; 1200226026Sdelphij 1201226026Sdelphij mtx_lock(&sc->gen_lock); 1202226026Sdelphij if ( tws_get_state(sc) == TWS_RESET ) { 1203226026Sdelphij mtx_unlock(&sc->gen_lock); 1204226026Sdelphij return; 1205226026Sdelphij } 1206226026Sdelphij 1207226026Sdelphij xpt_freeze_simq(sc->sim, 1); 1208226026Sdelphij 1209226026Sdelphij tws_send_event(sc, TWS_RESET_START); 1210226026Sdelphij 1211226026Sdelphij device_printf(sc->tws_dev, "Resetting controller\n"); 1212226026Sdelphij 1213226026Sdelphij tws_assert_soft_reset(sc); 1214226026Sdelphij tws_turn_off_interrupts(sc); 1215226026Sdelphij tws_reset_cb( (void*) sc ); 1216226026Sdelphij tws_reinit( (void*) sc ); 1217226026Sdelphij 1218226026Sdelphij// device_printf(sc->tws_dev, "Controller Reset complete!\n"); 1219226026Sdelphij tws_send_event(sc, TWS_RESET_COMPLETE); 1220226026Sdelphij mtx_unlock(&sc->gen_lock); 1221226026Sdelphij 1222226026Sdelphij xpt_release_simq(sc->sim, 1); 1223226026Sdelphij} 1224226026Sdelphij 1225226026Sdelphijstatic void 1226226026Sdelphijtws_reset_cb(void *arg) 1227226026Sdelphij{ 1228226026Sdelphij struct tws_softc *sc = (struct tws_softc *)arg; 1229226026Sdelphij time_t endt; 1230226026Sdelphij int found = 0; 1231226026Sdelphij u_int32_t reg; 1232226026Sdelphij 1233226026Sdelphij if ( tws_get_state(sc) != TWS_RESET ) { 1234226026Sdelphij return; 1235226026Sdelphij } 1236226026Sdelphij 1237226026Sdelphij// device_printf(sc->tws_dev, "Draining Busy Queue\n"); 1238226026Sdelphij tws_drain_busy_queue(sc); 1239226026Sdelphij// device_printf(sc->tws_dev, "Draining Reserved Reqs\n"); 1240226026Sdelphij tws_drain_reserved_reqs(sc); 1241226026Sdelphij// device_printf(sc->tws_dev, "Draining Response Queue\n"); 1242226026Sdelphij tws_drain_response_queue(sc); 1243226026Sdelphij 1244226026Sdelphij// device_printf(sc->tws_dev, "Looking for controller ready flag...\n"); 1245226026Sdelphij endt = TWS_LOCAL_TIME + TWS_POLL_TIMEOUT; 1246226026Sdelphij while ((TWS_LOCAL_TIME <= endt) && (!found)) { 1247226026Sdelphij reg = tws_read_reg(sc, TWS_I2O0_SCRPD3, 4); 1248226026Sdelphij if ( reg & TWS_BIT13 ) { 1249226026Sdelphij found = 1; 1250226026Sdelphij// device_printf(sc->tws_dev, " ... Got it!\n"); 1251226026Sdelphij } 1252226026Sdelphij } 1253226026Sdelphij if ( !found ) 1254226026Sdelphij device_printf(sc->tws_dev, " ... Controller ready flag NOT found!\n"); 1255226026Sdelphij} 1256226026Sdelphij 1257226026Sdelphijstatic void 1258226026Sdelphijtws_reinit(void *arg) 1259226026Sdelphij{ 1260226026Sdelphij struct tws_softc *sc = (struct tws_softc *)arg; 1261226026Sdelphij int timeout_val=0; 1262226026Sdelphij int try=2; 1263226026Sdelphij int done=0; 1264226026Sdelphij 1265226026Sdelphij 1266226026Sdelphij// device_printf(sc->tws_dev, "Waiting for Controller Ready\n"); 1267226026Sdelphij while ( !done && try ) { 1268226026Sdelphij if ( tws_ctlr_ready(sc) ) { 1269226026Sdelphij done = 1; 1270226026Sdelphij break; 1271226026Sdelphij } else { 1272226026Sdelphij timeout_val += 5; 1273226026Sdelphij if ( timeout_val >= TWS_RESET_TIMEOUT ) { 1274226026Sdelphij timeout_val = 0; 1275226026Sdelphij if ( try ) 1276226026Sdelphij tws_assert_soft_reset(sc); 1277226026Sdelphij try--; 1278226026Sdelphij } 1279226026Sdelphij mtx_sleep(sc, &sc->gen_lock, 0, "tws_reinit", 5*hz); 1280226026Sdelphij } 1281226026Sdelphij } 1282226026Sdelphij 1283226026Sdelphij if (!done) { 1284226026Sdelphij device_printf(sc->tws_dev, "FAILED to get Controller Ready!\n"); 1285226026Sdelphij return; 1286226026Sdelphij } 1287226026Sdelphij 1288226026Sdelphij sc->obfl_q_overrun = false; 1289226026Sdelphij// device_printf(sc->tws_dev, "Sending initConnect\n"); 1290226026Sdelphij if ( tws_init_connect(sc, tws_queue_depth) ) { 1291226026Sdelphij TWS_TRACE_DEBUG(sc, "initConnect failed", 0, sc->is64bit); 1292226026Sdelphij } 1293226026Sdelphij tws_init_obfl_q(sc); 1294226026Sdelphij 1295226026Sdelphij tws_turn_on_interrupts(sc); 1296226026Sdelphij 1297263125Sdelphij wakeup_one(sc); 1298226026Sdelphij} 1299226026Sdelphij 1300226026Sdelphij 1301226026Sdelphijstatic void 1302226026Sdelphijtws_freeze_simq(struct tws_softc *sc, struct tws_request *req) 1303226026Sdelphij{ 1304226026Sdelphij /* Only for IO commands */ 1305226026Sdelphij if (req->type == TWS_REQ_TYPE_SCSI_IO) { 1306226026Sdelphij union ccb *ccb = (union ccb *)(req->ccb_ptr); 1307226026Sdelphij 1308226026Sdelphij xpt_freeze_simq(sc->sim, 1); 1309226026Sdelphij ccb->ccb_h.status |= CAM_RELEASE_SIMQ; 1310226026Sdelphij ccb->ccb_h.status |= CAM_REQUEUE_REQ; 1311226026Sdelphij } 1312226026Sdelphij} 1313226026Sdelphij 1314226026Sdelphij 1315226026SdelphijTUNABLE_INT("hw.tws.cam_depth", &tws_cam_depth); 1316