diff options
author | dfr <dfr@FreeBSD.org> | 1999-05-22 15:18:28 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 1999-05-22 15:18:28 +0000 |
commit | 6f9e5e854190ab2e7fbe71ec2b59354a448a1950 (patch) | |
tree | afd3454efd3e35a02a2f525336e9c7188ac49147 /sys/amd64 | |
parent | cd70cc4f2c802c38796d000c8a8ad692a695e9f5 (diff) | |
download | FreeBSD-src-6f9e5e854190ab2e7fbe71ec2b59354a448a1950.zip FreeBSD-src-6f9e5e854190ab2e7fbe71ec2b59354a448a1950.tar.gz |
* Factor out the common code between the isa bus drivers for i386 and alpha.
* Re-work the resource allocation code to use helper functions in subr_bus.c.
* Add simple isa interface for manipulating the resource ranges which can be
allocated and remove the code from isa_write_ivar() which was previously
used for this purpose.
Diffstat (limited to 'sys/amd64')
-rw-r--r-- | sys/amd64/isa/isa.c | 463 |
1 files changed, 32 insertions, 431 deletions
diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c index 9078b5b..a467cb5 100644 --- a/sys/amd64/isa/isa.c +++ b/sys/amd64/isa/isa.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: isa.c,v 1.125 1999/05/08 21:59:25 dfr Exp $ + * $Id: isa.c,v 1.126 1999/05/14 11:22:28 dfr Exp $ */ /* @@ -68,261 +68,12 @@ #include <machine/resource.h> #include <isa/isavar.h> +#include <isa/isa_common.h> -MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); - -/* - * The structure used to attach devices to the isa bus. - */ -struct isa_device { - int id_port[ISA_NPORT_IVARS]; - u_short id_portsize[ISA_NPORT_IVARS]; - vm_offset_t id_maddr[ISA_NMEM_IVARS]; - vm_size_t id_msize[ISA_NMEM_IVARS]; - int id_irq[ISA_NIRQ_IVARS]; - int id_drq[ISA_NDRQ_IVARS]; - int id_flags; - struct resource *id_portres[ISA_NPORT_IVARS]; - struct resource *id_memres[ISA_NMEM_IVARS]; - struct resource *id_irqres[ISA_NIRQ_IVARS]; - struct resource *id_drqres[ISA_NDRQ_IVARS]; -}; - -#define DEVTOISA(dev) ((struct isa_device *) device_get_ivars(dev)) - -static devclass_t isa_devclass; - -/* - * At 'probe' time, we add all the devices which we know about to the - * bus. The generic attach routine will probe and attach them if they - * are alive. - */ -static int -isa_probe(device_t dev) -{ - isa_wrap_old_drivers(); - return bus_generic_probe(dev); -} - -extern device_t isa_bus_device; - -static int -isa_attach(device_t dev) +void +isa_init(void) { - /* - * Arrange for bus_generic_attach(dev) to be called later. - */ - isa_bus_device = dev; - return 0; -} - -/* - * Add a new child with default ivars. - */ -static device_t -isa_add_child(device_t dev, device_t place, const char *name, int unit) -{ - struct isa_device *idev; - - idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT); - if (!idev) - return 0; - bzero(idev, sizeof *idev); - - idev->id_port[0] = -1; - idev->id_port[1] = -1; - idev->id_portsize[0] = 0; - idev->id_portsize[1] = 0; - idev->id_maddr[0] = 0; - idev->id_maddr[1] = 0; - idev->id_msize[0] = 0; - idev->id_msize[1] = 0; - idev->id_irq[0] = -1; - idev->id_irq[1] = -1; - idev->id_drq[0] = -1; - idev->id_drq[1] = -1; - idev->id_flags = 0; - - if (place) - return device_add_child_after(dev, place, name, unit, idev); - else - return device_add_child(dev, name, unit, idev); -} - -static void -isa_print_child(device_t bus, device_t dev) -{ - struct isa_device *id = DEVTOISA(dev); - - if (id->id_port[0] > 0 || id->id_port[1] > 0 - || id->id_maddr[0] > 0 || id->id_maddr[1] > 0 - || id->id_irq[0] >= 0 || id->id_irq[1] >= 0 - || id->id_drq[0] >= 0 || id->id_drq[1] >= 0) - printf(" at"); - if (id->id_port[0] > 0 && id->id_port[1] > 0) { - printf(" ports %#x", (u_int)id->id_port[0]); - if (id->id_portsize[0] > 1) - printf("-%#x", (u_int)(id->id_port[0] - + id->id_portsize[0] - 1)); - printf(" and %#x", (u_int)id->id_port[1]); - if (id->id_portsize[1] > 1) - printf("-%#x", (u_int)(id->id_port[1] - + id->id_portsize[1] - 1)); - } else if (id->id_port[0] > 0) { - printf(" port %#x", (u_int)id->id_port[0]); - if (id->id_portsize[0] > 1) - printf("-%#x", (u_int)(id->id_port[0] - + id->id_portsize[0] - 1)); - } else if (id->id_port[1] > 0) { - printf(" port %#x", (u_int)id->id_port[1]); - if (id->id_portsize[1] > 1) - printf("-%#x", (u_int)(id->id_port[1] - + id->id_portsize[1] - 1)); - } - if (id->id_maddr[0] && id->id_maddr[1]) { - printf(" iomem %#x", (u_int)id->id_maddr[0]); - if (id->id_msize[0]) - printf("-%#x", (u_int)(id->id_maddr[0] - + id->id_msize[0] - 1)); - printf(" and %#x", (u_int)id->id_maddr[1]); - if (id->id_msize[1]) - printf("-%#x", (u_int)(id->id_maddr[1] - + id->id_msize[1] - 1)); - } else if (id->id_maddr[0]) { - printf(" iomem %#x", (u_int)id->id_maddr[0]); - if (id->id_msize[0]) - printf("-%#x", (u_int)(id->id_maddr[0] - + id->id_msize[0] - 1)); - } else if (id->id_maddr[1]) { - printf(" iomem %#x", (u_int)id->id_maddr[1]); - if (id->id_msize[1]) - printf("-%#x", (u_int)(id->id_maddr[1] - + id->id_msize[1] - 1)); - } - if (id->id_irq[0] >= 0 && id->id_irq[1] >= 0) - printf(" irqs %d and %d", id->id_irq[0], id->id_irq[1]); - else if (id->id_irq[0] >= 0) - printf(" irq %d", id->id_irq[0]); - else if (id->id_irq[1] >= 0) - printf(" irq %d", id->id_irq[1]); - if (id->id_drq[0] >= 0 && id->id_drq[1] >= 0) - printf(" drqs %d and %d", id->id_drq[0], id->id_drq[1]); - else if (id->id_drq[0] >= 0) - printf(" drq %d", id->id_drq[0]); - else if (id->id_drq[1] >= 0) - printf(" drq %d", id->id_drq[1]); - - if (id->id_flags) - printf(" flags %#x", id->id_flags); - - printf(" on %s%d", - device_get_name(bus), device_get_unit(bus)); -} - -static int -isa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) -{ - struct isa_device* idev = DEVTOISA(dev); - - switch (index) { - case ISA_IVAR_PORT_0: - *result = idev->id_port[0]; - break; - case ISA_IVAR_PORT_1: - *result = idev->id_port[1]; - break; - case ISA_IVAR_PORTSIZE_0: - *result = idev->id_portsize[0]; - break; - case ISA_IVAR_PORTSIZE_1: - *result = idev->id_portsize[1]; - break; - case ISA_IVAR_MADDR_0: - *result = idev->id_maddr[0]; - break; - case ISA_IVAR_MADDR_1: - *result = idev->id_maddr[1]; - break; - case ISA_IVAR_MSIZE_0: - *result = idev->id_msize[0]; - break; - case ISA_IVAR_MSIZE_1: - *result = idev->id_msize[1]; - break; - case ISA_IVAR_IRQ_0: - *result = idev->id_irq[0]; - break; - case ISA_IVAR_IRQ_1: - *result = idev->id_irq[1]; - break; - case ISA_IVAR_DRQ_0: - *result = idev->id_drq[0]; - break; - case ISA_IVAR_DRQ_1: - *result = idev->id_drq[1]; - break; - case ISA_IVAR_FLAGS: - *result = idev->id_flags; - break; - } - return ENOENT; -} - -/* - * XXX -- this interface is pretty much irrelevant in the presence of - * BUS_ALLOC_RESOURCE / BUS_RELEASE_RESOURCE (at least for the ivars which - * are defined at this point). - */ -static int -isa_write_ivar(device_t bus, device_t dev, - int index, uintptr_t value) -{ - struct isa_device* idev = DEVTOISA(dev); - - switch (index) { - case ISA_IVAR_PORT_0: - idev->id_port[0] = value; - break; - case ISA_IVAR_PORT_1: - idev->id_port[1] = value; - break; - case ISA_IVAR_PORTSIZE_0: - idev->id_portsize[0] = value; - break; - case ISA_IVAR_PORTSIZE_1: - idev->id_portsize[1] = value; - break; - case ISA_IVAR_MADDR_0: - idev->id_maddr[0] = value; - break; - case ISA_IVAR_MADDR_1: - idev->id_maddr[1] = value; - break; - case ISA_IVAR_MSIZE_0: - idev->id_msize[0] = value; - break; - case ISA_IVAR_MSIZE_1: - idev->id_msize[1] = value; - break; - case ISA_IVAR_IRQ_0: - idev->id_irq[0] = value; - break; - case ISA_IVAR_IRQ_1: - idev->id_irq[1] = value; - break; - case ISA_IVAR_DRQ_0: - idev->id_drq[0] = value; - break; - case ISA_IVAR_DRQ_1: - idev->id_drq[1] = value; - break; - case ISA_IVAR_FLAGS: - idev->id_flags = value; - break; - default: - return (ENOENT); - } - return (0); + isa_wrap_old_drivers(); } /* @@ -333,157 +84,43 @@ isa_write_ivar(device_t bus, device_t dev, * platform. When porting this code to another architecture, it may be * necessary to interpose a mapping layer here. */ -static struct resource * +struct resource * isa_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { - int isdefault; - struct resource *rv, **rvp = 0; - struct isa_device *id = DEVTOISA(child); - - if (child) { - /* - * If this is our child, then use the isa_device to find - * defaults and to record results. - */ - if (device_get_devclass(device_get_parent(child)) == isa_devclass) - id = DEVTOISA(child); - else - id = NULL; - } else - id = NULL; - isdefault = (id != NULL && start == 0UL && end == ~0UL && *rid == 0); - if (*rid > 1) - return 0; - - switch (type) { - case SYS_RES_IRQ: - if (isdefault && id->id_irq[0] >= 0) { - start = id->id_irq[0]; - end = id->id_irq[0]; - count = 1; - } - if (id) - rvp = &id->id_irqres[*rid]; - break; - - case SYS_RES_DRQ: - if (isdefault && id->id_drq[0] >= 0) { - start = id->id_drq[0]; - end = id->id_drq[0]; - count = 1; - } - if (id) - rvp = &id->id_drqres[*rid]; - break; - - case SYS_RES_MEMORY: - if (isdefault && id->id_maddr[0]) { - start = id->id_maddr[0]; - count = max(count, (u_long)id->id_msize[0]); - end = id->id_maddr[0] + count; - } - if (id) - rvp = &id->id_memres[*rid]; - break; - - case SYS_RES_IOPORT: - if (isdefault && id->id_port[0]) { - start = id->id_port[0]; - count = max(count, (u_long)id->id_portsize[0]); - end = id->id_port[0] + count; - } - if (id) - rvp = &id->id_portres[*rid]; - break; - - default: - return 0; - } - /* - * If the client attempts to reallocate a resource without - * releasing what was there previously, die horribly so that - * he knows how he !@#$ed up. + * Consider adding a resource definition. We allow rid 0-1 for + * irq, drq and memory and rid 0-7 for ports which is sufficient for + * isapnp. */ - if (rvp && *rvp != 0) - panic("%s%d: (%d, %d) not free for %s%d\n", - device_get_name(bus), device_get_unit(bus), - type, *rid, - device_get_name(child), device_get_unit(child)); - - /* - * nexus_alloc_resource had better not change *rid... - */ - rv = BUS_ALLOC_RESOURCE(device_get_parent(bus), child, type, rid, - start, end, count, flags); - if (rvp && (*rvp = rv) != 0) { - switch (type) { - case SYS_RES_MEMORY: - id->id_maddr[*rid] = rv->r_start; - id->id_msize[*rid] = count; - break; - case SYS_RES_IOPORT: - id->id_port[*rid] = rv->r_start; - id->id_portsize[*rid] = count; - break; - case SYS_RES_IRQ: - id->id_irq[*rid] = rv->r_start; - break; - case SYS_RES_DRQ: - id->id_drq[*rid] = rv->r_start; - break; + int passthrough = (device_get_parent(child) != bus); + int isdefault = (start == 0UL && end == ~0UL); + struct resource_list *rl; + struct resource_list_entry *rle; + + if (!passthrough && !isdefault) { + rl = device_get_ivars(child); + rle = resource_list_find(rl, type, *rid); + if (!rle) { + if (*rid < 0) + return 0; + if (type != SYS_RES_IOPORT && *rid > 1) + return 0; + if (type == SYS_RES_IOPORT && *rid > 7) + return 0; + resource_list_add(rl, type, *rid, start, end, count); } } - return rv; + + return resource_list_alloc(bus, child, type, rid, + start, end, count, flags); } -static int +int isa_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { - int rv; - struct isa_device *id = DEVTOISA(child); - - if (rid > 1) - return EINVAL; - - switch (type) { - case SYS_RES_IRQ: - case SYS_RES_DRQ: - case SYS_RES_IOPORT: - case SYS_RES_MEMORY: - break; - default: - return (ENOENT); - } - - rv = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r); - - if (rv == 0) { - switch (type) { - case SYS_RES_IRQ: - id->id_irqres[rid] = 0; - break; - - case SYS_RES_DRQ: - id->id_drqres[rid] = 0; - break; - - case SYS_RES_MEMORY: - id->id_memres[rid] = 0; - break; - - case SYS_RES_IOPORT: - id->id_portres[rid] = 0; - break; - - default: - return ENOENT; - } - } - - return rv; + return resource_list_release(bus, child, type, rid, r); } /* @@ -492,7 +129,7 @@ isa_release_resource(device_t bus, device_t child, int type, int rid, * to pass the child (the i386 nexus knows about this and is prepared to * deal). */ -static int +int isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags, void (*ihand)(void *), void *arg, void **cookiep) { @@ -500,45 +137,9 @@ isa_setup_intr(device_t bus, device_t child, struct resource *r, int flags, ihand, arg, cookiep)); } -static int +int isa_teardown_intr(device_t bus, device_t child, struct resource *r, void *cookie) { return (BUS_TEARDOWN_INTR(device_get_parent(bus), child, r, cookie)); } - -static device_method_t isa_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, isa_probe), - DEVMETHOD(device_attach, isa_attach), - DEVMETHOD(device_detach, bus_generic_detach), - DEVMETHOD(device_shutdown, bus_generic_shutdown), - DEVMETHOD(device_suspend, bus_generic_suspend), - DEVMETHOD(device_resume, bus_generic_resume), - - /* Bus interface */ - DEVMETHOD(bus_add_child, isa_add_child), - DEVMETHOD(bus_print_child, isa_print_child), - DEVMETHOD(bus_read_ivar, isa_read_ivar), - DEVMETHOD(bus_write_ivar, isa_write_ivar), - DEVMETHOD(bus_alloc_resource, isa_alloc_resource), - DEVMETHOD(bus_release_resource, isa_release_resource), - DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), - DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), - DEVMETHOD(bus_setup_intr, isa_setup_intr), - DEVMETHOD(bus_teardown_intr, isa_teardown_intr), - - { 0, 0 } -}; - -static driver_t isa_driver = { - "isa", - isa_methods, - 1, /* no softc */ -}; - -/* - * ISA can be attached to a PCI-ISA bridge or directly to the nexus. - */ -DRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); -DRIVER_MODULE(isa, nexus, isa_driver, isa_devclass, 0, 0); |