Example #1
0
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);

}
Example #2
0
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);
}
Example #3
0
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);

}
Example #4
0
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);
}
Example #5
0
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);
}