Correctly handle BIOS resources that are duplicated (!). There are many

systems that have overlapping regions specified in their sysresource
objects.  This patch fixes ATA DMA and acpi_timer allocation for such
sysctems.  It should eventually be moved to resource_list_add() if it is
a valid generalized approach.  The minimal approach for 5.3 is:

"Loop through all current resources to see if the new one overlaps
any existing ones.  If so, the old one always takes precedence and
the new one is adjusted (or rejected).  We check for three cases:

1. Tail of new resource overlaps head of old resource:  truncate the
   new resource so it is contiguous with the start of the old.
2. New resource wholly contained within the old resource:  error.
3. Head of new resource overlaps tail of old resource:  truncate the
   new resource so it is contiguous, following the old."

Tested by:	Radek Kozlowski <radek_at_raadradd.com>
Discussed with:	imp
MFC after:	4 days
This commit is contained in:
Nate Lawson 2004-08-20 16:52:44 +00:00
parent 7500723246
commit d22e9c6e0d
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=134086

View File

@ -504,6 +504,51 @@ struct acpi_res_context {
void *ar_parent;
};
/*
* Add a resource to the device's resource list. We define our own function
* for this since bus_set_resource() doesn't handle duplicates of any kind.
*
* XXX This should be merged into resource_list_add() eventually.
*/
static int
acpi_reslist_add(device_t dev, int type, int rid, u_long start, u_long count)
{
struct resource_list_entry *rle;
struct resource_list *rl;
u_long end;
end = start + count - 1;
rl = BUS_GET_RESOURCE_LIST(device_get_parent(dev), dev);
/*
* Loop through all current resources to see if the new one overlaps
* any existing ones. If so, the old one always takes precedence and
* the new one is adjusted (or rejected). We check for three cases:
*
* 1. Tail of new resource overlaps head of old resource: truncate the
* new resource so it is contiguous with the start of the old.
* 2. New resource wholly contained within the old resource: error.
* 3. Head of new resource overlaps tail of old resource: truncate the
* new resource so it is contiguous, following the old.
*/
SLIST_FOREACH(rle, rl, link) {
if (rle->type == type) {
if (start < rle->start && end >= rle->start) {
count = rle->start - start;
break;
} else if (start >= rle->start && start <= rle->end) {
if (end > rle->end) {
start = rle->end + 1;
count = end - rle->end + 1;
break;
} else
return (EEXIST);
}
}
}
return (bus_set_resource(dev, type, rid, start, count));
}
static void
acpi_res_set_init(device_t dev, void *arg, void **context)
{
@ -534,7 +579,7 @@ acpi_res_set_ioport(device_t dev, void *context, u_int32_t base,
if (cp == NULL)
return;
bus_set_resource(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
acpi_reslist_add(dev, SYS_RES_IOPORT, cp->ar_nio++, base, length);
}
static void
@ -557,7 +602,7 @@ acpi_res_set_memory(device_t dev, void *context, u_int32_t base,
if (cp == NULL)
return;
bus_set_resource(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
acpi_reslist_add(dev, SYS_RES_MEMORY, cp->ar_nmem++, base, length);
}
static void
@ -584,7 +629,7 @@ acpi_res_set_irq(device_t dev, void *context, u_int32_t *irq, int count,
if (count != 1)
return;
bus_set_resource(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
acpi_reslist_add(dev, SYS_RES_IRQ, cp->ar_nirq++, *irq, 1);
}
static void
@ -599,7 +644,7 @@ acpi_res_set_drq(device_t dev, void *context, u_int32_t *drq, int count)
if (count != 1)
return;
bus_set_resource(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
acpi_reslist_add(dev, SYS_RES_DRQ, cp->ar_ndrq++, *drq, 1);
}
static void