diff options
author | David Gwynne <dlg@cvs.openbsd.org> | 2006-06-30 08:29:43 +0000 |
---|---|---|
committer | David Gwynne <dlg@cvs.openbsd.org> | 2006-06-30 08:29:43 +0000 |
commit | 5386bc85c8e7b26ee9d7ad450c0ce0f66a32ac34 (patch) | |
tree | 471cbc83e44110598b63ba3a9f746fdc9ca41e28 /sys | |
parent | d6e01429cf3b55ad248d98a5de5da1041a3374f8 (diff) |
add mpi_inq. this is a custom io function that does an inquiry against
either a normal target, or against a physical disk using the raid passthru
command. it is necessary since the normal io path can only be used by the
midlayer, and only against normal targets. this will be used for ppr
against the disks in raid volumes on scsi controllers.
tested by marco@
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/ic/mpi.c | 85 |
1 files changed, 82 insertions, 3 deletions
diff --git a/sys/dev/ic/mpi.c b/sys/dev/ic/mpi.c index e48e64d8cd5..c5c22aabb1b 100644 --- a/sys/dev/ic/mpi.c +++ b/sys/dev/ic/mpi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mpi.c,v 1.50 2006/06/29 10:43:21 dlg Exp $ */ +/* $OpenBSD: mpi.c,v 1.51 2006/06/30 08:29:42 dlg Exp $ */ /* * Copyright (c) 2005, 2006 David Gwynne <dlg@openbsd.org> @@ -83,6 +83,7 @@ void mpi_fc_print(struct mpi_softc *); void mpi_run_ppr(struct mpi_softc *); int mpi_ppr(struct mpi_softc *, struct scsi_link *, int, int, int); +int mpi_inq(struct mpi_softc *, u_int16_t, int); void mpi_timeout_xs(void *); int mpi_load_xs(struct mpi_ccb *); @@ -371,7 +372,6 @@ mpi_ppr(struct mpi_softc *sc, struct scsi_link *link, int period, int offset, struct mpi_cfg_hdr hdr0, hdr1; struct mpi_cfg_spi_dev_pg0 pg0; struct mpi_cfg_spi_dev_pg1 pg1; - struct scsi_inquiry_data inqbuf; u_int32_t address; DNPRINTF(MPI_D_PPR, "%s: mpi_ppr period: %d offset: %d try: %d " @@ -477,7 +477,7 @@ mpi_ppr(struct mpi_softc *sc, struct scsi_link *link, int period, int offset, "conf: 0x%08x\n", DEVNAME(sc), pg1.req_params1, pg1.req_offset, pg1.req_period, pg1.req_params2, letoh32(pg1.configuration)); - if (scsi_inquire(link, &inqbuf, SCSI_POLL) != 0) { + if (mpi_inq(sc, link->target, 0) != 0) { DNPRINTF(MPI_D_PPR, "%s: mpi_ppr unable to do inquiry against " "target %d\n", DEVNAME(sc), link->target); return (EIO); @@ -545,6 +545,85 @@ mpi_ppr(struct mpi_softc *sc, struct scsi_link *link, int period, int offset, return (0); } +int +mpi_inq(struct mpi_softc *sc, u_int16_t target, int physdisk) +{ + struct mpi_ccb *ccb; + struct scsi_inquiry inq; + struct { + struct mpi_msg_scsi_io io; + struct mpi_sge sge; + struct scsi_inquiry_data inqbuf; + struct scsi_sense_data sense; + } __packed *bundle; + struct mpi_msg_scsi_io *io; + struct mpi_sge *sge; + u_int64_t addr; + + DNPRINTF(MPI_D_PPR, "%s: mpi_inq\n", DEVNAME(sc)); + + bzero(&inq, sizeof(inq)); + inq.opcode = INQUIRY; + + ccb = mpi_get_ccb(sc); + if (ccb == NULL) + return (1); + + ccb->ccb_done = mpi_empty_done; + + bundle = ccb->ccb_cmd; + io = &bundle->io; + sge = &bundle->sge; + + io->function = physdisk ? MPI_FUNCTION_RAID_SCSI_IO_PASSTHROUGH : + MPI_FUNCTION_SCSI_IO_REQUEST; + /* + * bus is always 0 + * io->bus = htole16(sc->sc_bus); + */ + io->target_id = target; + + io->cdb_length = sizeof(inq); + io->sense_buf_len = sizeof(struct scsi_sense_data); + io->msg_flags = MPI_SCSIIO_SENSE_BUF_ADDR_WIDTH_64; + + io->msg_context = htole32(ccb->ccb_id); + + /* + * always lun 0 + * io->lun[0] = htobe16(link->lun); + */ + + io->direction = MPI_SCSIIO_DIR_READ; + io->tagging = MPI_SCSIIO_ATTR_NO_DISCONNECT; + + bcopy(&inq, io->cdb, sizeof(inq)); + + io->data_length = htole32(sizeof(struct scsi_inquiry_data)); + + io->sense_buf_low_addr = htole32(ccb->ccb_cmd_dva + + ((u_int8_t *)&bundle->sense - (u_int8_t *)bundle)); + + sge->sg_hdr = htole32(MPI_SGE_FL_TYPE_SIMPLE | MPI_SGE_FL_SIZE_64 | + MPI_SGE_FL_LAST | MPI_SGE_FL_EOB | MPI_SGE_FL_EOL | + sizeof(inq)); + + addr = ccb->ccb_cmd_dva + + ((u_int8_t *)&bundle->inqbuf - (u_int8_t *)bundle); + sge->sg_hi_addr = htole32((u_int32_t)(addr >> 32)); + sge->sg_lo_addr = htole32((u_int32_t)addr); + + if (mpi_poll(sc, ccb, 5000) != 0) + return (1); + + if (ccb->ccb_reply != NULL) + mpi_push_reply(sc, ccb->ccb_reply_dva); + + mpi_put_ccb(sc, ccb); + + return (0); +} + void mpi_detach(struct mpi_softc *sc) { |