In message: <[EMAIL PROTECTED]>
            "M. Warner Losh" <[EMAIL PROTECTED]> writes:
: Can people test these?  I seem to have only good, well behaved fdc
: devices :-)  These patches should be considered experimental.  I've
: tried them on one machine only.

Hmmm.  Last minute changes suck.  The last patch will crash in some
cease.  This one should be a lot better.

Warner

Only in /dell/imp/FreeBSD/src/sys/dev/fdc: .#fdc.c.1.276
Only in /dell/imp/FreeBSD/src/sys/dev/fdc: CVS
Only in .: fd.c
diff -du /dell/imp/FreeBSD/src/sys/dev/fdc/fdc.c ./fdc.c
--- /dell/imp/FreeBSD/src/sys/dev/fdc/fdc.c     Mon Sep 13 00:01:47 2004
+++ ./fdc.c     Sun Sep 12 23:59:09 2004
@@ -197,9 +197,18 @@
 #define        FDCTL   7       /* Control Register (W) */
 
 /*
- * this is the secret PIO data port (offset from base)
+ * The YE-DATA PC Card floppies use PIO to read in the data rather than
+ * DMA due to the wild variability of DMA for the PC Card devices.  In
+ * addition, if we cannot setup the DMA resources for the ISA attachment,
+ * we'll use this same offset for data transfer.
+ *
+ * For this mode, offset 0 and 1 must be used to setup the transfer
+ * for this floppy.  This means they are only available on those systems
+ * that map them to the floppy drive.  Newer systems do not do this, and
+ * we should likely prohibit access to them (or disallow NODMA to be set).
  */
-#define FDC_YE_DATAPORT 6
+#define FDBCDR         0       /* And 1 */
+#define FD_YE_DATAPORT 6       /* Drive Data port */
 
 #define        FDI_DCHG        0x80    /* diskette has been changed */
                                /* requires drive and motor being selected */
@@ -337,6 +346,19 @@
        return bus_space_read_1(fdc->ctlt, fdc->ctlh, fdc->ctl_off);
 }
 
+/*
+ * Magic pseudo-DMA initialization for YE FDC. Sets count and
+ * direction.
+ */
+static void
+fdbcdr_wr(struct fdc_data *fdc, int iswrite, uint16_t count)
+{
+       bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + FDBCDR,
+           (count - 1) & 0xff);
+       bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + FDBCDR + 1,
+         ((iswrite ? 0x80 : 0) | (((count - 1) >> 8) & 0x7f)));
+}
+
 static int
 fdc_err(struct fdc_data *fdc, const char *s)
 {
@@ -634,18 +656,6 @@
 }
 
 /*
- * Magic pseudo-DMA initialization for YE FDC. Sets count and
- * direction.
- */
-#define SET_BCDR(fdc,wr,cnt,port) \
-       do { \
-       bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port,  \
-           ((cnt)-1) & 0xff);                                           \
-       bus_space_write_1(fdc->portt, fdc->porth, fdc->port_off + port + 1, \
-           ((wr ? 0x80 : 0) | ((((cnt)-1) >> 8) & 0x7f))); \
-       } while (0)
-
-/*
  * fdc_pio(): perform programmed IO read/write for YE PCMCIA floppy.
  */
 static void
@@ -660,13 +670,13 @@
        count = fdc->fd->fd_iosize;
 
        if (bp->bio_cmd == BIO_READ) {
-               SET_BCDR(fdc, 0, count, 0);
+               fdbcdr_wr(fdc, 0, count);
                bus_space_read_multi_1(fdc->portt, fdc->porth, fdc->port_off +
-                   FDC_YE_DATAPORT, cptr, count);
+                   FD_YE_DATAPORT, cptr, count);
        } else {
                bus_space_write_multi_1(fdc->portt, fdc->porth, fdc->port_off +
-                   FDC_YE_DATAPORT, cptr, count);
-               SET_BCDR(fdc, 0, count, 0);
+                   FD_YE_DATAPORT, cptr, count);
+               fdbcdr_wr(fdc, 0, count);       /* needed? */
        }
 }
 
