i386 isa bounce buffers by hannken@eis.cs.tu-bs.de
authorderaadt <deraadt@openbsd.org>
Tue, 28 Nov 1995 16:15:42 +0000 (16:15 +0000)
committerderaadt <deraadt@openbsd.org>
Tue, 28 Nov 1995 16:15:42 +0000 (16:15 +0000)
ultra14f does not bounce properly yet.

sys/dev/isa/aha.c
sys/dev/isa/aha1542.c
sys/dev/isa/isadma.c
sys/dev/isa/isadmavar.h
sys/dev/isa/ultra14f.c
sys/dev/isa/wd.c
sys/dev/isa/wd7000.c

index a15a51b..d516a8d 100644 (file)
@@ -1,5 +1,4 @@
 /*     $NetBSD: aha1542.c,v 1.53 1995/10/03 20:58:56 mycroft Exp $     */
-
 /*
  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
  *
@@ -50,6 +49,7 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/syslog.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/errno.h>
@@ -63,6 +63,7 @@
 #include <machine/pio.h>
 
 #include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
 #define Debugger() panic("should call debugger here (aha1542.c)")
 #endif /* ! DDB */
 
+/* XXX fixme: */
+/* on i386 at least xfers from/to user memory */
+/* cannot be serviced at interrupt time. */
+#ifdef i386
+#include <machine/vmparam.h>
+#define VOLATILE_XS(xs) \
+       ((xs)->datalen > 0 && \
+       ((vm_offset_t)((xs)->data) < VM_MIN_KERNEL_ADDRESS) && \
+       ((xs)->flags & SCSI_POLL) == 0)
+#else
+#define VOLATILE_XS(xs)        0
+#endif
+
+#undef TUNE_1542       /* if bus speed check breaks the machine, undefine it */
+
 /************************** board definitions *******************************/
 
 /*
@@ -184,7 +200,7 @@ struct aha_mbx {
 
 /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
 #define        AHA_NSEG        17      /* Number of scatter gather segments <= 16 */
-                               /* allow 64 K i/o (min) */
+                               /* allow 60 K i/o (min) */
 
 struct aha_ccb {
        u_char opcode;
@@ -207,16 +223,19 @@ struct aha_ccb {
                u_char seg_len[3];
                u_char seg_addr[3];
        } scat_gath[AHA_NSEG];
+#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
        /*----------------------------------------------------------------*/
        TAILQ_ENTRY(aha_ccb) chain;
        struct aha_ccb *nexthash;
-       long hashkey;
        struct scsi_xfer *xs;           /* the scsi_xfer for this cmd */
        int flags;
 #define CCB_FREE       0
 #define CCB_ACTIVE     1
 #define CCB_ABORTED    2
        struct aha_mbx_out *mbx;        /* pointer to mail box */
+       struct isadma_seg ccb_phys[1];  /* phys segment of this ccb */
+       struct isadma_seg data_phys[AHA_NSEG];  /* phys segments of data */
+       int data_nseg;
 };
 
 /*
@@ -302,8 +321,6 @@ struct aha_extbios {
 
 /*********************************** end of board definitions***************/
 
-#define KVTOPHYS(x)    vtophys(x)
-
 #ifdef AHADEBUG
 int    aha_debug = 1;
 #endif /*AHADEBUG */
@@ -549,7 +566,7 @@ ahaprint(aux, name)
        void *aux;
        char *name;
 {
-       if (name != NULL)       
+       if (name != NULL)
                printf("%s: scsibus ", name);
        return UNCONF;
 }
@@ -566,7 +583,7 @@ ahaattach(parent, self, aux)
        struct aha_softc *aha = (void *)self;
 
        if (ia->ia_drq != DRQUNK)
-               isa_dmacascade(ia->ia_drq);
+               isadma_cascade(ia->ia_drq);
 
        aha_init(aha);
        TAILQ_INIT(&aha->free_ccb);
@@ -727,6 +744,9 @@ aha_free_ccb(aha, ccb, flags)
 
        s = splbio();
 
+       if (ccb->ccb_phys[0].addr)
+               isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
+
        ccb->flags = CCB_FREE;
        TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
 
@@ -748,14 +768,6 @@ aha_init_ccb(aha, ccb)
        int hashnum;
 
        bzero(ccb, sizeof(struct aha_ccb));
-       /*
-        * put in the phystokv hash table
-        * Never gets taken out.
-        */
-       ccb->hashkey = KVTOPHYS(ccb);
-       hashnum = CCB_HASH(ccb->hashkey);
-       ccb->nexthash = aha->ccbhash[hashnum];
-       aha->ccbhash[hashnum] = ccb;
 }
 
 static inline void
@@ -775,10 +787,15 @@ aha_get_ccb(aha, flags)
        int flags;
 {
        struct aha_ccb *ccb;
-       int s;
+       int hashnum, mflags, 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
@@ -809,6 +826,17 @@ aha_get_ccb(aha, flags)
        aha_reset_ccb(aha, ccb);
        ccb->flags = CCB_ACTIVE;
 
+       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);
+               ccb->nexthash = aha->ccbhash[hashnum];
+               aha->ccbhash[hashnum] = ccb;
+       } else {
+               ccb->ccb_phys[0].addr = 0;
+               aha_free_ccb(aha, ccb, flags);
+               ccb = 0;
+       }
+
 out:
        splx(s);
        return (ccb);
@@ -823,14 +851,18 @@ aha_ccb_phys_kv(aha, ccb_phys)
        u_long ccb_phys;
 {
        int hashnum = CCB_HASH(ccb_phys);
-       struct aha_ccb *ccb = aha->ccbhash[hashnum];
+       struct aha_ccb *res, **ccb = &aha->ccbhash[hashnum];
 
-       while (ccb) {
-               if (ccb->hashkey == ccb_phys)
+       while (*ccb) {
+               if ((*ccb)->ccb_phys[0].addr == ccb_phys)
                        break;
-               ccb = ccb->nexthash;
+               (*ccb) = (*ccb)->nexthash;
        }
-       return ccb;
+
+       if (res = *ccb)
+               *ccb = (*ccb)->nexthash;
+
+       return res;
 }
 
 /*
@@ -874,7 +906,7 @@ aha_send_mbo(aha, cmd, ccb)
        }
 
        /* Link ccb to mbo. */
-       lto3b(KVTOPHYS(ccb), wmbo->ccb_addr);
+       lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
        ccb->mbx = wmbo;
        wmbo->cmd = cmd;
 
@@ -941,6 +973,19 @@ aha_done(aha, ccb)
                        xs->resid = 0;
        }
        xs->flags |= ITSDONE;
