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
This commit is contained in:
parent
b361f6c620
commit
6b6474a302
@ -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);
|
||||
|
36
sys/isa/fd.c
36
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);
|
||||
|
Loading…
Reference in New Issue
Block a user