@@ -940,7 +950,7 @@
        /* Do PIO if we have to */
        if (fdc->flags & FDC_NODMA) {
                if (bp->bio_cmd & (BIO_READ|BIO_WRITE|BIO_FMT))
-                       SET_BCDR(fdc, 1, fd->fd_iosize, 0);
+                       fdbcdr_wr(fdc, 1, fd->fd_iosize);
                if (bp->bio_cmd & (BIO_WRITE|BIO_FMT))
                        fdc_pio(fdc);
        }
@@ -1484,39 +1494,30 @@
        device_t dev;
 
        dev = fdc->fdc_dev;
-       if (fdc->fdc_intr) {
+       if (fdc->fdc_intr)
                BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq,
                    fdc->fdc_intr);
-               fdc->fdc_intr = NULL;
-       }
-       if (fdc->res_irq != 0) {
-               bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
-                                       fdc->res_irq);
+       fdc->fdc_intr = NULL;
+       if (fdc->res_irq != NULL)
                bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq,
-                                    fdc->res_irq);
-               fdc->res_irq = NULL;
-       }
-       if (fdc->res_ctl != 0) {
-               bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
-                                       fdc->res_ctl);
+                   fdc->res_irq);
+       fdc->res_irq = NULL;
+       if (fdc->res_ctl != NULL)
                bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ctl,
-                                    fdc->res_ctl);
-               fdc->res_ctl = NULL;
-       }
-       if (fdc->res_ioport != 0) {
-               bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
-                                       fdc->res_ioport);
+                   fdc->res_ctl);
+       fdc->res_ctl = NULL;
+       if (fdc->res_sts != NULL)
+               bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_sts,
+                   fdc->res_sts);
+       fdc->res_sts = NULL;
+       if (fdc->res_ioport != NULL)
                bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport,
-                                    fdc->res_ioport);
-               fdc->res_ioport = NULL;
-       }
-       if (fdc->res_drq != 0) {
-               bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
-                                       fdc->res_drq);
+                   fdc->res_ioport);
+       fdc->res_ioport = NULL;
+       if (fdc->res_drq != NULL)
                bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq,
-                                    fdc->res_drq);
-               fdc->res_drq = NULL;
-       }
+                   fdc->res_drq);
+       fdc->res_drq = NULL;
 }
 
 int