+
+       if (VOLATILE_XS(xs)) {
+               wakeup(ccb);
+               return;
+       }
+
+       if (ccb->data_nseg) {
+               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);
+       }
        aha_free_ccb(aha, ccb, xs->flags);
        scsi_done(xs);
 }
@@ -952,7 +997,6 @@ int
 aha_find(aha)
        struct aha_softc *aha;
 {
-       u_char ad[3];
        volatile int i, sts;
        struct aha_config conf;
        struct aha_inquire inquire;
@@ -1090,16 +1134,6 @@ noinquire:
        aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
        aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
 
-#ifdef TUNE_1542
-#error XXX Must deal with configuring the DRQ channel if we do this.
-       /*
-        * Initialize memory transfer speed
-        * Not compiled in by default because it breaks some machines
-        */
-       if (!aha_set_bus_speed(aha))
-               return EIO;
-#endif /* TUNE_1542 */
-
        return 0;
 }
 
@@ -1111,12 +1145,25 @@ aha_init(aha)
        struct aha_softc *aha;
 {
        u_char ad[3];
+       struct isadma_seg mbx_phys[1];
        int i;
 
+#ifdef TUNE_1542
        /*
-        * Initialize mail box
+        * Initialize memory transfer speed
+        * Not compiled in by default because it breaks some machines
+        */
+       if (!aha_set_bus_speed(aha))
+               panic("aha_init: cannot set bus speed");
+#endif /* TUNE_1542 */
+
+       /*
+        * Initialize mail box. This mapping will never be undone.
         */
-       lto3b(KVTOPHYS(&aha->aha_mbx), ad);
+       if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
+           mbx_phys, ISADMA_MAP_CONTIG) != 1)
+               panic("aha_init: cannot map mail box");
+       lto3b(mbx_phys[0].addr, ad);
 
        aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
            ad[0], ad[1], ad[2]);
@@ -1155,10 +1202,7 @@ aha_scsi_cmd(xs)
        struct aha_softc *aha = sc_link->adapter_softc;
        struct aha_ccb *ccb;
        struct aha_scat_gath *sg;
-       int seg;                /* scatter gather seg being worked on */
-       int thiskv;
-       u_long thisphys, nextphys;
-       int bytes_this_seg, bytes_this_page, datalen, flags;
+       int seg, datalen, flags, mflags;
        struct iovec *iovp;
        struct aha_mbx_out *mbo;
        int s;
@@ -1170,6 +1214,10 @@ 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 ((flags & (ITSDONE|INUSE)) != INUSE) {
                printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
                xs->flags &= ~ITSDONE;
@@ -1199,9 +1247,11 @@ aha_scsi_cmd(xs)
        ccb->req_sense_length = sizeof(ccb->scsi_sense);
        ccb->host_stat = 0x00;
        ccb->target_stat = 0x00;
+       ccb->data_nseg = 0;
 
        if (xs->datalen && (flags & SCSI_RESET) == 0) {
-               lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+               sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
+               lto3b((vm_offset_t)sg, ccb->data_addr);
                sg = ccb->scat_gath;
                seg = 0;
 #ifdef TFS
@@ -1227,73 +1277,25 @@ aha_scsi_cmd(xs)
                         * Set up the scatter gather block
                         */
 
-                       SC_DEBUG(sc_link, SDEV_DB4,
-                               ("%d @0x%x:- ", xs->datalen, xs->data));
-                       datalen = xs->datalen;
-                       thiskv = (int) xs->data;
-                       thisphys = KVTOPHYS(thiskv);
-
-                       while (datalen && seg < AHA_NSEG) {
-                               bytes_this_seg = 0;
-
-                               /* put in the base address */
-                               lto3b(thisphys, sg->seg_addr);
-
-                               SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
-
-                               /* do it at least once */
-                               nextphys = thisphys;
-                               while (datalen && thisphys == nextphys) {
-                                       /*
-                                        * This page is contiguous (physically)
-                                        * with the the last, just extend the
-                                        * length
-                                        */
-                                       /* check it fits on the ISA bus */
-                                       if (thisphys > 0xFFFFFF) {
-                                               printf("%s: DMA beyond"
-                                                       " end of ISA\n",
-                                                       aha->sc_dev.dv_xname);
-                                               xs->error = XS_DRIVER_STUFFUP;
-                                               aha_free_ccb(aha, ccb, flags);
-                                               return COMPLETE;
-                                       }
-                                       /** how far to the end of the page ***/
-                                       nextphys = (thisphys & ~PGOFSET) + NBPG;
-                                       bytes_this_page = nextphys - thisphys;
-                                       /**** or the data ****/
-                                       bytes_this_page = min(bytes_this_page,
-                                                             datalen);
-                                       bytes_this_seg += bytes_this_page;
-                                       datalen -= bytes_this_page;
-
-                                       /* get more ready for the next page */
-                                       thiskv = (thiskv & ~PGOFSET) + NBPG;
-                                       if (datalen)
-                                               thisphys = KVTOPHYS(thiskv);
-                               }
-                               /*
-                                * next page isn't contiguous, finish the seg
-                                */
-                               SC_DEBUGN(sc_link, SDEV_DB4,
-                                   ("(0x%x)", bytes_this_seg));
-                               lto3b(bytes_this_seg, sg->seg_len);
-                               sg++;
-                               seg++;
+                       ccb->data_nseg = isadma_map(xs->data, xs->datalen,
+                           ccb->data_phys, mflags);
+                       for (seg = 0; seg < ccb->data_nseg; seg++) {
+                               lto3b(ccb->data_phys[seg].addr,
+                                   sg[seg].seg_addr);
+                               lto3b(ccb->data_phys[seg].length,
+                                   sg[seg].seg_len);
                        }
                }
-               lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length);
-               SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
-               if (datalen) {
-                       /*
-                        * there's still data, must have run out of segs!
-                        */
-                       printf("%s: aha_scsi_cmd, more than %d dma segs\n",
-                           aha->sc_dev.dv_xname, AHA_NSEG);
+               lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
+               if (ccb->data_nseg == 0) {
+                       printf("%s: aha_scsi_cmd, cannot map\n",
+                           aha->sc_dev.dv_xname);
                        xs->error = XS_DRIVER_STUFFUP;
                        aha_free_ccb(aha, ccb, flags);
                        return COMPLETE;
-               }
+               } else if (flags & SCSI_DATA_OUT)
+                       isadma_copytobuf(xs->data, xs->datalen,
+                           ccb->data_nseg, ccb->data_phys);
        } else {                /* No data xfer, use non S/G values */
                lto3b(0, ccb->data_addr);
                lto3b(0, ccb->data_length);
@@ -1309,9 +1311,14 @@ aha_scsi_cmd(xs)
 
        s = splbio();
 
+       isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
+
        if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
                splx(s);
                xs->error = XS_DRIVER_STUFFUP;
+               if (ccb->data_nseg)
+                       isadma_unmap(xs->data, xs->datalen,
+                           ccb->data_nseg, ccb->data_phys);
                aha_free_ccb(aha, ccb, flags);
                return TRY_AGAIN_LATER;
        }
