summaryrefslogtreecommitdiff
path: root/sys/dev/ic
diff options
context:
space:
mode:
authorMarco Peereboom <marco@cvs.openbsd.org>2006-05-17 16:00:54 +0000
committerMarco Peereboom <marco@cvs.openbsd.org>2006-05-17 16:00:54 +0000
commit5eb58755945b6184808b43291263f183fc261a28 (patch)
tree500d5285bbb59dc6f0c5eca9ebb8fee8cdfb5cca /sys/dev/ic
parentd900c06e4c4372c5c10b84a15232bb603a110ee1 (diff)
Refactor scsi path so that we can have a single sgl function for io and non-io
traffic. Redo parameters on functions that were passing too many parameters around.
Diffstat (limited to 'sys/dev/ic')
-rw-r--r--sys/dev/ic/mfi.c177
-rw-r--r--sys/dev/ic/mfivar.h14
2 files changed, 103 insertions, 88 deletions
diff --git a/sys/dev/ic/mfi.c b/sys/dev/ic/mfi.c
index 61fe8b35534..0730b058bf2 100644
--- a/sys/dev/ic/mfi.c
+++ b/sys/dev/ic/mfi.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfi.c,v 1.35 2006/05/16 23:11:48 marco Exp $ */
+/* $OpenBSD: mfi.c,v 1.36 2006/05/17 16:00:52 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -73,21 +73,21 @@ struct mfi_ccb *mfi_get_ccb(struct mfi_softc *);
void mfi_put_ccb(struct mfi_ccb *);
int mfi_init_ccb(struct mfi_softc *);
-u_int32_t mfi_read(struct mfi_softc *, bus_size_t);
-void mfi_write(struct mfi_softc *, bus_size_t, u_int32_t);
struct mfi_mem *mfi_allocmem(struct mfi_softc *, size_t);
void mfi_freemem(struct mfi_softc *, struct mfi_mem *);
+
int mfi_transition_firmware(struct mfi_softc *);
int mfi_initialize_firmware(struct mfi_softc *);
+u_int32_t mfi_read(struct mfi_softc *, bus_size_t);
+void mfi_write(struct mfi_softc *, bus_size_t, u_int32_t);
+int mfi_poll(struct mfi_ccb *);
+int mfi_despatch_cmd(struct mfi_ccb *);
-int mfi_despatch_cmd(struct mfi_softc *, struct mfi_ccb *);
-int mfi_poll(struct mfi_softc *, struct mfi_ccb *);
-int mfi_start_xs(struct mfi_softc *, struct mfi_ccb *,
- struct scsi_xfer *);
+int mfi_create_sgl(struct mfi_ccb *, int);
/* LD commands */
-int mfi_generic_scsi(struct scsi_xfer *);
-void mfi_done_generic_scsi(struct mfi_softc *, struct mfi_ccb *);
+int mfi_scsi_ld(struct mfi_ccb *, struct scsi_xfer *);
+void mfi_scsi_ld_done(struct mfi_ccb *);
#if NBIO > 0
int mfi_ioctl(struct device *, u_long, caddr_t);
@@ -134,6 +134,8 @@ mfi_put_ccb(struct mfi_ccb *ccb)
ccb->ccb_frame_size = 0;
ccb->ccb_extra_frames = 0;
ccb->ccb_sgl = NULL;
+ ccb->ccb_data = NULL;
+ ccb->ccb_len = 0;
TAILQ_INSERT_TAIL(&sc->sc_ccb_freeq, ccb, ccb_link);
splx(s);
}
@@ -381,7 +383,7 @@ mfi_initialize_firmware(struct mfi_softc *sc)
qinfo->miq_rq_entries, qinfo->miq_rq_addr_lo,
qinfo->miq_pi_addr_lo, qinfo->miq_ci_addr_lo);
- if (mfi_poll(sc, ccb)) {
+ if (mfi_poll(ccb)) {
printf("%s: mfi_initialize_firmware failed\n", DEVNAME(sc));
return (1);
}
@@ -514,29 +516,30 @@ nopcq:
}
int
-mfi_despatch_cmd(struct mfi_softc *sc, struct mfi_ccb *ccb)
+mfi_despatch_cmd(struct mfi_ccb *ccb)
{
- DNPRINTF(MFI_D_CMD, "%s: mfi_despatch_cmd\n", DEVNAME(sc));
+ DNPRINTF(MFI_D_CMD, "%s: mfi_despatch_cmd\n",
+ DEVNAME(ccb->ccb_sc));
- mfi_write(sc, MFI_IQP, htole32((ccb->ccb_pframe >> 3) |
+ mfi_write(ccb->ccb_sc, MFI_IQP, htole32((ccb->ccb_pframe >> 3) |
ccb->ccb_extra_frames));
return(0);
}
int
-mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
+mfi_poll(struct mfi_ccb *ccb)
{
struct mfi_frame_header *hdr;
int to = 0;
- DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(sc));
+ DNPRINTF(MFI_D_CMD, "%s: mfi_poll\n", DEVNAME(ccb->ccb_sc));
hdr = &ccb->ccb_frame->mfr_header;
hdr->mfh_cmd_status = 0xff;
hdr->mfh_flags |= MFI_FRAME_DONT_POST_IN_REPLY_QUEUE;
- mfi_despatch_cmd(sc, ccb);
+ mfi_despatch_cmd(ccb);
while (hdr->mfh_cmd_status == 0xff) {
delay(1000);
@@ -544,7 +547,7 @@ mfi_poll(struct mfi_softc *sc, struct mfi_ccb *ccb)
break;
}
if (hdr->mfh_cmd_status == 0xff) {
- printf("%s: timeout on ccb %d\n", DEVNAME(sc),
+ printf("%s: timeout on ccb %d\n", DEVNAME(ccb->ccb_sc),
hdr->mfh_context);
ccb->ccb_flags |= MFI_CCB_F_ERR;
return (1);
@@ -596,30 +599,25 @@ mfi_intr(void *arg)
}
void
-mfi_done_generic_scsi(struct mfi_softc *sc, struct mfi_ccb *ccb)
+mfi_scsi_ld_done(struct mfi_ccb *ccb)
{
#ifdef MFI_DEBUG
struct scsi_xfer *xs = ccb->ccb_xs;
struct scsi_link *link = xs->sc_link;
DNPRINTF(MFI_D_CMD, "%s: mfi_ld_done_inquiry: %.0x\n",
- DEVNAME(sc), link->target);
+ DEVNAME(ccb->ccb_sc), link->target);
#endif /* MFI_DEBUG */
}
int
-mfi_generic_scsi(struct scsi_xfer *xs)
+mfi_scsi_ld(struct mfi_ccb *ccb, 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_generic_scsi: %d\n",
- DEVNAME(sc), link->target);
-
- if ((ccb = mfi_get_ccb(sc)) == NULL)
- return (TRY_AGAIN_LATER);
+ DNPRINTF(MFI_D_CMD, "%s: mfi_scsi_ld: %d\n",
+ DEVNAME((struct mfi_softc *)link->adapter_softc), link->target);
pf = &ccb->ccb_frame->mfr_pass;
pf->mpf_header.mfh_cmd = MFI_CMD_LD_SCSI_IO;
@@ -636,17 +634,27 @@ mfi_generic_scsi(struct scsi_xfer *xs)
memset(pf->mpf_cdb, 0, 16);
memcpy(pf->mpf_cdb, &xs->cmdstore, xs->cmdlen);
- ccb->ccb_done = mfi_done_generic_scsi;
- ccb->ccb_xs = xs; /* XXX here or in mfi_start_xs? */
+ ccb->ccb_done = mfi_scsi_ld_done;
+ ccb->ccb_xs = xs;
ccb->ccb_frame_size = MFI_PASS_FRAME_SIZE;
ccb->ccb_sgl = &pf->mpf_sgl;
+
if (xs->flags & (SCSI_DATA_IN | SCSI_DATA_OUT))
ccb->ccb_direction = xs->flags & SCSI_DATA_IN ?
MFI_DATA_IN : MFI_DATA_OUT;
else
ccb->ccb_direction = 0;
- return (mfi_start_xs(sc, ccb, xs));
+ if (xs->data) {
+ ccb->ccb_data = xs->data;
+ ccb->ccb_len = xs->datalen;
+
+ if (mfi_create_sgl(ccb, xs->flags & SCSI_NOSLEEP) ?
+ BUS_DMA_NOWAIT : BUS_DMA_WAITOK)
+ return (1);
+ }
+
+ return (0);
}
int
@@ -666,22 +674,19 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
if (!cold) {
DNPRINTF(MFI_D_CMD, "%s: no interrupt io yet %02x\n",
DEVNAME(sc), xs->cmd->opcode);
- xs->error = XS_DRIVER_STUFFUP;
- xs->flags |= ITSDONE;
- scsi_done(xs);
- return (COMPLETE);
+ goto stuffup;
}
if (target >= MFI_MAX_LD || !sc->sc_ld[target].ld_present ||
link->lun != 0) {
DNPRINTF(MFI_D_CMD, "%s: invalid target %d\n",
DEVNAME(sc), target);
- xs->error = XS_DRIVER_STUFFUP;
- xs->flags |= ITSDONE;
- scsi_done(xs);
- return (COMPLETE);
+ goto stuffup;
}
+ if ((ccb = mfi_get_ccb(sc)) == NULL)
+ return (TRY_AGAIN_LATER);
+
xs->error = XS_NOERROR;
switch (xs->cmd->opcode) {
@@ -694,43 +699,74 @@ mfi_scsi_cmd(struct scsi_xfer *xs)
/* hand it of to the firmware and let it deal with it */
default:
- return (mfi_generic_scsi(xs));
+ if (mfi_scsi_ld(ccb, xs)) {
+ mfi_put_ccb(ccb);
+ goto stuffup;
+ }
+ break;
}
DNPRINTF(MFI_D_CMD, "%s: start io %d\n", DEVNAME(sc), target);
- return (mfi_start_xs(sc, ccb, xs));
+ if (xs->flags & SCSI_POLL) {
+ if (mfi_poll(ccb)) {
+ /* XXX check for sense in ccb->ccb_sense? */
+ printf("%s: mfi_scsi_cmd poll failed\n",
+ DEVNAME(sc));
+ mfi_put_ccb(ccb);
+ 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);
+ }
+ DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd poll complete %d\n",
+ DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs);
+
+ mfi_put_ccb(ccb);
+ return (COMPLETE);
+ }
+
+ mfi_despatch_cmd(ccb);
+
+ DNPRINTF(MFI_D_DMA, "%s: mfi_scsi_cmd queued %d\n", DEVNAME(sc),
+ ccb->ccb_dmamap->dm_nsegs);
+
+ return (SUCCESSFULLY_QUEUED);
+
+stuffup:
+ xs->error = XS_DRIVER_STUFFUP;
+ xs->flags |= ITSDONE;
+ scsi_done(xs);
+ return (COMPLETE);
}
int
-mfi_start_xs(struct mfi_softc *sc, struct mfi_ccb *ccb,
- struct scsi_xfer *xs)
+mfi_create_sgl(struct mfi_ccb *ccb, int flags)
{
+ struct mfi_softc *sc = ccb->ccb_sc;
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: %p %p %d\n", DEVNAME(sc), xs,
- xs->data, xs->datalen);
+ DNPRINTF(MFI_D_DMA, "%s: mfi_create_sgl\n", DEVNAME(sc));
- if (!xs->data)
- goto skipsgl;
+ if (!ccb->ccb_data)
+ return (1);
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);
+ ccb->ccb_data, ccb->ccb_len, NULL, flags);
if (error) {
if (error == EFBIG)
- printf("more than %d dma segs\n", sc->sc_max_sgl);
+ 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;
- xs->flags |= ITSDONE;
- scsi_done(xs);
- return (COMPLETE);
+ return (1);
}
hdr = &ccb->ccb_frame->mfr_header;
@@ -739,8 +775,8 @@ mfi_start_xs(struct mfi_softc *sc, struct mfi_ccb *ccb,
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);
- DNPRINTF(MFI_D_DMA, "%s: addr: %x len: %x\n", DEVNAME(sc),
- sgl->sg32[i].addr, sgl->sg32[i].len);
+ DNPRINTF(MFI_D_DMA, "%s: addr: %x len: %x\n",
+ DEVNAME(sc), sgl->sg32[i].addr, sgl->sg32[i].len);
}
if (ccb->ccb_direction == MFI_DATA_IN) {
@@ -768,32 +804,7 @@ mfi_start_xs(struct mfi_softc *sc, struct mfi_ccb *ccb,
ccb->ccb_dmamap->dm_nsegs,
ccb->ccb_extra_frames);
-skipsgl:
- if (xs->flags & SCSI_POLL) {
- if (mfi_poll(sc, ccb)) {
- printf("%s: mfi_poll failed\n", DEVNAME(sc));
- 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);
- }
- DNPRINTF(MFI_D_DMA, "%s: mfi_start_xs complete %d\n",
- DEVNAME(sc), ccb->ccb_dmamap->dm_nsegs);
-
- mfi_put_ccb(ccb);
- return (COMPLETE);
- }
-
- mfi_despatch_cmd(sc, ccb);
-
- DNPRINTF(MFI_D_DMA, "%s: mfi_start_xs: queued %d\n", DEVNAME(sc),
- ccb->ccb_dmamap->dm_nsegs);
-
- return (SUCCESSFULLY_QUEUED);
+ return (0);
}
int
diff --git a/sys/dev/ic/mfivar.h b/sys/dev/ic/mfivar.h
index 5f5108d1d72..a2f6e4b9ba0 100644
--- a/sys/dev/ic/mfivar.h
+++ b/sys/dev/ic/mfivar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: mfivar.h,v 1.16 2006/05/16 22:51:10 marco Exp $ */
+/* $OpenBSD: mfivar.h,v 1.17 2006/05/17 16:00:53 marco Exp $ */
/*
* Copyright (c) 2006 Marco Peereboom <marco@peereboom.us>
*
@@ -67,14 +67,18 @@ struct mfi_ccb {
union mfi_sgl *ccb_sgl;
+ /* data for sgl */
+ void *ccb_data;
+ uint32_t ccb_len;
+
uint32_t ccb_direction;
-#define MFI_DATA_IN 0
-#define MFI_DATA_OUT 1
+#define MFI_DATA_NONE 0
+#define MFI_DATA_IN 1
+#define MFI_DATA_OUT 2
struct scsi_xfer *ccb_xs;
- void (*ccb_done)(struct mfi_softc *sc,
- struct mfi_ccb *ccb);
+ void (*ccb_done)(struct mfi_ccb *);
volatile enum {
MFI_CCB_FREE,