- When iterating over the register resources of the children don't use

the iteration variable as the RID when adding the respective resource
  to the child via bus_set_resource(). In case a device has both I/O
  and memory resources this generates gaps in the newbus resources of
  the child, e.g. its first memory resource might end up as RID 1.
  To solve this mimic resource_list_add_next() via resource_list_find()
  and bus_set_resource(); we can't just use resource_list_add_next()
  here as this would circumvent the limit checks in isa_set_resource()
  of the common ISA code.
  This however is more or less a theoretical problem so far as all known
  ISA devices on sparc64 soley use I/O space.
- Just use bus_generic_rl_release_resource() for isa_release_resource()
  instead of re-implementing the former.
- Improve some comments to better reflect reality, minor clean-up and
  simplifications, return NULL instead of 0 were appropriate.
This commit is contained in:
Marius Strobl 2005-05-19 15:47:37 +00:00
parent 0f93d8245d
commit 42be1191a0

View File

@ -153,12 +153,10 @@ isa_init(device_t dev)
} }
} }
struct ofw_isa_pnp_map { static struct {
const char *name; const char *name;
uint32_t id; uint32_t id;
}; } ofw_isa_pnp_map[] = {
static struct ofw_isa_pnp_map pnp_map[] = {
{ "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */ { "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */
{ "dma", 0x0002d041 }, /* PNP0200 */ { "dma", 0x0002d041 }, /* PNP0200 */
{ "floppy", 0x0007d041 }, /* PNP0700 */ { "floppy", 0x0007d041 }, /* PNP0700 */
@ -176,12 +174,13 @@ static void
isa_setup_children(device_t dev, phandle_t parent) isa_setup_children(device_t dev, phandle_t parent)
{ {
struct isa_regs *regs; struct isa_regs *regs;
struct resource_list *rl;
device_t cdev; device_t cdev;
u_int64_t end, start; u_int64_t end, start;
ofw_isa_intr_t *intrs, rintr; ofw_isa_intr_t *intrs, rintr;
phandle_t node; phandle_t node;
uint32_t *drqs, *regidx; uint32_t *drqs, *regidx;
int i, ndrq, nintr, nreg, nregidx, rtype; int i, ndrq, nintr, nreg, nregidx, rid, rtype;
char *name; char *name;
/* /*
@ -208,10 +207,10 @@ isa_setup_children(device_t dev, phandle_t parent)
continue; continue;
} }
for (i = 0; pnp_map[i].name != NULL; i++) for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++)
if (strcmp(pnp_map[i].name, name) == 0) if (strcmp(ofw_isa_pnp_map[i].name, name) == 0)
break; break;
if (i == (sizeof(pnp_map) / sizeof(*pnp_map)) - 1) { if (ofw_isa_pnp_map[i].name == NULL) {
printf("isa_setup_children: no PnP map entry for node " printf("isa_setup_children: no PnP map entry for node "
"0x%lx: %s\n", (unsigned long)node, name); "0x%lx: %s\n", (unsigned long)node, name);
continue; continue;
@ -220,9 +219,10 @@ isa_setup_children(device_t dev, phandle_t parent)
if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) == if ((cdev = BUS_ADD_CHILD(dev, ISA_ORDER_PNPBIOS, NULL, -1)) ==
NULL) NULL)
panic("isa_setup_children: BUS_ADD_CHILD failed"); panic("isa_setup_children: BUS_ADD_CHILD failed");
isa_set_logicalid(cdev, pnp_map[i].id); isa_set_logicalid(cdev, ofw_isa_pnp_map[i].id);
isa_set_vendorid(cdev, pnp_map[i].id); isa_set_vendorid(cdev, ofw_isa_pnp_map[i].id);
rl = BUS_GET_RESOURCE_LIST(dev, cdev);
nreg = OF_getprop_alloc(node, "reg", sizeof(*regs), nreg = OF_getprop_alloc(node, "reg", sizeof(*regs),
(void **)&regs); (void **)&regs);
for (i = 0; i < nreg; i++) { for (i = 0; i < nreg; i++) {
@ -230,7 +230,10 @@ isa_setup_children(device_t dev, phandle_t parent)
end = start + regs[i].size - 1; end = start + regs[i].size - 1;
rtype = ofw_isa_range_map(isab_ranges, isab_nrange, rtype = ofw_isa_range_map(isab_ranges, isab_nrange,
&start, &end, NULL); &start, &end, NULL);
bus_set_resource(cdev, rtype, i, start, rid = 0;
while (resource_list_find(rl, rtype, rid) != NULL)
rid++;
bus_set_resource(cdev, rtype, rid, start,
end - start + 1); end - start + 1);
} }
if (nreg == -1 && parent != isab_node) { if (nreg == -1 && parent != isab_node) {
@ -251,8 +254,12 @@ isa_setup_children(device_t dev, phandle_t parent)
end = start + regs[regidx[i]].size - 1; end = start + regs[regidx[i]].size - 1;
rtype = ofw_isa_range_map(isab_ranges, rtype = ofw_isa_range_map(isab_ranges,
isab_nrange, &start, &end, NULL); isab_nrange, &start, &end, NULL);
bus_set_resource(cdev, rtype, i, start, rid = 0;
end - start + 1); while (resource_list_find(rl, rtype,
rid) != NULL)
rid++;
bus_set_resource(cdev, rtype, rid,
start, end - start + 1);
} }
} }
if (regidx != NULL) if (regidx != NULL)
@ -304,35 +311,35 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid,
*/ */
int passthrough = (device_get_parent(child) != bus); int passthrough = (device_get_parent(child) != bus);
int isdefault = (start == 0UL && end == ~0UL); int isdefault = (start == 0UL && end == ~0UL);
struct isa_device* idev = DEVTOISA(child); struct resource_list *rl;
struct resource_list *rl = &idev->id_resources;
struct resource_list_entry *rle; struct resource_list_entry *rle;
u_long base, limit; u_long base, limit;
rl = BUS_GET_RESOURCE_LIST(bus, child);
if (!passthrough && !isdefault) { if (!passthrough && !isdefault) {
rle = resource_list_find(rl, type, *rid); rle = resource_list_find(rl, type, *rid);
if (!rle) { if (!rle) {
if (*rid < 0) if (*rid < 0)
return 0; return (NULL);
switch (type) { switch (type) {
case SYS_RES_IRQ: case SYS_RES_IRQ:
if (*rid >= ISA_NIRQ) if (*rid >= ISA_NIRQ)
return 0; return (NULL);
break; break;
case SYS_RES_DRQ: case SYS_RES_DRQ:
if (*rid >= ISA_NDRQ) if (*rid >= ISA_NDRQ)
return 0; return (NULL);
break; break;
case SYS_RES_MEMORY: case SYS_RES_MEMORY:
if (*rid >= ISA_NMEM) if (*rid >= ISA_NMEM)
return 0; return (NULL);
break; break;
case SYS_RES_IOPORT: case SYS_RES_IOPORT:
if (*rid >= ISA_NPORT) if (*rid >= ISA_NPORT)
return 0; return (NULL);
break; break;
default: default:
return 0; return (NULL);
} }
resource_list_add(rl, type, *rid, start, end, count); resource_list_add(rl, type, *rid, start, end, count);
} }
@ -384,10 +391,8 @@ int
isa_release_resource(device_t bus, device_t child, int type, int rid, isa_release_resource(device_t bus, device_t child, int type, int rid,
struct resource *res) struct resource *res)
{ {
struct isa_device* idev = DEVTOISA(child);
struct resource_list *rl = &idev->id_resources;
return (resource_list_release(rl, bus, child, type, rid, res)); return (bus_generic_rl_release_resource(bus, child, type, rid, res));
} }
int int
@ -397,9 +402,10 @@ isa_setup_intr(device_t dev, device_t child,
{ {
/* /*
* Just pass through. This is going to be handled by either one of * Just pass through. This is going to be handled by either
* the parent PCI buses or the nexus device. * one of the parent PCI buses or the nexus device.
* The interrupt was routed at allocation time. * The interrupt had been routed before it was added to the
* resource list of the child.
*/ */
return (BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, intr, return (BUS_SETUP_INTR(device_get_parent(dev), child, irq, flags, intr,
arg, cookiep)); arg, cookiep));