From owner-freebsd-hackers@FreeBSD.ORG Mon Sep 13 05:39:41 2004 Return-Path: Delivered-To: freebsd-hackers@freebsd.org Received: from mx1.FreeBSD.org (mx1.freebsd.org [216.136.204.125]) by hub.freebsd.org (Postfix) with ESMTP id EEC8F16A4CE for ; Mon, 13 Sep 2004 05:39:41 +0000 (GMT) Received: from harmony.village.org (rover.village.org [168.103.84.182]) by mx1.FreeBSD.org (Postfix) with ESMTP id EA8FF43D4C for ; Mon, 13 Sep 2004 05:39:40 +0000 (GMT) (envelope-from imp@bsdimp.com) Received: from localhost (warner@rover2.village.org [10.0.0.1]) by harmony.village.org (8.13.1/8.13.1) with ESMTP id i8D5d9rm021491 for ; Sun, 12 Sep 2004 23:39:09 -0600 (MDT) (envelope-from imp@bsdimp.com) Date: Sun, 12 Sep 2004 23:39:46 -0600 (MDT) Message-Id: <20040912.233946.30892794.imp@bsdimp.com> To: hackers@freebsd.org From: "M. Warner Losh" X-Mailer: Mew version 3.3 on Emacs 21.3 / Mule 5.0 (SAKAKI) Mime-Version: 1.0 Content-Type: Multipart/Mixed; boundary="--Next_Part(Sun_Sep_12_23:39:46_2004_595)--" Content-Transfer-Encoding: 7bit Subject: Preliminary fdc patches X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.1 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 13 Sep 2004 05:39:42 -0000 ----Next_Part(Sun_Sep_12_23:39:46_2004_595)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit 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. Warner ----Next_Part(Sun_Sep_12_23:39:46_2004_595)-- Content-Type: Text/Plain; charset=us-ascii Content-Transfer-Encoding: 7bit Content-Disposition: inline; filename=fdc-patch Index: fdc.c =================================================================== RCS file: /cache/ncvs/src/sys/dev/fdc/fdc.c,v retrieving revision 1.286 diff -u -r1.286 fdc.c --- fdc.c 27 Aug 2004 17:08:24 -0000 1.286 +++ fdc.c 13 Sep 2004 05:24:10 -0000 @@ -306,28 +306,28 @@ fdout_wr(struct fdc_data *fdc, u_int8_t v) { - bus_space_write_1(fdc->portt, fdc->porth, FDOUT+fdc->port_off, v); + bus_space_write_1(fdc->portt, fdc->porth, FDOUT + fdc->port_off, v); } static u_int8_t fdsts_rd(struct fdc_data *fdc) { - return bus_space_read_1(fdc->portt, fdc->porth, FDSTS+fdc->port_off); + return (bus_space_read_1(fdc->stst, fdc->stsh, FDSTS + fdc->sts_off)); } static void fddata_wr(struct fdc_data *fdc, u_int8_t v) { - bus_space_write_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off, v); + bus_space_write_1(fdc->stst, fdc->stsh, FDDATA + fdc->sts_off, v); } static u_int8_t fddata_rd(struct fdc_data *fdc) { - return bus_space_read_1(fdc->portt, fdc->porth, FDDATA+fdc->port_off); + return (bus_space_read_1(fdc->stst, fdc->stsh, FDDATA + fdc->sts_off)); } static u_int8_t @@ -1484,39 +1484,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 && fdc->rid_ctl != -1) 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 && fdc->rid_sts != -1) + 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 Index: fdc_isa.c =================================================================== RCS file: /cache/ncvs/src/sys/dev/fdc/fdc_isa.c,v retrieving revision 1.12 diff -u -r1.12 fdc_isa.c --- fdc_isa.c 31 Aug 2004 20:37:10 -0000 1.12 +++ fdc_isa.c 13 Sep 2004 05:33:58 -0000 @@ -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 Index: fdc_pccard.c =================================================================== RCS file: /cache/ncvs/src/sys/dev/fdc/fdc_pccard.c,v retrieving revision 1.9 diff -u -r1.9 fdc_pccard.c --- fdc_pccard.c 20 Aug 2004 15:14:25 -0000 1.9 +++ fdc_pccard.c 13 Sep 2004 05:34:23 -0000 @@ -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; Index: fdcvar.h =================================================================== RCS file: /cache/ncvs/src/sys/dev/fdc/fdcvar.h,v retrieving revision 1.4 diff -u -r1.4 fdcvar.h --- fdcvar.h 20 Aug 2004 15:14:25 -0000 1.4 +++ fdcvar.h 13 Sep 2004 05:30:09 -0000 @@ -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; ----Next_Part(Sun_Sep_12_23:39:46_2004_595)----