diff options
author | marius <marius@FreeBSD.org> | 2005-05-19 15:47:37 +0000 |
---|---|---|
committer | marius <marius@FreeBSD.org> | 2005-05-19 15:47:37 +0000 |
commit | 0ef27299c3538d580cf75375e746f66dce6fd6e1 (patch) | |
tree | 6b9c99aab65ffeccd5977b373f814103ea36eeca /sys | |
parent | 906cfe30a450d9ef16216f5fba3f4b63fbf21899 (diff) | |
download | FreeBSD-src-0ef27299c3538d580cf75375e746f66dce6fd6e1.zip FreeBSD-src-0ef27299c3538d580cf75375e746f66dce6fd6e1.tar.gz |
- 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.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/sparc64/isa/isa.c | 60 |
1 files changed, 33 insertions, 27 deletions
diff --git a/sys/sparc64/isa/isa.c b/sys/sparc64/isa/isa.c index b849dfc..4147e37 100644 --- a/sys/sparc64/isa/isa.c +++ b/sys/sparc64/isa/isa.c @@ -153,12 +153,10 @@ isa_init(device_t dev) } } -struct ofw_isa_pnp_map { +static struct { const char *name; uint32_t id; -}; - -static struct ofw_isa_pnp_map pnp_map[] = { +} ofw_isa_pnp_map[] = { { "SUNW,lomh", 0x0000ae4e }, /* SUN0000 */ { "dma", 0x0002d041 }, /* PNP0200 */ { "floppy", 0x0007d041 }, /* PNP0700 */ @@ -176,12 +174,13 @@ static void isa_setup_children(device_t dev, phandle_t parent) { struct isa_regs *regs; + struct resource_list *rl; device_t cdev; u_int64_t end, start; ofw_isa_intr_t *intrs, rintr; phandle_t node; uint32_t *drqs, *regidx; - int i, ndrq, nintr, nreg, nregidx, rtype; + int i, ndrq, nintr, nreg, nregidx, rid, rtype; char *name; /* @@ -208,10 +207,10 @@ isa_setup_children(device_t dev, phandle_t parent) continue; } - for (i = 0; pnp_map[i].name != NULL; i++) - if (strcmp(pnp_map[i].name, name) == 0) + for (i = 0; ofw_isa_pnp_map[i].name != NULL; i++) + if (strcmp(ofw_isa_pnp_map[i].name, name) == 0) 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 " "0x%lx: %s\n", (unsigned long)node, name); 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)) == NULL) panic("isa_setup_children: BUS_ADD_CHILD failed"); - isa_set_logicalid(cdev, pnp_map[i].id); - isa_set_vendorid(cdev, pnp_map[i].id); + isa_set_logicalid(cdev, ofw_isa_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), (void **)®s); 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; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &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); } 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; rtype = ofw_isa_range_map(isab_ranges, isab_nrange, &start, &end, NULL); - bus_set_resource(cdev, rtype, i, start, - end - start + 1); + rid = 0; + while (resource_list_find(rl, rtype, + rid) != NULL) + rid++; + bus_set_resource(cdev, rtype, rid, + start, end - start + 1); } } 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 isdefault = (start == 0UL && end == ~0UL); - struct isa_device* idev = DEVTOISA(child); - struct resource_list *rl = &idev->id_resources; + struct resource_list *rl; struct resource_list_entry *rle; u_long base, limit; + rl = BUS_GET_RESOURCE_LIST(bus, child); if (!passthrough && !isdefault) { rle = resource_list_find(rl, type, *rid); if (!rle) { if (*rid < 0) - return 0; + return (NULL); switch (type) { case SYS_RES_IRQ: if (*rid >= ISA_NIRQ) - return 0; + return (NULL); break; case SYS_RES_DRQ: if (*rid >= ISA_NDRQ) - return 0; + return (NULL); break; case SYS_RES_MEMORY: if (*rid >= ISA_NMEM) - return 0; + return (NULL); break; case SYS_RES_IOPORT: if (*rid >= ISA_NPORT) - return 0; + return (NULL); break; default: - return 0; + return (NULL); } 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, 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 @@ -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 - * the parent PCI buses or the nexus device. - * The interrupt was routed at allocation time. + * Just pass through. This is going to be handled by either + * one of the parent PCI buses or the nexus device. + * 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, arg, cookiep)); |