@@ -1320,6 +1327,25 @@ aha_scsi_cmd(xs)
         * Usually return SUCCESSFULLY QUEUED
         */
        SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
+
+       if (VOLATILE_XS(xs)) {
+               if (tsleep(ccb, PRIBIO, "ahawait", (xs->timeout * hz) / 1000)) {
+                       aha_timeout(ccb);
+                       tsleep(ccb, PRIBIO, "ahawait1", 2000);
+               }
+               splx(s);
+               if (ccb->data_nseg) {
+                       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);
+               }
+               aha_free_ccb(aha, ccb, xs->flags);
+               scsi_done(xs);
+               return COMPLETE;
+       }
+
        if ((flags & SCSI_POLL) == 0) {
                timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
                splx(s);
@@ -1402,19 +1428,18 @@ aha_set_bus_speed(aha)
                lastworking = speed;
        }
        if (lastworking == -1) {
-               printf("no working bus speed\n");
+               printf(" no working bus speed");
                return 0;
        }
-       printf("%d nsec ", aha_bus_speeds[lastworking].nsecs);
+       printf("%d nsec ", aha_bus_speeds[lastworking].nsecs);
        if (lastworking == 7)   /* is slowest already */
-               printf("marginal\n");
+               printf("marginal");
        else {
                lastworking++;
-               printf("ok, using %d nsec\n",
-                   aha_bus_speeds[lastworking].nsecs);
+               printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
        }
        if (!aha_bus_speed_check(aha, lastworking)) {
-               printf("test retry failed.. aborting.\n");
+               printf("test retry failed.. aborting.");
                return 0;
        }
        return 1;
@@ -1435,9 +1460,24 @@ aha_bus_speed_check(aha, speed)
        int speed;
 {
        int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
-       int loopcount;
+       int result, loopcount;
+       struct isadma_seg test_phys[1], scratch_phys[1];
        u_char ad[3];
 
+       result = 1;
+
+       if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
+           scratch_phys, ISADMA_MAP_CONTIG) != 1)
+               return 0;
+       if (isadma_map(aha_test_string, sizeof(aha_test_string), 
+           test_phys, ISADMA_MAP_CONTIG) != 1) {
+               isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
+                   1, scratch_phys);
+               return 0;
+       }
+       isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
+           1, test_phys);
+
        /*
         * Set the dma-speed
         */
@@ -1448,7 +1488,7 @@ aha_bus_speed_check(aha, speed)
         * it's address. Read it onto the board
         */
        for (loopcount = 100; loopcount; loopcount--) {
-               lto3b(KVTOPHYS(aha_test_string), ad);
+               lto3b(test_phys[0].addr, ad);
                aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
 
                /*
@@ -1456,9 +1496,13 @@ aha_bus_speed_check(aha, speed)
                 * board.
                 */
                bzero(aha_scratch_buf, 54);
+               isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
+                                1, scratch_phys);
 
-               lto3b(KVTOPHYS(aha_scratch_buf), ad);
+               lto3b(scratch_phys[0].addr, ad);
                aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
+               isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
+                                  1, scratch_phys);
 
                /*
                 * Compare the original data and the final data and return the
@@ -1466,12 +1510,19 @@ aha_bus_speed_check(aha, speed)
                 * first 54 bytes, because that's all the board copies during
                 * WRITE_FIFO and READ_FIFO.
                 */
-               if (bcmp(aha_test_string, aha_scratch_buf, 54))
-                       return 0; /* failed test */
+               if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
+                       result = 0; /* failed test */
+                       break;
+               }
        }
 
+       isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
+           1, scratch_phys);
+       isadma_unmap(aha_test_string, sizeof(aha_test_string),
+           1, test_phys);
+
        /* copy succeeded; assume speed ok */
-       return 1;
+       return result;
 }
 #endif /* TUNE_1542 */
 
index a15a51b..d516a8d 100644 (file)
@@ -1,5 +1,4 @@
 /*     $NetBSD: aha1542.c,v 1.53 1995/10/03 20:58:56 mycroft Exp $     */
-
 /*
  * Copyright (c) 1994 Charles Hannum.  All rights reserved.
  *
@@ -50,6 +49,7 @@
 
 #include <sys/types.h>
 #include <sys/param.h>
+#include <sys/syslog.h>
 #include <sys/systm.h>
 #include <sys/kernel.h>
 #include <sys/errno.h>
@@ -63,6 +63,7 @@
 #include <machine/pio.h>
 
 #include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
 
 #define Debugger() panic("should call debugger here (aha1542.c)")
 #endif /* ! DDB */
 
+/* XXX fixme: */
+/* on i386 at least xfers from/to user memory */
+/* cannot be serviced at interrupt time. */
+#ifdef i386
+#include <machine/vmparam.h>
+#define VOLATILE_XS(xs) \
+       ((xs)->datalen > 0 && \
+       ((vm_offset_t)((xs)->data) < VM_MIN_KERNEL_ADDRESS) && \
+       ((xs)->flags & SCSI_POLL) == 0)
+#else
+#define VOLATILE_XS(xs)        0
+#endif
+
+#undef TUNE_1542       /* if bus speed check breaks the machine, undefine it */
+
 /************************** board definitions *******************************/
 
 /*
@@ -184,7 +200,7 @@ struct aha_mbx {
 
 /* FOR OLD VERSIONS OF THE !%$@ this may have to be 16 (yuk) */
 #define        AHA_NSEG        17      /* Number of scatter gather segments <= 16 */
