static void mfi_disk_strategy(struct bio *bio) { struct mfi_disk *sc; struct mfi_softc *controller; sc = bio->bio_disk->d_drv1; if (sc == NULL) { bio->bio_error = EINVAL; bio->bio_flags |= BIO_ERROR; bio->bio_resid = bio->bio_bcount; biodone(bio); return; } controller = sc->ld_controller; bio->bio_driver1 = (void *)(uintptr_t)sc->ld_id; /* Mark it as LD IO */ bio->bio_driver2 = (void *)MFI_LD_IO; mtx_lock(&controller->mfi_io_lock); mfi_enqueue_bio(controller, bio); mfi_startio(controller); mtx_unlock(&controller->mfi_io_lock); return; }
static int mfi_disk_strategy(struct dev_strategy_args *ap) { struct bio *bio = ap->a_bio; struct buf *bp = bio->bio_buf; struct mfi_disk *sc = ap->a_head.a_dev->si_drv1; struct mfi_softc *controller = sc->ld_controller; if (sc == NULL) { bp->b_error = EINVAL; bp->b_flags |= B_ERROR; bp->b_resid = bp->b_bcount; biodone(bio); return (0); } if (controller->hw_crit_error) { bp->b_error = EBUSY; return (0); } if (controller->issuepend_done == 0) { bp->b_error = EBUSY; return (0); } /* * XXX swildner * * If it's a null transfer, do nothing. FreeBSD's original driver * doesn't have this, but that caused hard error messages (even * though everything else continued to work fine). Interestingly, * only when HAMMER was used. * * Several others of our RAID drivers have this check, such as * aac(4) and ida(4), so we insert it here, too. * * The cause of null transfers is yet unknown. */ if (bp->b_bcount == 0) { bp->b_resid = bp->b_bcount; biodone(bio); return (0); } bio->bio_driver_info = sc; lockmgr(&controller->mfi_io_lock, LK_EXCLUSIVE); mfi_enqueue_bio(controller, bio); devstat_start_transaction(&sc->ld_devstat); mfi_startio(controller); lockmgr(&controller->mfi_io_lock, LK_RELEASE); return (0); }
static void mfip_cam_action(struct cam_sim *sim, union ccb *ccb) { struct mfip_softc *sc = cam_sim_softc(sim); struct mfi_softc *mfisc = sc->mfi_sc; mtx_assert(&mfisc->mfi_io_lock, MA_OWNED); switch (ccb->ccb_h.func_code) { case XPT_PATH_INQ: { struct ccb_pathinq *cpi = &ccb->cpi; cpi->version_num = 1; cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; cpi->target_sprt = 0; cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN; cpi->hba_eng_cnt = 0; cpi->max_target = MFI_SCSI_MAX_TARGETS; cpi->max_lun = MFI_SCSI_MAX_LUNS; cpi->initiator_id = MFI_SCSI_INITIATOR_ID; strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); strncpy(cpi->hba_vid, "LSI", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); cpi->bus_id = cam_sim_bus(sim); cpi->base_transfer_speed = 150000; cpi->transport = XPORT_SAS; cpi->transport_version = 0; cpi->protocol = PROTO_SCSI; cpi->protocol_version = SCSI_REV_2; cpi->ccb_h.status = CAM_REQ_CMP; break; } case XPT_RESET_BUS: ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_RESET_DEV: ccb->ccb_h.status = CAM_REQ_CMP; break; case XPT_GET_TRAN_SETTINGS: { struct ccb_trans_settings_sas *sas = &ccb->cts.xport_specific.sas; ccb->cts.protocol = PROTO_SCSI; ccb->cts.protocol_version = SCSI_REV_2; ccb->cts.transport = XPORT_SAS; ccb->cts.transport_version = 0; sas->valid &= ~CTS_SAS_VALID_SPEED; sas->bitrate = 150000; ccb->ccb_h.status = CAM_REQ_CMP; break; } case XPT_SET_TRAN_SETTINGS: ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; break; case XPT_SCSI_IO: { struct ccb_hdr *ccbh = &ccb->ccb_h; struct ccb_scsiio *csio = &ccb->csio; ccbh->status = CAM_REQ_INPROG; if (csio->cdb_len > MFI_SCSI_MAX_CDB_LEN) { ccbh->status = CAM_REQ_INVALID; break; } if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { if (ccbh->flags & CAM_DATA_PHYS) { ccbh->status = CAM_REQ_INVALID; break; } if (ccbh->flags & CAM_SCATTER_VALID) { ccbh->status = CAM_REQ_INVALID; break; } } ccbh->ccb_mfip_ptr = sc; TAILQ_INSERT_TAIL(&mfisc->mfi_cam_ccbq, ccbh, sim_links.tqe); mfi_startio(mfisc); return; } default: ccb->ccb_h.status = CAM_REQ_INVALID; break; } xpt_done(ccb); return; }