diff -du /dell/imp/FreeBSD/src/sys/dev/fdc/fdc_isa.c ./fdc_isa.c
--- /dell/imp/FreeBSD/src/sys/dev/fdc/fdc_isa.c Mon Sep 13 00:01:47 2004
+++ ./fdc_isa.c Sun Sep 12 23:59:09 2004
@@ -57,9 +57,8 @@
 int
 fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc)
 {
-       int ispnp, nports;
+       int nports = 6;
 
-       ispnp = (fdc->flags & FDC_ISPNP) != 0;
        fdc->fdc_dev = dev;
        fdc->rid_ioport = 0;
        fdc->rid_irq = 0;
@@ -69,99 +68,84 @@
        /*
         * On standard ISA, we don't just use an 8 port range
         * (e.g. 0x3f0-0x3f7) since that covers an IDE control
-        * register at 0x3f6.
+        * register at 0x3f6.  So, on older hardware, we use
+        * 0x3f0-0x3f5 and 0x3f7.  However, some BIOSs omit the
+        * control port, while others start at 0x3f2.  Of the latter,
+        * sometimes we have two resources, other times we have one.
+        * We have to deal with the following cases:
         *
-        * Isn't PC hardware wonderful.
+        * 1:   0x3f0-0x3f5                     # very rare
+        * 2:   0x3f0                           # hints -> 0x3f0-0x3f5,0x3f7
+        * 3:   0x3f0-0x3f5,0x3f7               # Most common
+        * 4:   0x3f2-0x3f5,0x3f7               # Second most common
+        * 5:   0x3f2-0x3f5                     # implies 0x3f7 too.
+        * 6:   0x3f2-0x3f3,0x3f4-0x3f5,0x3f7   # becoming common
+        * 7:   0x3f2-0x3f3,0x3f4-0x3f5         # rare
+        *
+        * The following code is generic for any value of 0x3fx :-)
         */
-       nports = ispnp ? 1 : 6;
 
        /*
-        * Some ACPI BIOSen have _CRS objects for the floppy device that
-        * split the I/O port resource into several resources.  We detect
-        * this case by checking if there are more than 2 IOPORT resources.
-        * If so, we use the resource with the smallest start address as
-        * the port RID and the largest start address as the control RID.
+        * First, allocated the main range of ports.  In the best of
+        * worlds, this is 4 or 6 ports.  In others, well, that's
+        * why this function is so complicated.
         */
-       if (bus_get_resource_count(dev, SYS_RES_IOPORT, 2) != 0) {
-               u_long min_start, max_start, tmp;
-               int i;
-
-               /* Find the min/max start addresses and their RIDs. */
-               max_start = 0ul;
-               min_start = ~0ul;
-               for (i = 0; bus_get_resource_count(dev, SYS_RES_IOPORT, i) > 0;
-                   i++) {
-                       tmp = bus_get_resource_start(dev, SYS_RES_IOPORT, i);
-                       KASSERT(tmp != 0, ("bogus resource"));
-                       if (tmp < min_start) {
-                               min_start = tmp;
-                               fdc->rid_ioport = i;
-                       }
-                       if (tmp > max_start) {
-                               max_start = tmp;
-                               fdc->rid_ctl = i;
-                       }
-               }
-       }
-
        fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
            &fdc->rid_ioport, 0ul, ~0ul, nports, RF_ACTIVE);
        if (fdc->res_ioport == 0) {
-               device_printf(dev, "cannot reserve I/O port range (%d ports)\n",
-                             nports);
-               return ENXIO;
+               device_printf(dev, "cannot allocate I/O port (%d ports)\n",
+                   nports);
+               return (ENXIO);
        }
        fdc->portt = rman_get_bustag(fdc->res_ioport);
        fdc->porth = rman_get_bushandle(fdc->res_ioport);
 
        /*
-        * Some BIOSen report the device at 0x3f2-0x3f5,0x3f7
-        * and some at 0x3f0-0x3f5,0x3f7. We detect the former
-        * by checking the size and adjust the port address
-        * accordingly.
+        * Handle cases 4-7 above
         */
-       if (bus_get_resource_count(dev, SYS_RES_IOPORT, 0) == 4)
-               fdc->port_off = -2;
+       fdc->port_off = -(fdc->porth & 0x7);
 
        /*
-        * Register the control port range as rid 1 if it
-        * isn't there already. Most PnP BIOSen will have
-        * already done this but non-PnP configurations don't.
-        *
-        * And some (!!) report 0x3f2-0x3f5 and completely
-        * leave out the control register!  It seems that some
-        * non-antique controller chips have a different
-        * method of programming the transfer speed which
-        * doesn't require the control register, but it's
-        * mighty bogus as the chip still responds to the
-        * address for the control register.
+        * Deal with case 6 and 7: FDSTS and FDSATA are in rid 1.
         */
-       if (bus_get_resource_count(dev, SYS_RES_IOPORT, 1) == 0) {
-               u_long ctlstart;
-               /* Find the control port, usually 0x3f7 */
-               ctlstart = rman_get_start(fdc->res_ioport) + fdc->port_off + 7;
-               bus_set_resource(dev, SYS_RES_IOPORT, 1, ctlstart, 1);
+       if (rman_get_size(fdc->res_ioport) == 2) {
+               fdc->rid_sts = 1;
+               fdc->res_sts = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
+                   &fdc->rid_sts, RF_ACTIVE);
+               if (fdc->res_sts == NULL) {
+                       device_printf(dev, "Can't alloc rid 1");
+                       fdc_release_resources(fdc);
+                       return (ENXIO);
+               }
+               fdc->rid_ctl++;
+               fdc->sts_off = -4;
+       } else {
+               fdc->res_sts = NULL;
+               fdc->sts_off = fdc->port_off;
        }