-                               /* allow 64 K i/o (min) */
+                               /* allow 60 K i/o (min) */
 
 struct aha_ccb {
        u_char opcode;
@@ -207,16 +223,19 @@ struct aha_ccb {
                u_char seg_len[3];
                u_char seg_addr[3];
        } scat_gath[AHA_NSEG];
+#define CCB_PHYS_SIZE ((int)&((struct aha_ccb *)0)->chain)
        /*----------------------------------------------------------------*/
        TAILQ_ENTRY(aha_ccb) chain;
        struct aha_ccb *nexthash;
-       long hashkey;
        struct scsi_xfer *xs;           /* the scsi_xfer for this cmd */
        int flags;
 #define CCB_FREE       0
 #define CCB_ACTIVE     1
 #define CCB_ABORTED    2
        struct aha_mbx_out *mbx;        /* pointer to mail box */
+       struct isadma_seg ccb_phys[1];  /* phys segment of this ccb */
+       struct isadma_seg data_phys[AHA_NSEG];  /* phys segments of data */
+       int data_nseg;
 };
 
 /*
@@ -302,8 +321,6 @@ struct aha_extbios {
 
 /*********************************** end of board definitions***************/
 
-#define KVTOPHYS(x)    vtophys(x)
-
 #ifdef AHADEBUG
 int    aha_debug = 1;
 #endif /*AHADEBUG */
@@ -549,7 +566,7 @@ ahaprint(aux, name)
        void *aux;
        char *name;
 {
-       if (name != NULL)       
+       if (name != NULL)
                printf("%s: scsibus ", name);
        return UNCONF;
 }
@@ -566,7 +583,7 @@ ahaattach(parent, self, aux)
        struct aha_softc *aha = (void *)self;
 
        if (ia->ia_drq != DRQUNK)
-               isa_dmacascade(ia->ia_drq);
+               isadma_cascade(ia->ia_drq);
 
        aha_init(aha);
        TAILQ_INIT(&aha->free_ccb);
@@ -727,6 +744,9 @@ aha_free_ccb(aha, ccb, flags)
 
        s = splbio();
 
+       if (ccb->ccb_phys[0].addr)
+               isadma_unmap((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
+
        ccb->flags = CCB_FREE;
        TAILQ_INSERT_HEAD(&aha->free_ccb, ccb, chain);
 
@@ -748,14 +768,6 @@ aha_init_ccb(aha, ccb)
        int hashnum;
 
        bzero(ccb, sizeof(struct aha_ccb));
-       /*
-        * put in the phystokv hash table
-        * Never gets taken out.
-        */
-       ccb->hashkey = KVTOPHYS(ccb);
-       hashnum = CCB_HASH(ccb->hashkey);
-       ccb->nexthash = aha->ccbhash[hashnum];
-       aha->ccbhash[hashnum] = ccb;
 }
 
 static inline void
@@ -775,10 +787,15 @@ aha_get_ccb(aha, flags)
        int flags;
 {
        struct aha_ccb *ccb;
-       int s;
+       int hashnum, mflags, 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
@@ -809,6 +826,17 @@ aha_get_ccb(aha, flags)
        aha_reset_ccb(aha, ccb);
        ccb->flags = CCB_ACTIVE;
 
+       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);
+               ccb->nexthash = aha->ccbhash[hashnum];
+               aha->ccbhash[hashnum] = ccb;
+       } else {
+               ccb->ccb_phys[0].addr = 0;
+               aha_free_ccb(aha, ccb, flags);
+               ccb = 0;
+       }
+
 out:
        splx(s);
        return (ccb);
@@ -823,14 +851,18 @@ aha_ccb_phys_kv(aha, ccb_phys)
        u_long ccb_phys;
 {
        int hashnum = CCB_HASH(ccb_phys);
-       struct aha_ccb *ccb = aha->ccbhash[hashnum];
+       struct aha_ccb *res, **ccb = &aha->ccbhash[hashnum];
 
-       while (ccb) {
-               if (ccb->hashkey == ccb_phys)
+       while (*ccb) {
+               if ((*ccb)->ccb_phys[0].addr == ccb_phys)
                        break;
-               ccb = ccb->nexthash;
+               (*ccb) = (*ccb)->nexthash;
        }
-       return ccb;
+
+       if (res = *ccb)
+               *ccb = (*ccb)->nexthash;
+
+       return res;
 }
 
 /*
@@ -874,7 +906,7 @@ aha_send_mbo(aha, cmd, ccb)
        }
 
        /* Link ccb to mbo. */
-       lto3b(KVTOPHYS(ccb), wmbo->ccb_addr);
+       lto3b(ccb->ccb_phys[0].addr, wmbo->ccb_addr);
        ccb->mbx = wmbo;
        wmbo->cmd = cmd;
 
@@ -941,6 +973,19 @@ aha_done(aha, ccb)
                        xs->resid = 0;
        }
        xs->flags |= ITSDONE;
+
+       if (VOLATILE_XS(xs)) {
+               wakeup(ccb);
+               return;
+       }
+
+       if (ccb->data_nseg) {
+               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);
+       }
        aha_free_ccb(aha, ccb, xs->flags);
        scsi_done(xs);
 }
@@ -952,7 +997,6 @@ int
 aha_find(aha)
        struct aha_softc *aha;
 {
-       u_char ad[3];
        volatile int i, sts;
        struct aha_config conf;
        struct aha_inquire inquire;
@@ -1090,16 +1134,6 @@ noinquire:
        aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_ON_TIME_SET, 7);
        aha_cmd(aha, 1, 0, 0, 0, AHA_BUS_OFF_TIME_SET, 4);
 
-#ifdef TUNE_1542
-#error XXX Must deal with configuring the DRQ channel if we do this.
-       /*
-        * Initialize memory transfer speed
-        * Not compiled in by default because it breaks some machines
-        */
-       if (!aha_set_bus_speed(aha))
-               return EIO;
-#endif /* TUNE_1542 */
-
        return 0;
 }
 
