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;
}
Esempio n. 2
0
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);
}
Esempio n. 3
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;
}