summaryrefslogtreecommitdiffstats
path: root/sys/isa
diff options
context:
space:
mode:
authornjl <njl@FreeBSD.org>2004-02-15 20:30:22 +0000
committernjl <njl@FreeBSD.org>2004-02-15 20:30:22 +0000
commitd3d228237561f16ad427ffaf3b036f2339ed0104 (patch)
treeda963b00c528fe150a945f07858b39366577ba28 /sys/isa
parent70edb52ffb2f8713bd2ea0249d357cf5d49809c4 (diff)
downloadFreeBSD-src-d3d228237561f16ad427ffaf3b036f2339ed0104.zip
FreeBSD-src-d3d228237561f16ad427ffaf3b036f2339ed0104.tar.gz
Workaround some ACPI BIOSen which break the IO port into multiple
resources. (Note that the correct range is 0x3f7,0x3f0-0x3f5.) Such devices will be detected as follows: fdc0: <Enhanced floppy controller (i82077, NE72065 or clone)> port 0x3f7,0x3f4-0x3f5,0x3f2-0x3f3,0x3f0-0x3f1 irq 6 drq 2 on acpi0 To do this, we find the minimum and maximum start addresses for the resources and use them as the base for the IO and control ports. Help from: jhb
Diffstat (limited to 'sys/isa')
-rw-r--r--sys/isa/fd.c36
1 files changed, 35 insertions, 1 deletions
diff --git a/sys/isa/fd.c b/sys/isa/fd.c
index fe88b94..5cc9408 100644
--- a/sys/isa/fd.c
+++ b/sys/isa/fd.c
@@ -686,6 +686,7 @@ fdc_alloc_resources(struct fdc_data *fdc)
ispcmcia = (fdc->flags & FDC_ISPCMCIA) != 0;
fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0;
fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0;
+ fdc->rid_ctl = 1;
/*
* On standard ISA, we don't just use an 8 port range
@@ -699,6 +700,40 @@ fdc_alloc_resources(struct fdc_data *fdc)
* one with offset 7 as control register.
*/
nports = ispcmcia ? 8 : (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.
+ */
+ 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;
+ }
+ }
+ if (min_start + 7 != max_start) {
+ device_printf(dev, "I/O to control range incorrect\n");
+ return (ENXIO);
+ }
+ }
+
fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT,
&fdc->rid_ioport, 0ul, ~0ul,
nports, RF_ACTIVE);
@@ -746,7 +781,6 @@ fdc_alloc_resources(struct fdc_data *fdc)
/*
* Now (finally!) allocate the control port.
*/
- fdc->rid_ctl = 1;
fdc->res_ctl = bus_alloc_resource(dev, SYS_RES_IOPORT,
&fdc->rid_ctl,
0ul, ~0ul, 1, RF_ACTIVE);
OpenPOWER on IntegriCloud