@@ -1111,12 +1145,25 @@ aha_init(aha)
        struct aha_softc *aha;
 {
        u_char ad[3];
+       struct isadma_seg mbx_phys[1];
        int i;
 
+#ifdef TUNE_1542
        /*
-        * Initialize mail box
+        * Initialize memory transfer speed
+        * Not compiled in by default because it breaks some machines
+        */
+       if (!aha_set_bus_speed(aha))
+               panic("aha_init: cannot set bus speed");
+#endif /* TUNE_1542 */
+
+       /*
+        * Initialize mail box. This mapping will never be undone.
         */
-       lto3b(KVTOPHYS(&aha->aha_mbx), ad);
+       if (isadma_map((caddr_t)(&aha->aha_mbx), sizeof(struct aha_mbx),
+           mbx_phys, ISADMA_MAP_CONTIG) != 1)
+               panic("aha_init: cannot map mail box");
+       lto3b(mbx_phys[0].addr, ad);
 
        aha_cmd(aha, 4, 0, 0, 0, AHA_MBX_INIT, AHA_MBX_SIZE,
            ad[0], ad[1], ad[2]);
@@ -1155,10 +1202,7 @@ aha_scsi_cmd(xs)
        struct aha_softc *aha = sc_link->adapter_softc;
        struct aha_ccb *ccb;
        struct aha_scat_gath *sg;
-       int seg;                /* scatter gather seg being worked on */
-       int thiskv;
-       u_long thisphys, nextphys;
-       int bytes_this_seg, bytes_this_page, datalen, flags;
+       int seg, datalen, flags, mflags;
        struct iovec *iovp;
        struct aha_mbx_out *mbo;
        int s;
@@ -1170,6 +1214,10 @@ 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 ((flags & (ITSDONE|INUSE)) != INUSE) {
                printf("%s: done or not in use?\n", aha->sc_dev.dv_xname);
                xs->flags &= ~ITSDONE;
@@ -1199,9 +1247,11 @@ aha_scsi_cmd(xs)
        ccb->req_sense_length = sizeof(ccb->scsi_sense);
        ccb->host_stat = 0x00;
        ccb->target_stat = 0x00;
+       ccb->data_nseg = 0;
 
        if (xs->datalen && (flags & SCSI_RESET) == 0) {
-               lto3b(KVTOPHYS(ccb->scat_gath), ccb->data_addr);
+               sg = ((struct aha_ccb *)(ccb->ccb_phys[0].addr))->scat_gath;
+               lto3b((vm_offset_t)sg, ccb->data_addr);
                sg = ccb->scat_gath;
                seg = 0;
 #ifdef TFS
@@ -1227,73 +1277,25 @@ aha_scsi_cmd(xs)
                         * Set up the scatter gather block
                         */
 
-                       SC_DEBUG(sc_link, SDEV_DB4,
-                               ("%d @0x%x:- ", xs->datalen, xs->data));
-                       datalen = xs->datalen;
-                       thiskv = (int) xs->data;
-                       thisphys = KVTOPHYS(thiskv);
-
-                       while (datalen && seg < AHA_NSEG) {
-                               bytes_this_seg = 0;
-
-                               /* put in the base address */
-                               lto3b(thisphys, sg->seg_addr);
-
-                               SC_DEBUGN(sc_link, SDEV_DB4, ("0x%x", thisphys));
-
-                               /* do it at least once */
-                               nextphys = thisphys;
-                               while (datalen && thisphys == nextphys) {
-                                       /*
-                                        * This page is contiguous (physically)
-                                        * with the the last, just extend the
-                                        * length
-                                        */
-                                       /* check it fits on the ISA bus */
-                                       if (thisphys > 0xFFFFFF) {
-                                               printf("%s: DMA beyond"
-                                                       " end of ISA\n",
-                                                       aha->sc_dev.dv_xname);
-                                               xs->error = XS_DRIVER_STUFFUP;
-                                               aha_free_ccb(aha, ccb, flags);
-                                               return COMPLETE;
-                                       }
-                                       /** how far to the end of the page ***/
-                                       nextphys = (thisphys & ~PGOFSET) + NBPG;
-                                       bytes_this_page = nextphys - thisphys;
-                                       /**** or the data ****/
-                                       bytes_this_page = min(bytes_this_page,
-                                                             datalen);
-                                       bytes_this_seg += bytes_this_page;
-                                       datalen -= bytes_this_page;
-
-                                       /* get more ready for the next page */
-                                       thiskv = (thiskv & ~PGOFSET) + NBPG;
-                                       if (datalen)
-                                               thisphys = KVTOPHYS(thiskv);
-                               }
-                               /*
-                                * next page isn't contiguous, finish the seg
-                                */
-                               SC_DEBUGN(sc_link, SDEV_DB4,
-                                   ("(0x%x)", bytes_this_seg));
-                               lto3b(bytes_this_seg, sg->seg_len);
-                               sg++;
-                               seg++;
+                       ccb->data_nseg = isadma_map(xs->data, xs->datalen,
+                           ccb->data_phys, mflags);
+                       for (seg = 0; seg < ccb->data_nseg; seg++) {
+                               lto3b(ccb->data_phys[seg].addr,
+                                   sg[seg].seg_addr);
+                               lto3b(ccb->data_phys[seg].length,
+                                   sg[seg].seg_len);
                        }
                }
-               lto3b(seg * sizeof(struct aha_scat_gath), ccb->data_length);
-               SC_DEBUGN(sc_link, SDEV_DB4, ("\n"));
-               if (datalen) {
-                       /*
-                        * there's still data, must have run out of segs!
-                        */
-                       printf("%s: aha_scsi_cmd, more than %d dma segs\n",
-                           aha->sc_dev.dv_xname, AHA_NSEG);
+               lto3b(ccb->data_nseg * sizeof(struct aha_scat_gath), ccb->data_length);
+               if (ccb->data_nseg == 0) {
+                       printf("%s: aha_scsi_cmd, cannot map\n",
+                           aha->sc_dev.dv_xname);
                        xs->error = XS_DRIVER_STUFFUP;
                        aha_free_ccb(aha, ccb, flags);
                        return COMPLETE;
-               }
+               } else if (flags & SCSI_DATA_OUT)
+                       isadma_copytobuf(xs->data, xs->datalen,
+                           ccb->data_nseg, ccb->data_phys);
        } else {                /* No data xfer, use non S/G values */
                lto3b(0, ccb->data_addr);
                lto3b(0, ccb->data_length);
@@ -1309,9 +1311,14 @@ aha_scsi_cmd(xs)
 
        s = splbio();
 
+       isadma_copytobuf((caddr_t)ccb, CCB_PHYS_SIZE, 1, ccb->ccb_phys);
+
        if (aha_send_mbo(aha, AHA_MBO_START, ccb) == NULL) {
                splx(s);
                xs->error = XS_DRIVER_STUFFUP;
+               if (ccb->data_nseg)
+                       isadma_unmap(xs->data, xs->datalen,
+                           ccb->data_nseg, ccb->data_phys);
                aha_free_ccb(aha, ccb, flags);
                return TRY_AGAIN_LATER;
        }
@@ -1320,6 +1327,25 @@ aha_scsi_cmd(xs)
         * Usually return SUCCESSFULLY QUEUED
         */
        SC_DEBUG(sc_link, SDEV_DB3, ("cmd_sent\n"));
+
+       if (VOLATILE_XS(xs)) {
+               if (tsleep(ccb, PRIBIO, "ahawait", (xs->timeout * hz) / 1000)) {
+                       aha_timeout(ccb);
+                       tsleep(ccb, PRIBIO, "ahawait1", 2000);
+               }
+               splx(s);
+               if (ccb->data_nseg) {
+                       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);
+               }
+               aha_free_ccb(aha, ccb, xs->flags);
+               scsi_done(xs);
+               return COMPLETE;
+       }
+
        if ((flags & SCSI_POLL) == 0) {
                timeout(aha_timeout, ccb, (xs->timeout * hz) / 1000);
                splx(s);
@@ -1402,19 +1428,18 @@ aha_set_bus_speed(aha)
                lastworking = speed;
        }
        if (lastworking == -1) {
-               printf("no working bus speed\n");
+               printf(" no working bus speed");
                return 0;
        }
-       printf("%d nsec ", aha_bus_speeds[lastworking].nsecs);
+       printf("%d nsec ", aha_bus_speeds[lastworking].nsecs);
        if (lastworking == 7)   /* is slowest already */
-               printf("marginal\n");
+               printf("marginal");
        else {
                lastworking++;
-               printf("ok, using %d nsec\n",
-                   aha_bus_speeds[lastworking].nsecs);
+               printf("ok, using %d nsec", aha_bus_speeds[lastworking].nsecs);
        }
        if (!aha_bus_speed_check(aha, lastworking)) {
-               printf("test retry failed.. aborting.\n");
+               printf("test retry failed.. aborting.");
                return 0;
        }
        return 1;
@@ -1435,9 +1460,24 @@ aha_bus_speed_check(aha, speed)
        int speed;
 {
        int numspeeds = sizeof(aha_bus_speeds) / sizeof(struct bus_speed);
-       int loopcount;
+       int result, loopcount;
+       struct isadma_seg test_phys[1], scratch_phys[1];
        u_char ad[3];
 
+       result = 1;
+
+       if (isadma_map(aha_scratch_buf, sizeof(aha_scratch_buf),
+           scratch_phys, ISADMA_MAP_CONTIG) != 1)
+               return 0;
+       if (isadma_map(aha_test_string, sizeof(aha_test_string), 
+           test_phys, ISADMA_MAP_CONTIG) != 1) {
+               isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
+                   1, scratch_phys);
+               return 0;
+       }
+       isadma_copytobuf(aha_test_string, sizeof(aha_test_string),
+           1, test_phys);
+
        /*
         * Set the dma-speed
         */
@@ -1448,7 +1488,7 @@ aha_bus_speed_check(aha, speed)
         * it's address. Read it onto the board
         */
        for (loopcount = 100; loopcount; loopcount--) {
-               lto3b(KVTOPHYS(aha_test_string), ad);
+               lto3b(test_phys[0].addr, ad);
                aha_cmd(aha, 3, 0, 0, 0, AHA_WRITE_FIFO, ad[0], ad[1], ad[2]);
 
                /*
@@ -1456,9 +1496,13 @@ aha_bus_speed_check(aha, speed)
                 * board.
                 */
                bzero(aha_scratch_buf, 54);
+               isadma_copytobuf(aha_scratch_buf, sizeof(aha_scratch_buf),
+                                1, scratch_phys);
 
-               lto3b(KVTOPHYS(aha_scratch_buf), ad);
+               lto3b(scratch_phys[0].addr, ad);
                aha_cmd(aha, 3, 0, 0, 0, AHA_READ_FIFO, ad[0], ad[1], ad[2]);
+               isadma_copyfrombuf(aha_scratch_buf, sizeof(aha_scratch_buf),
+                                  1, scratch_phys);
 
                /*
                 * Compare the original data and the final data and return the
@@ -1466,12 +1510,19 @@ aha_bus_speed_check(aha, speed)
                 * first 54 bytes, because that's all the board copies during
                 * WRITE_FIFO and READ_FIFO.
                 */
-               if (bcmp(aha_test_string, aha_scratch_buf, 54))
-                       return 0; /* failed test */
+               if (bcmp(aha_test_string, aha_scratch_buf, 54)) {
+                       result = 0; /* failed test */
+                       break;
+               }
        }
 
+       isadma_unmap(aha_scratch_buf, sizeof(aha_scratch_buf),
+           1, scratch_phys);
+       isadma_unmap(aha_test_string, sizeof(aha_test_string),
+           1, test_phys);
+
        /* copy succeeded; assume speed ok */
-       return 1;
+       return result;
 }
 #endif /* TUNE_1542 */
 
index bcb72cc..cb353a5 100644 (file)
 #include <dev/isa/isadmavar.h>
 #include <dev/isa/isadmareg.h>
 
-/* region of physical memory known to be contiguous */
-vm_offset_t isaphysmem;
-static caddr_t dma_bounce[8];          /* XXX */
-static char bounced[8];                /* XXX */
-#define MAXDMASZ 512           /* XXX */
+struct dma_info {
+       int flags;
+       caddr_t addr;
+       vm_size_t nbytes;
+       struct isadma_seg phys[1];
+};
+
+static struct dma_info dma_info[8];
 
 /* high byte of address is stored in this port for i-th dma channel */
 static int dmapageport[8] =
        { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a };
 
 /*
- * isa_dmacascade(): program 8237 DMA controller channel to accept
+ * isadma_cascade(): program 8237 DMA controller channel to accept
  * external dma control by a board.
  */
 void
-isa_dmacascade(chan)
+isadma_cascade(chan)
        int chan;
 {
 
 #ifdef DIAGNOSTIC
        if (chan < 0 || chan > 7)
-               panic("isa_dmacascade: impossible request"); 
+               panic("isadma_cascade: impossible request"); 
 #endif
 
        /* set dma channel mode, and set dma channel mode */
@@ -51,43 +54,47 @@ isa_dmacascade(chan)
 }
 
 /*
- * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment
+ * isadma_start(): program 8237 DMA controller channel, avoid page alignment
  * problems by using a bounce buffer.
  */
 void
-isa_dmastart(flags, addr, nbytes, chan)
-       int flags;
+isadma_start(addr, nbytes, chan, flags)
        caddr_t addr;
        vm_size_t nbytes;
        int chan;
+       int flags;
 {
-       vm_offset_t phys;
+       struct dma_info *di;
        int waport;
-       caddr_t newaddr;
+       int mflags;
+       vm_size_t size;
 
 #ifdef DIAGNOSTIC
        if (chan < 0 || chan > 7 ||
+           ((flags & ISADMA_START_READ) == 0) == ((flags & ISADMA_START_WRITE) == 0) ||
            ((chan & 4) ? (nbytes >= (1<<17) || nbytes & 1 || (u_int)addr & 1) :
            (nbytes >= (1<<16))))
-               panic("isa_dmastart: impossible request"); 
+               panic("isadma_start: impossible request"); 
 #endif
 
-       if (isa_dmarangecheck(addr, nbytes, chan)) {
-               if (dma_bounce[chan] == 0)
-                       dma_bounce[chan] =
-                           /*(caddr_t)malloc(MAXDMASZ, M_TEMP, M_WAITOK);*/
-                           (caddr_t) isaphysmem + NBPG*chan;
-               bounced[chan] = 1;
-               newaddr = dma_bounce[chan];
-               *(int *) newaddr = 0;   /* XXX */
-               /* copy bounce buffer on write */
-               if ((flags & B_READ) == 0)
-                       bcopy(addr, newaddr, nbytes);
-               addr = newaddr;
+       di = dma_info+chan;
+       if (di->flags != 0) {
+               log(LOG_ERR,"isadma_start: old request active on %d\n",chan);
+               isadma_abort(chan);
        }
 
-       /* translate to physical */
-       phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr);
+       di->flags = flags;
+       di->addr = addr;
+       di->nbytes = nbytes;
+
+       mflags = ISADMA_MAP_WAITOK | ISADMA_MAP_BOUNCE | ISADMA_MAP_CONTIG;
+       mflags |= (chan & 4) ? ISADMA_MAP_16BIT : ISADMA_MAP_8BIT;
+
+       if (isadma_map(addr, nbytes, di->phys, mflags) != 1)
+               panic("isadma_start: cannot map");
+
+       if ((flags & ISADMA_START_READ) == 0)
+               isadma_copytobuf(addr, nbytes, 1, di->phys);
 
        if ((chan & 4) == 0) {
                /*
@@ -95,7 +102,7 @@ isa_dmastart(flags, addr, nbytes, chan)
                 * byte mode channels.
                 */
                /* set dma channel mode, and reset address ff */
-               if (flags & B_READ)
+               if (flags & ISADMA_START_READ)
                        outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_WRITE);
                else
                        outb(DMA1_MODE, chan | DMA37MD_SINGLE | DMA37MD_READ);
@@ -103,9 +110,9 @@ isa_dmastart(flags, addr, nbytes, chan)
 
                /* send start address */
                waport =  DMA1_CHN(chan);
-               outb(waport, phys);
-               outb(waport, phys>>8);
-               outb(dmapageport[chan], phys>>16);
+               outb(waport, di->phys[0].addr);
+               outb(waport, di->phys[0].addr>>8);
+               outb(dmapageport[chan], di->phys[0].addr>>16);
 
                /* send count */
                outb(waport + 1, --nbytes);
@@ -119,7 +126,7 @@ isa_dmastart(flags, addr, nbytes, chan)
                 * word mode channels.
                 */
                /* set dma channel mode, and reset address ff */
-               if (flags & B_READ)
+               if (flags & ISADMA_START_READ)
                        outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_WRITE);
                else
                        outb(DMA2_MODE, (chan & 3) | DMA37MD_SINGLE | DMA37MD_READ);
@@ -127,9 +134,9 @@ isa_dmastart(flags, addr, nbytes, chan)
 
                /* send start address */
                waport = DMA2_CHN(chan & 3);
-               outb(waport, phys>>1);
-               outb(waport, phys>>9);
-               outb(dmapageport[chan], phys>>16);
+               outb(waport, di->phys[0].addr>>1);
+               outb(waport, di->phys[0].addr>>9);
+               outb(dmapageport[chan], di->phys[0].addr>>16);
 
                /* send count */
                nbytes >>= 1;
@@ -142,38 +149,50 @@ isa_dmastart(flags, addr, nbytes, chan)
 }
 
 void
