diff options
author | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2002-06-07 20:41:07 +0000 |
---|---|---|
committer | Niklas Hallqvist <niklas@cvs.openbsd.org> | 2002-06-07 20:41:07 +0000 |
commit | 098df8404a5180aada1285305c423edc7ff3dfe2 (patch) | |
tree | a5587c16a242e774a6153607e0ebefff708facba /sys/dev/isa/aha.c | |
parent | 594c5a16fc05b1707f9c41afaad2b94d539ffd5c (diff) |
bus_dma-ify, now it works again, sorry for the inconvenience
Diffstat (limited to 'sys/dev/isa/aha.c')
-rw-r--r-- | sys/dev/isa/aha.c | 224 |
1 files changed, 124 insertions, 100 deletions
diff --git a/sys/dev/isa/aha.c b/sys/dev/isa/aha.c index 2cdfb097893..2a5ac429cce 100644 --- a/sys/dev/isa/aha.c +++ b/sys/dev/isa/aha.c @@ -1,8 +1,7 @@ -/* $OpenBSD: aha.c,v 1.45 2002/06/07 01:25:07 niklas Exp $ */ +/* $OpenBSD: aha.c,v 1.46 2002/06/07 20:41:06 niklas Exp $ */ /* $NetBSD: aha.c,v 1.11 1996/05/12 23:51:23 mycroft Exp $ */ #undef AHADIAG -#define integrate /* * Copyright (c) 1994, 1996 Charles M. Hannum. All rights reserved. @@ -66,6 +65,7 @@ #include <machine/intr.h> #include <machine/pio.h> +#include <machine/bus.h> #include <scsi/scsi_all.h> #include <scsi/scsiconf.h> @@ -119,6 +119,7 @@ struct aha_softc { struct device sc_dev; struct isadev sc_id; void *sc_ih; + bus_dma_tag_t sc_dmat; int sc_iobase; int sc_irq, sc_drq; @@ -140,11 +141,11 @@ int aha_debug = 1; #endif /* AHADEBUG */ int aha_cmd(int, struct aha_softc *, int, u_char *, int, u_char *); -integrate void aha_finish_ccbs(struct aha_softc *); +void aha_finish_ccbs(struct aha_softc *); int ahaintr(void *); -integrate void aha_reset_ccb(struct aha_softc *, struct aha_ccb *); +void aha_reset_ccb(struct aha_softc *, struct aha_ccb *); void aha_free_ccb(struct aha_softc *, struct aha_ccb *); -integrate void aha_init_ccb(struct aha_softc *, struct aha_ccb *); +int aha_init_ccb(struct aha_softc *, struct aha_ccb *, int); struct aha_ccb *aha_get_ccb(struct aha_softc *, int); struct aha_ccb *aha_ccb_phys_kv(struct aha_softc *, u_long); void aha_queue_ccb(struct aha_softc *, struct aha_ccb *); @@ -253,7 +254,7 @@ aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf) if (!i) { printf("%s: aha_cmd, host not idle(0x%x)\n", name, sts); - return ENXIO; + return (ENXIO); } } /* @@ -280,7 +281,7 @@ aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf) printf("%s: aha_cmd, cmd/data port full\n", name); outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST); - return ENXIO; + return (ENXIO); } outb(iobase + AHA_CMD_PORT, *ibuf++); } @@ -300,7 +301,7 @@ aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf) printf("%s: aha_cmd, cmd/data port empty %d\n", name, ocnt); outb(iobase + AHA_CTRL_PORT, AHA_CTRL_SRST); - return ENXIO; + return (ENXIO); } *obuf++ = inb(iobase + AHA_DATA_PORT); } @@ -320,11 +321,11 @@ aha_cmd(iobase, sc, icnt, ibuf, ocnt, obuf) if (!i) { printf("%s: aha_cmd, host not finished(0x%x)\n", name, sts); - return ENXIO; + return (ENXIO); } } outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST); - return 0; + return (0); } int @@ -332,7 +333,7 @@ aha_isapnp_probe(parent, match, aux) struct device *parent; void *match, *aux; { - return 1; + return (1); } @@ -354,17 +355,17 @@ ahaprobe(parent, match, aux) for (i = 0; i < nbtports; i++) if (btports[i] == ia->ia_iobase) - return 0; + return (0); #endif /* See if there is a unit at this location. */ if (aha_find(ia, NULL, 0) != 0) - return 0; + return (0); ia->ia_msize = 0; ia->ia_iosize = 4; /* IRQ and DRQ set by aha_find(). */ - return 1; + return (1); } /* @@ -387,6 +388,7 @@ ahaattach(parent, self, aux) if (aha_find(ia, sc, isapnp) != 0) panic("ahaattach: aha_find of %s failed", self->dv_xname); sc->sc_iobase = ia->ia_iobase; + sc->sc_dmat = ia->ia_dmat; if (sc->sc_drq != DRQUNK && isapnp == 0) isadma_cascade(sc->sc_drq); @@ -414,7 +416,7 @@ ahaattach(parent, self, aux) config_found(self, &sc->sc_link, scsiprint); } -integrate void +void aha_finish_ccbs(sc) struct aha_softc *sc; { @@ -492,8 +494,8 @@ AGAIN: if ((ccb->xs->flags & SCSI_POLL) == 0) timeout_del(&ccb->xs->stimeout); - isadma_copyfrombuf((caddr_t)ccb, CCB_PHYS_SIZE, - 1, ccb->ccb_phys); + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0, + ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD); aha_done(sc, ccb); next: @@ -526,7 +528,7 @@ ahaintr(arg) */ sts = inb(iobase + AHA_INTR_PORT); if ((sts & AHA_INTR_ANYINTR) == 0) - return 0; + return (0); outb(iobase + AHA_CTRL_PORT, AHA_CTRL_IRST); #ifdef AHADIAG @@ -549,10 +551,10 @@ ahaintr(arg) if (sts & AHA_INTR_MBIF) aha_finish_ccbs(sc); - return 1; + return (1); } -integrate void +void aha_reset_ccb(sc, ccb) struct aha_softc *sc; struct aha_ccb *ccb; @@ -574,16 +576,17 @@ aha_free_ccb(sc, ccb) s = splbio(); - if (ccb->ccb_phys[0].addr) - isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + if (ccb->ccb_dmam->dm_segs[0].ds_addr != 0) + bus_dmamap_unload(sc->sc_dmat, ccb->ccb_dmam); /* remove from hash table */ - hashnum = CCB_HASH(ccb->ccb_phys[0].addr); + hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr); hashccb = &sc->sc_ccbhash[hashnum]; while (*hashccb) { - if ((*hashccb)->ccb_phys[0].addr == ccb->ccb_phys[0].addr) { + if ((*hashccb)->ccb_dmam->dm_segs[0].ds_addr == + ccb->ccb_dmam->dm_segs[0].ds_addr) { *hashccb = (*hashccb)->nexthash; break; } @@ -603,13 +606,37 @@ aha_free_ccb(sc, ccb) splx(s); } -integrate void -aha_init_ccb(sc, ccb) +int +aha_init_ccb(sc, ccb, flags) struct aha_softc *sc; struct aha_ccb *ccb; + int flags; { + int error, wait, state = 0; + bzero(ccb, sizeof(struct aha_ccb)); aha_reset_ccb(sc, ccb); + + wait = (flags & SCSI_NOSLEEP) ? BUS_DMA_NOWAIT : BUS_DMA_WAITOK; + /* Create a DMA map for the data area. */ + error = bus_dmamap_create(sc->sc_dmat, MAXPHYS, (MAXPHYS / NBPG) + 1, + MAXPHYS, 0, wait | BUS_DMA_ALLOCNOW, &ccb->dmam); + if (error) + goto fail; + state++; + + /* Create a DMA map for the command control block. */ + error = bus_dmamap_create(sc->sc_dmat, CCB_PHYS_SIZE, 1, CCB_PHYS_SIZE, + 0, wait | BUS_DMA_ALLOCNOW, &ccb->ccb_dmam); + if (error) + goto fail; + + return (0); + + fail: + if (state > 0) + bus_dmamap_destroy(sc->sc_dmat, ccb->dmam); + return (error); } /* @@ -624,15 +651,10 @@ aha_get_ccb(sc, flags) int flags; { struct aha_ccb *ccb; - int hashnum, mflags, s; + int hashnum, s; s = splbio(); - if (flags & SCSI_NOSLEEP) - mflags = ISADMA_MAP_BOUNCE; - else - mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; - /* * If we can and have to, sleep waiting for one to come free * but only if we can't allocate a new one. @@ -644,35 +666,36 @@ aha_get_ccb(sc, flags) break; } if (sc->sc_numccbs < AHA_CCB_MAX) { - ccb = (struct aha_ccb *) malloc(sizeof(struct aha_ccb), - M_TEMP, M_NOWAIT); - if (!ccb) { + MALLOC(ccb, struct aha_ccb *, sizeof *ccb, M_DEVBUF, + (flags & SCSI_NOSLEEP) ? M_NOWAIT : M_WAITOK); + if (ccb == NULL) { printf("%s: can't malloc ccb\n", sc->sc_dev.dv_xname); goto out; } - aha_init_ccb(sc, ccb); - sc->sc_numccbs++; - break; + if (aha_init_ccb(sc, ccb, flags) == 0) { + sc->sc_numccbs++; + break; + } + FREE(ccb, M_DEVBUF); + ccb = NULL; } - if ((flags & SCSI_NOSLEEP) != 0) + if (flags & SCSI_NOSLEEP) goto out; tsleep(&sc->sc_free_ccb, PRIBIO, "ahaccb", 0); } ccb->flags |= CCB_ALLOC; - if (isadma_map((caddr_t)ccb, CCB_PHYS_SIZE, ccb->ccb_phys, - mflags | ISADMA_MAP_CONTIG) == 1) { - hashnum = CCB_HASH(ccb->ccb_phys[0].addr); + if (bus_dmamap_load(sc->sc_dmat, ccb->ccb_dmam, ccb, CCB_PHYS_SIZE, + NULL, BUS_DMA_NOWAIT) != 0) { + aha_free_ccb(sc, ccb); + ccb = NULL; + } else { + hashnum = CCB_HASH(ccb->ccb_dmam->dm_segs[0].ds_addr); ccb->nexthash = sc->sc_ccbhash[hashnum]; sc->sc_ccbhash[hashnum] = ccb; - } else { - ccb->ccb_phys[0].addr = 0; - aha_free_ccb(sc, ccb); - ccb = 0; } - out: splx(s); return (ccb); @@ -690,11 +713,11 @@ aha_ccb_phys_kv(sc, ccb_phys) struct aha_ccb *ccb = sc->sc_ccbhash[hashnum]; while (ccb) { - if (ccb->ccb_phys[0].addr == ccb_phys) + if (ccb->ccb_dmam->dm_segs[0].ds_addr == ccb_phys) break; ccb = ccb->nexthash; } - return ccb; + return (ccb); } /* @@ -777,9 +800,9 @@ aha_start_ccbs(sc) #endif /* Link ccb to mbo. */ - isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, - 1, ccb->ccb_phys); - ltophys(ccb->ccb_phys[0].addr, wmbo->ccb_addr); + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0, + ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_PREWRITE); + ltophys(ccb->ccb_dmam->dm_segs[0].ds_addr, wmbo->ccb_addr); if (ccb->flags & CCB_ABORT) wmbo->cmd = AHA_MBO_ABORT; else @@ -873,12 +896,14 @@ aha_done(sc, ccb) return; } - if (ccb->data_nseg) { + if (ccb->dmam->dm_nsegs > 0) { if (xs->flags & SCSI_DATA_IN) - isadma_copyfrombuf(xs->data, xs->datalen, - ccb->data_nseg, ccb->data_phys); - isadma_unmap(xs->data, xs->datalen, - ccb->data_nseg, ccb->data_phys); + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTREAD); + if (xs->flags & SCSI_DATA_OUT) + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->sc_dmat, ccb->dmam); } aha_free_ccb(sc, ccb); scsi_done(xs); @@ -918,7 +943,7 @@ aha_find(ia, sc, isapnp) if (aha_debug) printf("aha_find: No answer from adaptec board\n"); #endif /* AHADEBUG */ - return 1; + return (1); } /* @@ -948,7 +973,7 @@ aha_find(ia, sc, isapnp) default: printf("aha_find: illegal drq setting %x\n", config.reply.chan); - return 1; + return (1); } if (isapnp) irq = ia->ia_irq; @@ -975,7 +1000,7 @@ aha_find(ia, sc, isapnp) default: printf("aha_find: illegal irq setting %x\n", config.reply.intr); - return EIO; + return (EIO); } if (isapnp) drq = ia->ia_drq; @@ -993,14 +1018,14 @@ aha_find(ia, sc, isapnp) if (ia->ia_irq == IRQUNK) ia->ia_irq = irq; else if (ia->ia_irq != irq) - return 1; + return (1); if (ia->ia_drq == DRQUNK) ia->ia_drq = drq; else if (ia->ia_drq != drq) - return 1; + return (1); } - return 0; + return (0); } /* @@ -1232,7 +1257,7 @@ aha_scsi_cmd(xs) struct aha_softc *sc = sc_link->adapter_softc; struct aha_ccb *ccb; struct aha_scat_gath *sg; - int seg, flags, mflags; + int seg, flags; #ifdef TFS struct iovec *iovp; int datalen; @@ -1246,13 +1271,9 @@ aha_scsi_cmd(xs) * then we can't allow it to sleep */ flags = xs->flags; - if (flags & SCSI_NOSLEEP) - mflags = ISADMA_MAP_BOUNCE; - else - mflags = ISADMA_MAP_BOUNCE | ISADMA_MAP_WAITOK; if ((ccb = aha_get_ccb(sc, flags)) == NULL) { xs->error = XS_DRIVER_STUFFUP; - return TRY_AGAIN_LATER; + return (TRY_AGAIN_LATER); } ccb->xs = xs; ccb->timeout = xs->timeout; @@ -1296,27 +1317,30 @@ aha_scsi_cmd(xs) /* * Set up the scatter-gather block. */ - ccb->data_nseg = isadma_map(xs->data, xs->datalen, - ccb->data_phys, mflags); - for (seg = 0; seg < ccb->data_nseg; seg++) { - ltophys(ccb->data_phys[seg].addr, + if (bus_dmamap_load(sc->sc_dmat, ccb->dmam, xs->data, + xs->datalen, NULL, BUS_DMA_NOWAIT) != 0) { + aha_free_ccb(sc, ccb); + xs->error = XS_DRIVER_STUFFUP; + return (TRY_AGAIN_LATER); + } + for (seg = 0; seg < ccb->dmam->dm_nsegs; seg++) { + ltophys(ccb->dmam->dm_segs[seg].ds_addr, sg[seg].seg_addr); - ltophys(ccb->data_phys[seg].length, + ltophys(ccb->dmam->dm_segs[seg].ds_len, sg[seg].seg_len); } } - /* end of iov/kv decision */ - if (ccb->data_nseg == 0) { - printf("%s: aha_scsi_cmd, cannot map\n", - sc->sc_dev.dv_xname); - goto bad; - } else if (flags & SCSI_DATA_OUT) - isadma_copytobuf(xs->data, xs->datalen, - ccb->data_nseg, ccb->data_phys); + if (flags & SCSI_DATA_OUT) + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, BUS_DMASYNC_PREWRITE); + if (flags & SCSI_DATA_IN) + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, BUS_DMASYNC_PREREAD); ltophys((unsigned) - ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath, + ((struct aha_ccb *)(ccb->ccb_dmam->dm_segs[0].ds_addr))-> + scat_gath, ccb->data_addr); - ltophys(ccb->data_nseg * sizeof(struct aha_scat_gath), + ltophys(ccb->dmam->dm_nsegs * sizeof(struct aha_scat_gath), ccb->data_length); } else { /* No data xfer, use non S/G values */ ltophys(0, ccb->data_addr); @@ -1345,22 +1369,26 @@ aha_scsi_cmd(xs) while ((ccb->xs->flags & ITSDONE) == 0) { tsleep(ccb, PRIBIO, "ahawait", 0); } - if (ccb->data_nseg) { + if (ccb->dmam->dm_nsegs > 0) { + if (flags & SCSI_DATA_OUT) + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, + BUS_DMASYNC_POSTWRITE); if (flags & SCSI_DATA_IN) - isadma_copyfrombuf(xs->data, xs->datalen, - ccb->data_nseg, ccb->data_phys); - isadma_unmap(xs->data, xs->datalen, - ccb->data_nseg, ccb->data_phys); + bus_dmamap_sync(sc->sc_dmat, ccb->dmam, 0, + ccb->dmam->dm_mapsize, + BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->sc_dmat, ccb->dmam); } aha_free_ccb(sc, ccb); scsi_done(xs); splx(s); - return COMPLETE; + return (COMPLETE); } splx(s); if ((flags & SCSI_POLL) == 0) - return SUCCESSFULLY_QUEUED; + return (SUCCESSFULLY_QUEUED); /* * If we can't use interrupts, poll on completion @@ -1370,12 +1398,7 @@ aha_scsi_cmd(xs) if (aha_poll(sc, xs, ccb->timeout)) aha_timeout(ccb); } - return COMPLETE; - -bad: - xs->error = XS_DRIVER_STUFFUP; - aha_free_ccb(sc, ccb); - return COMPLETE; + return (COMPLETE); } /* @@ -1398,11 +1421,11 @@ aha_poll(sc, xs, count) if (inb(iobase + AHA_INTR_PORT) & AHA_INTR_ANYINTR) ahaintr(sc); if (xs->flags & ITSDONE) - return 0; + return (0); delay(1000); /* only happens in boot so ok */ count--; } - return 1; + return (1); } void @@ -1416,7 +1439,8 @@ aha_timeout(arg) int s; s = splbio(); - isadma_copyfrombuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys); + bus_dmamap_sync(sc->sc_dmat, ccb->ccb_dmam, 0, + ccb->ccb_dmam->dm_mapsize, BUS_DMASYNC_POSTREAD); xs = ccb->xs; sc_link = xs->sc_link; sc = sc_link->adapter_softc; |