diff options
author | Marco Peereboom <marco@cvs.openbsd.org> | 2006-05-15 23:20:58 +0000 |
---|---|---|
committer | Marco Peereboom <marco@cvs.openbsd.org> | 2006-05-15 23:20:58 +0000 |
commit | 8c2f3074e2bddb3fe5f8d874bf7413210bf7b0b4 (patch) | |
tree | 48147de6323b1829920f0ae1d452279f8f27147e /sys/dev/ic | |
parent | 4e41010bb42a7c0b1fde0a955cf4a983f908616b (diff) |
Add INQUIRY command.
Add sgl magic.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r-- | sys/dev/ic/mfi.c | 199 | ||||
-rw-r--r-- | sys/dev/ic/mfireg.h | 3 | ||||
-rw-r--r-- | sys/dev/ic/mfivar.h | 11 |
3 files changed, 197 insertions, 16 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c index bf2bb156d2c..fefd68bd9ab 100644 --- a/sys/dev/ic/mfi.c +++ b/sys/dev/ic/mfi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: mfi.c,v 1.25 2006/05/10 21:48:50 marco Exp $ */ +/* $OpenBSD: mfi.c,v 1.26 2006/05/15 23:20:56 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -85,6 +85,10 @@ int mfi_poll(struct mfi_softc *, struct mfi_ccb *); int mfi_start_xs(struct mfi_softc *, struct mfi_ccb *, struct scsi_xfer *); +/* LD commands */ +int mfi_ld_inquiry(struct scsi_xfer *); +void mfi_done_ld_inquiry(struct mfi_softc *, struct mfi_ccb *); + #if NBIO > 0 int mfi_ioctl(struct device *, u_long, caddr_t); int mfi_ioctl_inq(struct mfi_softc *, struct bioc_inq *); @@ -443,9 +447,6 @@ mfi_attach(struct mfi_softc *sc) goto noinit; } - /* enable interrupts */ - mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR); - #if NBIO > 0 if (bio_register(&sc->sc_dev, mfi_ioctl) != 0) panic("%s: controller registration failed", DEVNAME(sc)); @@ -453,8 +454,36 @@ mfi_attach(struct mfi_softc *sc) sc->sc_ioctl = mfi_ioctl; #endif /* NBIO > 0 */ + sc->sc_max_ld = MFI_MAX_LD; + + /* XXX fake one ld for now */ + sc->sc_ld_cnt = 2; + sc->sc_ld[0].ld_present = 1; + sc->sc_ld[1].ld_present = 1; + sc->sc_max_ld = 2; + + if (sc->sc_ld_cnt) + sc->sc_link.openings = sc->sc_max_cmds / sc->sc_ld_cnt; + else + sc->sc_link.openings = sc->sc_max_cmds; + + sc->sc_link.device = &mfi_dev; + sc->sc_link.adapter_softc = sc; + sc->sc_link.adapter = &mfi_switch; + sc->sc_link.adapter_target = sc->sc_max_ld; + sc->sc_link.adapter_buswidth = sc->sc_max_ld; +#if 0 + printf(", FW %s, BIOS v%s, %dMB RAM\n" + "%s: %d channels, %d %ss, %d logical drives\n", + sc->sc_fwver, sc->sc_biosver, sc->sc_memory, DEVNAME(sc), + sc->sc_channels, sc->sc_targets, p, sc->sc_ld_cnt); +#endif + config_found(&sc->sc_dev, &sc->sc_link, scsiprint); + /* enable interrupts */ + mfi_write(sc, MFI_OMSK, MFI_ENABLE_INTR); + return (0); noinit: mfi_freemem(sc, sc->sc_sense); @@ -547,6 +576,55 @@ mfi_intr(void *arg) return (claimed); } +void +mfi_done_ld_inquiry(struct mfi_softc *sc, struct mfi_ccb *ccb) +{ + struct scsi_xfer *xs = ccb->ccb_xs; + struct scsi_link *link = xs->sc_link; + + DNPRINTF(MFI_D_CMD, "%s: mfi_ld_inquiry_done: %.0x\n", + DEVNAME(sc), link->target); +} + +int +mfi_ld_inquiry(struct scsi_xfer *xs) +{ + struct scsi_link *link = xs->sc_link; + struct mfi_softc *sc = link->adapter_softc; + struct mfi_ccb *ccb; + struct mfi_pass_frame *pf; + + DNPRINTF(MFI_D_CMD, "%s: mfi_ld_inquiry: %.0x\n", + DEVNAME(sc), link->target); + + if ((ccb = mfi_get_ccb(sc)) == NULL) + return (TRY_AGAIN_LATER); + + pf = &ccb->ccb_frame->mfr_pass; + pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO; + pf->mpf_header.mfh_target_id = link->target; + pf->mpf_header.mfh_lun_id = 0; + pf->mpf_header.mfh_cdb_len = 6; + pf->mpf_header.mfh_timeout = 0; + pf->mpf_header.mfh_data_len= sizeof(struct scsi_inquiry_data); /* XXX */ + pf->mpf_header.mfh_sense_len = MFI_SENSE_SIZE; + + pf->mpf_sense_addr_hi = 0; + pf->mpf_sense_addr_lo = htole32(ccb->ccb_psense); + + memset(pf->mpf_cdb, 0, 16); + pf->mpf_cdb[0] = INQUIRY; + pf->mpf_cdb[4] = sizeof(struct scsi_inquiry_data); + + ccb->ccb_done = mfi_done_ld_inquiry; + ccb->ccb_xs = xs; /* XXX here or in mfi_start_xs? */ + ccb->ccb_sgl = &pf->mpf_sgl; + ccb->ccb_direction = MFI_DATA_IN; + ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE; + + return (mfi_start_xs(sc, ccb, xs)); +} + int mfi_scsi_cmd(struct scsi_xfer *xs) { @@ -556,13 +634,14 @@ mfi_scsi_cmd(struct scsi_xfer *xs) struct mfi_ccb *ccb; u_int8_t target = link->target; - DNPRINTF(MFI_D_CMD, "mfi_scsi_cmd\n"); + DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_cmd opcode: %.0x\n", + DEVNAME(sc), xs->cmd->opcode); /* only issue IO through this path, create seperate path for mgmt */ if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present || link->lun != 0) { - DNPRINTF(MFI_D_CMD, "%s: invalid target %d ", + DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n", DEVNAME(sc), target); xs->error = XS_DRIVER_STUFFUP; xs->flags |= ITSDONE; @@ -572,32 +651,124 @@ mfi_scsi_cmd(struct scsi_xfer *xs) xs->error = XS_NOERROR; - switch (xs->cmd->opcode) { - case READ_COMMAND: /* IO path */ + /* IO path */ + case READ_COMMAND: case READ_BIG: case WRITE_COMMAND: case WRITE_BIG: break; - default: /* the rest is a DCDB */ - break; + /* DCDB */ + case INQUIRY: + return (mfi_ld_inquiry(xs)); + /* NOTREACHED */ + + case SYNCHRONIZE_CACHE: + case TEST_UNIT_READY: + case START_STOP: +#if 0 + case VERIFY: +#endif + case PREVENT_ALLOW: + case REQUEST_SENSE: + case READ_CAPACITY: + DNPRINTF(MFI_D_CMD, "%s: not implemented yet %.0x\n", + DEVNAME(sc), xs->cmd->opcode); + xs->error = XS_DRIVER_STUFFUP; + xs->flags |= ITSDONE; + scsi_done(xs); + return (COMPLETE); + /* NOTREACHED */ + + /* illegal opcode */ + default: + bzero(&xs->sense, sizeof(xs->sense)); + xs->sense.error_code = SSD_ERRCODE_VALID | 0x70; + xs->sense.flags = SKEY_ILLEGAL_REQUEST; + xs->sense.add_sense_code = 0x20; /* invalid opcode */ + xs->error = XS_SENSE; + xs->flags |= ITSDONE; + scsi_done(xs); + return (COMPLETE); + /* NOTREACHED */ } return (mfi_start_xs(sc, ccb, xs)); } -int mfi_start_xs(struct mfi_softc *sc, struct mfi_ccb *ccb, +int +mfi_start_xs(struct mfi_softc *sc, struct mfi_ccb *ccb, struct scsi_xfer *xs) { - return (1); /* XXX not yet */ + struct mfi_frame_header *hdr; + bus_dma_segment_t *sgd; + union mfi_sgl *sgl; + int error, i; + + DNPRINTF(MFI_D_DMA, "%s: mfi_start_xs:\n", DEVNAME(sc)); + + error = bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmamap, + xs->data, xs->datalen, NULL, + (xs->flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK); + if (error) { + if (error == EFBIG) + printf("more than %d dma segs\n", sc->sc_max_sgl); + else + printf("error %d loading dma map\n", error); + + mfi_put_ccb(ccb); + xs->error = XS_DRIVER_STUFFUP; + scsi_done(xs); + return (COMPLETE); + } + + hdr = &ccb->ccb_frame->mfr_header; + sgl = ccb->ccb_sgl; + sgd = ccb->ccb_dmamap->dm_segs; + for (i = 0; i < ccb->ccb_dmamap->dm_nsegs; i++) { + sgl->sg32[i].addr = htole32(sgd[i].ds_addr); + sgl->sg32[i].len = htole32(sgd[i].ds_len); + } + + if (ccb->ccb_direction == MFI_DATA_IN) { + hdr->mfh_flags |= MFI_FRAME_DIR_READ; + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, + ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); + } else { + hdr->mfh_flags |= MFI_FRAME_DIR_WRITE; + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmamap, 0, + ccb->ccb_dmamap->dm_mapsize, BUS_DMASYNC_PREWRITE); + } + + hdr->mfh_sg_count = ccb->ccb_dmamap->dm_nsegs; + ccb->ccb_frame_size += sc->sc_frames_size * ccb->ccb_dmamap->dm_nsegs; + ccb->ccb_extra_frames = (ccb->ccb_frame_size - 1) / MFI_FRAME_SIZE; + + mfi_despatch_cmd(sc, ccb); + + if (ccb->ccb_xs->flags & SCSI_POLL) { + if (mfi_poll(sc, ccb)) { + printf("%s: mfi_poll failed\n", DEVNAME(sc)); + xs->error = XS_DRIVER_STUFFUP; + } + DNPRINTF(MFI_D_DMA, "%s: mfi_start_xs complete %d\n", + DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs); + mfi_put_ccb(ccb); + return (COMPLETE); + } + + DNPRINTF(MFI_D_DMA, "%s: mfi_start_xs: queued %d\n", DEVNAME(sc), + ccb->ccb_dmamap->dm_nsegs); + + return (SUCCESSFULLY_QUEUED); } int mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag, struct proc *p) { - struct mfi_softc *sc = (struct mfi_softc *)link->adapter_softc; + struct mfi_softc *sc = (struct mfi_softc *)link->adapter_softc; DNPRINTF(MFI_D_IOCTL, "mfi_scsi_ioctl\n"); @@ -611,7 +782,7 @@ mfi_scsi_ioctl(struct scsi_link *link, u_long cmd, caddr_t addr, int flag, int mfi_ioctl(struct device *dev, u_long cmd, caddr_t addr) { - struct mfi_softc *sc = (struct mfi_softc *)dev; + struct mfi_softc *sc = (struct mfi_softc *)dev; int error = 0; DNPRINTF(MFI_D_IOCTL, "%s: ioctl ", DEVNAME(sc)); diff --git a/sys/dev/ic/mfireg.h b/sys/dev/ic/mfireg.h index d917e22ad5b..1d4dfb3bb16 100644 --- a/sys/dev/ic/mfireg.h +++ b/sys/dev/ic/mfireg.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mfireg.h,v 1.10 2006/05/10 21:48:50 marco Exp $ */ +/* $OpenBSD: mfireg.h,v 1.11 2006/05/15 23:20:57 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -291,6 +291,7 @@ struct mfi_io_frame { union mfi_sgl mif_sgl; } __packed; +#define MFI_PASS_FRAME_SIZE 48 struct mfi_pass_frame { struct mfi_frame_header mpf_header; uint32_t mpf_sense_addr_lo; diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h index 8c0a244ee27..80c1a111202 100644 --- a/sys/dev/ic/mfivar.h +++ b/sys/dev/ic/mfivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: mfivar.h,v 1.14 2006/05/10 21:48:50 marco Exp $ */ +/* $OpenBSD: mfivar.h,v 1.15 2006/05/15 23:20:57 marco Exp $ */ /* * Copyright (c) 2006 Marco Peereboom <marco@peereboom.us> * @@ -57,6 +57,7 @@ struct mfi_ccb { union mfi_frame *ccb_frame; paddr_t ccb_pframe; + uint32_t ccb_frame_size; uint32_t ccb_extra_frames; struct mfi_sense *ccb_sense; @@ -64,6 +65,12 @@ struct mfi_ccb { bus_dmamap_t ccb_dmamap; + union mfi_sgl *ccb_sgl; + + uint32_t ccb_direction; +#define MFI_DATA_IN 0 +#define MFI_DATA_OUT 1 + struct scsi_xfer *ccb_xs; void (*ccb_done)(struct mfi_softc *sc, @@ -106,6 +113,8 @@ struct mfi_softc { /* firmware determined max and totals */ uint32_t sc_max_cmds; uint32_t sc_max_sgl; + uint32_t sc_max_ld; + uint32_t sc_ld_cnt; /* all commands */ struct mfi_ccb *sc_ccb; |