-isa_dmaabort(chan)
+isadma_abort(chan)
        int chan;
 {
+       struct dma_info *di;
 
 #ifdef DIAGNOSTIC
        if (chan < 0 || chan > 7)
-               panic("isa_dmaabort: impossible request");
+               panic("isadma_abort: impossible request");
 #endif
 
-       bounced[chan] = 0;
+       di = dma_info+chan;
+       if (di->flags == 0) {
+               log(LOG_ERR,"isadma_abort: no request active on %d\n",chan);
+               return;
+       }
 
        /* mask channel */
        if ((chan & 4) == 0)
                outb(DMA1_SMSK, DMA37SM_SET | chan);
        else
                outb(DMA2_SMSK, DMA37SM_SET | (chan & 3));
+
+       isadma_unmap(di->addr, di->nbytes, 1, di->phys);
+       di->flags = 0;
 }
 
 void
-isa_dmadone(flags, addr, nbytes, chan)
-       int flags;
-       caddr_t addr;
-       vm_size_t nbytes;
+isadma_done(chan)
        int chan;
 {
+       struct dma_info *di;
        u_char tc;
 
 #ifdef DIAGNOSTIC
        if (chan < 0 || chan > 7)
-               panic("isa_dmadone: impossible request");
+               panic("isadma_done: impossible request");
 #endif
 
+       di = dma_info+chan;
+       if (di->flags == 0) {
+               log(LOG_ERR,"isadma_done: no request active on %d\n",chan);
+               return;
+       }
+
        /* check that the terminal count was reached */
        if ((chan & 4) == 0)
                tc = inb(DMA1_SR) & (1 << chan);
@@ -189,85 +208,9 @@ isa_dmadone(flags, addr, nbytes, chan)
        else
                outb(DMA2_SMSK, DMA37SM_SET | (chan & 3));
 
-       /* copy bounce buffer on read */
-       if (bounced[chan]) {
-               bcopy(dma_bounce[chan], addr, nbytes);
-               bounced[chan] = 0;
-       }
-}
+       if (di->flags & ISADMA_START_READ)
+               isadma_copyfrombuf(di->addr, di->nbytes, 1, di->phys);
 
