int tws_send_generic_cmd(struct tws_softc *sc, u_int8_t opcode) { struct tws_request *req; struct tws_cmd_generic *cmd; TWS_TRACE_DEBUG(sc, "entry", sc, opcode); req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD); if ( req == NULL ) { TWS_TRACE_DEBUG(sc, "no requests", 0, 0); return(FAILURE); } cmd = &(req->cmd_pkt->cmd.pkt_g.generic); bzero(cmd, sizeof(struct tws_cmd_generic)); /* req->cmd_pkt->hdr.header_desc.size_header = 128; */ req->cb = tws_cmd_complete; cmd->sgl_off__opcode = BUILD_RES__OPCODE(0, opcode); cmd->size = 2; cmd->request_id = req->request_id; cmd->host_id__unit = 0; cmd->status = 0; cmd->flags = 0; cmd->count = 0; req->error_code = tws_submit_command(sc, req); return(SUCCESS); }
int32_t tws_map_request(struct tws_softc *sc, struct tws_request *req) { int32_t error = 0; /* If the command involves data, map that too. */ if (req->data != NULL) { /* * Map the data buffer into bus space and build the SG list. */ lockmgr(&sc->io_lock, LK_EXCLUSIVE); error = bus_dmamap_load(sc->data_tag, req->dma_map, req->data, req->length, tws_dmamap_data_load_cbfn, req, BUS_DMA_WAITOK); lockmgr(&sc->io_lock, LK_RELEASE); if (error == EINPROGRESS) { TWS_TRACE(sc, "in progress", 0, error); /* tws_freeze_simq(sc); */ error = TWS_REQ_ERR_INPROGRESS; } } else { /* no data involved */ error = tws_submit_command(sc, req); } req->error_code = error; return(error); }
static void tws_dmamap_data_load_cbfn(void *arg, bus_dma_segment_t *segs, int nseg, int error) { struct tws_request *req = (struct tws_request *)arg; struct tws_softc *sc = req->sc; u_int16_t sgls = nseg; void *sgl_ptr; struct tws_cmd_generic *gcmd; if ( error ) { TWS_TRACE(sc, "SOMETHING BAD HAPPENED! error = %d\n", error, 0); } if ( error == EFBIG ) { TWS_TRACE(sc, "not enough data segs", 0, nseg); req->error_code = error; req->ccb_ptr->ccb_h.status = CAM_REQ_TOO_BIG; return; } if ( req->flags & TWS_DIR_IN ) bus_dmamap_sync(req->sc->data_tag, req->dma_map, BUS_DMASYNC_PREREAD); if ( req->flags & TWS_DIR_OUT ) bus_dmamap_sync(req->sc->data_tag, req->dma_map, BUS_DMASYNC_PREWRITE); if ( segs ) { if ( (req->type == TWS_REQ_TYPE_PASSTHRU && GET_OPCODE(req->cmd_pkt->cmd.pkt_a.res__opcode) != TWS_FW_CMD_EXECUTE_SCSI) || req->type == TWS_REQ_TYPE_GETSET_PARAM) { gcmd = &req->cmd_pkt->cmd.pkt_g.generic; sgl_ptr = (u_int32_t *)(gcmd) + gcmd->size; gcmd->size += sgls * ((req->sc->is64bit && !tws_use_32bit_sgls) ? 4 : 2 ); tws_fill_sg_list(req->sc, (void *)segs, sgl_ptr, sgls); } else { tws_fill_sg_list(req->sc, (void *)segs, (void *)&(req->cmd_pkt->cmd.pkt_a.sg_list), sgls); req->cmd_pkt->cmd.pkt_a.lun_h4__sgl_entries |= sgls ; } } req->error_code = tws_submit_command(req->sc, req); }
int32_t tws_map_request(struct tws_softc *sc, struct tws_request *req) { int32_t error = 0; /* If the command involves data, map that too. */ if (req->data != NULL) { int my_flags = ((req->type == TWS_REQ_TYPE_SCSI_IO) ? BUS_DMA_WAITOK : BUS_DMA_NOWAIT); /* * Map the data buffer into bus space and build the SG list. */ mtx_lock(&sc->io_lock); if (req->flags & TWS_DATA_CCB) error = bus_dmamap_load_ccb(sc->data_tag, req->dma_map, req->data, tws_dmamap_data_load_cbfn, req, my_flags); else error = bus_dmamap_load(sc->data_tag, req->dma_map, req->data, req->length, tws_dmamap_data_load_cbfn, req, my_flags); mtx_unlock(&sc->io_lock); if (error == EINPROGRESS) { TWS_TRACE(sc, "in progress", 0, error); tws_freeze_simq(sc, req); error = 0; // EINPROGRESS is not a fatal error. } } else { /* no data involved */ error = tws_submit_command(sc, req); } return(error); }
int tws_init_connect(struct tws_softc *sc, u_int16_t mcreadits ) { struct tws_request *req; struct tws_cmd_init_connect *initc; u_int16_t reqid; u_int64_t mfa; TWS_TRACE_DEBUG(sc, "entry", 0, mcreadits); #if 0 req = tws_get_request(sc, TWS_REQ_TYPE_INTERNAL_CMD); #else // 0 req = &sc->reqs[TWS_REQ_TYPE_INTERNAL_CMD]; bzero(&req->cmd_pkt->cmd, sizeof(struct tws_command_apache)); req->data = NULL; req->length = 0; req->type = TWS_REQ_TYPE_INTERNAL_CMD; req->flags = TWS_DIR_UNKNOWN; req->error_code = TWS_REQ_RET_INVALID; req->cb = NULL; req->ccb_ptr = NULL; req->thandle.callout = NULL; req->next = req->prev = NULL; req->state = TWS_REQ_STATE_BUSY; #endif // 0 if ( req == NULL ) { TWS_TRACE_DEBUG(sc, "no requests", 0, 0); // device_printf(sc->tws_dev, "No requests for initConnect\n"); return(FAILURE); } tws_swap16(0xbeef); /* just for test */ tws_swap32(0xdeadbeef); /* just for test */ tws_swap64(0xdeadbeef); /* just for test */ initc = &(req->cmd_pkt->cmd.pkt_g.init_connect); /* req->cmd_pkt->hdr.header_desc.size_header = 128; */ initc->res1__opcode = BUILD_RES__OPCODE(0, TWS_FW_CMD_INIT_CONNECTION); initc->size = 6; initc->request_id = req->request_id; initc->message_credits = mcreadits; initc->features |= TWS_BIT_EXTEND; if ( sc->is64bit && !tws_use_32bit_sgls ) initc->features |= TWS_64BIT_SG_ADDRESSES; /* assuming set features is always on */ initc->size = 6; initc->fw_srl = sc->cinfo.working_srl = TWS_CURRENT_FW_SRL; initc->fw_arch_id = 0; initc->fw_branch = sc->cinfo.working_branch = 0; initc->fw_build = sc->cinfo.working_build = 0; req->error_code = tws_submit_command(sc, req); reqid = tws_poll4_response(sc, &mfa); if ( reqid != TWS_INVALID_REQID && reqid == req->request_id ) { sc->cinfo.fw_on_ctlr_srl = initc->fw_srl; sc->cinfo.fw_on_ctlr_branch = initc->fw_branch; sc->cinfo.fw_on_ctlr_build = initc->fw_build; sc->stats.reqs_out++; req->state = TWS_REQ_STATE_FREE; } else { /* * REVISIT::If init connect fails we need to reset the ctlr * and try again? */ TWS_TRACE(sc, "unexpected req_id ", reqid, 0); TWS_TRACE(sc, "INITCONNECT FAILED", reqid, 0); return(FAILURE); } return(SUCCESS); }