diff options
author | imp <imp@FreeBSD.org> | 2004-09-20 06:12:19 +0000 |
---|---|---|
committer | imp <imp@FreeBSD.org> | 2004-09-20 06:12:19 +0000 |
commit | 9ee28251177e93c5acc68b1b2fc030fa01f49769 (patch) | |
tree | a7e68e03cc17a3f41607e39f5bf58a3d435c15ee | |
parent | 3c09ffb8d96ce21904234240869560df65deb8ed (diff) | |
download | FreeBSD-src-9ee28251177e93c5acc68b1b2fc030fa01f49769.zip FreeBSD-src-9ee28251177e93c5acc68b1b2fc030fa01f49769.tar.gz |
das@ has a ACPI bios that lists 0x3f0-0x3f1, 0x3f2-0x3f3, 0x3f4-0x3f5
and 0x3f7. fdc_isa_alloc_resource() didn't work right in this case
(it accessed FDOUT correctly due to an overflow of the first resource.
It accesed FDSTS and FDDATA incorrectly via the second resource (which
wound up accessing FDOUT and the tape register at 0x3f3) and badly for
the CTL register (at location 0x3f4). This is a minimal fix that just
'eats' the first one if it covers two locations and has an offset of
0. This confusion lead the floppy driver to think there'd been a disk
change, which uncovered a deadlock in the floppy/geom code which lead
to a panic. These changes fix that by fixing the underlying resource
problem, but doesn't address the potential deadlock issue that might
still be there.
This is a minimal fix so it can more safely be merged into 5 w/o risk
for known working configurations (hence the use of the ugly goto,
which reduces case 8 to case 6 w/o affecting cases 1-7). A more
invasive fix that will handle more ACPI resource list diversity is in
the pipeline that should kill these issues once and for all, while
staying within the resources that we allocate.
Tested/Reported by: das
Reviewed by: njl
MFC before: re->next_release_name(5.3-BETA5);
-rw-r--r-- | sys/dev/fdc/fdc_isa.c | 18 |
1 files changed, 14 insertions, 4 deletions
diff --git a/sys/dev/fdc/fdc_isa.c b/sys/dev/fdc/fdc_isa.c index b912771..0833fed 100644 --- a/sys/dev/fdc/fdc_isa.c +++ b/sys/dev/fdc/fdc_isa.c @@ -81,6 +81,7 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc) * 5: 0x3f2-0x3f5 # implies 0x3f7 too. * 6: 0x3f2-0x3f3,0x3f4-0x3f5,0x3f7 # becoming common * 7: 0x3f2-0x3f3,0x3f4-0x3f5 # rare + * 8: 0x3f0-0x3f1,0x3f2-0x3f3,0x3f4-0x3f5,0x3f7 * * The following code is generic for any value of 0x3fx :-) */ @@ -90,6 +91,7 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc) * worlds, this is 4 or 6 ports. In others, well, that's * why this function is so complicated. */ +again_ioport: fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, &fdc->rid_ioport, 0ul, ~0ul, nports, RF_ACTIVE); if (fdc->res_ioport == 0) { @@ -97,19 +99,27 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc) nports); return (ENXIO); } + if ((rman_get_start(fdc->res_ioport) & 0x7) == 0 && + rman_get_size(fdc->res_ioport) == 2) { + /* Case 8 */ + bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + fdc->rid_ioport++; + goto again_ioport; + } fdc->portt = rman_get_bustag(fdc->res_ioport); fdc->porth = rman_get_bushandle(fdc->res_ioport); /* - * Handle cases 4-7 above + * Handle cases 4-8 above */ fdc->port_off = -(fdc->porth & 0x7); /* - * Deal with case 6 and 7: FDSTS and FDSATA are in rid 1. + * Deal with case 6, 7, and 8: FDSTS and FDSATA are in rid 1. */ if (rman_get_size(fdc->res_ioport) == 2) { - fdc->rid_sts = 1; + fdc->rid_sts = fdc->rid_ioport + 1; fdc->res_sts = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &fdc->rid_sts, RF_ACTIVE); if (fdc->res_sts == NULL) { @@ -117,7 +127,6 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc) fdc_release_resources(fdc); return (ENXIO); } - fdc->rid_ctl++; fdc->sts_off = -4; fdc->stst = rman_get_bustag(fdc->res_sts); fdc->stsh = rman_get_bushandle(fdc->res_sts); @@ -133,6 +142,7 @@ fdc_isa_alloc_resources(device_t dev, struct fdc_data *fdc) * fake it from the ioports resource. XXX IS THIS THE RIGHT THING * TO DO, OR SHOULD WE CREATE A NEW RID? (I think we need a new rid) */ + fdc->rid_ctl = fdc->rid_sts + 1; fdc->res_ctl = bus_alloc_resource_any(dev, SYS_RES_IOPORT, &fdc->rid_ctl, RF_ACTIVE); if (fdc->res_ctl == NULL) { |