-/*
- * Check for problems with the address range of a DMA transfer
- * (non-contiguous physical pages, outside of bus address space,
- * crossing DMA page boundaries).
- * Return true if special handling needed.
- */
-int
-isa_dmarangecheck(va, length, chan)
-       vm_offset_t va;
-       u_long length;
-       int chan;
-{
-       vm_offset_t phys, priorpage = 0, endva;
-       u_int dma_pgmsk = (chan & 4) ?  ~(128*1024-1) : ~(64*1024-1);
-
-       endva = round_page(va + length);
-       for (; va < endva ; va += NBPG) {
-               phys = trunc_page(pmap_extract(pmap_kernel(), va));
-               if (phys == 0)
-                       panic("isa_dmacheck: no physical page present");
-               if (phys >= (1<<24)) 
-                       return 1;
-               if (priorpage) {
-                       if (priorpage + NBPG != phys)
-                               return 1;
-                       /* check if crossing a DMA page boundary */
-                       if ((priorpage ^ phys) & dma_pgmsk)
-                               return 1;
-               }
-               priorpage = phys;
-       }
-       return 0;
-}
-
-/* head of queue waiting for physmem to become available */
-struct buf isa_physmemq;
-
-/* blocked waiting for resource to become free for exclusive use */
-static isaphysmemflag;
-/* if waited for and call requested when free (B_CALL) */
-static void (*isaphysmemunblock)(); /* needs to be a list */
-
-/*
- * Allocate contiguous physical memory for transfer, returning
- * a *virtual* address to region. May block waiting for resource.
- * (assumed to be called at splbio())
- */
-caddr_t
-isa_allocphysmem(caddr_t va, unsigned length, void (*func)()) {
-       
-       isaphysmemunblock = func;
-       while (isaphysmemflag & B_BUSY) {
-               isaphysmemflag |= B_WANTED;
-               sleep((caddr_t)&isaphysmemflag, PRIBIO);
-       }
-       isaphysmemflag |= B_BUSY;
-
-       return((caddr_t)isaphysmem);
-}
-
-/*
- * Free contiguous physical memory used for transfer.
- * (assumed to be called at splbio())
- */
-void
-isa_freephysmem(caddr_t va, unsigned length) {
-
-       isaphysmemflag &= ~B_BUSY;
-       if (isaphysmemflag & B_WANTED) {
-               isaphysmemflag &= B_WANTED;
-               wakeup((caddr_t)&isaphysmemflag);
-               if (isaphysmemunblock)
-                       (*isaphysmemunblock)();
-       }
+       isadma_unmap(di->addr, di->nbytes, 1, di->phys);
+       di->flags = 0;
 }