+       fdc->stst = rman_get_bustag(fdc->res_sts);
+       fdc->stsh = rman_get_bushandle(fdc->res_sts);
 
        /*
-        * Now (finally!) allocate the control port.
+        * allocate the control port.  For cases 1, 2, 5 and 7, we
+        * fake it from the ioports resource.
         */
        fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT,
            &fdc->rid_ctl, RF_ACTIVE);
-       if (fdc->res_ctl == 0) {
-               device_printf(dev,
-                   "cannot reserve control I/O port range (control port)\n");
-               return ENXIO;
+       if (fdc->res_ctl == NULL) {
+               fdc->ctl_off = 7 + fdc->port_off;
+               fdc->res_ctl = NULL;
+       } else {
+               fdc->ctl_off = 0;
        }
        fdc->ctlt = rman_get_bustag(fdc->res_ctl);
        fdc->ctlh = rman_get_bushandle(fdc->res_ctl);
-       fdc->ctl_off = 0;
 
        fdc->res_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ, &fdc->rid_irq,
-                                             RF_ACTIVE | RF_SHAREABLE);
+           RF_ACTIVE | RF_SHAREABLE);
        if (fdc->res_irq == 0) {
                device_printf(dev, "cannot reserve interrupt line\n");
-               return ENXIO;
+               return (ENXIO);
        }
 
        if ((fdc->flags & FDC_NODMA) == 0) {
@@ -169,12 +153,13 @@
                    &fdc->rid_drq, RF_ACTIVE | RF_SHAREABLE);
                if (fdc->res_drq == 0) {
                        device_printf(dev, "cannot reserve DMA request line\n");
+                       /* This is broken and doesn't work for ISA case */
                        fdc->flags |= FDC_NODMA;
                } else
                        fdc->dmachan = rman_get_start(fdc->res_drq);
        }
 
-       return 0;
+       return (0);
 }
 
 static int
diff -du /dell/imp/FreeBSD/src/sys/dev/fdc/fdc_pccard.c ./fdc_pccard.c
--- /dell/imp/FreeBSD/src/sys/dev/fdc/fdc_pccard.c      Mon Sep 13 00:01:47 2004
+++ ./fdc_pccard.c      Sun Sep 12 23:53:01 2004
@@ -65,6 +65,9 @@
        }
        fdc->portt = rman_get_bustag(fdc->res_ioport);
        fdc->porth = rman_get_bushandle(fdc->res_ioport);
+       fdc->stst = fdc->portt;
+       fdc->stsh = fdc->porth;
+       fdc->sts_off = 0;
        fdc->ctlt = fdc->portt;
        fdc->ctlh = fdc->porth;
        fdc->ctl_off = 7;
diff -du /dell/imp/FreeBSD/src/sys/dev/fdc/fdcvar.h ./fdcvar.h
--- /dell/imp/FreeBSD/src/sys/dev/fdc/fdcvar.h  Mon Sep 13 00:01:47 2004
+++ ./fdcvar.h  Sun Sep 12 23:59:09 2004
@@ -57,14 +57,17 @@
        int     fdc_errs;       /* number of logged errors */
        struct  bio_queue_head head;
        struct  bio *bp;        /* active buffer */
-       struct  resource *res_ioport, *res_ctl, *res_irq, *res_drq;
-       int     rid_ioport, rid_ctl, rid_irq, rid_drq;
-       int     port_off;
+       struct  resource *res_ioport, *res_sts, *res_ctl, *res_irq, *res_drq;
+       int     rid_ioport, rid_sts, rid_ctl, rid_irq, rid_drq;
        bus_space_tag_t portt;
        bus_space_handle_t porth;
+       bus_space_tag_t stst;
+       bus_space_handle_t stsh;
        bus_space_tag_t ctlt;
        bus_space_handle_t ctlh;
+       int     port_off;
        int     ctl_off;
+       int     sts_off;
        void    *fdc_intr;
        struct  device *fdc_dev;
        struct mtx fdc_mtx;
_______________________________________________
[EMAIL PROTECTED] mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-hackers
To unsubscribe, send any mail to "[EMAIL PROTECTED]"

Reply via email to