static int ld_twa_dobio(struct ld_twa_softc *sc, void *data, size_t datasize, daddr_t blkno, struct buf *bp) { int rv; struct twa_request *tr; struct twa_softc *twa; twa = device_private(device_parent(sc->sc_ld.sc_dv)); if ((tr = twa_get_request(twa, 0)) == NULL) { return (EAGAIN); } if (bp->b_flags & B_READ) { tr->tr_flags = TWA_CMD_DATA_OUT; } else { tr->tr_flags = TWA_CMD_DATA_IN; } tr->tr_data = data; tr->tr_length = datasize; tr->tr_cmd_pkt_type = (TWA_CMD_PKT_TYPE_9K | TWA_CMD_PKT_TYPE_EXTERNAL); tr->tr_command->cmd_hdr.header_desc.size_header = 128; tr->tr_command->command.cmd_pkt_9k.command.opcode = TWA_OP_EXECUTE_SCSI_COMMAND; tr->tr_command->command.cmd_pkt_9k.unit = sc->sc_hwunit; tr->tr_command->command.cmd_pkt_9k.request_id = tr->tr_request_id; tr->tr_command->command.cmd_pkt_9k.status = 0; tr->tr_command->command.cmd_pkt_9k.sgl_entries = 1; tr->tr_command->command.cmd_pkt_9k.sgl_offset = 16; /* offset from end of hdr = max cdb len */ ld_twa_scsicmd(sc, tr, bp); tr->tr_callback = ld_twa_handler; tr->tr_ld_sc = sc; tr->bp = bp; rv = twa_map_request(tr); return (rv); }
/* * Function name: twa_action * Description: Driver entry point for CAM's use. * * Input: sim -- sim corresponding to the ctlr * ccb -- ptr to CAM request * Output: None * Return value: None */ void twa_action(struct cam_sim *sim, union ccb *ccb) { struct twa_softc *sc = (struct twa_softc *)cam_sim_softc(sim); struct ccb_hdr *ccb_h = &(ccb->ccb_h); switch (ccb_h->func_code) { case XPT_SCSI_IO: /* SCSI I/O */ { struct twa_request *tr; if ((sc->twa_state & TWA_STATE_SIMQ_FROZEN) || ((tr = twa_get_request(sc)) == NULL)) { twa_dbg_dprint(2, sc, "simq frozen/Cannot get request pkt."); /* * Freeze the simq to maintain ccb ordering. The next * ccb that gets completed will unfreeze the simq. */ twa_disallow_new_requests(sc); ccb_h->status |= CAM_REQUEUE_REQ; xpt_done(ccb); break; } tr->tr_cmd_pkt_type |= TWA_CMD_PKT_TYPE_EXTERNAL; tr->tr_private = ccb; tr->tr_callback = twa_complete_io; if (twa_execute_scsi(tr, ccb)) twa_release_request(tr); break; } case XPT_ABORT: twa_dbg_dprint(2, sc, "Abort request"); ccb_h->status = CAM_UA_ABORT; xpt_done(ccb); break; case XPT_RESET_BUS: twa_printf(sc, "Reset Bus request from CAM...\n"); if (twa_reset(sc)) { twa_printf(sc, "Reset Bus failed!\n"); ccb_h->status = CAM_REQ_CMP_ERR; } else ccb_h->status = CAM_REQ_CMP; xpt_done(ccb); break; case XPT_SET_TRAN_SETTINGS: twa_dbg_dprint(3, sc, "XPT_SET_TRAN_SETTINGS"); /* * This command is not supported, since it's very specific * to SCSI, and we are doing ATA. */ ccb_h->status = CAM_FUNC_NOTAVAIL; xpt_done(ccb); break; case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings *cts = &ccb->cts; twa_dbg_dprint(3, sc, "XPT_GET_TRAN_SETTINGS"); cts->valid = (CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID); cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB); ccb_h->status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_CALC_GEOMETRY: { struct ccb_calc_geometry *geom; twa_dbg_dprint(3, sc, "XPT_CALC_GEOMETRY request"); geom = &ccb->ccg; if (geom->volume_size > 0x200000) /* 1 GB */ { geom->heads = 255; geom->secs_per_track = 63; } else { geom->heads = 64; geom->secs_per_track = 32; } geom->cylinders = geom->volume_size / (geom->heads * geom->secs_per_track); ccb_h->status = CAM_REQ_CMP; xpt_done(ccb); break; } case XPT_PATH_INQ: /* Path inquiry -- get twa properties */ { struct ccb_pathinq *path_inq = &ccb->cpi; twa_dbg_dprint(3, sc, "XPT_PATH_INQ request"); path_inq->version_num = 1; path_inq->hba_inquiry = 0; path_inq->target_sprt = 0; path_inq->hba_misc = 0; path_inq->hba_eng_cnt = 0; path_inq->max_target = TWA_MAX_UNITS; path_inq->max_lun = 0; path_inq->unit_number = cam_sim_unit(sim); path_inq->bus_id = cam_sim_bus(sim); path_inq->initiator_id = 12; path_inq->base_transfer_speed = 100000; strncpy(path_inq->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(path_inq->hba_vid, "3ware", HBA_IDLEN); strncpy(path_inq->dev_name, cam_sim_name(sim), DEV_IDLEN); ccb_h->status = CAM_REQ_CMP; xpt_done(ccb); break; } default: twa_dbg_dprint(3, sc, "func_code = %x", ccb_h->func_code); ccb_h->status = CAM_REQ_INVALID; xpt_done(ccb); break; } }