index e2c92c8..d20a6e4 100644 (file)
@@ -1,6 +1,34 @@
 /*     $NetBSD: isadmavar.h,v 1.2 1994/10/27 04:17:09 cgd Exp $        */
 
-void isa_dmacascade __P((int));
-void isa_dmastart __P((int, caddr_t, vm_size_t, int));
-void isa_dmaabort __P((int));
-void isa_dmadone __P((int, caddr_t, vm_size_t, int));
+#define ISADMA_START_READ      0x0001  /* read from device */
+#define ISADMA_START_WRITE     0x0002  /* write to device */
+
+#define        ISADMA_MAP_WAITOK       0x0001  /* OK for isadma_map to sleep */
+#define        ISADMA_MAP_BOUNCE       0x0002  /* use bounce buffer if necessary */
+#define        ISADMA_MAP_CONTIG       0x0004  /* must be physically contiguous */
+#define        ISADMA_MAP_8BIT         0x0008  /* must not cross 64k boundary */
+#define        ISADMA_MAP_16BIT        0x0010  /* must not cross 128k boundary */
+
+struct isadma_seg {            /* a physical contiguous segment */
+       vm_offset_t addr;       /* address of this segment */
+       vm_size_t length;       /* length of this segment (bytes) */
+};
+
+int isadma_map __P((caddr_t, vm_size_t, struct isadma_seg *, int));
+void isadma_unmap __P((caddr_t, vm_size_t, int, struct isadma_seg *));
+void isadma_copytobuf __P((caddr_t, vm_size_t, int, struct isadma_seg *));
+void isadma_copyfrombuf __P((caddr_t, vm_size_t, int, struct isadma_seg *));
+
+void isadma_cascade __P((int));
+void isadma_start __P((caddr_t, vm_size_t, int, int));
+void isadma_abort __P((int));
+void isadma_done __P((int));
+
+/*
+ * XXX these are needed until all drivers have been cleaned up
+ */
+#define isa_dmacascade(c)      isadma_cascade((c))
+#define isa_dmastart(f, a, s, c) \
+    isadma_start((a), (s), (c), (f)&B_READ?ISADMA_START_READ:ISADMA_START_WRITE)
+#define isa_dmaabort(c)                isadma_abort((c))
+#define isa_dmadone(a, s, c, f)        isadma_abort((c))
index 4a2cf62..849d486 100644 (file)
@@ -66,6 +66,7 @@
 #include <machine/pio.h>
 
 #include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
 
 #include <scsi/scsi_all.h>
 #include <scsi/scsiconf.h>
index 90b6f37..c9d1695 100644 (file)
@@ -55,6 +55,7 @@
 #include <machine/pio.h>
 
 #include <dev/isa/isavar.h>
+#include <dev/isa/isadmavar.h>
 #include <dev/isa/wdreg.h>
 
 #define        WAITTIME        (4 * hz)        /* time to wait for a completion */
index 97c1ebd..cd86dd0 100644 (file)
@@ -40,6 +40,7 @@
 #include <machine/cpu.h>
 #include <machine/pio.h>
 
+#include <dev/isa/isadmavar.h>
 #include <i386/isa/isa_device.h>       /* XXX BROKEN */
 
 extern int delaycount;  /* from clock setup code */