diff options
Diffstat (limited to 'sys')
147 files changed, 10870 insertions, 5332 deletions
diff --git a/sys/alpha/alpha/autoconf.c b/sys/alpha/alpha/autoconf.c index da47473..e5489c6 100644 --- a/sys/alpha/alpha/autoconf.c +++ b/sys/alpha/alpha/autoconf.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: autoconf.c,v 1.14 1999/03/12 14:44:46 gallatin Exp $ + * $Id: autoconf.c,v 1.15 1999/03/28 17:33:38 dfr Exp $ */ #include "opt_bootp.h" @@ -190,7 +190,7 @@ configure(void *dummy) if((hwrpb->rpb_type != ST_DEC_3000_300) && (hwrpb->rpb_type != ST_DEC_3000_500)){ - pci_configure(); + /* pci_configure(); */ /* * Probe ISA devices after everything. diff --git a/sys/alpha/conf/files.alpha b/sys/alpha/conf/files.alpha index 6f747e3..d0f4003 100644 --- a/sys/alpha/conf/files.alpha +++ b/sys/alpha/conf/files.alpha @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.alpha,v 1.16 1999/01/23 16:53:26 dfr Exp $ +# $Id: files.alpha,v 1.17 1999/03/10 10:36:50 yokota Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -112,10 +112,13 @@ mcclock_if.h standard \ no-obj no-implicit-rule before-depend \ clean "mcclock_if.h" alpha/pci/cia.c optional cia +alpha/pci/cia_pci.c optional cia alpha/pci/pci_eb164_intr.s optional cia alpha/pci/apecs.c optional apecs +alpha/pci/apecs_pci.c optional apecs alpha/pci/pci_eb64plus_intr.s optional apecs alpha/pci/lca.c optional lca +alpha/pci/lca_pci.c optional lca alpha/pci/pcibus.c optional pci alpha/isa/isa.c optional isa alpha/isa/mcclock_isa.c optional isa @@ -157,3 +160,10 @@ dev/syscons/syscons.c optional sc device-driver dev/syscons/scvidctl.c optional sc device-driver isa/syscons_isa.c optional sc device-driver isa/psm.c optional psm device-driver +dev/ata/ata-all.c optional ata device-driver +dev/ata/ata-dma.c optional ata device-driver +dev/ata/atapi-all.c optional ata device-driver +dev/ata/ata-disk.c optional atadisk device-driver +dev/ata/atapi-cd.c optional atapicd device-driver +dev/ata/atapi-fd.c optional atapifd device-driver +dev/ata/atapi-tape.c optional atapist device-driver diff --git a/sys/alpha/include/chipset.h b/sys/alpha/include/chipset.h index f7a61be..66f59bb 100644 --- a/sys/alpha/include/chipset.h +++ b/sys/alpha/include/chipset.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: chipset.h,v 1.5 1998/10/06 14:18:39 dfr Exp $ + * $Id: chipset.h,v 1.6 1998/11/15 18:25:16 dfr Exp $ */ #ifndef _MACHINE_CHIPSET_H_ @@ -100,13 +100,6 @@ typedef struct alpha_chipset { */ alpha_chipset_read_hae_t* read_hae; alpha_chipset_write_hae_t* write_hae; - - /* - * PCI interrupt device. - * (XXX hack until I change pci code to use new - * device framework.) - */ - void* intrdev; } alpha_chipset_t; extern alpha_chipset_t chipset; diff --git a/sys/alpha/include/cpuconf.h b/sys/alpha/include/cpuconf.h index 6bddc82..1965a5a 100644 --- a/sys/alpha/include/cpuconf.h +++ b/sys/alpha/include/cpuconf.h @@ -73,6 +73,7 @@ extern struct platform { void (*pci_intr_map) __P((void *)); void (*pci_intr_disable) __P((int)); void (*pci_intr_enable) __P((int)); + int (*pci_setup_ide_intr) __P((int chan, void (*fn)(void*), void *arg)); } platform; /* diff --git a/sys/alpha/include/cpufunc.h b/sys/alpha/include/cpufunc.h index bc4ffe3..8326970 100644 --- a/sys/alpha/include/cpufunc.h +++ b/sys/alpha/include/cpufunc.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cpufunc.h,v 1.2 1998/07/22 08:25:39 dfr Exp $ + * $Id: cpufunc.h,v 1.3 1998/08/17 08:21:31 dfr Exp $ */ #ifndef _MACHINE_CPUFUNC_H_ @@ -59,11 +59,45 @@ breakpoint(void) #define writel(pa,v) chipset.writel(pa,v) /* + * Bulk i/o (for IDE driver). + */ +static __inline void insw(u_int32_t port, void *buffer, size_t count) +{ + u_int16_t *p = (u_int16_t *) buffer; + while (count--) + *p++ = inw(port); +} + +static __inline void insl(u_int32_t port, void *buffer, size_t count) +{ + u_int32_t *p = (u_int32_t *) buffer; + while (count--) + *p++ = inl(port); +} + +static __inline void outsw(u_int32_t port, const void *buffer, size_t count) +{ + const u_int16_t *p = (const u_int16_t *) buffer; + while (count--) + outw(port, *p++); +} + +static __inline void outsl(u_int32_t port, const void *buffer, size_t count) +{ + const u_int32_t *p = (const u_int32_t *) buffer; + while (count--) + outl(port, *p++); +} + +/* * String version of IO memory access ops: */ extern void memcpy_fromio(void *, u_int32_t, size_t); extern void memcpy_toio(u_int32_t, void *, size_t); +extern void memcpy_io(u_int32_t, u_int32_t, size_t); extern void memset_io(u_int32_t, int, size_t); +extern void memsetw(void *, int, size_t); +extern void memsetw_io(u_int32_t, int, size_t); #endif /* KERNEL */ diff --git a/sys/alpha/isa/isa.c b/sys/alpha/isa/isa.c index 56df551..5b6b54e 100644 --- a/sys/alpha/isa/isa.c +++ b/sys/alpha/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.8 1998/11/28 09:55:16 dfr Exp $ + * $Id: isa.c,v 1.9 1999/01/23 16:53:27 dfr Exp $ */ #include <sys/param.h> @@ -31,11 +31,13 @@ #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/malloc.h> #include <sys/rman.h> #include <isa/isareg.h> #include <isa/isavar.h> +#include <alpha/isa/isavar.h> #include <machine/intr.h> #include <machine/intrcnt.h> #include <machine/resource.h> @@ -78,10 +80,6 @@ static struct resource *isa_alloc_resource(device_t bus, device_t child, u_long count, u_int flags); static int isa_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r); -static int isa_setup_intr(device_t dev, device_t child, struct resource *irq, - driver_intr_t *intr, void *arg, void **cookiep); -static int isa_teardown_intr(device_t dev, device_t child, - struct resource *irq, void *cookie); static device_method_t isa_methods[] = { /* Device interface */ @@ -139,7 +137,7 @@ isa_add_device(device_t dev, const char *name, int unit) idev->id_portsize[0] = 0; idev->id_portsize[1] = 0; - if (resource_int_value(name, unit, "iomem", &t) == 0) + if (resource_int_value(name, unit, "maddr", &t) == 0) idev->id_maddr[0] = t; else idev->id_maddr[0] = 0; @@ -236,6 +234,8 @@ isa_probe(device_t dev) { int i; + device_set_desc(dev, "ISA bus"); + /* * Add all devices configured to be attached to isa0. */ @@ -256,14 +256,7 @@ isa_probe(device_t dev) resource_query_unit(i)); } - isa_irq_rman.rm_start = 0; - isa_irq_rman.rm_end = 15; - isa_irq_rman.rm_type = RMAN_ARRAY; - isa_irq_rman.rm_descr = "ISA Interrupt request lines"; - if (rman_init(&isa_irq_rman) - || rman_manage_region(&isa_irq_rman, 0, 1) - || rman_manage_region(&isa_irq_rman, 3, 15)) - panic("isa_probe isa_irq_rman"); + isa_init_intr(); return 0; } @@ -276,13 +269,6 @@ isa_attach(device_t dev) if (bootverbose) printf("isa_attach: mask=%04x\n", isa_irq_mask()); - /* mask all isa interrupts */ - outb(IO_ICU1+1, 0xff); - outb(IO_ICU2+1, 0xff); - - /* make sure chaining irq is enabled */ - isa_intr_enable(2); - /* * Arrange for bus_generic_attach(dev) to be called later. */ @@ -340,12 +326,14 @@ isa_print_child(device_t bus, device_t dev) printf("-%#x", (u_int)(id->id_maddr[1] + id->id_msize[1] - 1)); } +#if 0 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]); +#endif 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) @@ -406,8 +394,10 @@ isa_read_ivar(device_t bus, device_t dev, case ISA_IVAR_FLAGS: *result = idev->id_flags; break; + default: + return (ENOENT); } - return ENOENT; + return (0); } static int @@ -462,6 +452,43 @@ isa_write_ivar(device_t bus, device_t dev, return (0); } +void isa_init_intr(void) +{ + static int initted = 0; + + if (initted) return; + initted = 1; + + isa_irq_rman.rm_start = 0; + isa_irq_rman.rm_end = 15; + isa_irq_rman.rm_type = RMAN_ARRAY; + isa_irq_rman.rm_descr = "ISA Interrupt request lines"; + if (rman_init(&isa_irq_rman) + || rman_manage_region(&isa_irq_rman, 0, 1) + || rman_manage_region(&isa_irq_rman, 3, 15)) + panic("isa_probe isa_irq_rman"); + + /* mask all isa interrupts */ + outb(IO_ICU1+1, 0xff); + outb(IO_ICU2+1, 0xff); + + /* make sure chaining irq is enabled */ + isa_intr_enable(2); +} + +struct resource * +isa_alloc_intr(device_t bus, device_t child, int irq) +{ + return rman_reserve_resource(&isa_irq_rman, irq, irq, 1, + 0, child); +} + +int +isa_release_intr(device_t bus, device_t child, struct resource *r) +{ + return rman_release_resource(r); +} + /* * This implementation simply passes the request up to the parent * bus, which in our case is the pci chipset device, substituting any @@ -502,7 +529,7 @@ isa_alloc_resource(device_t bus, device_t child, int type, int *rid, * The hack implementation of intr_create() passes a * NULL child device. */ - if (isdefault && (id == NULL || id->id_irq[0] >= 0)) { + if (isdefault && id && id->id_irq[0] >= 0) { start = id->id_irq[0]; end = id->id_irq[0]; count = 1; @@ -576,7 +603,6 @@ isa_release_resource(device_t bus, device_t child, int type, int rid, struct resource *r) { int rv; - struct resource **rp; struct isa_device *id = DEVTOISA(child); if (rid > 1) @@ -595,7 +621,7 @@ isa_release_resource(device_t bus, device_t child, int type, int rid, rv = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r); - if (rv) { + if (rv == 0) { switch (type) { case SYS_RES_IRQ: id->id_irqres[rid] = 0; @@ -652,7 +678,7 @@ isa_handle_intr(void *arg) outb(IO_ICU1, 0x20 | (irq > 7 ? 2 : irq)); } -static int +int isa_setup_intr(device_t dev, device_t child, struct resource *irq, driver_intr_t *intr, void *arg, void **cookiep) @@ -681,10 +707,15 @@ isa_setup_intr(device_t dev, device_t child, isa_intr_enable(irq->r_start); *cookiep = ii; + + if (child) + device_printf(child, "interrupting at ISA irq %d\n", + (int)irq->r_start); + return 0; } -static int +int isa_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { @@ -696,6 +727,4 @@ isa_teardown_intr(device_t dev, device_t child, return 0; } -DRIVER_MODULE(isa, cia, isa_driver, isa_devclass, 0, 0); -DRIVER_MODULE(isa, apecs, isa_driver, isa_devclass, 0, 0); -DRIVER_MODULE(isa, lca, isa_driver, isa_devclass, 0, 0); +DRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); diff --git a/sys/alpha/isa/isavar.h b/sys/alpha/isa/isavar.h new file mode 100644 index 0000000..ce0e8ce --- /dev/null +++ b/sys/alpha/isa/isavar.h @@ -0,0 +1,39 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * Export low-level interrupt handling code for chipsets which route + * interrupts via the ISA interrupt controller. + */ +void isa_init_intr(void); +struct resource *isa_alloc_intr(device_t bus, device_t child, int irq); +int isa_release_intr(device_t bus, device_t child, struct resource *r); +int isa_setup_intr(device_t dev, device_t child, struct resource *irq, + driver_intr_t *intr, void *arg, void **cookiep); +int isa_teardown_intr(device_t dev, device_t child, struct resource *irq, + void *cookie); diff --git a/sys/alpha/pci/apecs.c b/sys/alpha/pci/apecs.c index 66bedcf..fb86dc9 100644 --- a/sys/alpha/pci/apecs.c +++ b/sys/alpha/pci/apecs.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: apecs.c,v 1.4 1998/12/04 22:54:42 archie Exp $ + * $Id: apecs.c,v 1.5 1999/01/18 20:15:07 gallatin Exp $ */ /* * Copyright (c) 1995, 1996 Carnegie-Mellon University. @@ -60,12 +60,15 @@ #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #include <alpha/pci/apecsreg.h> #include <alpha/pci/apecsvar.h> #include <alpha/pci/pcibus.h> +#include <alpha/isa/isavar.h> #include <machine/intr.h> +#include <machine/resource.h> #include <machine/intrcnt.h> #include <machine/cpuconf.h> #include <machine/swiz.h> @@ -75,7 +78,6 @@ static devclass_t apecs_devclass; static device_t apecs0; /* XXX only one for now */ -static device_t isa0; struct apecs_softc { vm_offset_t dmem_base; /* dense memory */ @@ -442,18 +444,25 @@ apecs_write_hae(u_int64_t hae) static int apecs_probe(device_t dev); static int apecs_attach(device_t dev); +static struct resource *apecs_alloc_resource(device_t bus, device_t child, + int type, int *rid, u_long start, + u_long end, u_long count, + u_int flags); +static int apecs_release_resource(device_t bus, device_t child, + int type, int rid, struct resource *r); static int apecs_setup_intr(device_t dev, device_t child, struct resource *irq, driver_intr_t *intr, void *arg, void **cookiep); static int apecs_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie); + static device_method_t apecs_methods[] = { /* Device interface */ DEVMETHOD(device_probe, apecs_probe), DEVMETHOD(device_attach, apecs_attach), /* Bus interface */ - DEVMETHOD(bus_alloc_resource, pci_alloc_resource), - DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_alloc_resource, apecs_alloc_resource), + DEVMETHOD(bus_release_resource, apecs_release_resource), DEVMETHOD(bus_activate_resource, pci_activate_resource), DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), DEVMETHOD(bus_setup_intr, apecs_setup_intr), @@ -499,29 +508,19 @@ apecs_probe(device_t dev) apecs_hae_mem = REGVAL(EPIC_HAXR1); pci_init_resources(); + isa_init_intr(); - isa0 = device_add_child(dev, "isa", 0, 0); + device_add_child(dev, "pcib", 0, 0); return 0; } -extern void isa_intr(void* frame, u_long vector); - static int apecs_attach(device_t dev) { struct apecs_softc* sc = APECS_SOFTC(dev); apecs_init(); - /* - * the avanti routes interrupts through the isa interrupt - * controller, so we need to special case it - */ - if(hwrpb->rpb_type == ST_DEC_2100_A50) - chipset.intrdev = isa0; - else - chipset.intrdev = apecs0; - sc->dmem_base = APECS_PCI_DENSE; sc->smem_base = APECS_PCI_SPARSE; sc->io_base = APECS_PCI_SIO; @@ -541,6 +540,27 @@ apecs_attach(device_t dev) return 0; } +static struct resource * +apecs_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + if (type == SYS_RES_IRQ) + return isa_alloc_intr(bus, child, start); + else + return pci_alloc_resource(bus, child, type, rid, + start, end, count, flags); +} + +static int +apecs_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + if (type == SYS_RES_IRQ) + return isa_release_intr(bus, child, r); + else + return pci_release_resource(bus, child, type, rid, r); +} + static int apecs_setup_intr(device_t dev, device_t child, struct resource *irq, @@ -548,6 +568,13 @@ apecs_setup_intr(device_t dev, device_t child, { int error; + /* + * the avanti routes interrupts through the isa interrupt + * controller, so we need to special case it + */ + if(hwrpb->rpb_type == ST_DEC_2100_A50) + return isa_setup_intr(dev, child, irq, intr, arg, cookiep); + error = rman_activate_resource(irq); if (error) return error; @@ -567,6 +594,13 @@ static int apecs_teardown_intr(device_t dev, device_t child, struct resource *irq, void *cookie) { + /* + * the avanti routes interrupts through the isa interrupt + * controller, so we need to special case it + */ + if(hwrpb->rpb_type == ST_DEC_2100_A50) + return isa_teardown_intr(dev, child, irq, cookie); + alpha_teardown_intr(cookie); return rman_deactivate_resource(irq); } diff --git a/sys/alpha/pci/apecs_pci.c b/sys/alpha/pci/apecs_pci.c new file mode 100644 index 0000000..fb0b339 --- /dev/null +++ b/sys/alpha/pci/apecs_pci.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPEAPECSL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +static devclass_t pcib_devclass; + +static int +apecs_pcib_probe(device_t dev) +{ + device_set_desc(dev, "2107x PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t apecs_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, apecs_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t apecs_pcib_driver = { + "pcib", + apecs_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, apecs, apecs_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/cia.c b/sys/alpha/pci/cia.c index 350df00..e967493 100644 --- a/sys/alpha/pci/cia.c +++ b/sys/alpha/pci/cia.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: cia.c,v 1.14 1998/12/04 22:54:42 archie Exp $ + * $Id: cia.c,v 1.15 1999/03/28 17:52:17 dfr Exp $ */ /*- * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -96,6 +96,7 @@ #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #include <alpha/pci/ciareg.h> @@ -654,6 +655,7 @@ static device_method_t cia_methods[] = { DEVMETHOD(device_attach, cia_attach), /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_alloc_resource, pci_alloc_resource), DEVMETHOD(bus_release_resource, pci_release_resource), DEVMETHOD(bus_activate_resource, pci_activate_resource), @@ -724,11 +726,12 @@ cia_probe(device_t dev) if (cia0) return ENXIO; cia0 = dev; - device_set_desc(dev, "2117x PCI adapter"); /* XXX */ + device_set_desc(dev, "2117x Core Logic chipset"); /* XXX */ pci_init_resources(); + isa_init_intr(); - device_add_child(dev, "isa", 0, 0); + device_add_child(dev, "pcib", 0, 0); return 0; } @@ -736,12 +739,10 @@ cia_probe(device_t dev) static int cia_attach(device_t dev) { - struct cia_softc* sc = CIA_SOFTC(dev); char* name; int pass; cia_init(); - chipset.intrdev = dev; name = cia_ispyxis ? "Pyxis" : "ALCOR/ALCOR2"; if (cia_ispyxis) { @@ -832,6 +833,9 @@ cia_setup_intr(device_t dev, device_t child, /* Enable PCI interrupt */ platform.pci_intr_enable(irq->r_start); + device_printf(child, "interrupting at CIA irq %d\n", + (int) irq->r_start); + return 0; } @@ -844,4 +848,3 @@ cia_teardown_intr(device_t dev, device_t child, } DRIVER_MODULE(cia, root, cia_driver, cia_devclass, 0, 0); - diff --git a/sys/alpha/pci/cia_pci.c b/sys/alpha/pci/cia_pci.c new file mode 100644 index 0000000..e77c3b4 --- /dev/null +++ b/sys/alpha/pci/cia_pci.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +static devclass_t pcib_devclass; + +static int +cia_pcib_probe(device_t dev) +{ + device_set_desc(dev, "2117x PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t cia_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, cia_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t cia_pcib_driver = { + "pcib", + cia_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, cia, cia_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/lca.c b/sys/alpha/pci/lca.c index f3b194d..b60fb3e 100644 --- a/sys/alpha/pci/lca.c +++ b/sys/alpha/pci/lca.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: lca.c,v 1.4 1998/11/15 18:25:16 dfr Exp $ + * $Id: lca.c,v 1.5 1998/12/04 22:54:42 archie Exp $ */ #include <sys/param.h> @@ -35,15 +35,16 @@ #include <alpha/pci/lcareg.h> #include <alpha/pci/lcavar.h> #include <alpha/pci/pcibus.h> -#include <machine/swiz.h> +#include <alpha/isa/isavar.h> #include <machine/intr.h> +#include <machine/resource.h> #include <machine/cpuconf.h> +#include <machine/swiz.h> #define KV(pa) ALPHA_PHYS_TO_K0SEG(pa) static devclass_t lca_devclass; static device_t lca0; /* XXX only one for now */ -static device_t isa0; struct lca_softc { int junk; @@ -333,8 +334,12 @@ lca_write_hae(u_int64_t hae) static int lca_probe(device_t dev); static int lca_attach(device_t dev); -static void *lca_create_intr(device_t dev, device_t child, int irq, driver_intr_t *intr, void *arg); -static int lca_connect_intr(device_t dev, void* ih); +static struct resource *lca_alloc_resource(device_t bus, device_t child, + int type, int *rid, u_long start, + u_long end, u_long count, + u_int flags); +static int lca_release_resource(device_t bus, device_t child, + int type, int rid, struct resource *r); static device_method_t lca_methods[] = { /* Device interface */ @@ -342,10 +347,12 @@ static device_method_t lca_methods[] = { DEVMETHOD(device_attach, lca_attach), /* Bus interface */ - DEVMETHOD(bus_alloc_resource, pci_alloc_resource), - DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_alloc_resource, lca_alloc_resource), + DEVMETHOD(bus_release_resource, lca_release_resource), DEVMETHOD(bus_activate_resource, pci_activate_resource), DEVMETHOD(bus_deactivate_resource, pci_deactivate_resource), + DEVMETHOD(bus_setup_intr, isa_setup_intr), + DEVMETHOD(bus_teardown_intr, isa_teardown_intr), { 0, 0 } }; @@ -380,9 +387,12 @@ lca_probe(device_t dev) if (lca0) return ENXIO; lca0 = dev; - device_set_desc(dev, "21066 PCI adapter"); /* XXX */ + device_set_desc(dev, "21066 Core Logic chipset"); /* XXX */ + + pci_init_resources(); + isa_init_intr(); - isa0 = device_add_child(dev, "isa", 0, 0); + device_add_child(dev, "pcib", 0, 0); return 0; } @@ -393,7 +403,6 @@ lca_attach(device_t dev) struct lca_softc* sc = LCA_SOFTC(dev); lca_init(); - chipset.intrdev = isa0; set_iointr(alpha_dispatch_intr); @@ -408,5 +417,26 @@ lca_attach(device_t dev) return 0; } +static struct resource * +lca_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + if (type == SYS_RES_IRQ) + return isa_alloc_intr(bus, child, start); + else + return pci_alloc_resource(bus, child, type, rid, + start, end, count, flags); +} + +static int +lca_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + if (type == SYS_RES_IRQ) + return isa_release_intr(bus, child, r); + else + return pci_release_resource(bus, child, type, rid, r); +} + DRIVER_MODULE(lca, root, lca_driver, lca_devclass, 0, 0); diff --git a/sys/alpha/pci/lca_pci.c b/sys/alpha/pci/lca_pci.c new file mode 100644 index 0000000..61e3525 --- /dev/null +++ b/sys/alpha/pci/lca_pci.c @@ -0,0 +1,73 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPELCAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +static devclass_t pcib_devclass; + +static int +lca_pcib_probe(device_t dev) +{ + device_set_desc(dev, "21066 PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t lca_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, lca_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t lca_pcib_driver = { + "pcib", + lca_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, lca, lca_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/alpha/pci/pcibus.c b/sys/alpha/pci/pcibus.c index 697373c..ffb726a 100644 --- a/sys/alpha/pci/pcibus.c +++ b/sys/alpha/pci/pcibus.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcibus.c,v 1.7 1998/11/18 23:53:12 dfr Exp $ + * $Id: pcibus.c,v 1.8 1998/12/27 18:03:29 dfr Exp $ * */ @@ -32,6 +32,7 @@ #include <sys/kernel.h> #include <sys/module.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/interrupt.h> #include <sys/sysctl.h> #include <sys/rman.h> @@ -40,6 +41,7 @@ #include <machine/chipset.h> #include <machine/cpuconf.h> #include <machine/resource.h> +#include <alpha/pci/pcibus.h> char chipset_type[10]; int chipset_bwx = 0; @@ -129,6 +131,8 @@ pci_cvt_to_bwx(vm_offset_t sparse) return NULL; } +#if 0 + /* * These can disappear when I update the pci code to use the new * device framework. @@ -160,6 +164,8 @@ intr_connect(struct intrec *idesc) return 0; } +#endif + void alpha_platform_assign_pciintr(pcicfgregs *cfg) { @@ -167,6 +173,20 @@ alpha_platform_assign_pciintr(pcicfgregs *cfg) platform.pci_intr_map((void *)cfg); } +int +alpha_platform_setup_ide_intr(int chan, driver_intr_t *fn, void *arg) +{ + if (platform.pci_setup_ide_intr) + return platform.pci_setup_ide_intr(chan, fn, arg); + else { + int irqs[2] = { 14, 15 }; + void *junk; + struct resource *res; + res = isa_alloc_intr(0, 0, irqs[chan]); + return isa_setup_intr(0, 0, res, fn, arg, &junk); + } +} + static struct rman irq_rman, port_rman, mem_rman; void pci_init_resources() @@ -177,23 +197,23 @@ void pci_init_resources() irq_rman.rm_descr = "PCI Interrupt request lines"; if (rman_init(&irq_rman) || rman_manage_region(&irq_rman, 0, 31)) - panic("cia_probe irq_rman"); + panic("pci_init_resources irq_rman"); port_rman.rm_start = 0; - port_rman.rm_end = 0xffff; + port_rman.rm_end = ~0u; port_rman.rm_type = RMAN_ARRAY; port_rman.rm_descr = "I/O ports"; if (rman_init(&port_rman) - || rman_manage_region(&port_rman, 0, 0xffff)) - panic("cia_probe port_rman"); + || rman_manage_region(&port_rman, 0x0, (1L << 32))) + panic("pci_init_resources port_rman"); mem_rman.rm_start = 0; mem_rman.rm_end = ~0u; mem_rman.rm_type = RMAN_ARRAY; - mem_rman.rm_descr = "I/O memory addresses"; + mem_rman.rm_descr = "I/O memory"; if (rman_init(&mem_rman) || rman_manage_region(&mem_rman, 0x0, (1L << 32))) - panic("cia_probe mem_rman"); + panic("pci_init_resources mem_rman"); } /* @@ -205,6 +225,7 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, u_long start, u_long end, u_long count, u_int flags) { struct rman *rm; + struct resource *rv; switch (type) { case SYS_RES_IRQ: @@ -223,7 +244,20 @@ pci_alloc_resource(device_t bus, device_t child, int type, int *rid, return 0; } - return rman_reserve_resource(rm, start, end, count, flags, child); + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return 0; + + if (type == SYS_RES_MEMORY) { + rman_set_bustag(rv, ALPHA_BUS_SPACE_MEM); + rman_set_bushandle(rv, rv->r_start); + rman_set_virtual(rv, (void *) rv->r_start); /* XXX */ + } else if (type == SYS_RES_IOPORT) { + rman_set_bustag(rv, ALPHA_BUS_SPACE_IO); + rman_set_bushandle(rv, rv->r_start); + } + + return rv; } int @@ -266,12 +300,37 @@ memcpy_toio(u_int32_t d, void *s, size_t size) } void +memcpy_io(u_int32_t d, u_int32_t s, size_t size) +{ + while (size--) + writeb(d++, readb(s++)); +} + +void memset_io(u_int32_t d, int val, size_t size) { while (size--) writeb(d++, val); } +void +memsetw(void *d, int val, size_t size) +{ + u_int16_t *sp = d; + + while (size--) + *sp++ = val; +} + +void +memsetw_io(u_int32_t d, int val, size_t size) +{ + while (size--) { + writew(d, val); + d += sizeof(u_int16_t); + } +} + #include "opt_ddb.h" #ifdef DDB #include <ddb/ddb.h> @@ -280,7 +339,6 @@ DB_COMMAND(in, db_in) { int c; int size; - u_int32_t val; if (!have_addr) return; @@ -307,7 +365,7 @@ DB_COMMAND(in, db_in) if (count <= 0) count = 1; while (--count >= 0) { - db_printf("%08x:\t", addr); + db_printf("%08lx:\t", addr); switch (size) { case 1: db_printf("%02x\n", inb(addr)); diff --git a/sys/alpha/tc/tc.c b/sys/alpha/tc/tc.c index 0c88726..dd99f14 100644 --- a/sys/alpha/tc/tc.c +++ b/sys/alpha/tc/tc.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: tc.c,v 1.1 1998/08/20 08:27:10 dfr Exp $ */ /* * Copyright (c) 1994, 1995, 1996 Carnegie-Mellon University. * All rights reserved. @@ -568,8 +568,6 @@ tc_attach(device_t dev) tc0 = dev; - chipset.intrdev = dev; - switch(hwrpb->rpb_type){ #ifdef DEC_3000_300 case ST_DEC_3000_300: diff --git a/sys/alpha/tc/tcasic.c b/sys/alpha/tc/tcasic.c index 1dd4fee..eeb6953 100644 --- a/sys/alpha/tc/tcasic.c +++ b/sys/alpha/tc/tcasic.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: tcasic.c,v 1.1 1998/08/20 08:27:11 dfr Exp $ */ /* from $NetBSD: tcasic.c,v 1.23 1998/05/14 00:01:31 thorpej Exp $ */ /* @@ -97,7 +97,6 @@ tcasic_attach(device_t dev) tcasic0 = dev; /* chipset = tcasic_chipset;*/ - chipset.intrdev = dev; device_probe_and_attach(tc0); return 0; } diff --git a/sys/alpha/tlsb/dwlpx.c b/sys/alpha/tlsb/dwlpx.c index bb80abf..5a2a5cd 100644 --- a/sys/alpha/tlsb/dwlpx.c +++ b/sys/alpha/tlsb/dwlpx.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: dwlpx.c,v 1.6 1998/09/04 08:01:26 dfr Exp $ + * $Id: dwlpx.c,v 1.7 1998/11/15 18:25:16 dfr Exp $ */ #include "opt_simos.h" @@ -293,7 +293,7 @@ dwlpx_attach(device_t dev) dwlpx0 = dev; chipset = dwlpx_chipset; - chipset.intrdev = dev; + /* chipset.intrdev = dev; */ regs = KV(DWLPX_BASE(kft_get_node(dev), kft_get_hosenum(dev))); sc->dmem_base = regs + (0L << 32); diff --git a/sys/amd64/amd64/autoconf.c b/sys/amd64/amd64/autoconf.c index fc7ab85..c501281 100644 --- a/sys/amd64/amd64/autoconf.c +++ b/sys/amd64/amd64/autoconf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.111 1999/01/19 00:10:59 peter Exp $ + * $Id: autoconf.c,v 1.112 1999/04/15 14:52:24 bde Exp $ */ /* @@ -50,9 +50,11 @@ #include "opt_cd9660.h" #include "opt_mfs.h" #include "opt_nfsroot.h" +#include "opt_bus.h" #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/conf.h> #include <sys/disklabel.h> #include <sys/diskslice.h> @@ -74,13 +76,19 @@ #include "isa.h" #if NISA > 0 +#ifdef OLD_BUS_ARCH #include <i386/isa/isa_device.h> +#else +device_t isa_bus_device = 0; +#endif /* OLD_BUS_ARCH */ #endif #include "pnp.h" #if NPNP > 0 +#ifdef OLD_BUS_ARCH #include <i386/isa/pnp.h> #endif +#endif #include "eisa.h" #if NEISA > 0 @@ -92,8 +100,6 @@ #include <pci/pcivar.h> #endif -#include <sys/bus.h> - static void configure_first __P((void *)); static void configure __P((void *)); static void configure_final __P((void *)); @@ -186,6 +192,8 @@ configure_finish() { } +device_t nexus_dev; + /* * Determine i/o configuration for a machine. */ @@ -228,21 +236,21 @@ configure(dummy) eisa_configure(); #endif -#if NPCI > 0 - pci_configure(); -#endif - #if NPNP > 0 pnp_configure(); #endif -#if NISA > 0 - isa_configure(); -#endif + /* nexus0 is the top of the i386 device tree */ + device_add_child(root_bus, "nexus", 0, 0); /* initialize new bus architecture */ root_bus_configure(); +#if NISA > 0 + if (isa_bus_device) + bus_generic_attach(isa_bus_device); +#endif + /* * Now we're ready to handle (pending) interrupts. * XXX this is slightly misplaced. diff --git a/sys/amd64/amd64/exception.S b/sys/amd64/amd64/exception.S index 79e1d1a..a9286fa 100644 --- a/sys/amd64/amd64/exception.S +++ b/sys/amd64/amd64/exception.S @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.56 1999/02/25 11:03:08 bde Exp $ + * $Id: exception.s,v 1.57 1999/02/28 10:53:28 bde Exp $ */ #include "npx.h" @@ -139,7 +139,7 @@ IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can - * call npxintr to clear the error. It would be better to handle + * call npx_intr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. @@ -180,7 +180,7 @@ IDTVEC(fpu) movl %eax,_cpl #endif /* SMP */ - call _npxintr + call _npx_intr incb _intr_nesting_level MEXITCOUNT diff --git a/sys/amd64/amd64/exception.s b/sys/amd64/amd64/exception.s index 79e1d1a..a9286fa 100644 --- a/sys/amd64/amd64/exception.s +++ b/sys/amd64/amd64/exception.s @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.56 1999/02/25 11:03:08 bde Exp $ + * $Id: exception.s,v 1.57 1999/02/28 10:53:28 bde Exp $ */ #include "npx.h" @@ -139,7 +139,7 @@ IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can - * call npxintr to clear the error. It would be better to handle + * call npx_intr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. @@ -180,7 +180,7 @@ IDTVEC(fpu) movl %eax,_cpl #endif /* SMP */ - call _npxintr + call _npx_intr incb _intr_nesting_level MEXITCOUNT diff --git a/sys/amd64/amd64/fpu.c b/sys/amd64/amd64/fpu.c index 2371e7b..dc2eb73 100644 --- a/sys/amd64/amd64/fpu.c +++ b/sys/amd64/amd64/fpu.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.65 1999/01/08 16:29:59 bde Exp $ + * $Id: npx.c,v 1.66 1999/03/28 23:28:18 dt Exp $ */ #include "npx.h" @@ -43,10 +43,14 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/sysctl.h> #include <sys/proc.h> +#include <machine/bus.h> +#include <sys/rman.h> #ifdef NPX_DEBUG #include <sys/syslog.h> #endif @@ -64,6 +68,7 @@ #ifndef SMP #include <machine/clock.h> #endif +#include <machine/resource.h> #include <machine/specialreg.h> #include <machine/segments.h> @@ -72,7 +77,6 @@ #include <i386/isa/intr_machdep.h> #include <i386/isa/isa.h> #endif -#include <i386/isa/isa_device.h> /* * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. @@ -83,9 +87,6 @@ #define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) -/* XXX - should be in header file. */ -ointhand2_t npxintr; - #ifdef __GNUC__ #define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr))) @@ -119,18 +120,15 @@ void stop_emulating __P((void)); typedef u_char bool_t; -static int npxattach __P((struct isa_device *dvp)); -static int npxprobe __P((struct isa_device *dvp)); -static int npxprobe1 __P((struct isa_device *dvp)); +static int npx_attach __P((device_t dev)); + void npx_intr __P((void *)); +static int npx_probe __P((device_t dev)); +static int npx_probe1 __P((device_t dev)); #ifdef I586_CPU static long timezero __P((const char *funcname, void (*func)(void *buf, size_t len))); #endif /* I586_CPU */ -struct isa_driver npxdriver = { - npxprobe, npxattach, "npx", -}; - int hw_float; /* XXX currently just alias for npx_exists */ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, @@ -191,12 +189,13 @@ __asm(" \n\ * need to use interrupts. Return 1 if device exists. */ static int -npxprobe(dvp) - struct isa_device *dvp; +npx_probe(dev) + device_t dev; { -#ifdef SMP +/*#ifdef SMP*/ +#if 1 - return npxprobe1(dvp); + return npx_probe1(dev); #else /* SMP */ @@ -213,20 +212,20 @@ npxprobe(dvp) * install suitable handlers and run with interrupts enabled so we * won't need to do so much here. */ - npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1; + npx_intrno = NRSVIDT + 13; save_eflags = read_eflags(); disable_intr(); save_icu1_mask = inb(IO_ICU1 + 1); save_icu2_mask = inb(IO_ICU2 + 1); save_idt_npxintr = idt[npx_intrno]; save_idt_npxtrap = idt[16]; - outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq)); - outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8)); + outb(IO_ICU1 + 1, ~IRQ_SLAVE); + outb(IO_ICU2 + 1, ~(1 << (13 - 8))); setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); npx_idt_probeintr = idt[npx_intrno]; enable_intr(); - result = npxprobe1(dvp); + result = npx_probe1(dev); disable_intr(); outb(IO_ICU1 + 1, save_icu1_mask); outb(IO_ICU2 + 1, save_icu2_mask); @@ -239,8 +238,8 @@ npxprobe(dvp) } static int -npxprobe1(dvp) - struct isa_device *dvp; +npx_probe1(dev) + device_t dev; { #ifndef SMP u_short control; @@ -280,21 +279,18 @@ npxprobe1(dvp) */ fninit(); -#ifdef SMP - +/*#ifdef SMP*/ +#if 1 /* * Exception 16 MUST work for SMP. */ npx_irq13 = 0; npx_ex16 = hw_float = npx_exists = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + device_set_desc(dev, "math processor"); + return (0); -#else /* SMP */ +#else /* !SMP */ + device_set_desc(dev, "math processor"); /* * Don't use fwait here because it might hang. @@ -335,14 +331,12 @@ npxprobe1(dvp) * Good, exception 16 works. */ npx_ex16 = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + return (0); } if (npx_intrs_while_probing != 0) { + int rid; + struct resource *r; + void *intr; /* * Bad, we are stuck with IRQ13. */ @@ -350,8 +344,30 @@ npxprobe1(dvp) /* * npxattach would be too late to set npx0_imask. */ - npx0_imask |= dvp->id_irq; - return (IO_NPXSIZE); + npx0_imask |= (1 << 13); + + /* + * We allocate these resources permanently, + * so there is no need to keep track of them. + */ + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IOPORT, + &rid, IO_NPX, IO_NPX, + IO_NPXSIZE, RF_ACTIVE); + if (r == 0) + panic("npx: can't get ports"); + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, 13, 13, + 1, RF_ACTIVE); + if (r == 0) + panic("npx: can't get IRQ"); + BUS_SETUP_INTR(device_get_parent(dev), + dev, r, npx_intr, 0, &intr); + if (intr == 0) + panic("npx: can't create intr"); + + return (0); } /* * Worse, even IRQ13 is broken. Use emulator. @@ -363,13 +379,7 @@ npxprobe1(dvp) * emulator and say that it has been installed. XXX handle devices * that aren't really devices better. */ - dvp->id_irq = 0; - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - + return (0); #endif /* SMP */ } @@ -377,14 +387,15 @@ npxprobe1(dvp) * Attach routine - announce which it is, and wire into system */ int -npxattach(dvp) - struct isa_device *dvp; +npx_attach(dev) + device_t dev; { - dvp->id_ointr = npxintr; + int flags; - /* The caller has printed "irq 13" for the npx_irq13 case. */ - if (!npx_irq13) { - printf("npx%d: ", dvp->id_unit); + device_print_prettyname(dev); + if (npx_irq13) { + printf("using IRQ 13 interface\n"); + } else { if (npx_ex16) printf("INT 16 interface\n"); #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) @@ -401,23 +412,26 @@ npxattach(dvp) npxinit(__INITIAL_NPXCW__); #ifdef I586_CPU + if (resource_int_value("npx", 0, "flags", &flags) != 0) + flags = 0; + if (cpu_class == CPUCLASS_586 && npx_ex16 && timezero("i586_bzero()", i586_bzero) < timezero("bzero()", bzero) * 4 / 5) { - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { bcopy_vector = i586_bcopy; ovbcopy_vector = i586_bcopy; } - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) bzero = i586_bzero; - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { copyin_vector = i586_copyin; copyout_vector = i586_copyout; } } #endif - return (1); /* XXX unused */ + return (0); /* XXX unused */ } /* @@ -494,8 +508,8 @@ npxexit(p) * solution for signals other than SIGFPE. */ void -npxintr(unit) - int unit; +npx_intr(dummy) + void *dummy; { int code; struct intrframe *frame; @@ -518,7 +532,7 @@ npxintr(unit) /* * Pass exception to process. */ - frame = (struct intrframe *)&unit; /* XXX */ + frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* * Interrupt is essentially a trap, so we can afford to call @@ -686,4 +700,31 @@ timezero(funcname, func) } #endif /* I586_CPU */ +static device_method_t npx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, npx_probe), + DEVMETHOD(device_attach, npx_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), + + { 0, 0 } +}; + +static driver_t npx_driver = { + "npx", + npx_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + +static devclass_t npx_devclass; + +/* + * We prefer to attach to the root nexus so that the usual case (exception 16) + * doesn't describe the processor as being `on isa'. + */ +DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0); + #endif /* NNPX > 0 */ diff --git a/sys/amd64/amd64/legacy.c b/sys/amd64/amd64/legacy.c new file mode 100644 index 0000000..7df4387 --- /dev/null +++ b/sys/amd64/amd64/legacy.c @@ -0,0 +1,409 @@ +/* + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * This code implements a `root nexus' for Intel Architecture + * machines. The function of the root nexus is to serve as an + * attachment point for both processors and buses, and to manage + * resources which are common to all of them. In particular, + * this code implements the core resource managers for interrupt + * requests, DMA requests (which rightfully should be a part of the + * ISA code but it's easier to do it here for now), I/O port addresses, + * and I/O memory address space. + */ + +#include "opt_smp.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/ipl.h> +#include <machine/resource.h> +#ifdef APIC_IO +#include <machine/smp.h> +#include <machine/mpapic.h> +#endif + +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/intr_machdep.h> + +#include <pci/pcivar.h> + +#include "eisa.h" +#include "isa.h" +#include "pci.h" +#include "npx.h" +#include "apm.h" + +static struct rman irq_rman, drq_rman, port_rman, mem_rman; + +static int nexus_probe(device_t); +static void nexus_print_child(device_t, device_t); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_release_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_setup_intr(device_t, device_t, struct resource *, + void (*)(void *), void *, void **); +static int nexus_teardown_intr(device_t, device_t, struct resource *, + void *); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, nexus_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_release_resource, nexus_release_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_driver = { + "nexus", + nexus_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; +static devclass_t nexus_devclass; + +DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); + +#ifdef APIC_IO +#define LASTIRQ (NINTR - 1) +#else +#define LASTIRQ 15 +#endif + +static int +nexus_probe(device_t dev) +{ + device_t child; + + device_quiet(dev); /* suppress attach message for neatness */ + + irq_rman.rm_start = 0; + irq_rman.rm_end = LASTIRQ; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, 0, 1) + || rman_manage_region(&irq_rman, 3, LASTIRQ)) + panic("nexus_probe irq_rman"); + + drq_rman.rm_start = 0; + drq_rman.rm_end = 7; + drq_rman.rm_type = RMAN_ARRAY; + drq_rman.rm_descr = "DMA request lines"; + /* XXX drq 0 not available on some machines */ + if (rman_init(&drq_rman) + || rman_manage_region(&drq_rman, 0, 7)) + panic("nexus_probe drq_rman"); + + port_rman.rm_start = 0; + port_rman.rm_end = 0xffff; + port_rman.rm_type = RMAN_ARRAY; + port_rman.rm_descr = "I/O ports"; + if (rman_init(&port_rman) + || rman_manage_region(&port_rman, 0, 0xffff)) + panic("nexus_probe port_rman"); + + mem_rman.rm_start = 0; + mem_rman.rm_end = ~0u; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "I/O memory addresses"; + if (rman_init(&mem_rman) + || rman_manage_region(&mem_rman, 0, ~0)) + panic("nexus_probe mem_rman"); + +#if NNPX > 0 + child = device_add_child(dev, "npx", 0, 0); + if (child == 0) + panic("nexus_probe npx"); +#endif /* NNPX > 0 */ +#if NAPM > 0 + child = device_add_child(dev, "apm", 0, 0); + if (child == 0) + panic("nexus_probe apm"); +#endif /* NAPM > 0 */ +#if NPCI > 0 + /* Add a PCI bridge if pci bus is present */ + if (pci_cfgopen() != 0) { + child = device_add_child(dev, "pcib", 0, 0); + if (child == 0) + panic("nexus_probe pcib"); + } +#endif +#if 0 && NEISA > 0 + child = device_add_child(dev, "eisa", 0, 0); + if (child == 0) + panic("nexus_probe eisa"); +#endif +#if NISA > 0 + /* Add an ISA bus directly if pci bus is not present */ + if (pci_cfgopen() == 0) { + child = device_add_child(dev, "isa", 0, 0); + if (child == 0) + panic("nexus_probe isa"); + } +#endif + return 0; +} + +static void +nexus_print_child(device_t bus, device_t child) +{ + printf(" on motherboard"); +} + +/* + * Allocate a resource on behalf of child. NB: child is usually going to be a + * child of one of our descendants, not a direct child of nexus0. + * (Exceptions include npx.) + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *rv; + struct rman *rm; + + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + + case SYS_RES_DRQ: + rm = &drq_rman; + break; + + case SYS_RES_IOPORT: + rm = &port_rman; + break; + + case SYS_RES_MEMORY: + rm = &mem_rman; + break; + + default: + return 0; + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return 0; + + if (type == SYS_RES_MEMORY) { + caddr_t vaddr = 0; + + if (rv->r_end < 1024 * 1024 * 1024) { + /* + * The first 1Mb is mapped at KERNBASE. + */ + vaddr = (caddr_t)((uintptr_t)KERNBASE + rv->r_start); + } else { + u_int32_t paddr; + u_int32_t psize; + u_int32_t poffs; + + paddr = rv->r_start; + psize = rv->r_end - rv->r_start; + + poffs = paddr - trunc_page(paddr); + vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs; + } + rman_set_virtual(rv, vaddr); + rman_set_bustag(rv, I386_BUS_SPACE_MEM); + rman_set_bushandle(rv, (bus_space_handle_t) vaddr); + } else if (type == SYS_RES_IOPORT) { + rman_set_bustag(rv, I386_BUS_SPACE_IO); + rman_set_bushandle(rv, rv->r_start); + } + return rv; +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_activate_resource(r)); +} + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_deactivate_resource(r)); +} + +static int +nexus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_release_resource(r)); +} + +/* + * Currently this uses the really grody interface from kern/kern_intr.c + * (which really doesn't belong in kern/anything.c). Eventually, all of + * the code in kern_intr.c and machdep_intr.c should get moved here, since + * this is going to be the official interface. + */ +static int +nexus_setup_intr(device_t bus, device_t child, struct resource *irq, + void (*ihand)(void *), void *arg, void **cookiep) +{ + intrmask_t *mask; + driver_t *driver; + int error, icflags; + + if (child) + device_printf(child, "interrupting at irq %d\n", + (int)irq->r_start); + + *cookiep = 0; + if (irq->r_flags & RF_SHAREABLE) + icflags = 0; + else + icflags = INTR_EXCL; + + driver = device_get_driver(child); + switch (driver->type) { + case DRIVER_TYPE_TTY: + mask = &tty_imask; + break; + case (DRIVER_TYPE_TTY | DRIVER_TYPE_FAST): + mask = &tty_imask; + icflags |= INTR_FAST; + break; + case DRIVER_TYPE_BIO: + mask = &bio_imask; + break; + case DRIVER_TYPE_NET: + mask = &net_imask; + break; + case DRIVER_TYPE_CAM: + mask = &cam_imask; + break; + case DRIVER_TYPE_MISC: + mask = 0; + break; + default: + panic("still using grody create_intr interface"); + } + + /* + * We depend here on rman_activate_resource() being idempotent. + */ + error = rman_activate_resource(irq); + if (error) + return (error); + + *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg, + mask, icflags); + if (*cookiep) + error = intr_connect(*cookiep); + else + error = EINVAL; /* XXX ??? */ + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + return (intr_destroy(ih)); +} + +static devclass_t pcib_devclass; + +static int +nexus_pcib_probe(device_t dev) +{ + device_set_desc(dev, "PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t nexus_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_pcib_driver = { + "pcib", + nexus_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/amd64/amd64/machdep.c b/sys/amd64/amd64/machdep.c index 6ed3182..6980279 100644 --- a/sys/amd64/amd64/machdep.c +++ b/sys/amd64/amd64/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.327 1999/03/06 04:46:18 wollman Exp $ + * $Id: machdep.c,v 1.328 1999/04/03 22:19:58 jdp Exp $ */ #include "apm.h" @@ -71,6 +71,7 @@ #include <sys/sysent.h> #include <sys/sysctl.h> #include <sys/vmmeter.h> +#include <sys/bus.h> #ifdef SYSVSHM #include <sys/shm.h> @@ -125,7 +126,9 @@ #include <machine/perfmon.h> #endif +#ifdef OLD_BUS_ARCH #include <i386/isa/isa_device.h> +#endif #include <i386/isa/intr_machdep.h> #ifndef VM86 #include <i386/isa/rtc.h> @@ -1164,8 +1167,10 @@ init386(first) unsigned biosbasemem, biosextmem; struct gate_descriptor *gdp; int gsel_tss; +#if NNPX > 0 + int msize; +#endif - struct isa_device *idp; #ifndef SMP /* table descriptors - used to load tables by microp */ struct region_descriptor r_gdt, r_idt; @@ -1454,10 +1459,11 @@ init386(first) #endif #if NNPX > 0 - idp = find_isadev(isa_devtab_null, &npxdriver, 0); - if (idp != NULL && idp->id_msize != 0) { - Maxmem = idp->id_msize / 4; - speculative_mprobe = FALSE; + if (resource_int_value("npx", 0, "msize", &msize) == 0) { + if (msize != 0) { + Maxmem = msize / 4; + speculative_mprobe = FALSE; + } } #endif diff --git a/sys/amd64/amd64/nexus.c b/sys/amd64/amd64/nexus.c new file mode 100644 index 0000000..7df4387 --- /dev/null +++ b/sys/amd64/amd64/nexus.c @@ -0,0 +1,409 @@ +/* + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * This code implements a `root nexus' for Intel Architecture + * machines. The function of the root nexus is to serve as an + * attachment point for both processors and buses, and to manage + * resources which are common to all of them. In particular, + * this code implements the core resource managers for interrupt + * requests, DMA requests (which rightfully should be a part of the + * ISA code but it's easier to do it here for now), I/O port addresses, + * and I/O memory address space. + */ + +#include "opt_smp.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/ipl.h> +#include <machine/resource.h> +#ifdef APIC_IO +#include <machine/smp.h> +#include <machine/mpapic.h> +#endif + +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/intr_machdep.h> + +#include <pci/pcivar.h> + +#include "eisa.h" +#include "isa.h" +#include "pci.h" +#include "npx.h" +#include "apm.h" + +static struct rman irq_rman, drq_rman, port_rman, mem_rman; + +static int nexus_probe(device_t); +static void nexus_print_child(device_t, device_t); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_release_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_setup_intr(device_t, device_t, struct resource *, + void (*)(void *), void *, void **); +static int nexus_teardown_intr(device_t, device_t, struct resource *, + void *); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, nexus_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_release_resource, nexus_release_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_driver = { + "nexus", + nexus_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; +static devclass_t nexus_devclass; + +DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); + +#ifdef APIC_IO +#define LASTIRQ (NINTR - 1) +#else +#define LASTIRQ 15 +#endif + +static int +nexus_probe(device_t dev) +{ + device_t child; + + device_quiet(dev); /* suppress attach message for neatness */ + + irq_rman.rm_start = 0; + irq_rman.rm_end = LASTIRQ; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, 0, 1) + || rman_manage_region(&irq_rman, 3, LASTIRQ)) + panic("nexus_probe irq_rman"); + + drq_rman.rm_start = 0; + drq_rman.rm_end = 7; + drq_rman.rm_type = RMAN_ARRAY; + drq_rman.rm_descr = "DMA request lines"; + /* XXX drq 0 not available on some machines */ + if (rman_init(&drq_rman) + || rman_manage_region(&drq_rman, 0, 7)) + panic("nexus_probe drq_rman"); + + port_rman.rm_start = 0; + port_rman.rm_end = 0xffff; + port_rman.rm_type = RMAN_ARRAY; + port_rman.rm_descr = "I/O ports"; + if (rman_init(&port_rman) + || rman_manage_region(&port_rman, 0, 0xffff)) + panic("nexus_probe port_rman"); + + mem_rman.rm_start = 0; + mem_rman.rm_end = ~0u; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "I/O memory addresses"; + if (rman_init(&mem_rman) + || rman_manage_region(&mem_rman, 0, ~0)) + panic("nexus_probe mem_rman"); + +#if NNPX > 0 + child = device_add_child(dev, "npx", 0, 0); + if (child == 0) + panic("nexus_probe npx"); +#endif /* NNPX > 0 */ +#if NAPM > 0 + child = device_add_child(dev, "apm", 0, 0); + if (child == 0) + panic("nexus_probe apm"); +#endif /* NAPM > 0 */ +#if NPCI > 0 + /* Add a PCI bridge if pci bus is present */ + if (pci_cfgopen() != 0) { + child = device_add_child(dev, "pcib", 0, 0); + if (child == 0) + panic("nexus_probe pcib"); + } +#endif +#if 0 && NEISA > 0 + child = device_add_child(dev, "eisa", 0, 0); + if (child == 0) + panic("nexus_probe eisa"); +#endif +#if NISA > 0 + /* Add an ISA bus directly if pci bus is not present */ + if (pci_cfgopen() == 0) { + child = device_add_child(dev, "isa", 0, 0); + if (child == 0) + panic("nexus_probe isa"); + } +#endif + return 0; +} + +static void +nexus_print_child(device_t bus, device_t child) +{ + printf(" on motherboard"); +} + +/* + * Allocate a resource on behalf of child. NB: child is usually going to be a + * child of one of our descendants, not a direct child of nexus0. + * (Exceptions include npx.) + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *rv; + struct rman *rm; + + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + + case SYS_RES_DRQ: + rm = &drq_rman; + break; + + case SYS_RES_IOPORT: + rm = &port_rman; + break; + + case SYS_RES_MEMORY: + rm = &mem_rman; + break; + + default: + return 0; + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return 0; + + if (type == SYS_RES_MEMORY) { + caddr_t vaddr = 0; + + if (rv->r_end < 1024 * 1024 * 1024) { + /* + * The first 1Mb is mapped at KERNBASE. + */ + vaddr = (caddr_t)((uintptr_t)KERNBASE + rv->r_start); + } else { + u_int32_t paddr; + u_int32_t psize; + u_int32_t poffs; + + paddr = rv->r_start; + psize = rv->r_end - rv->r_start; + + poffs = paddr - trunc_page(paddr); + vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs; + } + rman_set_virtual(rv, vaddr); + rman_set_bustag(rv, I386_BUS_SPACE_MEM); + rman_set_bushandle(rv, (bus_space_handle_t) vaddr); + } else if (type == SYS_RES_IOPORT) { + rman_set_bustag(rv, I386_BUS_SPACE_IO); + rman_set_bushandle(rv, rv->r_start); + } + return rv; +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_activate_resource(r)); +} + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_deactivate_resource(r)); +} + +static int +nexus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_release_resource(r)); +} + +/* + * Currently this uses the really grody interface from kern/kern_intr.c + * (which really doesn't belong in kern/anything.c). Eventually, all of + * the code in kern_intr.c and machdep_intr.c should get moved here, since + * this is going to be the official interface. + */ +static int +nexus_setup_intr(device_t bus, device_t child, struct resource *irq, + void (*ihand)(void *), void *arg, void **cookiep) +{ + intrmask_t *mask; + driver_t *driver; + int error, icflags; + + if (child) + device_printf(child, "interrupting at irq %d\n", + (int)irq->r_start); + + *cookiep = 0; + if (irq->r_flags & RF_SHAREABLE) + icflags = 0; + else + icflags = INTR_EXCL; + + driver = device_get_driver(child); + switch (driver->type) { + case DRIVER_TYPE_TTY: + mask = &tty_imask; + break; + case (DRIVER_TYPE_TTY | DRIVER_TYPE_FAST): + mask = &tty_imask; + icflags |= INTR_FAST; + break; + case DRIVER_TYPE_BIO: + mask = &bio_imask; + break; + case DRIVER_TYPE_NET: + mask = &net_imask; + break; + case DRIVER_TYPE_CAM: + mask = &cam_imask; + break; + case DRIVER_TYPE_MISC: + mask = 0; + break; + default: + panic("still using grody create_intr interface"); + } + + /* + * We depend here on rman_activate_resource() being idempotent. + */ + error = rman_activate_resource(irq); + if (error) + return (error); + + *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg, + mask, icflags); + if (*cookiep) + error = intr_connect(*cookiep); + else + error = EINVAL; /* XXX ??? */ + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + return (intr_destroy(ih)); +} + +static devclass_t pcib_devclass; + +static int +nexus_pcib_probe(device_t dev) +{ + device_set_desc(dev, "PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t nexus_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_pcib_driver = { + "pcib", + nexus_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC index 60cc225..03e74ce 100644 --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC,v 1.160 1999/04/16 16:17:05 n_hibma Exp $ +# $Id: GENERIC,v 1.161 1999/04/16 18:27:18 jkh Exp $ machine "i386" cpu "I386_CPU" @@ -53,10 +53,10 @@ config kernel root on wd0 #options NAPIC=1 # number of IO APICs #options NINTR=24 # number of INTs -controller isa0 -controller pnp0 # PnP support for ISA -controller eisa0 -controller pci0 +controller isa0 at nexus? +#controller pnp0 # PnP support for ISA +#controller eisa0 +controller pci0 at nexus? controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 disk fd0 at fdc0 drive 0 @@ -108,9 +108,9 @@ controller matcd0 at isa? port 0x230 bio device scd0 at isa? port 0x230 bio # atkbdc0 controlls both the keyboard and the PS/2 mouse -controller atkbdc0 at isa? port IO_KBD tty -device atkbd0 at isa? tty irq 1 -device psm0 at isa? tty irq 12 +controller atkbdc0 at isa? port IO_KBD +device atkbd0 at atkbdc? tty irq 1 +device psm0 at atkbdc? tty irq 12 device vga0 at isa? port ? conflicts @@ -126,12 +126,12 @@ device sc0 at isa? tty # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines #options PCVT_SCANSET=2 # IBM keyboards are non-std -device npx0 at isa? port IO_NPX irq 13 +device npx0 at nexus? port IO_NPX irq 13 # # Laptop support (see LINT for more options) # -device apm0 at isa? disable flags 0x31 # Advanced Power Management +device apm0 at nexus? disable flags 0x31 # Advanced Power Management # PCCARD (PCMCIA) support #controller card0 @@ -178,8 +178,8 @@ device ex0 at isa? port? net irq? device fe0 at isa? port 0x300 net irq ? device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 device lnc0 at isa? port 0x280 net irq 10 drq 0 -device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 -device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 +#device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 +#device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 device cs0 at isa? port 0x300 net irq ? pseudo-device loop diff --git a/sys/amd64/isa/intr_machdep.c b/sys/amd64/isa/intr_machdep.c index 944eb4e..4f7c1e9 100644 --- a/sys/amd64/isa/intr_machdep.c +++ b/sys/amd64/isa/intr_machdep.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.16 1999/01/08 19:17:48 bde Exp $ + * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $ */ #include "opt_auto_eoi.h" @@ -328,6 +328,7 @@ isa_get_nameunit(int id) return ("clk0"); /* XXX may also be sloppy driver */ if (id == 1) return ("rtc0"); +#if 0 for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; @@ -343,6 +344,7 @@ isa_get_nameunit(int id) for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; +#endif return "???"; found_device: diff --git a/sys/amd64/isa/isa.c b/sys/amd64/isa/isa.c index 1e91da8..4b48e36 100644 --- a/sys/amd64/isa/isa.c +++ b/sys/amd64/isa/isa.c @@ -1,10 +1,7 @@ /*- - * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1998 Doug Rabson * All rights reserved. * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -13,18 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -33,1041 +23,601 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $ + * $Id: isa.c,v 1.4 1998/09/16 08:23:51 dfr Exp $ */ /* - * code to manage AT bus + * Modifications for Intel architecture by Garrett A. Wollman. + * Copyright 1998 Massachusetts Institute of Technology * - * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): - * Fixed uninitialized variable problem and added code to deal - * with DMA page boundaries in isa_dmarangecheck(). Fixed word - * mode DMA count compution and reorganized DMA setup code in - * isa_dmastart() + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> -#include <sys/buf.h> +#include <sys/kernel.h> +#include <sys/bus.h> #include <sys/malloc.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#ifdef APIC_IO -#include <machine/smp.h> -#endif /* APIC_IO */ -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/intr_machdep.h> -#include <i386/isa/isa.h> -#include <i386/isa/ic/i8237.h> - -#include <sys/interrupt.h> - -#include "pnp.h" -#if NPNP > 0 -#include <i386/isa/pnp.h> -#endif +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> -/* -** Register definitions for DMA controller 1 (channels 0..3): -*/ -#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ -#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ -#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ -#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ +#include <machine/resource.h> -/* -** Register definitions for DMA controller 2 (channels 4..7): -*/ -#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ -#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ -#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ -#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ +#include <isa/isavar.h> -static void config_isadev __P((struct isa_device *isdp, u_int *mp)); -static void config_isadev_c __P((struct isa_device *isdp, u_int *mp, - int reconfig)); -static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, - int item, char const *whatnot, char const *reason, - char const *format)); -static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, - u_int checkbits)); -static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); +MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); /* - * print a conflict message + * The structure used to attach devices to the isa bus. */ +struct isa_device { + short 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; + static void -conflict(dvp, tmpdvp, item, whatnot, reason, format) - struct isa_device *dvp; - struct isa_device *tmpdvp; - int item; - char const *whatnot; - char const *reason; - char const *format; +isa_add_device(device_t dev, const char *name, int unit) { - printf("%s%d not %sed due to %s conflict with %s%d at ", - dvp->id_driver->name, dvp->id_unit, whatnot, reason, - tmpdvp->id_driver->name, tmpdvp->id_unit); - printf(format, item); - printf("\n"); -} + struct isa_device *idev; + device_t child; + int sensitive, t; + static device_t last_sensitive; -/* - * Check to see if things are already in use, like IRQ's, I/O addresses - * and Memory addresses. - */ -static int -haveseen(dvp, tmpdvp, checkbits) - struct isa_device *dvp; - struct isa_device *tmpdvp; - u_int checkbits; -{ - /* - * Ignore all conflicts except IRQ ones if conflicts are allowed. - */ - if (dvp->id_conflicts) - checkbits &= ~(CC_DRQ | CC_IOADDR | CC_MEMADDR); - /* - * Only check against devices that have already been found. - */ - if (tmpdvp->id_alive) { - char const *whatnot; + if (resource_int_value(name, unit, "sensitive", &sensitive) != 0) + sensitive = 0; - /* - * Check for device driver & unit conflict; just drop probing - * a device which has already probed true. This is usually - * not strictly a conflict, but rather the case of somebody - * having specified several mutually exclusive configurations - * for a single device. - */ - if (tmpdvp->id_driver == dvp->id_driver && - tmpdvp->id_unit == dvp->id_unit) { - return 1; - } + idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT); + if (!idev) + return; + bzero(idev, sizeof *idev); - whatnot = checkbits & CC_ATTACH ? "attach" : "prob"; - /* - * Check for I/O address conflict. We can only check the - * starting address of the device against the range of the - * device that has already been probed since we do not - * know how many I/O addresses this device uses. - */ - if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { - if ((dvp->id_iobase >= tmpdvp->id_iobase) && - (dvp->id_iobase <= - (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_iobase, - whatnot, "I/O address", "0x%x"); - return 1; - } - } - /* - * Check for Memory address conflict. We can check for - * range overlap, but it will not catch all cases since the - * driver may adjust the msize paramater during probe, for - * now we just check that the starting address does not - * fall within any allocated region. - * XXX could add a second check after the probe for overlap, - * since at that time we would know the full range. - * XXX KERNBASE is a hack, we should have vaddr in the table! - */ - if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { - if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && - (KERNBASE + dvp->id_maddr <= - (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - (int)dvp->id_maddr, whatnot, - "maddr", "0x%x"); - return 1; - } - } - /* - * Check for IRQ conflicts. - */ - if (checkbits & CC_IRQ && tmpdvp->id_irq) { - if (tmpdvp->id_irq == dvp->id_irq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - ffs(dvp->id_irq) - 1, whatnot, - "irq", "%d"); - return 1; - } - } - /* - * Check for DRQ conflicts. - */ - if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { - if (tmpdvp->id_drq == dvp->id_drq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_drq, - whatnot, "drq", "%d"); - return 1; - } - } - } - return 0; -} + if (resource_int_value(name, unit, "port", &t) == 0) + idev->id_port[0] = t; + else + idev->id_port[0] = -1; + idev->id_port[1] = 0; -#ifdef RESOURCE_CHECK -#include <sys/drvresource.h> + if (resource_int_value(name, unit, "portsize", &t) == 0) + idev->id_portsize[0] = t; + else + idev->id_portsize[0] = 0; + idev->id_portsize[1] = 0; -static int -checkone (struct isa_device *dvp, int type, addr_t low, addr_t high, - char *resname, char *resfmt, int attaching) -{ - int result = 0; - if (bootverbose) { - if (low == high) - printf("\tcheck %s: 0x%x\n", resname, low); - else - printf("\tcheck %s: 0x%x to 0x%x\n", - resname, low, high); - } - if (resource_check(type, RESF_NONE, low, high) != NULL) { - char *whatnot = attaching ? "attach" : "prob"; - static struct isa_device dummydev; - static struct isa_driver dummydrv; - struct isa_device *tmpdvp = &dummydev; + if (resource_int_value(name, unit, "maddr", &t) == 0) + idev->id_maddr[0] = t; + else + idev->id_maddr[0] = 0; + idev->id_maddr[1] = 0; - dummydev.id_driver = &dummydrv; - dummydev.id_unit = 0; - dummydrv.name = "pci"; - conflict(dvp, tmpdvp, low, whatnot, resname, resfmt); - result = 1; - } else if (attaching) { - if (low == high) - printf("\tregister %s: 0x%x\n", resname, low); - else - printf("\tregister %s: 0x%x to 0x%x\n", - resname, low, high); - resource_claim(dvp, type, RESF_NONE, low, high); - } - return (result); -} + if (resource_int_value(name, unit, "msize", &t) == 0) + idev->id_msize[0] = t; + else + idev->id_msize[0] = 0; + idev->id_msize[1] = 0; -static int -check_pciconflict(struct isa_device *dvp, int checkbits) -{ - int result = 0; - int attaching = (checkbits & CC_ATTACH) != 0; + if (resource_int_value(name, unit, "flags", &t) == 0) + idev->id_flags = t; + else + idev->id_flags = 0; - if (checkbits & CC_MEMADDR) { - long maddr = dvp->id_maddr; - long msize = dvp->id_msize; - if (msize > 0) { - if (checkone(dvp, REST_MEM, maddr, maddr + msize - 1, - "maddr", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IOADDR) { - unsigned iobase = dvp->id_iobase; - unsigned iosize = dvp->id_alive; - if (iosize == -1) - iosize = 1; /* XXX can't do much about this ... */ - if (iosize > 0) { - if (checkone(dvp, REST_PORT, iobase, iobase + iosize -1, - "I/O address", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IRQ) { - int irq = ffs(dvp->id_irq) - 1; - if (irq >= 0) { - if (checkone(dvp, REST_INT, irq, irq, - "irq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_DRQ) { - int drq = dvp->id_drq; - if (drq >= 0) { - if (checkone(dvp, REST_DMA, drq, drq, - "drq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (result != 0) - resource_free (dvp); - return (result); -} -#endif /* RESOURCE_CHECK */ + if (resource_int_value(name, unit, "irq", &t) == 0) + idev->id_irq[0] = t; + else + idev->id_irq[0] = -1; + idev->id_irq[1] = -1; -/* - * Search through all the isa_devtab_* tables looking for anything that - * conflicts with the current device. - */ -int -haveseen_isadev(dvp, checkbits) - struct isa_device *dvp; - u_int checkbits; -{ -#if NPNP > 0 - struct pnp_dlist_node *nod; -#endif - struct isa_device *tmpdvp; - int status = 0; + if (resource_int_value(name, unit, "drq", &t) == 0) + idev->id_drq[0] = t; + else + idev->id_drq[0] = -1; + idev->id_drq[1] = -1; - for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_cam; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } -#if NPNP > 0 - for (nod = pnp_device_list; nod != NULL; nod = nod->next) - if (status |= haveseen(dvp, &(nod->dev), checkbits)) - return status; -#endif -#ifdef RESOURCE_CHECK - if (!dvp->id_conflicts) - status = check_pciconflict(dvp, checkbits); - else if (bootverbose) - printf("\tnot checking for resource conflicts ...\n"); -#endif /* RESOURCE_CHECK */ - return(status); + if (sensitive) + child = device_add_child_after(dev, last_sensitive, name, + unit, idev); + else + child = device_add_child(dev, name, unit, idev); + if (child == 0) + return; + else if (sensitive) + last_sensitive = child; + + if (resource_int_value(name, unit, "disabled", &t) == 0 && t != 0) + device_disable(child); } /* - * Configure all ISA devices + * 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. */ -void -isa_configure() +static int +isa_probe(device_t dev) { - struct isa_device *dvp; + int i; + static char buf[] = "isaXXX"; - printf("Probing for devices on the ISA bus:\n"); - /* First probe all the sensitive probes */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - - /* Then all the bad ones */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - -/* - * XXX we should really add the tty device to net_imask when the line is - * switched to SLIPDISC, and then remove it when it is switched away from - * SLIPDISC. No need to block out ALL ttys during a splimp when only one - * of them is running slip. - * - * XXX actually, blocking all ttys during a splimp doesn't matter so much - * with sio because the serial interrupt layer doesn't use tty_imask. Only - * non-serial ttys suffer. It's more stupid that ALL 'net's are blocked - * during spltty. - */ -#include "sl.h" -#if NSL > 0 - net_imask |= tty_imask; - tty_imask = net_imask; -#endif - - if (bootverbose) - printf("imasks: bio %x, tty %x, net %x\n", - bio_imask, tty_imask, net_imask); + device_set_desc(dev, "ISA bus"); /* - * Finish initializing intr_mask[]. Note that the partly - * constructed masks aren't actually used since we're at splhigh. - * For fully dynamic initialization, register_intr() and - * icu_unset() will have to adjust the masks for _all_ - * interrupts and for tty_imask, etc. + * Add all devices configured to be attached to isa0. */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - register_imask(dvp, tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - register_imask(dvp, bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - register_imask(dvp, net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - register_imask(dvp, cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - register_imask(dvp, SWI_CLOCK_MASK); -} - -/* - * Configure an ISA device. - */ -static void -config_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 0); -} - -void -reconfig_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 1); -} - -static void -config_isadev_c(isdp, mp, reconfig) - struct isa_device *isdp; - u_int *mp; - int reconfig; -{ - u_int checkbits; - int id_alive; - int last_alive; - struct isa_driver *dp = isdp->id_driver; - - if (!isdp->id_enabled) { - if (bootverbose) - printf("%s%d: disabled, not probed.\n", dp->name, isdp->id_unit); - return; + sprintf(buf, "isa%d", device_get_unit(dev)); + for (i = resource_query_string(-1, "at", buf); + i != -1; + i = resource_query_string(i, "at", buf)) { + isa_add_device(dev, resource_query_name(i), + resource_query_unit(i)); } - checkbits = CC_DRQ | CC_IOADDR | CC_MEMADDR; - if (!reconfig && haveseen_isadev(isdp, checkbits)) - return; - if (!reconfig && isdp->id_maddr) { - isdp->id_maddr -= ISA_HOLE_START; - isdp->id_maddr += atdevbase; - } - if (reconfig) { - last_alive = isdp->id_alive; - isdp->id_reconfig = 1; - } - else { - last_alive = 0; - isdp->id_reconfig = 0; - } - id_alive = (*dp->probe)(isdp); - if (id_alive) { - /* - * Only print the I/O address range if id_alive != -1 - * Right now this is a temporary fix just for the new - * NPX code so that if it finds a 486 that can use trap - * 16 it will not report I/O addresses. - * Rod Grimes 04/26/94 - */ - if (!isdp->id_reconfig) { - printf("%s%d", dp->name, isdp->id_unit); - if (id_alive != -1) { - if (isdp->id_iobase == -1) - printf(" at"); - else { - printf(" at 0x%x", isdp->id_iobase); - if (isdp->id_iobase + id_alive - 1 != - isdp->id_iobase) { - printf("-0x%x", - isdp->id_iobase + id_alive - 1); - } - } - } - if (isdp->id_irq) - printf(" irq %d", ffs(isdp->id_irq) - 1); - if (isdp->id_drq != -1) - printf(" drq %d", isdp->id_drq); - if (isdp->id_maddr) - printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); - if (isdp->id_msize) - printf(" msize %d", isdp->id_msize); - if (isdp->id_flags) - printf(" flags 0x%x", isdp->id_flags); - if (isdp->id_iobase && !(isdp->id_iobase & 0xf300)) { - printf(" on motherboard"); - } else if (isdp->id_iobase >= 0x1000 && - !(isdp->id_iobase & 0x300)) { - printf (" on eisa slot %d", - isdp->id_iobase >> 12); - } else { - printf (" on isa"); - } - printf("\n"); - /* - * Check for conflicts again. The driver may have - * changed *dvp. We should weaken the early check - * since the driver may have been able to change - * *dvp to avoid conflicts if given a chance. We - * already skip the early check for IRQs and force - * a check for IRQs in the next group of checks. - */ - checkbits |= CC_ATTACH | CC_IRQ; - if (haveseen_isadev(isdp, checkbits)) - return; - isdp->id_alive = id_alive; - } - (*dp->attach)(isdp); - if (isdp->id_irq != 0 && isdp->id_intr == NULL) - printf("%s%d: irq with no handler\n", - dp->name, isdp->id_unit); - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { -#ifdef APIC_IO - /* - * Some motherboards use upper IRQs for traditional - * ISA INTerrupt sources. In particular we have - * seen the secondary IDE connected to IRQ20. - * This code detects and fixes this situation. - */ - u_int apic_mask; - int rirq; - apic_mask = isa_apic_mask(isdp->id_irq); - if (apic_mask != isdp->id_irq) { - rirq = ffs(isdp->id_irq) - 1; - isdp->id_irq = apic_mask; - undirect_isa_irq(rirq); /* free for ISA */ - } -#endif /* APIC_IO */ - register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, - isdp->id_ri_flags, isdp->id_intr, - mp, isdp->id_unit); - } - } else { - if (isdp->id_reconfig) { - (*dp->attach)(isdp); /* reconfiguration attach */ - } - if (!last_alive) { - if (!isdp->id_reconfig) { - printf("%s%d not found", - dp->name, isdp->id_unit); - if (isdp->id_iobase != -1) - printf(" at 0x%x", isdp->id_iobase); - printf("\n"); - } - } else { -#if 0 - /* This code has not been tested.... */ - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { - icu_unset(ffs(isdp->id_irq) - 1, - isdp->id_intr); - if (mp) - INTRUNMASK(*mp, isdp->id_irq); - } -#else - printf ("icu_unset() not supported here ...\n"); -#endif - } + /* + * and isa? + */ + for (i = resource_query_string(-1, "at", "isa"); + i != -1; + i = resource_query_string(i, "at", "isa")) { + isa_add_device(dev, resource_query_name(i), + resource_query_unit(i)); } -} -static caddr_t dma_bouncebuf[8]; -static u_int dma_bouncebufsize[8]; -static u_int8_t dma_bounced = 0; -static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ -static u_int8_t dma_inuse = 0; /* User for acquire/release */ -static u_int8_t dma_auto_mode = 0; + isa_wrap_old_drivers(); -#define VALID_DMA_MASK (7) + return 0; +} -/* high byte of address is stored in this port for i-th dma channel */ -static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; +extern device_t isa_bus_device; -/* - * Setup a DMA channel's bounce buffer. - */ -void -isa_dmainit(chan, bouncebufsize) - int chan; - u_int bouncebufsize; +static int +isa_attach(device_t dev) { - void *buf; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmainit: channel out of range"); - - if (dma_bouncebuf[chan] != NULL) - panic("isa_dmainit: impossible request"); -#endif - - dma_bouncebufsize[chan] = bouncebufsize; - - /* Try malloc() first. It works better if it works. */ - buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); - if (buf != NULL) { - if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { - dma_bouncebuf[chan] = buf; - return; - } - free(buf, M_DEVBUF); - } - buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, - 1ul, chan & 4 ? 0x20000ul : 0x10000ul); - if (buf == NULL) - printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); - else - dma_bouncebuf[chan] = buf; + /* + * Arrange for bus_generic_attach(dev) to be called later. + */ + isa_bus_device = dev; + return 0; } -/* - * Register a DMA channel's usage. Usually called from a device driver - * in open() or during its initialization. - */ -int -isa_dma_acquire(chan) - int chan; +static void +isa_print_child(device_t bus, device_t dev) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_acquire: channel out of range"); -#endif - - if (dma_inuse & (1 << chan)) { - printf("isa_dma_acquire: channel %d already in use\n", chan); - return (EBUSY); - } - dma_inuse |= (1 << chan); - dma_auto_mode &= ~(1 << chan); - - return (0); + 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)); } -/* - * Unregister a DMA channel's usage. Usually called from a device driver - * during close() or during its shutdown. - */ -void -isa_dma_release(chan) - int chan; +static int +isa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_release: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dma_release: channel %d not in use\n", chan); -#endif - - if (dma_busy & (1 << chan)) { - dma_busy &= ~(1 << chan); - /* - * XXX We should also do "dma_bounced &= (1 << chan);" - * because we are acting on behalf of isa_dmadone() which - * was not called to end the last DMA operation. This does - * not matter now, but it may in the future. - */ - } - - dma_inuse &= ~(1 << chan); - dma_auto_mode &= ~(1 << chan); + 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; } /* - * isa_dmacascade(): program 8237 DMA controller channel to accept - * external dma control by a board. + * 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). */ -void -isa_dmacascade(chan) - int chan; +static int +isa_write_ivar(device_t bus, device_t dev, + int index, uintptr_t value) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmacascade: channel out of range"); -#endif - - /* set dma channel mode, and set dma channel mode */ - if ((chan & 4) == 0) { - outb(DMA1_MODE, DMA37MD_CASCADE | chan); - outb(DMA1_SMSK, chan); - } else { - outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); - outb(DMA2_SMSK, chan & 3); + 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_dmastart(): program 8237 DMA controller channel, avoid page alignment - * problems by using a bounce buffer. + * This implementation simply passes the request up to the parent + * bus, which in our case is the special i386 nexus, substituting any + * configured values if the caller defaulted. We can get away with + * this because there is no special mapping for ISA resources on an Intel + * platform. When porting this code to another architecture, it may be + * necessary to interpose a mapping layer here. */ -void -isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) +static 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) { - vm_offset_t phys; - int waport; - caddr_t newaddr; + int isdefault; + struct resource *rv, **rvp = 0; + struct isa_device *id = DEVTOISA(child); -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmastart: channel out of range"); - - if ((chan < 4 && nbytes > (1<<16)) - || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) - panic("isa_dmastart: impossible request"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastart: channel %d not acquired\n", chan); -#endif - -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if (dma_busy & (1 << chan)) - printf("isa_dmastart: channel %d busy\n", chan); -#endif - - dma_busy |= (1 << chan); - - if (isa_dmarangecheck(addr, nbytes, chan)) { - if (dma_bouncebuf[chan] == NULL - || dma_bouncebufsize[chan] < nbytes) - panic("isa_dmastart: bad bounce buffer"); - dma_bounced |= (1 << chan); - newaddr = dma_bouncebuf[chan]; - - /* copy bounce buffer on write */ - if (!(flags & B_READ)) - bcopy(addr, newaddr, nbytes); - addr = newaddr; - } - - /* translate to physical */ - phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); - - if (flags & B_RAW) { - dma_auto_mode |= (1 << chan); - } else { - dma_auto_mode &= ~(1 << chan); - } - - if ((chan & 4) == 0) { + if (child) { /* - * Program one of DMA channels 0..3. These are - * byte mode channels. + * If this is our child, then use the isa_device to find + * defaults and to record results. */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); - } - else - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); + if (device_get_devclass(device_get_parent(child)) == isa_devclass) + id = DEVTOISA(child); else - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); - outb(DMA1_FFC, 0); - - /* send start address */ - waport = DMA1_CHN(chan); - outb(waport, phys); - outb(waport, phys>>8); - outb(dmapageport[chan], phys>>16); - - /* send count */ - outb(waport + 1, --nbytes); - outb(waport + 1, nbytes>>8); - - /* unmask channel */ - outb(DMA1_SMSK, chan); - } else { - /* - * Program one of DMA channels 4..7. These are - * word mode channels. - */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); + 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; } - else - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); - outb(DMA2_FFC, 0); - - /* send start address */ - waport = DMA2_CHN(chan - 4); - outb(waport, phys>>1); - outb(waport, phys>>9); - outb(dmapageport[chan], phys>>16); - - /* send count */ - nbytes >>= 1; - outb(waport + 2, --nbytes); - outb(waport + 2, nbytes>>8); + 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; - /* unmask channel */ - outb(DMA2_SMSK, chan & 3); + default: + return 0; } -} - -void -isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmadone: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmadone: channel %d not acquired\n", chan); -#endif - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) - printf("isa_dmadone: channel %d not busy\n", chan); - if ((dma_auto_mode & (1 << chan)) == 0) - outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); - - if (dma_bounced & (1 << chan)) { - /* copy bounce buffer on read */ - if (flags & B_READ) - bcopy(dma_bouncebuf[chan], addr, nbytes); + /* + * If the client attempts to reallocate a resource without + * releasing what was there previously, die horribly so that + * he knows how he !@#$ed up. + */ + 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)); - dma_bounced &= ~(1 << chan); + /* + * 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; + } } - dma_busy &= ~(1 << chan); + return rv; } -/* - * Check for problems with the address range of a DMA transfer - * (non-contiguous physical pages, outside of bus address space, - * crossing DMA page boundaries). - * Return true if special handling needed. - */ - static int -isa_dmarangecheck(caddr_t va, u_int length, int chan) +isa_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) { - vm_offset_t phys, priorpage = 0, endva; - u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); - - endva = (vm_offset_t)round_page((vm_offset_t)va + length); - for (; va < (caddr_t) endva ; va += PAGE_SIZE) { - phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); -#define ISARAM_END RAM_END - if (phys == 0) - panic("isa_dmacheck: no physical page present"); - if (phys >= ISARAM_END) - return (1); - if (priorpage) { - if (priorpage + PAGE_SIZE != phys) - return (1); - /* check if crossing a DMA page boundary */ - if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) - return (1); - } - priorpage = phys; - } - return (0); -} + int rv; + struct isa_device *id = DEVTOISA(child); -/* - * Query the progress of a transfer on a DMA channel. - * - * To avoid having to interrupt a transfer in progress, we sample - * each of the high and low databytes twice, and apply the following - * logic to determine the correct count. - * - * Reads are performed with interrupts disabled, thus it is to be - * expected that the time between reads is very small. At most - * one rollover in the low count byte can be expected within the - * four reads that are performed. - * - * There are three gaps in which a rollover can occur : - * - * - read low1 - * gap1 - * - read high1 - * gap2 - * - read low2 - * gap3 - * - read high2 - * - * If a rollover occurs in gap1 or gap2, the low2 value will be - * greater than the low1 value. In this case, low2 and high2 are a - * corresponding pair. - * - * In any other case, low1 and high1 can be considered to be correct. - * - * The function returns the number of bytes remaining in the transfer, - * or -1 if the channel requested is not active. - * - */ -int -isa_dmastatus(int chan) -{ - u_long cnt = 0; - int ffport, waport; - u_long low1, high1, low2, high2; + if (rid > 1) + return EINVAL; - /* channel active? */ - if ((dma_inuse & (1 << chan)) == 0) { - printf("isa_dmastatus: channel %d not active\n", chan); - return(-1); + switch (type) { + case SYS_RES_IRQ: + case SYS_RES_DRQ: + case SYS_RES_IOPORT: + case SYS_RES_MEMORY: + break; + default: + return (ENOENT); } - /* channel busy? */ - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) { - printf("chan %d not busy\n", chan); - return -2 ; - } - if (chan < 4) { /* low DMA controller */ - ffport = DMA1_FFC; - waport = DMA1_CHN(chan) + 1; - } else { /* high DMA controller */ - ffport = DMA2_FFC; - waport = DMA2_CHN(chan - 4) + 2; - } + rv = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r); - disable_intr(); /* no interrupts Mr Jones! */ - outb(ffport, 0); /* clear register LSB flipflop */ - low1 = inb(waport); - high1 = inb(waport); - outb(ffport, 0); /* clear again */ - low2 = inb(waport); - high2 = inb(waport); - enable_intr(); /* enable interrupts again */ +#if 0 + if (rv) { + /* Kludge, isa as a child of pci doesn't have mapping regs */ + printf("WARNING: isa_release_resource: BUS_RELEASE_RESOURCE() failed: %d\n", rv); + rv = 0; + } +#endif - /* - * Now decide if a wrap has tried to skew our results. - * Note that after TC, the count will read 0xffff, while we want - * to return zero, so we add and then mask to compensate. - */ - if (low1 >= low2) { - cnt = (low1 + (high1 << 8) + 1) & 0xffff; - } else { - cnt = (low2 + (high2 << 8) + 1) & 0xffff; + if (rv == 0) { + switch (type) { + case SYS_RES_IRQ: + id->id_irqres[rid] = 0; + id->id_irq[rid] = -1; + break; + + case SYS_RES_DRQ: + id->id_drqres[rid] = 0; + id->id_drq[rid] = -1; + break; + + case SYS_RES_MEMORY: + id->id_memres[rid] = 0; + id->id_maddr[rid] = 0; + id->id_msize[rid] = 0; + break; + + case SYS_RES_IOPORT: + id->id_portres[rid] = 0; + id->id_port[rid] = 0; + id->id_portsize[rid] = 0; + break; + + default: + return ENOENT; + } } - if (chan >= 4) /* high channels move words */ - cnt *= 2; - return(cnt); + return rv; } /* - * Stop a DMA transfer currently in progress. + * We can't use the bus_generic_* versions of these methods because those + * methods always pass the bus param as the requesting device, and we need + * to pass the child (the i386 nexus knows about this and is prepared to + * deal). */ -int -isa_dmastop(int chan) +static int +isa_setup_intr(device_t bus, device_t child, struct resource *r, + void (*ihand)(void *), void *arg, void **cookiep) { - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastop: channel %d not acquired\n", chan); - - if (((dma_busy & (1 << chan)) == 0) && - ((dma_auto_mode & (1 << chan)) == 0)) { - printf("chan %d not busy\n", chan); - return -2 ; - } - - if ((chan & 4) == 0) { - outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); - } else { - outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); - } - return(isa_dmastatus(chan)); + return (BUS_SETUP_INTR(device_get_parent(bus), child, r, ihand, arg, + cookiep)); } -/* - * Find the highest priority enabled display device. Since we can't - * distinguish display devices from ttys, depend on display devices - * being sensitive and before sensitive non-display devices (if any) - * in isa_devtab_tty. - * - * XXX we should add capability flags IAMDISPLAY and ISUPPORTCONSOLES. - */ -struct isa_device * -find_display() +static int +isa_teardown_intr(device_t bus, device_t child, struct resource *r, + void *cookie) { - struct isa_device *dvp; - - for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) - if (dvp->id_driver->sensitive_hw && dvp->id_enabled) - return (dvp); - return (NULL); + 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_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, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + /* - * find an ISA device in a given isa_devtab_* table, given - * the table to search, the expected id_driver entry, and the unit number. - * - * this function is defined in isa_device.h, and this location is debatable; - * i put it there because it's useless w/o, and directly operates on - * the other stuff in that file. - * + * ISA can be attached to a PCI-ISA bridge or directly to the nexus. */ - -struct isa_device * -find_isadev(table, driverp, unit) - struct isa_device *table; - struct isa_driver *driverp; - int unit; -{ - if (driverp == NULL) /* sanity check */ - return (NULL); - - while ((table->id_driver != driverp) || (table->id_unit != unit)) { - if (table->id_driver == 0) - return NULL; - - table++; - } - - return (table); -} +DRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); +DRIVER_MODULE(isa, nexus, isa_driver, isa_devclass, 0, 0); diff --git a/sys/amd64/isa/isa_dma.c b/sys/amd64/isa/isa_dma.c new file mode 100644 index 0000000..abea7f8 --- /dev/null +++ b/sys/amd64/isa/isa_dma.c @@ -0,0 +1,510 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 + * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $ + */ + +/* + * code to manage AT bus + * + * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): + * Fixed uninitialized variable problem and added code to deal + * with DMA page boundaries in isa_dmarangecheck(). Fixed word + * mode DMA count compution and reorganized DMA setup code in + * isa_dmastart() + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <machine/ipl.h> +#include <machine/md_var.h> +#ifdef APIC_IO +#include <machine/smp.h> +#endif /* APIC_IO */ +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/intr_machdep.h> +#include <i386/isa/isa.h> +#include <i386/isa/ic/i8237.h> + +#include <sys/interrupt.h> + +#include "pnp.h" +#if NPNP > 0 +#include <i386/isa/pnp.h> +#endif + +/* +** Register definitions for DMA controller 1 (channels 0..3): +*/ +#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ +#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ +#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ +#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ + +/* +** Register definitions for DMA controller 2 (channels 4..7): +*/ +#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ +#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ +#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ +#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ + +static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); + +static caddr_t dma_bouncebuf[8]; +static u_int dma_bouncebufsize[8]; +static u_int8_t dma_bounced = 0; +static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ +static u_int8_t dma_inuse = 0; /* User for acquire/release */ +static u_int8_t dma_auto_mode = 0; + +#define VALID_DMA_MASK (7) + +/* high byte of address is stored in this port for i-th dma channel */ +static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; + +/* + * Setup a DMA channel's bounce buffer. + */ +void +isa_dmainit(chan, bouncebufsize) + int chan; + u_int bouncebufsize; +{ + void *buf; + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmainit: channel out of range"); + + if (dma_bouncebuf[chan] != NULL) + panic("isa_dmainit: impossible request"); +#endif + + dma_bouncebufsize[chan] = bouncebufsize; + + /* Try malloc() first. It works better if it works. */ + buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); + if (buf != NULL) { + if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { + dma_bouncebuf[chan] = buf; + return; + } + free(buf, M_DEVBUF); + } + buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, + 1ul, chan & 4 ? 0x20000ul : 0x10000ul); + if (buf == NULL) + printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); + else + dma_bouncebuf[chan] = buf; +} + +/* + * Register a DMA channel's usage. Usually called from a device driver + * in open() or during its initialization. + */ +int +isa_dma_acquire(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_acquire: channel out of range"); +#endif + + if (dma_inuse & (1 << chan)) { + printf("isa_dma_acquire: channel %d already in use\n", chan); + return (EBUSY); + } + dma_inuse |= (1 << chan); + dma_auto_mode &= ~(1 << chan); + + return (0); +} + +/* + * Unregister a DMA channel's usage. Usually called from a device driver + * during close() or during its shutdown. + */ +void +isa_dma_release(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_release: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dma_release: channel %d not in use\n", chan); +#endif + + if (dma_busy & (1 << chan)) { + dma_busy &= ~(1 << chan); + /* + * XXX We should also do "dma_bounced &= (1 << chan);" + * because we are acting on behalf of isa_dmadone() which + * was not called to end the last DMA operation. This does + * not matter now, but it may in the future. + */ + } + + dma_inuse &= ~(1 << chan); + dma_auto_mode &= ~(1 << chan); +} + +/* + * isa_dmacascade(): program 8237 DMA controller channel to accept + * external dma control by a board. + */ +void +isa_dmacascade(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmacascade: channel out of range"); +#endif + + /* set dma channel mode, and set dma channel mode */ + if ((chan & 4) == 0) { + outb(DMA1_MODE, DMA37MD_CASCADE | chan); + outb(DMA1_SMSK, chan); + } else { + outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); + outb(DMA2_SMSK, chan & 3); + } +} + +/* + * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment + * problems by using a bounce buffer. + */ +void +isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) +{ + vm_offset_t phys; + int waport; + caddr_t newaddr; + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmastart: channel out of range"); + + if ((chan < 4 && nbytes > (1<<16)) + || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) + panic("isa_dmastart: impossible request"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastart: channel %d not acquired\n", chan); +#endif + +#if 0 + /* + * XXX This should be checked, but drivers like ad1848 only call + * isa_dmastart() once because they use Auto DMA mode. If we + * leave this in, drivers that do this will print this continuously. + */ + if (dma_busy & (1 << chan)) + printf("isa_dmastart: channel %d busy\n", chan); +#endif + + dma_busy |= (1 << chan); + + if (isa_dmarangecheck(addr, nbytes, chan)) { + if (dma_bouncebuf[chan] == NULL + || dma_bouncebufsize[chan] < nbytes) + panic("isa_dmastart: bad bounce buffer"); + dma_bounced |= (1 << chan); + newaddr = dma_bouncebuf[chan]; + + /* copy bounce buffer on write */ + if (!(flags & B_READ)) + bcopy(addr, newaddr, nbytes); + addr = newaddr; + } + + /* translate to physical */ + phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); + + if (flags & B_RAW) { + dma_auto_mode |= (1 << chan); + } else { + dma_auto_mode &= ~(1 << chan); + } + + if ((chan & 4) == 0) { + /* + * Program one of DMA channels 0..3. These are + * byte mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If B_RAW flag is set, then use autoinitialise mode */ + if (flags & B_RAW) { + if (flags & B_READ) + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); + } + else + if (flags & B_READ) + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); + outb(DMA1_FFC, 0); + + /* send start address */ + waport = DMA1_CHN(chan); + outb(waport, phys); + outb(waport, phys>>8); + outb(dmapageport[chan], phys>>16); + + /* send count */ + outb(waport + 1, --nbytes); + outb(waport + 1, nbytes>>8); + + /* unmask channel */ + outb(DMA1_SMSK, chan); + } else { + /* + * Program one of DMA channels 4..7. These are + * word mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If B_RAW flag is set, then use autoinitialise mode */ + if (flags & B_RAW) { + if (flags & B_READ) + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); + } + else + if (flags & B_READ) + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); + outb(DMA2_FFC, 0); + + /* send start address */ + waport = DMA2_CHN(chan - 4); + outb(waport, phys>>1); + outb(waport, phys>>9); + outb(dmapageport[chan], phys>>16); + + /* send count */ + nbytes >>= 1; + outb(waport + 2, --nbytes); + outb(waport + 2, nbytes>>8); + + /* unmask channel */ + outb(DMA2_SMSK, chan & 3); + } +} + +void +isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmadone: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmadone: channel %d not acquired\n", chan); +#endif + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) + printf("isa_dmadone: channel %d not busy\n", chan); + + if ((dma_auto_mode & (1 << chan)) == 0) + outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); + + if (dma_bounced & (1 << chan)) { + /* copy bounce buffer on read */ + if (flags & B_READ) + bcopy(dma_bouncebuf[chan], addr, nbytes); + + dma_bounced &= ~(1 << chan); + } + dma_busy &= ~(1 << chan); +} + +/* + * Check for problems with the address range of a DMA transfer + * (non-contiguous physical pages, outside of bus address space, + * crossing DMA page boundaries). + * Return true if special handling needed. + */ + +static int +isa_dmarangecheck(caddr_t va, u_int length, int chan) +{ + vm_offset_t phys, priorpage = 0, endva; + u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); + + endva = (vm_offset_t)round_page((vm_offset_t)va + length); + for (; va < (caddr_t) endva ; va += PAGE_SIZE) { + phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); +#define ISARAM_END RAM_END + if (phys == 0) + panic("isa_dmacheck: no physical page present"); + if (phys >= ISARAM_END) + return (1); + if (priorpage) { + if (priorpage + PAGE_SIZE != phys) + return (1); + /* check if crossing a DMA page boundary */ + if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) + return (1); + } + priorpage = phys; + } + return (0); +} + +/* + * Query the progress of a transfer on a DMA channel. + * + * To avoid having to interrupt a transfer in progress, we sample + * each of the high and low databytes twice, and apply the following + * logic to determine the correct count. + * + * Reads are performed with interrupts disabled, thus it is to be + * expected that the time between reads is very small. At most + * one rollover in the low count byte can be expected within the + * four reads that are performed. + * + * There are three gaps in which a rollover can occur : + * + * - read low1 + * gap1 + * - read high1 + * gap2 + * - read low2 + * gap3 + * - read high2 + * + * If a rollover occurs in gap1 or gap2, the low2 value will be + * greater than the low1 value. In this case, low2 and high2 are a + * corresponding pair. + * + * In any other case, low1 and high1 can be considered to be correct. + * + * The function returns the number of bytes remaining in the transfer, + * or -1 if the channel requested is not active. + * + */ +int +isa_dmastatus(int chan) +{ + u_long cnt = 0; + int ffport, waport; + u_long low1, high1, low2, high2; + + /* channel active? */ + if ((dma_inuse & (1 << chan)) == 0) { + printf("isa_dmastatus: channel %d not active\n", chan); + return(-1); + } + /* channel busy? */ + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) { + printf("chan %d not busy\n", chan); + return -2 ; + } + if (chan < 4) { /* low DMA controller */ + ffport = DMA1_FFC; + waport = DMA1_CHN(chan) + 1; + } else { /* high DMA controller */ + ffport = DMA2_FFC; + waport = DMA2_CHN(chan - 4) + 2; + } + + disable_intr(); /* no interrupts Mr Jones! */ + outb(ffport, 0); /* clear register LSB flipflop */ + low1 = inb(waport); + high1 = inb(waport); + outb(ffport, 0); /* clear again */ + low2 = inb(waport); + high2 = inb(waport); + enable_intr(); /* enable interrupts again */ + + /* + * Now decide if a wrap has tried to skew our results. + * Note that after TC, the count will read 0xffff, while we want + * to return zero, so we add and then mask to compensate. + */ + if (low1 >= low2) { + cnt = (low1 + (high1 << 8) + 1) & 0xffff; + } else { + cnt = (low2 + (high2 << 8) + 1) & 0xffff; + } + + if (chan >= 4) /* high channels move words */ + cnt *= 2; + return(cnt); +} + +/* + * Stop a DMA transfer currently in progress. + */ +int +isa_dmastop(int chan) +{ + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastop: channel %d not acquired\n", chan); + + if (((dma_busy & (1 << chan)) == 0) && + ((dma_auto_mode & (1 << chan)) == 0)) { + printf("chan %d not busy\n", chan); + return -2 ; + } + + if ((chan & 4) == 0) { + outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); + } else { + outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); + } + return(isa_dmastatus(chan)); +} diff --git a/sys/amd64/isa/isa_dma.h b/sys/amd64/isa/isa_dma.h new file mode 100644 index 0000000..3fe234c --- /dev/null +++ b/sys/amd64/isa/isa_dma.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91 + * $Id: isa_device.h,v 1.57 1999/01/17 06:33:43 bde Exp $ + */ + +#ifndef _I386_ISA_ISA_DMA_H_ +#define _I386_ISA_ISA_DMA_H_ + +#ifdef KERNEL +void isa_dmacascade __P((int chan)); +void isa_dmadone __P((int flags, caddr_t addr, int nbytes, int chan)); +void isa_dmainit __P((int chan, u_int bouncebufsize)); +void isa_dmastart __P((int flags, caddr_t addr, u_int nbytes, int chan)); +int isa_dma_acquire __P((int chan)); +void isa_dma_release __P((int chan)); +int isa_dmastatus __P((int chan)); +int isa_dmastop __P((int chan)); +#endif /* KERNEL */ + +#endif /* !_I386_ISA_ISA_DMA_H_ */ diff --git a/sys/amd64/isa/nmi.c b/sys/amd64/isa/nmi.c index 944eb4e..4f7c1e9 100644 --- a/sys/amd64/isa/nmi.c +++ b/sys/amd64/isa/nmi.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.16 1999/01/08 19:17:48 bde Exp $ + * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $ */ #include "opt_auto_eoi.h" @@ -328,6 +328,7 @@ isa_get_nameunit(int id) return ("clk0"); /* XXX may also be sloppy driver */ if (id == 1) return ("rtc0"); +#if 0 for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; @@ -343,6 +344,7 @@ isa_get_nameunit(int id) for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; +#endif return "???"; found_device: diff --git a/sys/amd64/isa/npx.c b/sys/amd64/isa/npx.c index 2371e7b..dc2eb73 100644 --- a/sys/amd64/isa/npx.c +++ b/sys/amd64/isa/npx.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.65 1999/01/08 16:29:59 bde Exp $ + * $Id: npx.c,v 1.66 1999/03/28 23:28:18 dt Exp $ */ #include "npx.h" @@ -43,10 +43,14 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/sysctl.h> #include <sys/proc.h> +#include <machine/bus.h> +#include <sys/rman.h> #ifdef NPX_DEBUG #include <sys/syslog.h> #endif @@ -64,6 +68,7 @@ #ifndef SMP #include <machine/clock.h> #endif +#include <machine/resource.h> #include <machine/specialreg.h> #include <machine/segments.h> @@ -72,7 +77,6 @@ #include <i386/isa/intr_machdep.h> #include <i386/isa/isa.h> #endif -#include <i386/isa/isa_device.h> /* * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. @@ -83,9 +87,6 @@ #define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) -/* XXX - should be in header file. */ -ointhand2_t npxintr; - #ifdef __GNUC__ #define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr))) @@ -119,18 +120,15 @@ void stop_emulating __P((void)); typedef u_char bool_t; -static int npxattach __P((struct isa_device *dvp)); -static int npxprobe __P((struct isa_device *dvp)); -static int npxprobe1 __P((struct isa_device *dvp)); +static int npx_attach __P((device_t dev)); + void npx_intr __P((void *)); +static int npx_probe __P((device_t dev)); +static int npx_probe1 __P((device_t dev)); #ifdef I586_CPU static long timezero __P((const char *funcname, void (*func)(void *buf, size_t len))); #endif /* I586_CPU */ -struct isa_driver npxdriver = { - npxprobe, npxattach, "npx", -}; - int hw_float; /* XXX currently just alias for npx_exists */ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, @@ -191,12 +189,13 @@ __asm(" \n\ * need to use interrupts. Return 1 if device exists. */ static int -npxprobe(dvp) - struct isa_device *dvp; +npx_probe(dev) + device_t dev; { -#ifdef SMP +/*#ifdef SMP*/ +#if 1 - return npxprobe1(dvp); + return npx_probe1(dev); #else /* SMP */ @@ -213,20 +212,20 @@ npxprobe(dvp) * install suitable handlers and run with interrupts enabled so we * won't need to do so much here. */ - npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1; + npx_intrno = NRSVIDT + 13; save_eflags = read_eflags(); disable_intr(); save_icu1_mask = inb(IO_ICU1 + 1); save_icu2_mask = inb(IO_ICU2 + 1); save_idt_npxintr = idt[npx_intrno]; save_idt_npxtrap = idt[16]; - outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq)); - outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8)); + outb(IO_ICU1 + 1, ~IRQ_SLAVE); + outb(IO_ICU2 + 1, ~(1 << (13 - 8))); setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); npx_idt_probeintr = idt[npx_intrno]; enable_intr(); - result = npxprobe1(dvp); + result = npx_probe1(dev); disable_intr(); outb(IO_ICU1 + 1, save_icu1_mask); outb(IO_ICU2 + 1, save_icu2_mask); @@ -239,8 +238,8 @@ npxprobe(dvp) } static int -npxprobe1(dvp) - struct isa_device *dvp; +npx_probe1(dev) + device_t dev; { #ifndef SMP u_short control; @@ -280,21 +279,18 @@ npxprobe1(dvp) */ fninit(); -#ifdef SMP - +/*#ifdef SMP*/ +#if 1 /* * Exception 16 MUST work for SMP. */ npx_irq13 = 0; npx_ex16 = hw_float = npx_exists = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + device_set_desc(dev, "math processor"); + return (0); -#else /* SMP */ +#else /* !SMP */ + device_set_desc(dev, "math processor"); /* * Don't use fwait here because it might hang. @@ -335,14 +331,12 @@ npxprobe1(dvp) * Good, exception 16 works. */ npx_ex16 = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + return (0); } if (npx_intrs_while_probing != 0) { + int rid; + struct resource *r; + void *intr; /* * Bad, we are stuck with IRQ13. */ @@ -350,8 +344,30 @@ npxprobe1(dvp) /* * npxattach would be too late to set npx0_imask. */ - npx0_imask |= dvp->id_irq; - return (IO_NPXSIZE); + npx0_imask |= (1 << 13); + + /* + * We allocate these resources permanently, + * so there is no need to keep track of them. + */ + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IOPORT, + &rid, IO_NPX, IO_NPX, + IO_NPXSIZE, RF_ACTIVE); + if (r == 0) + panic("npx: can't get ports"); + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, 13, 13, + 1, RF_ACTIVE); + if (r == 0) + panic("npx: can't get IRQ"); + BUS_SETUP_INTR(device_get_parent(dev), + dev, r, npx_intr, 0, &intr); + if (intr == 0) + panic("npx: can't create intr"); + + return (0); } /* * Worse, even IRQ13 is broken. Use emulator. @@ -363,13 +379,7 @@ npxprobe1(dvp) * emulator and say that it has been installed. XXX handle devices * that aren't really devices better. */ - dvp->id_irq = 0; - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - + return (0); #endif /* SMP */ } @@ -377,14 +387,15 @@ npxprobe1(dvp) * Attach routine - announce which it is, and wire into system */ int -npxattach(dvp) - struct isa_device *dvp; +npx_attach(dev) + device_t dev; { - dvp->id_ointr = npxintr; + int flags; - /* The caller has printed "irq 13" for the npx_irq13 case. */ - if (!npx_irq13) { - printf("npx%d: ", dvp->id_unit); + device_print_prettyname(dev); + if (npx_irq13) { + printf("using IRQ 13 interface\n"); + } else { if (npx_ex16) printf("INT 16 interface\n"); #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) @@ -401,23 +412,26 @@ npxattach(dvp) npxinit(__INITIAL_NPXCW__); #ifdef I586_CPU + if (resource_int_value("npx", 0, "flags", &flags) != 0) + flags = 0; + if (cpu_class == CPUCLASS_586 && npx_ex16 && timezero("i586_bzero()", i586_bzero) < timezero("bzero()", bzero) * 4 / 5) { - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { bcopy_vector = i586_bcopy; ovbcopy_vector = i586_bcopy; } - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) bzero = i586_bzero; - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { copyin_vector = i586_copyin; copyout_vector = i586_copyout; } } #endif - return (1); /* XXX unused */ + return (0); /* XXX unused */ } /* @@ -494,8 +508,8 @@ npxexit(p) * solution for signals other than SIGFPE. */ void -npxintr(unit) - int unit; +npx_intr(dummy) + void *dummy; { int code; struct intrframe *frame; @@ -518,7 +532,7 @@ npxintr(unit) /* * Pass exception to process. */ - frame = (struct intrframe *)&unit; /* XXX */ + frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* * Interrupt is essentially a trap, so we can afford to call @@ -686,4 +700,31 @@ timezero(funcname, func) } #endif /* I586_CPU */ +static device_method_t npx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, npx_probe), + DEVMETHOD(device_attach, npx_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), + + { 0, 0 } +}; + +static driver_t npx_driver = { + "npx", + npx_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + +static devclass_t npx_devclass; + +/* + * We prefer to attach to the root nexus so that the usual case (exception 16) + * doesn't describe the processor as being `on isa'. + */ +DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0); + #endif /* NNPX > 0 */ diff --git a/sys/boot/alpha/boot1/boot1.c b/sys/boot/alpha/boot1/boot1.c index 9eac7ec..7346c5b 100644 --- a/sys/boot/alpha/boot1/boot1.c +++ b/sys/boot/alpha/boot1/boot1.c @@ -1,5 +1,5 @@ /* - * $Id: boot1.c,v 1.2 1998/09/26 10:51:36 dfr Exp $ + * $Id: boot1.c,v 1.3 1998/10/18 19:05:07 dfr Exp $ * From $NetBSD: bootxx.c,v 1.4 1997/09/06 14:08:29 drochner Exp $ */ @@ -49,6 +49,18 @@ putchar(int c) prom_putchar(c); } +int +getchar() +{ + return prom_getchar(); +} + +int +ischar() +{ + return prom_poll(); +} + void puts(const char *s) { @@ -150,9 +162,37 @@ devclose() } void +getfilename(char *filename) +{ + int c; + char *p; + + puts("Boot: "); + + while ((c = getchar()) != '\n') { + if (c == '\b') { + if (p > filename) { + puts("\b \b"); + p--; + } + } else + *p++ = c; + } + *p = '\0'; + return; +} + +void loadfile(char *name, char *addr) { int n; + char filename[512]; + char *p; + + restart: + puts("Loading "); + puts(name); + puts("\n"); if (openrd(name)) { puts("Can't open file "); @@ -161,9 +201,17 @@ loadfile(char *name, char *addr) halt(); } + p = addr; do { - n = readit(addr, 1024); - addr += n; + n = readit(p, 1024); + p += n; + if (ischar()) { + puts("Stop!\n"); + devclose(); + getfilename(filename); + name = filename; + goto restart; + } twiddle(); } while (n > 0); diff --git a/sys/boot/alpha/libalpha/prom.c b/sys/boot/alpha/libalpha/prom.c index 535ce31..380326c 100644 --- a/sys/boot/alpha/libalpha/prom.c +++ b/sys/boot/alpha/libalpha/prom.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: prom.c,v 1.1.1.1 1998/08/21 03:17:42 msmith Exp $ */ /* $NetBSD: prom.c,v 1.3 1997/09/06 14:03:58 drochner Exp $ */ /* @@ -41,7 +41,7 @@ static void prom_probe(struct console *cp); static int prom_init(int); void prom_putchar(int); int prom_getchar(void); -static int prom_poll(void); +int prom_poll(void); struct console promconsole = { "prom", diff --git a/sys/boot/alpha/libalpha/start.S b/sys/boot/alpha/libalpha/start.S index 39c3e48..f42b5da 100644 --- a/sys/boot/alpha/libalpha/start.S +++ b/sys/boot/alpha/libalpha/start.S @@ -1,5 +1,5 @@ /* - * $Id: start.S,v 1.1.1.1 1998/08/21 03:17:42 msmith Exp $ + * $Id: start.S,v 1.2 1998/10/31 17:12:32 dfr Exp $ * From: $NetBSD: start.S,v 1.4 1998/03/28 00:54:15 cgd Exp $ */ @@ -45,6 +45,7 @@ .set noreorder /* don't reorder instructions */ #define ENTRY_FRAME 32 +#define STACK_SIZE 8192 NESTED(start, 1, ENTRY_FRAME, ra, 0, 0) br pv,Lstartgp @@ -57,7 +58,7 @@ Lstartgp: CALL(bzero) #if defined(NETBOOT) || defined(LOADER) - lda sp,stack + 8192 - ENTRY_FRAME + lda sp,stack + STACK_SIZE - ENTRY_FRAME #endif CALL(main) /* transfer to C */ @@ -84,5 +85,5 @@ LEAF(cpu_number, 0) END(cpu_number) #if defined(NETBOOT) || defined(LOADER) -BSS(stack, 8192) +BSS(stack, STACK_SIZE) #endif diff --git a/sys/boot/alpha/netboot/Makefile b/sys/boot/alpha/netboot/Makefile index 927522c..4643add 100644 --- a/sys/boot/alpha/netboot/Makefile +++ b/sys/boot/alpha/netboot/Makefile @@ -15,6 +15,7 @@ SRCS+= main.c conf.c dev_net.c .include <${.CURDIR}/../../common/Makefile.inc> CFLAGS+= -mno-fp-regs CFLAGS+= -I${.CURDIR}/../../common -I${.CURDIR} +CFLAGS+= -I${.CURDIR}/../../.. -I. CFLAGS+= -I${.OBJDIR} CFLAGS+= -DNETBOOT diff --git a/sys/boot/common/bootstrap.h b/sys/boot/common/bootstrap.h index 996c07e..b405ac7 100644 --- a/sys/boot/common/bootstrap.h +++ b/sys/boot/common/bootstrap.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bootstrap.h,v 1.19 1999/01/22 23:50:13 msmith Exp $ + * $Id: bootstrap.h,v 1.20 1999/02/04 17:06:45 dcs Exp $ */ #include <sys/types.h> @@ -214,8 +214,8 @@ extern int elf_loadmodule(char *filename, vm_offset_t dest, struct loaded_module /* XXX just for conversion's sake, until we move to the new linker set code */ #define SET_FOREACH(pvar, set) \ - for (pvar = set.ls_items; \ - pvar < set.ls_items + set.ls_length; \ + for ((char*) pvar = set.ls_items; \ + (char*) pvar < (char*) &set.ls_items[set.ls_length]; \ pvar++) #else /* NEW_LINKER_SET */ diff --git a/sys/boot/ofw/libofw/ofw_console.c b/sys/boot/ofw/libofw/ofw_console.c index 535ce31..380326c 100644 --- a/sys/boot/ofw/libofw/ofw_console.c +++ b/sys/boot/ofw/libofw/ofw_console.c @@ -1,4 +1,4 @@ -/* $Id$ */ +/* $Id: prom.c,v 1.1.1.1 1998/08/21 03:17:42 msmith Exp $ */ /* $NetBSD: prom.c,v 1.3 1997/09/06 14:03:58 drochner Exp $ */ /* @@ -41,7 +41,7 @@ static void prom_probe(struct console *cp); static int prom_init(int); void prom_putchar(int); int prom_getchar(void); -static int prom_poll(void); +int prom_poll(void); struct console promconsole = { "prom", diff --git a/sys/conf/Makefile.i386 b/sys/conf/Makefile.i386 index 9c9ba23..cf6a212 100644 --- a/sys/conf/Makefile.i386 +++ b/sys/conf/Makefile.i386 @@ -1,7 +1,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.144 1999/04/13 18:25:08 peter Exp $ +# $Id: Makefile.i386,v 1.145 1999/04/15 14:52:23 bde Exp $ # # Makefile for FreeBSD # @@ -17,7 +17,7 @@ # # Which version of config(8) is required. -%VERSREQ= 300012 +%VERSREQ= 400013 KERNFORMAT?= elf diff --git a/sys/conf/Makefile.powerpc b/sys/conf/Makefile.powerpc index 9c9ba23..cf6a212 100644 --- a/sys/conf/Makefile.powerpc +++ b/sys/conf/Makefile.powerpc @@ -1,7 +1,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.144 1999/04/13 18:25:08 peter Exp $ +# $Id: Makefile.i386,v 1.145 1999/04/15 14:52:23 bde Exp $ # # Makefile for FreeBSD # @@ -17,7 +17,7 @@ # # Which version of config(8) is required. -%VERSREQ= 300012 +%VERSREQ= 400013 KERNFORMAT?= elf diff --git a/sys/conf/NOTES b/sys/conf/NOTES index 833fbc9..20b284b 100644 --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.581 1999/04/14 16:54:00 peter Exp $ +# $Id: LINT,v 1.582 1999/04/16 16:17:04 n_hibma Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -827,7 +827,7 @@ options "MSGBUF_SIZE=40960" # # Mandatory ISA devices: isa, npx # -controller isa0 +controller isa0 at nexus? # # Options for `isa': @@ -888,10 +888,10 @@ options "NTIMECOUNTER=20" controller pnp0 # The keyboard controller; it controlls the keyboard and the PS/2 mouse. -controller atkbdc0 at isa? port IO_KBD tty +controller atkbdc0 at isa? port IO_KBD # The AT keyboard -device atkbd0 at isa? tty irq 1 +device atkbd0 at atkbdc? tty irq 1 # Options for atkbd: options ATKBD_DFLT_KEYMAP # specify the built-in keymap @@ -907,7 +907,7 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev # 0x04 Old-style (XT) keyboard support, useful for older ThinkPads # PS/2 mouse -device psm0 at isa? tty irq 12 +device psm0 at atkbdc? tty irq 12 # Options for psm: options PSM_HOOKAPM #hook the APM resume event, useful @@ -977,7 +977,7 @@ options SC_DISABLE_REBOOT # disable reboot key sequence # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). -device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 +device npx0 at nexus? port IO_NPX iosiz 0x0 flags 0x0 irq 13 # # `flags' for npx0: @@ -1464,7 +1464,7 @@ controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 -device apm0 at isa? +device apm0 at nexus? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port IO_GAME @@ -1632,7 +1632,7 @@ options "EISA_SLOTS=12" # The "oltr" driver supports the following Olicom PCI token-ring adapters # OC-3136, OC-3137, OC-3139, OC-3140, OC-3141, OC-3540, OC-3250 # -controller pci0 +controller pci0 at nexus? controller ahc1 controller ncr0 controller isp0 diff --git a/sys/conf/files b/sys/conf/files index 66e94b0..7987e0a 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -613,6 +613,21 @@ pci/ncr.c optional ncr device-driver pci/pci.c optional pci device-driver pci/pci_compat.c optional pci pci/pcisupport.c optional pci +pci_if.o optional pci \ + dependency "pci_if.c pci_if.h" \ + compile-with "${NORMAL_C}" \ + no-implicit-rule local +pci_if.c optional pci \ + dependency "$S/kern/makedevops.pl $S/pci/pci_if.m" \ + compile-with "perl5 $S/kern/makedevops.pl -c $S/pci/pci_if.m" \ + no-obj no-implicit-rule before-depend local \ + clean "pci_if.c" +pci_if.h optional pci \ + dependency "$S/kern/makedevops.pl $S/pci/pci_if.m" \ + compile-with "perl5 $S/kern/makedevops.pl -h $S/pci/pci_if.m" \ + no-obj no-implicit-rule before-depend \ + clean "pci_if.h" +pci/tek390.c optional amd device-driver pci/simos.c optional simos device-driver pci/alpm.c optional alpm device-driver pci/xrpu.c optional xrpu device-driver diff --git a/sys/conf/files.alpha b/sys/conf/files.alpha index 6f747e3..d0f4003 100644 --- a/sys/conf/files.alpha +++ b/sys/conf/files.alpha @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.alpha,v 1.16 1999/01/23 16:53:26 dfr Exp $ +# $Id: files.alpha,v 1.17 1999/03/10 10:36:50 yokota Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -112,10 +112,13 @@ mcclock_if.h standard \ no-obj no-implicit-rule before-depend \ clean "mcclock_if.h" alpha/pci/cia.c optional cia +alpha/pci/cia_pci.c optional cia alpha/pci/pci_eb164_intr.s optional cia alpha/pci/apecs.c optional apecs +alpha/pci/apecs_pci.c optional apecs alpha/pci/pci_eb64plus_intr.s optional apecs alpha/pci/lca.c optional lca +alpha/pci/lca_pci.c optional lca alpha/pci/pcibus.c optional pci alpha/isa/isa.c optional isa alpha/isa/mcclock_isa.c optional isa @@ -157,3 +160,10 @@ dev/syscons/syscons.c optional sc device-driver dev/syscons/scvidctl.c optional sc device-driver isa/syscons_isa.c optional sc device-driver isa/psm.c optional psm device-driver +dev/ata/ata-all.c optional ata device-driver +dev/ata/ata-dma.c optional ata device-driver +dev/ata/atapi-all.c optional ata device-driver +dev/ata/ata-disk.c optional atadisk device-driver +dev/ata/atapi-cd.c optional atapicd device-driver +dev/ata/atapi-fd.c optional atapifd device-driver +dev/ata/atapi-tape.c optional atapist device-driver diff --git a/sys/conf/files.i386 b/sys/conf/files.i386 index 81f360e..ba0dba1 100644 --- a/sys/conf/files.i386 +++ b/sys/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.234 1999/04/13 19:38:10 peter Exp $ +# $Id: files.i386,v 1.235 1999/04/15 14:52:23 bde Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -90,6 +90,7 @@ i386/i386/mp_machdep.c optional smp i386/i386/mpapic.c optional smp i386/i386/mpboot.s optional smp i386/i386/mplock.s optional smp +i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon profiling-routine i386/i386/perfmon.c optional perfmon i386/i386/pmap.c standard @@ -125,8 +126,8 @@ i386/ibcs2/imgact_coff.c optional ibcs2 i386/isa/adv_isa.c optional adv device-driver #i386/isa/aha1542.c optional aha device-driver i386/isa/aha_isa.c optional aha device-driver -i386/isa/atkbd_isa.c optional atkbd device-driver -i386/isa/atkbdc_isa.c optional atkbdc device-driver +isa/atkbd_isa.c optional atkbd device-driver +isa/atkbdc_isa.c optional atkbdc device-driver i386/isa/bt_isa.c optional bt device-driver i386/isa/clock.c standard i386/isa/cronyx.c optional cx device-driver @@ -177,6 +178,8 @@ i386/isa/mse.c optional mse device-driver i386/isa/npx.c mandatory npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver +i386/isa/isa_compat.c optional isa device-driver +i386/isa/isa_dma.c optional isa device-driver i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver @@ -190,7 +193,7 @@ i386/isa/pnp.c optional pnp device-driver i386/isa/prof_machdep.c optional profiling-routine i386/isa/ppc.c optional ppc device-driver i386/isa/pcf.c optional pcf device-driver -i386/isa/psm.c optional psm device-driver +isa/psm.c optional psm device-driver i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver i386/isa/rp.c optional rp device-driver @@ -198,7 +201,7 @@ i386/isa/scd.c optional scd device-driver i386/isa/si.c optional si device-driver i386/isa/si2_z280.c optional si device-driver i386/isa/si3_t225.c optional si device-driver -i386/isa/sio.c optional sio device-driver +isa/sio.c optional sio device-driver i386/isa/snd/sound.c optional pcm device-driver i386/isa/snd/dmabuf.c optional pcm device-driver i386/isa/snd/ad1848.c optional pcm device-driver @@ -268,9 +271,9 @@ i386/isa/sound/cs4232.c optional css device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/stallion.c optional stl device-driver -i386/isa/syscons_isa.c optional sc device-driver +isa/syscons_isa.c optional sc device-driver i386/isa/vesa.c optional vga device-driver -i386/isa/vga_isa.c optional vga device-driver +isa/vga_isa.c optional vga device-driver i386/isa/tw.c optional tw device-driver i386/isa/wd.c optional wdc device-driver i386/isa/wd.c optional wd device-driver diff --git a/sys/dev/aha/aha_isa.c b/sys/dev/aha/aha_isa.c index 9426679..c3704df 100644 --- a/sys/dev/aha/aha_isa.c +++ b/sys/dev/aha/aha_isa.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $ + * $Id: aha_isa.c,v 1.6 1999/01/20 06:21:23 imp Exp $ */ #include "pnp.h" @@ -257,7 +257,6 @@ static void ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NAHATOT) return; @@ -278,9 +277,7 @@ ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &ahadriver; - dvp = find_isadev(isa_devtab_tty, &ahadriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = aha_isa_probe(dev)) != 0) diff --git a/sys/dev/ata/ata-all.c b/sys/dev/ata/ata-all.c index 680c334..4bee8d3 100644 --- a/sys/dev/ata/ata-all.c +++ b/sys/dev/ata/ata-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-all.c,v 1.5 1999/03/28 18:57:18 sos Exp $ + * $Id: ata-all.c,v 1.6 1999/04/10 18:53:35 sos Exp $ */ #include "ata.h" @@ -44,12 +44,18 @@ #include <vm/vm.h> #include <vm/pmap.h> #include <machine/clock.h> +#ifdef __i386__ #include <machine/smp.h> +#endif #include <pci/pcivar.h> #include <pci/pcireg.h> +#ifdef __i386__ #include <i386/isa/icu.h> #include <i386/isa/isa.h> #include <i386/isa/isa_device.h> +#else +#include <isa/isareg.h> +#endif #include <dev/ata/ata-all.h> #include <dev/ata/ata-disk.h> #include <dev/ata/atapi-all.h> @@ -62,7 +68,7 @@ #endif /* prototypes */ -#if NISA > 0 +#if NISA > 0 && defined(__i386__) static int32_t ata_isaprobe(struct isa_device *); static int32_t ata_isaattach(struct isa_device *); #endif @@ -76,9 +82,10 @@ static void ataintr(int32_t); static int32_t atanlun = 0; struct ata_softc *atadevices[MAXATA]; + +#if NISA > 0 && defined(__i386__) struct isa_driver atadriver = { ata_isaprobe, ata_isaattach, "ata" }; -#if NISA > 0 static int32_t ata_isaprobe(struct isa_device *devp) { @@ -133,6 +140,10 @@ ata_pciprobe(pcici_t tag, pcidi_t type) return "Promise Ultra/33 IDE controller"; case 0x522910b9: return "AcerLabs Aladdin IDE controller"; + case 0x06401095: + return "CMD 640 IDE controller"; + case 0x06461095: + return "CMD 646 IDE controller"; #if 0 case 0x05711106: return "VIA Apollo IDE controller"; @@ -222,14 +233,18 @@ ata_pciattach(pcici_t tag, int32_t unit) lun = 0; if (ata_probe(iobase_1, altiobase_1, bmaddr_1, tag, &lun)) { if (iobase_1 == IO_WD1) +#ifdef __i386__ register_intr(irq1, (int)"", 0, (inthand2_t *)ataintr, &bio_imask, lun); +#else + alpha_platform_setup_ide_intr(0, ataintr, (void *)(intptr_t)lun); +#endif else { if (sysctrl) pci_map_int(tag, (inthand2_t *)promise_intr, - (void *)lun, &bio_imask); + (void *)(intptr_t)lun, &bio_imask); else - pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask); + pci_map_int(tag, (inthand2_t *)ataintr, (void *)(intptr_t)lun,&bio_imask); } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", lun, iobase_1, isa_apic_irq(irq1), unit); @@ -237,11 +252,15 @@ ata_pciattach(pcici_t tag, int32_t unit) lun = 1; if (ata_probe(iobase_2, altiobase_2, bmaddr_2, tag, &lun)) { if (iobase_2 == IO_WD2) +#ifdef __i386__ register_intr(irq2, (int)"", 0, (inthand2_t *)ataintr, &bio_imask, lun); +#else + alpha_platform_setup_ide_intr(1, ataintr, (void *)(intptr_t)lun); +#endif else { if (!sysctrl) - pci_map_int(tag, (inthand2_t *)ataintr, (void *)lun,&bio_imask); + pci_map_int(tag, (inthand2_t *)ataintr, (void *)(intptr_t)lun,&bio_imask); } printf("ata%d at 0x%04x irq %d on ata-pci%d\n", lun, iobase_2, isa_apic_irq(irq2), unit); @@ -418,6 +437,7 @@ ata_probe(int32_t ioaddr, int32_t altioaddr, int32_t bmaddr, #ifndef ATA_STATIC_ID atanlun++; #endif + outb(scp->ioaddr + ATA_DRIVE, ATA_D_IBM | ATA_MASTER); return ATA_IOSIZE; } @@ -571,7 +591,7 @@ printf("ata_command: addr=%04x, device=%02x, cmd=%02x, c=%d, h=%d, s=%d, count=% scp->active = ATA_WAIT_INTR; outb(scp->ioaddr + ATA_CMD, command); if (tsleep((caddr_t)scp, PRIBIO, "atacmd", 500)) { - printf("ata_command: timeout waiting for interrupt"); + printf("ata_command: timeout waiting for interrupt\n"); scp->active = ATA_IDLE; return -1; } diff --git a/sys/dev/ata/ata-disk.c b/sys/dev/ata/ata-disk.c index c5f7a41..c5efe55 100644 --- a/sys/dev/ata/ata-disk.c +++ b/sys/dev/ata/ata-disk.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-disk.c,v 1.5 1999/03/28 18:57:18 sos Exp $ + * $Id: ata-disk.c,v 1.6 1999/04/10 18:53:35 sos Exp $ */ #include "ata.h" @@ -527,11 +527,11 @@ ad_transfer(struct buf *bp) /* output the data */ #if 0 outsw(adp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)bp->b_data + adp->donecount), + (void *)((uintptr_t)bp->b_data + adp->donecount), adp->currentsize / sizeof(int16_t)); #else outsl(adp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)bp->b_data + adp->donecount), + (void *)((uintptr_t)bp->b_data + adp->donecount), adp->currentsize / sizeof(int32_t)); #endif adp->bytecount -= adp->currentsize; @@ -590,11 +590,11 @@ oops: /* data ready, read in */ #if 0 insw(adp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)bp->b_data + adp->donecount), + (void *)((uintptr_t)bp->b_data + adp->donecount), adp->currentsize / sizeof(int16_t)); #else insl(adp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)bp->b_data + adp->donecount), + (void *)((uintptr_t)bp->b_data + adp->donecount), adp->currentsize / sizeof(int32_t)); #endif adp->bytecount -= adp->currentsize; diff --git a/sys/dev/ata/ata-dma.c b/sys/dev/ata/ata-dma.c index fe0a08c..0886dbe 100644 --- a/sys/dev/ata/ata-dma.c +++ b/sys/dev/ata/ata-dma.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: ata-dma.c,v 1.3 1999/03/30 13:09:47 sos Exp $ + * $Id: ata-dma.c,v 1.4 1999/04/10 18:53:35 sos Exp $ */ #include "ata.h" @@ -42,6 +42,12 @@ #include <pci/pcireg.h> #include <dev/ata/ata-all.h> +#ifdef __alpha__ +#undef vtophys +#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \ + + 1*1024*1024*1024) +#endif + /* misc defines */ #define MIN(a,b) ((a)>(b)?(b):(a)) @@ -64,7 +70,7 @@ ata_dmainit(struct ata_softc *scp, int32_t device, if (!(dmatab = malloc(PAGE_SIZE, M_DEVBUF, M_NOWAIT))) return -1; - if (((int)dmatab>>PAGE_SHIFT)^(((int)dmatab+PAGE_SIZE-1)>>PAGE_SHIFT)) { + if (((uintptr_t)dmatab>>PAGE_SHIFT)^(((uintptr_t)dmatab+PAGE_SIZE-1)>>PAGE_SHIFT)) { printf("ata_dmainit: dmatab crosses page boundary, no DMA\n"); free(dmatab, M_DEVBUF); return -1; @@ -252,7 +258,7 @@ ata_dmasetup(struct ata_softc *scp, int32_t device, #ifdef ATA_DEBUGDMA printf("ata%d: dmasetup\n", scp->lun); #endif - if (((u_int32_t)data & 1) || (count & 1)) + if (((uintptr_t)data & 1) || (count & 1)) return -1; if (!count) { @@ -263,7 +269,7 @@ ata_dmasetup(struct ata_softc *scp, int32_t device, dmatab = scp->dmatab[device ? 1 : 0]; dma_base = vtophys(data); - dma_count = MIN(count, (PAGE_SIZE - ((u_int32_t)data & PAGE_MASK))); + dma_count = MIN(count, (PAGE_SIZE - ((uintptr_t)data & PAGE_MASK))); data += dma_count; count -= dma_count; diff --git a/sys/dev/ata/atapi-all.c b/sys/dev/ata/atapi-all.c index 6322475..3b48966 100644 --- a/sys/dev/ata/atapi-all.c +++ b/sys/dev/ata/atapi-all.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atapi-all.c,v 1.5 1999/03/28 18:57:19 sos Exp $ + * $Id: atapi-all.c,v 1.6 1999/04/10 18:53:35 sos Exp $ */ #include "ata.h" @@ -310,13 +310,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); printf("atapi_interrupt: write data underrun %d/%d\n", length, request->bytecount); outsw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), length / sizeof(int16_t)); + (void *)((uintptr_t)request->data), length / sizeof(int16_t)); for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) outw(atp->controller->ioaddr + ATA_DATA, 0); } else { outsw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), length / sizeof(int16_t)); + (void *)((uintptr_t)request->data), length / sizeof(int16_t)); } request->bytecount -= length; request->data += length; @@ -331,13 +331,13 @@ printf("atapi_interrupt: length=%d reason=0x%02x\n", length, reason); printf("atapi_interrupt: read data overrun %d/%d\n", length, request->bytecount); insw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), length / sizeof(int16_t)); + (void *)((uintptr_t)request->data), length / sizeof(int16_t)); for (resid=request->bytecount; resid<length; resid+=sizeof(int16_t)) inw(atp->controller->ioaddr + ATA_DATA); } else { insw(atp->controller->ioaddr + ATA_DATA, - (void *)((int32_t)request->data), length / sizeof(int16_t)); + (void *)((uintptr_t)request->data), length / sizeof(int16_t)); } request->bytecount -= length; request->data += length; diff --git a/sys/dev/atkbdc/atkbd.c b/sys/dev/atkbdc/atkbd.c index f9e28fe..80c81a5 100644 --- a/sys/dev/atkbdc/atkbd.c +++ b/sys/dev/atkbdc/atkbd.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atkbd.c,v 1.4 1999/01/28 10:55:55 yokota Exp $ + * $Id: atkbd.c,v 1.5 1999/03/10 10:36:52 yokota Exp $ */ #include "atkbd.h" @@ -46,7 +46,7 @@ #include <dev/kbd/atkbdreg.h> #include <dev/kbd/atkbdcreg.h> -#ifndef __i386__ +#if 1 #include <sys/bus.h> #include <isa/isareg.h> @@ -89,6 +89,7 @@ static struct cdevsw atkbd_cdevsw = { #endif /* KBD_INSTALL_CDEV */ +#if 0 #ifdef __i386__ atkbd_softc_t @@ -110,6 +111,7 @@ atkbd_softc_t } #endif /* __i386__ */ +#endif int atkbd_probe_unit(int unit, int port, int irq, int flags) @@ -376,16 +378,14 @@ atkbd_configure(int flags) { keyboard_t *kbd; int arg[2]; -#ifdef __i386__ - struct isa_device *dev; int i; /* XXX: a kludge to obtain the device configuration flags */ - dev = find_isadev(isa_devtab_tty, &atkbddriver, 0); - if (dev != NULL) { - flags |= dev->id_flags; + if (resource_int_value("atkbd", 0, "flags", &i) == 0) { + flags |= i; /* if the driver is disabled, unregister the keyboard if any */ - if (!dev->id_enabled) { + if (resource_int_value("atkbd", 0, "disabled", &i) == 0 + && i != 0) { i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); if (i >= 0) { kbd = kbd_get_keyboard(i); @@ -395,8 +395,7 @@ atkbd_configure(int flags) } } } -#endif - + /* probe the keyboard controller */ atkbdc_configure(); diff --git a/sys/dev/atkbdc/atkbd_atkbdc.c b/sys/dev/atkbdc/atkbd_atkbdc.c index ade1ba0..1d7ee62 100644 --- a/sys/dev/atkbdc/atkbd_atkbdc.c +++ b/sys/dev/atkbdc/atkbd_atkbdc.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atkbd_isa.c,v 1.1 1999/01/23 16:53:27 dfr Exp $ + * $Id: atkbd_isa.c,v 1.2 1999/03/10 10:36:49 yokota Exp $ */ #include "atkbd.h" @@ -37,6 +37,7 @@ #include <sys/conf.h> #include <sys/tty.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #include <machine/resource.h> @@ -70,9 +71,9 @@ static driver_t atkbd_driver = { static int atkbdprobe(device_t dev) { - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; device_set_desc(dev, "AT Keyboard"); @@ -89,9 +90,9 @@ static int atkbdattach(device_t dev) { atkbd_softc_t *sc; - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; struct resource *res; void *ih; int zero = 0; diff --git a/sys/dev/atkbdc/atkbd_isa.c b/sys/dev/atkbdc/atkbd_isa.c index ade1ba0..1d7ee62 100644 --- a/sys/dev/atkbdc/atkbd_isa.c +++ b/sys/dev/atkbdc/atkbd_isa.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atkbd_isa.c,v 1.1 1999/01/23 16:53:27 dfr Exp $ + * $Id: atkbd_isa.c,v 1.2 1999/03/10 10:36:49 yokota Exp $ */ #include "atkbd.h" @@ -37,6 +37,7 @@ #include <sys/conf.h> #include <sys/tty.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #include <machine/resource.h> @@ -70,9 +71,9 @@ static driver_t atkbd_driver = { static int atkbdprobe(device_t dev) { - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; device_set_desc(dev, "AT Keyboard"); @@ -89,9 +90,9 @@ static int atkbdattach(device_t dev) { atkbd_softc_t *sc; - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; struct resource *res; void *ih; int zero = 0; diff --git a/sys/dev/atkbdc/psm.c b/sys/dev/atkbdc/psm.c index e7eb469..b3dc1d0 100644 --- a/sys/dev/atkbdc/psm.c +++ b/sys/dev/atkbdc/psm.c @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: psm.c,v 1.2 1998/11/15 18:25:17 dfr Exp $ + * $Id: psm.c,v 1.3 1999/01/23 16:53:28 dfr Exp $ */ /* @@ -76,6 +76,7 @@ #include <sys/poll.h> #include <sys/syslog.h> #include <sys/malloc.h> +#include <machine/bus.h> #include <sys/rman.h> #ifdef DEVFS #include <sys/devfsext.h> @@ -740,8 +741,8 @@ psmprobe(device_t dev) { int unit = device_get_unit(dev); struct psm_softc *sc = device_get_softc(dev); - u_long port; - u_long flags; + uintptr_t port; + uintptr_t flags; int stat[3]; int command_byte; int mask; @@ -991,7 +992,7 @@ psmattach(device_t dev) struct psm_softc *sc = device_get_softc(dev); void *ih; struct resource *res; - u_long irq; + uintptr_t irq; int zero = 0; if (sc == NULL) /* shouldn't happen */ diff --git a/sys/dev/cs/if_cs.c b/sys/dev/cs/if_cs.c index 4a9c390..f96f024 100644 --- a/sys/dev/cs/if_cs.c +++ b/sys/dev/cs/if_cs.c @@ -27,7 +27,7 @@ */ /* - * $Id: if_cs.c,v 1.8 1999/01/12 00:27:43 eivind Exp $ + * $Id: if_cs.c,v 1.9 1999/01/28 01:59:53 dillon Exp $ * * Device driver for Crystal Semiconductor CS8920 based ethernet * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997 @@ -1352,7 +1352,6 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, int iobase, unit, flags; u_int irq; int drq; - struct isa_device *dvp; struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); if (read_pnp_parms ( &d , ldn ) == 0 ) { @@ -1373,9 +1372,7 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, if (dev->id_driver == NULL) { dev->id_driver = &csdriver; - dvp = find_isadev(isa_devtab_net, &csdriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if (!sc) return; diff --git a/sys/dev/ed/if_ed.c b/sys/dev/ed/if_ed.c index 1408b2b..29bb9d1 100644 --- a/sys/dev/ed/if_ed.c +++ b/sys/dev/ed/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.149 1999/01/28 01:59:53 dillon Exp $ + * $Id: if_ed.c,v 1.150 1999/03/17 16:44:51 luigi Exp $ */ /* @@ -3488,7 +3488,6 @@ static void edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NEDTOT) return; @@ -3509,9 +3508,7 @@ edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &eddriver; - dvp = find_isadev(isa_devtab_net, &eddriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = ed_probe(dev)) != 0) diff --git a/sys/dev/fdc/fdc.c b/sys/dev/fdc/fdc.c index 07223f1..0414b18 100644 --- a/sys/dev/fdc/fdc.c +++ b/sys/dev/fdc/fdc.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.133 1999/02/10 00:03:32 ken Exp $ + * $Id: fd.c,v 1.134 1999/04/06 03:06:51 peter Exp $ * */ @@ -60,26 +60,37 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/bus.h> #include <sys/conf.h> -#include <sys/fcntl.h> -#include <machine/clock.h> -#include <machine/ioctl_fd.h> #include <sys/disklabel.h> -#include <sys/buf.h> #include <sys/devicestat.h> +#include <sys/fcntl.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/proc.h> #include <sys/syslog.h> -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/fdreg.h> -#include <i386/isa/fdc.h> -#include <i386/isa/rtc.h> + +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/clock.h> +#include <machine/ioctl_fd.h> +#include <machine/resource.h> #include <machine/stdarg.h> + #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ +#include <isa/isavar.h> +#include <i386/isa/isa.h> +#include <i386/isa/isa_dma.h> +#include <i386/isa/fdreg.h> +#include <i386/isa/fdc.h> +#include <i386/isa/rtc.h> + /* misuse a flag to identify format operation */ #define B_FORMAT B_XXX @@ -151,13 +162,13 @@ static struct fd_type fd_types[NUMTYPES] = /***********************************************************************\ * Per controller structure. * \***********************************************************************/ -struct fdc_data fdc_data[NFDC]; +static devclass_t fdc_devclass; /***********************************************************************\ * Per drive structure. * * N per controller (DRVS_PER_CTLR) * \***********************************************************************/ -static struct fd_data { +struct fd_data { struct fdc_data *fdc; /* pointer to controller structure */ int fdsu; /* this units number on this controller */ int type; /* Drive type (FD_1440...) */ @@ -179,7 +190,10 @@ static struct fd_data { void *bdevs[1 + NUMDENS + MAXPARTITIONS]; void *cdevs[1 + NUMDENS + MAXPARTITIONS]; #endif -} fd_data[NFD]; + device_t dev; + fdu_t fdu; +}; +static devclass_t fd_devclass; /***********************************************************************\ * Throughout this file the following conventions will be used: * @@ -195,29 +209,26 @@ static struct fd_data { static int yeattach(struct isa_device *); #endif -/* autoconfig functions */ -static int fdprobe(struct isa_device *); -static int fdattach(struct isa_device *); - /* needed for ft driver, thus exported */ -int in_fdc(fdcu_t); -int out_fdc(fdcu_t, int); +int in_fdc(struct fdc_data *); +int out_fdc(struct fdc_data *, int); /* internal functions */ -static void set_motor(fdcu_t, int, int); +static void fdc_add_device(device_t, const char *, int); +static void fdc_intr(void *); +static void set_motor(struct fdc_data *, int, int); # define TURNON 1 # define TURNOFF 0 static timeout_t fd_turnoff; static timeout_t fd_motor_on; -static void fd_turnon(fdu_t); +static void fd_turnon(struct fd_data *); static void fdc_reset(fdc_p); -static int fd_in(fdcu_t, int *); -static void fdstart(fdcu_t); +static int fd_in(struct fdc_data *, int *); +static void fdstart(struct fdc_data *); static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; -static ointhand2_t fdintr; -static int fdstate(fdcu_t, fdc_p); -static int retrier(fdcu_t); +static int fdstate(struct fdc_data *); +static int retrier(struct fdc_data *); static int fdformat(dev_t, struct fd_formb *, struct proc *); static int enable_fifo(fdc_p fdc); @@ -356,13 +367,6 @@ static int yeintr(struct pccard_devinfo *devi) #endif /* NCARD > 0 */ #endif /* FDC_YE */ - -/* autoconfig structure */ - -struct isa_driver fdcdriver = { - fdprobe, fdattach, "fdc", -}; - static d_open_t Fdopen; /* NOTE, not fdopen */ static d_read_t fdread; static d_write_t fdwrite; @@ -374,28 +378,18 @@ static d_strategy_t fdstrategy; #define CDEV_MAJOR 9 #define BDEV_MAJOR 2 - -static struct cdevsw fd_cdevsw = { - Fdopen, fdclose, fdread, fdwrite, - fdioctl, nostop, nullreset, nodevtotty, - seltrue, nommap, fdstrategy, "fd", - NULL, -1, nodump, nopsize, - D_DISK, 0, -1 }; - - -static struct isa_device *fdcdevs[NFDC]; - - static int -fdc_err(fdcu_t fdcu, const char *s) +fdc_err(struct fdc_data *fdc, const char *s) { - fdc_data[fdcu].fdc_errs++; - if(s) { - if(fdc_data[fdcu].fdc_errs < FDC_ERRMAX) - printf("fdc%d: %s", fdcu, s); - else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX) - printf("fdc%d: too many errors, not logging any more\n", - fdcu); + fdc->fdc_errs++; + if (s) { + if (fdc->fdc_errs < FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("%s", s); + } else if (fdc->fdc_errs == FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("too many errors, not logging any more\n"); + } } return FD_FAILED; @@ -407,9 +401,8 @@ fdc_err(fdcu_t fdcu, const char *s) * # of output bytes, output bytes as ints ..., * # of input bytes, input bytes as ints ... */ - static int -fd_cmd(fdcu_t fdcu, int n_out, ...) +fd_cmd(struct fdc_data *fdc, int n_out, ...) { u_char cmd; int n_in; @@ -422,26 +415,26 @@ fd_cmd(fdcu_t fdcu, int n_out, ...) va_start(ap, n_out); for (n = 0; n < n_out; n++) { - if (out_fdc(fdcu, va_arg(ap, int)) < 0) + if (out_fdc(fdc, va_arg(ap, int)) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %x failed at out byte %d of %d\n", cmd, n + 1, n_out); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } n_in = va_arg(ap, int); for (n = 0; n < n_in; n++) { int *ptr = va_arg(ap, int *); - if (fd_in(fdcu, ptr) < 0) + if (fd_in(fdc, ptr) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %02x failed at in byte %d of %d\n", cmd, n + 1, n_in); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } @@ -462,8 +455,8 @@ enable_fifo(fdc_p fdc) * first byte, and check for an early turn of data directon. */ - if (out_fdc(fdc->fdcu, I8207X_CONFIGURE) < 0) - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + if (out_fdc(fdc, I8207X_CONFIGURE) < 0) + return fdc_err(fdc, "Enable FIFO failed\n"); /* If command is invalid, return */ j = 100000; @@ -474,17 +467,17 @@ enable_fifo(fdc_p fdc) return FD_FAILED; } if (j<0 || - fd_cmd(fdc->fdcu, 3, + fd_cmd(fdc, 3, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { fdc_reset(fdc); - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + return fdc_err(fdc, "Enable FIFO failed\n"); } fdc->flags |= FDC_HAS_FIFO; return 0; } - if (fd_cmd(fdc->fdcu, 4, + if (fd_cmd(fdc, 4, I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) - return fdc_err(fdc->fdcu, "Re-enable FIFO failed\n"); + return fdc_err(fdc, "Re-enable FIFO failed\n"); return 0; } @@ -493,9 +486,9 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) { int st3; - if (fd_cmd(fdc->fdcu, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) + if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) { - return fdc_err(fdc->fdcu, "Sense Drive Status failed\n"); + return fdc_err(fdc, "Sense Drive Status failed\n"); } if (st3p) *st3p = st3; @@ -506,13 +499,11 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) static int fd_sense_int(fdc_p fdc, int *st0p, int *cylp) { - int st0, cyl; + int cyl, st0, ret; - int ret = fd_cmd(fdc->fdcu, 1, NE7CMD_SENSEI, 1, &st0); - - if (ret) - { - (void)fdc_err(fdc->fdcu, + ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); + if (ret) { + (void)fdc_err(fdc, "sense intr err reading stat reg 0\n"); return ret; } @@ -520,17 +511,15 @@ fd_sense_int(fdc_p fdc, int *st0p, int *cylp) if (st0p) *st0p = st0; - if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) - { + if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { /* * There doesn't seem to have been an interrupt. */ return FD_NOT_VALID; } - if (fd_in(fdc->fdcu, &cyl) < 0) - { - return fdc_err(fdc->fdcu, "can't get cyl num\n"); + if (fd_in(fdc, &cyl) < 0) { + return fdc_err(fdc, "can't get cyl num\n"); } if (cylp) @@ -545,8 +534,7 @@ fd_read_status(fdc_p fdc, int fdsu) { int i, ret; - for (i = 0; i < 7; i++) - { + for (i = 0; i < 7; i++) { /* * XXX types are poorly chosen. Only bytes can by read * from the hardware, but fdc->status[] wants u_ints and @@ -554,7 +542,7 @@ fd_read_status(fdc_p fdc, int fdsu) */ int status; - ret = fd_in(fdc->fdcu, &status); + ret = fd_in(fdc, &status); fdc->status[i] = status; if (ret != 0) break; @@ -572,34 +560,92 @@ fd_read_status(fdc_p fdc, int fdsu) /* autoconfiguration stuff */ /****************************************************************************/ -/* - * probe for existance of controller - */ static int -fdprobe(struct isa_device *dev) +fdc_probe(device_t dev) { - fdcu_t fdcu = dev->id_unit; - if(fdc_data[fdcu].flags & FDC_ATTACHED) - { - printf("fdc%d: unit used multiple times\n", fdcu); - return 0; + int error, i, ic_type; + struct fdc_data *fdc; + char myname[8]; /* better be long enough */ + + fdc = device_get_softc(dev); + bzero(fdc, sizeof *fdc); + fdc->fdc_dev = dev; + fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0; + fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0; + + fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, + &fdc->rid_ioport, 0ul, ~0ul, + IO_FDCSIZE, RF_ACTIVE); + if (fdc->res_ioport == 0) { + device_print_prettyname(dev); + printf("cannot reserve I/O port range\n"); + error = ENXIO; + goto out; } - - fdcdevs[fdcu] = dev; - fdc_data[fdcu].baseport = dev->id_iobase; + fdc->baseport = fdc->res_ioport->r_start; + + fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, + &fdc->rid_irq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_irq == 0) { + device_print_prettyname(dev); + printf("cannot reserve interrupt line\n"); + error = ENXIO; + goto out; + } + fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, + &fdc->rid_drq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_drq == 0) { + device_print_prettyname(dev); + printf("cannot reserve DMA request line\n"); + error = ENXIO; + goto out; + } + fdc->dmachan = fdc->res_drq->r_start; + error = BUS_SETUP_INTR(device_get_parent(dev), dev, + fdc->res_irq, fdc_intr, fdc, &fdc->fdc_intr); /* First - lets reset the floppy controller */ - outb(dev->id_iobase+FDOUT, 0); + outb(fdc->baseport + FDOUT, 0); DELAY(100); - outb(dev->id_iobase+FDOUT, FDO_FRST); + outb(fdc->baseport + FDOUT, FDO_FRST); /* see if it can handle a command */ - if (fd_cmd(fdcu, - 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), - 0)) - { - return(0); + if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), + NE7_SPEC_2(2, 0), 0)) { + error = ENXIO; + goto out; + } + + if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) { + ic_type = (u_char)ic_type; + switch (ic_type) { + case 0x80: + device_set_desc(dev, "NEC 765 or clone"); + fdc->fdct = FDC_NE765; + break; + case 0x81: + device_set_desc(dev, "Intel 82077 or clone"); + fdc->fdct = FDC_I82077; + break; + case 0x90: + device_set_desc(dev, "NEC 72065B or clone"); + fdc->fdct = FDC_NE72065; + break; + default: + device_set_desc(dev, "generic floppy controller"); + fdc->fdct = FDC_UNKNOWN; + break; + } } + + snprintf(myname, sizeof(myname), "%s%d", device_get_name(dev), + device_get_unit(dev)); + for (i = resource_query_string(-1, "at", myname); i != -1; + i = resource_query_string(i, "at", myname)) + fdc_add_device(dev, resource_query_name(i), + resource_query_unit(i)); #ifdef FDC_YE /* * don't succeed on probe; wait @@ -608,277 +654,312 @@ fdprobe(struct isa_device *dev) if (dev->id_flags & FDC_IS_PCMCIA) return(0); #endif - return (IO_FDCSIZE); + return (0); + +out: + if (fdc->fdc_intr) + BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, + fdc->fdc_intr); + if (fdc->res_irq != 0) { + bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + } + if (fdc->res_ioport != 0) { + bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + } + if (fdc->res_drq != 0) { + bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + } + return (error); } /* - * wire controller into system, look for floppy units + * Aped dfr@freebsd.org's isa_add_device(). */ +static void +fdc_add_device(device_t dev, const char *name, int unit) +{ + int disabled, *ivar; + device_t child; + + ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT); + if (ivar == 0) + return; + if (resource_int_value(name, unit, "drive", ivar) == 0) + *ivar = 0; + child = device_add_child(dev, name, unit, ivar); + if (child == 0) + return; + if (resource_int_value(name, unit, "disabled", &disabled) == 0) + device_disable(child); +} + static int -fdattach(struct isa_device *dev) +fdc_attach(device_t dev) { - unsigned fdt; - fdu_t fdu; - fdcu_t fdcu = dev->id_unit; - fdc_p fdc = fdc_data + fdcu; - fd_p fd; - int fdsu, st0, st3, i; - struct isa_device *fdup; - int ic_type = 0; -#ifdef DEVFS - int mynor; - int typemynor; - int typesize; -#endif + struct fdc_data *fdc = device_get_softc(dev); + fdcu_t fdcu = device_get_unit(dev); - dev->id_ointr = fdintr; fdc->fdcu = fdcu; fdc->flags |= FDC_ATTACHED; - fdc->dmachan = dev->id_drq; + /* Acquire the DMA channel forever, The driver will do the rest */ + /* XXX should integrate with rman */ isa_dma_acquire(fdc->dmachan); isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); fdc->state = DEVIDLE; + /* reset controller, turn motor off, clear fdout mirror reg */ outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); bufq_init(&fdc->head); - /* check for each floppy drive */ - for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { - if (fdup->id_iobase != dev->id_iobase) - continue; - fdu = fdup->id_unit; - fd = &fd_data[fdu]; - if (fdu >= (NFD)) - continue; - fdsu = fdup->id_physid; - /* look up what bios thinks we have */ - switch (fdu) { - case 0: if (dev->id_flags & FDC_PRETEND_D0) - fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; - else - fdt = (rtcin(RTC_FDISKETTE) & 0xf0); - break; - case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); - break; - default: fdt = RTCFDT_NONE; - break; - } - /* is there a unit? */ - if ((fdt == RTCFDT_NONE) - ) { - fd->type = NO_TYPE; - continue; - } +#ifdef FIFO_BEFORE_MOTORON + /* Hmm, this doesn't work here - is set_motor() magic? -Peter */ + if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(dev); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } +#endif + /* + * Probe and attach any children as were configured above. + */ + return (bus_generic_attach(dev)); +} - /* select it */ - set_motor(fdcu, fdsu, TURNON); - DELAY(1000000); /* 1 sec */ +static void +fdc_print_child(device_t me, device_t child) +{ + printf(" at %s%d drive %d", device_get_name(me), device_get_unit(me), + *(int *)device_get_ivars(child)); +} - if (ic_type == 0 && - fd_cmd(fdcu, 1, NE7CMD_VERSION, 1, &ic_type) == 0) - { -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("fdc%d: ", fdcu); -#endif - ic_type = (u_char)ic_type; - switch( ic_type ) { - case 0x80: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 765\n"); -#endif - fdc->fdct = FDC_NE765; - break; - case 0x81: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("Intel 82077\n"); -#endif - fdc->fdct = FDC_I82077; - break; - case 0x90: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 72065B\n"); +static int +fd_probe(device_t dev) +{ + int i; + u_int fdt, st0, st3; + struct fd_data *fd; + struct fdc_data *fdc; + fdsu_t fdsu; +#ifndef FIFO_BEFORE_MOTORON + static int fd_fifo = 0; #endif - fdc->fdct = FDC_NE72065; - break; - default: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("unknown IC type %02x\n", ic_type); + + fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */ + fd = device_get_softc(dev); + fdc = device_get_softc(device_get_parent(dev)); + + bzero(fd, sizeof *fd); + fd->dev = dev; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->fdu = device_get_unit(dev); + + /* look up what bios thinks we have */ + switch (fd->fdu) { + case 0: + if (isa_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0) + fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; + else + fdt = (rtcin(RTC_FDISKETTE) & 0xf0); + break; + case 1: + fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); + break; + default: + fdt = RTCFDT_NONE; + break; + } + + /* is there a unit? */ + if (fdt == RTCFDT_NONE) + return (ENXIO); + + /* select it */ + set_motor(fdc, fdsu, TURNON); + DELAY(1000000); /* 1 sec */ + +#ifndef FIFO_BEFORE_MOTORON + if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(device_get_parent(dev)); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } + fd_fifo = 1; #endif - fdc->fdct = FDC_UNKNOWN; - break; - } - if (fdc->fdct != FDC_NE765 && - fdc->fdct != FDC_UNKNOWN && - enable_fifo(fdc) == 0) { - printf("fdc%d: FIFO enabled", fdcu); - printf(", %d bytes threshold\n", - fifo_threshold); - } - } - if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* if at track 0, first seek inwards */ - /* seek some steps: */ - (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); - DELAY(300000); /* ...wait a moment... */ - (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ - } - /* If we're at track 0 first seek inwards. */ - if ((fd_sense_drive_status(fdc, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* Seek some steps... */ - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { - /* ...wait a moment... */ - DELAY(300000); - /* make ctrlr happy: */ - (void)fd_sense_int(fdc, 0, 0); - } + if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) + && (st3 & NE7_ST3_T0)) { + /* if at track 0, first seek inwards */ + /* seek some steps: */ + fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0); + DELAY(300000); /* ...wait a moment... */ + fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ + } + + /* If we're at track 0 first seek inwards. */ + if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { + /* Seek some steps... */ + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { + /* ...wait a moment... */ + DELAY(300000); + /* make ctrlr happy: */ + fd_sense_int(fdc, 0, 0); } + } - for(i = 0; i < 2; i++) { - /* - * we must recalibrate twice, just in case the - * heads have been beyond cylinder 76, since most - * FDCs still barf when attempting to recalibrate - * more than 77 steps - */ - /* go back to 0: */ - if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { - /* a second being enough for full stroke seek*/ - DELAY(i == 0? 1000000: 300000); + for (i = 0; i < 2; i++) { + /* + * we must recalibrate twice, just in case the + * heads have been beyond cylinder 76, since most + * FDCs still barf when attempting to recalibrate + * more than 77 steps + */ + /* go back to 0: */ + if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { + /* a second being enough for full stroke seek*/ + DELAY(i == 0 ? 1000000 : 300000); - /* anything responding? */ - if (fd_sense_int(fdc, &st0, 0) == 0 && - (st0 & NE7_ST0_EC) == 0) - break; /* already probed succesfully */ - } + /* anything responding? */ + if (fd_sense_int(fdc, &st0, 0) == 0 && + (st0 & NE7_ST0_EC) == 0) + break; /* already probed succesfully */ } + } - set_motor(fdcu, fdsu, TURNOFF); + set_motor(fdc, fdsu, TURNOFF); - if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ - continue; + if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ + return (ENXIO); - fd->track = FD_NO_TRACK; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->options = 0; - callout_handle_init(&fd->toffhandle); - callout_handle_init(&fd->tohandle); - printf("fd%d: ", fdu); - - switch (fdt) { - case RTCFDT_12M: - printf("1.2MB 5.25in\n"); - fd->type = FD_1200; - break; - case RTCFDT_144M | RTCFDT_144M_PRETENDED: - printf("config-pretended "); - fdt = RTCFDT_144M; - /* fallthrough */ - case RTCFDT_144M: - printf("1.44MB 3.5in\n"); - fd->type = FD_1440; + fd->track = FD_NO_TRACK; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->options = 0; + callout_handle_init(&fd->toffhandle); + callout_handle_init(&fd->tohandle); + + switch (fdt) { + case RTCFDT_12M: + device_set_desc(dev, "1200-KB 5.25\" drive"); + fd->type = FD_1200; + break; + case RTCFDT_144M | RTCFDT_144M_PRETENDED: + device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive"); + fdt = RTCFDT_144M; + fd->type = FD_1440; + case RTCFDT_144M: + device_set_desc(dev, "1440-KB 3.5\" drive"); + fd->type = FD_1440; + break; + case RTCFDT_288M: + case RTCFDT_288M_1: + device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); + fd->type = FD_1440; + break; + case RTCFDT_360K: + device_set_desc(dev, "360-KB 5.25\" drive"); + fd->type = FD_360; + break; + case RTCFDT_720K: + printf("720-KB 3.5\" drive"); + fd->type = FD_720; + break; + default: + return (ENXIO); + } + return (0); +} + +static int +fd_attach(device_t dev) +{ + struct fd_data *fd; + + fd = device_get_softc(dev); + +#ifdef DEVFS /* XXX bitrot */ + mynor = fdu << 6; + fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d", fdu); + fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d", fdu); + for (i = 1; i < 1 + NUMDENS; i++) { + /* + * XXX this and the lookup in Fdopen() should be + * data driven. + */ + switch (fd->type) { + case FD_360: + if (i != FD_360) + continue; break; - case RTCFDT_288M: - case RTCFDT_288M_1: - printf("2.88MB 3.5in - 1.44MB mode\n"); - fd->type = FD_1440; + case FD_720: + if (i != FD_720 && i != FD_800 && i != FD_820) + continue; break; - case RTCFDT_360K: - printf("360KB 5.25in\n"); - fd->type = FD_360; + case FD_1200: + if (i != FD_360 && i != FD_720 && i != FD_800 + && i != FD_820 && i != FD_1200 + && i != FD_1440 && i != FD_1480) + continue; break; - case RTCFDT_720K: - printf("720KB 3.5in\n"); - fd->type = FD_720; + case FD_1440: + if (i != FD_720 && i != FD_800 && i != FD_820 + && i != FD_1200 && i != FD_1440 + && i != FD_1480 && i != FD_1720) + continue; break; - default: - printf("unknown\n"); - fd->type = NO_TYPE; - continue; } -#ifdef DEVFS - mynor = fdu << 6; - fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d", fdu); - fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d", fdu); - for (i = 1; i < 1 + NUMDENS; i++) { - /* - * XXX this and the lookup in Fdopen() should be - * data driven. - */ - switch (fd->type) { - case FD_360: - if (i != FD_360) - continue; - break; - case FD_720: - if (i != FD_720 && i != FD_800 && i != FD_820) - continue; - break; - case FD_1200: - if (i != FD_360 && i != FD_720 && i != FD_800 - && i != FD_820 && i != FD_1200 - && i != FD_1440 && i != FD_1480) - continue; - break; - case FD_1440: - if (i != FD_720 && i != FD_800 && i != FD_820 - && i != FD_1200 && i != FD_1440 - && i != FD_1480 && i != FD_1720) - continue; - break; - } - typesize = fd_types[i - 1].size / 2; - /* - * XXX all these conversions give bloated code and - * confusing names. - */ - if (typesize == 1476) - typesize = 1480; - if (typesize == 1722) - typesize = 1720; - typemynor = mynor | i; - fd->bdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d.%d", fdu, typesize); - fd->cdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d.%d", fdu, typesize); - } - - for (i = 0; i < MAXPARTITIONS; i++) { - fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], - "fd%d%c", fdu, 'a' + i); - fd->cdevs[1 + NUMDENS + i] = - devfs_makelink(fd->cdevs[0], - "rfd%d%c", fdu, 'a' + i); - } -#endif /* DEVFS */ + typesize = fd_types[i - 1].size / 2; /* - * Export the drive to the devstat interface. + * XXX all these conversions give bloated code and + * confusing names. */ - devstat_add_entry(&fd->device_stats, "fd", - fdu, 512, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, - DEVSTAT_PRIORITY_FD); - + if (typesize == 1476) + typesize = 1480; + if (typesize == 1722) + typesize = 1720; + typemynor = mynor | i; + fd->bdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d.%d", fdu, typesize); + fd->cdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d.%d", fdu, typesize); } - return (1); + for (i = 0; i < MAXPARTITIONS; i++) { + fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], + "fd%d%c", fdu, 'a' + i); + fd->cdevs[1 + NUMDENS + i] = + devfs_makelink(fd->cdevs[0], + "rfd%d%c", fdu, 'a' + i); + } +#endif /* DEVFS */ + /* + * Export the drive to the devstat interface. + */ + devstat_add_entry(&fd->device_stats, device_get_name(dev), + device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, + DEVSTAT_PRIORITY_FD); + return (0); } - - #ifdef FDC_YE /* * this is a subset of fdattach() optimized for the Y-E Data @@ -1016,9 +1097,9 @@ static int yeattach(struct isa_device *dev) /* remember to not deselect the drive we're working on */ /****************************************************************************/ static void -set_motor(fdcu_t fdcu, int fdsu, int turnon) +set_motor(struct fdc_data *fdc, int fdsu, int turnon) { - int fdout = fdc_data[fdcu].fdout; + int fdout = fdc->fdout; int needspecify = 0; if(turnon) { @@ -1038,83 +1119,78 @@ set_motor(fdcu_t fdcu, int fdsu, int turnon) fdout |= (FDO_FRST|FDO_FDMAEN); } - outb(fdc_data[fdcu].baseport+FDOUT, fdout); - fdc_data[fdcu].fdout = fdout; + outb(fdc->baseport+FDOUT, fdout); + fdc->fdout = fdout; TRACE1("[0x%x->FDOUT]", fdout); - if(needspecify) { + if (needspecify) { /* * XXX * special case: since we have just woken up the FDC * from its sleep, we silently assume the command will * be accepted, and do not test for a timeout */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); - if (fdc_data[fdcu].flags & FDC_HAS_FIFO) - (void) enable_fifo(&fdc_data[fdcu]); + if (fdc->flags & FDC_HAS_FIFO) + (void) enable_fifo(fdc); } } static void -fd_turnoff(void *arg1) +fd_turnoff(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; - fd_p fd = fd_data + fdu; + fd_p fd = xfd; - TRACE1("[fd%d: turnoff]", fdu); + TRACE1("[fd%d: turnoff]", fd->fdu); /* * Don't turn off the motor yet if the drive is active. * XXX shouldn't even schedule turnoff until drive is inactive * and nothing is queued on it. */ - if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { - fd->toffhandle = timeout(fd_turnoff, arg1, 4 * hz); + if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); return; } s = splbio(); fd->flags &= ~FD_MOTOR; - set_motor(fd->fdc->fdcu, fd->fdsu, TURNOFF); + set_motor(fd->fdc, fd->fdsu, TURNOFF); splx(s); } static void -fd_motor_on(void *arg1) +fd_motor_on(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; + fd_p fd = xfd; - fd_p fd = fd_data + fdu; s = splbio(); fd->flags &= ~FD_MOTOR_WAIT; if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) { - fdintr(fd->fdc->fdcu); + fdc_intr(fd->fdc); } splx(s); } static void -fd_turnon(fdu_t fdu) +fd_turnon(fd_p fd) { - fd_p fd = fd_data + fdu; if(!(fd->flags & FD_MOTOR)) { fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); - set_motor(fd->fdc->fdcu, fd->fdsu, TURNON); - timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ + set_motor(fd->fdc, fd->fdsu, TURNON); + timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ } } static void fdc_reset(fdc_p fdc) { - fdcu_t fdcu = fdc->fdcu; - /* Try a reset, keep motor on */ outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); @@ -1127,7 +1203,7 @@ fdc_reset(fdc_p fdc) TRACE1("[0x%x->FDOUT]", fdc->fdout); /* XXX after a reset, silently believe the FDC will accept commands */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); if (fdc->flags & FDC_HAS_FIFO) @@ -1138,16 +1214,16 @@ fdc_reset(fdc_p fdc) /* fdc in/out */ /****************************************************************************/ int -in_fdc(fdcu_t fdcu) +in_fdc(struct fdc_data *fdc) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1161,16 +1237,16 @@ in_fdc(fdcu_t fdcu) * fd_in: Like in_fdc, but allows you to see if it worked. */ static int -fd_in(fdcu_t fdcu, int *ptr) +fd_in(struct fdc_data *fdc, int *ptr) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1185,21 +1261,21 @@ fd_in(fdcu_t fdcu, int *ptr) } int -out_fdc(fdcu_t fdcu, int x) +out_fdc(struct fdc_data *fdc, int x) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i; /* Check that the direction bit is set */ i = 100000; while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); - if (i <= 0) return fdc_err(fdcu, "direction bit not set\n"); + if (i <= 0) return fdc_err(fdc, "direction bit not set\n"); /* Check that the floppy controller is ready for a command */ i = 100000; while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); if (i <= 0) - return fdc_err(fdcu, bootverbose? "output ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "output ready timeout\n": 0); /* Send the command and return */ outb(baseport+FDDATA, x); @@ -1215,32 +1291,33 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); int type = FDTYPE(minor(dev)); + fd_p fd; fdc_p fdc; /* check bounds */ - if (fdu >= NFD) - return(ENXIO); - fdc = fd_data[fdu].fdc; - if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) - return(ENXIO); + if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0) + return (ENXIO); + fdc = fd->fdc; + if ((fdc == NULL) || (fd->type == NO_TYPE)) + return (ENXIO); if (type > NUMDENS) - return(ENXIO); + return (ENXIO); if (type == 0) - type = fd_data[fdu].type; + type = fd->type; else { /* * For each type of basic drive, make sure we are trying * to open a type it can do, */ - if (type != fd_data[fdu].type) { - switch (fd_data[fdu].type) { + if (type != fd->type) { + switch (fd->type) { case FD_360: - return(ENXIO); + return (ENXIO); case FD_720: if ( type != FD_820 && type != FD_800 ) - return(ENXIO); + return (ENXIO); break; case FD_1200: switch (type) { @@ -1279,9 +1356,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) } } } - fd_data[fdu].ft = fd_types + type - 1; - fd_data[fdu].flags |= FD_OPEN; - + fd->ft = fd_types + type - 1; + fd->flags |= FD_OPEN; + device_busy(fd->dev); + device_busy(fd->fdc->fdc_dev); return 0; } @@ -1289,11 +1367,13 @@ int fdclose(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); + struct fd_data *fd; - fd_data[fdu].flags &= ~FD_OPEN; - fd_data[fdu].options &= ~FDOPT_NORETRY; + fd = devclass_get_softc(fd_devclass, fdu); + fd->flags &= ~FD_OPEN; + fd->options &= ~FDOPT_NORETRY; - return(0); + return (0); } static int @@ -1317,16 +1397,17 @@ fdstrategy(struct buf *bp) { unsigned nblocks, blknum, cando; int s; - fdcu_t fdcu; fdu_t fdu; fdc_p fdc; fd_p fd; size_t fdblk; fdu = FDUNIT(minor(bp->b_dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); + if (fd == 0) + panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", + (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev)); fdc = fd->fdc; - fdcu = fdc->fdcu; #ifdef FDC_YE if (fd->type == NO_TYPE) { bp->b_error = ENXIO; @@ -1341,7 +1422,7 @@ fdstrategy(struct buf *bp) fdblk = 128 << (fd->ft->secsize); if (!(bp->b_flags & B_FORMAT)) { - if ((fdu >= NFD) || (bp->b_blkno < 0)) { + if (bp->b_blkno < 0) { printf( "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", fdu, (u_long)bp->b_blkno, bp->b_bcount); @@ -1386,12 +1467,12 @@ fdstrategy(struct buf *bp) bp->b_pblkno = bp->b_blkno; s = splbio(); bufqdisksort(&fdc->head, bp); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */ + untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ /* Tell devstat we are starting on the transaction */ devstat_start_transaction(&fd->device_stats); - fdstart(fdcu); + fdstart(fdc); splx(s); return; @@ -1409,27 +1490,25 @@ bad: * will pick up our work when the present work completes * \***************************************************************/ static void -fdstart(fdcu_t fdcu) +fdstart(struct fdc_data *fdc) { int s; s = splbio(); - if(fdc_data[fdcu].state == DEVIDLE) + if(fdc->state == DEVIDLE) { - fdintr(fdcu); + fdc_intr(fdc); } splx(s); } static void -fd_iotimeout(void *arg1) +fd_iotimeout(void *xfdc) { fdc_p fdc; - fdcu_t fdcu; int s; - fdcu = (fdcu_t)arg1; - fdc = fdc_data + fdcu; + fdc = xfdc; TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* @@ -1447,19 +1526,18 @@ fd_iotimeout(void *arg1) fdc->status[0] = NE7_ST0_IC_IV; fdc->flags &= ~FDC_STAT_VALID; fdc->state = IOTIMEDOUT; - fdintr(fdcu); + fdc_intr(fdc); splx(s); } /* just ensure it has the right spl */ static void -fd_pseudointr(void *arg1) +fd_pseudointr(void *xfdc) { - fdcu_t fdcu = (fdcu_t)arg1; int s; s = splbio(); - fdintr(fdcu); + fdc_intr(xfdc); splx(s); } @@ -1469,11 +1547,11 @@ fd_pseudointr(void *arg1) * ALWAYS called at SPLBIO * \***********************************************************************/ static void -fdintr(fdcu_t fdcu) +fdc_intr(void *xfdc) { - fdc_p fdc = fdc_data + fdcu; - while(fdstate(fdcu, fdc)) - ; + fdc_p fdc = xfdc; + while(fdstate(fdc)) + ; } #ifdef FDC_YE @@ -1513,7 +1591,7 @@ static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) * if it returns a non zero value, it should be called again immediatly * \***********************************************************************/ static int -fdstate(fdcu_t fdcu, fdc_p fdc) +fdstate(fdc_p fdc) { int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; @@ -1537,26 +1615,25 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * Force into the IDLE state, * \***********************************************/ fdc->state = DEVIDLE; - if(fdc->fd) - { - printf("fd%d: unexpected valid fd pointer\n", - fdc->fdu); + if (fdc->fd) { + device_print_prettyname(fdc->fdc_dev); + printf("unexpected valid fd pointer\n"); fdc->fd = (fd_p) 0; fdc->fdu = -1; } - TRACE1("[fdc%d IDLE]", fdcu); - return(0); + TRACE1("[fdc%d IDLE]", fdc->fdcu); + return (0); } fdu = FDUNIT(minor(bp->b_dev)); - fd = fd_data + fdu; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; - if (fdc->fd && (fd != fdc->fd)) - { - printf("fd%d: confused fd pointers\n", fdu); + if (fdc->fd && (fd != fdc->fd)) { + device_print_prettyname(fd->dev); + printf("confused fd pointers\n"); } read = bp->b_flags & B_READ; format = bp->b_flags & B_FORMAT; - if(format) { + if (format) { finfo = (struct fd_formb *)bp->b_data; fd->skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; @@ -1569,8 +1646,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) TRACE1("fd%d", fdu); TRACE1("[%s]", fdstates[fdc->state]); TRACE1("(0x%x)", fd->flags); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); - fd->toffhandle = timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); + untimeout(fd_turnoff, fd, fd->toffhandle); + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); switch (fdc->state) { case DEVIDLE: @@ -1585,10 +1662,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * If the next drive has a motor startup pending, then * * it will start up in its own good time * \*******************************************************/ - if(fd->flags & FD_MOTOR_WAIT) - { + if(fd->flags & FD_MOTOR_WAIT) { fdc->state = MOTORWAIT; - return(0); /* come back later */ + return (0); /* come back later */ } /*******************************************************\ * Maybe if it's not starting, it SHOULD be starting * @@ -1596,12 +1672,12 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (!(fd->flags & FD_MOTOR)) { fdc->state = MOTORWAIT; - fd_turnon(fdu); - return(0); + fd_turnon(fd); + return (0); } else /* at least make sure we are selected */ { - set_motor(fdcu, fd->fdsu, TURNON); + set_motor(fdc, fd->fdsu, TURNON); } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1615,7 +1691,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = SEEKCOMPLETE; break; } - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, b_cylinder * fd->ft->steptrac, 0)) { @@ -1624,20 +1700,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * the FDC went off to the Saints... */ fdc->retry = 6; /* try a reset */ - return(retrier(fdcu)); + return(retrier(fdc)); } fd->track = FD_NO_TRACK; fdc->state = SEEKWAIT; return(0); /* will return later */ case SEEKWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 16); + timeout(fd_pseudointr, fdc, hz / 16); fdc->state = SEEKCOMPLETE; return(0); /* will return later */ case SEEKCOMPLETE : /* SEEK DONE, START DMA */ /* Make sure seek really happened*/ - if(fd->track == FD_NO_TRACK) - { + if(fd->track == FD_NO_TRACK) { int descyl = b_cylinder * fd->ft->steptrac; do { /* @@ -1669,8 +1744,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) return 0; /* hope for a real intr */ } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); - if (0 == descyl) - { + if (0 == descyl) { int failed = 0; /* * seek to cyl 0 requested; make sure we are @@ -1685,22 +1759,20 @@ fdstate(fdcu_t fdcu, fdc_p fdc) failed = 1; } - if (failed) - { + if (failed) { if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } - if (cyl != descyl) - { + if (cyl != descyl) { printf( "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, descyl, cyl, st0); if (fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } @@ -1726,7 +1798,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; /* reset the beast */ - return(retrier(fdcu)); + return (retrier(fdc)); } if(st3 & NE7_ST3_WP) { @@ -1749,8 +1821,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) } } - if(format) - { + if (format) { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) (void)fdcpio(fdcu,bp->b_flags, @@ -1758,25 +1829,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) bp->b_bcount); #endif /* formatting */ - if(fd_cmd(fdcu, 6, - NE7CMD_FORMAT, - head << 2 | fdu, + if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu, finfo->fd_formb_secshift, finfo->fd_formb_nsecs, finfo->fd_formb_gaplen, - finfo->fd_formb_fillbyte, - 0)) - { + finfo->fd_formb_fillbyte, 0)) { /* controller fell over */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } - } - else - { + } else { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) { /* @@ -1795,7 +1860,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdblk); } #endif - if (fd_cmd(fdcu, 9, + if (fd_cmd(fdc, 9, (read ? NE7CMD_READ : NE7CMD_WRITE), head << 2 | fdu, /* head & unit */ fd->track, /* track */ @@ -1805,14 +1870,13 @@ fdstate(fdcu_t fdcu, fdc_p fdc) sectrac, /* sectors/track */ fd->ft->gap, /* gap size */ fd->ft->datalen, /* data length */ - 0)) - { + 0)) { /* the beast is sleeping again */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } } #ifdef FDC_YE @@ -1834,8 +1898,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ #endif fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); - return(0); /* will return later */ + fd->tohandle = timeout(fd_iotimeout, fdc, hz); + return (0); /* will return later */ #ifdef FDC_YE case PIOREAD: /* @@ -1847,16 +1911,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ #endif case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, fdc, fd->tohandle); - if (fd_read_status(fdc, fd->fdsu)) - { + if (fd_read_status(fdc, fd->fdsu)) { isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ - return retrier(fdcu); + return (retrier(fdc)); } fdc->state = IOTIMEDOUT; @@ -1869,8 +1932,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) #endif isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); - if (fdc->status[0] & NE7_ST0_IC) - { + if (fdc->status[0] & NE7_ST0_IC) { if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT && fdc->status[1] & NE7_ST1_OR) { /* @@ -1890,17 +1952,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc) && fdc->status[2] & NE7_ST2_WC && fdc->retry < 3) fdc->retry = 3; /* force recalibrate */ - return(retrier(fdcu)); + return (retrier(fdc)); } /* All OK */ fd->skip += fdblk; - if (!format && fd->skip < bp->b_bcount - bp->b_resid) - { + if (!format && fd->skip < bp->b_bcount - bp->b_resid) { /* set up next transfer */ fdc->state = DOSEEK; - } - else - { + } else { /* ALL DONE */ fd->skip = 0; fdc->bp = NULL; @@ -1915,7 +1974,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->fdu = -1; fdc->state = FINDWORK; } - return(1); + return (1); case RESETCTLR: fdc_reset(fdc); fdc->retry++; @@ -1931,21 +1990,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = STARTRECAL; /* Fall through. */ case STARTRECAL: - if(fd_cmd(fdcu, - 2, NE7CMD_RECAL, fdu, - 0)) /* Recalibrate Function */ - { + if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { /* arrgl */ fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } fdc->state = RECALWAIT; - return(0); /* will return later */ + return (0); /* will return later */ case RECALWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 8); + timeout(fd_pseudointr, fdc, hz / 8); fdc->state = RECALCOMPLETE; - return(0); /* will return later */ + return (0); /* will return later */ case RECALCOMPLETE: do { /* @@ -1971,16 +2027,16 @@ fdstate(fdcu_t fdcu, fdc_p fdc) printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, st0, NE7_ST0BITS, cyl); if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } fd->track = 0; /* Seek (probably) necessary */ fdc->state = DOSEEK; - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ case MOTORWAIT: if(fd->flags & FD_MOTOR_WAIT) { - return(0); /* time's not up yet */ + return (0); /* time's not up yet */ } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1993,9 +2049,10 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ fdc->state = STARTRECAL; } - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ default: - printf("fdc%d: Unexpected FD int->", fdcu); + device_print_prettyname(fdc->fdc_dev); + printf("unexpected FD int->"); if (fd_read_status(fdc, fd->fdsu) == 0) printf("FDC status :%x %x %x %x %x %x %x ", fdc->status[0], @@ -2010,28 +2067,31 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (fd_sense_int(fdc, &st0, &cyl) != 0) { printf("[controller is dead now]\n"); - return(0); + return (0); } printf("ST0 = %x, PCN = %x\n", st0, cyl); - return(0); + return (0); } /*XXX confusing: some branches return immediately, others end up here*/ - return(1); /* Come back immediatly to new state */ + return (1); /* Come back immediatly to new state */ } static int -retrier(fdcu) - fdcu_t fdcu; +retrier(struct fdc_data *fdc) { - fdc_p fdc = fdc_data + fdcu; register struct buf *bp; + struct fd_data *fd; + int fdu; bp = fdc->bp; - if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) + /* XXX shouldn't this be cached somewhere? */ + fdu = FDUNIT(minor(bp->b_dev)); + fd = devclass_get_softc(fd_devclass, fdu); + if (fd->options & FDOPT_NORETRY) goto fail; - switch(fdc->retry) - { + + switch (fdc->retry) { case 0: case 1: case 2: fdc->state = SEEKCOMPLETE; break; @@ -2084,10 +2144,10 @@ retrier(fdcu) fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - return(1); + return (1); } fdc->retry++; - return(1); + return (1); } static int @@ -2104,7 +2164,7 @@ fdformat(dev, finfo, p) size_t fdblk; fdu = FDUNIT(minor(dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; /* set up a buffer header for fdstrategy() */ @@ -2135,20 +2195,19 @@ fdformat(dev, finfo, p) /* ...and wait for it to complete */ s = splbio(); - while(!(bp->b_flags & B_DONE)) - { + while(!(bp->b_flags & B_DONE)) { rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); - if(rv == EWOULDBLOCK) + if (rv == EWOULDBLOCK) break; } splx(s); - if(rv == EWOULDBLOCK) { + if (rv == EWOULDBLOCK) { /* timed out */ rv = EIO; biodone(bp); } - if(bp->b_flags & B_ERROR) + if (bp->b_flags & B_ERROR) rv = bp->b_error; /* * allow the process to be swapped @@ -2171,7 +2230,7 @@ fdioctl(dev, cmd, addr, flag, p) struct proc *p; { fdu_t fdu = FDUNIT(minor(dev)); - fd_p fd = &fd_data[fdu]; + fd_p fd = devclass_get_softc(fd_devclass, fdu); size_t fdblk; struct fd_type *fdt; @@ -2181,13 +2240,12 @@ fdioctl(dev, cmd, addr, flag, p) fdblk = 128 << fd->ft->secsize; - switch (cmd) - { + switch (cmd) { case DIOCGDINFO: bzero(buffer, sizeof (buffer)); dl = (struct disklabel *)buffer; dl->d_secsize = fdblk; - fdt = fd_data[FDUNIT(minor(dev))].ft; + fdt = fd->ft; dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; @@ -2211,8 +2269,7 @@ fdioctl(dev, cmd, addr, flag, p) break; case DIOCWDINFO: - if ((flag & FWRITE) == 0) - { + if ((flag & FWRITE) == 0) { error = EBADF; break; } @@ -2227,9 +2284,9 @@ fdioctl(dev, cmd, addr, flag, p) (struct disklabel *)buffer); break; case FD_FORM: - if((flag & FWRITE) == 0) + if ((flag & FWRITE) == 0) error = EBADF; /* must be opened for writing */ - else if(((struct fd_formb *)addr)->format_version != + else if (((struct fd_formb *)addr)->format_version != FD_FORMAT_VERSION) error = EINVAL; /* wrong version of formatting prog */ else @@ -2242,7 +2299,7 @@ fdioctl(dev, cmd, addr, flag, p) case FD_STYPE: /* set drive type */ /* this is considered harmful; only allow for superuser */ - if(suser(p->p_ucred, &p->p_acflag) != 0) + if (suser(p->p_ucred, &p->p_acflag) != 0) return EPERM; *fd->ft = *(struct fd_type *)addr; break; @@ -2262,22 +2319,62 @@ fdioctl(dev, cmd, addr, flag, p) return (error); } +static device_method_t fdc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fdc_probe), + DEVMETHOD(device_attach, fdc_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), -static fd_devsw_installed = 0; + /* Bus interface */ + DEVMETHOD(bus_print_child, fdc_print_child), + /* Our children never use any other bus interface methods. */ -static void fd_drvinit(void *notused ) -{ + { 0, 0 } +}; - if( ! fd_devsw_installed ) { - cdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &fd_cdevsw); - fd_devsw_installed = 1; - } -} +static driver_t fdc_driver = { + "fdc", + fdc_methods, + DRIVER_TYPE_BIO, + sizeof(struct fdc_data) +}; -SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL) +DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0); +static device_method_t fd_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fd_probe), + DEVMETHOD(device_attach, fd_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */ + DEVMETHOD(device_resume, bus_generic_resume), /* XXX */ -#endif + { 0, 0 } +}; + +static driver_t fd_driver = { + "fd", + fd_methods, + DRIVER_TYPE_BIO, + sizeof(struct fd_data) +}; + +static struct cdevsw fd_cdevsw = { + Fdopen, fdclose, fdread, fdwrite, + fdioctl, nostop, nullreset, nodevtotty, + seltrue, nommap, fdstrategy, "fd", + NULL, -1, nodump, nopsize, + D_DISK, 0, -1 +}; + +BDEV_DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, BDEV_MAJOR, CDEV_MAJOR, + fd_cdevsw, 0, 0); + +#endif /* NFDC > 0 */ /* * Hello emacs, these are the diff --git a/sys/dev/fxp/if_fxp.c b/sys/dev/fxp/if_fxp.c index 77f0ade..53b8d4d 100644 --- a/sys/dev/fxp/if_fxp.c +++ b/sys/dev/fxp/if_fxp.c @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.65 1999/03/17 16:44:53 luigi Exp $ + * $Id: if_fxp.c,v 1.66 1999/03/20 04:51:25 wes Exp $ */ /* @@ -89,6 +89,10 @@ #else /* __FreeBSD__ */ #include <sys/sockio.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <net/ethernet.h> #include <net/if_arp.h> @@ -491,51 +495,31 @@ fxp_ether_ioctl(ifp, cmd, data) #else /* __FreeBSD__ */ -static u_long fxp_count; -static const char *fxp_probe __P((pcici_t, pcidi_t)); -static void fxp_attach __P((pcici_t, int)); - -static void fxp_shutdown __P((int, void *)); - -static struct pci_device fxp_device = { - "fxp", - fxp_probe, - fxp_attach, - &fxp_count, - NULL -}; -DATA_SET(pcidevice_set, fxp_device); - /* * Return identification string if this is device is ours. */ -static const char * -fxp_probe(config_id, device_id) - pcici_t config_id; - pcidi_t device_id; +static int +fxp_probe(device_t dev) { - if (((device_id & 0xffff) == FXP_VENDORID_INTEL) && - ((device_id >> 16) & 0xffff) == FXP_DEVICEID_i82557) - return ("Intel EtherExpress Pro 10/100B Ethernet"); + if ((pci_get_vendor(dev) == FXP_VENDORID_INTEL) && + (pci_get_device(dev) == FXP_DEVICEID_i82557)) { + device_set_desc(dev, "Intel EtherExpress Pro 10/100B Ethernet"); + return 0; + } - return NULL; + return ENXIO; } -static void -fxp_attach(config_id, unit) - pcici_t config_id; - int unit; +static int +fxp_attach(device_t dev) { - struct fxp_softc *sc; - vm_offset_t pbase; + int error = 0; + struct fxp_softc *sc = device_get_softc(dev); struct ifnet *ifp; int s; u_long val; + int rid; - sc = malloc(sizeof(struct fxp_softc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return; - bzero(sc, sizeof(struct fxp_softc)); callout_handle_init(&sc->stat_ch); s = splimp(); @@ -543,39 +527,56 @@ fxp_attach(config_id, unit) /* * Enable bus mastering. */ - val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); + val = pci_read_config(dev, PCIR_COMMAND, 2); val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val); + pci_write_config(dev, PCIR_COMMAND, val, 2); /* * Map control/status registers. */ - if (!pci_map_mem(config_id, FXP_PCI_MMBA, - (vm_offset_t *)&sc->csr, &pbase)) { - printf("fxp%d: couldn't map memory\n", unit); + rid = FXP_PCI_MMBA; + sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->mem) { + device_printf(dev, "could not map memory\n"); + error = ENXIO; goto fail; - } + } + sc->csr = rman_get_virtual(sc->mem); /* XXX use bus_space */ /* * Allocate our interrupt. */ - if (!pci_map_int(config_id, fxp_intr, sc, &net_imask)) { - printf("fxp%d: couldn't map interrupt\n", unit); + rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->irq == NULL) { + device_printf(dev, "could not map interrupt\n"); + error = ENXIO; + goto fail; + } + + error = bus_setup_intr(dev, sc->irq, fxp_intr, sc, &sc->ih); + if (error) { + device_printf(dev, "could not setup irq\n"); goto fail; } /* Do generic parts of attach. */ if (fxp_attach_common(sc, sc->arpcom.ac_enaddr)) { /* Failed! */ - (void) pci_unmap_int(config_id); + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem); + error = ENXIO; goto fail; } - printf("fxp%d: Ethernet address %6D%s\n", unit, + device_printf(dev, "Ethernet address %6D%s\n", sc->arpcom.ac_enaddr, ":", sc->phy_10Mbps_only ? ", 10Mbps" : ""); ifp = &sc->arpcom.ac_if; - ifp->if_unit = unit; + ifp->if_unit = device_get_unit(dev); ifp->if_name = "fxp"; ifp->if_output = ether_output; ifp->if_baudrate = 100000000; @@ -600,19 +601,63 @@ fxp_attach(config_id, unit) bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif + splx(s); + return 0; + + fail: + splx(s); + return error; +} + +/* + * Detach interface. + */ +static int +fxp_detach(device_t dev) +{ + struct fxp_softc *sc = device_get_softc(dev); + int s; + + s = splimp(); + /* - * Add shutdown hook so that DMA is disabled prior to reboot. Not - * doing do could allow DMA to corrupt kernel memory during the - * reboot before the driver initializes. + * Close down routes etc. */ - at_shutdown(fxp_shutdown, sc, SHUTDOWN_POST_SYNC); + if_detach(&sc->arpcom.ac_if); - splx(s); - return; + /* + * Stop DMA and drop transmit queue. + */ + fxp_stop(sc); + + /* + * Deallocate resources. + */ + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem); + + /* + * Free all the receive buffers. + */ + if (sc->rfa_headm != NULL) + m_freem(sc->rfa_headm); + + /* + * Free all media structures. + */ + ifmedia_removeall(&sc->sc_media); + + /* + * Free anciliary structures. + */ + free(sc->cbl_base, M_DEVBUF); + free(sc->fxp_stats, M_DEVBUF); + free(sc->mcsp, M_DEVBUF); - fail: - free(sc, M_DEVBUF); splx(s); + + return 0; } /* @@ -620,14 +665,39 @@ fxp_attach(config_id, unit) * main purpose of this routine is to shut off receiver DMA so that * kernel memory doesn't get clobbered during warmboot. */ -static void -fxp_shutdown(howto, sc) - int howto; - void *sc; +static int +fxp_shutdown(device_t dev) { - fxp_stop((struct fxp_softc *) sc); + /* + * Make sure that DMA is disabled prior to reboot. Not doing + * do could allow DMA to corrupt kernel memory during the + * reboot before the driver initializes. + */ + fxp_stop((struct fxp_softc *) device_get_softc(dev)); + return 0; } +static device_method_t fxp_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fxp_probe), + DEVMETHOD(device_attach, fxp_attach), + DEVMETHOD(device_detach, fxp_detach), + DEVMETHOD(device_shutdown, fxp_shutdown), + + { 0, 0 } +}; + +static driver_t fxp_driver = { + "fxp", + fxp_methods, + DRIVER_TYPE_NET, + sizeof(struct fxp_softc), +}; + +static devclass_t fxp_devclass; + +DRIVER_MODULE(fxp, pci, fxp_driver, fxp_devclass, 0, 0); + #endif /* __NetBSD__ */ /************************************************************* diff --git a/sys/dev/fxp/if_fxpvar.h b/sys/dev/fxp/if_fxpvar.h index ce8d8fe..042d2df 100644 --- a/sys/dev/fxp/if_fxpvar.h +++ b/sys/dev/fxp/if_fxpvar.h @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxpvar.h,v 1.5 1998/06/07 17:12:38 dfr Exp $ + * $Id: if_fxpvar.h,v 1.6 1998/08/02 00:29:15 dg Exp $ */ /* @@ -48,6 +48,9 @@ struct fxp_softc { #else struct arpcom arpcom; /* per-interface network data */ caddr_t csr; /* control/status registers */ + struct resource *mem; /* resource descriptor for registers */ + struct resource *irq; /* resource descriptor for interrupt */ + void *ih; /* interrupt handler cookie */ #endif /* __NetBSD__ */ struct mbuf *rfa_headm; /* first mbuf in receive frame area */ struct mbuf *rfa_tailm; /* last mbuf in receive frame area */ diff --git a/sys/dev/kbd/atkbd.c b/sys/dev/kbd/atkbd.c index f9e28fe..80c81a5 100644 --- a/sys/dev/kbd/atkbd.c +++ b/sys/dev/kbd/atkbd.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atkbd.c,v 1.4 1999/01/28 10:55:55 yokota Exp $ + * $Id: atkbd.c,v 1.5 1999/03/10 10:36:52 yokota Exp $ */ #include "atkbd.h" @@ -46,7 +46,7 @@ #include <dev/kbd/atkbdreg.h> #include <dev/kbd/atkbdcreg.h> -#ifndef __i386__ +#if 1 #include <sys/bus.h> #include <isa/isareg.h> @@ -89,6 +89,7 @@ static struct cdevsw atkbd_cdevsw = { #endif /* KBD_INSTALL_CDEV */ +#if 0 #ifdef __i386__ atkbd_softc_t @@ -110,6 +111,7 @@ atkbd_softc_t } #endif /* __i386__ */ +#endif int atkbd_probe_unit(int unit, int port, int irq, int flags) @@ -376,16 +378,14 @@ atkbd_configure(int flags) { keyboard_t *kbd; int arg[2]; -#ifdef __i386__ - struct isa_device *dev; int i; /* XXX: a kludge to obtain the device configuration flags */ - dev = find_isadev(isa_devtab_tty, &atkbddriver, 0); - if (dev != NULL) { - flags |= dev->id_flags; + if (resource_int_value("atkbd", 0, "flags", &i) == 0) { + flags |= i; /* if the driver is disabled, unregister the keyboard if any */ - if (!dev->id_enabled) { + if (resource_int_value("atkbd", 0, "disabled", &i) == 0 + && i != 0) { i = kbd_find_keyboard(ATKBD_DRIVER_NAME, ATKBD_DEFAULT); if (i >= 0) { kbd = kbd_get_keyboard(i); @@ -395,8 +395,7 @@ atkbd_configure(int flags) } } } -#endif - + /* probe the keyboard controller */ atkbdc_configure(); diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c index e449fc2..889550c 100644 --- a/sys/dev/pci/pci.c +++ b/sys/dev/pci/pci.c @@ -23,10 +23,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci.c,v 1.93 1999/01/19 23:29:18 se Exp $ + * $Id: pci.c,v 1.94 1999/04/11 02:47:31 eivind Exp $ * */ +#include "opt_bus.h" + #include "pci.h" #if NPCI > 0 @@ -50,6 +52,11 @@ #include <vm/pmap.h> #include <vm/vm_extern.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + #include <pci/pcireg.h> #include <pci/pcivar.h> #include <pci/pci_ioctl.h> @@ -338,11 +345,10 @@ pci_readcfg(pcicfgregs *probe) M_DEVBUF, M_WAITOK); if (devlist_entry == NULL) return (NULL); + bzero(devlist_entry, sizeof *devlist_entry); cfg = &devlist_entry->cfg; - bzero(cfg, sizeof *cfg); - cfg->bus = probe->bus; cfg->slot = probe->slot; cfg->func = probe->func; @@ -450,113 +456,6 @@ pci_freecfg(struct pci_devinfo *dinfo) } #endif -static void -pci_addcfg(struct pci_devinfo *dinfo) -{ - if (bootverbose) { - int i; - pcicfgregs *cfg = &dinfo->cfg; - - printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", - cfg->vendor, cfg->device, cfg->revid); - printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", - cfg->baseclass, cfg->subclass, cfg->progif, - cfg->hdrtype, cfg->mfdev); - printf("\tsubordinatebus=%x \tsecondarybus=%x\n", - cfg->subordinatebus, cfg->secondarybus); -#ifdef PCI_DEBUG - printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", - cfg->cmdreg, cfg->statreg, cfg->cachelnsz); - printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", - cfg->lattimer, cfg->lattimer * 30, - cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); -#endif /* PCI_DEBUG */ - if (cfg->intpin > 0) - printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); - - for (i = 0; i < cfg->nummaps; i++) { - pcimap *m = &cfg->map[i]; - printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", - i, m->type, m->ln2range, m->base, m->ln2size); - } - } - pci_drvattach(dinfo); /* XXX currently defined in pci_compat.c */ -} - -/* scan one PCI bus for devices */ - -static int -pci_probebus(int bus) -{ - pcicfgregs probe; - int bushigh = bus; - -#ifdef SIMOS -#undef PCI_SLOTMAX -#define PCI_SLOTMAX 0 -#endif - - bzero(&probe, sizeof probe); - /* XXX KDM */ - /* probe.parent = pci_bridgeto(bus); */ - probe.bus = bus; - for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { - int pcifunchigh = 0; - for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { - struct pci_devinfo *dinfo = pci_readcfg(&probe); - if (dinfo != NULL) { - if (dinfo->cfg.mfdev) - pcifunchigh = 7; - /* - * XXX: Temporarily move pci_addcfg() up before - * the use of cfg->subordinatebus. This is - * necessary, since pci_addcfg() calls the - * device's probe(), which may read the bus# - * from some device dependent register of - * some host to PCI bridges. The probe will - * eventually be moved to pci_readcfg(), and - * pci_addcfg() will then be moved back down - * below the conditional statement ... - */ - pci_addcfg(dinfo); - - if (bushigh < dinfo->cfg.subordinatebus) - bushigh = dinfo->cfg.subordinatebus; - if (bushigh < dinfo->cfg.secondarybus) - bushigh = dinfo->cfg.secondarybus; - - /* XXX KDM */ - /* cfg = NULL; we don't own this anymore ... */ - } - } - } - return (bushigh); -} - -/* scan a PCI bus tree reached through one PCI attachment point */ - -int -pci_probe(pciattach *parent) -{ - int bushigh; - int bus = 0; - - STAILQ_INIT(&pci_devq); - - bushigh = pci_bushigh(); - while (bus <= bushigh) { - int newbushigh; - - printf("Probing for devices on PCI bus %d:\n", bus); - newbushigh = pci_probebus(bus); - - if (bushigh < newbushigh) - bushigh = newbushigh; - bus++; - } - return (bushigh); -} - /* * This is the user interface to PCI configuration space. */ @@ -750,8 +649,8 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) "pci_match_conf) (%d)\npci_ioctl: " "pat_buf_len should be = %d\n", cio->pat_buf_len, cio->num_patterns, - sizeof(struct pci_match_conf), - sizeof(struct pci_match_conf) * + (int)sizeof(struct pci_match_conf), + (int)sizeof(struct pci_match_conf) * cio->num_patterns); printf("pci_ioctl: do your headers match your " "kernel?\n"); @@ -945,4 +844,534 @@ pci_cdevinit(void *dummy) SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL); +#include "pci_if.h" + +/* + * A simple driver to wrap the old pci driver mechanism for back-compat. + */ + +static int +pci_compat_probe(device_t dev) +{ + struct pci_device *dvp; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + const char *name; + int error; + + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + dvp = device_get_driver(dev)->priv; + + /* + * Do the wrapped probe. + */ + error = ENXIO; + if (dvp && dvp->pd_probe) { + name = dvp->pd_probe(cfg, (cfg->device << 16) + cfg->vendor); + if (name) { + device_set_desc_copy(dev, name); + error = 0; + } + } + + return error; +} + +static int +pci_compat_attach(device_t dev) +{ + struct pci_device *dvp; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + int unit; + + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + dvp = device_get_driver(dev)->priv; + + unit = device_get_unit(dev); + if (unit > *dvp->pd_count) + *dvp->pd_count = unit; + if (dvp->pd_attach) + dvp->pd_attach(cfg, unit); + + /* + * XXX KDM for some devices, dvp->pd_name winds up NULL. + * I haven't investigated enough to figure out why this + * would happen. + */ + if (dvp->pd_name != NULL) + strncpy(dinfo->conf.pd_name, dvp->pd_name, + sizeof(dinfo->conf.pd_name)); + else + strncpy(dinfo->conf.pd_name, "????", + sizeof(dinfo->conf.pd_name)); + dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0; + dinfo->conf.pd_unit = unit; + + return 0; +} + +static device_method_t pci_compat_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pci_compat_probe), + DEVMETHOD(device_attach, pci_compat_attach), + + { 0, 0 } +}; + +static devclass_t pci_devclass; + +/* + * Create a new style driver around each old pci driver. + */ +static void +pci_wrap_old_drivers(void) +{ + struct pci_device **dvpp, *dvp; + + dvpp = (struct pci_device **)pcidevice_set.ls_items; + while ((dvp = *dvpp++) != NULL) { + driver_t *driver; + driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT); + if (!driver) + continue; + bzero(driver, sizeof(driver_t)); + driver->name = dvp->pd_name; + driver->methods = pci_compat_methods; + driver->type = 0; /* XXX fixup in pci_map_int() */ + driver->softc = sizeof(struct pci_devinfo *); + driver->priv = dvp; + devclass_add_driver(pci_devclass, driver); + } +} + +/* + * New style pci driver. Parent device is either a pci-host-bridge or a + * pci-pci-bridge. Both kinds are represented by instances of pcib. + */ + +static void +pci_print_verbose(struct pci_devinfo *dinfo) +{ + if (bootverbose) { + int i; + pcicfgregs *cfg = &dinfo->cfg; + + printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", + cfg->vendor, cfg->device, cfg->revid); + printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", + cfg->baseclass, cfg->subclass, cfg->progif, + cfg->hdrtype, cfg->mfdev); + printf("\tsubordinatebus=%x \tsecondarybus=%x\n", + cfg->subordinatebus, cfg->secondarybus); +#ifdef PCI_DEBUG + printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", + cfg->cmdreg, cfg->statreg, cfg->cachelnsz); + printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", + cfg->lattimer, cfg->lattimer * 30, + cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); +#endif /* PCI_DEBUG */ + if (cfg->intpin > 0) + printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); + + for (i = 0; i < cfg->nummaps; i++) { + pcimap *m = &cfg->map[i]; + printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", + i, m->type, m->ln2range, m->base, m->ln2size); + } + } +} + +static int +pci_add_children(device_t dev, int busno) +{ + pcicfgregs probe; + int bushigh = busno; + +#ifdef SIMOS +#undef PCI_SLOTMAX +#define PCI_SLOTMAX 0 +#endif + + bzero(&probe, sizeof probe); + /* XXX KDM */ + /* probe.parent = pci_bridgeto(bus); */ + probe.bus = busno; + for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { + int pcifunchigh = 0; + for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { + struct pci_devinfo *dinfo = pci_readcfg(&probe); + if (dinfo != NULL) { + if (dinfo->cfg.mfdev) + pcifunchigh = 7; + + pci_print_verbose(dinfo); + dinfo->cfg.dev = + device_add_child(dev, NULL, -1, dinfo); + + if (bushigh < dinfo->cfg.subordinatebus) + bushigh = dinfo->cfg.subordinatebus; + if (bushigh < dinfo->cfg.secondarybus) + bushigh = dinfo->cfg.secondarybus; + } + } + } + + return bushigh; +} + +static int +pci_new_probe(device_t dev) +{ + STAILQ_INIT(&pci_devq); + device_set_desc(dev, "PCI bus"); + + pci_add_children(dev, device_get_unit(dev)); + + return 0; +} + +static void +pci_print_child(device_t dev, device_t child) +{ + printf(" at device %d.%d", pci_get_slot(child), pci_get_function(child)); + printf(" on %s%d", device_get_name(dev), device_get_unit(dev)); +} + +static int +pci_read_ivar(device_t dev, device_t child, int which, u_long *result) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + + switch (which) { + case PCI_IVAR_SUBVENDOR: + *result = cfg->subvendor; + break; + case PCI_IVAR_SUBDEVICE: + *result = cfg->subdevice; + break; + case PCI_IVAR_VENDOR: + *result = cfg->vendor; + break; + case PCI_IVAR_DEVICE: + *result = cfg->device; + break; + case PCI_IVAR_DEVID: + *result = (cfg->device << 16) | cfg->vendor; + break; + case PCI_IVAR_CLASS: + *result = cfg->baseclass; + break; + case PCI_IVAR_SUBCLASS: + *result = cfg->subclass; + break; + case PCI_IVAR_PROGIF: + *result = cfg->progif; + break; + case PCI_IVAR_REVID: + *result = cfg->revid; + break; + case PCI_IVAR_INTPIN: + *result = cfg->intpin; + break; + case PCI_IVAR_IRQ: + *result = cfg->intline; + break; + case PCI_IVAR_BUS: + *result = cfg->bus; + break; + case PCI_IVAR_SLOT: + *result = cfg->slot; + break; + case PCI_IVAR_FUNCTION: + *result = cfg->func; + break; + case PCI_IVAR_SECONDARYBUS: + *result = cfg->secondarybus; + break; + case PCI_IVAR_SUBORDINATEBUS: + *result = cfg->subordinatebus; + break; + default: + return ENOENT; + } + return 0; +} + +static int +pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + + switch (which) { + case PCI_IVAR_SUBVENDOR: + case PCI_IVAR_SUBDEVICE: + case PCI_IVAR_VENDOR: + case PCI_IVAR_DEVICE: + case PCI_IVAR_DEVID: + case PCI_IVAR_CLASS: + case PCI_IVAR_SUBCLASS: + case PCI_IVAR_PROGIF: + case PCI_IVAR_REVID: + case PCI_IVAR_INTPIN: + case PCI_IVAR_IRQ: + case PCI_IVAR_BUS: + case PCI_IVAR_SLOT: + case PCI_IVAR_FUNCTION: + return EINVAL; /* disallow for now */ + + case PCI_IVAR_SECONDARYBUS: + cfg->secondarybus = value; + break; + case PCI_IVAR_SUBORDINATEBUS: + cfg->subordinatebus = value; + break; + default: + return ENOENT; + } + return 0; +} + +static int +pci_mapno(pcicfgregs *cfg, int reg) +{ + int i, nummaps; + pcimap *map; + + nummaps = cfg->nummaps; + map = cfg->map; + + for (i = 0; i < nummaps; i++) + if (map[i].reg == reg) + return (i); + return (-1); +} + +static int +pci_porten(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); +} + +static int +pci_isportmap(pcicfgregs *cfg, int map) + +{ + return ((unsigned)map < cfg->nummaps + && (cfg->map[map].type & PCI_MAPPORT) != 0); +} + +static int +pci_memen(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); +} + +static int +pci_ismemmap(pcicfgregs *cfg, int map) +{ + return ((unsigned)map < cfg->nummaps + && (cfg->map[map].type & PCI_MAPMEM) != 0); +} + +static struct resource * +pci_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + int isdefault; + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + struct resource *rv, **rvp = 0; + int map; + + isdefault = (device_get_parent(child) == dev + && start == 0UL && end == ~0UL && count == 1); + + switch (type) { + case SYS_RES_IRQ: + if (*rid != 0) + return 0; + if (isdefault && cfg->intline != 255) { + start = cfg->intline; + end = cfg->intline; + count = 1; + } + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + if (isdefault) { + map = pci_mapno(cfg, *rid); + if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { + start = cfg->map[map].base; + count = 1 << cfg->map[map].ln2size; + end = start + count; + rvp = &cfg->map[map].res; + } else + return 0; + } + break; + + case SYS_RES_IOPORT: + if (isdefault) { + map = pci_mapno(cfg, *rid); + if (pci_porten(cfg) && pci_isportmap(cfg, map)) { + start = cfg->map[map].base; + count = 1 << cfg->map[map].ln2size; + end = start + count; + rvp = &cfg->map[map].res; + } else + return 0; + } + break; + + default: + return 0; + } + + rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + type, rid, start, end, count, flags); + if (rvp) + *rvp = rv; + + return rv; +} + +static int +pci_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + int rv; + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + int map = 0; + + switch (type) { + case SYS_RES_IRQ: + if (rid != 0) + return EINVAL; + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + /* + * Only check the map registers if this is a direct + * descendant. + */ + if (device_get_parent(child) == dev) + map = pci_mapno(cfg, rid); + else + map = -1; + break; + + default: + return (ENOENT); + } + + rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); + + if (rv == 0) { + switch (type) { + case SYS_RES_IRQ: + cfg->irqres = 0; + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + if (map != -1) + cfg->map[map].res = 0; + break; + + default: + return ENOENT; + } + } + + return rv; +} + +static u_int32_t +pci_read_config_method(device_t dev, device_t child, int reg, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + return pci_cfgread(cfg, reg, width); +} + +static void +pci_write_config_method(device_t dev, device_t child, int reg, + u_int32_t val, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + pci_cfgwrite(cfg, reg, val, width); +} + +static int +pci_modevent(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + pci_wrap_old_drivers(); + break; + + case MOD_UNLOAD: + break; + } + + return 0; +} + +static device_method_t pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pci_new_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, pci_print_child), + DEVMETHOD(bus_read_ivar, pci_read_ivar), + DEVMETHOD(bus_write_ivar, pci_write_ivar), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_alloc_resource, pci_alloc_resource), + DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + /* PCI interface */ + DEVMETHOD(pci_read_config, pci_read_config_method), + DEVMETHOD(pci_write_config, pci_write_config_method), + + { 0, 0 } +}; + +static driver_t pci_driver = { + "pci", + pci_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + +DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); + #endif /* NPCI > 0 */ diff --git a/sys/dev/pci/pci_if.m b/sys/dev/pci/pci_if.m new file mode 100644 index 0000000..b2fa675 --- /dev/null +++ b/sys/dev/pci/pci_if.m @@ -0,0 +1,44 @@ +# +# Copyright (c) 1998 Doug Rabson +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +INTERFACE pci; + +METHOD u_int32_t read_config { + device_t dev; + device_t child; + int reg; + int width; +}; + +METHOD void write_config { + device_t dev; + device_t child; + int reg; + u_int32_t val; + int width; +}; diff --git a/sys/dev/pci/pcireg.h b/sys/dev/pci/pcireg.h index 0adb540..9c0dba0 100644 --- a/sys/dev/pci/pcireg.h +++ b/sys/dev/pci/pcireg.h @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcireg.h,v 1.19 1997/09/20 07:41:58 dyson Exp $ + * $Id: pcireg.h,v 1.20 1998/10/07 03:40:51 gibbs Exp $ * */ @@ -173,7 +173,7 @@ #define PCIS_MEMORY_OTHER 0x80 #define PCIC_BRIDGE 0x06 -#define PCIS_BRDIGE_HOST 0x00 +#define PCIS_BRIDGE_HOST 0x00 #define PCIS_BRIDGE_ISA 0x01 #define PCIS_BRIDGE_EISA 0x02 #define PCIS_BRIDGE_MCA 0x03 diff --git a/sys/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h index 7843e3a..55f72a1 100644 --- a/sys/dev/pci/pcivar.h +++ b/sys/dev/pci/pcivar.h @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcivar.h,v 1.24 1999/01/13 04:59:19 bde Exp $ + * $Id: pcivar.h,v 1.25 1999/01/19 23:29:20 se Exp $ * */ @@ -67,13 +67,17 @@ typedef struct { u_int8_t ln2size; u_int8_t ln2range; u_int8_t reg; /* offset of map register in config space */ +/* u_int8_t dummy;*/ + struct resource *res; /* handle from resource manager */ } pcimap; /* config header information common to all header types */ typedef struct pcicfg { + struct device *dev; /* device which owns this */ pcimap *map; /* pointer to array of PCI maps */ void *hdrspec; /* pointer to header type specific data */ + struct resource *irqres; /* resource descriptor for interrupt mapping */ u_int16_t subvendor; /* card vendor ID */ u_int16_t subdevice; /* card device ID, assigned by card vendor */ @@ -182,6 +186,79 @@ void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes); vm_offset_t pci_cvt_to_dense (vm_offset_t); vm_offset_t pci_cvt_to_bwx (vm_offset_t); #endif /* __alpha__ */ + +#ifdef _SYS_BUS_H_ + +#include "pci_if.h" + +enum pci_device_ivars { + PCI_IVAR_SUBVENDOR, + PCI_IVAR_SUBDEVICE, + PCI_IVAR_VENDOR, + PCI_IVAR_DEVICE, + PCI_IVAR_DEVID, + PCI_IVAR_CLASS, + PCI_IVAR_SUBCLASS, + PCI_IVAR_PROGIF, + PCI_IVAR_REVID, + PCI_IVAR_INTPIN, + PCI_IVAR_IRQ, + PCI_IVAR_BUS, + PCI_IVAR_SLOT, + PCI_IVAR_FUNCTION, + PCI_IVAR_SECONDARYBUS, + PCI_IVAR_SUBORDINATEBUS, +}; + +/* + * Simplified accessors for pci devices + */ +#define PCI_ACCESSOR(A, B, T) \ + \ +static __inline T pci_get_ ## A(device_t dev) \ +{ \ + uintptr_t v; \ + BUS_READ_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, &v); \ + return (T) v; \ +} \ + \ +static __inline void pci_set_ ## A(device_t dev, T t) \ +{ \ + u_long v = (u_long) t; \ + BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v); \ +} + +PCI_ACCESSOR(subvendor, SUBVENDOR, u_int16_t) +PCI_ACCESSOR(subdevice, SUBDEVICE, u_int16_t) +PCI_ACCESSOR(vendor, VENDOR, u_int16_t) +PCI_ACCESSOR(device, DEVICE, u_int16_t) +PCI_ACCESSOR(devid, DEVID, u_int32_t) +PCI_ACCESSOR(class, CLASS, u_int8_t) +PCI_ACCESSOR(subclass, SUBCLASS, u_int8_t) +PCI_ACCESSOR(progif, PROGIF, u_int8_t) +PCI_ACCESSOR(revid, REVID, u_int8_t) +PCI_ACCESSOR(intpin, INTPIN, u_int8_t) +PCI_ACCESSOR(irq, IRQ, u_int8_t) +PCI_ACCESSOR(bus, BUS, u_int8_t) +PCI_ACCESSOR(slot, SLOT, u_int8_t) +PCI_ACCESSOR(function, FUNCTION, u_int8_t) +PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t) +PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t) + +static __inline u_int32_t +pci_read_config(device_t dev, int reg, int width) +{ + return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width); +} + +static __inline void +pci_write_config(device_t dev, int reg, u_int32_t val, int width) +{ + PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width); +} + +#endif + /* for compatibility to FreeBSD-2.2 version of PCI code */ #ifdef PCI_COMPAT diff --git a/sys/dev/rp/rp.c b/sys/dev/rp/rp.c index 3ac4ee9..e9357fa 100644 --- a/sys/dev/rp/rp.c +++ b/sys/dev/rp/rp.c @@ -1180,7 +1180,6 @@ int rpattach(dev) struct isa_device *dev; { - struct isa_device *idev; dev_t rp_dev; int iobase, unit, /*rpmajor,*/ oldspl; int num_ports, num_chan, num_aiops; @@ -1280,13 +1279,6 @@ struct isa_device *dev; } } - idev = find_isadev(isa_devtab_tty, &rpdriver, - RP_MPMASTER(dev) + rp_pcicount); - if(idev == NULL) { - printf("rp%d: master device %d not configured\n", - dev->id_unit, RP_MPMASTER(dev)); - } -/* printf("COOL!! Device is found!!\n"); for(rpmajor=0;rpmajor<nchrdev;rpmajor++) if(cdevsw[rpmajor].d_open == rpopen) printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor); diff --git a/sys/dev/sio/sio.c b/sys/dev/sio/sio.c index ee031b4..1a40360 100644 --- a/sys/dev/sio/sio.c +++ b/sys/dev/sio/sio.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: sio.c,v 1.220 1999/01/19 00:21:47 peter Exp $ + * $Id: sio.c,v 1.221 1999/01/30 12:17:35 phk Exp $ * from: @(#)com.c 7.5 (Berkeley) 5/16/91 * from: i386/isa sio.c,v 1.215 */ @@ -68,6 +68,7 @@ #include <sys/syslog.h> #include <sys/sysctl.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #ifdef DEVFS #include <sys/devfsext.h> @@ -103,8 +104,10 @@ #endif +#ifndef __i386__ #define disable_intr() 0 #define enable_intr() 0 +#endif #ifdef SMP #define disable_intr() COM_DISABLE_INTR() @@ -2607,6 +2610,21 @@ static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); static void siocntxwait __P((Port_t iobase)); +#ifdef __i386__ +/* + * XXX: sciocnget() and sciocnputc() are not declared static, as they are + * referred to from i386/i386/i386-gdbstub.c. + */ +static cn_probe_t siocnprobe; +static cn_init_t siocninit; +static cn_checkc_t siocncheckc; + cn_getc_t siocngetc; + cn_putc_t siocnputc; + +CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc); + +#endif + static void siocntxwait(iobase) Port_t iobase; @@ -2731,11 +2749,9 @@ void siocnprobe(cp) struct consdev *cp; { -#if 0 speed_t boot_speed; u_char cfcr; - struct isa_device *dvp; - int s; + int s, unit; struct siocnstate sp; /* @@ -2753,10 +2769,16 @@ siocnprobe(cp) * don't need to probe. */ cp->cn_pri = CN_DEAD; - for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) - if (dvp->id_driver == &siodriver && dvp->id_enabled - && COM_CONSOLE(dvp)) { - siocniobase = dvp->id_iobase; + + for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ + int flags; + if (resource_int_value("sio", unit, "flags", &flags)) + continue; + if (COM_CONSOLE(flags)) { + int port; + if (resource_int_value("sio", unit, "port", &port)) + continue; + siocniobase = port; s = spltty(); if (boothowto & RB_SERIAL) { boot_speed = siocngetspeed(siocniobase, @@ -2784,17 +2806,19 @@ siocnprobe(cp) siocnopen(&sp, siocniobase, comdefaultrate); splx(s); - if (!COM_LLCONSOLE(dvp)) { - cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); - cp->cn_pri = COM_FORCECONSOLE(dvp) + if (!COM_LLCONSOLE(flags)) { + cp->cn_dev = makedev(CDEV_MAJOR, unit); + cp->cn_pri = COM_FORCECONSOLE(flags) || boothowto & RB_SERIAL ? CN_REMOTE : CN_NORMAL; } break; } -#endif + } } +#ifdef __alpha__ + struct consdev siocons = { NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL, makedev(CDEV_MAJOR, 0), CN_NORMAL, @@ -2877,6 +2901,8 @@ siogdbattach(port, speed) return 0; } +#endif + void siocninit(cp) struct consdev *cp; @@ -3158,7 +3184,6 @@ static void siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NSIOTOT) return; @@ -3180,9 +3205,7 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &siodriver; - dvp = find_isadev(isa_devtab_tty, &siodriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = sioprobe(dev)) != 0) diff --git a/sys/dev/syscons/syscons.c b/sys/dev/syscons/syscons.c index a874dbb..a2db9b4 100644 --- a/sys/dev/syscons/syscons.c +++ b/sys/dev/syscons/syscons.c @@ -25,7 +25,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: syscons.c,v 1.298 1999/02/05 11:52:11 yokota Exp $ + * $Id: syscons.c,v 1.299 1999/03/10 10:36:53 yokota Exp $ */ #include "sc.h" @@ -1869,6 +1869,7 @@ extern struct isa_driver scdriver; static void sccnprobe(struct consdev *cp) { +#if 0 struct isa_device *dvp; /* @@ -1885,6 +1886,13 @@ sccnprobe(struct consdev *cp) return; } sckbdprobe(dvp->id_unit, dvp->id_flags, TRUE); +#else + if (!scvidprobe(0, 0, TRUE)) { + cp->cn_pri = CN_DEAD; + return; + } + sckbdprobe(0, 0, TRUE); +#endif /* initialize required fields */ cp->cn_dev = makedev(CDEV_MAJOR, SC_CONSOLE); diff --git a/sys/dev/usb/ohci.c b/sys/dev/usb/ohci.c index 334a998..b97fee0 100644 --- a/sys/dev/usb/ohci.c +++ b/sys/dev/usb/ohci.c @@ -59,6 +59,10 @@ #include <sys/queue.h> #include <sys/select.h> +#ifdef __FreeBSD__ +#include <machine/bus_pio.h> +#include <machine/bus_memio.h> +#endif #include <machine/bus.h> #include <machine/endian.h> @@ -162,15 +166,9 @@ void ohci_dump_td __P((ohci_soft_td_t *)); void ohci_dump_ed __P((ohci_soft_ed_t *)); #endif -#if defined(__NetBSD__) #define OWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) #define OREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) #define OREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) -#elif defined(__FreeBSD__) -#define OWRITE4(sc, r, x) *(u_int32_t *) ((sc)->sc_iobase + (r)) = x -#define OREAD4(sc, r) (*(u_int32_t *) ((sc)->sc_iobase + (r))) -#define OREAD2(sc, r) (*(u_int16_t *) ((sc)->sc_iobase + (r))) -#endif /* Reverse the bits in a value 0 .. 31 */ static u_int8_t revbits[OHCI_NO_INTRS] = diff --git a/sys/dev/usb/ohci_pci.c b/sys/dev/usb/ohci_pci.c index 3c20ff7..1aea5f1 100644 --- a/sys/dev/usb/ohci_pci.c +++ b/sys/dev/usb/ohci_pci.c @@ -44,6 +44,8 @@ * USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl */ +#include "opt_bus.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -52,23 +54,13 @@ #include <sys/device.h> #include <sys/proc.h> #include <sys/queue.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <pci/pcivar.h> #include <pci/pcireg.h> -#define PCI_CLASS_SERIALBUS 0x0c000000 -#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000 -#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000 -#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000 -#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000 - -#define PCI_INTERFACE(d) (((d) >> 8) & 0xff) -#define PCI_SUBCLASS(d) ((d) & PCI_SUBCLASS_MASK) -#define PCI_CLASS(d) ((d) & PCI_CLASS_MASK) - - #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> @@ -77,7 +69,6 @@ #include <dev/usb/ohcireg.h> #include <dev/usb/ohcivar.h> - #define PCI_OHCI_VENDORID_ALI 0x10b9 #define PCI_OHCI_VENDORID_CMDTECH 0x1095 #define PCI_OHCI_VENDORID_COMPAQ 0x0e11 @@ -98,27 +89,12 @@ static const char *ohci_device_usb0673 = "CMD Tech 673 (USB0673) USB Host Contr static const char *ohci_device_generic = "OHCI (generic) USB Host Controller"; - -static const char *ohci_pci_probe __P((pcici_t, pcidi_t)); -static void ohci_pci_attach __P((pcici_t, int)); - -static u_long ohci_count = 0; - -static struct pci_device ohci_pci_device = { - "ohci", - ohci_pci_probe, - ohci_pci_attach, - &ohci_count, - NULL -}; - -DATA_SET(pcidevice_set, ohci_pci_device); - +#define PCI_OHCI_BASE_REG 0x10 static const char * -ohci_pci_probe(pcici_t config_id, pcidi_t device_id) +ohci_pci_match(device_t dev) { - u_int32_t class; + u_int32_t device_id = pci_get_devid(dev); switch(device_id) { case PCI_OHCI_DEVICEID_ALADDIN_V: @@ -132,54 +108,72 @@ ohci_pci_probe(pcici_t config_id, pcidi_t device_id) case PCI_OHCI_DEVICEID_NEC: return (ohci_device_nec); default: - class = pci_conf_read(config_id, PCI_CLASS_REG); - if ( (PCI_CLASS(class) == PCI_CLASS_SERIALBUS) - && (PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB) - && (PCI_INTERFACE(class) == PCI_INTERFACE_OHCI)) { - return(ohci_device_generic); + if ( pci_get_class(dev) == PCIC_SERIALBUS + && pci_get_subclass(dev) == PCIS_SERIALBUS_USB + && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { + return (ohci_device_generic); } } return NULL; /* dunno */ } -static void -ohci_pci_attach(pcici_t config_id, int unit) +static int +ohci_pci_probe(device_t dev) { - vm_offset_t pbase; + const char *desc = ohci_pci_match(dev); + if (desc) { + device_set_desc(dev, desc); + return 0; + } else { + return ENXIO; + } +} + +static int +ohci_pci_attach(device_t dev) +{ + int unit = device_get_unit(dev); + ohci_softc_t *sc = device_get_softc(dev); device_t usbus; - ohci_softc_t *sc; usbd_status err; - int id; + int rid; + struct resource *res; + void *ih; + int error; + + rid = PCI_CBMEM; + res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!res) { + device_printf(dev, "could not map memory\n"); + return ENXIO; + } - sc = malloc(sizeof(ohci_softc_t), M_DEVBUF, M_NOWAIT); - /* Do not free it below, intr might use the sc */ - if ( sc == NULL ) { - printf("ohci%d: could not allocate memory", unit); - return; - } - memset(sc, 0, sizeof(ohci_softc_t)); + sc->iot = rman_get_bustag(res); + sc->ioh = rman_get_bushandle(res); - if(!pci_map_mem(config_id, PCI_CBMEM, - (vm_offset_t *)&sc->sc_iobase, &pbase)) { - printf("ohci%d: could not map memory\n", unit); - return; - } + rid = 0; + res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (res == NULL) { + device_printf(dev, "could not allocate irq\n"); + return ENOMEM; + } - if ( !pci_map_int(config_id, (pci_inthand_t *)ohci_intr, - (void *) sc, &bio_imask)) { - printf("ohci%d: could not map irq\n", unit); - return; + error = bus_setup_intr(dev, res, (driver_intr_t *) ohci_intr, sc, &ih); + if (error) { + device_printf(dev, "could not setup irq\n"); + return error; } - usbus = device_add_child(root_bus, "usb", -1, sc); + usbus = device_add_child(dev, "usb", -1, sc); if (!usbus) { - printf("ohci%d: could not add USB device to root bus\n", unit); - return; + printf("ohci%d: could not add USB device\n", unit); + return ENOMEM; } - id = pci_conf_read(config_id, PCI_ID_REG); - switch(id) { + switch (pci_get_devid(dev)) { case PCI_OHCI_DEVICEID_ALADDIN_V: device_set_desc(usbus, ohci_device_aladdin_v); sprintf(sc->sc_vendor, "AcerLabs"); @@ -202,7 +196,7 @@ ohci_pci_attach(pcici_t config_id, int unit) break; default: if (bootverbose) - printf("(New OHCI DeviceId=0x%08x)\n", id); + printf("(New OHCI DeviceId=0x%08x)\n", pci_get_devid(dev)); device_set_desc(usbus, ohci_device_generic); sprintf(sc->sc_vendor, "(unknown)"); } @@ -211,8 +205,36 @@ ohci_pci_attach(pcici_t config_id, int unit) err = ohci_init(sc); if (err != USBD_NORMAL_COMPLETION) { printf("ohci%d: init failed, error=%d\n", unit, err); - device_delete_child(root_bus, usbus); + device_delete_child(dev, usbus); } - return; + return device_probe_and_attach(sc->sc_bus.bdev); } + +static device_method_t ohci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ohci_pci_probe), + DEVMETHOD(device_attach, ohci_pci_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t ohci_driver = { + "ohci", + ohci_methods, + DRIVER_TYPE_BIO, + sizeof(ohci_softc_t), +}; + +static devclass_t ohci_devclass; + +DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0); diff --git a/sys/dev/usb/ohcivar.h b/sys/dev/usb/ohcivar.h index 9063073..b485f50 100644 --- a/sys/dev/usb/ohcivar.h +++ b/sys/dev/usb/ohcivar.h @@ -72,7 +72,8 @@ typedef struct ohci_softc { /* XXX should keep track of all DMA memory */ #elif defined(__FreeBSD__) - int sc_iobase; + bus_space_tag_t iot; + bus_space_handle_t ioh; #endif /* __FreeBSD__ */ usb_dma_t sc_hccadma; diff --git a/sys/dev/usb/ucom.c b/sys/dev/usb/ucom.c index 07cc3f9..00bb152 100644 --- a/sys/dev/usb/ucom.c +++ b/sys/dev/usb/ucom.c @@ -126,13 +126,8 @@ USB_ATTACH(ucom) static int ucom_detach(device_t self) { - const char *devinfo = device_get_desc(self); - DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); return 0; } #endif diff --git a/sys/dev/usb/ugen.c b/sys/dev/usb/ugen.c index cbd9e1e..cc14a7d 100644 --- a/sys/dev/usb/ugen.c +++ b/sys/dev/usb/ugen.c @@ -992,13 +992,8 @@ ugenpoll(dev, events, p) static int ugen_detach(device_t self) { - const char *devinfo = device_get_desc(self); - DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); return 0; } diff --git a/sys/dev/usb/uhci.c b/sys/dev/usb/uhci.c index 30c69fd..62cb106 100644 --- a/sys/dev/usb/uhci.c +++ b/sys/dev/usb/uhci.c @@ -63,6 +63,9 @@ cgiform.tpl #include <sys/queue.h> #include <sys/select.h> +#if defined(__FreeBSD__) +#include <machine/bus_pio.h> +#endif #include <machine/bus.h> #include <dev/usb/usb.h> @@ -225,11 +228,11 @@ void uhci_dump_td __P((uhci_soft_td_t *)); #define UREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) #define UREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) #elif defined(__FreeBSD__) -#define UWRITE2(sc,r,x) outw((sc)->sc_iobase + (r), (x)) -#define UWRITE4(sc,r,x) outl((sc)->sc_iobase + (r), (x)) -#define UREAD1(sc,r) inb((sc)->sc_iobase + (r)) -#define UREAD2(sc,r) inw((sc)->sc_iobase + (r)) -#define UREAD4(sc,r) inl((sc)->sc_iobase + (r)) +#define UWRITE2(sc, r, x) bus_space_write_2((sc)->iot, (sc)->ioh, (r), (x)) +#define UWRITE4(sc, r, x) bus_space_write_4((sc)->iot, (sc)->ioh, (r), (x)) +#define UREAD1(sc, r) bus_space_read_1((sc)->iot, (sc)->ioh, (r)) +#define UREAD2(sc, r) bus_space_read_2((sc)->iot, (sc)->ioh, (r)) +#define UREAD4(sc, r) bus_space_read_4((sc)->iot, (sc)->ioh, (r)) #endif #define UHCICMD(sc, cmd) UWRITE2(sc, UHCI_CMD, cmd) diff --git a/sys/dev/usb/uhci_pci.c b/sys/dev/usb/uhci_pci.c index 6ed3cee..4bddf8b 100644 --- a/sys/dev/usb/uhci_pci.c +++ b/sys/dev/usb/uhci_pci.c @@ -1,4 +1,4 @@ -/* FreeBSD $Id: uhci_pci.c,v 1.4 1999/04/06 23:09:58 n_hibma Exp $ */ +/* FreeBSD $Id: uhci_pci.c,v 1.5 1999/04/11 14:24:20 n_hibma Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,6 +37,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_bus.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -45,23 +47,13 @@ #include <sys/device.h> #include <sys/proc.h> #include <sys/queue.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <pci/pcivar.h> #include <pci/pcireg.h> -#define PCI_CLASS_SERIALBUS 0x0c000000 -#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000 -#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000 -#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000 -#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000 - -#define PCI_INTERFACE(d) (((d)>>8)&0xff) -#define PCI_SUBCLASS(d) ((d)&PCI_SUBCLASS_MASK) -#define PCI_CLASS(d) ((d)&PCI_CLASS_MASK) - - #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> @@ -70,7 +62,6 @@ #include <dev/usb/uhcireg.h> #include <dev/usb/uhcivar.h> - #define PCI_UHCI_VENDORID_INTEL 0x8086 #define PCI_UHCI_VENDORID_VIA 0x1106 @@ -85,26 +76,10 @@ static const char *uhci_device_generic = "UHCI (generic) USB Controller"; #define PCI_UHCI_BASE_REG 0x20 -static const char *uhci_pci_probe __P((pcici_t, pcidi_t)); -static void uhci_pci_attach __P((pcici_t, int)); - -static u_long uhci_count = 0; - -static struct pci_device uhci_pci_device = { - "uhci", - uhci_pci_probe, - uhci_pci_attach, - &uhci_count, - NULL -}; - -DATA_SET(pcidevice_set, uhci_pci_device); - - static const char * -uhci_pci_probe(pcici_t config_id, pcidi_t device_id) +uhci_pci_match(device_t dev) { - u_int32_t class; + u_int32_t device_id = pci_get_devid(dev); if (device_id == PCI_UHCI_DEVICEID_PIIX3) { return (uhci_device_piix3); @@ -113,10 +88,9 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id) } else if (device_id == PCI_UHCI_DEVICEID_VT83C572) { return (uhci_device_vt83c572); } else { - class = pci_conf_read(config_id, PCI_CLASS_REG); - if ( PCI_CLASS(class) == PCI_CLASS_SERIALBUS - && PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB - && PCI_INTERFACE(class) == PCI_INTERFACE_UHCI) { + if ( pci_get_class(dev) == PCIC_SERIALBUS + && pci_get_subclass(dev) == PCIS_SERIALBUS_USB + && pci_get_progif(dev) == PCI_INTERFACE_UHCI) { return (uhci_device_generic); } } @@ -124,42 +98,64 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id) return NULL; /* dunno... */ } -static void -uhci_pci_attach(pcici_t config_id, int unit) +static int +uhci_pci_probe(device_t dev) +{ + const char *desc = uhci_pci_match(dev); + if (desc) { + device_set_desc(dev, desc); + return 0; + } else { + return ENXIO; + } +} + +static int +uhci_pci_attach(device_t dev) { - int id, legsup; + int unit = device_get_unit(dev); + int legsup; char *typestr; usbd_status err; - uhci_softc_t *sc = NULL; device_t usbus; - - sc = malloc(sizeof(uhci_softc_t), M_DEVBUF, M_NOWAIT); - /* Do not free it below, intr might use the sc */ - if ( sc == NULL ) { - printf("uhci%d: could not allocate memory", unit); - return; + uhci_softc_t *sc = device_get_softc(dev); + int rid; + struct resource *res; + void *ih; + int error; + + rid = PCI_UHCI_BASE_REG; + res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!res) { + device_printf(dev, "could not map ports\n"); + return ENXIO; + } + + sc->iot = rman_get_bustag(res); + sc->ioh = rman_get_bushandle(res); + + rid = 0; + res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (res == NULL) { + device_printf(dev, "could not allocate irq\n"); + return ENOMEM; } - memset(sc, 0, sizeof(uhci_softc_t)); - - if ( !pci_map_port(config_id, PCI_UHCI_BASE_REG, &sc->sc_iobase) ) { - printf("uhci%d: could not map port\n", unit); - return; - } - - if ( !pci_map_int(config_id, (pci_inthand_t *)uhci_intr, - (void *) sc, &bio_imask)) { - printf("uhci%d: could not map irq\n", unit); - return; + + error = bus_setup_intr(dev, res, (driver_intr_t *) uhci_intr, sc, &ih); + if (error) { + device_printf(dev, "could not setup irq\n"); + return error; } - usbus = device_add_child(root_bus, "usb", -1, sc); + usbus = device_add_child(dev, "usb", -1, sc); if (!usbus) { - printf("usb%d: could not add USB device to root bus\n", unit); - return; + printf("usb%d: could not add USB device\n", unit); + return ENOMEM; } - id = pci_conf_read(config_id, PCI_ID_REG); - switch (id) { + switch (pci_get_devid(dev)) { case PCI_UHCI_DEVICEID_PIIX3: device_set_desc(usbus, uhci_device_piix3); sprintf(sc->sc_vendor, "Intel"); @@ -173,13 +169,13 @@ uhci_pci_attach(pcici_t config_id, int unit) sprintf(sc->sc_vendor, "VIA"); break; default: - printf("(New UHCI DeviceId=0x%08x)\n", id); + printf("(New UHCI DeviceId=0x%08x)\n", pci_get_devid(dev)); device_set_desc(usbus, uhci_device_generic); - sprintf(sc->sc_vendor, "(0x%08x)", id); + sprintf(sc->sc_vendor, "(0x%08x)", pci_get_devid(dev)); } if (bootverbose) { - switch(pci_conf_read(config_id, PCI_USBREV) & PCI_USBREV_MASK) { + switch(pci_read_config(dev, PCI_USBREV, 4) & PCI_USBREV_MASK) { case PCI_USBREV_PRE_1_0: typestr = "pre 1.0"; break; @@ -191,25 +187,53 @@ uhci_pci_attach(pcici_t config_id, int unit) break; } printf("uhci%d: USB version %s, chip rev. %d\n", unit, typestr, - (int) pci_conf_read(config_id, PCIR_REVID) & 0xff); + pci_get_revid(dev)); } - legsup = pci_conf_read(config_id, PCI_LEGSUP); + legsup = pci_read_config(dev, PCI_LEGSUP, 4); if ( !(legsup & PCI_LEGSUP_USBPIRQDEN) ) { #if ! (defined(USBVERBOSE) || defined(USB_DEBUG)) if (bootverbose) #endif printf("uhci%d: PIRQD enable not set\n", unit); legsup |= PCI_LEGSUP_USBPIRQDEN; - pci_conf_write(config_id, PCI_LEGSUP, legsup); + pci_write_config(dev, PCI_LEGSUP, legsup, 4); } sc->sc_bus.bdev = usbus; err = uhci_init(sc); if (err != USBD_NORMAL_COMPLETION) { printf("uhci%d: init failed, error=%d\n", unit, err); - device_delete_child(root_bus, usbus); + device_delete_child(dev, usbus); } - return; + return device_probe_and_attach(sc->sc_bus.bdev); } + +static device_method_t uhci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uhci_pci_probe), + DEVMETHOD(device_attach, uhci_pci_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t uhci_driver = { + "uhci", + uhci_methods, + DRIVER_TYPE_BIO, + sizeof(uhci_softc_t), +}; + +static devclass_t uhci_devclass; + +DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0); diff --git a/sys/dev/usb/uhcivar.h b/sys/dev/usb/uhcivar.h index 2171374..89fed85 100644 --- a/sys/dev/usb/uhcivar.h +++ b/sys/dev/usb/uhcivar.h @@ -125,7 +125,8 @@ typedef struct uhci_softc { bus_dma_tag_t sc_dmatag; /* DMA tag */ /* XXX should keep track of all DMA memory */ #elif defined(__FreeBSD__) - int sc_iobase; + bus_space_tag_t iot; + bus_space_handle_t ioh; #endif /* defined(__FreeBSD__) */ uhci_physaddr_t *sc_pframes; diff --git a/sys/dev/usb/uhid.c b/sys/dev/usb/uhid.c index a55944b..e434556 100644 --- a/sys/dev/usb/uhid.c +++ b/sys/dev/usb/uhid.c @@ -200,13 +200,8 @@ USB_ATTACH(uhid) static int uhid_detach(device_t self) { - const char *devinfo = device_get_desc(self); - DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); return 0; } #endif diff --git a/sys/dev/usb/uhub.c b/sys/dev/usb/uhub.c index 2f4029c..bf53c01 100644 --- a/sys/dev/usb/uhub.c +++ b/sys/dev/usb/uhub.c @@ -81,10 +81,15 @@ usbd_status uhub_init_port __P((struct usbd_port *)); void uhub_disconnect_port __P((struct usbd_port *up)); usbd_status uhub_explore __P((usbd_device_handle hub)); void uhub_intr __P((usbd_request_handle, usbd_private_handle, usbd_status)); +#ifdef __FreeBSD__ +#include "usb_if.h" +static void uhub_disconnected __P((device_t)); +#endif /* void uhub_disco __P((void *)); */ -USB_DECLARE_DRIVER(uhub); +USB_DECLARE_DRIVER_INIT(uhub, + DEVMETHOD(usb_disconnected, uhub_disconnected)); #if defined(__FreeBSD__) devclass_t uhubroot_devclass; @@ -251,8 +256,8 @@ USB_ATTACH(uhub) } #if defined(__FreeBSD__) -static int -uhub_detach(device_t self) +static void +uhub_disconnected(device_t self) { struct uhub_softc *sc = device_get_softc(self); struct usbd_port *up; @@ -264,12 +269,20 @@ uhub_detach(device_t self) nports = dev->hub->hubdesc.bNbrPorts; for (p = 0; p < nports; p++) { up = &sc->sc_hub->hub->ports[p]; - if (up->device) + if (up->device) { uhub_disconnect_port(up); + } } - free(sc->sc_hub->hub, M_USB); + return; +} +static int +uhub_detach(device_t self) +{ + struct uhub_softc *sc = device_get_softc(self); + DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); + free(sc->sc_hub->hub, M_USB); return 0; } #endif @@ -502,6 +515,7 @@ uhub_disconnect_port(up) } } #if defined(__FreeBSD__) + USB_DISCONNECTED(sc->sc_dev); device_delete_child(scp->sc_dev, sc->sc_dev); #endif diff --git a/sys/dev/usb/ulpt.c b/sys/dev/usb/ulpt.c index 0984460..9aaf024 100644 --- a/sys/dev/usb/ulpt.c +++ b/sys/dev/usb/ulpt.c @@ -437,13 +437,8 @@ ulptioctl(dev, cmd, data, flag, p) static int ulpt_detach(device_t self) { - const char *devinfo = device_get_desc(self); - DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); return 0; } diff --git a/sys/dev/usb/umodem.c b/sys/dev/usb/umodem.c index 7a1b600..c624b86 100644 --- a/sys/dev/usb/umodem.c +++ b/sys/dev/usb/umodem.c @@ -125,13 +125,8 @@ USB_ATTACH(umodem) static int umodem_detach(device_t self) { - const char *devinfo = device_get_desc(self); - DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); return 0; } diff --git a/sys/dev/usb/ums.c b/sys/dev/usb/ums.c index 9464566..4d3578b 100644 --- a/sys/dev/usb/ums.c +++ b/sys/dev/usb/ums.c @@ -363,7 +363,6 @@ static int ums_detach(device_t self) { struct ums_softc *sc = device_get_softc(self); - const char *devinfo = device_get_desc(self); if (sc->sc_enabled) { usbd_abort_pipe(sc->sc_intrpipe); @@ -372,10 +371,7 @@ ums_detach(device_t self) sc->sc_disconnected = 1; DPRINTF(("%s: disconnected\n", USBDEVNAME(self))); - if (devinfo) { - device_set_desc(self, NULL); - free((void *)devinfo, M_USB); - } + device_set_desc(self, NULL); free(sc->sc_loc_btn, M_USB); free(sc->sc_ibuf, M_USB); diff --git a/sys/dev/usb/usb.c b/sys/dev/usb/usb.c index 935f951..8d9689a 100644 --- a/sys/dev/usb/usb.c +++ b/sys/dev/usb/usb.c @@ -408,5 +408,6 @@ usb_detach(device_t self) return (1); } -DRIVER_MODULE(usb, root, usb_driver, usb_devclass, 0, 0); +DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0); +DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0); #endif diff --git a/sys/dev/usb/usb_if.m b/sys/dev/usb/usb_if.m index 2c5e521..62ea118 100644 --- a/sys/dev/usb/usb_if.m +++ b/sys/dev/usb/usb_if.m @@ -25,7 +25,7 @@ # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # -# $Id: usb_if.m,v 1.3 1999/01/07 23:31:37 n_hibma Exp $ +# $Id: usb_if.m,v 1.4 1999/03/22 19:58:59 n_hibma Exp $ # # USB interface description @@ -38,3 +38,10 @@ INTERFACE usb; METHOD int reconfigure { device_t dev; }; + +# The device is being disconnected and should clean up before +# being destroyed. +# +METHOD void disconnected { + device_t dev; +}; diff --git a/sys/dev/usb/usb_port.h b/sys/dev/usb/usb_port.h index f1dd74a..ea144b9 100644 --- a/sys/dev/usb/usb_port.h +++ b/sys/dev/usb/usb_port.h @@ -126,7 +126,7 @@ __CONCAT(dname,_attach)(parent, self, aux) \ * because of includes in the wrong order. */ #define bdevice device_t -#define USBDEVNAME(bdev) usbd_devname(&bdev) +#define USBDEVNAME(bdev) device_get_nameunit(bdev) /* XXX Change this when FreeBSD has memset */ diff --git a/sys/dev/usb/usbdi.c b/sys/dev/usb/usbdi.c index d045a4d..8b88cd3 100644 --- a/sys/dev/usb/usbdi.c +++ b/sys/dev/usb/usbdi.c @@ -1302,30 +1302,7 @@ usbd_driver_load(module_t mod, int what, void *arg) void usbd_device_set_desc(device_t device, char *devinfo) { - size_t l; - char *desc; - - if ( devinfo ) { - l = strlen(devinfo); - desc = malloc(l+1, M_USB, M_NOWAIT); - if (desc) - memcpy(desc, devinfo, l+1); - } else - desc = NULL; - - device_set_desc(device, desc); -} - -char * -usbd_devname(bdevice *bdev) -{ - static char buf[20]; - /* XXX a static buffer is not exactly a good idea, but the only - * thing that goes wrong is the string that is being printed - */ - - sprintf(buf, "%s%d", device_get_name(*bdev), device_get_unit(*bdev)); - return (buf); + device_set_desc_copy(device, devinfo); } #endif diff --git a/sys/dev/usb/usbdi.h b/sys/dev/usb/usbdi.h index 8cdcfdb..7a41f8b 100644 --- a/sys/dev/usb/usbdi.h +++ b/sys/dev/usb/usbdi.h @@ -336,7 +336,6 @@ usb_endpoint_descriptor_t *usbd_get_endpoint_descriptor #if defined(__FreeBSD__) int usbd_driver_load __P((module_t mod, int what, void *arg)); void usbd_device_set_desc __P((device_t device, char *devinfo)); -char *usbd_devname(bdevice *bdev); bus_print_child_t usbd_print_child; #endif diff --git a/sys/i386/apm/apm.c b/sys/i386/apm/apm.c index 42515c8..359e99e 100644 --- a/sys/i386/apm/apm.c +++ b/sys/i386/apm/apm.c @@ -15,7 +15,7 @@ * * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm.c,v 1.76 1998/12/04 21:28:39 archie Exp $ + * $Id: apm.c,v 1.77 1998/12/10 23:36:14 msmith Exp $ */ #include "opt_devfs.h" @@ -30,7 +30,7 @@ #include <sys/systm.h> #include <sys/time.h> #include <sys/reboot.h> -#include <i386/isa/isa_device.h> +#include <sys/bus.h> #include <machine/apm_bios.h> #include <machine/segments.h> #include <machine/clock.h> @@ -432,11 +432,15 @@ void apm_suspend(int state) { struct apm_softc *sc = &apm_softc; + int error; if (!sc) return; if (sc->initialized) { + error = DEVICE_SUSPEND(root_bus); + if (error) + return; /* XXX no error reporting */ apm_execute_hook(hook[APM_HOOK_SUSPEND]); if (apm_suspend_system(state) == 0) apm_processevent(); @@ -454,8 +458,10 @@ apm_resume(void) if (!sc) return; - if (sc->initialized) + if (sc->initialized) { + DEVICE_RESUME(root_bus); apm_execute_hook(hook[APM_HOOK_RESUME]); + } } @@ -623,9 +629,6 @@ apm_not_halt_cpu(void) } /* device driver definitions */ -static int apmprobe (struct isa_device *); -static int apmattach(struct isa_device *); -struct isa_driver apmdriver = { apmprobe, apmattach, "apm" }; /* * probe APM (dummy): @@ -639,18 +642,24 @@ struct isa_driver apmdriver = { apmprobe, apmattach, "apm" }; */ static int -apmprobe(struct isa_device *dvp) +apm_probe(device_t dev) { #ifdef VM86 struct vm86frame vmf; int i; #endif + int flags; + + device_set_desc(dev, "APM BIOS"); - if ( dvp->id_unit > 0 ) { + if ( device_get_unit(dev) > 0 ) { printf("apm: Only one APM driver supported.\n"); - return 0; + return ENXIO; } + if (resource_int_value("apm", 0, "flags", &flags) != 0) + flags = 0; + #ifdef VM86 bzero(&vmf, sizeof(struct vm86frame)); /* safety */ vmf.vmf_ax = (APM_BIOS << 8) | APM_INSTCHECK; @@ -712,9 +721,9 @@ apmprobe(struct isa_device *dvp) printf("apm: 32-bit connection error.\n"); return 0; } - if (dvp->id_flags & 0x20) + if (flags & 0x20) statclock_disable = 1; - return -1; + return 0; } @@ -779,10 +788,14 @@ apm_processevent(void) */ static int -apmattach(struct isa_device *dvp) +apm_attach(device_t dev) { #define APM_KERNBASE KERNBASE struct apm_softc *sc = &apm_softc; + int flags; + + if (resource_int_value("apm", 0, "flags", &flags) != 0) + flags = 0; sc->initialized = 0; @@ -833,11 +846,11 @@ apmattach(struct isa_device *dvp) apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL); apm_addr.offset = sc->cs_entry; - if ((dvp->id_flags & 0x10)) { - if ((dvp->id_flags & 0xf) >= 0x2) { + if ((flags & 0x10)) { + if ((flags & 0xf) >= 0x2) { apm_driver_version(0x102); } - if (!apm_version && (dvp->id_flags & 0xf) >= 0x1) { + if (!apm_version && (flags & 0xf) >= 0x1) { apm_driver_version(0x101); } } else { @@ -1009,19 +1022,22 @@ apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) return error; } +static device_method_t apm_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, apm_probe), + DEVMETHOD(device_attach, apm_attach), -static apm_devsw_installed = 0; + { 0, 0 } +}; -static void -apm_drvinit(void *unused) -{ - dev_t dev; +static driver_t apm_driver = { + "apm", + apm_methods, + DRIVER_TYPE_MISC, + 1, /* no softc (XXX) */ +}; - if( ! apm_devsw_installed ) { - dev = makedev(CDEV_MAJOR,0); - cdevsw_add(&dev,&apm_cdevsw,NULL); - apm_devsw_installed = 1; - } -} +static devclass_t apm_devclass; -SYSINIT(apmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,apm_drvinit,NULL) +CDEV_DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, + CDEV_MAJOR, apm_cdevsw, 0, 0); diff --git a/sys/i386/bios/apm.c b/sys/i386/bios/apm.c index 42515c8..359e99e 100644 --- a/sys/i386/bios/apm.c +++ b/sys/i386/bios/apm.c @@ -15,7 +15,7 @@ * * Sep, 1994 Implemented on FreeBSD 1.1.5.1R (Toshiba AVS001WD) * - * $Id: apm.c,v 1.76 1998/12/04 21:28:39 archie Exp $ + * $Id: apm.c,v 1.77 1998/12/10 23:36:14 msmith Exp $ */ #include "opt_devfs.h" @@ -30,7 +30,7 @@ #include <sys/systm.h> #include <sys/time.h> #include <sys/reboot.h> -#include <i386/isa/isa_device.h> +#include <sys/bus.h> #include <machine/apm_bios.h> #include <machine/segments.h> #include <machine/clock.h> @@ -432,11 +432,15 @@ void apm_suspend(int state) { struct apm_softc *sc = &apm_softc; + int error; if (!sc) return; if (sc->initialized) { + error = DEVICE_SUSPEND(root_bus); + if (error) + return; /* XXX no error reporting */ apm_execute_hook(hook[APM_HOOK_SUSPEND]); if (apm_suspend_system(state) == 0) apm_processevent(); @@ -454,8 +458,10 @@ apm_resume(void) if (!sc) return; - if (sc->initialized) + if (sc->initialized) { + DEVICE_RESUME(root_bus); apm_execute_hook(hook[APM_HOOK_RESUME]); + } } @@ -623,9 +629,6 @@ apm_not_halt_cpu(void) } /* device driver definitions */ -static int apmprobe (struct isa_device *); -static int apmattach(struct isa_device *); -struct isa_driver apmdriver = { apmprobe, apmattach, "apm" }; /* * probe APM (dummy): @@ -639,18 +642,24 @@ struct isa_driver apmdriver = { apmprobe, apmattach, "apm" }; */ static int -apmprobe(struct isa_device *dvp) +apm_probe(device_t dev) { #ifdef VM86 struct vm86frame vmf; int i; #endif + int flags; + + device_set_desc(dev, "APM BIOS"); - if ( dvp->id_unit > 0 ) { + if ( device_get_unit(dev) > 0 ) { printf("apm: Only one APM driver supported.\n"); - return 0; + return ENXIO; } + if (resource_int_value("apm", 0, "flags", &flags) != 0) + flags = 0; + #ifdef VM86 bzero(&vmf, sizeof(struct vm86frame)); /* safety */ vmf.vmf_ax = (APM_BIOS << 8) | APM_INSTCHECK; @@ -712,9 +721,9 @@ apmprobe(struct isa_device *dvp) printf("apm: 32-bit connection error.\n"); return 0; } - if (dvp->id_flags & 0x20) + if (flags & 0x20) statclock_disable = 1; - return -1; + return 0; } @@ -779,10 +788,14 @@ apm_processevent(void) */ static int -apmattach(struct isa_device *dvp) +apm_attach(device_t dev) { #define APM_KERNBASE KERNBASE struct apm_softc *sc = &apm_softc; + int flags; + + if (resource_int_value("apm", 0, "flags", &flags) != 0) + flags = 0; sc->initialized = 0; @@ -833,11 +846,11 @@ apmattach(struct isa_device *dvp) apm_addr.segment = GSEL(GAPMCODE32_SEL, SEL_KPL); apm_addr.offset = sc->cs_entry; - if ((dvp->id_flags & 0x10)) { - if ((dvp->id_flags & 0xf) >= 0x2) { + if ((flags & 0x10)) { + if ((flags & 0xf) >= 0x2) { apm_driver_version(0x102); } - if (!apm_version && (dvp->id_flags & 0xf) >= 0x1) { + if (!apm_version && (flags & 0xf) >= 0x1) { apm_driver_version(0x101); } } else { @@ -1009,19 +1022,22 @@ apmioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) return error; } +static device_method_t apm_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, apm_probe), + DEVMETHOD(device_attach, apm_attach), -static apm_devsw_installed = 0; + { 0, 0 } +}; -static void -apm_drvinit(void *unused) -{ - dev_t dev; +static driver_t apm_driver = { + "apm", + apm_methods, + DRIVER_TYPE_MISC, + 1, /* no softc (XXX) */ +}; - if( ! apm_devsw_installed ) { - dev = makedev(CDEV_MAJOR,0); - cdevsw_add(&dev,&apm_cdevsw,NULL); - apm_devsw_installed = 1; - } -} +static devclass_t apm_devclass; -SYSINIT(apmdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,apm_drvinit,NULL) +CDEV_DRIVER_MODULE(apm, nexus, apm_driver, apm_devclass, + CDEV_MAJOR, apm_cdevsw, 0, 0); diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC index 60cc225..03e74ce 100644 --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -11,7 +11,7 @@ # device lines is present in the ./LINT configuration file. If you are # in doubt as to the purpose or necessity of a line, check first in LINT. # -# $Id: GENERIC,v 1.160 1999/04/16 16:17:05 n_hibma Exp $ +# $Id: GENERIC,v 1.161 1999/04/16 18:27:18 jkh Exp $ machine "i386" cpu "I386_CPU" @@ -53,10 +53,10 @@ config kernel root on wd0 #options NAPIC=1 # number of IO APICs #options NINTR=24 # number of INTs -controller isa0 -controller pnp0 # PnP support for ISA -controller eisa0 -controller pci0 +controller isa0 at nexus? +#controller pnp0 # PnP support for ISA +#controller eisa0 +controller pci0 at nexus? controller fdc0 at isa? port "IO_FD1" bio irq 6 drq 2 disk fd0 at fdc0 drive 0 @@ -108,9 +108,9 @@ controller matcd0 at isa? port 0x230 bio device scd0 at isa? port 0x230 bio # atkbdc0 controlls both the keyboard and the PS/2 mouse -controller atkbdc0 at isa? port IO_KBD tty -device atkbd0 at isa? tty irq 1 -device psm0 at isa? tty irq 12 +controller atkbdc0 at isa? port IO_KBD +device atkbd0 at atkbdc? tty irq 1 +device psm0 at atkbdc? tty irq 12 device vga0 at isa? port ? conflicts @@ -126,12 +126,12 @@ device sc0 at isa? tty # If you have a ThinkPAD, uncomment this along with the rest of the PCVT lines #options PCVT_SCANSET=2 # IBM keyboards are non-std -device npx0 at isa? port IO_NPX irq 13 +device npx0 at nexus? port IO_NPX irq 13 # # Laptop support (see LINT for more options) # -device apm0 at isa? disable flags 0x31 # Advanced Power Management +device apm0 at nexus? disable flags 0x31 # Advanced Power Management # PCCARD (PCMCIA) support #controller card0 @@ -178,8 +178,8 @@ device ex0 at isa? port? net irq? device fe0 at isa? port 0x300 net irq ? device le0 at isa? port 0x300 net irq 5 iomem 0xd0000 device lnc0 at isa? port 0x280 net irq 10 drq 0 -device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 -device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 +#device ze0 at isa? port 0x300 net irq 10 iomem 0xd8000 +#device zp0 at isa? port 0x300 net irq 10 iomem 0xd8000 device cs0 at isa? port 0x300 net irq ? pseudo-device loop diff --git a/sys/i386/conf/LINT b/sys/i386/conf/LINT index 833fbc9..20b284b 100644 --- a/sys/i386/conf/LINT +++ b/sys/i386/conf/LINT @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.581 1999/04/14 16:54:00 peter Exp $ +# $Id: LINT,v 1.582 1999/04/16 16:17:04 n_hibma Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -827,7 +827,7 @@ options "MSGBUF_SIZE=40960" # # Mandatory ISA devices: isa, npx # -controller isa0 +controller isa0 at nexus? # # Options for `isa': @@ -888,10 +888,10 @@ options "NTIMECOUNTER=20" controller pnp0 # The keyboard controller; it controlls the keyboard and the PS/2 mouse. -controller atkbdc0 at isa? port IO_KBD tty +controller atkbdc0 at isa? port IO_KBD # The AT keyboard -device atkbd0 at isa? tty irq 1 +device atkbd0 at atkbdc? tty irq 1 # Options for atkbd: options ATKBD_DFLT_KEYMAP # specify the built-in keymap @@ -907,7 +907,7 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev # 0x04 Old-style (XT) keyboard support, useful for older ThinkPads # PS/2 mouse -device psm0 at isa? tty irq 12 +device psm0 at atkbdc? tty irq 12 # Options for psm: options PSM_HOOKAPM #hook the APM resume event, useful @@ -977,7 +977,7 @@ options SC_DISABLE_REBOOT # disable reboot key sequence # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). -device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 +device npx0 at nexus? port IO_NPX iosiz 0x0 flags 0x0 irq 13 # # `flags' for npx0: @@ -1464,7 +1464,7 @@ controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 -device apm0 at isa? +device apm0 at nexus? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port IO_GAME @@ -1632,7 +1632,7 @@ options "EISA_SLOTS=12" # The "oltr" driver supports the following Olicom PCI token-ring adapters # OC-3136, OC-3137, OC-3139, OC-3140, OC-3141, OC-3540, OC-3250 # -controller pci0 +controller pci0 at nexus? controller ahc1 controller ncr0 controller isp0 diff --git a/sys/i386/conf/Makefile.i386 b/sys/i386/conf/Makefile.i386 index 9c9ba23..cf6a212 100644 --- a/sys/i386/conf/Makefile.i386 +++ b/sys/i386/conf/Makefile.i386 @@ -1,7 +1,7 @@ # Makefile.i386 -- with config changes. # Copyright 1990 W. Jolitz # from: @(#)Makefile.i386 7.1 5/10/91 -# $Id: Makefile.i386,v 1.144 1999/04/13 18:25:08 peter Exp $ +# $Id: Makefile.i386,v 1.145 1999/04/15 14:52:23 bde Exp $ # # Makefile for FreeBSD # @@ -17,7 +17,7 @@ # # Which version of config(8) is required. -%VERSREQ= 300012 +%VERSREQ= 400013 KERNFORMAT?= elf diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES index 833fbc9..20b284b 100644 --- a/sys/i386/conf/NOTES +++ b/sys/i386/conf/NOTES @@ -2,7 +2,7 @@ # LINT -- config file for checking all the sources, tries to pull in # as much of the source tree as it can. # -# $Id: LINT,v 1.581 1999/04/14 16:54:00 peter Exp $ +# $Id: LINT,v 1.582 1999/04/16 16:17:04 n_hibma Exp $ # # NB: You probably don't want to try running a kernel built from this # file. Instead, you should start from GENERIC, and add options from @@ -827,7 +827,7 @@ options "MSGBUF_SIZE=40960" # # Mandatory ISA devices: isa, npx # -controller isa0 +controller isa0 at nexus? # # Options for `isa': @@ -888,10 +888,10 @@ options "NTIMECOUNTER=20" controller pnp0 # The keyboard controller; it controlls the keyboard and the PS/2 mouse. -controller atkbdc0 at isa? port IO_KBD tty +controller atkbdc0 at isa? port IO_KBD # The AT keyboard -device atkbd0 at isa? tty irq 1 +device atkbd0 at atkbdc? tty irq 1 # Options for atkbd: options ATKBD_DFLT_KEYMAP # specify the built-in keymap @@ -907,7 +907,7 @@ options KBD_INSTALL_CDEV # install a CDEV entry in /dev # 0x04 Old-style (XT) keyboard support, useful for older ThinkPads # PS/2 mouse -device psm0 at isa? tty irq 12 +device psm0 at atkbdc? tty irq 12 # Options for psm: options PSM_HOOKAPM #hook the APM resume event, useful @@ -977,7 +977,7 @@ options SC_DISABLE_REBOOT # disable reboot key sequence # buggy. If it is not configured then you *must* configure math emulation # (see above). If both npx0 and emulation are configured, then only npx0 # is used (provided it works). -device npx0 at isa? port IO_NPX iosiz 0x0 flags 0x0 irq 13 +device npx0 at nexus? port IO_NPX iosiz 0x0 flags 0x0 irq 13 # # `flags' for npx0: @@ -1464,7 +1464,7 @@ controller matcd0 at isa? port 0x230 bio device wt0 at isa? port 0x300 bio irq 5 drq 1 device ctx0 at isa? port 0x230 iomem 0xd0000 device spigot0 at isa? port 0xad6 irq 15 iomem 0xee000 -device apm0 at isa? +device apm0 at nexus? device gp0 at isa? port 0x2c0 tty device gsc0 at isa? port "IO_GSC1" tty drq 3 device joy0 at isa? port IO_GAME @@ -1632,7 +1632,7 @@ options "EISA_SLOTS=12" # The "oltr" driver supports the following Olicom PCI token-ring adapters # OC-3136, OC-3137, OC-3139, OC-3140, OC-3141, OC-3540, OC-3250 # -controller pci0 +controller pci0 at nexus? controller ahc1 controller ncr0 controller isp0 diff --git a/sys/i386/conf/files.i386 b/sys/i386/conf/files.i386 index 81f360e..ba0dba1 100644 --- a/sys/i386/conf/files.i386 +++ b/sys/i386/conf/files.i386 @@ -1,7 +1,7 @@ # This file tells config what files go into building a kernel, # files marked standard are always included. # -# $Id: files.i386,v 1.234 1999/04/13 19:38:10 peter Exp $ +# $Id: files.i386,v 1.235 1999/04/15 14:52:23 bde Exp $ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and @@ -90,6 +90,7 @@ i386/i386/mp_machdep.c optional smp i386/i386/mpapic.c optional smp i386/i386/mpboot.s optional smp i386/i386/mplock.s optional smp +i386/i386/nexus.c standard i386/i386/perfmon.c optional perfmon profiling-routine i386/i386/perfmon.c optional perfmon i386/i386/pmap.c standard @@ -125,8 +126,8 @@ i386/ibcs2/imgact_coff.c optional ibcs2 i386/isa/adv_isa.c optional adv device-driver #i386/isa/aha1542.c optional aha device-driver i386/isa/aha_isa.c optional aha device-driver -i386/isa/atkbd_isa.c optional atkbd device-driver -i386/isa/atkbdc_isa.c optional atkbdc device-driver +isa/atkbd_isa.c optional atkbd device-driver +isa/atkbdc_isa.c optional atkbdc device-driver i386/isa/bt_isa.c optional bt device-driver i386/isa/clock.c standard i386/isa/cronyx.c optional cx device-driver @@ -177,6 +178,8 @@ i386/isa/mse.c optional mse device-driver i386/isa/npx.c mandatory npx device-driver i386/isa/pcaudio.c optional pca device-driver i386/isa/matcd/matcd.c optional matcd device-driver +i386/isa/isa_compat.c optional isa device-driver +i386/isa/isa_dma.c optional isa device-driver i386/isa/pcibus.c optional pci device-driver i386/isa/pcicx.c optional ze device-driver i386/isa/pcicx.c optional zp device-driver @@ -190,7 +193,7 @@ i386/isa/pnp.c optional pnp device-driver i386/isa/prof_machdep.c optional profiling-routine i386/isa/ppc.c optional ppc device-driver i386/isa/pcf.c optional pcf device-driver -i386/isa/psm.c optional psm device-driver +isa/psm.c optional psm device-driver i386/isa/random_machdep.c standard i386/isa/rc.c optional rc device-driver i386/isa/rp.c optional rp device-driver @@ -198,7 +201,7 @@ i386/isa/scd.c optional scd device-driver i386/isa/si.c optional si device-driver i386/isa/si2_z280.c optional si device-driver i386/isa/si3_t225.c optional si device-driver -i386/isa/sio.c optional sio device-driver +isa/sio.c optional sio device-driver i386/isa/snd/sound.c optional pcm device-driver i386/isa/snd/dmabuf.c optional pcm device-driver i386/isa/snd/ad1848.c optional pcm device-driver @@ -268,9 +271,9 @@ i386/isa/sound/cs4232.c optional css device-driver i386/isa/spigot.c optional spigot device-driver i386/isa/spkr.c optional speaker device-driver i386/isa/stallion.c optional stl device-driver -i386/isa/syscons_isa.c optional sc device-driver +isa/syscons_isa.c optional sc device-driver i386/isa/vesa.c optional vga device-driver -i386/isa/vga_isa.c optional vga device-driver +isa/vga_isa.c optional vga device-driver i386/isa/tw.c optional tw device-driver i386/isa/wd.c optional wdc device-driver i386/isa/wd.c optional wd device-driver diff --git a/sys/i386/i386/autoconf.c b/sys/i386/i386/autoconf.c index fc7ab85..c501281 100644 --- a/sys/i386/i386/autoconf.c +++ b/sys/i386/i386/autoconf.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)autoconf.c 7.1 (Berkeley) 5/9/91 - * $Id: autoconf.c,v 1.111 1999/01/19 00:10:59 peter Exp $ + * $Id: autoconf.c,v 1.112 1999/04/15 14:52:24 bde Exp $ */ /* @@ -50,9 +50,11 @@ #include "opt_cd9660.h" #include "opt_mfs.h" #include "opt_nfsroot.h" +#include "opt_bus.h" #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/conf.h> #include <sys/disklabel.h> #include <sys/diskslice.h> @@ -74,13 +76,19 @@ #include "isa.h" #if NISA > 0 +#ifdef OLD_BUS_ARCH #include <i386/isa/isa_device.h> +#else +device_t isa_bus_device = 0; +#endif /* OLD_BUS_ARCH */ #endif #include "pnp.h" #if NPNP > 0 +#ifdef OLD_BUS_ARCH #include <i386/isa/pnp.h> #endif +#endif #include "eisa.h" #if NEISA > 0 @@ -92,8 +100,6 @@ #include <pci/pcivar.h> #endif -#include <sys/bus.h> - static void configure_first __P((void *)); static void configure __P((void *)); static void configure_final __P((void *)); @@ -186,6 +192,8 @@ configure_finish() { } +device_t nexus_dev; + /* * Determine i/o configuration for a machine. */ @@ -228,21 +236,21 @@ configure(dummy) eisa_configure(); #endif -#if NPCI > 0 - pci_configure(); -#endif - #if NPNP > 0 pnp_configure(); #endif -#if NISA > 0 - isa_configure(); -#endif + /* nexus0 is the top of the i386 device tree */ + device_add_child(root_bus, "nexus", 0, 0); /* initialize new bus architecture */ root_bus_configure(); +#if NISA > 0 + if (isa_bus_device) + bus_generic_attach(isa_bus_device); +#endif + /* * Now we're ready to handle (pending) interrupts. * XXX this is slightly misplaced. diff --git a/sys/i386/i386/exception.s b/sys/i386/i386/exception.s index 79e1d1a..a9286fa 100644 --- a/sys/i386/i386/exception.s +++ b/sys/i386/i386/exception.s @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: exception.s,v 1.56 1999/02/25 11:03:08 bde Exp $ + * $Id: exception.s,v 1.57 1999/02/28 10:53:28 bde Exp $ */ #include "npx.h" @@ -139,7 +139,7 @@ IDTVEC(fpu) #if NNPX > 0 /* * Handle like an interrupt (except for accounting) so that we can - * call npxintr to clear the error. It would be better to handle + * call npx_intr to clear the error. It would be better to handle * npx interrupts as traps. This used to be difficult for nested * interrupts, but now it is fairly easy - mask nested ones the * same as SWI_AST's. @@ -180,7 +180,7 @@ IDTVEC(fpu) movl %eax,_cpl #endif /* SMP */ - call _npxintr + call _npx_intr incb _intr_nesting_level MEXITCOUNT diff --git a/sys/i386/i386/legacy.c b/sys/i386/i386/legacy.c new file mode 100644 index 0000000..7df4387 --- /dev/null +++ b/sys/i386/i386/legacy.c @@ -0,0 +1,409 @@ +/* + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * This code implements a `root nexus' for Intel Architecture + * machines. The function of the root nexus is to serve as an + * attachment point for both processors and buses, and to manage + * resources which are common to all of them. In particular, + * this code implements the core resource managers for interrupt + * requests, DMA requests (which rightfully should be a part of the + * ISA code but it's easier to do it here for now), I/O port addresses, + * and I/O memory address space. + */ + +#include "opt_smp.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/ipl.h> +#include <machine/resource.h> +#ifdef APIC_IO +#include <machine/smp.h> +#include <machine/mpapic.h> +#endif + +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/intr_machdep.h> + +#include <pci/pcivar.h> + +#include "eisa.h" +#include "isa.h" +#include "pci.h" +#include "npx.h" +#include "apm.h" + +static struct rman irq_rman, drq_rman, port_rman, mem_rman; + +static int nexus_probe(device_t); +static void nexus_print_child(device_t, device_t); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_release_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_setup_intr(device_t, device_t, struct resource *, + void (*)(void *), void *, void **); +static int nexus_teardown_intr(device_t, device_t, struct resource *, + void *); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, nexus_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_release_resource, nexus_release_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_driver = { + "nexus", + nexus_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; +static devclass_t nexus_devclass; + +DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); + +#ifdef APIC_IO +#define LASTIRQ (NINTR - 1) +#else +#define LASTIRQ 15 +#endif + +static int +nexus_probe(device_t dev) +{ + device_t child; + + device_quiet(dev); /* suppress attach message for neatness */ + + irq_rman.rm_start = 0; + irq_rman.rm_end = LASTIRQ; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, 0, 1) + || rman_manage_region(&irq_rman, 3, LASTIRQ)) + panic("nexus_probe irq_rman"); + + drq_rman.rm_start = 0; + drq_rman.rm_end = 7; + drq_rman.rm_type = RMAN_ARRAY; + drq_rman.rm_descr = "DMA request lines"; + /* XXX drq 0 not available on some machines */ + if (rman_init(&drq_rman) + || rman_manage_region(&drq_rman, 0, 7)) + panic("nexus_probe drq_rman"); + + port_rman.rm_start = 0; + port_rman.rm_end = 0xffff; + port_rman.rm_type = RMAN_ARRAY; + port_rman.rm_descr = "I/O ports"; + if (rman_init(&port_rman) + || rman_manage_region(&port_rman, 0, 0xffff)) + panic("nexus_probe port_rman"); + + mem_rman.rm_start = 0; + mem_rman.rm_end = ~0u; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "I/O memory addresses"; + if (rman_init(&mem_rman) + || rman_manage_region(&mem_rman, 0, ~0)) + panic("nexus_probe mem_rman"); + +#if NNPX > 0 + child = device_add_child(dev, "npx", 0, 0); + if (child == 0) + panic("nexus_probe npx"); +#endif /* NNPX > 0 */ +#if NAPM > 0 + child = device_add_child(dev, "apm", 0, 0); + if (child == 0) + panic("nexus_probe apm"); +#endif /* NAPM > 0 */ +#if NPCI > 0 + /* Add a PCI bridge if pci bus is present */ + if (pci_cfgopen() != 0) { + child = device_add_child(dev, "pcib", 0, 0); + if (child == 0) + panic("nexus_probe pcib"); + } +#endif +#if 0 && NEISA > 0 + child = device_add_child(dev, "eisa", 0, 0); + if (child == 0) + panic("nexus_probe eisa"); +#endif +#if NISA > 0 + /* Add an ISA bus directly if pci bus is not present */ + if (pci_cfgopen() == 0) { + child = device_add_child(dev, "isa", 0, 0); + if (child == 0) + panic("nexus_probe isa"); + } +#endif + return 0; +} + +static void +nexus_print_child(device_t bus, device_t child) +{ + printf(" on motherboard"); +} + +/* + * Allocate a resource on behalf of child. NB: child is usually going to be a + * child of one of our descendants, not a direct child of nexus0. + * (Exceptions include npx.) + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *rv; + struct rman *rm; + + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + + case SYS_RES_DRQ: + rm = &drq_rman; + break; + + case SYS_RES_IOPORT: + rm = &port_rman; + break; + + case SYS_RES_MEMORY: + rm = &mem_rman; + break; + + default: + return 0; + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return 0; + + if (type == SYS_RES_MEMORY) { + caddr_t vaddr = 0; + + if (rv->r_end < 1024 * 1024 * 1024) { + /* + * The first 1Mb is mapped at KERNBASE. + */ + vaddr = (caddr_t)((uintptr_t)KERNBASE + rv->r_start); + } else { + u_int32_t paddr; + u_int32_t psize; + u_int32_t poffs; + + paddr = rv->r_start; + psize = rv->r_end - rv->r_start; + + poffs = paddr - trunc_page(paddr); + vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs; + } + rman_set_virtual(rv, vaddr); + rman_set_bustag(rv, I386_BUS_SPACE_MEM); + rman_set_bushandle(rv, (bus_space_handle_t) vaddr); + } else if (type == SYS_RES_IOPORT) { + rman_set_bustag(rv, I386_BUS_SPACE_IO); + rman_set_bushandle(rv, rv->r_start); + } + return rv; +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_activate_resource(r)); +} + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_deactivate_resource(r)); +} + +static int +nexus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_release_resource(r)); +} + +/* + * Currently this uses the really grody interface from kern/kern_intr.c + * (which really doesn't belong in kern/anything.c). Eventually, all of + * the code in kern_intr.c and machdep_intr.c should get moved here, since + * this is going to be the official interface. + */ +static int +nexus_setup_intr(device_t bus, device_t child, struct resource *irq, + void (*ihand)(void *), void *arg, void **cookiep) +{ + intrmask_t *mask; + driver_t *driver; + int error, icflags; + + if (child) + device_printf(child, "interrupting at irq %d\n", + (int)irq->r_start); + + *cookiep = 0; + if (irq->r_flags & RF_SHAREABLE) + icflags = 0; + else + icflags = INTR_EXCL; + + driver = device_get_driver(child); + switch (driver->type) { + case DRIVER_TYPE_TTY: + mask = &tty_imask; + break; + case (DRIVER_TYPE_TTY | DRIVER_TYPE_FAST): + mask = &tty_imask; + icflags |= INTR_FAST; + break; + case DRIVER_TYPE_BIO: + mask = &bio_imask; + break; + case DRIVER_TYPE_NET: + mask = &net_imask; + break; + case DRIVER_TYPE_CAM: + mask = &cam_imask; + break; + case DRIVER_TYPE_MISC: + mask = 0; + break; + default: + panic("still using grody create_intr interface"); + } + + /* + * We depend here on rman_activate_resource() being idempotent. + */ + error = rman_activate_resource(irq); + if (error) + return (error); + + *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg, + mask, icflags); + if (*cookiep) + error = intr_connect(*cookiep); + else + error = EINVAL; /* XXX ??? */ + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + return (intr_destroy(ih)); +} + +static devclass_t pcib_devclass; + +static int +nexus_pcib_probe(device_t dev) +{ + device_set_desc(dev, "PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t nexus_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_pcib_driver = { + "pcib", + nexus_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/i386/i386/machdep.c b/sys/i386/i386/machdep.c index 6ed3182..6980279 100644 --- a/sys/i386/i386/machdep.c +++ b/sys/i386/i386/machdep.c @@ -35,7 +35,7 @@ * SUCH DAMAGE. * * from: @(#)machdep.c 7.4 (Berkeley) 6/3/91 - * $Id: machdep.c,v 1.327 1999/03/06 04:46:18 wollman Exp $ + * $Id: machdep.c,v 1.328 1999/04/03 22:19:58 jdp Exp $ */ #include "apm.h" @@ -71,6 +71,7 @@ #include <sys/sysent.h> #include <sys/sysctl.h> #include <sys/vmmeter.h> +#include <sys/bus.h> #ifdef SYSVSHM #include <sys/shm.h> @@ -125,7 +126,9 @@ #include <machine/perfmon.h> #endif +#ifdef OLD_BUS_ARCH #include <i386/isa/isa_device.h> +#endif #include <i386/isa/intr_machdep.h> #ifndef VM86 #include <i386/isa/rtc.h> @@ -1164,8 +1167,10 @@ init386(first) unsigned biosbasemem, biosextmem; struct gate_descriptor *gdp; int gsel_tss; +#if NNPX > 0 + int msize; +#endif - struct isa_device *idp; #ifndef SMP /* table descriptors - used to load tables by microp */ struct region_descriptor r_gdt, r_idt; @@ -1454,10 +1459,11 @@ init386(first) #endif #if NNPX > 0 - idp = find_isadev(isa_devtab_null, &npxdriver, 0); - if (idp != NULL && idp->id_msize != 0) { - Maxmem = idp->id_msize / 4; - speculative_mprobe = FALSE; + if (resource_int_value("npx", 0, "msize", &msize) == 0) { + if (msize != 0) { + Maxmem = msize / 4; + speculative_mprobe = FALSE; + } } #endif diff --git a/sys/i386/i386/nexus.c b/sys/i386/i386/nexus.c new file mode 100644 index 0000000..7df4387 --- /dev/null +++ b/sys/i386/i386/nexus.c @@ -0,0 +1,409 @@ +/* + * Copyright 1998 Massachusetts Institute of Technology + * + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +/* + * This code implements a `root nexus' for Intel Architecture + * machines. The function of the root nexus is to serve as an + * attachment point for both processors and buses, and to manage + * resources which are common to all of them. In particular, + * this code implements the core resource managers for interrupt + * requests, DMA requests (which rightfully should be a part of the + * ISA code but it's easier to do it here for now), I/O port addresses, + * and I/O memory address space. + */ + +#include "opt_smp.h" + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/bus.h> +#include <sys/interrupt.h> +#include <sys/kernel.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/vmparam.h> +#include <vm/vm.h> +#include <vm/pmap.h> +#include <machine/pmap.h> + +#include <machine/ipl.h> +#include <machine/resource.h> +#ifdef APIC_IO +#include <machine/smp.h> +#include <machine/mpapic.h> +#endif + +#include <i386/isa/isa.h> +#include <i386/isa/icu.h> +#include <i386/isa/intr_machdep.h> + +#include <pci/pcivar.h> + +#include "eisa.h" +#include "isa.h" +#include "pci.h" +#include "npx.h" +#include "apm.h" + +static struct rman irq_rman, drq_rman, port_rman, mem_rman; + +static int nexus_probe(device_t); +static void nexus_print_child(device_t, device_t); +static struct resource *nexus_alloc_resource(device_t, device_t, int, int *, + u_long, u_long, u_long, u_int); +static int nexus_activate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_deactivate_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_release_resource(device_t, device_t, int, int, + struct resource *); +static int nexus_setup_intr(device_t, device_t, struct resource *, + void (*)(void *), void *, void **); +static int nexus_teardown_intr(device_t, device_t, struct resource *, + void *); + +static device_method_t nexus_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, nexus_print_child), + DEVMETHOD(bus_read_ivar, bus_generic_read_ivar), + DEVMETHOD(bus_write_ivar, bus_generic_write_ivar), + DEVMETHOD(bus_alloc_resource, nexus_alloc_resource), + DEVMETHOD(bus_release_resource, nexus_release_resource), + DEVMETHOD(bus_activate_resource, nexus_activate_resource), + DEVMETHOD(bus_deactivate_resource, nexus_deactivate_resource), + DEVMETHOD(bus_setup_intr, nexus_setup_intr), + DEVMETHOD(bus_teardown_intr, nexus_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_driver = { + "nexus", + nexus_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; +static devclass_t nexus_devclass; + +DRIVER_MODULE(nexus, root, nexus_driver, nexus_devclass, 0, 0); + +#ifdef APIC_IO +#define LASTIRQ (NINTR - 1) +#else +#define LASTIRQ 15 +#endif + +static int +nexus_probe(device_t dev) +{ + device_t child; + + device_quiet(dev); /* suppress attach message for neatness */ + + irq_rman.rm_start = 0; + irq_rman.rm_end = LASTIRQ; + irq_rman.rm_type = RMAN_ARRAY; + irq_rman.rm_descr = "Interrupt request lines"; + if (rman_init(&irq_rman) + || rman_manage_region(&irq_rman, 0, 1) + || rman_manage_region(&irq_rman, 3, LASTIRQ)) + panic("nexus_probe irq_rman"); + + drq_rman.rm_start = 0; + drq_rman.rm_end = 7; + drq_rman.rm_type = RMAN_ARRAY; + drq_rman.rm_descr = "DMA request lines"; + /* XXX drq 0 not available on some machines */ + if (rman_init(&drq_rman) + || rman_manage_region(&drq_rman, 0, 7)) + panic("nexus_probe drq_rman"); + + port_rman.rm_start = 0; + port_rman.rm_end = 0xffff; + port_rman.rm_type = RMAN_ARRAY; + port_rman.rm_descr = "I/O ports"; + if (rman_init(&port_rman) + || rman_manage_region(&port_rman, 0, 0xffff)) + panic("nexus_probe port_rman"); + + mem_rman.rm_start = 0; + mem_rman.rm_end = ~0u; + mem_rman.rm_type = RMAN_ARRAY; + mem_rman.rm_descr = "I/O memory addresses"; + if (rman_init(&mem_rman) + || rman_manage_region(&mem_rman, 0, ~0)) + panic("nexus_probe mem_rman"); + +#if NNPX > 0 + child = device_add_child(dev, "npx", 0, 0); + if (child == 0) + panic("nexus_probe npx"); +#endif /* NNPX > 0 */ +#if NAPM > 0 + child = device_add_child(dev, "apm", 0, 0); + if (child == 0) + panic("nexus_probe apm"); +#endif /* NAPM > 0 */ +#if NPCI > 0 + /* Add a PCI bridge if pci bus is present */ + if (pci_cfgopen() != 0) { + child = device_add_child(dev, "pcib", 0, 0); + if (child == 0) + panic("nexus_probe pcib"); + } +#endif +#if 0 && NEISA > 0 + child = device_add_child(dev, "eisa", 0, 0); + if (child == 0) + panic("nexus_probe eisa"); +#endif +#if NISA > 0 + /* Add an ISA bus directly if pci bus is not present */ + if (pci_cfgopen() == 0) { + child = device_add_child(dev, "isa", 0, 0); + if (child == 0) + panic("nexus_probe isa"); + } +#endif + return 0; +} + +static void +nexus_print_child(device_t bus, device_t child) +{ + printf(" on motherboard"); +} + +/* + * Allocate a resource on behalf of child. NB: child is usually going to be a + * child of one of our descendants, not a direct child of nexus0. + * (Exceptions include npx.) + */ +static struct resource * +nexus_alloc_resource(device_t bus, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + struct resource *rv; + struct rman *rm; + + switch (type) { + case SYS_RES_IRQ: + rm = &irq_rman; + break; + + case SYS_RES_DRQ: + rm = &drq_rman; + break; + + case SYS_RES_IOPORT: + rm = &port_rman; + break; + + case SYS_RES_MEMORY: + rm = &mem_rman; + break; + + default: + return 0; + } + + rv = rman_reserve_resource(rm, start, end, count, flags, child); + if (rv == 0) + return 0; + + if (type == SYS_RES_MEMORY) { + caddr_t vaddr = 0; + + if (rv->r_end < 1024 * 1024 * 1024) { + /* + * The first 1Mb is mapped at KERNBASE. + */ + vaddr = (caddr_t)((uintptr_t)KERNBASE + rv->r_start); + } else { + u_int32_t paddr; + u_int32_t psize; + u_int32_t poffs; + + paddr = rv->r_start; + psize = rv->r_end - rv->r_start; + + poffs = paddr - trunc_page(paddr); + vaddr = (caddr_t) pmap_mapdev(paddr-poffs, psize+poffs) + poffs; + } + rman_set_virtual(rv, vaddr); + rman_set_bustag(rv, I386_BUS_SPACE_MEM); + rman_set_bushandle(rv, (bus_space_handle_t) vaddr); + } else if (type == SYS_RES_IOPORT) { + rman_set_bustag(rv, I386_BUS_SPACE_IO); + rman_set_bushandle(rv, rv->r_start); + } + return rv; +} + +static int +nexus_activate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_activate_resource(r)); +} + +static int +nexus_deactivate_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_deactivate_resource(r)); +} + +static int +nexus_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) +{ + return (rman_release_resource(r)); +} + +/* + * Currently this uses the really grody interface from kern/kern_intr.c + * (which really doesn't belong in kern/anything.c). Eventually, all of + * the code in kern_intr.c and machdep_intr.c should get moved here, since + * this is going to be the official interface. + */ +static int +nexus_setup_intr(device_t bus, device_t child, struct resource *irq, + void (*ihand)(void *), void *arg, void **cookiep) +{ + intrmask_t *mask; + driver_t *driver; + int error, icflags; + + if (child) + device_printf(child, "interrupting at irq %d\n", + (int)irq->r_start); + + *cookiep = 0; + if (irq->r_flags & RF_SHAREABLE) + icflags = 0; + else + icflags = INTR_EXCL; + + driver = device_get_driver(child); + switch (driver->type) { + case DRIVER_TYPE_TTY: + mask = &tty_imask; + break; + case (DRIVER_TYPE_TTY | DRIVER_TYPE_FAST): + mask = &tty_imask; + icflags |= INTR_FAST; + break; + case DRIVER_TYPE_BIO: + mask = &bio_imask; + break; + case DRIVER_TYPE_NET: + mask = &net_imask; + break; + case DRIVER_TYPE_CAM: + mask = &cam_imask; + break; + case DRIVER_TYPE_MISC: + mask = 0; + break; + default: + panic("still using grody create_intr interface"); + } + + /* + * We depend here on rman_activate_resource() being idempotent. + */ + error = rman_activate_resource(irq); + if (error) + return (error); + + *cookiep = intr_create((void *)(intptr_t)-1, irq->r_start, ihand, arg, + mask, icflags); + if (*cookiep) + error = intr_connect(*cookiep); + else + error = EINVAL; /* XXX ??? */ + + return (error); +} + +static int +nexus_teardown_intr(device_t dev, device_t child, struct resource *r, void *ih) +{ + return (intr_destroy(ih)); +} + +static devclass_t pcib_devclass; + +static int +nexus_pcib_probe(device_t dev) +{ + device_set_desc(dev, "PCI host bus adapter"); + + device_add_child(dev, "pci", 0, 0); + + return 0; +} + +static device_method_t nexus_pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nexus_pcib_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t nexus_pcib_driver = { + "pcib", + nexus_pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +DRIVER_MODULE(pcib, nexus, nexus_pcib_driver, pcib_devclass, 0, 0); diff --git a/sys/i386/i386/userconfig.c b/sys/i386/i386/userconfig.c index 5c557a7..751c7b8 100644 --- a/sys/i386/i386/userconfig.c +++ b/sys/i386/i386/userconfig.c @@ -46,7 +46,7 @@ ** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF ** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. ** - ** $Id: userconfig.c,v 1.132 1999/02/21 16:33:51 n_hibma Exp $ + ** $Id: userconfig.c,v 1.133 1999/04/06 17:08:30 wpaul Exp $ **/ /** @@ -115,11 +115,13 @@ #include <sys/reboot.h> #include <sys/linker.h> #include <sys/sysctl.h> +#include <sys/bus.h> #include <machine/cons.h> #include <machine/md_var.h> #include <machine/limits.h> + #include <i386/isa/isa_device.h> #include "pnp.h" @@ -132,11 +134,17 @@ static MALLOC_DEFINE(M_DEVL, "isa_devlist", "isa_device lists in userconfig()"); static struct isa_device *isa_devlist; /* list read by kget to extract changes */ +static struct isa_device *isa_devtab; /* fake isa_device table */ +static struct isa_driver *isa_drvtab; /* fake driver list */ static int userconfig_boot_parsing; /* set if we are reading from the boot instructions */ #define putchar(x) cnputc(x) +static void load_devtab(void); +static void free_devtab(void); +static void save_resource(struct isa_device *); + static int sysctl_machdep_uc_devlist SYSCTL_HANDLER_ARGS { @@ -279,8 +287,6 @@ getchar(void) #endif #ifdef VISUAL_USERCONFIG -static struct isa_device *devtabs[] = { isa_devtab_bio, isa_devtab_tty, isa_devtab_net, - isa_devtab_cam, isa_devtab_null, NULL }; typedef struct { @@ -538,12 +544,10 @@ setdev(DEV_LIST *dev, int enabled) static void getdevs(void) { - int i,j; + int i; struct isa_device *ap; - for (j = 0; devtabs[j]; j++) /* ISA devices */ - { - ap = devtabs[j]; /* pointer to array of devices */ + ap = isa_devtab; /* pointer to array of devices */ for (i = 0; ap[i].id_id; i++) /* for each device in this table */ { scratch.unit = ap[i].id_unit; /* device parameters */ @@ -563,7 +567,6 @@ getdevs(void) if (!devinfo(&scratch)) /* get more info on the device */ insdev(&scratch,ap[i].id_enabled?active:inactive); } - } #if NPCI > 0 for (i = 0; i < pcidevice_set.ls_length; i++) { @@ -847,6 +850,7 @@ savelist(DEV_LIST *list, int active) { id_pn = id_p->id_next; bcopy(list->device,id_p,sizeof(struct isa_device)); + save_resource(list->device); id_p->id_next = id_pn; break; } @@ -855,6 +859,7 @@ savelist(DEV_LIST *list, int active) { id_pn = malloc(sizeof(struct isa_device),M_DEVL,M_WAITOK); bcopy(list->device,id_pn,sizeof(struct isa_device)); + save_resource(list->device); id_pn->id_next = isa_devlist; isa_devlist = id_pn; /* park at top of list */ } @@ -2510,7 +2515,7 @@ visuserconfig(void) * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: userconfig.c,v 1.132 1999/02/21 16:33:51 n_hibma Exp $ + * $Id: userconfig.c,v 1.133 1999/04/06 17:08:30 wpaul Exp $ */ #include "scbus.h" @@ -2659,6 +2664,7 @@ userconfig(void) int rval; Cmd *cmd; + load_devtab(); init_config_script(); while (1) { @@ -2693,8 +2699,10 @@ userconfig(void) continue; } rval = (*cmd->handler)(cmd->parms); - if (rval) + if (rval) { + free_devtab(); return; + } } } @@ -2792,11 +2800,7 @@ static int list_devices(CmdParm *parms) { lineno = 0; - if (lsdevtab(&isa_devtab_bio[0])) return 0; - if (lsdevtab(&isa_devtab_tty[0])) return 0; - if (lsdevtab(&isa_devtab_net[0])) return 0; - if (lsdevtab(&isa_devtab_cam[0])) return 0; - if (lsdevtab(&isa_devtab_null[0])) return 0; + if (lsdevtab(isa_devtab)) return 0; #if NPNP > 0 if (lspnp()) return 0; #endif @@ -3312,20 +3316,65 @@ lsdevtab(struct isa_device *dt) return(0); } +static void +load_devtab(void) +{ + int i, val; + int count = resource_count(); + int id = 1; + int dt; + char *name; + int unit; + + isa_devtab = malloc(sizeof(struct isa_device)*(count + 1),M_DEVL,M_WAITOK); + isa_drvtab = malloc(sizeof(struct isa_driver)*(count + 1),M_DEVL,M_WAITOK); + bzero(isa_devtab, sizeof(struct isa_device) * (count + 1)); + bzero(isa_drvtab, sizeof(struct isa_driver) * (count + 1)); + dt = 0; + for (i = 0; i < count; i++) { + name = resource_query_name(i); + unit = resource_query_unit(i); + if (unit < 0) + continue; /* skip wildcards */ + isa_devtab[dt].id_id = id++; + isa_devtab[dt].id_driver = &isa_drvtab[dt]; + resource_int_value(name, unit, "port", &isa_devtab[dt].id_iobase); + val = 0; + resource_int_value(name, unit, "irq", &val); + isa_devtab[dt].id_irq = (1 << val); + resource_int_value(name, unit, "drq", &isa_devtab[dt].id_drq); + resource_int_value(name, unit, "maddr",(int *)&isa_devtab[dt].id_maddr); + resource_int_value(name, unit, "msize", &isa_devtab[dt].id_msize); + isa_devtab[dt].id_unit = unit; + resource_int_value(name, unit, "flags", &isa_devtab[dt].id_flags); + val = 0; + resource_int_value(name, unit, "disabled", &val); + isa_devtab[dt].id_enabled = !val; + isa_drvtab[dt].name = malloc(strlen(name) + 1, M_DEVL,M_WAITOK); + strcpy(isa_drvtab[dt].name, name); + dt++; + } +} + +static void +free_devtab(void) +{ + int i; + int count = resource_count(); + + for (i = 0; i < count; i++) + if (isa_drvtab[i].name) + free(isa_drvtab[i].name, M_DEVL); + free(isa_drvtab, M_DEVL); + free(isa_devtab, M_DEVL); +} + static struct isa_device * find_device(char *devname, int unit) { struct isa_device *ret; - if ((ret = search_devtable(&isa_devtab_bio[0], devname, unit)) != NULL) - return ret; - if ((ret = search_devtable(&isa_devtab_tty[0], devname, unit)) != NULL) - return ret; - if ((ret = search_devtable(&isa_devtab_net[0], devname, unit)) != NULL) - return ret; - if ((ret = search_devtable(&isa_devtab_cam[0], devname, unit)) != NULL) - return ret; - if ((ret = search_devtable(&isa_devtab_null[0], devname, unit)) != NULL) + if ((ret = search_devtable(isa_devtab, devname, unit)) != NULL) return ret; return NULL; } @@ -3532,6 +3581,29 @@ list_scsi(CmdParm *parms) } #endif +static void +save_resource(struct isa_device *idev) +{ + int i; + char *name; + int unit; + int count = resource_count(); + + for (i = 0; i < count; i++) { + name = resource_query_name(i); + unit = resource_query_unit(i); + if (strcmp(name, idev->id_driver->name) || unit != idev->id_unit) + continue; + resource_set_int(i, "port", isa_devtab[i].id_iobase); + resource_set_int(i, "irq", (1 << isa_devtab[i].id_irq)); + resource_set_int(i, "drq", isa_devtab[i].id_drq); + resource_set_int(i, "maddr", (int)isa_devtab[i].id_maddr); + resource_set_int(i, "msize", isa_devtab[i].id_msize); + resource_set_int(i, "flags", isa_devtab[i].id_flags); + resource_set_int(i, "disabled", !isa_devtab[i].id_enabled); + } +} + static int save_dev(idev) struct isa_device *idev; @@ -3544,6 +3616,7 @@ struct isa_device *idev; if (id_p->id_id == idev->id_id) { id_pn = id_p->id_next; bcopy(idev,id_p,sizeof(struct isa_device)); + save_resource(idev); id_p->id_next = id_pn; return 1; } diff --git a/sys/i386/include/asnames.h b/sys/i386/include/asnames.h index b1d8a08..8ac432c 100644 --- a/sys/i386/include/asnames.h +++ b/sys/i386/include/asnames.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: asnames.h,v 1.29 1999/02/22 15:13:34 bde Exp $ + * $Id: asnames.h,v 1.30 1999/02/25 12:53:34 bde Exp $ */ #ifndef _MACHINE_ASNAMES_H_ @@ -291,7 +291,7 @@ #define _normalize_nuo normalize_nuo #define _npx_intrs_while_probing npx_intrs_while_probing #define _npx_traps_while_probing npx_traps_while_probing -#define _npxintr npxintr +#define _npx_intr npx_intr #define _npxproc npxproc #define _npxsave npxsave #define _other_cpus other_cpus diff --git a/sys/i386/isa/aha_isa.c b/sys/i386/isa/aha_isa.c index 9426679..c3704df 100644 --- a/sys/i386/isa/aha_isa.c +++ b/sys/i386/isa/aha_isa.c @@ -28,7 +28,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: aha_isa.c,v 1.5 1998/11/10 06:44:54 gibbs Exp $ + * $Id: aha_isa.c,v 1.6 1999/01/20 06:21:23 imp Exp $ */ #include "pnp.h" @@ -257,7 +257,6 @@ static void ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NAHATOT) return; @@ -278,9 +277,7 @@ ahapnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &ahadriver; - dvp = find_isadev(isa_devtab_tty, &ahadriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = aha_isa_probe(dev)) != 0) diff --git a/sys/i386/isa/fd.c b/sys/i386/isa/fd.c index 07223f1..0414b18 100644 --- a/sys/i386/isa/fd.c +++ b/sys/i386/isa/fd.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.133 1999/02/10 00:03:32 ken Exp $ + * $Id: fd.c,v 1.134 1999/04/06 03:06:51 peter Exp $ * */ @@ -60,26 +60,37 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/bus.h> #include <sys/conf.h> -#include <sys/fcntl.h> -#include <machine/clock.h> -#include <machine/ioctl_fd.h> #include <sys/disklabel.h> -#include <sys/buf.h> #include <sys/devicestat.h> +#include <sys/fcntl.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/proc.h> #include <sys/syslog.h> -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/fdreg.h> -#include <i386/isa/fdc.h> -#include <i386/isa/rtc.h> + +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/clock.h> +#include <machine/ioctl_fd.h> +#include <machine/resource.h> #include <machine/stdarg.h> + #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ +#include <isa/isavar.h> +#include <i386/isa/isa.h> +#include <i386/isa/isa_dma.h> +#include <i386/isa/fdreg.h> +#include <i386/isa/fdc.h> +#include <i386/isa/rtc.h> + /* misuse a flag to identify format operation */ #define B_FORMAT B_XXX @@ -151,13 +162,13 @@ static struct fd_type fd_types[NUMTYPES] = /***********************************************************************\ * Per controller structure. * \***********************************************************************/ -struct fdc_data fdc_data[NFDC]; +static devclass_t fdc_devclass; /***********************************************************************\ * Per drive structure. * * N per controller (DRVS_PER_CTLR) * \***********************************************************************/ -static struct fd_data { +struct fd_data { struct fdc_data *fdc; /* pointer to controller structure */ int fdsu; /* this units number on this controller */ int type; /* Drive type (FD_1440...) */ @@ -179,7 +190,10 @@ static struct fd_data { void *bdevs[1 + NUMDENS + MAXPARTITIONS]; void *cdevs[1 + NUMDENS + MAXPARTITIONS]; #endif -} fd_data[NFD]; + device_t dev; + fdu_t fdu; +}; +static devclass_t fd_devclass; /***********************************************************************\ * Throughout this file the following conventions will be used: * @@ -195,29 +209,26 @@ static struct fd_data { static int yeattach(struct isa_device *); #endif -/* autoconfig functions */ -static int fdprobe(struct isa_device *); -static int fdattach(struct isa_device *); - /* needed for ft driver, thus exported */ -int in_fdc(fdcu_t); -int out_fdc(fdcu_t, int); +int in_fdc(struct fdc_data *); +int out_fdc(struct fdc_data *, int); /* internal functions */ -static void set_motor(fdcu_t, int, int); +static void fdc_add_device(device_t, const char *, int); +static void fdc_intr(void *); +static void set_motor(struct fdc_data *, int, int); # define TURNON 1 # define TURNOFF 0 static timeout_t fd_turnoff; static timeout_t fd_motor_on; -static void fd_turnon(fdu_t); +static void fd_turnon(struct fd_data *); static void fdc_reset(fdc_p); -static int fd_in(fdcu_t, int *); -static void fdstart(fdcu_t); +static int fd_in(struct fdc_data *, int *); +static void fdstart(struct fdc_data *); static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; -static ointhand2_t fdintr; -static int fdstate(fdcu_t, fdc_p); -static int retrier(fdcu_t); +static int fdstate(struct fdc_data *); +static int retrier(struct fdc_data *); static int fdformat(dev_t, struct fd_formb *, struct proc *); static int enable_fifo(fdc_p fdc); @@ -356,13 +367,6 @@ static int yeintr(struct pccard_devinfo *devi) #endif /* NCARD > 0 */ #endif /* FDC_YE */ - -/* autoconfig structure */ - -struct isa_driver fdcdriver = { - fdprobe, fdattach, "fdc", -}; - static d_open_t Fdopen; /* NOTE, not fdopen */ static d_read_t fdread; static d_write_t fdwrite; @@ -374,28 +378,18 @@ static d_strategy_t fdstrategy; #define CDEV_MAJOR 9 #define BDEV_MAJOR 2 - -static struct cdevsw fd_cdevsw = { - Fdopen, fdclose, fdread, fdwrite, - fdioctl, nostop, nullreset, nodevtotty, - seltrue, nommap, fdstrategy, "fd", - NULL, -1, nodump, nopsize, - D_DISK, 0, -1 }; - - -static struct isa_device *fdcdevs[NFDC]; - - static int -fdc_err(fdcu_t fdcu, const char *s) +fdc_err(struct fdc_data *fdc, const char *s) { - fdc_data[fdcu].fdc_errs++; - if(s) { - if(fdc_data[fdcu].fdc_errs < FDC_ERRMAX) - printf("fdc%d: %s", fdcu, s); - else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX) - printf("fdc%d: too many errors, not logging any more\n", - fdcu); + fdc->fdc_errs++; + if (s) { + if (fdc->fdc_errs < FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("%s", s); + } else if (fdc->fdc_errs == FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("too many errors, not logging any more\n"); + } } return FD_FAILED; @@ -407,9 +401,8 @@ fdc_err(fdcu_t fdcu, const char *s) * # of output bytes, output bytes as ints ..., * # of input bytes, input bytes as ints ... */ - static int -fd_cmd(fdcu_t fdcu, int n_out, ...) +fd_cmd(struct fdc_data *fdc, int n_out, ...) { u_char cmd; int n_in; @@ -422,26 +415,26 @@ fd_cmd(fdcu_t fdcu, int n_out, ...) va_start(ap, n_out); for (n = 0; n < n_out; n++) { - if (out_fdc(fdcu, va_arg(ap, int)) < 0) + if (out_fdc(fdc, va_arg(ap, int)) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %x failed at out byte %d of %d\n", cmd, n + 1, n_out); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } n_in = va_arg(ap, int); for (n = 0; n < n_in; n++) { int *ptr = va_arg(ap, int *); - if (fd_in(fdcu, ptr) < 0) + if (fd_in(fdc, ptr) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %02x failed at in byte %d of %d\n", cmd, n + 1, n_in); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } @@ -462,8 +455,8 @@ enable_fifo(fdc_p fdc) * first byte, and check for an early turn of data directon. */ - if (out_fdc(fdc->fdcu, I8207X_CONFIGURE) < 0) - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + if (out_fdc(fdc, I8207X_CONFIGURE) < 0) + return fdc_err(fdc, "Enable FIFO failed\n"); /* If command is invalid, return */ j = 100000; @@ -474,17 +467,17 @@ enable_fifo(fdc_p fdc) return FD_FAILED; } if (j<0 || - fd_cmd(fdc->fdcu, 3, + fd_cmd(fdc, 3, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { fdc_reset(fdc); - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + return fdc_err(fdc, "Enable FIFO failed\n"); } fdc->flags |= FDC_HAS_FIFO; return 0; } - if (fd_cmd(fdc->fdcu, 4, + if (fd_cmd(fdc, 4, I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) - return fdc_err(fdc->fdcu, "Re-enable FIFO failed\n"); + return fdc_err(fdc, "Re-enable FIFO failed\n"); return 0; } @@ -493,9 +486,9 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) { int st3; - if (fd_cmd(fdc->fdcu, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) + if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) { - return fdc_err(fdc->fdcu, "Sense Drive Status failed\n"); + return fdc_err(fdc, "Sense Drive Status failed\n"); } if (st3p) *st3p = st3; @@ -506,13 +499,11 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) static int fd_sense_int(fdc_p fdc, int *st0p, int *cylp) { - int st0, cyl; + int cyl, st0, ret; - int ret = fd_cmd(fdc->fdcu, 1, NE7CMD_SENSEI, 1, &st0); - - if (ret) - { - (void)fdc_err(fdc->fdcu, + ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); + if (ret) { + (void)fdc_err(fdc, "sense intr err reading stat reg 0\n"); return ret; } @@ -520,17 +511,15 @@ fd_sense_int(fdc_p fdc, int *st0p, int *cylp) if (st0p) *st0p = st0; - if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) - { + if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { /* * There doesn't seem to have been an interrupt. */ return FD_NOT_VALID; } - if (fd_in(fdc->fdcu, &cyl) < 0) - { - return fdc_err(fdc->fdcu, "can't get cyl num\n"); + if (fd_in(fdc, &cyl) < 0) { + return fdc_err(fdc, "can't get cyl num\n"); } if (cylp) @@ -545,8 +534,7 @@ fd_read_status(fdc_p fdc, int fdsu) { int i, ret; - for (i = 0; i < 7; i++) - { + for (i = 0; i < 7; i++) { /* * XXX types are poorly chosen. Only bytes can by read * from the hardware, but fdc->status[] wants u_ints and @@ -554,7 +542,7 @@ fd_read_status(fdc_p fdc, int fdsu) */ int status; - ret = fd_in(fdc->fdcu, &status); + ret = fd_in(fdc, &status); fdc->status[i] = status; if (ret != 0) break; @@ -572,34 +560,92 @@ fd_read_status(fdc_p fdc, int fdsu) /* autoconfiguration stuff */ /****************************************************************************/ -/* - * probe for existance of controller - */ static int -fdprobe(struct isa_device *dev) +fdc_probe(device_t dev) { - fdcu_t fdcu = dev->id_unit; - if(fdc_data[fdcu].flags & FDC_ATTACHED) - { - printf("fdc%d: unit used multiple times\n", fdcu); - return 0; + int error, i, ic_type; + struct fdc_data *fdc; + char myname[8]; /* better be long enough */ + + fdc = device_get_softc(dev); + bzero(fdc, sizeof *fdc); + fdc->fdc_dev = dev; + fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0; + fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0; + + fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, + &fdc->rid_ioport, 0ul, ~0ul, + IO_FDCSIZE, RF_ACTIVE); + if (fdc->res_ioport == 0) { + device_print_prettyname(dev); + printf("cannot reserve I/O port range\n"); + error = ENXIO; + goto out; } - - fdcdevs[fdcu] = dev; - fdc_data[fdcu].baseport = dev->id_iobase; + fdc->baseport = fdc->res_ioport->r_start; + + fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, + &fdc->rid_irq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_irq == 0) { + device_print_prettyname(dev); + printf("cannot reserve interrupt line\n"); + error = ENXIO; + goto out; + } + fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, + &fdc->rid_drq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_drq == 0) { + device_print_prettyname(dev); + printf("cannot reserve DMA request line\n"); + error = ENXIO; + goto out; + } + fdc->dmachan = fdc->res_drq->r_start; + error = BUS_SETUP_INTR(device_get_parent(dev), dev, + fdc->res_irq, fdc_intr, fdc, &fdc->fdc_intr); /* First - lets reset the floppy controller */ - outb(dev->id_iobase+FDOUT, 0); + outb(fdc->baseport + FDOUT, 0); DELAY(100); - outb(dev->id_iobase+FDOUT, FDO_FRST); + outb(fdc->baseport + FDOUT, FDO_FRST); /* see if it can handle a command */ - if (fd_cmd(fdcu, - 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), - 0)) - { - return(0); + if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), + NE7_SPEC_2(2, 0), 0)) { + error = ENXIO; + goto out; + } + + if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) { + ic_type = (u_char)ic_type; + switch (ic_type) { + case 0x80: + device_set_desc(dev, "NEC 765 or clone"); + fdc->fdct = FDC_NE765; + break; + case 0x81: + device_set_desc(dev, "Intel 82077 or clone"); + fdc->fdct = FDC_I82077; + break; + case 0x90: + device_set_desc(dev, "NEC 72065B or clone"); + fdc->fdct = FDC_NE72065; + break; + default: + device_set_desc(dev, "generic floppy controller"); + fdc->fdct = FDC_UNKNOWN; + break; + } } + + snprintf(myname, sizeof(myname), "%s%d", device_get_name(dev), + device_get_unit(dev)); + for (i = resource_query_string(-1, "at", myname); i != -1; + i = resource_query_string(i, "at", myname)) + fdc_add_device(dev, resource_query_name(i), + resource_query_unit(i)); #ifdef FDC_YE /* * don't succeed on probe; wait @@ -608,277 +654,312 @@ fdprobe(struct isa_device *dev) if (dev->id_flags & FDC_IS_PCMCIA) return(0); #endif - return (IO_FDCSIZE); + return (0); + +out: + if (fdc->fdc_intr) + BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, + fdc->fdc_intr); + if (fdc->res_irq != 0) { + bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + } + if (fdc->res_ioport != 0) { + bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + } + if (fdc->res_drq != 0) { + bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + } + return (error); } /* - * wire controller into system, look for floppy units + * Aped dfr@freebsd.org's isa_add_device(). */ +static void +fdc_add_device(device_t dev, const char *name, int unit) +{ + int disabled, *ivar; + device_t child; + + ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT); + if (ivar == 0) + return; + if (resource_int_value(name, unit, "drive", ivar) == 0) + *ivar = 0; + child = device_add_child(dev, name, unit, ivar); + if (child == 0) + return; + if (resource_int_value(name, unit, "disabled", &disabled) == 0) + device_disable(child); +} + static int -fdattach(struct isa_device *dev) +fdc_attach(device_t dev) { - unsigned fdt; - fdu_t fdu; - fdcu_t fdcu = dev->id_unit; - fdc_p fdc = fdc_data + fdcu; - fd_p fd; - int fdsu, st0, st3, i; - struct isa_device *fdup; - int ic_type = 0; -#ifdef DEVFS - int mynor; - int typemynor; - int typesize; -#endif + struct fdc_data *fdc = device_get_softc(dev); + fdcu_t fdcu = device_get_unit(dev); - dev->id_ointr = fdintr; fdc->fdcu = fdcu; fdc->flags |= FDC_ATTACHED; - fdc->dmachan = dev->id_drq; + /* Acquire the DMA channel forever, The driver will do the rest */ + /* XXX should integrate with rman */ isa_dma_acquire(fdc->dmachan); isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); fdc->state = DEVIDLE; + /* reset controller, turn motor off, clear fdout mirror reg */ outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); bufq_init(&fdc->head); - /* check for each floppy drive */ - for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { - if (fdup->id_iobase != dev->id_iobase) - continue; - fdu = fdup->id_unit; - fd = &fd_data[fdu]; - if (fdu >= (NFD)) - continue; - fdsu = fdup->id_physid; - /* look up what bios thinks we have */ - switch (fdu) { - case 0: if (dev->id_flags & FDC_PRETEND_D0) - fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; - else - fdt = (rtcin(RTC_FDISKETTE) & 0xf0); - break; - case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); - break; - default: fdt = RTCFDT_NONE; - break; - } - /* is there a unit? */ - if ((fdt == RTCFDT_NONE) - ) { - fd->type = NO_TYPE; - continue; - } +#ifdef FIFO_BEFORE_MOTORON + /* Hmm, this doesn't work here - is set_motor() magic? -Peter */ + if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(dev); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } +#endif + /* + * Probe and attach any children as were configured above. + */ + return (bus_generic_attach(dev)); +} - /* select it */ - set_motor(fdcu, fdsu, TURNON); - DELAY(1000000); /* 1 sec */ +static void +fdc_print_child(device_t me, device_t child) +{ + printf(" at %s%d drive %d", device_get_name(me), device_get_unit(me), + *(int *)device_get_ivars(child)); +} - if (ic_type == 0 && - fd_cmd(fdcu, 1, NE7CMD_VERSION, 1, &ic_type) == 0) - { -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("fdc%d: ", fdcu); -#endif - ic_type = (u_char)ic_type; - switch( ic_type ) { - case 0x80: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 765\n"); -#endif - fdc->fdct = FDC_NE765; - break; - case 0x81: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("Intel 82077\n"); -#endif - fdc->fdct = FDC_I82077; - break; - case 0x90: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 72065B\n"); +static int +fd_probe(device_t dev) +{ + int i; + u_int fdt, st0, st3; + struct fd_data *fd; + struct fdc_data *fdc; + fdsu_t fdsu; +#ifndef FIFO_BEFORE_MOTORON + static int fd_fifo = 0; #endif - fdc->fdct = FDC_NE72065; - break; - default: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("unknown IC type %02x\n", ic_type); + + fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */ + fd = device_get_softc(dev); + fdc = device_get_softc(device_get_parent(dev)); + + bzero(fd, sizeof *fd); + fd->dev = dev; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->fdu = device_get_unit(dev); + + /* look up what bios thinks we have */ + switch (fd->fdu) { + case 0: + if (isa_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0) + fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; + else + fdt = (rtcin(RTC_FDISKETTE) & 0xf0); + break; + case 1: + fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); + break; + default: + fdt = RTCFDT_NONE; + break; + } + + /* is there a unit? */ + if (fdt == RTCFDT_NONE) + return (ENXIO); + + /* select it */ + set_motor(fdc, fdsu, TURNON); + DELAY(1000000); /* 1 sec */ + +#ifndef FIFO_BEFORE_MOTORON + if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(device_get_parent(dev)); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } + fd_fifo = 1; #endif - fdc->fdct = FDC_UNKNOWN; - break; - } - if (fdc->fdct != FDC_NE765 && - fdc->fdct != FDC_UNKNOWN && - enable_fifo(fdc) == 0) { - printf("fdc%d: FIFO enabled", fdcu); - printf(", %d bytes threshold\n", - fifo_threshold); - } - } - if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* if at track 0, first seek inwards */ - /* seek some steps: */ - (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); - DELAY(300000); /* ...wait a moment... */ - (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ - } - /* If we're at track 0 first seek inwards. */ - if ((fd_sense_drive_status(fdc, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* Seek some steps... */ - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { - /* ...wait a moment... */ - DELAY(300000); - /* make ctrlr happy: */ - (void)fd_sense_int(fdc, 0, 0); - } + if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) + && (st3 & NE7_ST3_T0)) { + /* if at track 0, first seek inwards */ + /* seek some steps: */ + fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0); + DELAY(300000); /* ...wait a moment... */ + fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ + } + + /* If we're at track 0 first seek inwards. */ + if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { + /* Seek some steps... */ + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { + /* ...wait a moment... */ + DELAY(300000); + /* make ctrlr happy: */ + fd_sense_int(fdc, 0, 0); } + } - for(i = 0; i < 2; i++) { - /* - * we must recalibrate twice, just in case the - * heads have been beyond cylinder 76, since most - * FDCs still barf when attempting to recalibrate - * more than 77 steps - */ - /* go back to 0: */ - if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { - /* a second being enough for full stroke seek*/ - DELAY(i == 0? 1000000: 300000); + for (i = 0; i < 2; i++) { + /* + * we must recalibrate twice, just in case the + * heads have been beyond cylinder 76, since most + * FDCs still barf when attempting to recalibrate + * more than 77 steps + */ + /* go back to 0: */ + if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { + /* a second being enough for full stroke seek*/ + DELAY(i == 0 ? 1000000 : 300000); - /* anything responding? */ - if (fd_sense_int(fdc, &st0, 0) == 0 && - (st0 & NE7_ST0_EC) == 0) - break; /* already probed succesfully */ - } + /* anything responding? */ + if (fd_sense_int(fdc, &st0, 0) == 0 && + (st0 & NE7_ST0_EC) == 0) + break; /* already probed succesfully */ } + } - set_motor(fdcu, fdsu, TURNOFF); + set_motor(fdc, fdsu, TURNOFF); - if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ - continue; + if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ + return (ENXIO); - fd->track = FD_NO_TRACK; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->options = 0; - callout_handle_init(&fd->toffhandle); - callout_handle_init(&fd->tohandle); - printf("fd%d: ", fdu); - - switch (fdt) { - case RTCFDT_12M: - printf("1.2MB 5.25in\n"); - fd->type = FD_1200; - break; - case RTCFDT_144M | RTCFDT_144M_PRETENDED: - printf("config-pretended "); - fdt = RTCFDT_144M; - /* fallthrough */ - case RTCFDT_144M: - printf("1.44MB 3.5in\n"); - fd->type = FD_1440; + fd->track = FD_NO_TRACK; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->options = 0; + callout_handle_init(&fd->toffhandle); + callout_handle_init(&fd->tohandle); + + switch (fdt) { + case RTCFDT_12M: + device_set_desc(dev, "1200-KB 5.25\" drive"); + fd->type = FD_1200; + break; + case RTCFDT_144M | RTCFDT_144M_PRETENDED: + device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive"); + fdt = RTCFDT_144M; + fd->type = FD_1440; + case RTCFDT_144M: + device_set_desc(dev, "1440-KB 3.5\" drive"); + fd->type = FD_1440; + break; + case RTCFDT_288M: + case RTCFDT_288M_1: + device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); + fd->type = FD_1440; + break; + case RTCFDT_360K: + device_set_desc(dev, "360-KB 5.25\" drive"); + fd->type = FD_360; + break; + case RTCFDT_720K: + printf("720-KB 3.5\" drive"); + fd->type = FD_720; + break; + default: + return (ENXIO); + } + return (0); +} + +static int +fd_attach(device_t dev) +{ + struct fd_data *fd; + + fd = device_get_softc(dev); + +#ifdef DEVFS /* XXX bitrot */ + mynor = fdu << 6; + fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d", fdu); + fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d", fdu); + for (i = 1; i < 1 + NUMDENS; i++) { + /* + * XXX this and the lookup in Fdopen() should be + * data driven. + */ + switch (fd->type) { + case FD_360: + if (i != FD_360) + continue; break; - case RTCFDT_288M: - case RTCFDT_288M_1: - printf("2.88MB 3.5in - 1.44MB mode\n"); - fd->type = FD_1440; + case FD_720: + if (i != FD_720 && i != FD_800 && i != FD_820) + continue; break; - case RTCFDT_360K: - printf("360KB 5.25in\n"); - fd->type = FD_360; + case FD_1200: + if (i != FD_360 && i != FD_720 && i != FD_800 + && i != FD_820 && i != FD_1200 + && i != FD_1440 && i != FD_1480) + continue; break; - case RTCFDT_720K: - printf("720KB 3.5in\n"); - fd->type = FD_720; + case FD_1440: + if (i != FD_720 && i != FD_800 && i != FD_820 + && i != FD_1200 && i != FD_1440 + && i != FD_1480 && i != FD_1720) + continue; break; - default: - printf("unknown\n"); - fd->type = NO_TYPE; - continue; } -#ifdef DEVFS - mynor = fdu << 6; - fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d", fdu); - fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d", fdu); - for (i = 1; i < 1 + NUMDENS; i++) { - /* - * XXX this and the lookup in Fdopen() should be - * data driven. - */ - switch (fd->type) { - case FD_360: - if (i != FD_360) - continue; - break; - case FD_720: - if (i != FD_720 && i != FD_800 && i != FD_820) - continue; - break; - case FD_1200: - if (i != FD_360 && i != FD_720 && i != FD_800 - && i != FD_820 && i != FD_1200 - && i != FD_1440 && i != FD_1480) - continue; - break; - case FD_1440: - if (i != FD_720 && i != FD_800 && i != FD_820 - && i != FD_1200 && i != FD_1440 - && i != FD_1480 && i != FD_1720) - continue; - break; - } - typesize = fd_types[i - 1].size / 2; - /* - * XXX all these conversions give bloated code and - * confusing names. - */ - if (typesize == 1476) - typesize = 1480; - if (typesize == 1722) - typesize = 1720; - typemynor = mynor | i; - fd->bdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d.%d", fdu, typesize); - fd->cdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d.%d", fdu, typesize); - } - - for (i = 0; i < MAXPARTITIONS; i++) { - fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], - "fd%d%c", fdu, 'a' + i); - fd->cdevs[1 + NUMDENS + i] = - devfs_makelink(fd->cdevs[0], - "rfd%d%c", fdu, 'a' + i); - } -#endif /* DEVFS */ + typesize = fd_types[i - 1].size / 2; /* - * Export the drive to the devstat interface. + * XXX all these conversions give bloated code and + * confusing names. */ - devstat_add_entry(&fd->device_stats, "fd", - fdu, 512, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, - DEVSTAT_PRIORITY_FD); - + if (typesize == 1476) + typesize = 1480; + if (typesize == 1722) + typesize = 1720; + typemynor = mynor | i; + fd->bdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d.%d", fdu, typesize); + fd->cdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d.%d", fdu, typesize); } - return (1); + for (i = 0; i < MAXPARTITIONS; i++) { + fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], + "fd%d%c", fdu, 'a' + i); + fd->cdevs[1 + NUMDENS + i] = + devfs_makelink(fd->cdevs[0], + "rfd%d%c", fdu, 'a' + i); + } +#endif /* DEVFS */ + /* + * Export the drive to the devstat interface. + */ + devstat_add_entry(&fd->device_stats, device_get_name(dev), + device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, + DEVSTAT_PRIORITY_FD); + return (0); } - - #ifdef FDC_YE /* * this is a subset of fdattach() optimized for the Y-E Data @@ -1016,9 +1097,9 @@ static int yeattach(struct isa_device *dev) /* remember to not deselect the drive we're working on */ /****************************************************************************/ static void -set_motor(fdcu_t fdcu, int fdsu, int turnon) +set_motor(struct fdc_data *fdc, int fdsu, int turnon) { - int fdout = fdc_data[fdcu].fdout; + int fdout = fdc->fdout; int needspecify = 0; if(turnon) { @@ -1038,83 +1119,78 @@ set_motor(fdcu_t fdcu, int fdsu, int turnon) fdout |= (FDO_FRST|FDO_FDMAEN); } - outb(fdc_data[fdcu].baseport+FDOUT, fdout); - fdc_data[fdcu].fdout = fdout; + outb(fdc->baseport+FDOUT, fdout); + fdc->fdout = fdout; TRACE1("[0x%x->FDOUT]", fdout); - if(needspecify) { + if (needspecify) { /* * XXX * special case: since we have just woken up the FDC * from its sleep, we silently assume the command will * be accepted, and do not test for a timeout */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); - if (fdc_data[fdcu].flags & FDC_HAS_FIFO) - (void) enable_fifo(&fdc_data[fdcu]); + if (fdc->flags & FDC_HAS_FIFO) + (void) enable_fifo(fdc); } } static void -fd_turnoff(void *arg1) +fd_turnoff(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; - fd_p fd = fd_data + fdu; + fd_p fd = xfd; - TRACE1("[fd%d: turnoff]", fdu); + TRACE1("[fd%d: turnoff]", fd->fdu); /* * Don't turn off the motor yet if the drive is active. * XXX shouldn't even schedule turnoff until drive is inactive * and nothing is queued on it. */ - if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { - fd->toffhandle = timeout(fd_turnoff, arg1, 4 * hz); + if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); return; } s = splbio(); fd->flags &= ~FD_MOTOR; - set_motor(fd->fdc->fdcu, fd->fdsu, TURNOFF); + set_motor(fd->fdc, fd->fdsu, TURNOFF); splx(s); } static void -fd_motor_on(void *arg1) +fd_motor_on(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; + fd_p fd = xfd; - fd_p fd = fd_data + fdu; s = splbio(); fd->flags &= ~FD_MOTOR_WAIT; if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) { - fdintr(fd->fdc->fdcu); + fdc_intr(fd->fdc); } splx(s); } static void -fd_turnon(fdu_t fdu) +fd_turnon(fd_p fd) { - fd_p fd = fd_data + fdu; if(!(fd->flags & FD_MOTOR)) { fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); - set_motor(fd->fdc->fdcu, fd->fdsu, TURNON); - timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ + set_motor(fd->fdc, fd->fdsu, TURNON); + timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ } } static void fdc_reset(fdc_p fdc) { - fdcu_t fdcu = fdc->fdcu; - /* Try a reset, keep motor on */ outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); @@ -1127,7 +1203,7 @@ fdc_reset(fdc_p fdc) TRACE1("[0x%x->FDOUT]", fdc->fdout); /* XXX after a reset, silently believe the FDC will accept commands */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); if (fdc->flags & FDC_HAS_FIFO) @@ -1138,16 +1214,16 @@ fdc_reset(fdc_p fdc) /* fdc in/out */ /****************************************************************************/ int -in_fdc(fdcu_t fdcu) +in_fdc(struct fdc_data *fdc) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1161,16 +1237,16 @@ in_fdc(fdcu_t fdcu) * fd_in: Like in_fdc, but allows you to see if it worked. */ static int -fd_in(fdcu_t fdcu, int *ptr) +fd_in(struct fdc_data *fdc, int *ptr) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1185,21 +1261,21 @@ fd_in(fdcu_t fdcu, int *ptr) } int -out_fdc(fdcu_t fdcu, int x) +out_fdc(struct fdc_data *fdc, int x) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i; /* Check that the direction bit is set */ i = 100000; while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); - if (i <= 0) return fdc_err(fdcu, "direction bit not set\n"); + if (i <= 0) return fdc_err(fdc, "direction bit not set\n"); /* Check that the floppy controller is ready for a command */ i = 100000; while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); if (i <= 0) - return fdc_err(fdcu, bootverbose? "output ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "output ready timeout\n": 0); /* Send the command and return */ outb(baseport+FDDATA, x); @@ -1215,32 +1291,33 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); int type = FDTYPE(minor(dev)); + fd_p fd; fdc_p fdc; /* check bounds */ - if (fdu >= NFD) - return(ENXIO); - fdc = fd_data[fdu].fdc; - if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) - return(ENXIO); + if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0) + return (ENXIO); + fdc = fd->fdc; + if ((fdc == NULL) || (fd->type == NO_TYPE)) + return (ENXIO); if (type > NUMDENS) - return(ENXIO); + return (ENXIO); if (type == 0) - type = fd_data[fdu].type; + type = fd->type; else { /* * For each type of basic drive, make sure we are trying * to open a type it can do, */ - if (type != fd_data[fdu].type) { - switch (fd_data[fdu].type) { + if (type != fd->type) { + switch (fd->type) { case FD_360: - return(ENXIO); + return (ENXIO); case FD_720: if ( type != FD_820 && type != FD_800 ) - return(ENXIO); + return (ENXIO); break; case FD_1200: switch (type) { @@ -1279,9 +1356,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) } } } - fd_data[fdu].ft = fd_types + type - 1; - fd_data[fdu].flags |= FD_OPEN; - + fd->ft = fd_types + type - 1; + fd->flags |= FD_OPEN; + device_busy(fd->dev); + device_busy(fd->fdc->fdc_dev); return 0; } @@ -1289,11 +1367,13 @@ int fdclose(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); + struct fd_data *fd; - fd_data[fdu].flags &= ~FD_OPEN; - fd_data[fdu].options &= ~FDOPT_NORETRY; + fd = devclass_get_softc(fd_devclass, fdu); + fd->flags &= ~FD_OPEN; + fd->options &= ~FDOPT_NORETRY; - return(0); + return (0); } static int @@ -1317,16 +1397,17 @@ fdstrategy(struct buf *bp) { unsigned nblocks, blknum, cando; int s; - fdcu_t fdcu; fdu_t fdu; fdc_p fdc; fd_p fd; size_t fdblk; fdu = FDUNIT(minor(bp->b_dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); + if (fd == 0) + panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", + (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev)); fdc = fd->fdc; - fdcu = fdc->fdcu; #ifdef FDC_YE if (fd->type == NO_TYPE) { bp->b_error = ENXIO; @@ -1341,7 +1422,7 @@ fdstrategy(struct buf *bp) fdblk = 128 << (fd->ft->secsize); if (!(bp->b_flags & B_FORMAT)) { - if ((fdu >= NFD) || (bp->b_blkno < 0)) { + if (bp->b_blkno < 0) { printf( "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", fdu, (u_long)bp->b_blkno, bp->b_bcount); @@ -1386,12 +1467,12 @@ fdstrategy(struct buf *bp) bp->b_pblkno = bp->b_blkno; s = splbio(); bufqdisksort(&fdc->head, bp); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */ + untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ /* Tell devstat we are starting on the transaction */ devstat_start_transaction(&fd->device_stats); - fdstart(fdcu); + fdstart(fdc); splx(s); return; @@ -1409,27 +1490,25 @@ bad: * will pick up our work when the present work completes * \***************************************************************/ static void -fdstart(fdcu_t fdcu) +fdstart(struct fdc_data *fdc) { int s; s = splbio(); - if(fdc_data[fdcu].state == DEVIDLE) + if(fdc->state == DEVIDLE) { - fdintr(fdcu); + fdc_intr(fdc); } splx(s); } static void -fd_iotimeout(void *arg1) +fd_iotimeout(void *xfdc) { fdc_p fdc; - fdcu_t fdcu; int s; - fdcu = (fdcu_t)arg1; - fdc = fdc_data + fdcu; + fdc = xfdc; TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* @@ -1447,19 +1526,18 @@ fd_iotimeout(void *arg1) fdc->status[0] = NE7_ST0_IC_IV; fdc->flags &= ~FDC_STAT_VALID; fdc->state = IOTIMEDOUT; - fdintr(fdcu); + fdc_intr(fdc); splx(s); } /* just ensure it has the right spl */ static void -fd_pseudointr(void *arg1) +fd_pseudointr(void *xfdc) { - fdcu_t fdcu = (fdcu_t)arg1; int s; s = splbio(); - fdintr(fdcu); + fdc_intr(xfdc); splx(s); } @@ -1469,11 +1547,11 @@ fd_pseudointr(void *arg1) * ALWAYS called at SPLBIO * \***********************************************************************/ static void -fdintr(fdcu_t fdcu) +fdc_intr(void *xfdc) { - fdc_p fdc = fdc_data + fdcu; - while(fdstate(fdcu, fdc)) - ; + fdc_p fdc = xfdc; + while(fdstate(fdc)) + ; } #ifdef FDC_YE @@ -1513,7 +1591,7 @@ static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) * if it returns a non zero value, it should be called again immediatly * \***********************************************************************/ static int -fdstate(fdcu_t fdcu, fdc_p fdc) +fdstate(fdc_p fdc) { int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; @@ -1537,26 +1615,25 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * Force into the IDLE state, * \***********************************************/ fdc->state = DEVIDLE; - if(fdc->fd) - { - printf("fd%d: unexpected valid fd pointer\n", - fdc->fdu); + if (fdc->fd) { + device_print_prettyname(fdc->fdc_dev); + printf("unexpected valid fd pointer\n"); fdc->fd = (fd_p) 0; fdc->fdu = -1; } - TRACE1("[fdc%d IDLE]", fdcu); - return(0); + TRACE1("[fdc%d IDLE]", fdc->fdcu); + return (0); } fdu = FDUNIT(minor(bp->b_dev)); - fd = fd_data + fdu; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; - if (fdc->fd && (fd != fdc->fd)) - { - printf("fd%d: confused fd pointers\n", fdu); + if (fdc->fd && (fd != fdc->fd)) { + device_print_prettyname(fd->dev); + printf("confused fd pointers\n"); } read = bp->b_flags & B_READ; format = bp->b_flags & B_FORMAT; - if(format) { + if (format) { finfo = (struct fd_formb *)bp->b_data; fd->skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; @@ -1569,8 +1646,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) TRACE1("fd%d", fdu); TRACE1("[%s]", fdstates[fdc->state]); TRACE1("(0x%x)", fd->flags); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); - fd->toffhandle = timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); + untimeout(fd_turnoff, fd, fd->toffhandle); + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); switch (fdc->state) { case DEVIDLE: @@ -1585,10 +1662,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * If the next drive has a motor startup pending, then * * it will start up in its own good time * \*******************************************************/ - if(fd->flags & FD_MOTOR_WAIT) - { + if(fd->flags & FD_MOTOR_WAIT) { fdc->state = MOTORWAIT; - return(0); /* come back later */ + return (0); /* come back later */ } /*******************************************************\ * Maybe if it's not starting, it SHOULD be starting * @@ -1596,12 +1672,12 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (!(fd->flags & FD_MOTOR)) { fdc->state = MOTORWAIT; - fd_turnon(fdu); - return(0); + fd_turnon(fd); + return (0); } else /* at least make sure we are selected */ { - set_motor(fdcu, fd->fdsu, TURNON); + set_motor(fdc, fd->fdsu, TURNON); } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1615,7 +1691,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = SEEKCOMPLETE; break; } - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, b_cylinder * fd->ft->steptrac, 0)) { @@ -1624,20 +1700,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * the FDC went off to the Saints... */ fdc->retry = 6; /* try a reset */ - return(retrier(fdcu)); + return(retrier(fdc)); } fd->track = FD_NO_TRACK; fdc->state = SEEKWAIT; return(0); /* will return later */ case SEEKWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 16); + timeout(fd_pseudointr, fdc, hz / 16); fdc->state = SEEKCOMPLETE; return(0); /* will return later */ case SEEKCOMPLETE : /* SEEK DONE, START DMA */ /* Make sure seek really happened*/ - if(fd->track == FD_NO_TRACK) - { + if(fd->track == FD_NO_TRACK) { int descyl = b_cylinder * fd->ft->steptrac; do { /* @@ -1669,8 +1744,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) return 0; /* hope for a real intr */ } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); - if (0 == descyl) - { + if (0 == descyl) { int failed = 0; /* * seek to cyl 0 requested; make sure we are @@ -1685,22 +1759,20 @@ fdstate(fdcu_t fdcu, fdc_p fdc) failed = 1; } - if (failed) - { + if (failed) { if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } - if (cyl != descyl) - { + if (cyl != descyl) { printf( "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, descyl, cyl, st0); if (fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } @@ -1726,7 +1798,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; /* reset the beast */ - return(retrier(fdcu)); + return (retrier(fdc)); } if(st3 & NE7_ST3_WP) { @@ -1749,8 +1821,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) } } - if(format) - { + if (format) { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) (void)fdcpio(fdcu,bp->b_flags, @@ -1758,25 +1829,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) bp->b_bcount); #endif /* formatting */ - if(fd_cmd(fdcu, 6, - NE7CMD_FORMAT, - head << 2 | fdu, + if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu, finfo->fd_formb_secshift, finfo->fd_formb_nsecs, finfo->fd_formb_gaplen, - finfo->fd_formb_fillbyte, - 0)) - { + finfo->fd_formb_fillbyte, 0)) { /* controller fell over */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } - } - else - { + } else { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) { /* @@ -1795,7 +1860,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdblk); } #endif - if (fd_cmd(fdcu, 9, + if (fd_cmd(fdc, 9, (read ? NE7CMD_READ : NE7CMD_WRITE), head << 2 | fdu, /* head & unit */ fd->track, /* track */ @@ -1805,14 +1870,13 @@ fdstate(fdcu_t fdcu, fdc_p fdc) sectrac, /* sectors/track */ fd->ft->gap, /* gap size */ fd->ft->datalen, /* data length */ - 0)) - { + 0)) { /* the beast is sleeping again */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } } #ifdef FDC_YE @@ -1834,8 +1898,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ #endif fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); - return(0); /* will return later */ + fd->tohandle = timeout(fd_iotimeout, fdc, hz); + return (0); /* will return later */ #ifdef FDC_YE case PIOREAD: /* @@ -1847,16 +1911,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ #endif case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, fdc, fd->tohandle); - if (fd_read_status(fdc, fd->fdsu)) - { + if (fd_read_status(fdc, fd->fdsu)) { isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ - return retrier(fdcu); + return (retrier(fdc)); } fdc->state = IOTIMEDOUT; @@ -1869,8 +1932,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) #endif isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); - if (fdc->status[0] & NE7_ST0_IC) - { + if (fdc->status[0] & NE7_ST0_IC) { if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT && fdc->status[1] & NE7_ST1_OR) { /* @@ -1890,17 +1952,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc) && fdc->status[2] & NE7_ST2_WC && fdc->retry < 3) fdc->retry = 3; /* force recalibrate */ - return(retrier(fdcu)); + return (retrier(fdc)); } /* All OK */ fd->skip += fdblk; - if (!format && fd->skip < bp->b_bcount - bp->b_resid) - { + if (!format && fd->skip < bp->b_bcount - bp->b_resid) { /* set up next transfer */ fdc->state = DOSEEK; - } - else - { + } else { /* ALL DONE */ fd->skip = 0; fdc->bp = NULL; @@ -1915,7 +1974,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->fdu = -1; fdc->state = FINDWORK; } - return(1); + return (1); case RESETCTLR: fdc_reset(fdc); fdc->retry++; @@ -1931,21 +1990,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = STARTRECAL; /* Fall through. */ case STARTRECAL: - if(fd_cmd(fdcu, - 2, NE7CMD_RECAL, fdu, - 0)) /* Recalibrate Function */ - { + if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { /* arrgl */ fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } fdc->state = RECALWAIT; - return(0); /* will return later */ + return (0); /* will return later */ case RECALWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 8); + timeout(fd_pseudointr, fdc, hz / 8); fdc->state = RECALCOMPLETE; - return(0); /* will return later */ + return (0); /* will return later */ case RECALCOMPLETE: do { /* @@ -1971,16 +2027,16 @@ fdstate(fdcu_t fdcu, fdc_p fdc) printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, st0, NE7_ST0BITS, cyl); if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } fd->track = 0; /* Seek (probably) necessary */ fdc->state = DOSEEK; - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ case MOTORWAIT: if(fd->flags & FD_MOTOR_WAIT) { - return(0); /* time's not up yet */ + return (0); /* time's not up yet */ } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1993,9 +2049,10 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ fdc->state = STARTRECAL; } - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ default: - printf("fdc%d: Unexpected FD int->", fdcu); + device_print_prettyname(fdc->fdc_dev); + printf("unexpected FD int->"); if (fd_read_status(fdc, fd->fdsu) == 0) printf("FDC status :%x %x %x %x %x %x %x ", fdc->status[0], @@ -2010,28 +2067,31 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (fd_sense_int(fdc, &st0, &cyl) != 0) { printf("[controller is dead now]\n"); - return(0); + return (0); } printf("ST0 = %x, PCN = %x\n", st0, cyl); - return(0); + return (0); } /*XXX confusing: some branches return immediately, others end up here*/ - return(1); /* Come back immediatly to new state */ + return (1); /* Come back immediatly to new state */ } static int -retrier(fdcu) - fdcu_t fdcu; +retrier(struct fdc_data *fdc) { - fdc_p fdc = fdc_data + fdcu; register struct buf *bp; + struct fd_data *fd; + int fdu; bp = fdc->bp; - if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) + /* XXX shouldn't this be cached somewhere? */ + fdu = FDUNIT(minor(bp->b_dev)); + fd = devclass_get_softc(fd_devclass, fdu); + if (fd->options & FDOPT_NORETRY) goto fail; - switch(fdc->retry) - { + + switch (fdc->retry) { case 0: case 1: case 2: fdc->state = SEEKCOMPLETE; break; @@ -2084,10 +2144,10 @@ retrier(fdcu) fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - return(1); + return (1); } fdc->retry++; - return(1); + return (1); } static int @@ -2104,7 +2164,7 @@ fdformat(dev, finfo, p) size_t fdblk; fdu = FDUNIT(minor(dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; /* set up a buffer header for fdstrategy() */ @@ -2135,20 +2195,19 @@ fdformat(dev, finfo, p) /* ...and wait for it to complete */ s = splbio(); - while(!(bp->b_flags & B_DONE)) - { + while(!(bp->b_flags & B_DONE)) { rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); - if(rv == EWOULDBLOCK) + if (rv == EWOULDBLOCK) break; } splx(s); - if(rv == EWOULDBLOCK) { + if (rv == EWOULDBLOCK) { /* timed out */ rv = EIO; biodone(bp); } - if(bp->b_flags & B_ERROR) + if (bp->b_flags & B_ERROR) rv = bp->b_error; /* * allow the process to be swapped @@ -2171,7 +2230,7 @@ fdioctl(dev, cmd, addr, flag, p) struct proc *p; { fdu_t fdu = FDUNIT(minor(dev)); - fd_p fd = &fd_data[fdu]; + fd_p fd = devclass_get_softc(fd_devclass, fdu); size_t fdblk; struct fd_type *fdt; @@ -2181,13 +2240,12 @@ fdioctl(dev, cmd, addr, flag, p) fdblk = 128 << fd->ft->secsize; - switch (cmd) - { + switch (cmd) { case DIOCGDINFO: bzero(buffer, sizeof (buffer)); dl = (struct disklabel *)buffer; dl->d_secsize = fdblk; - fdt = fd_data[FDUNIT(minor(dev))].ft; + fdt = fd->ft; dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; @@ -2211,8 +2269,7 @@ fdioctl(dev, cmd, addr, flag, p) break; case DIOCWDINFO: - if ((flag & FWRITE) == 0) - { + if ((flag & FWRITE) == 0) { error = EBADF; break; } @@ -2227,9 +2284,9 @@ fdioctl(dev, cmd, addr, flag, p) (struct disklabel *)buffer); break; case FD_FORM: - if((flag & FWRITE) == 0) + if ((flag & FWRITE) == 0) error = EBADF; /* must be opened for writing */ - else if(((struct fd_formb *)addr)->format_version != + else if (((struct fd_formb *)addr)->format_version != FD_FORMAT_VERSION) error = EINVAL; /* wrong version of formatting prog */ else @@ -2242,7 +2299,7 @@ fdioctl(dev, cmd, addr, flag, p) case FD_STYPE: /* set drive type */ /* this is considered harmful; only allow for superuser */ - if(suser(p->p_ucred, &p->p_acflag) != 0) + if (suser(p->p_ucred, &p->p_acflag) != 0) return EPERM; *fd->ft = *(struct fd_type *)addr; break; @@ -2262,22 +2319,62 @@ fdioctl(dev, cmd, addr, flag, p) return (error); } +static device_method_t fdc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fdc_probe), + DEVMETHOD(device_attach, fdc_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), -static fd_devsw_installed = 0; + /* Bus interface */ + DEVMETHOD(bus_print_child, fdc_print_child), + /* Our children never use any other bus interface methods. */ -static void fd_drvinit(void *notused ) -{ + { 0, 0 } +}; - if( ! fd_devsw_installed ) { - cdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &fd_cdevsw); - fd_devsw_installed = 1; - } -} +static driver_t fdc_driver = { + "fdc", + fdc_methods, + DRIVER_TYPE_BIO, + sizeof(struct fdc_data) +}; -SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL) +DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0); +static device_method_t fd_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fd_probe), + DEVMETHOD(device_attach, fd_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */ + DEVMETHOD(device_resume, bus_generic_resume), /* XXX */ -#endif + { 0, 0 } +}; + +static driver_t fd_driver = { + "fd", + fd_methods, + DRIVER_TYPE_BIO, + sizeof(struct fd_data) +}; + +static struct cdevsw fd_cdevsw = { + Fdopen, fdclose, fdread, fdwrite, + fdioctl, nostop, nullreset, nodevtotty, + seltrue, nommap, fdstrategy, "fd", + NULL, -1, nodump, nopsize, + D_DISK, 0, -1 +}; + +BDEV_DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, BDEV_MAJOR, CDEV_MAJOR, + fd_cdevsw, 0, 0); + +#endif /* NFDC > 0 */ /* * Hello emacs, these are the diff --git a/sys/i386/isa/fdc.h b/sys/i386/isa/fdc.h index 43bf9f8..83e291f 100644 --- a/sys/i386/isa/fdc.h +++ b/sys/i386/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.12 1998/12/12 08:16:01 imp Exp $ + * $Id: fdc.h,v 1.13 1999/01/15 09:15:27 bde Exp $ * */ @@ -70,6 +70,10 @@ struct fdc_data int fdc_errs; /* number of logged errors */ struct buf_queue_head head; struct buf *bp; /* active buffer */ + struct resource *res_ioport, *res_irq, *res_drq; + int rid_ioport, rid_irq, rid_drq; + void *fdc_intr; + struct device *fdc_dev; }; /***********************************************************************\ diff --git a/sys/i386/isa/if_cs.c b/sys/i386/isa/if_cs.c index 4a9c390..f96f024 100644 --- a/sys/i386/isa/if_cs.c +++ b/sys/i386/isa/if_cs.c @@ -27,7 +27,7 @@ */ /* - * $Id: if_cs.c,v 1.8 1999/01/12 00:27:43 eivind Exp $ + * $Id: if_cs.c,v 1.9 1999/01/28 01:59:53 dillon Exp $ * * Device driver for Crystal Semiconductor CS8920 based ethernet * adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997 @@ -1352,7 +1352,6 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, int iobase, unit, flags; u_int irq; int drq; - struct isa_device *dvp; struct cs_softc *sc = malloc(sizeof *sc, M_DEVBUF, M_NOWAIT); if (read_pnp_parms ( &d , ldn ) == 0 ) { @@ -1373,9 +1372,7 @@ cs_pnp_attach(u_long csn, u_long vend_id, char *name, if (dev->id_driver == NULL) { dev->id_driver = &csdriver; - dvp = find_isadev(isa_devtab_net, &csdriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if (!sc) return; diff --git a/sys/i386/isa/if_ed.c b/sys/i386/isa/if_ed.c index 1408b2b..29bb9d1 100644 --- a/sys/i386/isa/if_ed.c +++ b/sys/i386/isa/if_ed.c @@ -24,7 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_ed.c,v 1.149 1999/01/28 01:59:53 dillon Exp $ + * $Id: if_ed.c,v 1.150 1999/03/17 16:44:51 luigi Exp $ */ /* @@ -3488,7 +3488,6 @@ static void edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NEDTOT) return; @@ -3509,9 +3508,7 @@ edpnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &eddriver; - dvp = find_isadev(isa_devtab_net, &eddriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = ed_probe(dev)) != 0) diff --git a/sys/i386/isa/intr_machdep.c b/sys/i386/isa/intr_machdep.c index 944eb4e..4f7c1e9 100644 --- a/sys/i386/isa/intr_machdep.c +++ b/sys/i386/isa/intr_machdep.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.16 1999/01/08 19:17:48 bde Exp $ + * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $ */ #include "opt_auto_eoi.h" @@ -328,6 +328,7 @@ isa_get_nameunit(int id) return ("clk0"); /* XXX may also be sloppy driver */ if (id == 1) return ("rtc0"); +#if 0 for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; @@ -343,6 +344,7 @@ isa_get_nameunit(int id) for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; +#endif return "???"; found_device: diff --git a/sys/i386/isa/isa.c b/sys/i386/isa/isa.c index 1e91da8..4b48e36 100644 --- a/sys/i386/isa/isa.c +++ b/sys/i386/isa/isa.c @@ -1,10 +1,7 @@ /*- - * Copyright (c) 1991 The Regents of the University of California. + * Copyright (c) 1998 Doug Rabson * All rights reserved. * - * This code is derived from software contributed to Berkeley by - * William Jolitz. - * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -13,18 +10,11 @@ * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) @@ -33,1041 +23,601 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $ + * $Id: isa.c,v 1.4 1998/09/16 08:23:51 dfr Exp $ */ /* - * code to manage AT bus + * Modifications for Intel architecture by Garrett A. Wollman. + * Copyright 1998 Massachusetts Institute of Technology * - * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): - * Fixed uninitialized variable problem and added code to deal - * with DMA page boundaries in isa_dmarangecheck(). Fixed word - * mode DMA count compution and reorganized DMA setup code in - * isa_dmastart() + * Permission to use, copy, modify, and distribute this software and + * its documentation for any purpose and without fee is hereby + * granted, provided that both the above copyright notice and this + * permission notice appear in all copies, that both the above + * copyright notice and this permission notice appear in all + * supporting documentation, and that the name of M.I.T. not be used + * in advertising or publicity pertaining to distribution of the + * software without specific, written prior permission. M.I.T. makes + * no representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied + * warranty. + * + * THIS SOFTWARE IS PROVIDED BY M.I.T. ``AS IS''. M.I.T. DISCLAIMS + * ALL EXPRESS OR IMPLIED WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT + * SHALL M.I.T. BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. */ #include <sys/param.h> #include <sys/systm.h> -#include <sys/buf.h> +#include <sys/kernel.h> +#include <sys/bus.h> #include <sys/malloc.h> -#include <machine/ipl.h> -#include <machine/md_var.h> -#ifdef APIC_IO -#include <machine/smp.h> -#endif /* APIC_IO */ -#include <vm/vm.h> -#include <vm/vm_param.h> -#include <vm/pmap.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/intr_machdep.h> -#include <i386/isa/isa.h> -#include <i386/isa/ic/i8237.h> - -#include <sys/interrupt.h> - -#include "pnp.h" -#if NPNP > 0 -#include <i386/isa/pnp.h> -#endif +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> -/* -** Register definitions for DMA controller 1 (channels 0..3): -*/ -#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ -#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ -#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ -#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ +#include <machine/resource.h> -/* -** Register definitions for DMA controller 2 (channels 4..7): -*/ -#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ -#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ -#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ -#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ +#include <isa/isavar.h> -static void config_isadev __P((struct isa_device *isdp, u_int *mp)); -static void config_isadev_c __P((struct isa_device *isdp, u_int *mp, - int reconfig)); -static void conflict __P((struct isa_device *dvp, struct isa_device *tmpdvp, - int item, char const *whatnot, char const *reason, - char const *format)); -static int haveseen __P((struct isa_device *dvp, struct isa_device *tmpdvp, - u_int checkbits)); -static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); +MALLOC_DEFINE(M_ISADEV, "isadev", "ISA device"); /* - * print a conflict message + * The structure used to attach devices to the isa bus. */ +struct isa_device { + short 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; + static void -conflict(dvp, tmpdvp, item, whatnot, reason, format) - struct isa_device *dvp; - struct isa_device *tmpdvp; - int item; - char const *whatnot; - char const *reason; - char const *format; +isa_add_device(device_t dev, const char *name, int unit) { - printf("%s%d not %sed due to %s conflict with %s%d at ", - dvp->id_driver->name, dvp->id_unit, whatnot, reason, - tmpdvp->id_driver->name, tmpdvp->id_unit); - printf(format, item); - printf("\n"); -} + struct isa_device *idev; + device_t child; + int sensitive, t; + static device_t last_sensitive; -/* - * Check to see if things are already in use, like IRQ's, I/O addresses - * and Memory addresses. - */ -static int -haveseen(dvp, tmpdvp, checkbits) - struct isa_device *dvp; - struct isa_device *tmpdvp; - u_int checkbits; -{ - /* - * Ignore all conflicts except IRQ ones if conflicts are allowed. - */ - if (dvp->id_conflicts) - checkbits &= ~(CC_DRQ | CC_IOADDR | CC_MEMADDR); - /* - * Only check against devices that have already been found. - */ - if (tmpdvp->id_alive) { - char const *whatnot; + if (resource_int_value(name, unit, "sensitive", &sensitive) != 0) + sensitive = 0; - /* - * Check for device driver & unit conflict; just drop probing - * a device which has already probed true. This is usually - * not strictly a conflict, but rather the case of somebody - * having specified several mutually exclusive configurations - * for a single device. - */ - if (tmpdvp->id_driver == dvp->id_driver && - tmpdvp->id_unit == dvp->id_unit) { - return 1; - } + idev = malloc(sizeof(struct isa_device), M_ISADEV, M_NOWAIT); + if (!idev) + return; + bzero(idev, sizeof *idev); - whatnot = checkbits & CC_ATTACH ? "attach" : "prob"; - /* - * Check for I/O address conflict. We can only check the - * starting address of the device against the range of the - * device that has already been probed since we do not - * know how many I/O addresses this device uses. - */ - if (checkbits & CC_IOADDR && tmpdvp->id_alive != -1) { - if ((dvp->id_iobase >= tmpdvp->id_iobase) && - (dvp->id_iobase <= - (tmpdvp->id_iobase + tmpdvp->id_alive - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_iobase, - whatnot, "I/O address", "0x%x"); - return 1; - } - } - /* - * Check for Memory address conflict. We can check for - * range overlap, but it will not catch all cases since the - * driver may adjust the msize paramater during probe, for - * now we just check that the starting address does not - * fall within any allocated region. - * XXX could add a second check after the probe for overlap, - * since at that time we would know the full range. - * XXX KERNBASE is a hack, we should have vaddr in the table! - */ - if (checkbits & CC_MEMADDR && tmpdvp->id_maddr) { - if ((KERNBASE + dvp->id_maddr >= tmpdvp->id_maddr) && - (KERNBASE + dvp->id_maddr <= - (tmpdvp->id_maddr + tmpdvp->id_msize - 1))) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - (int)dvp->id_maddr, whatnot, - "maddr", "0x%x"); - return 1; - } - } - /* - * Check for IRQ conflicts. - */ - if (checkbits & CC_IRQ && tmpdvp->id_irq) { - if (tmpdvp->id_irq == dvp->id_irq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, - ffs(dvp->id_irq) - 1, whatnot, - "irq", "%d"); - return 1; - } - } - /* - * Check for DRQ conflicts. - */ - if (checkbits & CC_DRQ && tmpdvp->id_drq != -1) { - if (tmpdvp->id_drq == dvp->id_drq) { - if (!(checkbits & CC_QUIET)) - conflict(dvp, tmpdvp, dvp->id_drq, - whatnot, "drq", "%d"); - return 1; - } - } - } - return 0; -} + if (resource_int_value(name, unit, "port", &t) == 0) + idev->id_port[0] = t; + else + idev->id_port[0] = -1; + idev->id_port[1] = 0; -#ifdef RESOURCE_CHECK -#include <sys/drvresource.h> + if (resource_int_value(name, unit, "portsize", &t) == 0) + idev->id_portsize[0] = t; + else + idev->id_portsize[0] = 0; + idev->id_portsize[1] = 0; -static int -checkone (struct isa_device *dvp, int type, addr_t low, addr_t high, - char *resname, char *resfmt, int attaching) -{ - int result = 0; - if (bootverbose) { - if (low == high) - printf("\tcheck %s: 0x%x\n", resname, low); - else - printf("\tcheck %s: 0x%x to 0x%x\n", - resname, low, high); - } - if (resource_check(type, RESF_NONE, low, high) != NULL) { - char *whatnot = attaching ? "attach" : "prob"; - static struct isa_device dummydev; - static struct isa_driver dummydrv; - struct isa_device *tmpdvp = &dummydev; + if (resource_int_value(name, unit, "maddr", &t) == 0) + idev->id_maddr[0] = t; + else + idev->id_maddr[0] = 0; + idev->id_maddr[1] = 0; - dummydev.id_driver = &dummydrv; - dummydev.id_unit = 0; - dummydrv.name = "pci"; - conflict(dvp, tmpdvp, low, whatnot, resname, resfmt); - result = 1; - } else if (attaching) { - if (low == high) - printf("\tregister %s: 0x%x\n", resname, low); - else - printf("\tregister %s: 0x%x to 0x%x\n", - resname, low, high); - resource_claim(dvp, type, RESF_NONE, low, high); - } - return (result); -} + if (resource_int_value(name, unit, "msize", &t) == 0) + idev->id_msize[0] = t; + else + idev->id_msize[0] = 0; + idev->id_msize[1] = 0; -static int -check_pciconflict(struct isa_device *dvp, int checkbits) -{ - int result = 0; - int attaching = (checkbits & CC_ATTACH) != 0; + if (resource_int_value(name, unit, "flags", &t) == 0) + idev->id_flags = t; + else + idev->id_flags = 0; - if (checkbits & CC_MEMADDR) { - long maddr = dvp->id_maddr; - long msize = dvp->id_msize; - if (msize > 0) { - if (checkone(dvp, REST_MEM, maddr, maddr + msize - 1, - "maddr", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IOADDR) { - unsigned iobase = dvp->id_iobase; - unsigned iosize = dvp->id_alive; - if (iosize == -1) - iosize = 1; /* XXX can't do much about this ... */ - if (iosize > 0) { - if (checkone(dvp, REST_PORT, iobase, iobase + iosize -1, - "I/O address", "0x%x", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_IRQ) { - int irq = ffs(dvp->id_irq) - 1; - if (irq >= 0) { - if (checkone(dvp, REST_INT, irq, irq, - "irq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (checkbits & CC_DRQ) { - int drq = dvp->id_drq; - if (drq >= 0) { - if (checkone(dvp, REST_DMA, drq, drq, - "drq", "%d", attaching) != 0) { - result = 1; - attaching = 0; - } - } - } - if (result != 0) - resource_free (dvp); - return (result); -} -#endif /* RESOURCE_CHECK */ + if (resource_int_value(name, unit, "irq", &t) == 0) + idev->id_irq[0] = t; + else + idev->id_irq[0] = -1; + idev->id_irq[1] = -1; -/* - * Search through all the isa_devtab_* tables looking for anything that - * conflicts with the current device. - */ -int -haveseen_isadev(dvp, checkbits) - struct isa_device *dvp; - u_int checkbits; -{ -#if NPNP > 0 - struct pnp_dlist_node *nod; -#endif - struct isa_device *tmpdvp; - int status = 0; + if (resource_int_value(name, unit, "drq", &t) == 0) + idev->id_drq[0] = t; + else + idev->id_drq[0] = -1; + idev->id_drq[1] = -1; - for (tmpdvp = isa_devtab_tty; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_bio; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_net; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_cam; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } - for (tmpdvp = isa_devtab_null; tmpdvp->id_driver; tmpdvp++) { - status |= haveseen(dvp, tmpdvp, checkbits); - if (status) - return status; - } -#if NPNP > 0 - for (nod = pnp_device_list; nod != NULL; nod = nod->next) - if (status |= haveseen(dvp, &(nod->dev), checkbits)) - return status; -#endif -#ifdef RESOURCE_CHECK - if (!dvp->id_conflicts) - status = check_pciconflict(dvp, checkbits); - else if (bootverbose) - printf("\tnot checking for resource conflicts ...\n"); -#endif /* RESOURCE_CHECK */ - return(status); + if (sensitive) + child = device_add_child_after(dev, last_sensitive, name, + unit, idev); + else + child = device_add_child(dev, name, unit, idev); + if (child == 0) + return; + else if (sensitive) + last_sensitive = child; + + if (resource_int_value(name, unit, "disabled", &t) == 0 && t != 0) + device_disable(child); } /* - * Configure all ISA devices + * 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. */ -void -isa_configure() +static int +isa_probe(device_t dev) { - struct isa_device *dvp; + int i; + static char buf[] = "isaXXX"; - printf("Probing for devices on the ISA bus:\n"); - /* First probe all the sensitive probes */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - - /* Then all the bad ones */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, &cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - if (!dvp->id_driver->sensitive_hw) - config_isadev(dvp, (u_int *)NULL); - -/* - * XXX we should really add the tty device to net_imask when the line is - * switched to SLIPDISC, and then remove it when it is switched away from - * SLIPDISC. No need to block out ALL ttys during a splimp when only one - * of them is running slip. - * - * XXX actually, blocking all ttys during a splimp doesn't matter so much - * with sio because the serial interrupt layer doesn't use tty_imask. Only - * non-serial ttys suffer. It's more stupid that ALL 'net's are blocked - * during spltty. - */ -#include "sl.h" -#if NSL > 0 - net_imask |= tty_imask; - tty_imask = net_imask; -#endif - - if (bootverbose) - printf("imasks: bio %x, tty %x, net %x\n", - bio_imask, tty_imask, net_imask); + device_set_desc(dev, "ISA bus"); /* - * Finish initializing intr_mask[]. Note that the partly - * constructed masks aren't actually used since we're at splhigh. - * For fully dynamic initialization, register_intr() and - * icu_unset() will have to adjust the masks for _all_ - * interrupts and for tty_imask, etc. + * Add all devices configured to be attached to isa0. */ - for (dvp = isa_devtab_tty; dvp->id_driver; dvp++) - register_imask(dvp, tty_imask); - for (dvp = isa_devtab_bio; dvp->id_driver; dvp++) - register_imask(dvp, bio_imask); - for (dvp = isa_devtab_net; dvp->id_driver; dvp++) - register_imask(dvp, net_imask); - for (dvp = isa_devtab_cam; dvp->id_driver; dvp++) - register_imask(dvp, cam_imask); - for (dvp = isa_devtab_null; dvp->id_driver; dvp++) - register_imask(dvp, SWI_CLOCK_MASK); -} - -/* - * Configure an ISA device. - */ -static void -config_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 0); -} - -void -reconfig_isadev(isdp, mp) - struct isa_device *isdp; - u_int *mp; -{ - config_isadev_c(isdp, mp, 1); -} - -static void -config_isadev_c(isdp, mp, reconfig) - struct isa_device *isdp; - u_int *mp; - int reconfig; -{ - u_int checkbits; - int id_alive; - int last_alive; - struct isa_driver *dp = isdp->id_driver; - - if (!isdp->id_enabled) { - if (bootverbose) - printf("%s%d: disabled, not probed.\n", dp->name, isdp->id_unit); - return; + sprintf(buf, "isa%d", device_get_unit(dev)); + for (i = resource_query_string(-1, "at", buf); + i != -1; + i = resource_query_string(i, "at", buf)) { + isa_add_device(dev, resource_query_name(i), + resource_query_unit(i)); } - checkbits = CC_DRQ | CC_IOADDR | CC_MEMADDR; - if (!reconfig && haveseen_isadev(isdp, checkbits)) - return; - if (!reconfig && isdp->id_maddr) { - isdp->id_maddr -= ISA_HOLE_START; - isdp->id_maddr += atdevbase; - } - if (reconfig) { - last_alive = isdp->id_alive; - isdp->id_reconfig = 1; - } - else { - last_alive = 0; - isdp->id_reconfig = 0; - } - id_alive = (*dp->probe)(isdp); - if (id_alive) { - /* - * Only print the I/O address range if id_alive != -1 - * Right now this is a temporary fix just for the new - * NPX code so that if it finds a 486 that can use trap - * 16 it will not report I/O addresses. - * Rod Grimes 04/26/94 - */ - if (!isdp->id_reconfig) { - printf("%s%d", dp->name, isdp->id_unit); - if (id_alive != -1) { - if (isdp->id_iobase == -1) - printf(" at"); - else { - printf(" at 0x%x", isdp->id_iobase); - if (isdp->id_iobase + id_alive - 1 != - isdp->id_iobase) { - printf("-0x%x", - isdp->id_iobase + id_alive - 1); - } - } - } - if (isdp->id_irq) - printf(" irq %d", ffs(isdp->id_irq) - 1); - if (isdp->id_drq != -1) - printf(" drq %d", isdp->id_drq); - if (isdp->id_maddr) - printf(" maddr 0x%lx", kvtop(isdp->id_maddr)); - if (isdp->id_msize) - printf(" msize %d", isdp->id_msize); - if (isdp->id_flags) - printf(" flags 0x%x", isdp->id_flags); - if (isdp->id_iobase && !(isdp->id_iobase & 0xf300)) { - printf(" on motherboard"); - } else if (isdp->id_iobase >= 0x1000 && - !(isdp->id_iobase & 0x300)) { - printf (" on eisa slot %d", - isdp->id_iobase >> 12); - } else { - printf (" on isa"); - } - printf("\n"); - /* - * Check for conflicts again. The driver may have - * changed *dvp. We should weaken the early check - * since the driver may have been able to change - * *dvp to avoid conflicts if given a chance. We - * already skip the early check for IRQs and force - * a check for IRQs in the next group of checks. - */ - checkbits |= CC_ATTACH | CC_IRQ; - if (haveseen_isadev(isdp, checkbits)) - return; - isdp->id_alive = id_alive; - } - (*dp->attach)(isdp); - if (isdp->id_irq != 0 && isdp->id_intr == NULL) - printf("%s%d: irq with no handler\n", - dp->name, isdp->id_unit); - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { -#ifdef APIC_IO - /* - * Some motherboards use upper IRQs for traditional - * ISA INTerrupt sources. In particular we have - * seen the secondary IDE connected to IRQ20. - * This code detects and fixes this situation. - */ - u_int apic_mask; - int rirq; - apic_mask = isa_apic_mask(isdp->id_irq); - if (apic_mask != isdp->id_irq) { - rirq = ffs(isdp->id_irq) - 1; - isdp->id_irq = apic_mask; - undirect_isa_irq(rirq); /* free for ISA */ - } -#endif /* APIC_IO */ - register_intr(ffs(isdp->id_irq) - 1, isdp->id_id, - isdp->id_ri_flags, isdp->id_intr, - mp, isdp->id_unit); - } - } else { - if (isdp->id_reconfig) { - (*dp->attach)(isdp); /* reconfiguration attach */ - } - if (!last_alive) { - if (!isdp->id_reconfig) { - printf("%s%d not found", - dp->name, isdp->id_unit); - if (isdp->id_iobase != -1) - printf(" at 0x%x", isdp->id_iobase); - printf("\n"); - } - } else { -#if 0 - /* This code has not been tested.... */ - if (isdp->id_irq != 0 && isdp->id_intr != NULL) { - icu_unset(ffs(isdp->id_irq) - 1, - isdp->id_intr); - if (mp) - INTRUNMASK(*mp, isdp->id_irq); - } -#else - printf ("icu_unset() not supported here ...\n"); -#endif - } + /* + * and isa? + */ + for (i = resource_query_string(-1, "at", "isa"); + i != -1; + i = resource_query_string(i, "at", "isa")) { + isa_add_device(dev, resource_query_name(i), + resource_query_unit(i)); } -} -static caddr_t dma_bouncebuf[8]; -static u_int dma_bouncebufsize[8]; -static u_int8_t dma_bounced = 0; -static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ -static u_int8_t dma_inuse = 0; /* User for acquire/release */ -static u_int8_t dma_auto_mode = 0; + isa_wrap_old_drivers(); -#define VALID_DMA_MASK (7) + return 0; +} -/* high byte of address is stored in this port for i-th dma channel */ -static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; +extern device_t isa_bus_device; -/* - * Setup a DMA channel's bounce buffer. - */ -void -isa_dmainit(chan, bouncebufsize) - int chan; - u_int bouncebufsize; +static int +isa_attach(device_t dev) { - void *buf; - -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmainit: channel out of range"); - - if (dma_bouncebuf[chan] != NULL) - panic("isa_dmainit: impossible request"); -#endif - - dma_bouncebufsize[chan] = bouncebufsize; - - /* Try malloc() first. It works better if it works. */ - buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); - if (buf != NULL) { - if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { - dma_bouncebuf[chan] = buf; - return; - } - free(buf, M_DEVBUF); - } - buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, - 1ul, chan & 4 ? 0x20000ul : 0x10000ul); - if (buf == NULL) - printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); - else - dma_bouncebuf[chan] = buf; + /* + * Arrange for bus_generic_attach(dev) to be called later. + */ + isa_bus_device = dev; + return 0; } -/* - * Register a DMA channel's usage. Usually called from a device driver - * in open() or during its initialization. - */ -int -isa_dma_acquire(chan) - int chan; +static void +isa_print_child(device_t bus, device_t dev) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_acquire: channel out of range"); -#endif - - if (dma_inuse & (1 << chan)) { - printf("isa_dma_acquire: channel %d already in use\n", chan); - return (EBUSY); - } - dma_inuse |= (1 << chan); - dma_auto_mode &= ~(1 << chan); - - return (0); + 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)); } -/* - * Unregister a DMA channel's usage. Usually called from a device driver - * during close() or during its shutdown. - */ -void -isa_dma_release(chan) - int chan; +static int +isa_read_ivar(device_t bus, device_t dev, int index, uintptr_t * result) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dma_release: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dma_release: channel %d not in use\n", chan); -#endif - - if (dma_busy & (1 << chan)) { - dma_busy &= ~(1 << chan); - /* - * XXX We should also do "dma_bounced &= (1 << chan);" - * because we are acting on behalf of isa_dmadone() which - * was not called to end the last DMA operation. This does - * not matter now, but it may in the future. - */ - } - - dma_inuse &= ~(1 << chan); - dma_auto_mode &= ~(1 << chan); + 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; } /* - * isa_dmacascade(): program 8237 DMA controller channel to accept - * external dma control by a board. + * 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). */ -void -isa_dmacascade(chan) - int chan; +static int +isa_write_ivar(device_t bus, device_t dev, + int index, uintptr_t value) { -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmacascade: channel out of range"); -#endif - - /* set dma channel mode, and set dma channel mode */ - if ((chan & 4) == 0) { - outb(DMA1_MODE, DMA37MD_CASCADE | chan); - outb(DMA1_SMSK, chan); - } else { - outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); - outb(DMA2_SMSK, chan & 3); + 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_dmastart(): program 8237 DMA controller channel, avoid page alignment - * problems by using a bounce buffer. + * This implementation simply passes the request up to the parent + * bus, which in our case is the special i386 nexus, substituting any + * configured values if the caller defaulted. We can get away with + * this because there is no special mapping for ISA resources on an Intel + * platform. When porting this code to another architecture, it may be + * necessary to interpose a mapping layer here. */ -void -isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) +static 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) { - vm_offset_t phys; - int waport; - caddr_t newaddr; + int isdefault; + struct resource *rv, **rvp = 0; + struct isa_device *id = DEVTOISA(child); -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmastart: channel out of range"); - - if ((chan < 4 && nbytes > (1<<16)) - || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) - panic("isa_dmastart: impossible request"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastart: channel %d not acquired\n", chan); -#endif - -#if 0 - /* - * XXX This should be checked, but drivers like ad1848 only call - * isa_dmastart() once because they use Auto DMA mode. If we - * leave this in, drivers that do this will print this continuously. - */ - if (dma_busy & (1 << chan)) - printf("isa_dmastart: channel %d busy\n", chan); -#endif - - dma_busy |= (1 << chan); - - if (isa_dmarangecheck(addr, nbytes, chan)) { - if (dma_bouncebuf[chan] == NULL - || dma_bouncebufsize[chan] < nbytes) - panic("isa_dmastart: bad bounce buffer"); - dma_bounced |= (1 << chan); - newaddr = dma_bouncebuf[chan]; - - /* copy bounce buffer on write */ - if (!(flags & B_READ)) - bcopy(addr, newaddr, nbytes); - addr = newaddr; - } - - /* translate to physical */ - phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); - - if (flags & B_RAW) { - dma_auto_mode |= (1 << chan); - } else { - dma_auto_mode &= ~(1 << chan); - } - - if ((chan & 4) == 0) { + if (child) { /* - * Program one of DMA channels 0..3. These are - * byte mode channels. + * If this is our child, then use the isa_device to find + * defaults and to record results. */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); - else - outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); - } - else - if (flags & B_READ) - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); + if (device_get_devclass(device_get_parent(child)) == isa_devclass) + id = DEVTOISA(child); else - outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); - outb(DMA1_FFC, 0); - - /* send start address */ - waport = DMA1_CHN(chan); - outb(waport, phys); - outb(waport, phys>>8); - outb(dmapageport[chan], phys>>16); - - /* send count */ - outb(waport + 1, --nbytes); - outb(waport + 1, nbytes>>8); - - /* unmask channel */ - outb(DMA1_SMSK, chan); - } else { - /* - * Program one of DMA channels 4..7. These are - * word mode channels. - */ - /* set dma channel mode, and reset address ff */ - - /* If B_RAW flag is set, then use autoinitialise mode */ - if (flags & B_RAW) { - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); + 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; } - else - if (flags & B_READ) - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); - else - outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); - outb(DMA2_FFC, 0); - - /* send start address */ - waport = DMA2_CHN(chan - 4); - outb(waport, phys>>1); - outb(waport, phys>>9); - outb(dmapageport[chan], phys>>16); - - /* send count */ - nbytes >>= 1; - outb(waport + 2, --nbytes); - outb(waport + 2, nbytes>>8); + 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; - /* unmask channel */ - outb(DMA2_SMSK, chan & 3); + default: + return 0; } -} - -void -isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) -{ -#ifdef DIAGNOSTIC - if (chan & ~VALID_DMA_MASK) - panic("isa_dmadone: channel out of range"); - - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmadone: channel %d not acquired\n", chan); -#endif - - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) - printf("isa_dmadone: channel %d not busy\n", chan); - if ((dma_auto_mode & (1 << chan)) == 0) - outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); - - if (dma_bounced & (1 << chan)) { - /* copy bounce buffer on read */ - if (flags & B_READ) - bcopy(dma_bouncebuf[chan], addr, nbytes); + /* + * If the client attempts to reallocate a resource without + * releasing what was there previously, die horribly so that + * he knows how he !@#$ed up. + */ + 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)); - dma_bounced &= ~(1 << chan); + /* + * 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; + } } - dma_busy &= ~(1 << chan); + return rv; } -/* - * Check for problems with the address range of a DMA transfer - * (non-contiguous physical pages, outside of bus address space, - * crossing DMA page boundaries). - * Return true if special handling needed. - */ - static int -isa_dmarangecheck(caddr_t va, u_int length, int chan) +isa_release_resource(device_t bus, device_t child, int type, int rid, + struct resource *r) { - vm_offset_t phys, priorpage = 0, endva; - u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); - - endva = (vm_offset_t)round_page((vm_offset_t)va + length); - for (; va < (caddr_t) endva ; va += PAGE_SIZE) { - phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); -#define ISARAM_END RAM_END - if (phys == 0) - panic("isa_dmacheck: no physical page present"); - if (phys >= ISARAM_END) - return (1); - if (priorpage) { - if (priorpage + PAGE_SIZE != phys) - return (1); - /* check if crossing a DMA page boundary */ - if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) - return (1); - } - priorpage = phys; - } - return (0); -} + int rv; + struct isa_device *id = DEVTOISA(child); -/* - * Query the progress of a transfer on a DMA channel. - * - * To avoid having to interrupt a transfer in progress, we sample - * each of the high and low databytes twice, and apply the following - * logic to determine the correct count. - * - * Reads are performed with interrupts disabled, thus it is to be - * expected that the time between reads is very small. At most - * one rollover in the low count byte can be expected within the - * four reads that are performed. - * - * There are three gaps in which a rollover can occur : - * - * - read low1 - * gap1 - * - read high1 - * gap2 - * - read low2 - * gap3 - * - read high2 - * - * If a rollover occurs in gap1 or gap2, the low2 value will be - * greater than the low1 value. In this case, low2 and high2 are a - * corresponding pair. - * - * In any other case, low1 and high1 can be considered to be correct. - * - * The function returns the number of bytes remaining in the transfer, - * or -1 if the channel requested is not active. - * - */ -int -isa_dmastatus(int chan) -{ - u_long cnt = 0; - int ffport, waport; - u_long low1, high1, low2, high2; + if (rid > 1) + return EINVAL; - /* channel active? */ - if ((dma_inuse & (1 << chan)) == 0) { - printf("isa_dmastatus: channel %d not active\n", chan); - return(-1); + switch (type) { + case SYS_RES_IRQ: + case SYS_RES_DRQ: + case SYS_RES_IOPORT: + case SYS_RES_MEMORY: + break; + default: + return (ENOENT); } - /* channel busy? */ - if (((dma_busy & (1 << chan)) == 0) && - (dma_auto_mode & (1 << chan)) == 0 ) { - printf("chan %d not busy\n", chan); - return -2 ; - } - if (chan < 4) { /* low DMA controller */ - ffport = DMA1_FFC; - waport = DMA1_CHN(chan) + 1; - } else { /* high DMA controller */ - ffport = DMA2_FFC; - waport = DMA2_CHN(chan - 4) + 2; - } + rv = BUS_RELEASE_RESOURCE(device_get_parent(bus), child, type, rid, r); - disable_intr(); /* no interrupts Mr Jones! */ - outb(ffport, 0); /* clear register LSB flipflop */ - low1 = inb(waport); - high1 = inb(waport); - outb(ffport, 0); /* clear again */ - low2 = inb(waport); - high2 = inb(waport); - enable_intr(); /* enable interrupts again */ +#if 0 + if (rv) { + /* Kludge, isa as a child of pci doesn't have mapping regs */ + printf("WARNING: isa_release_resource: BUS_RELEASE_RESOURCE() failed: %d\n", rv); + rv = 0; + } +#endif - /* - * Now decide if a wrap has tried to skew our results. - * Note that after TC, the count will read 0xffff, while we want - * to return zero, so we add and then mask to compensate. - */ - if (low1 >= low2) { - cnt = (low1 + (high1 << 8) + 1) & 0xffff; - } else { - cnt = (low2 + (high2 << 8) + 1) & 0xffff; + if (rv == 0) { + switch (type) { + case SYS_RES_IRQ: + id->id_irqres[rid] = 0; + id->id_irq[rid] = -1; + break; + + case SYS_RES_DRQ: + id->id_drqres[rid] = 0; + id->id_drq[rid] = -1; + break; + + case SYS_RES_MEMORY: + id->id_memres[rid] = 0; + id->id_maddr[rid] = 0; + id->id_msize[rid] = 0; + break; + + case SYS_RES_IOPORT: + id->id_portres[rid] = 0; + id->id_port[rid] = 0; + id->id_portsize[rid] = 0; + break; + + default: + return ENOENT; + } } - if (chan >= 4) /* high channels move words */ - cnt *= 2; - return(cnt); + return rv; } /* - * Stop a DMA transfer currently in progress. + * We can't use the bus_generic_* versions of these methods because those + * methods always pass the bus param as the requesting device, and we need + * to pass the child (the i386 nexus knows about this and is prepared to + * deal). */ -int -isa_dmastop(int chan) +static int +isa_setup_intr(device_t bus, device_t child, struct resource *r, + void (*ihand)(void *), void *arg, void **cookiep) { - if ((dma_inuse & (1 << chan)) == 0) - printf("isa_dmastop: channel %d not acquired\n", chan); - - if (((dma_busy & (1 << chan)) == 0) && - ((dma_auto_mode & (1 << chan)) == 0)) { - printf("chan %d not busy\n", chan); - return -2 ; - } - - if ((chan & 4) == 0) { - outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); - } else { - outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); - } - return(isa_dmastatus(chan)); + return (BUS_SETUP_INTR(device_get_parent(bus), child, r, ihand, arg, + cookiep)); } -/* - * Find the highest priority enabled display device. Since we can't - * distinguish display devices from ttys, depend on display devices - * being sensitive and before sensitive non-display devices (if any) - * in isa_devtab_tty. - * - * XXX we should add capability flags IAMDISPLAY and ISUPPORTCONSOLES. - */ -struct isa_device * -find_display() +static int +isa_teardown_intr(device_t bus, device_t child, struct resource *r, + void *cookie) { - struct isa_device *dvp; - - for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) - if (dvp->id_driver->sensitive_hw && dvp->id_enabled) - return (dvp); - return (NULL); + 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_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, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + /* - * find an ISA device in a given isa_devtab_* table, given - * the table to search, the expected id_driver entry, and the unit number. - * - * this function is defined in isa_device.h, and this location is debatable; - * i put it there because it's useless w/o, and directly operates on - * the other stuff in that file. - * + * ISA can be attached to a PCI-ISA bridge or directly to the nexus. */ - -struct isa_device * -find_isadev(table, driverp, unit) - struct isa_device *table; - struct isa_driver *driverp; - int unit; -{ - if (driverp == NULL) /* sanity check */ - return (NULL); - - while ((table->id_driver != driverp) || (table->id_unit != unit)) { - if (table->id_driver == 0) - return NULL; - - table++; - } - - return (table); -} +DRIVER_MODULE(isa, isab, isa_driver, isa_devclass, 0, 0); +DRIVER_MODULE(isa, nexus, isa_driver, isa_devclass, 0, 0); diff --git a/sys/i386/isa/isa_compat.c b/sys/i386/isa/isa_compat.c new file mode 100644 index 0000000..82e6185 --- /dev/null +++ b/sys/i386/isa/isa_compat.c @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/kernel.h> +#include <sys/bus.h> +#include <sys/malloc.h> +#include <sys/module.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/resource.h> +#include <isa/isavar.h> +#include <i386/isa/isa_compat.h> +#include <i386/isa/isa_device.h> + +struct isa_compat_resources { + struct resource *ports; + struct resource *memory; + struct resource *drq; + struct resource *irq; +}; + +int +isa_compat_nextid(void) +{ + static int id = 2; /* id_id of -1, 0 and 1 are "used" */ + + return id++; +} + +static void +isa_compat_alloc_resources(device_t dev, struct isa_compat_resources *res) +{ + int rid; + + if (isa_get_port(dev) != -1) { + rid = 0; + res->ports = bus_alloc_resource(dev, SYS_RES_IOPORT, + &rid, 0ul, ~0ul, 1, + RF_ACTIVE); + if (res->ports == NULL) + printf("isa_compat: didn't get ports for %s\n", + device_get_name(dev)); + } else + res->ports = 0; + + if (isa_get_maddr(dev) != 0) { + rid = 0; + res->memory = bus_alloc_resource(dev, SYS_RES_MEMORY, + &rid, 0ul, ~0ul, 1, + RF_ACTIVE); + if (res->memory == NULL) + printf("isa_compat: didn't get memory for %s\n", + device_get_name(dev)); + } else + res->memory = 0; + + if (isa_get_drq(dev) != -1) { + rid = 0; + res->drq = bus_alloc_resource(dev, SYS_RES_DRQ, + &rid, 0ul, ~0ul, 1, + RF_ACTIVE); + if (res->drq == NULL) + printf("isa_compat: didn't get drq for %s\n", + device_get_name(dev)); + } else + res->drq = 0; + + if (isa_get_irq(dev) != -1) { + rid = 0; + res->irq = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, 0ul, ~0ul, 1, + RF_SHAREABLE | RF_ACTIVE); + if (res->irq == NULL) + printf("isa_compat: didn't get irq for %s\n", + device_get_name(dev)); + } else + res->irq = 0; +} + +static void +isa_compat_release_resources(device_t dev, struct isa_compat_resources *res) +{ + if (res->ports) { + bus_release_resource(dev, SYS_RES_IOPORT, 0, res->ports); + res->ports = 0; + } + if (res->memory) { + bus_release_resource(dev, SYS_RES_MEMORY, 0, res->memory); + res->memory = 0; + } + if (res->drq) { + bus_release_resource(dev, SYS_RES_DRQ, 0, res->drq); + res->drq = 0; + } + if (res->irq) { + bus_release_resource(dev, SYS_RES_IRQ, 0, res->irq); + res->irq = 0; + } +} + +static int +isa_compat_probe(device_t dev) +{ + struct isa_device *dvp = device_get_softc(dev); + struct isa_compat_resources res; + + bzero(&res, sizeof(res)); + /* + * Fill in the isa_device fields. + */ + dvp->id_id = isa_compat_nextid(); + dvp->id_driver = device_get_driver(dev)->priv; + dvp->id_iobase = isa_get_port(dev); + dvp->id_irq = (1 << isa_get_irq(dev)); + dvp->id_drq = isa_get_drq(dev); + dvp->id_maddr = (void *)isa_get_maddr(dev); + dvp->id_msize = isa_get_msize(dev); + dvp->id_unit = device_get_unit(dev); + dvp->id_flags = isa_get_flags(dev); + dvp->id_enabled = device_is_enabled(dev); + + /* + * Do the wrapped probe. + */ + if (dvp->id_driver->probe) { + int portsize; + isa_compat_alloc_resources(dev, &res); + if (res.memory) + dvp->id_maddr = rman_get_virtual(res.memory); + else + dvp->id_maddr = 0; + portsize = dvp->id_driver->probe(dvp); + isa_compat_release_resources(dev, &res); + if (portsize != 0) { + if (portsize > 0) + isa_set_portsize(dev, portsize); + if (dvp->id_iobase != isa_get_port(dev)) + isa_set_port(dev, dvp->id_iobase); + if (dvp->id_irq != (1 << isa_get_irq(dev))) + isa_set_irq(dev, ffs(dvp->id_irq) - 1); + if (dvp->id_drq != isa_get_drq(dev)) + isa_set_drq(dev, dvp->id_drq); + if (dvp->id_maddr != (void *) isa_get_maddr(dev)) + isa_set_maddr(dev, (int) dvp->id_maddr); + if (dvp->id_msize != isa_get_msize(dev)) + isa_set_msize(dev, dvp->id_msize); + return 0; + } + } + return ENXIO; +} + +static int +isa_compat_attach(device_t dev) +{ + struct isa_device *dvp = device_get_softc(dev); + struct isa_compat_resources res; + int error; + + bzero(&res, sizeof(res)); + isa_compat_alloc_resources(dev, &res); + if (dvp->id_driver->attach) + dvp->id_driver->attach(dvp); + if (res.irq && dvp->id_irq && dvp->id_intr) { + void *ih; + + error = BUS_SETUP_INTR(device_get_parent(dev), dev, + res.irq, + dvp->id_intr, + (void *)(uintptr_t)dvp->id_unit, + &ih); + if (error) + printf("isa_compat_attach: failed to setup intr: %d\n", + error); + } + return 0; +} + +static device_method_t isa_compat_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, isa_compat_probe), + DEVMETHOD(device_attach, isa_compat_attach), + + { 0, 0 } +}; + +/* + * Create a new style driver around each old isa driver. + */ +void +isa_wrap_old_drivers(void) +{ + int i; + struct old_isa_driver *op; + devclass_t isa_devclass = devclass_find("isa"); + + for (i = 0, op = &old_drivers[0]; i < old_drivers_count; i++, op++) { + driver_t *driver; + driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT); + if (!driver) + continue; + bzero(driver, sizeof(driver_t)); + driver->name = op->driver->name; + driver->methods = isa_compat_methods; + driver->type = op->type; + driver->softc = sizeof(struct isa_device *); + driver->priv = op->driver; + devclass_add_driver(isa_devclass, driver); + } +} + +int +haveseen_isadev(dvp, checkbits) + struct isa_device *dvp; + u_int checkbits; +{ + printf("haveseen_isadev() called - FIXME!\n"); + return 0; +} + +void +reconfig_isadev(isdp, mp) + struct isa_device *isdp; + u_int *mp; +{ + printf("reconfig_isadev() called - FIXME!\n"); +} diff --git a/sys/i386/isa/isa_compat.h b/sys/i386/isa/isa_compat.h new file mode 100644 index 0000000..5e48b89 --- /dev/null +++ b/sys/i386/isa/isa_compat.h @@ -0,0 +1,378 @@ +/*- + * Copyright (c) 1998 Doug Rabson + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id$ + */ + +#include "vt.h" +#include "bt.h" +#include "adv.h" +#include "aha.h" +#include "wdc.h" +#include "mse.h" +#include "ar.h" +#include "cs.h" +#include "cx.h" +#include "ed.h" +#include "el.h" +#include "ep.h" +#include "ex.h" +#include "fe.h" +#include "ie.h" +#include "le.h" +#include "lnc.h" +#include "rdp.h" +#include "sr.h" +#include "wl.h" +#include "ze.h" +#include "zp.h" +#include "oltr.h" +#include "pas.h" +#include "sb.h" +#include "sbxvi.h" +#include "sbmidi.h" +#include "awe.h" +#include "gus.h" +#include "mss.h" +#include "css.h" +#include "sscape.h" +#include "trix.h" +#include "opl.h" +#include "mpu.h" +#include "uart.h" +#include "pca.h" +#include "mcd.h" +#include "scd.h" +#include "matcd.h" +#include "wt.h" +#include "ctx.h" +#include "spigot.h" +#include "gp.h" +#include "gsc.h" +#include "joy.h" +#include "cy.h" +#include "dgb.h" +#include "dgm.h" +#include "labpc.h" +#include "rc.h" +#include "rp.h" +#include "tw.h" +#include "si.h" +#include "asc.h" +#include "stl.h" +#include "stli.h" +#include "loran.h" +#include "pcf.h" +#include "isic.h" +#include "tina.h" +#include "ppc.h" + +struct old_isa_driver { + int type; + struct isa_driver *driver; +}; + +extern struct isa_driver vtdriver; +extern struct isa_driver btdriver; +extern struct isa_driver advdriver; +extern struct isa_driver ahadriver; +extern struct isa_driver wdcdriver; +extern struct isa_driver msedriver; +extern struct isa_driver ardriver; +extern struct isa_driver csdriver; +extern struct isa_driver cxdriver; +extern struct isa_driver eddriver; +extern struct isa_driver eldriver; +extern struct isa_driver epdriver; +extern struct isa_driver exdriver; +extern struct isa_driver fedriver; +extern struct isa_driver iedriver; +extern struct isa_driver ledriver; +extern struct isa_driver lncdriver; +extern struct isa_driver rdpdriver; +extern struct isa_driver srdriver; +extern struct isa_driver wldriver; +extern struct isa_driver zedriver; +extern struct isa_driver zpdriver; +extern struct isa_driver oltrdriver; +extern struct isa_driver pasdriver; +extern struct isa_driver sbdriver; +extern struct isa_driver sbxvidriver; +extern struct isa_driver sbmididriver; +extern struct isa_driver awedriver; +extern struct isa_driver gusdriver; +extern struct isa_driver mssdriver; +extern struct isa_driver cssdriver; +extern struct isa_driver sscapedriver; +extern struct isa_driver trixdriver; +extern struct isa_driver sscape_mssdriver; +extern struct isa_driver opldriver; +extern struct isa_driver mpudriver; +extern struct isa_driver uartdriver; +extern struct isa_driver pcadriver; +extern struct isa_driver mcddriver; +extern struct isa_driver scddriver; +extern struct isa_driver matcddriver; +extern struct isa_driver wtdriver; +extern struct isa_driver ctxdriver; +extern struct isa_driver spigotdriver; +extern struct isa_driver gpdriver; +extern struct isa_driver gscdriver; +extern struct isa_driver joydriver; +extern struct isa_driver cydriver; +extern struct isa_driver dgbdriver; +extern struct isa_driver dgmdriver; +extern struct isa_driver labpcdriver; +extern struct isa_driver rcdriver; +extern struct isa_driver rpdriver; +extern struct isa_driver twdriver; +extern struct isa_driver sidriver; +extern struct isa_driver ascdriver; +extern struct isa_driver stldriver; +extern struct isa_driver stlidriver; +extern struct isa_driver lorandriver; +extern struct isa_driver pcfdriver; +extern struct isa_driver isicdriver; +extern struct isa_driver tinadriver; +extern struct isa_driver ppcdriver; + + +static struct old_isa_driver old_drivers[] = { + +/* Sensitive TTY */ + +/* Sensitive BIO */ + +/* Sensitive NET */ +#if NED > 0 + { DRIVER_TYPE_NET, &eddriver }, +#endif +#if NFE > 0 + { DRIVER_TYPE_NET, &fedriver }, +#endif +#if NRDP > 0 + { DRIVER_TYPE_NET, &rdpdriver }, +#endif + +/* Sensitive CAM */ + +/* TTY */ + +#if NVT > 0 + { DRIVER_TYPE_TTY, &vtdriver }, +#endif +#if NMSE > 0 + { DRIVER_TYPE_TTY, &msedriver }, +#endif +#if NPCA > 0 + { DRIVER_TYPE_TTY, &pcadriver }, +#endif +#if NGP > 0 + { DRIVER_TYPE_TTY, &gpdriver }, +#endif +#if NGSC > 0 + { DRIVER_TYPE_TTY, &gscdriver }, +#endif +#if NCY > 0 + { DRIVER_TYPE_TTY, &cydriver }, +#endif +#if NDGB > 0 + { DRIVER_TYPE_TTY, &dgbdriver }, +#endif +#if NDGM > 0 + { DRIVER_TYPE_TTY, &dgmdriver }, +#endif +#if NLABPC > 0 + { DRIVER_TYPE_TTY, &labpcdriver }, +#endif +#if NRCD > 0 + { DRIVER_TYPE_TTY, &rcdriver }, +#endif +#if NRP > 0 + { DRIVER_TYPE_TTY, &rpdriver }, +#endif +#if NTW > 0 + { DRIVER_TYPE_TTY, &twdriver }, +#endif +#if NSI > 0 + { DRIVER_TYPE_TTY, &sidriver }, +#endif +#if NASC > 0 + { DRIVER_TYPE_TTY, &ascdriver }, +#endif +#if NSTL > 0 + { DRIVER_TYPE_TTY, &stldriver }, +#endif +#if NSTLI > 0 + { DRIVER_TYPE_TTY, &stlidriver }, +#endif +#if NLORAN > 0 + { DRIVER_TYPE_TTY, &lorandriver }, +#endif +#if NPPC > 0 + { DRIVER_TYPE_TTY, &ppcdriver }, +#endif + +/* BIO */ + +#if NWDC > 0 + { DRIVER_TYPE_BIO, &wdcdriver }, +#endif +#if NMCD > 0 + { DRIVER_TYPE_BIO, &mcddriver }, +#endif +#if NSCD > 0 + { DRIVER_TYPE_BIO, &scddriver }, +#endif +#if NMATCD > 0 + { DRIVER_TYPE_BIO, &matcddriver }, +#endif +#if NWT > 0 + { DRIVER_TYPE_BIO, &wtdriver }, +#endif + +/* NET */ + +#if NIE > 0 + { DRIVER_TYPE_NET, &iedriver }, +#endif +#if NEP > 0 + { DRIVER_TYPE_NET, &epdriver }, +#endif +#if NEX > 0 + { DRIVER_TYPE_NET, &exdriver }, +#endif +#if NLE > 0 + { DRIVER_TYPE_NET, &ledriver }, +#endif +#if NLNC > 0 + { DRIVER_TYPE_NET, &lncdriver }, +#endif +#if NZE > 0 + { DRIVER_TYPE_NET, &zedriver }, +#endif +#if NZP > 0 + { DRIVER_TYPE_NET, &zpdriver }, +#endif +#if NCS > 0 + { DRIVER_TYPE_NET, &csdriver }, +#endif +#if NAR > 0 + { DRIVER_TYPE_NET, &ardriver }, +#endif +#if NCX > 0 + { DRIVER_TYPE_NET, &cxdriver }, +#endif +#if NEL > 0 + { DRIVER_TYPE_NET, &eldriver }, +#endif +#if NSR > 0 + { DRIVER_TYPE_NET, &srdriver }, +#endif +#if NWL > 0 + { DRIVER_TYPE_NET, &wldriver }, +#endif +#if NPCF > 0 + { DRIVER_TYPE_NET, &pcfdriver }, +#endif +#if NISIC > 0 + { DRIVER_TYPE_NET, &isicdriver }, +#endif +#if NTINA > 0 + { DRIVER_TYPE_NET, &tinadriver }, +#endif + +/* CAM */ + +#if NBT > 0 + { DRIVER_TYPE_CAM, &btdriver }, +#endif +#if NADV > 0 + { DRIVER_TYPE_CAM, &advdriver }, +#endif +#if NAHA > 0 + { DRIVER_TYPE_CAM, &ahadriver }, +#endif + +/* MISC */ + +#if NOLTR > 0 + { DRIVER_TYPE_MISC, &oltrdriver }, +#endif +#if NPAS > 0 + { DRIVER_TYPE_MISC, &pasdriver }, +#endif +#if NSB > 0 + { DRIVER_TYPE_MISC, &sbdriver }, +#endif +#if NSBVXI > 0 + { DRIVER_TYPE_MISC, &sbxvidriver }, +#endif +#if NSBMIDI > 0 + { DRIVER_TYPE_MISC, &sbmididriver }, +#endif +#if NAWE > 0 + { DRIVER_TYPE_MISC, &awedriver }, +#endif +#if NGUS > 0 + { DRIVER_TYPE_MISC, &gusdriver }, +#endif +#if NMSS > 0 + { DRIVER_TYPE_MISC, &mssdriver }, +#endif +#if NCSS > 0 + { DRIVER_TYPE_MISC, &cssdriver }, +#endif +#if NSSCAPE > 0 + { DRIVER_TYPE_MISC, &sscapedriver }, +#endif +#if NTRIX > 0 + { DRIVER_TYPE_MISC, &trixdriver }, +#endif +#if NSSCAPE > 0 + { DRIVER_TYPE_MISC, &sscape_mssdriver }, +#endif +#if NOPL > 0 + { DRIVER_TYPE_MISC, &opldriver }, +#endif +#if NMPU > 0 + { DRIVER_TYPE_MISC, &mpudriver }, +#endif +#if NUART > 0 + { DRIVER_TYPE_MISC, &uartdriver }, +#endif +#if NCTX > 0 + { DRIVER_TYPE_MISC, &ctxdriver }, +#endif +#if NSPIGOT > 0 + { DRIVER_TYPE_MISC, &spigotdriver }, +#endif +#if NJOY > 0 + { DRIVER_TYPE_MISC, &joydriver }, +#endif + +}; + +#define old_drivers_count (sizeof(old_drivers) / sizeof(old_drivers[0])) diff --git a/sys/i386/isa/isa_device.h b/sys/i386/isa/isa_device.h index d23f701..a7c1022 100644 --- a/sys/i386/isa/isa_device.h +++ b/sys/i386/isa/isa_device.h @@ -31,12 +31,16 @@ * SUCH DAMAGE. * * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91 - * $Id: isa_device.h,v 1.56 1998/10/22 05:58:39 bde Exp $ + * $Id: isa_device.h,v 1.57 1999/01/17 06:33:43 bde Exp $ */ #ifndef _I386_ISA_ISA_DEVICE_H_ #define _I386_ISA_ISA_DEVICE_H_ +#ifdef KERNEL +#include <i386/isa/isa_dma.h> +#endif + /* * ISA Bus Autoconfiguration */ @@ -105,30 +109,9 @@ struct isa_driver { #ifdef KERNEL -extern struct isa_device isa_biotab_fdc[]; -extern struct isa_device isa_biotab_wdc[]; -extern struct isa_device isa_devtab_bio[]; -extern struct isa_device isa_devtab_net[]; -extern struct isa_device isa_devtab_cam[]; -extern struct isa_device isa_devtab_null[]; -extern struct isa_device isa_devtab_tty[]; - -struct isa_device * - find_display __P((void)); -struct isa_device * - find_isadev __P((struct isa_device *table, struct isa_driver *driverp, - int unit)); int haveseen_isadev __P((struct isa_device *dvp, u_int checkbits)); -void isa_configure __P((void)); -void isa_dmacascade __P((int chan)); -void isa_dmadone __P((int flags, caddr_t addr, int nbytes, int chan)); -void isa_dmainit __P((int chan, u_int bouncebufsize)); -void isa_dmastart __P((int flags, caddr_t addr, u_int nbytes, int chan)); -int isa_dma_acquire __P((int chan)); -void isa_dma_release __P((int chan)); -int isa_dmastatus __P((int chan)); -int isa_dmastop __P((int chan)); void reconfig_isadev __P((struct isa_device *isdp, u_int *mp)); +int isa_compat_nextid __P((void)); #endif /* KERNEL */ diff --git a/sys/i386/isa/isa_dma.c b/sys/i386/isa/isa_dma.c new file mode 100644 index 0000000..abea7f8 --- /dev/null +++ b/sys/i386/isa/isa_dma.c @@ -0,0 +1,510 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * William Jolitz. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 + * $Id: isa.c,v 1.117 1998/11/29 15:42:40 phk Exp $ + */ + +/* + * code to manage AT bus + * + * 92/08/18 Frank P. MacLachlan (fpm@crash.cts.com): + * Fixed uninitialized variable problem and added code to deal + * with DMA page boundaries in isa_dmarangecheck(). Fixed word + * mode DMA count compution and reorganized DMA setup code in + * isa_dmastart() + */ + +#include <sys/param.h> +#include <sys/systm.h> +#include <sys/buf.h> +#include <sys/malloc.h> +#include <machine/ipl.h> +#include <machine/md_var.h> +#ifdef APIC_IO +#include <machine/smp.h> +#endif /* APIC_IO */ +#include <vm/vm.h> +#include <vm/vm_param.h> +#include <vm/pmap.h> +#include <i386/isa/isa_device.h> +#include <i386/isa/intr_machdep.h> +#include <i386/isa/isa.h> +#include <i386/isa/ic/i8237.h> + +#include <sys/interrupt.h> + +#include "pnp.h" +#if NPNP > 0 +#include <i386/isa/pnp.h> +#endif + +/* +** Register definitions for DMA controller 1 (channels 0..3): +*/ +#define DMA1_CHN(c) (IO_DMA1 + 1*(2*(c))) /* addr reg for channel c */ +#define DMA1_SMSK (IO_DMA1 + 1*10) /* single mask register */ +#define DMA1_MODE (IO_DMA1 + 1*11) /* mode register */ +#define DMA1_FFC (IO_DMA1 + 1*12) /* clear first/last FF */ + +/* +** Register definitions for DMA controller 2 (channels 4..7): +*/ +#define DMA2_CHN(c) (IO_DMA2 + 2*(2*(c))) /* addr reg for channel c */ +#define DMA2_SMSK (IO_DMA2 + 2*10) /* single mask register */ +#define DMA2_MODE (IO_DMA2 + 2*11) /* mode register */ +#define DMA2_FFC (IO_DMA2 + 2*12) /* clear first/last FF */ + +static int isa_dmarangecheck __P((caddr_t va, u_int length, int chan)); + +static caddr_t dma_bouncebuf[8]; +static u_int dma_bouncebufsize[8]; +static u_int8_t dma_bounced = 0; +static u_int8_t dma_busy = 0; /* Used in isa_dmastart() */ +static u_int8_t dma_inuse = 0; /* User for acquire/release */ +static u_int8_t dma_auto_mode = 0; + +#define VALID_DMA_MASK (7) + +/* high byte of address is stored in this port for i-th dma channel */ +static int dmapageport[8] = { 0x87, 0x83, 0x81, 0x82, 0x8f, 0x8b, 0x89, 0x8a }; + +/* + * Setup a DMA channel's bounce buffer. + */ +void +isa_dmainit(chan, bouncebufsize) + int chan; + u_int bouncebufsize; +{ + void *buf; + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmainit: channel out of range"); + + if (dma_bouncebuf[chan] != NULL) + panic("isa_dmainit: impossible request"); +#endif + + dma_bouncebufsize[chan] = bouncebufsize; + + /* Try malloc() first. It works better if it works. */ + buf = malloc(bouncebufsize, M_DEVBUF, M_NOWAIT); + if (buf != NULL) { + if (isa_dmarangecheck(buf, bouncebufsize, chan) == 0) { + dma_bouncebuf[chan] = buf; + return; + } + free(buf, M_DEVBUF); + } + buf = contigmalloc(bouncebufsize, M_DEVBUF, M_NOWAIT, 0ul, 0xfffffful, + 1ul, chan & 4 ? 0x20000ul : 0x10000ul); + if (buf == NULL) + printf("isa_dmainit(%d, %d) failed\n", chan, bouncebufsize); + else + dma_bouncebuf[chan] = buf; +} + +/* + * Register a DMA channel's usage. Usually called from a device driver + * in open() or during its initialization. + */ +int +isa_dma_acquire(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_acquire: channel out of range"); +#endif + + if (dma_inuse & (1 << chan)) { + printf("isa_dma_acquire: channel %d already in use\n", chan); + return (EBUSY); + } + dma_inuse |= (1 << chan); + dma_auto_mode &= ~(1 << chan); + + return (0); +} + +/* + * Unregister a DMA channel's usage. Usually called from a device driver + * during close() or during its shutdown. + */ +void +isa_dma_release(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dma_release: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dma_release: channel %d not in use\n", chan); +#endif + + if (dma_busy & (1 << chan)) { + dma_busy &= ~(1 << chan); + /* + * XXX We should also do "dma_bounced &= (1 << chan);" + * because we are acting on behalf of isa_dmadone() which + * was not called to end the last DMA operation. This does + * not matter now, but it may in the future. + */ + } + + dma_inuse &= ~(1 << chan); + dma_auto_mode &= ~(1 << chan); +} + +/* + * isa_dmacascade(): program 8237 DMA controller channel to accept + * external dma control by a board. + */ +void +isa_dmacascade(chan) + int chan; +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmacascade: channel out of range"); +#endif + + /* set dma channel mode, and set dma channel mode */ + if ((chan & 4) == 0) { + outb(DMA1_MODE, DMA37MD_CASCADE | chan); + outb(DMA1_SMSK, chan); + } else { + outb(DMA2_MODE, DMA37MD_CASCADE | (chan & 3)); + outb(DMA2_SMSK, chan & 3); + } +} + +/* + * isa_dmastart(): program 8237 DMA controller channel, avoid page alignment + * problems by using a bounce buffer. + */ +void +isa_dmastart(int flags, caddr_t addr, u_int nbytes, int chan) +{ + vm_offset_t phys; + int waport; + caddr_t newaddr; + +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmastart: channel out of range"); + + if ((chan < 4 && nbytes > (1<<16)) + || (chan >= 4 && (nbytes > (1<<17) || (u_int)addr & 1))) + panic("isa_dmastart: impossible request"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastart: channel %d not acquired\n", chan); +#endif + +#if 0 + /* + * XXX This should be checked, but drivers like ad1848 only call + * isa_dmastart() once because they use Auto DMA mode. If we + * leave this in, drivers that do this will print this continuously. + */ + if (dma_busy & (1 << chan)) + printf("isa_dmastart: channel %d busy\n", chan); +#endif + + dma_busy |= (1 << chan); + + if (isa_dmarangecheck(addr, nbytes, chan)) { + if (dma_bouncebuf[chan] == NULL + || dma_bouncebufsize[chan] < nbytes) + panic("isa_dmastart: bad bounce buffer"); + dma_bounced |= (1 << chan); + newaddr = dma_bouncebuf[chan]; + + /* copy bounce buffer on write */ + if (!(flags & B_READ)) + bcopy(addr, newaddr, nbytes); + addr = newaddr; + } + + /* translate to physical */ + phys = pmap_extract(pmap_kernel(), (vm_offset_t)addr); + + if (flags & B_RAW) { + dma_auto_mode |= (1 << chan); + } else { + dma_auto_mode &= ~(1 << chan); + } + + if ((chan & 4) == 0) { + /* + * Program one of DMA channels 0..3. These are + * byte mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If B_RAW flag is set, then use autoinitialise mode */ + if (flags & B_RAW) { + if (flags & B_READ) + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_AUTO|DMA37MD_READ|chan); + } + else + if (flags & B_READ) + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|chan); + else + outb(DMA1_MODE, DMA37MD_SINGLE|DMA37MD_READ|chan); + outb(DMA1_FFC, 0); + + /* send start address */ + waport = DMA1_CHN(chan); + outb(waport, phys); + outb(waport, phys>>8); + outb(dmapageport[chan], phys>>16); + + /* send count */ + outb(waport + 1, --nbytes); + outb(waport + 1, nbytes>>8); + + /* unmask channel */ + outb(DMA1_SMSK, chan); + } else { + /* + * Program one of DMA channels 4..7. These are + * word mode channels. + */ + /* set dma channel mode, and reset address ff */ + + /* If B_RAW flag is set, then use autoinitialise mode */ + if (flags & B_RAW) { + if (flags & B_READ) + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_AUTO|DMA37MD_READ|(chan&3)); + } + else + if (flags & B_READ) + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_WRITE|(chan&3)); + else + outb(DMA2_MODE, DMA37MD_SINGLE|DMA37MD_READ|(chan&3)); + outb(DMA2_FFC, 0); + + /* send start address */ + waport = DMA2_CHN(chan - 4); + outb(waport, phys>>1); + outb(waport, phys>>9); + outb(dmapageport[chan], phys>>16); + + /* send count */ + nbytes >>= 1; + outb(waport + 2, --nbytes); + outb(waport + 2, nbytes>>8); + + /* unmask channel */ + outb(DMA2_SMSK, chan & 3); + } +} + +void +isa_dmadone(int flags, caddr_t addr, int nbytes, int chan) +{ +#ifdef DIAGNOSTIC + if (chan & ~VALID_DMA_MASK) + panic("isa_dmadone: channel out of range"); + + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmadone: channel %d not acquired\n", chan); +#endif + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) + printf("isa_dmadone: channel %d not busy\n", chan); + + if ((dma_auto_mode & (1 << chan)) == 0) + outb(chan & 4 ? DMA2_SMSK : DMA1_SMSK, (chan & 3) | 4); + + if (dma_bounced & (1 << chan)) { + /* copy bounce buffer on read */ + if (flags & B_READ) + bcopy(dma_bouncebuf[chan], addr, nbytes); + + dma_bounced &= ~(1 << chan); + } + dma_busy &= ~(1 << chan); +} + +/* + * Check for problems with the address range of a DMA transfer + * (non-contiguous physical pages, outside of bus address space, + * crossing DMA page boundaries). + * Return true if special handling needed. + */ + +static int +isa_dmarangecheck(caddr_t va, u_int length, int chan) +{ + vm_offset_t phys, priorpage = 0, endva; + u_int dma_pgmsk = (chan & 4) ? ~(128*1024-1) : ~(64*1024-1); + + endva = (vm_offset_t)round_page((vm_offset_t)va + length); + for (; va < (caddr_t) endva ; va += PAGE_SIZE) { + phys = trunc_page(pmap_extract(pmap_kernel(), (vm_offset_t)va)); +#define ISARAM_END RAM_END + if (phys == 0) + panic("isa_dmacheck: no physical page present"); + if (phys >= ISARAM_END) + return (1); + if (priorpage) { + if (priorpage + PAGE_SIZE != phys) + return (1); + /* check if crossing a DMA page boundary */ + if (((u_int)priorpage ^ (u_int)phys) & dma_pgmsk) + return (1); + } + priorpage = phys; + } + return (0); +} + +/* + * Query the progress of a transfer on a DMA channel. + * + * To avoid having to interrupt a transfer in progress, we sample + * each of the high and low databytes twice, and apply the following + * logic to determine the correct count. + * + * Reads are performed with interrupts disabled, thus it is to be + * expected that the time between reads is very small. At most + * one rollover in the low count byte can be expected within the + * four reads that are performed. + * + * There are three gaps in which a rollover can occur : + * + * - read low1 + * gap1 + * - read high1 + * gap2 + * - read low2 + * gap3 + * - read high2 + * + * If a rollover occurs in gap1 or gap2, the low2 value will be + * greater than the low1 value. In this case, low2 and high2 are a + * corresponding pair. + * + * In any other case, low1 and high1 can be considered to be correct. + * + * The function returns the number of bytes remaining in the transfer, + * or -1 if the channel requested is not active. + * + */ +int +isa_dmastatus(int chan) +{ + u_long cnt = 0; + int ffport, waport; + u_long low1, high1, low2, high2; + + /* channel active? */ + if ((dma_inuse & (1 << chan)) == 0) { + printf("isa_dmastatus: channel %d not active\n", chan); + return(-1); + } + /* channel busy? */ + + if (((dma_busy & (1 << chan)) == 0) && + (dma_auto_mode & (1 << chan)) == 0 ) { + printf("chan %d not busy\n", chan); + return -2 ; + } + if (chan < 4) { /* low DMA controller */ + ffport = DMA1_FFC; + waport = DMA1_CHN(chan) + 1; + } else { /* high DMA controller */ + ffport = DMA2_FFC; + waport = DMA2_CHN(chan - 4) + 2; + } + + disable_intr(); /* no interrupts Mr Jones! */ + outb(ffport, 0); /* clear register LSB flipflop */ + low1 = inb(waport); + high1 = inb(waport); + outb(ffport, 0); /* clear again */ + low2 = inb(waport); + high2 = inb(waport); + enable_intr(); /* enable interrupts again */ + + /* + * Now decide if a wrap has tried to skew our results. + * Note that after TC, the count will read 0xffff, while we want + * to return zero, so we add and then mask to compensate. + */ + if (low1 >= low2) { + cnt = (low1 + (high1 << 8) + 1) & 0xffff; + } else { + cnt = (low2 + (high2 << 8) + 1) & 0xffff; + } + + if (chan >= 4) /* high channels move words */ + cnt *= 2; + return(cnt); +} + +/* + * Stop a DMA transfer currently in progress. + */ +int +isa_dmastop(int chan) +{ + if ((dma_inuse & (1 << chan)) == 0) + printf("isa_dmastop: channel %d not acquired\n", chan); + + if (((dma_busy & (1 << chan)) == 0) && + ((dma_auto_mode & (1 << chan)) == 0)) { + printf("chan %d not busy\n", chan); + return -2 ; + } + + if ((chan & 4) == 0) { + outb(DMA1_SMSK, (chan & 3) | 4 /* disable mask */); + } else { + outb(DMA2_SMSK, (chan & 3) | 4 /* disable mask */); + } + return(isa_dmastatus(chan)); +} diff --git a/sys/i386/isa/isa_dma.h b/sys/i386/isa/isa_dma.h new file mode 100644 index 0000000..3fe234c --- /dev/null +++ b/sys/i386/isa/isa_dma.h @@ -0,0 +1,51 @@ +/*- + * Copyright (c) 1991 The Regents of the University of California. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * from: @(#)isa_device.h 7.1 (Berkeley) 5/9/91 + * $Id: isa_device.h,v 1.57 1999/01/17 06:33:43 bde Exp $ + */ + +#ifndef _I386_ISA_ISA_DMA_H_ +#define _I386_ISA_ISA_DMA_H_ + +#ifdef KERNEL +void isa_dmacascade __P((int chan)); +void isa_dmadone __P((int flags, caddr_t addr, int nbytes, int chan)); +void isa_dmainit __P((int chan, u_int bouncebufsize)); +void isa_dmastart __P((int flags, caddr_t addr, u_int nbytes, int chan)); +int isa_dma_acquire __P((int chan)); +void isa_dma_release __P((int chan)); +int isa_dmastatus __P((int chan)); +int isa_dmastop __P((int chan)); +#endif /* KERNEL */ + +#endif /* !_I386_ISA_ISA_DMA_H_ */ diff --git a/sys/i386/isa/nmi.c b/sys/i386/isa/nmi.c index 944eb4e..4f7c1e9 100644 --- a/sys/i386/isa/nmi.c +++ b/sys/i386/isa/nmi.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)isa.c 7.2 (Berkeley) 5/13/91 - * $Id: intr_machdep.c,v 1.16 1999/01/08 19:17:48 bde Exp $ + * $Id: intr_machdep.c,v 1.17 1999/04/14 14:26:36 bde Exp $ */ #include "opt_auto_eoi.h" @@ -328,6 +328,7 @@ isa_get_nameunit(int id) return ("clk0"); /* XXX may also be sloppy driver */ if (id == 1) return ("rtc0"); +#if 0 for (dp = isa_devtab_bio; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; @@ -343,6 +344,7 @@ isa_get_nameunit(int id) for (dp = isa_devtab_tty; dp->id_driver != NULL; dp++) if (dp->id_id == id) goto found_device; +#endif return "???"; found_device: diff --git a/sys/i386/isa/npx.c b/sys/i386/isa/npx.c index 2371e7b..dc2eb73 100644 --- a/sys/i386/isa/npx.c +++ b/sys/i386/isa/npx.c @@ -32,7 +32,7 @@ * SUCH DAMAGE. * * from: @(#)npx.c 7.2 (Berkeley) 5/12/91 - * $Id: npx.c,v 1.65 1999/01/08 16:29:59 bde Exp $ + * $Id: npx.c,v 1.66 1999/03/28 23:28:18 dt Exp $ */ #include "npx.h" @@ -43,10 +43,14 @@ #include <sys/param.h> #include <sys/systm.h> +#include <sys/bus.h> #include <sys/kernel.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/sysctl.h> #include <sys/proc.h> +#include <machine/bus.h> +#include <sys/rman.h> #ifdef NPX_DEBUG #include <sys/syslog.h> #endif @@ -64,6 +68,7 @@ #ifndef SMP #include <machine/clock.h> #endif +#include <machine/resource.h> #include <machine/specialreg.h> #include <machine/segments.h> @@ -72,7 +77,6 @@ #include <i386/isa/intr_machdep.h> #include <i386/isa/isa.h> #endif -#include <i386/isa/isa_device.h> /* * 387 and 287 Numeric Coprocessor Extension (NPX) Driver. @@ -83,9 +87,6 @@ #define NPX_DISABLE_I586_OPTIMIZED_BZERO (1 << 1) #define NPX_DISABLE_I586_OPTIMIZED_COPYIO (1 << 2) -/* XXX - should be in header file. */ -ointhand2_t npxintr; - #ifdef __GNUC__ #define fldcw(addr) __asm("fldcw %0" : : "m" (*(addr))) @@ -119,18 +120,15 @@ void stop_emulating __P((void)); typedef u_char bool_t; -static int npxattach __P((struct isa_device *dvp)); -static int npxprobe __P((struct isa_device *dvp)); -static int npxprobe1 __P((struct isa_device *dvp)); +static int npx_attach __P((device_t dev)); + void npx_intr __P((void *)); +static int npx_probe __P((device_t dev)); +static int npx_probe1 __P((device_t dev)); #ifdef I586_CPU static long timezero __P((const char *funcname, void (*func)(void *buf, size_t len))); #endif /* I586_CPU */ -struct isa_driver npxdriver = { - npxprobe, npxattach, "npx", -}; - int hw_float; /* XXX currently just alias for npx_exists */ SYSCTL_INT(_hw,HW_FLOATINGPT, floatingpoint, @@ -191,12 +189,13 @@ __asm(" \n\ * need to use interrupts. Return 1 if device exists. */ static int -npxprobe(dvp) - struct isa_device *dvp; +npx_probe(dev) + device_t dev; { -#ifdef SMP +/*#ifdef SMP*/ +#if 1 - return npxprobe1(dvp); + return npx_probe1(dev); #else /* SMP */ @@ -213,20 +212,20 @@ npxprobe(dvp) * install suitable handlers and run with interrupts enabled so we * won't need to do so much here. */ - npx_intrno = NRSVIDT + ffs(dvp->id_irq) - 1; + npx_intrno = NRSVIDT + 13; save_eflags = read_eflags(); disable_intr(); save_icu1_mask = inb(IO_ICU1 + 1); save_icu2_mask = inb(IO_ICU2 + 1); save_idt_npxintr = idt[npx_intrno]; save_idt_npxtrap = idt[16]; - outb(IO_ICU1 + 1, ~(IRQ_SLAVE | dvp->id_irq)); - outb(IO_ICU2 + 1, ~(dvp->id_irq >> 8)); + outb(IO_ICU1 + 1, ~IRQ_SLAVE); + outb(IO_ICU2 + 1, ~(1 << (13 - 8))); setidt(16, probetrap, SDT_SYS386TGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); setidt(npx_intrno, probeintr, SDT_SYS386IGT, SEL_KPL, GSEL(GCODE_SEL, SEL_KPL)); npx_idt_probeintr = idt[npx_intrno]; enable_intr(); - result = npxprobe1(dvp); + result = npx_probe1(dev); disable_intr(); outb(IO_ICU1 + 1, save_icu1_mask); outb(IO_ICU2 + 1, save_icu2_mask); @@ -239,8 +238,8 @@ npxprobe(dvp) } static int -npxprobe1(dvp) - struct isa_device *dvp; +npx_probe1(dev) + device_t dev; { #ifndef SMP u_short control; @@ -280,21 +279,18 @@ npxprobe1(dvp) */ fninit(); -#ifdef SMP - +/*#ifdef SMP*/ +#if 1 /* * Exception 16 MUST work for SMP. */ npx_irq13 = 0; npx_ex16 = hw_float = npx_exists = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + device_set_desc(dev, "math processor"); + return (0); -#else /* SMP */ +#else /* !SMP */ + device_set_desc(dev, "math processor"); /* * Don't use fwait here because it might hang. @@ -335,14 +331,12 @@ npxprobe1(dvp) * Good, exception 16 works. */ npx_ex16 = 1; - dvp->id_irq = 0; /* zap the interrupt */ - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); + return (0); } if (npx_intrs_while_probing != 0) { + int rid; + struct resource *r; + void *intr; /* * Bad, we are stuck with IRQ13. */ @@ -350,8 +344,30 @@ npxprobe1(dvp) /* * npxattach would be too late to set npx0_imask. */ - npx0_imask |= dvp->id_irq; - return (IO_NPXSIZE); + npx0_imask |= (1 << 13); + + /* + * We allocate these resources permanently, + * so there is no need to keep track of them. + */ + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IOPORT, + &rid, IO_NPX, IO_NPX, + IO_NPXSIZE, RF_ACTIVE); + if (r == 0) + panic("npx: can't get ports"); + rid = 0; + r = bus_alloc_resource(dev, SYS_RES_IRQ, + &rid, 13, 13, + 1, RF_ACTIVE); + if (r == 0) + panic("npx: can't get IRQ"); + BUS_SETUP_INTR(device_get_parent(dev), + dev, r, npx_intr, 0, &intr); + if (intr == 0) + panic("npx: can't create intr"); + + return (0); } /* * Worse, even IRQ13 is broken. Use emulator. @@ -363,13 +379,7 @@ npxprobe1(dvp) * emulator and say that it has been installed. XXX handle devices * that aren't really devices better. */ - dvp->id_irq = 0; - /* - * special return value to flag that we do not - * actually use any I/O registers - */ - return (-1); - + return (0); #endif /* SMP */ } @@ -377,14 +387,15 @@ npxprobe1(dvp) * Attach routine - announce which it is, and wire into system */ int -npxattach(dvp) - struct isa_device *dvp; +npx_attach(dev) + device_t dev; { - dvp->id_ointr = npxintr; + int flags; - /* The caller has printed "irq 13" for the npx_irq13 case. */ - if (!npx_irq13) { - printf("npx%d: ", dvp->id_unit); + device_print_prettyname(dev); + if (npx_irq13) { + printf("using IRQ 13 interface\n"); + } else { if (npx_ex16) printf("INT 16 interface\n"); #if defined(MATH_EMULATE) || defined(GPL_MATH_EMULATE) @@ -401,23 +412,26 @@ npxattach(dvp) npxinit(__INITIAL_NPXCW__); #ifdef I586_CPU + if (resource_int_value("npx", 0, "flags", &flags) != 0) + flags = 0; + if (cpu_class == CPUCLASS_586 && npx_ex16 && timezero("i586_bzero()", i586_bzero) < timezero("bzero()", bzero) * 4 / 5) { - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BCOPY)) { bcopy_vector = i586_bcopy; ovbcopy_vector = i586_bcopy; } - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_BZERO)) bzero = i586_bzero; - if (!(dvp->id_flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { + if (!(flags & NPX_DISABLE_I586_OPTIMIZED_COPYIO)) { copyin_vector = i586_copyin; copyout_vector = i586_copyout; } } #endif - return (1); /* XXX unused */ + return (0); /* XXX unused */ } /* @@ -494,8 +508,8 @@ npxexit(p) * solution for signals other than SIGFPE. */ void -npxintr(unit) - int unit; +npx_intr(dummy) + void *dummy; { int code; struct intrframe *frame; @@ -518,7 +532,7 @@ npxintr(unit) /* * Pass exception to process. */ - frame = (struct intrframe *)&unit; /* XXX */ + frame = (struct intrframe *)&dummy; /* XXX */ if ((ISPL(frame->if_cs) == SEL_UPL) || (frame->if_eflags & PSL_VM)) { /* * Interrupt is essentially a trap, so we can afford to call @@ -686,4 +700,31 @@ timezero(funcname, func) } #endif /* I586_CPU */ +static device_method_t npx_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, npx_probe), + DEVMETHOD(device_attach, npx_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), + + { 0, 0 } +}; + +static driver_t npx_driver = { + "npx", + npx_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + +static devclass_t npx_devclass; + +/* + * We prefer to attach to the root nexus so that the usual case (exception 16) + * doesn't describe the processor as being `on isa'. + */ +DRIVER_MODULE(npx, nexus, npx_driver, npx_devclass, 0, 0); + #endif /* NNPX > 0 */ diff --git a/sys/i386/isa/rp.c b/sys/i386/isa/rp.c index 3ac4ee9..e9357fa 100644 --- a/sys/i386/isa/rp.c +++ b/sys/i386/isa/rp.c @@ -1180,7 +1180,6 @@ int rpattach(dev) struct isa_device *dev; { - struct isa_device *idev; dev_t rp_dev; int iobase, unit, /*rpmajor,*/ oldspl; int num_ports, num_chan, num_aiops; @@ -1280,13 +1279,6 @@ struct isa_device *dev; } } - idev = find_isadev(isa_devtab_tty, &rpdriver, - RP_MPMASTER(dev) + rp_pcicount); - if(idev == NULL) { - printf("rp%d: master device %d not configured\n", - dev->id_unit, RP_MPMASTER(dev)); - } -/* printf("COOL!! Device is found!!\n"); for(rpmajor=0;rpmajor<nchrdev;rpmajor++) if(cdevsw[rpmajor].d_open == rpopen) printf("From %d entries: Found entry at major = %d\n",nchrdev,rpmajor); diff --git a/sys/i386/isa/snd/sound.c b/sys/i386/isa/snd/sound.c index 6a5a92d..267901e 100644 --- a/sys/i386/isa/snd/sound.c +++ b/sys/i386/isa/snd/sound.c @@ -236,7 +236,6 @@ int pcmattach(struct isa_device * dev) { snddev_info *d = NULL ; - struct isa_device *dvp; int stat = 0; dev->id_ointr = pcmintr; @@ -292,9 +291,7 @@ pcmattach(struct isa_device * dev) */ if (dev->id_driver == NULL) { dev->id_driver = &pcmdriver ; - dvp=find_isadev(isa_devtab_tty, &pcmdriver, 0); - if (dvp) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } /* diff --git a/sys/i386/isa/sound/ad1848.c b/sys/i386/isa/sound/ad1848.c index 243ed78..18751d4 100644 --- a/sys/i386/isa/sound/ad1848.c +++ b/sys/i386/isa/sound/ad1848.c @@ -165,6 +165,10 @@ short ipri_to_irq(u_short ipri); void adintr(unit) { +#if 1 + /* this isn't ideal but should work */ + ad1848_interrupt(-1); +#else static short unit_to_irq[4] = {9, -1, -1, -1}; struct isa_device *dev; @@ -183,6 +187,7 @@ adintr(unit) ad1848_interrupt(unit_to_irq[unit]); } } +#endif } static int diff --git a/sys/i386/isa/wd.c b/sys/i386/isa/wd.c index fdf1fa6..9db2fee 100644 --- a/sys/i386/isa/wd.c +++ b/sys/i386/isa/wd.c @@ -34,7 +34,7 @@ * SUCH DAMAGE. * * from: @(#)wd.c 7.2 (Berkeley) 5/9/91 - * $Id: wd.c,v 1.192 1999/04/13 19:38:11 peter Exp $ + * $Id: wd.c,v 1.193 1999/04/13 20:22:30 peter Exp $ */ /* TODO: @@ -73,6 +73,7 @@ #include <sys/systm.h> #include <sys/kernel.h> #include <sys/conf.h> +#include <sys/bus.h> #include <sys/disklabel.h> #include <sys/diskslice.h> #include <sys/buf.h> @@ -400,10 +401,10 @@ wdattach(struct isa_device *dvp) #if defined(DEVFS) int mynor; #endif - u_int unit, lunit; - struct isa_device *wdup; + int unit, lunit, flags, i; struct disk *du; struct wdparams *wp; + static char buf[] = "wdcXXX"; dvp->id_intr = wdintr; @@ -418,14 +419,22 @@ wdattach(struct isa_device *dvp) } else bufq_init(&wdtab[dvp->id_unit].controller_queue); - for (wdup = isa_biotab_wdc; wdup->id_driver != 0; wdup++) { - if (wdup->id_iobase != dvp->id_iobase) + sprintf(buf, "wdc%d", dvp->id_unit); + for (i = resource_query_string(-1, "at", buf); + i != -1; + i = resource_query_string(i, "at", buf)) { + if (strcmp(resource_query_name(i), "wd")) + /* Avoid a bit of foot shooting. */ continue; - lunit = wdup->id_unit; + + lunit = resource_query_unit(i); if (lunit >= NWD) continue; - unit = wdup->id_physid; + if (resource_int_value("wd", lunit, "drive", &unit) != 0) + continue; + if (resource_int_value("wd", lunit, "flags", &flags) != 0) + flags = 0; du = malloc(sizeof *du, M_TEMP, M_NOWAIT); if (du == NULL) @@ -450,7 +459,7 @@ wdattach(struct isa_device *dvp) * Use the individual device flags or the controller * flags. */ - du->cfg_flags = wdup->id_flags | + du->cfg_flags = flags | ((dvp->id_flags) >> (16 * unit)); if (wdgetctlr(du) == 0) { diff --git a/sys/isa/atkbd_isa.c b/sys/isa/atkbd_isa.c index ade1ba0..1d7ee62 100644 --- a/sys/isa/atkbd_isa.c +++ b/sys/isa/atkbd_isa.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: atkbd_isa.c,v 1.1 1999/01/23 16:53:27 dfr Exp $ + * $Id: atkbd_isa.c,v 1.2 1999/03/10 10:36:49 yokota Exp $ */ #include "atkbd.h" @@ -37,6 +37,7 @@ #include <sys/conf.h> #include <sys/tty.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #include <machine/resource.h> @@ -70,9 +71,9 @@ static driver_t atkbd_driver = { static int atkbdprobe(device_t dev) { - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; device_set_desc(dev, "AT Keyboard"); @@ -89,9 +90,9 @@ static int atkbdattach(device_t dev) { atkbd_softc_t *sc; - u_long port; - u_long irq; - u_long flags; + uintptr_t port; + uintptr_t irq; + uintptr_t flags; struct resource *res; void *ih; int zero = 0; diff --git a/sys/isa/fd.c b/sys/isa/fd.c index 07223f1..0414b18 100644 --- a/sys/isa/fd.c +++ b/sys/isa/fd.c @@ -47,7 +47,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fd.c,v 1.133 1999/02/10 00:03:32 ken Exp $ + * $Id: fd.c,v 1.134 1999/04/06 03:06:51 peter Exp $ * */ @@ -60,26 +60,37 @@ #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> +#include <sys/buf.h> +#include <sys/bus.h> #include <sys/conf.h> -#include <sys/fcntl.h> -#include <machine/clock.h> -#include <machine/ioctl_fd.h> #include <sys/disklabel.h> -#include <sys/buf.h> #include <sys/devicestat.h> +#include <sys/fcntl.h> #include <sys/malloc.h> +#include <sys/module.h> #include <sys/proc.h> #include <sys/syslog.h> -#include <i386/isa/isa.h> -#include <i386/isa/isa_device.h> -#include <i386/isa/fdreg.h> -#include <i386/isa/fdc.h> -#include <i386/isa/rtc.h> + +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> + +#include <machine/clock.h> +#include <machine/ioctl_fd.h> +#include <machine/resource.h> #include <machine/stdarg.h> + #ifdef DEVFS #include <sys/devfsext.h> #endif /* DEVFS */ +#include <isa/isavar.h> +#include <i386/isa/isa.h> +#include <i386/isa/isa_dma.h> +#include <i386/isa/fdreg.h> +#include <i386/isa/fdc.h> +#include <i386/isa/rtc.h> + /* misuse a flag to identify format operation */ #define B_FORMAT B_XXX @@ -151,13 +162,13 @@ static struct fd_type fd_types[NUMTYPES] = /***********************************************************************\ * Per controller structure. * \***********************************************************************/ -struct fdc_data fdc_data[NFDC]; +static devclass_t fdc_devclass; /***********************************************************************\ * Per drive structure. * * N per controller (DRVS_PER_CTLR) * \***********************************************************************/ -static struct fd_data { +struct fd_data { struct fdc_data *fdc; /* pointer to controller structure */ int fdsu; /* this units number on this controller */ int type; /* Drive type (FD_1440...) */ @@ -179,7 +190,10 @@ static struct fd_data { void *bdevs[1 + NUMDENS + MAXPARTITIONS]; void *cdevs[1 + NUMDENS + MAXPARTITIONS]; #endif -} fd_data[NFD]; + device_t dev; + fdu_t fdu; +}; +static devclass_t fd_devclass; /***********************************************************************\ * Throughout this file the following conventions will be used: * @@ -195,29 +209,26 @@ static struct fd_data { static int yeattach(struct isa_device *); #endif -/* autoconfig functions */ -static int fdprobe(struct isa_device *); -static int fdattach(struct isa_device *); - /* needed for ft driver, thus exported */ -int in_fdc(fdcu_t); -int out_fdc(fdcu_t, int); +int in_fdc(struct fdc_data *); +int out_fdc(struct fdc_data *, int); /* internal functions */ -static void set_motor(fdcu_t, int, int); +static void fdc_add_device(device_t, const char *, int); +static void fdc_intr(void *); +static void set_motor(struct fdc_data *, int, int); # define TURNON 1 # define TURNOFF 0 static timeout_t fd_turnoff; static timeout_t fd_motor_on; -static void fd_turnon(fdu_t); +static void fd_turnon(struct fd_data *); static void fdc_reset(fdc_p); -static int fd_in(fdcu_t, int *); -static void fdstart(fdcu_t); +static int fd_in(struct fdc_data *, int *); +static void fdstart(struct fdc_data *); static timeout_t fd_iotimeout; static timeout_t fd_pseudointr; -static ointhand2_t fdintr; -static int fdstate(fdcu_t, fdc_p); -static int retrier(fdcu_t); +static int fdstate(struct fdc_data *); +static int retrier(struct fdc_data *); static int fdformat(dev_t, struct fd_formb *, struct proc *); static int enable_fifo(fdc_p fdc); @@ -356,13 +367,6 @@ static int yeintr(struct pccard_devinfo *devi) #endif /* NCARD > 0 */ #endif /* FDC_YE */ - -/* autoconfig structure */ - -struct isa_driver fdcdriver = { - fdprobe, fdattach, "fdc", -}; - static d_open_t Fdopen; /* NOTE, not fdopen */ static d_read_t fdread; static d_write_t fdwrite; @@ -374,28 +378,18 @@ static d_strategy_t fdstrategy; #define CDEV_MAJOR 9 #define BDEV_MAJOR 2 - -static struct cdevsw fd_cdevsw = { - Fdopen, fdclose, fdread, fdwrite, - fdioctl, nostop, nullreset, nodevtotty, - seltrue, nommap, fdstrategy, "fd", - NULL, -1, nodump, nopsize, - D_DISK, 0, -1 }; - - -static struct isa_device *fdcdevs[NFDC]; - - static int -fdc_err(fdcu_t fdcu, const char *s) +fdc_err(struct fdc_data *fdc, const char *s) { - fdc_data[fdcu].fdc_errs++; - if(s) { - if(fdc_data[fdcu].fdc_errs < FDC_ERRMAX) - printf("fdc%d: %s", fdcu, s); - else if(fdc_data[fdcu].fdc_errs == FDC_ERRMAX) - printf("fdc%d: too many errors, not logging any more\n", - fdcu); + fdc->fdc_errs++; + if (s) { + if (fdc->fdc_errs < FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("%s", s); + } else if (fdc->fdc_errs == FDC_ERRMAX) { + device_print_prettyname(fdc->fdc_dev); + printf("too many errors, not logging any more\n"); + } } return FD_FAILED; @@ -407,9 +401,8 @@ fdc_err(fdcu_t fdcu, const char *s) * # of output bytes, output bytes as ints ..., * # of input bytes, input bytes as ints ... */ - static int -fd_cmd(fdcu_t fdcu, int n_out, ...) +fd_cmd(struct fdc_data *fdc, int n_out, ...) { u_char cmd; int n_in; @@ -422,26 +415,26 @@ fd_cmd(fdcu_t fdcu, int n_out, ...) va_start(ap, n_out); for (n = 0; n < n_out; n++) { - if (out_fdc(fdcu, va_arg(ap, int)) < 0) + if (out_fdc(fdc, va_arg(ap, int)) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %x failed at out byte %d of %d\n", cmd, n + 1, n_out); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } n_in = va_arg(ap, int); for (n = 0; n < n_in; n++) { int *ptr = va_arg(ap, int *); - if (fd_in(fdcu, ptr) < 0) + if (fd_in(fdc, ptr) < 0) { char msg[50]; snprintf(msg, sizeof(msg), "cmd %02x failed at in byte %d of %d\n", cmd, n + 1, n_in); - return fdc_err(fdcu, msg); + return fdc_err(fdc, msg); } } @@ -462,8 +455,8 @@ enable_fifo(fdc_p fdc) * first byte, and check for an early turn of data directon. */ - if (out_fdc(fdc->fdcu, I8207X_CONFIGURE) < 0) - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + if (out_fdc(fdc, I8207X_CONFIGURE) < 0) + return fdc_err(fdc, "Enable FIFO failed\n"); /* If command is invalid, return */ j = 100000; @@ -474,17 +467,17 @@ enable_fifo(fdc_p fdc) return FD_FAILED; } if (j<0 || - fd_cmd(fdc->fdcu, 3, + fd_cmd(fdc, 3, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) { fdc_reset(fdc); - return fdc_err(fdc->fdcu, "Enable FIFO failed\n"); + return fdc_err(fdc, "Enable FIFO failed\n"); } fdc->flags |= FDC_HAS_FIFO; return 0; } - if (fd_cmd(fdc->fdcu, 4, + if (fd_cmd(fdc, 4, I8207X_CONFIGURE, 0, (fifo_threshold - 1) & 0xf, 0, 0) < 0) - return fdc_err(fdc->fdcu, "Re-enable FIFO failed\n"); + return fdc_err(fdc, "Re-enable FIFO failed\n"); return 0; } @@ -493,9 +486,9 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) { int st3; - if (fd_cmd(fdc->fdcu, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) + if (fd_cmd(fdc, 2, NE7CMD_SENSED, fdc->fdu, 1, &st3)) { - return fdc_err(fdc->fdcu, "Sense Drive Status failed\n"); + return fdc_err(fdc, "Sense Drive Status failed\n"); } if (st3p) *st3p = st3; @@ -506,13 +499,11 @@ fd_sense_drive_status(fdc_p fdc, int *st3p) static int fd_sense_int(fdc_p fdc, int *st0p, int *cylp) { - int st0, cyl; + int cyl, st0, ret; - int ret = fd_cmd(fdc->fdcu, 1, NE7CMD_SENSEI, 1, &st0); - - if (ret) - { - (void)fdc_err(fdc->fdcu, + ret = fd_cmd(fdc, 1, NE7CMD_SENSEI, 1, &st0); + if (ret) { + (void)fdc_err(fdc, "sense intr err reading stat reg 0\n"); return ret; } @@ -520,17 +511,15 @@ fd_sense_int(fdc_p fdc, int *st0p, int *cylp) if (st0p) *st0p = st0; - if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) - { + if ((st0 & NE7_ST0_IC) == NE7_ST0_IC_IV) { /* * There doesn't seem to have been an interrupt. */ return FD_NOT_VALID; } - if (fd_in(fdc->fdcu, &cyl) < 0) - { - return fdc_err(fdc->fdcu, "can't get cyl num\n"); + if (fd_in(fdc, &cyl) < 0) { + return fdc_err(fdc, "can't get cyl num\n"); } if (cylp) @@ -545,8 +534,7 @@ fd_read_status(fdc_p fdc, int fdsu) { int i, ret; - for (i = 0; i < 7; i++) - { + for (i = 0; i < 7; i++) { /* * XXX types are poorly chosen. Only bytes can by read * from the hardware, but fdc->status[] wants u_ints and @@ -554,7 +542,7 @@ fd_read_status(fdc_p fdc, int fdsu) */ int status; - ret = fd_in(fdc->fdcu, &status); + ret = fd_in(fdc, &status); fdc->status[i] = status; if (ret != 0) break; @@ -572,34 +560,92 @@ fd_read_status(fdc_p fdc, int fdsu) /* autoconfiguration stuff */ /****************************************************************************/ -/* - * probe for existance of controller - */ static int -fdprobe(struct isa_device *dev) +fdc_probe(device_t dev) { - fdcu_t fdcu = dev->id_unit; - if(fdc_data[fdcu].flags & FDC_ATTACHED) - { - printf("fdc%d: unit used multiple times\n", fdcu); - return 0; + int error, i, ic_type; + struct fdc_data *fdc; + char myname[8]; /* better be long enough */ + + fdc = device_get_softc(dev); + bzero(fdc, sizeof *fdc); + fdc->fdc_dev = dev; + fdc->rid_ioport = fdc->rid_irq = fdc->rid_drq = 0; + fdc->res_ioport = fdc->res_irq = fdc->res_drq = 0; + + fdc->res_ioport = bus_alloc_resource(dev, SYS_RES_IOPORT, + &fdc->rid_ioport, 0ul, ~0ul, + IO_FDCSIZE, RF_ACTIVE); + if (fdc->res_ioport == 0) { + device_print_prettyname(dev); + printf("cannot reserve I/O port range\n"); + error = ENXIO; + goto out; } - - fdcdevs[fdcu] = dev; - fdc_data[fdcu].baseport = dev->id_iobase; + fdc->baseport = fdc->res_ioport->r_start; + + fdc->res_irq = bus_alloc_resource(dev, SYS_RES_IRQ, + &fdc->rid_irq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_irq == 0) { + device_print_prettyname(dev); + printf("cannot reserve interrupt line\n"); + error = ENXIO; + goto out; + } + fdc->res_drq = bus_alloc_resource(dev, SYS_RES_DRQ, + &fdc->rid_drq, 0ul, ~0ul, 1, + RF_ACTIVE); + if (fdc->res_drq == 0) { + device_print_prettyname(dev); + printf("cannot reserve DMA request line\n"); + error = ENXIO; + goto out; + } + fdc->dmachan = fdc->res_drq->r_start; + error = BUS_SETUP_INTR(device_get_parent(dev), dev, + fdc->res_irq, fdc_intr, fdc, &fdc->fdc_intr); /* First - lets reset the floppy controller */ - outb(dev->id_iobase+FDOUT, 0); + outb(fdc->baseport + FDOUT, 0); DELAY(100); - outb(dev->id_iobase+FDOUT, FDO_FRST); + outb(fdc->baseport + FDOUT, FDO_FRST); /* see if it can handle a command */ - if (fd_cmd(fdcu, - 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), - 0)) - { - return(0); + if (fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), + NE7_SPEC_2(2, 0), 0)) { + error = ENXIO; + goto out; + } + + if (fd_cmd(fdc, 1, NE7CMD_VERSION, 1, &ic_type) == 0) { + ic_type = (u_char)ic_type; + switch (ic_type) { + case 0x80: + device_set_desc(dev, "NEC 765 or clone"); + fdc->fdct = FDC_NE765; + break; + case 0x81: + device_set_desc(dev, "Intel 82077 or clone"); + fdc->fdct = FDC_I82077; + break; + case 0x90: + device_set_desc(dev, "NEC 72065B or clone"); + fdc->fdct = FDC_NE72065; + break; + default: + device_set_desc(dev, "generic floppy controller"); + fdc->fdct = FDC_UNKNOWN; + break; + } } + + snprintf(myname, sizeof(myname), "%s%d", device_get_name(dev), + device_get_unit(dev)); + for (i = resource_query_string(-1, "at", myname); i != -1; + i = resource_query_string(i, "at", myname)) + fdc_add_device(dev, resource_query_name(i), + resource_query_unit(i)); #ifdef FDC_YE /* * don't succeed on probe; wait @@ -608,277 +654,312 @@ fdprobe(struct isa_device *dev) if (dev->id_flags & FDC_IS_PCMCIA) return(0); #endif - return (IO_FDCSIZE); + return (0); + +out: + if (fdc->fdc_intr) + BUS_TEARDOWN_INTR(device_get_parent(dev), dev, fdc->res_irq, + fdc->fdc_intr); + if (fdc->res_irq != 0) { + bus_deactivate_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + bus_release_resource(dev, SYS_RES_IRQ, fdc->rid_irq, + fdc->res_irq); + } + if (fdc->res_ioport != 0) { + bus_deactivate_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + bus_release_resource(dev, SYS_RES_IOPORT, fdc->rid_ioport, + fdc->res_ioport); + } + if (fdc->res_drq != 0) { + bus_deactivate_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + bus_release_resource(dev, SYS_RES_DRQ, fdc->rid_drq, + fdc->res_drq); + } + return (error); } /* - * wire controller into system, look for floppy units + * Aped dfr@freebsd.org's isa_add_device(). */ +static void +fdc_add_device(device_t dev, const char *name, int unit) +{ + int disabled, *ivar; + device_t child; + + ivar = malloc(sizeof *ivar, M_DEVBUF /* XXX */, M_NOWAIT); + if (ivar == 0) + return; + if (resource_int_value(name, unit, "drive", ivar) == 0) + *ivar = 0; + child = device_add_child(dev, name, unit, ivar); + if (child == 0) + return; + if (resource_int_value(name, unit, "disabled", &disabled) == 0) + device_disable(child); +} + static int -fdattach(struct isa_device *dev) +fdc_attach(device_t dev) { - unsigned fdt; - fdu_t fdu; - fdcu_t fdcu = dev->id_unit; - fdc_p fdc = fdc_data + fdcu; - fd_p fd; - int fdsu, st0, st3, i; - struct isa_device *fdup; - int ic_type = 0; -#ifdef DEVFS - int mynor; - int typemynor; - int typesize; -#endif + struct fdc_data *fdc = device_get_softc(dev); + fdcu_t fdcu = device_get_unit(dev); - dev->id_ointr = fdintr; fdc->fdcu = fdcu; fdc->flags |= FDC_ATTACHED; - fdc->dmachan = dev->id_drq; + /* Acquire the DMA channel forever, The driver will do the rest */ + /* XXX should integrate with rman */ isa_dma_acquire(fdc->dmachan); isa_dmainit(fdc->dmachan, 128 << 3 /* XXX max secsize */); fdc->state = DEVIDLE; + /* reset controller, turn motor off, clear fdout mirror reg */ outb(fdc->baseport + FDOUT, ((fdc->fdout = 0))); bufq_init(&fdc->head); - /* check for each floppy drive */ - for (fdup = isa_biotab_fdc; fdup->id_driver != 0; fdup++) { - if (fdup->id_iobase != dev->id_iobase) - continue; - fdu = fdup->id_unit; - fd = &fd_data[fdu]; - if (fdu >= (NFD)) - continue; - fdsu = fdup->id_physid; - /* look up what bios thinks we have */ - switch (fdu) { - case 0: if (dev->id_flags & FDC_PRETEND_D0) - fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; - else - fdt = (rtcin(RTC_FDISKETTE) & 0xf0); - break; - case 1: fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); - break; - default: fdt = RTCFDT_NONE; - break; - } - /* is there a unit? */ - if ((fdt == RTCFDT_NONE) - ) { - fd->type = NO_TYPE; - continue; - } +#ifdef FIFO_BEFORE_MOTORON + /* Hmm, this doesn't work here - is set_motor() magic? -Peter */ + if (fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(dev); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } +#endif + /* + * Probe and attach any children as were configured above. + */ + return (bus_generic_attach(dev)); +} - /* select it */ - set_motor(fdcu, fdsu, TURNON); - DELAY(1000000); /* 1 sec */ +static void +fdc_print_child(device_t me, device_t child) +{ + printf(" at %s%d drive %d", device_get_name(me), device_get_unit(me), + *(int *)device_get_ivars(child)); +} - if (ic_type == 0 && - fd_cmd(fdcu, 1, NE7CMD_VERSION, 1, &ic_type) == 0) - { -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("fdc%d: ", fdcu); -#endif - ic_type = (u_char)ic_type; - switch( ic_type ) { - case 0x80: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 765\n"); -#endif - fdc->fdct = FDC_NE765; - break; - case 0x81: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("Intel 82077\n"); -#endif - fdc->fdct = FDC_I82077; - break; - case 0x90: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("NEC 72065B\n"); +static int +fd_probe(device_t dev) +{ + int i; + u_int fdt, st0, st3; + struct fd_data *fd; + struct fdc_data *fdc; + fdsu_t fdsu; +#ifndef FIFO_BEFORE_MOTORON + static int fd_fifo = 0; #endif - fdc->fdct = FDC_NE72065; - break; - default: -#ifdef FDC_PRINT_BOGUS_CHIPTYPE - printf("unknown IC type %02x\n", ic_type); + + fdsu = *(int *)device_get_ivars(dev); /* xxx cheat a bit... */ + fd = device_get_softc(dev); + fdc = device_get_softc(device_get_parent(dev)); + + bzero(fd, sizeof *fd); + fd->dev = dev; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->fdu = device_get_unit(dev); + + /* look up what bios thinks we have */ + switch (fd->fdu) { + case 0: + if (isa_get_flags(fdc->fdc_dev) & FDC_PRETEND_D0) + fdt = RTCFDT_144M | RTCFDT_144M_PRETENDED; + else + fdt = (rtcin(RTC_FDISKETTE) & 0xf0); + break; + case 1: + fdt = ((rtcin(RTC_FDISKETTE) << 4) & 0xf0); + break; + default: + fdt = RTCFDT_NONE; + break; + } + + /* is there a unit? */ + if (fdt == RTCFDT_NONE) + return (ENXIO); + + /* select it */ + set_motor(fdc, fdsu, TURNON); + DELAY(1000000); /* 1 sec */ + +#ifndef FIFO_BEFORE_MOTORON + if (fd_fifo == 0 && fdc->fdct != FDC_NE765 && fdc->fdct != FDC_UNKNOWN + && enable_fifo(fdc) == 0) { + device_print_prettyname(device_get_parent(dev)); + printf("FIFO enabled, %d bytes threshold\n", fifo_threshold); + } + fd_fifo = 1; #endif - fdc->fdct = FDC_UNKNOWN; - break; - } - if (fdc->fdct != FDC_NE765 && - fdc->fdct != FDC_UNKNOWN && - enable_fifo(fdc) == 0) { - printf("fdc%d: FIFO enabled", fdcu); - printf(", %d bytes threshold\n", - fifo_threshold); - } - } - if ((fd_cmd(fdcu, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* if at track 0, first seek inwards */ - /* seek some steps: */ - (void)fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0); - DELAY(300000); /* ...wait a moment... */ - (void)fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ - } - /* If we're at track 0 first seek inwards. */ - if ((fd_sense_drive_status(fdc, &st3) == 0) && - (st3 & NE7_ST3_T0)) { - /* Seek some steps... */ - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { - /* ...wait a moment... */ - DELAY(300000); - /* make ctrlr happy: */ - (void)fd_sense_int(fdc, 0, 0); - } + if ((fd_cmd(fdc, 2, NE7CMD_SENSED, fdsu, 1, &st3) == 0) + && (st3 & NE7_ST3_T0)) { + /* if at track 0, first seek inwards */ + /* seek some steps: */ + fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0); + DELAY(300000); /* ...wait a moment... */ + fd_sense_int(fdc, 0, 0); /* make ctrlr happy */ + } + + /* If we're at track 0 first seek inwards. */ + if ((fd_sense_drive_status(fdc, &st3) == 0) && (st3 & NE7_ST3_T0)) { + /* Seek some steps... */ + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fdsu, 10, 0) == 0) { + /* ...wait a moment... */ + DELAY(300000); + /* make ctrlr happy: */ + fd_sense_int(fdc, 0, 0); } + } - for(i = 0; i < 2; i++) { - /* - * we must recalibrate twice, just in case the - * heads have been beyond cylinder 76, since most - * FDCs still barf when attempting to recalibrate - * more than 77 steps - */ - /* go back to 0: */ - if (fd_cmd(fdcu, 2, NE7CMD_RECAL, fdsu, 0) == 0) { - /* a second being enough for full stroke seek*/ - DELAY(i == 0? 1000000: 300000); + for (i = 0; i < 2; i++) { + /* + * we must recalibrate twice, just in case the + * heads have been beyond cylinder 76, since most + * FDCs still barf when attempting to recalibrate + * more than 77 steps + */ + /* go back to 0: */ + if (fd_cmd(fdc, 2, NE7CMD_RECAL, fdsu, 0) == 0) { + /* a second being enough for full stroke seek*/ + DELAY(i == 0 ? 1000000 : 300000); - /* anything responding? */ - if (fd_sense_int(fdc, &st0, 0) == 0 && - (st0 & NE7_ST0_EC) == 0) - break; /* already probed succesfully */ - } + /* anything responding? */ + if (fd_sense_int(fdc, &st0, 0) == 0 && + (st0 & NE7_ST0_EC) == 0) + break; /* already probed succesfully */ } + } - set_motor(fdcu, fdsu, TURNOFF); + set_motor(fdc, fdsu, TURNOFF); - if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ - continue; + if (st0 & NE7_ST0_EC) /* no track 0 -> no drive present */ + return (ENXIO); - fd->track = FD_NO_TRACK; - fd->fdc = fdc; - fd->fdsu = fdsu; - fd->options = 0; - callout_handle_init(&fd->toffhandle); - callout_handle_init(&fd->tohandle); - printf("fd%d: ", fdu); - - switch (fdt) { - case RTCFDT_12M: - printf("1.2MB 5.25in\n"); - fd->type = FD_1200; - break; - case RTCFDT_144M | RTCFDT_144M_PRETENDED: - printf("config-pretended "); - fdt = RTCFDT_144M; - /* fallthrough */ - case RTCFDT_144M: - printf("1.44MB 3.5in\n"); - fd->type = FD_1440; + fd->track = FD_NO_TRACK; + fd->fdc = fdc; + fd->fdsu = fdsu; + fd->options = 0; + callout_handle_init(&fd->toffhandle); + callout_handle_init(&fd->tohandle); + + switch (fdt) { + case RTCFDT_12M: + device_set_desc(dev, "1200-KB 5.25\" drive"); + fd->type = FD_1200; + break; + case RTCFDT_144M | RTCFDT_144M_PRETENDED: + device_set_desc(dev, "config-pretended 1440-MB 3.5\" drive"); + fdt = RTCFDT_144M; + fd->type = FD_1440; + case RTCFDT_144M: + device_set_desc(dev, "1440-KB 3.5\" drive"); + fd->type = FD_1440; + break; + case RTCFDT_288M: + case RTCFDT_288M_1: + device_set_desc(dev, "2880-KB 3.5\" drive (in 1440-KB mode)"); + fd->type = FD_1440; + break; + case RTCFDT_360K: + device_set_desc(dev, "360-KB 5.25\" drive"); + fd->type = FD_360; + break; + case RTCFDT_720K: + printf("720-KB 3.5\" drive"); + fd->type = FD_720; + break; + default: + return (ENXIO); + } + return (0); +} + +static int +fd_attach(device_t dev) +{ + struct fd_data *fd; + + fd = device_get_softc(dev); + +#ifdef DEVFS /* XXX bitrot */ + mynor = fdu << 6; + fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d", fdu); + fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d", fdu); + for (i = 1; i < 1 + NUMDENS; i++) { + /* + * XXX this and the lookup in Fdopen() should be + * data driven. + */ + switch (fd->type) { + case FD_360: + if (i != FD_360) + continue; break; - case RTCFDT_288M: - case RTCFDT_288M_1: - printf("2.88MB 3.5in - 1.44MB mode\n"); - fd->type = FD_1440; + case FD_720: + if (i != FD_720 && i != FD_800 && i != FD_820) + continue; break; - case RTCFDT_360K: - printf("360KB 5.25in\n"); - fd->type = FD_360; + case FD_1200: + if (i != FD_360 && i != FD_720 && i != FD_800 + && i != FD_820 && i != FD_1200 + && i != FD_1440 && i != FD_1480) + continue; break; - case RTCFDT_720K: - printf("720KB 3.5in\n"); - fd->type = FD_720; + case FD_1440: + if (i != FD_720 && i != FD_800 && i != FD_820 + && i != FD_1200 && i != FD_1440 + && i != FD_1480 && i != FD_1720) + continue; break; - default: - printf("unknown\n"); - fd->type = NO_TYPE; - continue; } -#ifdef DEVFS - mynor = fdu << 6; - fd->bdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d", fdu); - fd->cdevs[0] = devfs_add_devswf(&fd_cdevsw, mynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d", fdu); - for (i = 1; i < 1 + NUMDENS; i++) { - /* - * XXX this and the lookup in Fdopen() should be - * data driven. - */ - switch (fd->type) { - case FD_360: - if (i != FD_360) - continue; - break; - case FD_720: - if (i != FD_720 && i != FD_800 && i != FD_820) - continue; - break; - case FD_1200: - if (i != FD_360 && i != FD_720 && i != FD_800 - && i != FD_820 && i != FD_1200 - && i != FD_1440 && i != FD_1480) - continue; - break; - case FD_1440: - if (i != FD_720 && i != FD_800 && i != FD_820 - && i != FD_1200 && i != FD_1440 - && i != FD_1480 && i != FD_1720) - continue; - break; - } - typesize = fd_types[i - 1].size / 2; - /* - * XXX all these conversions give bloated code and - * confusing names. - */ - if (typesize == 1476) - typesize = 1480; - if (typesize == 1722) - typesize = 1720; - typemynor = mynor | i; - fd->bdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, - UID_ROOT, GID_OPERATOR, 0640, - "fd%d.%d", fdu, typesize); - fd->cdevs[i] = - devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, - UID_ROOT, GID_OPERATOR, 0640, - "rfd%d.%d", fdu, typesize); - } - - for (i = 0; i < MAXPARTITIONS; i++) { - fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], - "fd%d%c", fdu, 'a' + i); - fd->cdevs[1 + NUMDENS + i] = - devfs_makelink(fd->cdevs[0], - "rfd%d%c", fdu, 'a' + i); - } -#endif /* DEVFS */ + typesize = fd_types[i - 1].size / 2; /* - * Export the drive to the devstat interface. + * XXX all these conversions give bloated code and + * confusing names. */ - devstat_add_entry(&fd->device_stats, "fd", - fdu, 512, - DEVSTAT_NO_ORDERED_TAGS, - DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, - DEVSTAT_PRIORITY_FD); - + if (typesize == 1476) + typesize = 1480; + if (typesize == 1722) + typesize = 1720; + typemynor = mynor | i; + fd->bdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_BLK, + UID_ROOT, GID_OPERATOR, 0640, + "fd%d.%d", fdu, typesize); + fd->cdevs[i] = + devfs_add_devswf(&fd_cdevsw, typemynor, DV_CHR, + UID_ROOT, GID_OPERATOR, 0640, + "rfd%d.%d", fdu, typesize); } - return (1); + for (i = 0; i < MAXPARTITIONS; i++) { + fd->bdevs[1 + NUMDENS + i] = devfs_makelink(fd->bdevs[0], + "fd%d%c", fdu, 'a' + i); + fd->cdevs[1 + NUMDENS + i] = + devfs_makelink(fd->cdevs[0], + "rfd%d%c", fdu, 'a' + i); + } +#endif /* DEVFS */ + /* + * Export the drive to the devstat interface. + */ + devstat_add_entry(&fd->device_stats, device_get_name(dev), + device_get_unit(dev), 512, DEVSTAT_NO_ORDERED_TAGS, + DEVSTAT_TYPE_FLOPPY | DEVSTAT_TYPE_IF_OTHER, + DEVSTAT_PRIORITY_FD); + return (0); } - - #ifdef FDC_YE /* * this is a subset of fdattach() optimized for the Y-E Data @@ -1016,9 +1097,9 @@ static int yeattach(struct isa_device *dev) /* remember to not deselect the drive we're working on */ /****************************************************************************/ static void -set_motor(fdcu_t fdcu, int fdsu, int turnon) +set_motor(struct fdc_data *fdc, int fdsu, int turnon) { - int fdout = fdc_data[fdcu].fdout; + int fdout = fdc->fdout; int needspecify = 0; if(turnon) { @@ -1038,83 +1119,78 @@ set_motor(fdcu_t fdcu, int fdsu, int turnon) fdout |= (FDO_FRST|FDO_FDMAEN); } - outb(fdc_data[fdcu].baseport+FDOUT, fdout); - fdc_data[fdcu].fdout = fdout; + outb(fdc->baseport+FDOUT, fdout); + fdc->fdout = fdout; TRACE1("[0x%x->FDOUT]", fdout); - if(needspecify) { + if (needspecify) { /* * XXX * special case: since we have just woken up the FDC * from its sleep, we silently assume the command will * be accepted, and do not test for a timeout */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); - if (fdc_data[fdcu].flags & FDC_HAS_FIFO) - (void) enable_fifo(&fdc_data[fdcu]); + if (fdc->flags & FDC_HAS_FIFO) + (void) enable_fifo(fdc); } } static void -fd_turnoff(void *arg1) +fd_turnoff(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; - fd_p fd = fd_data + fdu; + fd_p fd = xfd; - TRACE1("[fd%d: turnoff]", fdu); + TRACE1("[fd%d: turnoff]", fd->fdu); /* * Don't turn off the motor yet if the drive is active. * XXX shouldn't even schedule turnoff until drive is inactive * and nothing is queued on it. */ - if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fdu) { - fd->toffhandle = timeout(fd_turnoff, arg1, 4 * hz); + if (fd->fdc->state != DEVIDLE && fd->fdc->fdu == fd->fdu) { + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); return; } s = splbio(); fd->flags &= ~FD_MOTOR; - set_motor(fd->fdc->fdcu, fd->fdsu, TURNOFF); + set_motor(fd->fdc, fd->fdsu, TURNOFF); splx(s); } static void -fd_motor_on(void *arg1) +fd_motor_on(void *xfd) { - fdu_t fdu = (fdu_t)arg1; int s; + fd_p fd = xfd; - fd_p fd = fd_data + fdu; s = splbio(); fd->flags &= ~FD_MOTOR_WAIT; if((fd->fdc->fd == fd) && (fd->fdc->state == MOTORWAIT)) { - fdintr(fd->fdc->fdcu); + fdc_intr(fd->fdc); } splx(s); } static void -fd_turnon(fdu_t fdu) +fd_turnon(fd_p fd) { - fd_p fd = fd_data + fdu; if(!(fd->flags & FD_MOTOR)) { fd->flags |= (FD_MOTOR + FD_MOTOR_WAIT); - set_motor(fd->fdc->fdcu, fd->fdsu, TURNON); - timeout(fd_motor_on, (caddr_t)fdu, hz); /* in 1 sec its ok */ + set_motor(fd->fdc, fd->fdsu, TURNON); + timeout(fd_motor_on, fd, hz); /* in 1 sec its ok */ } } static void fdc_reset(fdc_p fdc) { - fdcu_t fdcu = fdc->fdcu; - /* Try a reset, keep motor on */ outb(fdc->baseport + FDOUT, fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); TRACE1("[0x%x->FDOUT]", fdc->fdout & ~(FDO_FRST|FDO_FDMAEN)); @@ -1127,7 +1203,7 @@ fdc_reset(fdc_p fdc) TRACE1("[0x%x->FDOUT]", fdc->fdout); /* XXX after a reset, silently believe the FDC will accept commands */ - (void)fd_cmd(fdcu, 3, NE7CMD_SPECIFY, + (void)fd_cmd(fdc, 3, NE7CMD_SPECIFY, NE7_SPEC_1(3, 240), NE7_SPEC_2(2, 0), 0); if (fdc->flags & FDC_HAS_FIFO) @@ -1138,16 +1214,16 @@ fdc_reset(fdc_p fdc) /* fdc in/out */ /****************************************************************************/ int -in_fdc(fdcu_t fdcu) +in_fdc(struct fdc_data *fdc) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1161,16 +1237,16 @@ in_fdc(fdcu_t fdcu) * fd_in: Like in_fdc, but allows you to see if it worked. */ static int -fd_in(fdcu_t fdcu, int *ptr) +fd_in(struct fdc_data *fdc, int *ptr) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i, j = 100000; while ((i = inb(baseport+FDSTS) & (NE7_DIO|NE7_RQM)) != (NE7_DIO|NE7_RQM) && j-- > 0) if (i == NE7_RQM) - return fdc_err(fdcu, "ready for output in input\n"); + return fdc_err(fdc, "ready for output in input\n"); if (j <= 0) - return fdc_err(fdcu, bootverbose? "input ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "input ready timeout\n": 0); #ifdef FDC_DEBUG i = inb(baseport+FDDATA); TRACE1("[FDDATA->0x%x]", (unsigned char)i); @@ -1185,21 +1261,21 @@ fd_in(fdcu_t fdcu, int *ptr) } int -out_fdc(fdcu_t fdcu, int x) +out_fdc(struct fdc_data *fdc, int x) { - int baseport = fdc_data[fdcu].baseport; + int baseport = fdc->baseport; int i; /* Check that the direction bit is set */ i = 100000; while ((inb(baseport+FDSTS) & NE7_DIO) && i-- > 0); - if (i <= 0) return fdc_err(fdcu, "direction bit not set\n"); + if (i <= 0) return fdc_err(fdc, "direction bit not set\n"); /* Check that the floppy controller is ready for a command */ i = 100000; while ((inb(baseport+FDSTS) & NE7_RQM) == 0 && i-- > 0); if (i <= 0) - return fdc_err(fdcu, bootverbose? "output ready timeout\n": 0); + return fdc_err(fdc, bootverbose? "output ready timeout\n": 0); /* Send the command and return */ outb(baseport+FDDATA, x); @@ -1215,32 +1291,33 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); int type = FDTYPE(minor(dev)); + fd_p fd; fdc_p fdc; /* check bounds */ - if (fdu >= NFD) - return(ENXIO); - fdc = fd_data[fdu].fdc; - if ((fdc == NULL) || (fd_data[fdu].type == NO_TYPE)) - return(ENXIO); + if ((fd = devclass_get_softc(fd_devclass, fdu)) == 0) + return (ENXIO); + fdc = fd->fdc; + if ((fdc == NULL) || (fd->type == NO_TYPE)) + return (ENXIO); if (type > NUMDENS) - return(ENXIO); + return (ENXIO); if (type == 0) - type = fd_data[fdu].type; + type = fd->type; else { /* * For each type of basic drive, make sure we are trying * to open a type it can do, */ - if (type != fd_data[fdu].type) { - switch (fd_data[fdu].type) { + if (type != fd->type) { + switch (fd->type) { case FD_360: - return(ENXIO); + return (ENXIO); case FD_720: if ( type != FD_820 && type != FD_800 ) - return(ENXIO); + return (ENXIO); break; case FD_1200: switch (type) { @@ -1279,9 +1356,10 @@ Fdopen(dev_t dev, int flags, int mode, struct proc *p) } } } - fd_data[fdu].ft = fd_types + type - 1; - fd_data[fdu].flags |= FD_OPEN; - + fd->ft = fd_types + type - 1; + fd->flags |= FD_OPEN; + device_busy(fd->dev); + device_busy(fd->fdc->fdc_dev); return 0; } @@ -1289,11 +1367,13 @@ int fdclose(dev_t dev, int flags, int mode, struct proc *p) { fdu_t fdu = FDUNIT(minor(dev)); + struct fd_data *fd; - fd_data[fdu].flags &= ~FD_OPEN; - fd_data[fdu].options &= ~FDOPT_NORETRY; + fd = devclass_get_softc(fd_devclass, fdu); + fd->flags &= ~FD_OPEN; + fd->options &= ~FDOPT_NORETRY; - return(0); + return (0); } static int @@ -1317,16 +1397,17 @@ fdstrategy(struct buf *bp) { unsigned nblocks, blknum, cando; int s; - fdcu_t fdcu; fdu_t fdu; fdc_p fdc; fd_p fd; size_t fdblk; fdu = FDUNIT(minor(bp->b_dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); + if (fd == 0) + panic("fdstrategy: buf for nonexistent device (%#lx, %#lx)", + (u_long)major(bp->b_dev), (u_long)minor(bp->b_dev)); fdc = fd->fdc; - fdcu = fdc->fdcu; #ifdef FDC_YE if (fd->type == NO_TYPE) { bp->b_error = ENXIO; @@ -1341,7 +1422,7 @@ fdstrategy(struct buf *bp) fdblk = 128 << (fd->ft->secsize); if (!(bp->b_flags & B_FORMAT)) { - if ((fdu >= NFD) || (bp->b_blkno < 0)) { + if (bp->b_blkno < 0) { printf( "fd%d: fdstrat: bad request blkno = %lu, bcount = %ld\n", fdu, (u_long)bp->b_blkno, bp->b_bcount); @@ -1386,12 +1467,12 @@ fdstrategy(struct buf *bp) bp->b_pblkno = bp->b_blkno; s = splbio(); bufqdisksort(&fdc->head, bp); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); /* a good idea */ + untimeout(fd_turnoff, fd, fd->toffhandle); /* a good idea */ /* Tell devstat we are starting on the transaction */ devstat_start_transaction(&fd->device_stats); - fdstart(fdcu); + fdstart(fdc); splx(s); return; @@ -1409,27 +1490,25 @@ bad: * will pick up our work when the present work completes * \***************************************************************/ static void -fdstart(fdcu_t fdcu) +fdstart(struct fdc_data *fdc) { int s; s = splbio(); - if(fdc_data[fdcu].state == DEVIDLE) + if(fdc->state == DEVIDLE) { - fdintr(fdcu); + fdc_intr(fdc); } splx(s); } static void -fd_iotimeout(void *arg1) +fd_iotimeout(void *xfdc) { fdc_p fdc; - fdcu_t fdcu; int s; - fdcu = (fdcu_t)arg1; - fdc = fdc_data + fdcu; + fdc = xfdc; TRACE1("fd%d[fd_iotimeout()]", fdc->fdu); /* @@ -1447,19 +1526,18 @@ fd_iotimeout(void *arg1) fdc->status[0] = NE7_ST0_IC_IV; fdc->flags &= ~FDC_STAT_VALID; fdc->state = IOTIMEDOUT; - fdintr(fdcu); + fdc_intr(fdc); splx(s); } /* just ensure it has the right spl */ static void -fd_pseudointr(void *arg1) +fd_pseudointr(void *xfdc) { - fdcu_t fdcu = (fdcu_t)arg1; int s; s = splbio(); - fdintr(fdcu); + fdc_intr(xfdc); splx(s); } @@ -1469,11 +1547,11 @@ fd_pseudointr(void *arg1) * ALWAYS called at SPLBIO * \***********************************************************************/ static void -fdintr(fdcu_t fdcu) +fdc_intr(void *xfdc) { - fdc_p fdc = fdc_data + fdcu; - while(fdstate(fdcu, fdc)) - ; + fdc_p fdc = xfdc; + while(fdstate(fdc)) + ; } #ifdef FDC_YE @@ -1513,7 +1591,7 @@ static int fdcpio(fdcu_t fdcu, long flags, caddr_t addr, u_int count) * if it returns a non zero value, it should be called again immediatly * \***********************************************************************/ static int -fdstate(fdcu_t fdcu, fdc_p fdc) +fdstate(fdc_p fdc) { int read, format, head, i, sec = 0, sectrac, st0, cyl, st3; unsigned blknum = 0, b_cylinder = 0; @@ -1537,26 +1615,25 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * Force into the IDLE state, * \***********************************************/ fdc->state = DEVIDLE; - if(fdc->fd) - { - printf("fd%d: unexpected valid fd pointer\n", - fdc->fdu); + if (fdc->fd) { + device_print_prettyname(fdc->fdc_dev); + printf("unexpected valid fd pointer\n"); fdc->fd = (fd_p) 0; fdc->fdu = -1; } - TRACE1("[fdc%d IDLE]", fdcu); - return(0); + TRACE1("[fdc%d IDLE]", fdc->fdcu); + return (0); } fdu = FDUNIT(minor(bp->b_dev)); - fd = fd_data + fdu; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; - if (fdc->fd && (fd != fdc->fd)) - { - printf("fd%d: confused fd pointers\n", fdu); + if (fdc->fd && (fd != fdc->fd)) { + device_print_prettyname(fd->dev); + printf("confused fd pointers\n"); } read = bp->b_flags & B_READ; format = bp->b_flags & B_FORMAT; - if(format) { + if (format) { finfo = (struct fd_formb *)bp->b_data; fd->skip = (char *)&(finfo->fd_formb_cylno(0)) - (char *)finfo; @@ -1569,8 +1646,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) TRACE1("fd%d", fdu); TRACE1("[%s]", fdstates[fdc->state]); TRACE1("(0x%x)", fd->flags); - untimeout(fd_turnoff, (caddr_t)fdu, fd->toffhandle); - fd->toffhandle = timeout(fd_turnoff, (caddr_t)fdu, 4 * hz); + untimeout(fd_turnoff, fd, fd->toffhandle); + fd->toffhandle = timeout(fd_turnoff, fd, 4 * hz); switch (fdc->state) { case DEVIDLE: @@ -1585,10 +1662,9 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * If the next drive has a motor startup pending, then * * it will start up in its own good time * \*******************************************************/ - if(fd->flags & FD_MOTOR_WAIT) - { + if(fd->flags & FD_MOTOR_WAIT) { fdc->state = MOTORWAIT; - return(0); /* come back later */ + return (0); /* come back later */ } /*******************************************************\ * Maybe if it's not starting, it SHOULD be starting * @@ -1596,12 +1672,12 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (!(fd->flags & FD_MOTOR)) { fdc->state = MOTORWAIT; - fd_turnon(fdu); - return(0); + fd_turnon(fd); + return (0); } else /* at least make sure we are selected */ { - set_motor(fdcu, fd->fdsu, TURNON); + set_motor(fdc, fd->fdsu, TURNON); } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1615,7 +1691,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = SEEKCOMPLETE; break; } - if (fd_cmd(fdcu, 3, NE7CMD_SEEK, + if (fd_cmd(fdc, 3, NE7CMD_SEEK, fd->fdsu, b_cylinder * fd->ft->steptrac, 0)) { @@ -1624,20 +1700,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) * the FDC went off to the Saints... */ fdc->retry = 6; /* try a reset */ - return(retrier(fdcu)); + return(retrier(fdc)); } fd->track = FD_NO_TRACK; fdc->state = SEEKWAIT; return(0); /* will return later */ case SEEKWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 16); + timeout(fd_pseudointr, fdc, hz / 16); fdc->state = SEEKCOMPLETE; return(0); /* will return later */ case SEEKCOMPLETE : /* SEEK DONE, START DMA */ /* Make sure seek really happened*/ - if(fd->track == FD_NO_TRACK) - { + if(fd->track == FD_NO_TRACK) { int descyl = b_cylinder * fd->ft->steptrac; do { /* @@ -1669,8 +1744,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) return 0; /* hope for a real intr */ } while ((st0 & NE7_ST0_IC) == NE7_ST0_IC_RC); - if (0 == descyl) - { + if (0 == descyl) { int failed = 0; /* * seek to cyl 0 requested; make sure we are @@ -1685,22 +1759,20 @@ fdstate(fdcu_t fdcu, fdc_p fdc) failed = 1; } - if (failed) - { + if (failed) { if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } - if (cyl != descyl) - { + if (cyl != descyl) { printf( "fd%d: Seek to cyl %d failed; am at cyl %d (ST0 = 0x%x)\n", fdu, descyl, cyl, st0); if (fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } } @@ -1726,7 +1798,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; /* reset the beast */ - return(retrier(fdcu)); + return (retrier(fdc)); } if(st3 & NE7_ST3_WP) { @@ -1749,8 +1821,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) } } - if(format) - { + if (format) { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) (void)fdcpio(fdcu,bp->b_flags, @@ -1758,25 +1829,19 @@ fdstate(fdcu_t fdcu, fdc_p fdc) bp->b_bcount); #endif /* formatting */ - if(fd_cmd(fdcu, 6, - NE7CMD_FORMAT, - head << 2 | fdu, + if(fd_cmd(fdc, 6, NE7CMD_FORMAT, head << 2 | fdu, finfo->fd_formb_secshift, finfo->fd_formb_nsecs, finfo->fd_formb_gaplen, - finfo->fd_formb_fillbyte, - 0)) - { + finfo->fd_formb_fillbyte, 0)) { /* controller fell over */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } - } - else - { + } else { #ifdef FDC_YE if (fdc->flags & FDC_PCMCIA) { /* @@ -1795,7 +1860,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdblk); } #endif - if (fd_cmd(fdcu, 9, + if (fd_cmd(fdc, 9, (read ? NE7CMD_READ : NE7CMD_WRITE), head << 2 | fdu, /* head & unit */ fd->track, /* track */ @@ -1805,14 +1870,13 @@ fdstate(fdcu_t fdcu, fdc_p fdc) sectrac, /* sectors/track */ fd->ft->gap, /* gap size */ fd->ft->datalen, /* data length */ - 0)) - { + 0)) { /* the beast is sleeping again */ isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } } #ifdef FDC_YE @@ -1834,8 +1898,8 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ #endif fdc->state = IOCOMPLETE; - fd->tohandle = timeout(fd_iotimeout, (caddr_t)fdcu, hz); - return(0); /* will return later */ + fd->tohandle = timeout(fd_iotimeout, fdc, hz); + return (0); /* will return later */ #ifdef FDC_YE case PIOREAD: /* @@ -1847,16 +1911,15 @@ fdstate(fdcu_t fdcu, fdc_p fdc) /* FALLTHROUGH */ #endif case IOCOMPLETE: /* IO DONE, post-analyze */ - untimeout(fd_iotimeout, (caddr_t)fdcu, fd->tohandle); + untimeout(fd_iotimeout, fdc, fd->tohandle); - if (fd_read_status(fdc, fd->fdsu)) - { + if (fd_read_status(fdc, fd->fdsu)) { isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); if (fdc->retry < 6) fdc->retry = 6; /* force a reset */ - return retrier(fdcu); + return (retrier(fdc)); } fdc->state = IOTIMEDOUT; @@ -1869,8 +1932,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) #endif isa_dmadone(bp->b_flags, bp->b_data + fd->skip, format ? bp->b_bcount : fdblk, fdc->dmachan); - if (fdc->status[0] & NE7_ST0_IC) - { + if (fdc->status[0] & NE7_ST0_IC) { if ((fdc->status[0] & NE7_ST0_IC) == NE7_ST0_IC_AT && fdc->status[1] & NE7_ST1_OR) { /* @@ -1890,17 +1952,14 @@ fdstate(fdcu_t fdcu, fdc_p fdc) && fdc->status[2] & NE7_ST2_WC && fdc->retry < 3) fdc->retry = 3; /* force recalibrate */ - return(retrier(fdcu)); + return (retrier(fdc)); } /* All OK */ fd->skip += fdblk; - if (!format && fd->skip < bp->b_bcount - bp->b_resid) - { + if (!format && fd->skip < bp->b_bcount - bp->b_resid) { /* set up next transfer */ fdc->state = DOSEEK; - } - else - { + } else { /* ALL DONE */ fd->skip = 0; fdc->bp = NULL; @@ -1915,7 +1974,7 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->fdu = -1; fdc->state = FINDWORK; } - return(1); + return (1); case RESETCTLR: fdc_reset(fdc); fdc->retry++; @@ -1931,21 +1990,18 @@ fdstate(fdcu_t fdcu, fdc_p fdc) fdc->state = STARTRECAL; /* Fall through. */ case STARTRECAL: - if(fd_cmd(fdcu, - 2, NE7CMD_RECAL, fdu, - 0)) /* Recalibrate Function */ - { + if(fd_cmd(fdc, 2, NE7CMD_RECAL, fdu, 0)) { /* arrgl */ fdc->retry = 6; - return(retrier(fdcu)); + return (retrier(fdc)); } fdc->state = RECALWAIT; - return(0); /* will return later */ + return (0); /* will return later */ case RECALWAIT: /* allow heads to settle */ - timeout(fd_pseudointr, (caddr_t)fdcu, hz / 8); + timeout(fd_pseudointr, fdc, hz / 8); fdc->state = RECALCOMPLETE; - return(0); /* will return later */ + return (0); /* will return later */ case RECALCOMPLETE: do { /* @@ -1971,16 +2027,16 @@ fdstate(fdcu_t fdcu, fdc_p fdc) printf("fd%d: recal failed ST0 %b cyl %d\n", fdu, st0, NE7_ST0BITS, cyl); if(fdc->retry < 3) fdc->retry = 3; - return(retrier(fdcu)); + return (retrier(fdc)); } fd->track = 0; /* Seek (probably) necessary */ fdc->state = DOSEEK; - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ case MOTORWAIT: if(fd->flags & FD_MOTOR_WAIT) { - return(0); /* time's not up yet */ + return (0); /* time's not up yet */ } if (fdc->flags & FDC_NEEDS_RESET) { fdc->state = RESETCTLR; @@ -1993,9 +2049,10 @@ fdstate(fdcu_t fdcu, fdc_p fdc) */ fdc->state = STARTRECAL; } - return(1); /* will return immediatly */ + return (1); /* will return immediatly */ default: - printf("fdc%d: Unexpected FD int->", fdcu); + device_print_prettyname(fdc->fdc_dev); + printf("unexpected FD int->"); if (fd_read_status(fdc, fd->fdsu) == 0) printf("FDC status :%x %x %x %x %x %x %x ", fdc->status[0], @@ -2010,28 +2067,31 @@ fdstate(fdcu_t fdcu, fdc_p fdc) if (fd_sense_int(fdc, &st0, &cyl) != 0) { printf("[controller is dead now]\n"); - return(0); + return (0); } printf("ST0 = %x, PCN = %x\n", st0, cyl); - return(0); + return (0); } /*XXX confusing: some branches return immediately, others end up here*/ - return(1); /* Come back immediatly to new state */ + return (1); /* Come back immediatly to new state */ } static int -retrier(fdcu) - fdcu_t fdcu; +retrier(struct fdc_data *fdc) { - fdc_p fdc = fdc_data + fdcu; register struct buf *bp; + struct fd_data *fd; + int fdu; bp = fdc->bp; - if(fd_data[FDUNIT(minor(bp->b_dev))].options & FDOPT_NORETRY) + /* XXX shouldn't this be cached somewhere? */ + fdu = FDUNIT(minor(bp->b_dev)); + fd = devclass_get_softc(fd_devclass, fdu); + if (fd->options & FDOPT_NORETRY) goto fail; - switch(fdc->retry) - { + + switch (fdc->retry) { case 0: case 1: case 2: fdc->state = SEEKCOMPLETE; break; @@ -2084,10 +2144,10 @@ retrier(fdcu) fdc->flags |= FDC_NEEDS_RESET; fdc->fd = (fd_p) 0; fdc->fdu = -1; - return(1); + return (1); } fdc->retry++; - return(1); + return (1); } static int @@ -2104,7 +2164,7 @@ fdformat(dev, finfo, p) size_t fdblk; fdu = FDUNIT(minor(dev)); - fd = &fd_data[fdu]; + fd = devclass_get_softc(fd_devclass, fdu); fdblk = 128 << fd->ft->secsize; /* set up a buffer header for fdstrategy() */ @@ -2135,20 +2195,19 @@ fdformat(dev, finfo, p) /* ...and wait for it to complete */ s = splbio(); - while(!(bp->b_flags & B_DONE)) - { + while(!(bp->b_flags & B_DONE)) { rv = tsleep((caddr_t)bp, PRIBIO, "fdform", 20 * hz); - if(rv == EWOULDBLOCK) + if (rv == EWOULDBLOCK) break; } splx(s); - if(rv == EWOULDBLOCK) { + if (rv == EWOULDBLOCK) { /* timed out */ rv = EIO; biodone(bp); } - if(bp->b_flags & B_ERROR) + if (bp->b_flags & B_ERROR) rv = bp->b_error; /* * allow the process to be swapped @@ -2171,7 +2230,7 @@ fdioctl(dev, cmd, addr, flag, p) struct proc *p; { fdu_t fdu = FDUNIT(minor(dev)); - fd_p fd = &fd_data[fdu]; + fd_p fd = devclass_get_softc(fd_devclass, fdu); size_t fdblk; struct fd_type *fdt; @@ -2181,13 +2240,12 @@ fdioctl(dev, cmd, addr, flag, p) fdblk = 128 << fd->ft->secsize; - switch (cmd) - { + switch (cmd) { case DIOCGDINFO: bzero(buffer, sizeof (buffer)); dl = (struct disklabel *)buffer; dl->d_secsize = fdblk; - fdt = fd_data[FDUNIT(minor(dev))].ft; + fdt = fd->ft; dl->d_secpercyl = fdt->size / fdt->tracks; dl->d_type = DTYPE_FLOPPY; @@ -2211,8 +2269,7 @@ fdioctl(dev, cmd, addr, flag, p) break; case DIOCWDINFO: - if ((flag & FWRITE) == 0) - { + if ((flag & FWRITE) == 0) { error = EBADF; break; } @@ -2227,9 +2284,9 @@ fdioctl(dev, cmd, addr, flag, p) (struct disklabel *)buffer); break; case FD_FORM: - if((flag & FWRITE) == 0) + if ((flag & FWRITE) == 0) error = EBADF; /* must be opened for writing */ - else if(((struct fd_formb *)addr)->format_version != + else if (((struct fd_formb *)addr)->format_version != FD_FORMAT_VERSION) error = EINVAL; /* wrong version of formatting prog */ else @@ -2242,7 +2299,7 @@ fdioctl(dev, cmd, addr, flag, p) case FD_STYPE: /* set drive type */ /* this is considered harmful; only allow for superuser */ - if(suser(p->p_ucred, &p->p_acflag) != 0) + if (suser(p->p_ucred, &p->p_acflag) != 0) return EPERM; *fd->ft = *(struct fd_type *)addr; break; @@ -2262,22 +2319,62 @@ fdioctl(dev, cmd, addr, flag, p) return (error); } +static device_method_t fdc_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fdc_probe), + DEVMETHOD(device_attach, fdc_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), -static fd_devsw_installed = 0; + /* Bus interface */ + DEVMETHOD(bus_print_child, fdc_print_child), + /* Our children never use any other bus interface methods. */ -static void fd_drvinit(void *notused ) -{ + { 0, 0 } +}; - if( ! fd_devsw_installed ) { - cdevsw_add_generic(BDEV_MAJOR,CDEV_MAJOR, &fd_cdevsw); - fd_devsw_installed = 1; - } -} +static driver_t fdc_driver = { + "fdc", + fdc_methods, + DRIVER_TYPE_BIO, + sizeof(struct fdc_data) +}; -SYSINIT(fddev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,fd_drvinit,NULL) +DRIVER_MODULE(fdc, isa, fdc_driver, fdc_devclass, 0, 0); +static device_method_t fd_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fd_probe), + DEVMETHOD(device_attach, fd_attach), + DEVMETHOD(device_detach, bus_generic_detach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + DEVMETHOD(device_suspend, bus_generic_suspend), /* XXX */ + DEVMETHOD(device_resume, bus_generic_resume), /* XXX */ -#endif + { 0, 0 } +}; + +static driver_t fd_driver = { + "fd", + fd_methods, + DRIVER_TYPE_BIO, + sizeof(struct fd_data) +}; + +static struct cdevsw fd_cdevsw = { + Fdopen, fdclose, fdread, fdwrite, + fdioctl, nostop, nullreset, nodevtotty, + seltrue, nommap, fdstrategy, "fd", + NULL, -1, nodump, nopsize, + D_DISK, 0, -1 +}; + +BDEV_DRIVER_MODULE(fd, fdc, fd_driver, fd_devclass, BDEV_MAJOR, CDEV_MAJOR, + fd_cdevsw, 0, 0); + +#endif /* NFDC > 0 */ /* * Hello emacs, these are the diff --git a/sys/isa/fdc.h b/sys/isa/fdc.h index 43bf9f8..83e291f 100644 --- a/sys/isa/fdc.h +++ b/sys/isa/fdc.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * from: @(#)fd.c 7.4 (Berkeley) 5/25/91 - * $Id: fdc.h,v 1.12 1998/12/12 08:16:01 imp Exp $ + * $Id: fdc.h,v 1.13 1999/01/15 09:15:27 bde Exp $ * */ @@ -70,6 +70,10 @@ struct fdc_data int fdc_errs; /* number of logged errors */ struct buf_queue_head head; struct buf *bp; /* active buffer */ + struct resource *res_ioport, *res_irq, *res_drq; + int rid_ioport, rid_irq, rid_drq; + void *fdc_intr; + struct device *fdc_dev; }; /***********************************************************************\ diff --git a/sys/isa/isavar.h b/sys/isa/isavar.h index bb8ee55..21447b6 100644 --- a/sys/isa/isavar.h +++ b/sys/isa/isavar.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: isavar.h,v 1.1 1998/08/06 08:49:09 dfr Exp $ + * $Id: isavar.h,v 1.2 1998/11/15 18:25:17 dfr Exp $ */ #define ISA_NPORT_IVARS 2 @@ -63,7 +63,7 @@ extern int isa_irq_mask(void); \ static __inline T isa_get_ ## A(device_t dev) \ { \ - u_long v; \ + uintptr_t v; \ BUS_READ_IVAR(device_get_parent(dev), dev, ISA_IVAR_ ## B, &v); \ return (T) v; \ } \ @@ -78,4 +78,7 @@ ISA_ACCESSOR(port, PORT, int) ISA_ACCESSOR(portsize, PORTSIZE, int) ISA_ACCESSOR(flags, FLAGS, int) ISA_ACCESSOR(irq, IRQ, int) +ISA_ACCESSOR(drq, DRQ, int) +ISA_ACCESSOR(maddr, MADDR, int) +ISA_ACCESSOR(msize, MSIZE, int) diff --git a/sys/isa/psm.c b/sys/isa/psm.c index e7eb469..b3dc1d0 100644 --- a/sys/isa/psm.c +++ b/sys/isa/psm.c @@ -20,7 +20,7 @@ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: psm.c,v 1.2 1998/11/15 18:25:17 dfr Exp $ + * $Id: psm.c,v 1.3 1999/01/23 16:53:28 dfr Exp $ */ /* @@ -76,6 +76,7 @@ #include <sys/poll.h> #include <sys/syslog.h> #include <sys/malloc.h> +#include <machine/bus.h> #include <sys/rman.h> #ifdef DEVFS #include <sys/devfsext.h> @@ -740,8 +741,8 @@ psmprobe(device_t dev) { int unit = device_get_unit(dev); struct psm_softc *sc = device_get_softc(dev); - u_long port; - u_long flags; + uintptr_t port; + uintptr_t flags; int stat[3]; int command_byte; int mask; @@ -991,7 +992,7 @@ psmattach(device_t dev) struct psm_softc *sc = device_get_softc(dev); void *ih; struct resource *res; - u_long irq; + uintptr_t irq; int zero = 0; if (sc == NULL) /* shouldn't happen */ diff --git a/sys/isa/sio.c b/sys/isa/sio.c index ee031b4..1a40360 100644 --- a/sys/isa/sio.c +++ b/sys/isa/sio.c @@ -30,7 +30,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: sio.c,v 1.220 1999/01/19 00:21:47 peter Exp $ + * $Id: sio.c,v 1.221 1999/01/30 12:17:35 phk Exp $ * from: @(#)com.c 7.5 (Berkeley) 5/16/91 * from: i386/isa sio.c,v 1.215 */ @@ -68,6 +68,7 @@ #include <sys/syslog.h> #include <sys/sysctl.h> #include <sys/bus.h> +#include <machine/bus.h> #include <sys/rman.h> #ifdef DEVFS #include <sys/devfsext.h> @@ -103,8 +104,10 @@ #endif +#ifndef __i386__ #define disable_intr() 0 #define enable_intr() 0 +#endif #ifdef SMP #define disable_intr() COM_DISABLE_INTR() @@ -2607,6 +2610,21 @@ static void siocnclose __P((struct siocnstate *sp, Port_t iobase)); static void siocnopen __P((struct siocnstate *sp, Port_t iobase, int speed)); static void siocntxwait __P((Port_t iobase)); +#ifdef __i386__ +/* + * XXX: sciocnget() and sciocnputc() are not declared static, as they are + * referred to from i386/i386/i386-gdbstub.c. + */ +static cn_probe_t siocnprobe; +static cn_init_t siocninit; +static cn_checkc_t siocncheckc; + cn_getc_t siocngetc; + cn_putc_t siocnputc; + +CONS_DRIVER(sio, siocnprobe, siocninit, siocngetc, siocncheckc, siocnputc); + +#endif + static void siocntxwait(iobase) Port_t iobase; @@ -2731,11 +2749,9 @@ void siocnprobe(cp) struct consdev *cp; { -#if 0 speed_t boot_speed; u_char cfcr; - struct isa_device *dvp; - int s; + int s, unit; struct siocnstate sp; /* @@ -2753,10 +2769,16 @@ siocnprobe(cp) * don't need to probe. */ cp->cn_pri = CN_DEAD; - for (dvp = isa_devtab_tty; dvp->id_driver != NULL; dvp++) - if (dvp->id_driver == &siodriver && dvp->id_enabled - && COM_CONSOLE(dvp)) { - siocniobase = dvp->id_iobase; + + for (unit = 0; unit < 16; unit++) { /* XXX need to know how many */ + int flags; + if (resource_int_value("sio", unit, "flags", &flags)) + continue; + if (COM_CONSOLE(flags)) { + int port; + if (resource_int_value("sio", unit, "port", &port)) + continue; + siocniobase = port; s = spltty(); if (boothowto & RB_SERIAL) { boot_speed = siocngetspeed(siocniobase, @@ -2784,17 +2806,19 @@ siocnprobe(cp) siocnopen(&sp, siocniobase, comdefaultrate); splx(s); - if (!COM_LLCONSOLE(dvp)) { - cp->cn_dev = makedev(CDEV_MAJOR, dvp->id_unit); - cp->cn_pri = COM_FORCECONSOLE(dvp) + if (!COM_LLCONSOLE(flags)) { + cp->cn_dev = makedev(CDEV_MAJOR, unit); + cp->cn_pri = COM_FORCECONSOLE(flags) || boothowto & RB_SERIAL ? CN_REMOTE : CN_NORMAL; } break; } -#endif + } } +#ifdef __alpha__ + struct consdev siocons = { NULL, NULL, siocngetc, siocncheckc, siocnputc, NULL, makedev(CDEV_MAJOR, 0), CN_NORMAL, @@ -2877,6 +2901,8 @@ siogdbattach(port, speed) return 0; } +#endif + void siocninit(cp) struct consdev *cp; @@ -3158,7 +3184,6 @@ static void siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) { struct pnp_cinfo d; - struct isa_device *dvp; if (dev->id_unit >= NSIOTOT) return; @@ -3180,9 +3205,7 @@ siopnp_attach(u_long csn, u_long vend_id, char *name, struct isa_device *dev) if (dev->id_driver == NULL) { dev->id_driver = &siodriver; - dvp = find_isadev(isa_devtab_tty, &siodriver, 0); - if (dvp != NULL) - dev->id_id = dvp->id_id; + dev->id_id = isa_compat_nextid(); } if ((dev->id_alive = sioprobe(dev)) != 0) diff --git a/sys/isa/syscons_isa.c b/sys/isa/syscons_isa.c index 9f61cec..e837cab 100644 --- a/sys/isa/syscons_isa.c +++ b/sys/isa/syscons_isa.c @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id:$ + * $Id: syscons_isa.c,v 1.1 1999/01/23 16:53:30 dfr Exp $ */ #include "sc.h" @@ -38,6 +38,9 @@ #include <sys/bus.h> #include <machine/console.h> +#ifdef __i386__ +#include <machine/apm_bios.h> +#endif #include <dev/syscons/syscons.h> diff --git a/sys/isa/vga_isa.c b/sys/isa/vga_isa.c index 49baedb..b5e4903 100644 --- a/sys/isa/vga_isa.c +++ b/sys/isa/vga_isa.c @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: vga_isa.c,v 1.2 1999/02/05 11:52:08 yokota Exp $ + * $Id: vga_isa.c,v 1.3 1999/02/05 12:58:32 yokota Exp $ */ #include "vga.h" @@ -52,7 +52,7 @@ #include <dev/fb/fbreg.h> #include <dev/fb/vgareg.h> -#ifndef __i386__ +#if 1 #include <isa/isareg.h> #include <isa/isavar.h> #else @@ -71,7 +71,7 @@ typedef struct isavga_softc { video_adapter_t *adp; } isavga_softc_t; -#ifndef __i386__ +#if 1 #define ISAVGA_SOFTC(unit) \ ((isavga_softc_t *)devclass_get_softc(isavga_devclass, unit)) @@ -135,7 +135,7 @@ static struct cdevsw vga_cdevsw = { #endif /* FB_INSTALL_CDEV */ -#ifndef __i386__ +#if 1 static int isavga_probe(device_t dev) @@ -776,6 +776,9 @@ verify_adapter(video_adapter_t *adp) { vm_offset_t buf; u_int16_t v; +#if !defined(VGA_NO_BIOS) && !defined(VGA_NO_MODE_CHANGE) + u_int32_t p; +#endif buf = BIOS_PADDRTOVADDR(adp->va_window); v = readw(buf); @@ -1077,6 +1080,7 @@ probe_adapters(void) rows_offset = 1; } else { /* discard the table if we are not familiar with it... */ + u_char *mp; map_mode_table(mode_map, video_mode_ptr, M_VGA_CG320 + 1); mp = get_mode_param(adp->va_initial_mode); if (mp != NULL) @@ -1138,6 +1142,7 @@ probe_adapters(void) if (video_mode_ptr == NULL) { rows_offset = 1; } else { + u_char *mp; map_mode_table(mode_map, video_mode_ptr, M_ENH_C80x25 + 1); /* XXX how can one validate the EGA table... */ mp = get_mode_param(adp->va_initial_mode); diff --git a/sys/kern/bus_if.m b/sys/kern/bus_if.m index 8c48082..191906b 100644 --- a/sys/kern/bus_if.m +++ b/sys/kern/bus_if.m @@ -23,7 +23,7 @@ # OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF # SUCH DAMAGE. # -# $Id: bus_if.m,v 1.5 1998/11/14 21:58:51 wollman Exp $ +# $Id: bus_if.m,v 1.6 1999/03/29 08:54:19 dfr Exp $ # INTERFACE bus; @@ -80,6 +80,16 @@ METHOD void child_detached { }; # +# Called when a new driver is added to the devclass which owns this +# bus. The generic implementation of this method attempts to probe and +# attach any un-matched children of the bus. +# +METHOD void driver_added { + device_t dev; + driver_t *driver; +} + +# # Allocate a system resource attached to `dev' on behalf of `child'. # The types are defined in <machine/resource.h>; the meaning of the # resource-ID field varies from bus to bus (but *rid == 0 is always diff --git a/sys/kern/makedevops.pl b/sys/kern/makedevops.pl index 1c434d5..ce428e5 100644 --- a/sys/kern/makedevops.pl +++ b/sys/kern/makedevops.pl @@ -323,7 +323,7 @@ foreach $src ( @filenames ) { if ( $cfile ) { # Print out the method desc print CFILE "struct device_op_desc $mname\_desc = {\n"; - print CFILE "\t0, \"$mname\"\n"; + print CFILE "\t0, 0, \"$mname\"\n"; print CFILE "};\n\n"; # Print out the method itself diff --git a/sys/kern/subr_bus.c b/sys/kern/subr_bus.c index 4469b70..339ef32 100644 --- a/sys/kern/subr_bus.c +++ b/sys/kern/subr_bus.c @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: subr_bus.c,v 1.15 1999/01/27 21:49:57 dillon Exp $ + * $Id: subr_bus.c,v 1.16 1999/03/29 08:54:20 dfr Exp $ */ #include <sys/param.h> @@ -94,50 +94,62 @@ static void device_unregister_oids(device_t dev); * Method table handling */ static int next_method_offset = 1; -static int methods_count = 0; -static int methods_size = 0; +LIST_HEAD(methodlist, method) methods; struct method { - int offset; - char* name; + LIST_ENTRY(method) link; /* linked list of methods */ + int offset; /* offset in method table */ + int refs; /* count of device_op_desc users */ + char* name; /* unique name of method */ }; -static struct method *methods = 0; - static void register_method(struct device_op_desc *desc) { - int i; struct method* m; - for (i = 0; i < methods_count; i++) - if (!strcmp(methods[i].name, desc->name)) { - desc->offset = methods[i].offset; - PDEBUG(("methods[%d] has the same name, %s, with offset %d", - i, desc->name, desc->offset)); - return; - } - - if (methods_count == methods_size) { - struct method* p; + if (desc->method) { + desc->method->refs++; + return; + } - methods_size += 10; - p = (struct method*) malloc(methods_size * sizeof(struct method), - M_DEVBUF, M_NOWAIT); - if (!p) - panic("register_method: out of memory"); - if (methods) { - bcopy(methods, p, methods_count * sizeof(struct method)); - free(methods, M_DEVBUF); + for (m = LIST_FIRST(&methods); m; m = LIST_NEXT(m, link)) { + if (!strcmp(m->name, desc->name)) { + desc->offset = m->offset; + desc->method = m; + m->refs++; + PDEBUG(("methods %x has the same name, %s, with offset %d", + m, desc->name, desc->offset)); + return; } - methods = p; } - m = &methods[methods_count++]; - m->name = malloc(strlen(desc->name) + 1, M_DEVBUF, M_NOWAIT); - if (!m->name) + + m = (struct method *) malloc(sizeof(struct method) + + strlen(desc->name) + 1, + M_DEVBUF, M_NOWAIT); + if (!m) panic("register_method: out of memory"); + bzero(m, sizeof(struct method) + strlen(desc->name) + 1); + m->offset = next_method_offset++; + m->refs = 1; + m->name = (char*) (m + 1); strcpy(m->name, desc->name); - desc->offset = m->offset = next_method_offset++; + LIST_INSERT_HEAD(&methods, m, link); + + desc->offset = m->offset; + desc->method = m; +} + +static void +unregister_method(struct device_op_desc *desc) +{ + struct method *m = desc->method; + m->refs--; + if (m->refs == 0) { + LIST_REMOVE(m, link); + free(m, M_DEVBUF); + } + desc->method = 0; } static int error_method(void) @@ -161,10 +173,7 @@ compile_methods(driver_t *driver) * First register any methods which need it. */ for (i = 0, m = driver->methods; m->desc; i++, m++) - if (!m->desc->offset) - register_method(m->desc); - else - PDEBUG(("offset not equal to zero, method desc %d left as is", i)); + register_method(m->desc); /* * Then allocate the compiled op table. @@ -173,6 +182,7 @@ compile_methods(driver_t *driver) M_DEVBUF, M_NOWAIT); if (!ops) panic("compile_methods: out of memory"); + bzero(ops, sizeof(struct device_ops) + (next_method_offset-1) * sizeof(devop_t)); ops->maxoffset = next_method_offset; for (i = 0; i < next_method_offset; i++) @@ -186,6 +196,25 @@ compile_methods(driver_t *driver) driver->ops = ops; } +static void +free_methods(driver_t *driver) +{ + int i; + struct device_method *m; + + /* + * Unregister any methods which are no longer used. + */ + for (i = 0, m = driver->methods; m->desc; i++, m++) + unregister_method(m->desc); + + /* + * Free memory and clean up. + */ + free(driver->ops, M_DEVBUF); + driver->ops = 0; +} + /* * Devclass implementation */ @@ -211,6 +240,7 @@ devclass_find_internal(const char *classname, int create) M_DEVBUF, M_NOWAIT); if (!dc) return NULL; + bzero(dc, sizeof(struct devclass) + strlen(classname) + 1); dc->name = (char*) (dc + 1); strcpy(dc->name, classname); dc->devices = NULL; @@ -233,17 +263,20 @@ int devclass_add_driver(devclass_t dc, driver_t *driver) { driverlink_t dl; + int i; PDEBUG(("%s", DRIVERNAME(driver))); dl = malloc(sizeof *dl, M_DEVBUF, M_NOWAIT); if (!dl) return ENOMEM; + bzero(dl, sizeof *dl); /* - * Compile the drivers methods. + * Compile the driver's methods. */ - compile_methods(driver); + if (!driver->ops) + compile_methods(driver); /* * Make sure the devclass which the driver is implementing exists. @@ -252,6 +285,14 @@ devclass_add_driver(devclass_t dc, driver_t *driver) dl->driver = driver; TAILQ_INSERT_TAIL(&dc->drivers, dl, link); + driver->refs++; + + /* + * Call BUS_DRIVER_ADDED for any existing busses in this class. + */ + for (i = 0; i < dc->maxunit; i++) + if (dc->devices[i]) + BUS_DRIVER_ADDED(dc->devices[i], driver); return 0; } @@ -309,6 +350,10 @@ devclass_delete_driver(devclass_t busclass, driver_t *driver) TAILQ_REMOVE(&busclass->drivers, dl, link); free(dl, M_DEVBUF); + driver->refs--; + if (driver->refs == 0) + free_methods(driver); + return 0; } @@ -382,6 +427,7 @@ devclass_get_devices(devclass_t dc, device_t **devlistp, int *devcountp) list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); if (!list) return ENOMEM; + bzero(list, count * sizeof(device_t)); count = 0; for (i = 0; i < dc->maxunit; i++) @@ -462,6 +508,7 @@ devclass_add_device(devclass_t dc, device_t dev) dev->nameunit = malloc(buflen, M_DEVBUF, M_NOWAIT); if (!dev->nameunit) return ENOMEM; + bzero(dev->nameunit, buflen); if ((error = devclass_alloc_unit(dc, &dev->unit)) != 0) { free(dev->nameunit, M_DEVBUF); @@ -528,6 +575,7 @@ make_device(device_t parent, const char *name, dev = malloc(sizeof(struct device), M_DEVBUF, M_NOWAIT); if (!dev) return 0; + bzero(dev, sizeof(struct device)); dev->parent = parent; TAILQ_INIT(&dev->children); @@ -721,6 +769,7 @@ device_get_children(device_t dev, device_t **devlistp, int *devcountp) list = malloc(count * sizeof(device_t), M_TEMP, M_NOWAIT); if (!list) return ENOMEM; + bzero(list, count * sizeof(device_t)); count = 0; for (child = TAILQ_FIRST(&dev->children); child; @@ -1146,12 +1195,69 @@ device_unregister_oids(device_t dev) #endif +/*======================================*/ /* * Access functions for device resources. */ -extern struct config_device devtab[]; + +/* Supplied by config(8) in ioconf.c */ +extern struct config_device config_devtab[]; extern int devtab_count; +/* Runtime version */ +struct config_device *devtab = config_devtab; + +static int +resource_new_name(char *name, int unit) +{ + struct config_device *new; + + new = malloc((devtab_count + 1) * sizeof(*new), M_TEMP, M_NOWAIT); + if (new == NULL) + return -1; + if (devtab && devtab_count > 0) + bcopy(devtab, new, devtab_count * sizeof(*new)); + bzero(&new[devtab_count], sizeof(*new)); + new[devtab_count].name = malloc(strlen(name) + 1, M_TEMP, M_NOWAIT); + if (new[devtab_count].name == NULL) { + free(new, M_TEMP); + return -1; + } + strcpy(new[devtab_count].name, name); + new[devtab_count].unit = unit; + new[devtab_count].resource_count = 0; + new[devtab_count].resources = NULL; + devtab = new; + return devtab_count++; +} + +static int +resource_new_resname(int j, char *resname, resource_type type) +{ + struct config_resource *new; + int i; + + i = devtab[j].resource_count; + new = malloc((i + 1) * sizeof(*new), M_TEMP, M_NOWAIT); + if (new == NULL) + return -1; + if (devtab[j].resources && i > 0) + bcopy(devtab[j].resources, new, i * sizeof(*new)); + bzero(&new[i], sizeof(*new)); + new[i].name = malloc(strlen(resname) + 1, M_TEMP, M_NOWAIT); + if (new[i].name == NULL) { + free(new, M_TEMP); + return -1; + } + strcpy(new[i].name, resname); + new[i].type = type; + if (devtab[j].resources) + free(devtab[j].resources, M_TEMP); + devtab[j].resources = new; + devtab[j].resource_count = i + 1; + return i; +} + static int resource_match_string(int i, char *resname, char *value) { @@ -1163,8 +1269,8 @@ resource_match_string(int i, char *resname, char *value) if (!strcmp(res->name, resname) && res->type == RES_STRING && !strcmp(res->u.stringval, value)) - return TRUE; - return FALSE; + return j; + return -1; } static int @@ -1209,6 +1315,7 @@ resource_int_value(const char *name, int unit, char *resname, int *result) { int error; struct config_resource *res; + if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_INT) @@ -1222,6 +1329,7 @@ resource_long_value(const char *name, int unit, char *resname, long *result) { int error; struct config_resource *res; + if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_LONG) @@ -1235,6 +1343,7 @@ resource_string_value(const char *name, int unit, char *resname, char **result) { int error; struct config_resource *res; + if ((error = resource_find(name, unit, resname, &res)) != 0) return error; if (res->type != RES_STRING) @@ -1251,11 +1360,30 @@ resource_query_string(int i, char *resname, char *value) else i = i + 1; for (; i < devtab_count; i++) - if (resource_match_string(i, resname, value)) + if (resource_match_string(i, resname, value) >= 0) return i; return -1; } +int +resource_locate(int i, char *resname) +{ + if (i < 0) + i = 0; + else + i = i + 1; + for (; i < devtab_count; i++) + if (!strcmp(devtab[i].name, resname)) + return i; + return -1; +} + +int +resource_count(void) +{ + return devtab_count; +} + char * resource_query_name(int i) { @@ -1268,7 +1396,165 @@ resource_query_unit(int i) return devtab[i].unit; } +static int +resource_create(char *name, int unit, char *resname, resource_type type, + struct config_resource **result) +{ + int i, j; + struct config_resource *res = NULL; + + for (i = 0; i < devtab_count; i++) { + if (!strcmp(devtab[i].name, name) && devtab[i].unit == unit) { + res = devtab[i].resources; + break; + } + } + if (res == NULL) { + i = resource_new_name(name, unit); + if (i < 0) + return ENOMEM; + res = devtab[i].resources; + } + for (j = 0; j < devtab[i].resource_count; j++, res++) { + if (!strcmp(res->name, resname)) { + *result = res; + return 0; + } + } + j = resource_new_resname(i, resname, type); + if (j < 0) + return ENOMEM; + res = &devtab[i].resources[j]; + *result = res; + return 0; +} + +int +resource_set_int(int i, char *resname, int value) +{ + int error; + struct config_resource *res; +printf("resource_set_int\n"); + if (i < 0 || i >= devtab_count) + return EINVAL; + error = resource_create(devtab[i].name, devtab[i].unit, resname, + RES_INT, &res); + if (error) + return error; + if (res->type != RES_INT) + return EFTYPE; + res->u.intval = value; + return 0; +} + +int +resource_set_long(int i, char *resname, long value) +{ + int error; + struct config_resource *res; + +printf("resource_set_long\n"); + if (i < 0 || i >= devtab_count) + return EINVAL; + error = resource_create(devtab[i].name, devtab[i].unit, resname, + RES_LONG, &res); + if (error) + return error; + if (res->type != RES_LONG) + return EFTYPE; + res->u.longval = value; + return 0; +} + +int +resource_set_string(int i, char *resname, char *value) +{ + int error; + struct config_resource *res; + +printf("resource_set_string\n"); + if (i < 0 || i >= devtab_count) + return EINVAL; + error = resource_create(devtab[i].name, devtab[i].unit, resname, + RES_STRING, &res); + if (error) + return error; + if (res->type != RES_STRING) + return EFTYPE; + if (res->u.stringval) + free(res->u.stringval, M_TEMP); + res->u.stringval = malloc(strlen(value) + 1, M_TEMP, M_NOWAIT); + if (res->u.stringval == NULL) + return ENOMEM; + strcpy(res->u.stringval, value); + return 0; +} + + +static void +resource_cfgload(void *dummy __unused) +{ + struct config_resource *res, *cfgres; + int i, j; + int error; + char *name, *resname; + int unit; + resource_type type; + char *stringval; + int config_devtab_count; + + config_devtab_count = devtab_count; + devtab = NULL; + devtab_count = 0; + + for (i = 0; i < config_devtab_count; i++) { + name = config_devtab[i].name; + unit = config_devtab[i].unit; + + for (j = 0; j < config_devtab[i].resource_count; j++) { + cfgres = config_devtab[i].resources; + resname = cfgres[j].name; + type = cfgres[j].type; + error = resource_create(name, unit, resname, type, + &res); + if (error) { + printf("create resource %s%d: error %d\n", + name, unit, error); + continue; + } + if (res->type != type) { + printf("type mismatch %s%d: %d != %d\n", + name, unit, res->type, type); + continue; + } + switch (type) { + case RES_INT: + res->u.intval = cfgres[j].u.intval; + break; + case RES_LONG: + res->u.longval = cfgres[j].u.longval; + break; + case RES_STRING: + if (res->u.stringval) + free(res->u.stringval, M_TEMP); + stringval = cfgres[j].u.stringval; + res->u.stringval = malloc(strlen(stringval) + 1, + M_TEMP, M_NOWAIT); + if (res->u.stringval == NULL) + break; + strcpy(res->u.stringval, stringval); + break; + default: + panic("unknown resource type %d\n", type); + } + } + } +} +SYSINIT(cfgload, SI_SUB_KMEM, SI_ORDER_ANY + 50, resource_cfgload, 0) + + +/*======================================*/ /* * Some useful method implementations to make life easier for bus drivers. */ @@ -1308,7 +1594,7 @@ bus_generic_shutdown(device_t dev) for (child = TAILQ_FIRST(&dev->children); child; child = TAILQ_NEXT(child, link)) - DEVICE_SHUTDOWN(child); + device_shutdown(child); return 0; } @@ -1366,6 +1652,17 @@ bus_generic_write_ivar(device_t dev, device_t child, int index, return ENOENT; } +void +bus_generic_driver_added(device_t dev, driver_t *driver) +{ + device_t child; + + for (child = TAILQ_FIRST(&dev->children); + child; child = TAILQ_NEXT(child, link)) + if (child->state == DS_NOTPRESENT) + device_probe_and_attach(child); +} + int bus_generic_setup_intr(device_t dev, device_t child, struct resource *irq, driver_intr_t *intr, void *arg, void **cookiep) @@ -1513,6 +1810,7 @@ root_setup_intr(device_t dev, device_t child, driver_intr_t *intr, void *arg, static device_method_t root_methods[] = { /* Device interface */ + DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), DEVMETHOD(device_resume, bus_generic_resume), @@ -1548,6 +1846,10 @@ root_bus_module_handler(module_t mod, int what, void* arg) root_bus->state = DS_ATTACHED; root_devclass = devclass_find_internal("root", FALSE); return 0; + + case MOD_SHUTDOWN: + device_shutdown(root_bus); + return 0; } return 0; diff --git a/sys/kern/subr_rman.c b/sys/kern/subr_rman.c index fee2e2a..a043230 100644 --- a/sys/kern/subr_rman.c +++ b/sys/kern/subr_rman.c @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: subr_rman.c,v 1.5 1999/03/29 08:30:17 dfr Exp $ + * $Id: subr_rman.c,v 1.6 1999/04/11 02:27:06 eivind Exp $ */ /* @@ -62,8 +62,9 @@ #include <sys/kernel.h> #include <sys/lock.h> #include <sys/malloc.h> -#include <sys/rman.h> #include <sys/bus.h> /* XXX debugging */ +#include <machine/bus.h> +#include <sys/rman.h> static MALLOC_DEFINE(M_RMAN, "rman", "Resource manager"); @@ -73,6 +74,7 @@ static struct simplelock rman_lock; /* mutex to protect rman_head */ #endif static int int_rman_activate_resource(struct rman *rm, struct resource *r, struct resource **whohas); +static int int_rman_deactivate_resource(struct resource *r); static int int_rman_release_resource(struct rman *rm, struct resource *r); #define CIRCLEQ_TERMCOND(var, head) (var == (void *)&(head)) @@ -117,6 +119,7 @@ rman_manage_region(struct rman *rm, u_long start, u_long end) r = malloc(sizeof *r, M_RMAN, M_NOWAIT); if (r == 0) return ENOMEM; + bzero(r, sizeof *r); r->r_sharehead = 0; r->r_start = start; r->r_end = end; @@ -148,8 +151,10 @@ rman_fini(struct rman *rm) simple_lock(rm->rm_slock); for (r = rm->rm_list.cqh_first; !CIRCLEQ_TERMCOND(r, rm->rm_list); r = r->r_link.cqe_next) { - if (r->r_flags & RF_ALLOCATED) + if (r->r_flags & RF_ALLOCATED) { + simple_unlock(rm->rm_slock); return EBUSY; + } } /* @@ -254,14 +259,16 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, * split it in two. The first case requires * two new allocations; the second requires but one. */ - rv = malloc(sizeof *r, M_RMAN, M_NOWAIT); + rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT); if (rv == 0) goto out; + bzero(rv, sizeof *rv); rv->r_start = rstart; rv->r_end = rstart + count - 1; rv->r_flags = flags | RF_ALLOCATED; rv->r_dev = dev; rv->r_sharehead = 0; + rv->r_rm = rm; if (s->r_start < rv->r_start && s->r_end > rv->r_end) { #ifdef RMAN_DEBUG @@ -280,11 +287,13 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, rv = 0; goto out; } + bzero(r, sizeof *r); r->r_start = rv->r_end + 1; r->r_end = s->r_end; r->r_flags = s->r_flags; r->r_dev = 0; r->r_sharehead = 0; + r->r_rm = rm; s->r_end = rv->r_start - 1; CIRCLEQ_INSERT_AFTER(&rm->rm_list, s, rv, r_link); @@ -342,6 +351,7 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, rv = malloc(sizeof *rv, M_RMAN, M_NOWAIT); if (rv == 0) goto out; + bzero(rv, sizeof *rv); rv->r_start = s->r_start; rv->r_end = s->r_end; rv->r_flags = s->r_flags & @@ -356,6 +366,7 @@ rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, rv = 0; goto out; } + bzero(s->r_sharehead, sizeof *s->r_sharehead); LIST_INIT(s->r_sharehead); LIST_INSERT_HEAD(s->r_sharehead, s, r_sharelink); @@ -451,7 +462,7 @@ rman_await_resource(struct resource *r, int pri, int timo) simple_lock(rm->rm_slock); rv = int_rman_activate_resource(rm, r, &whohas); if (rv != EBUSY) - return (rv); + return (rv); /* returns with simplelock */ if (r->r_sharehead == 0) panic("rman_await_resource"); @@ -474,18 +485,28 @@ rman_await_resource(struct resource *r, int pri, int timo) } } -int -rman_deactivate_resource(struct resource *r) +static int +int_rman_deactivate_resource(struct resource *r) { struct rman *rm; rm = r->r_rm; - simple_lock(rm->rm_slock); r->r_flags &= ~RF_ACTIVE; if (r->r_flags & RF_WANTED) { r->r_flags &= ~RF_WANTED; wakeup(r->r_sharehead); } + return 0; +} + +int +rman_deactivate_resource(struct resource *r) +{ + struct rman *rm; + + rm = r->r_rm; + simple_lock(rm->rm_slock); + int_rman_deactivate_resource(r); simple_unlock(rm->rm_slock); return 0; } @@ -496,7 +517,7 @@ int_rman_release_resource(struct rman *rm, struct resource *r) struct resource *s, *t; if (r->r_flags & RF_ACTIVE) - return EBUSY; + int_rman_deactivate_resource(r); /* * Check for a sharing list first. If there is one, then we don't diff --git a/sys/net/if.c b/sys/net/if.c index 680bbd4..635be7d 100644 --- a/sys/net/if.c +++ b/sys/net/if.c @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * @(#)if.c 8.3 (Berkeley) 1/4/94 - * $Id: if.c,v 1.65 1999/02/01 20:03:27 phk Exp $ + * $Id: if.c,v 1.66 1999/02/19 13:41:35 phk Exp $ */ #include "opt_compat.h" @@ -178,6 +178,39 @@ if_attach(ifp) TAILQ_INSERT_HEAD(&ifp->if_addrhead, ifa, ifa_link); } } + +/* + * Detach an interface, removing it from the + * list of "active" interfaces. + */ +void +if_detach(ifp) + struct ifnet *ifp; +{ + struct ifaddr *ifa; + + /* + * Remove routes and flush queues. + */ + if_down(ifp); + + /* + * Remove address from ifnet_addrs[] and maybe decrement if_index. + * Clean up all addresses. + */ + ifnet_addrs[ifp->if_index] = 0; + while (ifnet_addrs[if_index] == 0) + if_index--; + + for (ifa = TAILQ_FIRST(&ifp->if_addrhead); ifa; + ifa = TAILQ_FIRST(&ifp->if_addrhead)) { + TAILQ_REMOVE(&ifp->if_addrhead, ifa, ifa_link); + IFAFREE(ifa); + } + + TAILQ_REMOVE(&ifnet, ifp, if_link); +} + /* * Locate an interface based on a complete address. */ diff --git a/sys/net/if_media.c b/sys/net/if_media.c index ee12880..553af92 100644 --- a/sys/net/if_media.c +++ b/sys/net/if_media.c @@ -1,5 +1,5 @@ /* $NetBSD: if_media.c,v 1.1 1997/03/17 02:55:15 thorpej Exp $ */ -/* $Id: if_media.c,v 1.5 1998/02/06 12:13:48 eivind Exp $ */ +/* $Id: if_media.c,v 1.6 1998/02/09 06:09:54 eivind Exp $ */ /* * Copyright (c) 1997 @@ -89,6 +89,19 @@ ifmedia_init(ifm, dontcare_mask, change_callback, status_callback) ifm->ifm_status = status_callback; } +void +ifmedia_removeall(ifm) + struct ifmedia *ifm; +{ + struct ifmedia_entry *entry; + + for (entry = LIST_FIRST(&ifm->ifm_list); entry; + entry = LIST_FIRST(&ifm->ifm_list)) { + LIST_REMOVE(entry, ifm_list); + free(entry, M_IFADDR); + } +} + /* * Add a media configuration to the list of supported media * for a specific interface instance. diff --git a/sys/net/if_media.h b/sys/net/if_media.h index c66fd9e..e363485 100644 --- a/sys/net/if_media.h +++ b/sys/net/if_media.h @@ -1,5 +1,5 @@ /* $NetBSD: if_media.h,v 1.3 1997/03/26 01:19:27 thorpej Exp $ */ -/* $Id: if_media.h,v 1.3 1999/02/20 11:17:59 julian Exp $ */ +/* $Id: if_media.h,v 1.5 1999/03/07 04:39:25 wpaul Exp $ */ /* * Copyright (c) 1997 @@ -87,6 +87,9 @@ struct ifmedia { void ifmedia_init __P((struct ifmedia *ifm, int dontcare_mask, ifm_change_cb_t change_callback, ifm_stat_cb_t status_callback)); +/* Remove all mediums from a struct ifmedia. */ +void ifmedia_removeall __P(( struct ifmedia *ifm)); + /* Add one supported medium to a struct ifmedia. */ void ifmedia_add __P((struct ifmedia *ifm, int mword, int data, void *aux)); diff --git a/sys/net/if_var.h b/sys/net/if_var.h index 31ce8f6..d66aeb7 100644 --- a/sys/net/if_var.h +++ b/sys/net/if_var.h @@ -31,7 +31,7 @@ * SUCH DAMAGE. * * From: @(#)if.h 8.1 (Berkeley) 6/10/93 - * $Id: if_var.h,v 1.9 1998/06/12 03:48:09 julian Exp $ + * $Id: if_var.h,v 1.10 1998/12/16 18:30:43 phk Exp $ */ #ifndef _NET_IF_VAR_H_ @@ -299,6 +299,7 @@ int if_addmulti __P((struct ifnet *, struct sockaddr *, int if_allmulti __P((struct ifnet *, int)); void if_attach __P((struct ifnet *)); int if_delmulti __P((struct ifnet *, struct sockaddr *)); +void if_detach __P((struct ifnet *)); void if_down __P((struct ifnet *)); void if_route __P((struct ifnet *, int flag, int fam)); void if_unroute __P((struct ifnet *, int flag, int fam)); diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c index 524b873..6faef01 100644 --- a/sys/pci/ide_pci.c +++ b/sys/pci/ide_pci.c @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: ide_pci.c,v 1.30 1999/04/13 19:38:12 peter Exp $ + * $Id: ide_pci.c,v 1.31 1999/04/13 20:22:33 peter Exp $ */ #include "pci.h" @@ -1514,6 +1514,7 @@ ide_pci_attach(pcici_t tag, int unit) wddma[unit].wdd_iobase = ide_pci_iobase; wddma[unit].wdd_altiobase = ide_pci_altiobase; +#if 0 /* * This code below is mighty bogus. The config entries for the * isa_devtab_bio are plugged in before the standard ISA bios scan. @@ -1582,7 +1583,7 @@ ide_pci_attach(pcici_t tag, int unit) } } } - +#endif bmista_1 = inb(iobase_bm_1 + BMISTA_PORT); bmista_2 = inb(iobase_bm_2 + BMISTA_PORT); diff --git a/sys/pci/if_fxp.c b/sys/pci/if_fxp.c index 77f0ade..53b8d4d 100644 --- a/sys/pci/if_fxp.c +++ b/sys/pci/if_fxp.c @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxp.c,v 1.65 1999/03/17 16:44:53 luigi Exp $ + * $Id: if_fxp.c,v 1.66 1999/03/20 04:51:25 wes Exp $ */ /* @@ -89,6 +89,10 @@ #else /* __FreeBSD__ */ #include <sys/sockio.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <net/ethernet.h> #include <net/if_arp.h> @@ -491,51 +495,31 @@ fxp_ether_ioctl(ifp, cmd, data) #else /* __FreeBSD__ */ -static u_long fxp_count; -static const char *fxp_probe __P((pcici_t, pcidi_t)); -static void fxp_attach __P((pcici_t, int)); - -static void fxp_shutdown __P((int, void *)); - -static struct pci_device fxp_device = { - "fxp", - fxp_probe, - fxp_attach, - &fxp_count, - NULL -}; -DATA_SET(pcidevice_set, fxp_device); - /* * Return identification string if this is device is ours. */ -static const char * -fxp_probe(config_id, device_id) - pcici_t config_id; - pcidi_t device_id; +static int +fxp_probe(device_t dev) { - if (((device_id & 0xffff) == FXP_VENDORID_INTEL) && - ((device_id >> 16) & 0xffff) == FXP_DEVICEID_i82557) - return ("Intel EtherExpress Pro 10/100B Ethernet"); + if ((pci_get_vendor(dev) == FXP_VENDORID_INTEL) && + (pci_get_device(dev) == FXP_DEVICEID_i82557)) { + device_set_desc(dev, "Intel EtherExpress Pro 10/100B Ethernet"); + return 0; + } - return NULL; + return ENXIO; } -static void -fxp_attach(config_id, unit) - pcici_t config_id; - int unit; +static int +fxp_attach(device_t dev) { - struct fxp_softc *sc; - vm_offset_t pbase; + int error = 0; + struct fxp_softc *sc = device_get_softc(dev); struct ifnet *ifp; int s; u_long val; + int rid; - sc = malloc(sizeof(struct fxp_softc), M_DEVBUF, M_NOWAIT); - if (sc == NULL) - return; - bzero(sc, sizeof(struct fxp_softc)); callout_handle_init(&sc->stat_ch); s = splimp(); @@ -543,39 +527,56 @@ fxp_attach(config_id, unit) /* * Enable bus mastering. */ - val = pci_conf_read(config_id, PCI_COMMAND_STATUS_REG); + val = pci_read_config(dev, PCIR_COMMAND, 2); val |= (PCIM_CMD_MEMEN|PCIM_CMD_BUSMASTEREN); - pci_conf_write(config_id, PCI_COMMAND_STATUS_REG, val); + pci_write_config(dev, PCIR_COMMAND, val, 2); /* * Map control/status registers. */ - if (!pci_map_mem(config_id, FXP_PCI_MMBA, - (vm_offset_t *)&sc->csr, &pbase)) { - printf("fxp%d: couldn't map memory\n", unit); + rid = FXP_PCI_MMBA; + sc->mem = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!sc->mem) { + device_printf(dev, "could not map memory\n"); + error = ENXIO; goto fail; - } + } + sc->csr = rman_get_virtual(sc->mem); /* XXX use bus_space */ /* * Allocate our interrupt. */ - if (!pci_map_int(config_id, fxp_intr, sc, &net_imask)) { - printf("fxp%d: couldn't map interrupt\n", unit); + rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (sc->irq == NULL) { + device_printf(dev, "could not map interrupt\n"); + error = ENXIO; + goto fail; + } + + error = bus_setup_intr(dev, sc->irq, fxp_intr, sc, &sc->ih); + if (error) { + device_printf(dev, "could not setup irq\n"); goto fail; } /* Do generic parts of attach. */ if (fxp_attach_common(sc, sc->arpcom.ac_enaddr)) { /* Failed! */ - (void) pci_unmap_int(config_id); + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem); + error = ENXIO; goto fail; } - printf("fxp%d: Ethernet address %6D%s\n", unit, + device_printf(dev, "Ethernet address %6D%s\n", sc->arpcom.ac_enaddr, ":", sc->phy_10Mbps_only ? ", 10Mbps" : ""); ifp = &sc->arpcom.ac_if; - ifp->if_unit = unit; + ifp->if_unit = device_get_unit(dev); ifp->if_name = "fxp"; ifp->if_output = ether_output; ifp->if_baudrate = 100000000; @@ -600,19 +601,63 @@ fxp_attach(config_id, unit) bpfattach(ifp, DLT_EN10MB, sizeof(struct ether_header)); #endif + splx(s); + return 0; + + fail: + splx(s); + return error; +} + +/* + * Detach interface. + */ +static int +fxp_detach(device_t dev) +{ + struct fxp_softc *sc = device_get_softc(dev); + int s; + + s = splimp(); + /* - * Add shutdown hook so that DMA is disabled prior to reboot. Not - * doing do could allow DMA to corrupt kernel memory during the - * reboot before the driver initializes. + * Close down routes etc. */ - at_shutdown(fxp_shutdown, sc, SHUTDOWN_POST_SYNC); + if_detach(&sc->arpcom.ac_if); - splx(s); - return; + /* + * Stop DMA and drop transmit queue. + */ + fxp_stop(sc); + + /* + * Deallocate resources. + */ + bus_teardown_intr(dev, sc->irq, sc->ih); + bus_release_resource(dev, SYS_RES_IRQ, 0, sc->irq); + bus_release_resource(dev, SYS_RES_MEMORY, FXP_PCI_MMBA, sc->mem); + + /* + * Free all the receive buffers. + */ + if (sc->rfa_headm != NULL) + m_freem(sc->rfa_headm); + + /* + * Free all media structures. + */ + ifmedia_removeall(&sc->sc_media); + + /* + * Free anciliary structures. + */ + free(sc->cbl_base, M_DEVBUF); + free(sc->fxp_stats, M_DEVBUF); + free(sc->mcsp, M_DEVBUF); - fail: - free(sc, M_DEVBUF); splx(s); + + return 0; } /* @@ -620,14 +665,39 @@ fxp_attach(config_id, unit) * main purpose of this routine is to shut off receiver DMA so that * kernel memory doesn't get clobbered during warmboot. */ -static void -fxp_shutdown(howto, sc) - int howto; - void *sc; +static int +fxp_shutdown(device_t dev) { - fxp_stop((struct fxp_softc *) sc); + /* + * Make sure that DMA is disabled prior to reboot. Not doing + * do could allow DMA to corrupt kernel memory during the + * reboot before the driver initializes. + */ + fxp_stop((struct fxp_softc *) device_get_softc(dev)); + return 0; } +static device_method_t fxp_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, fxp_probe), + DEVMETHOD(device_attach, fxp_attach), + DEVMETHOD(device_detach, fxp_detach), + DEVMETHOD(device_shutdown, fxp_shutdown), + + { 0, 0 } +}; + +static driver_t fxp_driver = { + "fxp", + fxp_methods, + DRIVER_TYPE_NET, + sizeof(struct fxp_softc), +}; + +static devclass_t fxp_devclass; + +DRIVER_MODULE(fxp, pci, fxp_driver, fxp_devclass, 0, 0); + #endif /* __NetBSD__ */ /************************************************************* diff --git a/sys/pci/if_fxpvar.h b/sys/pci/if_fxpvar.h index ce8d8fe..042d2df 100644 --- a/sys/pci/if_fxpvar.h +++ b/sys/pci/if_fxpvar.h @@ -27,7 +27,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: if_fxpvar.h,v 1.5 1998/06/07 17:12:38 dfr Exp $ + * $Id: if_fxpvar.h,v 1.6 1998/08/02 00:29:15 dg Exp $ */ /* @@ -48,6 +48,9 @@ struct fxp_softc { #else struct arpcom arpcom; /* per-interface network data */ caddr_t csr; /* control/status registers */ + struct resource *mem; /* resource descriptor for registers */ + struct resource *irq; /* resource descriptor for interrupt */ + void *ih; /* interrupt handler cookie */ #endif /* __NetBSD__ */ struct mbuf *rfa_headm; /* first mbuf in receive frame area */ struct mbuf *rfa_tailm; /* last mbuf in receive frame area */ diff --git a/sys/pci/if_pn.c b/sys/pci/if_pn.c index 425195e..3209051 100644 --- a/sys/pci/if_pn.c +++ b/sys/pci/if_pn.c @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_pn.c,v 1.50 1999/04/14 18:52:02 wpaul Exp $ + * $Id: if_pn.c,v 1.16 1999/04/14 19:40:07 wpaul Exp $ */ /* @@ -97,7 +97,13 @@ #ifndef lint static const char rcsid[] = - "$Id: if_pn.c,v 1.50 1999/04/14 18:52:02 wpaul Exp $"; + "$Id: if_pn.c,v 1.16 1999/04/14 19:40:07 wpaul Exp $"; +#endif + +#ifdef __alpha__ +#undef vtophys +#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \ + + 1*1024*1024*1024) #endif /* diff --git a/sys/pci/if_xl.c b/sys/pci/if_xl.c index d9b9e61..e848418 100644 --- a/sys/pci/if_xl.c +++ b/sys/pci/if_xl.c @@ -29,7 +29,7 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: if_xl.c,v 1.30 1999/04/15 03:18:33 wpaul Exp $ + * $Id: if_xl.c,v 1.31 1999/04/16 01:56:06 ghelmer Exp $ */ /* @@ -122,6 +122,12 @@ #include <pci/pcireg.h> #include <pci/pcivar.h> +#ifdef __alpha__ +#undef vtophys +#define vtophys(va) (pmap_kextract(((vm_offset_t) (va))) \ + + 1*1024*1024*1024) +#endif + /* * The following #define causes the code to use PIO to access the * chip's registers instead of memory mapped mode. The reason PIO mode @@ -158,7 +164,7 @@ #if !defined(lint) static const char rcsid[] = - "$Id: if_xl.c,v 1.30 1999/04/15 03:18:33 wpaul Exp $"; + "$Id: if_xl.c,v 1.31 1999/04/16 01:56:06 ghelmer Exp $"; #endif /* @@ -1513,7 +1519,7 @@ xl_attach(config_id, unit) } sc->xl_ldata = (struct xl_list_data *)sc->xl_ldata_ptr; - round = (unsigned int)sc->xl_ldata_ptr & 0xF; + round = (uintptr_t)sc->xl_ldata_ptr & 0xF; roundptr = sc->xl_ldata_ptr; for (i = 0; i < 8; i++) { if (round % 8) { diff --git a/sys/pci/ohci_pci.c b/sys/pci/ohci_pci.c index 3c20ff7..1aea5f1 100644 --- a/sys/pci/ohci_pci.c +++ b/sys/pci/ohci_pci.c @@ -44,6 +44,8 @@ * USB spec: http://www.teleport.com/cgi-bin/mailmerge.cgi/~usb/cgiform.tpl */ +#include "opt_bus.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -52,23 +54,13 @@ #include <sys/device.h> #include <sys/proc.h> #include <sys/queue.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <pci/pcivar.h> #include <pci/pcireg.h> -#define PCI_CLASS_SERIALBUS 0x0c000000 -#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000 -#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000 -#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000 -#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000 - -#define PCI_INTERFACE(d) (((d) >> 8) & 0xff) -#define PCI_SUBCLASS(d) ((d) & PCI_SUBCLASS_MASK) -#define PCI_CLASS(d) ((d) & PCI_CLASS_MASK) - - #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> @@ -77,7 +69,6 @@ #include <dev/usb/ohcireg.h> #include <dev/usb/ohcivar.h> - #define PCI_OHCI_VENDORID_ALI 0x10b9 #define PCI_OHCI_VENDORID_CMDTECH 0x1095 #define PCI_OHCI_VENDORID_COMPAQ 0x0e11 @@ -98,27 +89,12 @@ static const char *ohci_device_usb0673 = "CMD Tech 673 (USB0673) USB Host Contr static const char *ohci_device_generic = "OHCI (generic) USB Host Controller"; - -static const char *ohci_pci_probe __P((pcici_t, pcidi_t)); -static void ohci_pci_attach __P((pcici_t, int)); - -static u_long ohci_count = 0; - -static struct pci_device ohci_pci_device = { - "ohci", - ohci_pci_probe, - ohci_pci_attach, - &ohci_count, - NULL -}; - -DATA_SET(pcidevice_set, ohci_pci_device); - +#define PCI_OHCI_BASE_REG 0x10 static const char * -ohci_pci_probe(pcici_t config_id, pcidi_t device_id) +ohci_pci_match(device_t dev) { - u_int32_t class; + u_int32_t device_id = pci_get_devid(dev); switch(device_id) { case PCI_OHCI_DEVICEID_ALADDIN_V: @@ -132,54 +108,72 @@ ohci_pci_probe(pcici_t config_id, pcidi_t device_id) case PCI_OHCI_DEVICEID_NEC: return (ohci_device_nec); default: - class = pci_conf_read(config_id, PCI_CLASS_REG); - if ( (PCI_CLASS(class) == PCI_CLASS_SERIALBUS) - && (PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB) - && (PCI_INTERFACE(class) == PCI_INTERFACE_OHCI)) { - return(ohci_device_generic); + if ( pci_get_class(dev) == PCIC_SERIALBUS + && pci_get_subclass(dev) == PCIS_SERIALBUS_USB + && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { + return (ohci_device_generic); } } return NULL; /* dunno */ } -static void -ohci_pci_attach(pcici_t config_id, int unit) +static int +ohci_pci_probe(device_t dev) { - vm_offset_t pbase; + const char *desc = ohci_pci_match(dev); + if (desc) { + device_set_desc(dev, desc); + return 0; + } else { + return ENXIO; + } +} + +static int +ohci_pci_attach(device_t dev) +{ + int unit = device_get_unit(dev); + ohci_softc_t *sc = device_get_softc(dev); device_t usbus; - ohci_softc_t *sc; usbd_status err; - int id; + int rid; + struct resource *res; + void *ih; + int error; + + rid = PCI_CBMEM; + res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!res) { + device_printf(dev, "could not map memory\n"); + return ENXIO; + } - sc = malloc(sizeof(ohci_softc_t), M_DEVBUF, M_NOWAIT); - /* Do not free it below, intr might use the sc */ - if ( sc == NULL ) { - printf("ohci%d: could not allocate memory", unit); - return; - } - memset(sc, 0, sizeof(ohci_softc_t)); + sc->iot = rman_get_bustag(res); + sc->ioh = rman_get_bushandle(res); - if(!pci_map_mem(config_id, PCI_CBMEM, - (vm_offset_t *)&sc->sc_iobase, &pbase)) { - printf("ohci%d: could not map memory\n", unit); - return; - } + rid = 0; + res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (res == NULL) { + device_printf(dev, "could not allocate irq\n"); + return ENOMEM; + } - if ( !pci_map_int(config_id, (pci_inthand_t *)ohci_intr, - (void *) sc, &bio_imask)) { - printf("ohci%d: could not map irq\n", unit); - return; + error = bus_setup_intr(dev, res, (driver_intr_t *) ohci_intr, sc, &ih); + if (error) { + device_printf(dev, "could not setup irq\n"); + return error; } - usbus = device_add_child(root_bus, "usb", -1, sc); + usbus = device_add_child(dev, "usb", -1, sc); if (!usbus) { - printf("ohci%d: could not add USB device to root bus\n", unit); - return; + printf("ohci%d: could not add USB device\n", unit); + return ENOMEM; } - id = pci_conf_read(config_id, PCI_ID_REG); - switch(id) { + switch (pci_get_devid(dev)) { case PCI_OHCI_DEVICEID_ALADDIN_V: device_set_desc(usbus, ohci_device_aladdin_v); sprintf(sc->sc_vendor, "AcerLabs"); @@ -202,7 +196,7 @@ ohci_pci_attach(pcici_t config_id, int unit) break; default: if (bootverbose) - printf("(New OHCI DeviceId=0x%08x)\n", id); + printf("(New OHCI DeviceId=0x%08x)\n", pci_get_devid(dev)); device_set_desc(usbus, ohci_device_generic); sprintf(sc->sc_vendor, "(unknown)"); } @@ -211,8 +205,36 @@ ohci_pci_attach(pcici_t config_id, int unit) err = ohci_init(sc); if (err != USBD_NORMAL_COMPLETION) { printf("ohci%d: init failed, error=%d\n", unit, err); - device_delete_child(root_bus, usbus); + device_delete_child(dev, usbus); } - return; + return device_probe_and_attach(sc->sc_bus.bdev); } + +static device_method_t ohci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ohci_pci_probe), + DEVMETHOD(device_attach, ohci_pci_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t ohci_driver = { + "ohci", + ohci_methods, + DRIVER_TYPE_BIO, + sizeof(ohci_softc_t), +}; + +static devclass_t ohci_devclass; + +DRIVER_MODULE(ohci, pci, ohci_driver, ohci_devclass, 0, 0); diff --git a/sys/pci/pci.c b/sys/pci/pci.c index e449fc2..889550c 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -23,10 +23,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci.c,v 1.93 1999/01/19 23:29:18 se Exp $ + * $Id: pci.c,v 1.94 1999/04/11 02:47:31 eivind Exp $ * */ +#include "opt_bus.h" + #include "pci.h" #if NPCI > 0 @@ -50,6 +52,11 @@ #include <vm/pmap.h> #include <vm/vm_extern.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + #include <pci/pcireg.h> #include <pci/pcivar.h> #include <pci/pci_ioctl.h> @@ -338,11 +345,10 @@ pci_readcfg(pcicfgregs *probe) M_DEVBUF, M_WAITOK); if (devlist_entry == NULL) return (NULL); + bzero(devlist_entry, sizeof *devlist_entry); cfg = &devlist_entry->cfg; - bzero(cfg, sizeof *cfg); - cfg->bus = probe->bus; cfg->slot = probe->slot; cfg->func = probe->func; @@ -450,113 +456,6 @@ pci_freecfg(struct pci_devinfo *dinfo) } #endif -static void -pci_addcfg(struct pci_devinfo *dinfo) -{ - if (bootverbose) { - int i; - pcicfgregs *cfg = &dinfo->cfg; - - printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", - cfg->vendor, cfg->device, cfg->revid); - printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", - cfg->baseclass, cfg->subclass, cfg->progif, - cfg->hdrtype, cfg->mfdev); - printf("\tsubordinatebus=%x \tsecondarybus=%x\n", - cfg->subordinatebus, cfg->secondarybus); -#ifdef PCI_DEBUG - printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", - cfg->cmdreg, cfg->statreg, cfg->cachelnsz); - printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", - cfg->lattimer, cfg->lattimer * 30, - cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); -#endif /* PCI_DEBUG */ - if (cfg->intpin > 0) - printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); - - for (i = 0; i < cfg->nummaps; i++) { - pcimap *m = &cfg->map[i]; - printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", - i, m->type, m->ln2range, m->base, m->ln2size); - } - } - pci_drvattach(dinfo); /* XXX currently defined in pci_compat.c */ -} - -/* scan one PCI bus for devices */ - -static int -pci_probebus(int bus) -{ - pcicfgregs probe; - int bushigh = bus; - -#ifdef SIMOS -#undef PCI_SLOTMAX -#define PCI_SLOTMAX 0 -#endif - - bzero(&probe, sizeof probe); - /* XXX KDM */ - /* probe.parent = pci_bridgeto(bus); */ - probe.bus = bus; - for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { - int pcifunchigh = 0; - for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { - struct pci_devinfo *dinfo = pci_readcfg(&probe); - if (dinfo != NULL) { - if (dinfo->cfg.mfdev) - pcifunchigh = 7; - /* - * XXX: Temporarily move pci_addcfg() up before - * the use of cfg->subordinatebus. This is - * necessary, since pci_addcfg() calls the - * device's probe(), which may read the bus# - * from some device dependent register of - * some host to PCI bridges. The probe will - * eventually be moved to pci_readcfg(), and - * pci_addcfg() will then be moved back down - * below the conditional statement ... - */ - pci_addcfg(dinfo); - - if (bushigh < dinfo->cfg.subordinatebus) - bushigh = dinfo->cfg.subordinatebus; - if (bushigh < dinfo->cfg.secondarybus) - bushigh = dinfo->cfg.secondarybus; - - /* XXX KDM */ - /* cfg = NULL; we don't own this anymore ... */ - } - } - } - return (bushigh); -} - -/* scan a PCI bus tree reached through one PCI attachment point */ - -int -pci_probe(pciattach *parent) -{ - int bushigh; - int bus = 0; - - STAILQ_INIT(&pci_devq); - - bushigh = pci_bushigh(); - while (bus <= bushigh) { - int newbushigh; - - printf("Probing for devices on PCI bus %d:\n", bus); - newbushigh = pci_probebus(bus); - - if (bushigh < newbushigh) - bushigh = newbushigh; - bus++; - } - return (bushigh); -} - /* * This is the user interface to PCI configuration space. */ @@ -750,8 +649,8 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) "pci_match_conf) (%d)\npci_ioctl: " "pat_buf_len should be = %d\n", cio->pat_buf_len, cio->num_patterns, - sizeof(struct pci_match_conf), - sizeof(struct pci_match_conf) * + (int)sizeof(struct pci_match_conf), + (int)sizeof(struct pci_match_conf) * cio->num_patterns); printf("pci_ioctl: do your headers match your " "kernel?\n"); @@ -945,4 +844,534 @@ pci_cdevinit(void *dummy) SYSINIT(pcidev, SI_SUB_DRIVERS, SI_ORDER_MIDDLE+PCI_CDEV, pci_cdevinit, NULL); +#include "pci_if.h" + +/* + * A simple driver to wrap the old pci driver mechanism for back-compat. + */ + +static int +pci_compat_probe(device_t dev) +{ + struct pci_device *dvp; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + const char *name; + int error; + + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + dvp = device_get_driver(dev)->priv; + + /* + * Do the wrapped probe. + */ + error = ENXIO; + if (dvp && dvp->pd_probe) { + name = dvp->pd_probe(cfg, (cfg->device << 16) + cfg->vendor); + if (name) { + device_set_desc_copy(dev, name); + error = 0; + } + } + + return error; +} + +static int +pci_compat_attach(device_t dev) +{ + struct pci_device *dvp; + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + int unit; + + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + dvp = device_get_driver(dev)->priv; + + unit = device_get_unit(dev); + if (unit > *dvp->pd_count) + *dvp->pd_count = unit; + if (dvp->pd_attach) + dvp->pd_attach(cfg, unit); + + /* + * XXX KDM for some devices, dvp->pd_name winds up NULL. + * I haven't investigated enough to figure out why this + * would happen. + */ + if (dvp->pd_name != NULL) + strncpy(dinfo->conf.pd_name, dvp->pd_name, + sizeof(dinfo->conf.pd_name)); + else + strncpy(dinfo->conf.pd_name, "????", + sizeof(dinfo->conf.pd_name)); + dinfo->conf.pd_name[sizeof(dinfo->conf.pd_name) - 1] = 0; + dinfo->conf.pd_unit = unit; + + return 0; +} + +static device_method_t pci_compat_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pci_compat_probe), + DEVMETHOD(device_attach, pci_compat_attach), + + { 0, 0 } +}; + +static devclass_t pci_devclass; + +/* + * Create a new style driver around each old pci driver. + */ +static void +pci_wrap_old_drivers(void) +{ + struct pci_device **dvpp, *dvp; + + dvpp = (struct pci_device **)pcidevice_set.ls_items; + while ((dvp = *dvpp++) != NULL) { + driver_t *driver; + driver = malloc(sizeof(driver_t), M_DEVBUF, M_NOWAIT); + if (!driver) + continue; + bzero(driver, sizeof(driver_t)); + driver->name = dvp->pd_name; + driver->methods = pci_compat_methods; + driver->type = 0; /* XXX fixup in pci_map_int() */ + driver->softc = sizeof(struct pci_devinfo *); + driver->priv = dvp; + devclass_add_driver(pci_devclass, driver); + } +} + +/* + * New style pci driver. Parent device is either a pci-host-bridge or a + * pci-pci-bridge. Both kinds are represented by instances of pcib. + */ + +static void +pci_print_verbose(struct pci_devinfo *dinfo) +{ + if (bootverbose) { + int i; + pcicfgregs *cfg = &dinfo->cfg; + + printf("found->\tvendor=0x%04x, dev=0x%04x, revid=0x%02x\n", + cfg->vendor, cfg->device, cfg->revid); + printf("\tclass=%02x-%02x-%02x, hdrtype=0x%02x, mfdev=%d\n", + cfg->baseclass, cfg->subclass, cfg->progif, + cfg->hdrtype, cfg->mfdev); + printf("\tsubordinatebus=%x \tsecondarybus=%x\n", + cfg->subordinatebus, cfg->secondarybus); +#ifdef PCI_DEBUG + printf("\tcmdreg=0x%04x, statreg=0x%04x, cachelnsz=%d (dwords)\n", + cfg->cmdreg, cfg->statreg, cfg->cachelnsz); + printf("\tlattimer=0x%02x (%d ns), mingnt=0x%02x (%d ns), maxlat=0x%02x (%d ns)\n", + cfg->lattimer, cfg->lattimer * 30, + cfg->mingnt, cfg->mingnt * 250, cfg->maxlat, cfg->maxlat * 250); +#endif /* PCI_DEBUG */ + if (cfg->intpin > 0) + printf("\tintpin=%c, irq=%d\n", cfg->intpin +'a' -1, cfg->intline); + + for (i = 0; i < cfg->nummaps; i++) { + pcimap *m = &cfg->map[i]; + printf("\tmap[%d]: type %x, range %2d, base %08x, size %2d\n", + i, m->type, m->ln2range, m->base, m->ln2size); + } + } +} + +static int +pci_add_children(device_t dev, int busno) +{ + pcicfgregs probe; + int bushigh = busno; + +#ifdef SIMOS +#undef PCI_SLOTMAX +#define PCI_SLOTMAX 0 +#endif + + bzero(&probe, sizeof probe); + /* XXX KDM */ + /* probe.parent = pci_bridgeto(bus); */ + probe.bus = busno; + for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { + int pcifunchigh = 0; + for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { + struct pci_devinfo *dinfo = pci_readcfg(&probe); + if (dinfo != NULL) { + if (dinfo->cfg.mfdev) + pcifunchigh = 7; + + pci_print_verbose(dinfo); + dinfo->cfg.dev = + device_add_child(dev, NULL, -1, dinfo); + + if (bushigh < dinfo->cfg.subordinatebus) + bushigh = dinfo->cfg.subordinatebus; + if (bushigh < dinfo->cfg.secondarybus) + bushigh = dinfo->cfg.secondarybus; + } + } + } + + return bushigh; +} + +static int +pci_new_probe(device_t dev) +{ + STAILQ_INIT(&pci_devq); + device_set_desc(dev, "PCI bus"); + + pci_add_children(dev, device_get_unit(dev)); + + return 0; +} + +static void +pci_print_child(device_t dev, device_t child) +{ + printf(" at device %d.%d", pci_get_slot(child), pci_get_function(child)); + printf(" on %s%d", device_get_name(dev), device_get_unit(dev)); +} + +static int +pci_read_ivar(device_t dev, device_t child, int which, u_long *result) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + + switch (which) { + case PCI_IVAR_SUBVENDOR: + *result = cfg->subvendor; + break; + case PCI_IVAR_SUBDEVICE: + *result = cfg->subdevice; + break; + case PCI_IVAR_VENDOR: + *result = cfg->vendor; + break; + case PCI_IVAR_DEVICE: + *result = cfg->device; + break; + case PCI_IVAR_DEVID: + *result = (cfg->device << 16) | cfg->vendor; + break; + case PCI_IVAR_CLASS: + *result = cfg->baseclass; + break; + case PCI_IVAR_SUBCLASS: + *result = cfg->subclass; + break; + case PCI_IVAR_PROGIF: + *result = cfg->progif; + break; + case PCI_IVAR_REVID: + *result = cfg->revid; + break; + case PCI_IVAR_INTPIN: + *result = cfg->intpin; + break; + case PCI_IVAR_IRQ: + *result = cfg->intline; + break; + case PCI_IVAR_BUS: + *result = cfg->bus; + break; + case PCI_IVAR_SLOT: + *result = cfg->slot; + break; + case PCI_IVAR_FUNCTION: + *result = cfg->func; + break; + case PCI_IVAR_SECONDARYBUS: + *result = cfg->secondarybus; + break; + case PCI_IVAR_SUBORDINATEBUS: + *result = cfg->subordinatebus; + break; + default: + return ENOENT; + } + return 0; +} + +static int +pci_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + dinfo = device_get_ivars(child); + cfg = &dinfo->cfg; + + switch (which) { + case PCI_IVAR_SUBVENDOR: + case PCI_IVAR_SUBDEVICE: + case PCI_IVAR_VENDOR: + case PCI_IVAR_DEVICE: + case PCI_IVAR_DEVID: + case PCI_IVAR_CLASS: + case PCI_IVAR_SUBCLASS: + case PCI_IVAR_PROGIF: + case PCI_IVAR_REVID: + case PCI_IVAR_INTPIN: + case PCI_IVAR_IRQ: + case PCI_IVAR_BUS: + case PCI_IVAR_SLOT: + case PCI_IVAR_FUNCTION: + return EINVAL; /* disallow for now */ + + case PCI_IVAR_SECONDARYBUS: + cfg->secondarybus = value; + break; + case PCI_IVAR_SUBORDINATEBUS: + cfg->subordinatebus = value; + break; + default: + return ENOENT; + } + return 0; +} + +static int +pci_mapno(pcicfgregs *cfg, int reg) +{ + int i, nummaps; + pcimap *map; + + nummaps = cfg->nummaps; + map = cfg->map; + + for (i = 0; i < nummaps; i++) + if (map[i].reg == reg) + return (i); + return (-1); +} + +static int +pci_porten(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); +} + +static int +pci_isportmap(pcicfgregs *cfg, int map) + +{ + return ((unsigned)map < cfg->nummaps + && (cfg->map[map].type & PCI_MAPPORT) != 0); +} + +static int +pci_memen(pcicfgregs *cfg) +{ + return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); +} + +static int +pci_ismemmap(pcicfgregs *cfg, int map) +{ + return ((unsigned)map < cfg->nummaps + && (cfg->map[map].type & PCI_MAPMEM) != 0); +} + +static struct resource * +pci_alloc_resource(device_t dev, device_t child, int type, int *rid, + u_long start, u_long end, u_long count, u_int flags) +{ + int isdefault; + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + struct resource *rv, **rvp = 0; + int map; + + isdefault = (device_get_parent(child) == dev + && start == 0UL && end == ~0UL && count == 1); + + switch (type) { + case SYS_RES_IRQ: + if (*rid != 0) + return 0; + if (isdefault && cfg->intline != 255) { + start = cfg->intline; + end = cfg->intline; + count = 1; + } + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + if (isdefault) { + map = pci_mapno(cfg, *rid); + if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { + start = cfg->map[map].base; + count = 1 << cfg->map[map].ln2size; + end = start + count; + rvp = &cfg->map[map].res; + } else + return 0; + } + break; + + case SYS_RES_IOPORT: + if (isdefault) { + map = pci_mapno(cfg, *rid); + if (pci_porten(cfg) && pci_isportmap(cfg, map)) { + start = cfg->map[map].base; + count = 1 << cfg->map[map].ln2size; + end = start + count; + rvp = &cfg->map[map].res; + } else + return 0; + } + break; + + default: + return 0; + } + + rv = BUS_ALLOC_RESOURCE(device_get_parent(dev), child, + type, rid, start, end, count, flags); + if (rvp) + *rvp = rv; + + return rv; +} + +static int +pci_release_resource(device_t dev, device_t child, int type, int rid, + struct resource *r) +{ + int rv; + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + int map = 0; + + switch (type) { + case SYS_RES_IRQ: + if (rid != 0) + return EINVAL; + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + /* + * Only check the map registers if this is a direct + * descendant. + */ + if (device_get_parent(child) == dev) + map = pci_mapno(cfg, rid); + else + map = -1; + break; + + default: + return (ENOENT); + } + + rv = BUS_RELEASE_RESOURCE(device_get_parent(dev), child, type, rid, r); + + if (rv == 0) { + switch (type) { + case SYS_RES_IRQ: + cfg->irqres = 0; + break; + + case SYS_RES_DRQ: /* passthru for child isa */ + break; + + case SYS_RES_MEMORY: + case SYS_RES_IOPORT: + if (map != -1) + cfg->map[map].res = 0; + break; + + default: + return ENOENT; + } + } + + return rv; +} + +static u_int32_t +pci_read_config_method(device_t dev, device_t child, int reg, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + return pci_cfgread(cfg, reg, width); +} + +static void +pci_write_config_method(device_t dev, device_t child, int reg, + u_int32_t val, int width) +{ + struct pci_devinfo *dinfo = device_get_ivars(child); + pcicfgregs *cfg = &dinfo->cfg; + pci_cfgwrite(cfg, reg, val, width); +} + +static int +pci_modevent(module_t mod, int what, void *arg) +{ + switch (what) { + case MOD_LOAD: + pci_wrap_old_drivers(); + break; + + case MOD_UNLOAD: + break; + } + + return 0; +} + +static device_method_t pci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pci_new_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, pci_print_child), + DEVMETHOD(bus_read_ivar, pci_read_ivar), + DEVMETHOD(bus_write_ivar, pci_write_ivar), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + DEVMETHOD(bus_alloc_resource, pci_alloc_resource), + DEVMETHOD(bus_release_resource, pci_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + /* PCI interface */ + DEVMETHOD(pci_read_config, pci_read_config_method), + DEVMETHOD(pci_write_config, pci_write_config_method), + + { 0, 0 } +}; + +static driver_t pci_driver = { + "pci", + pci_methods, + DRIVER_TYPE_MISC, + 1, /* no softc */ +}; + +DRIVER_MODULE(pci, pcib, pci_driver, pci_devclass, pci_modevent, 0); + #endif /* NPCI > 0 */ diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c index f107e54..bfa1d59 100644 --- a/sys/pci/pci_compat.c +++ b/sys/pci/pci_compat.c @@ -23,10 +23,12 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pci_compat.c,v 1.20 1999/01/19 23:29:19 se Exp $ + * $Id: pci_compat.c,v 1.21 1999/04/11 02:46:20 eivind Exp $ * */ +#include "opt_bus.h" + #include "pci.h" #if NPCI > 0 @@ -41,6 +43,11 @@ #include <vm/pmap.h> #include <sys/interrupt.h> +#include <sys/bus.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> + #include <pci/pcireg.h> #include <pci/pcivar.h> @@ -56,118 +63,45 @@ /* ------------------------------------------------------------------------- */ -static int -pci_mapno(pcicfgregs *cfg, int reg) -{ - int i, nummaps; - pcimap *map; - - nummaps = cfg->nummaps; - map = cfg->map; - - for (i = 0; i < nummaps; i++) - if (map[i].reg == reg) - return (i); - return (-1); -} - -static int -pci_porten(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); -} - -static int -pci_isportmap(pcicfgregs *cfg, int map) - -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPPORT) != 0); -} - -static int -pci_memen(pcicfgregs *cfg) -{ - return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); -} - -static int -pci_ismemmap(pcicfgregs *cfg, int map) -{ - return ((unsigned)map < cfg->nummaps - && (cfg->map[map].type & PCI_MAPMEM) != 0); -} - -/* ------------------------------------------------------------------------- */ - u_long -pci_conf_read(pcici_t tag, u_long reg) +pci_conf_read(pcici_t cfg, u_long reg) { - return (pci_cfgread(tag, reg, 4)); + return (pci_read_config(cfg->dev, reg, 4)); } void -pci_conf_write(pcici_t tag, u_long reg, u_long data) +pci_conf_write(pcici_t cfg, u_long reg, u_long data) { - pci_cfgwrite(tag, reg, data, 4); + pci_write_config(cfg->dev, reg, data, 4); } int pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa) { - int map; - - map = pci_mapno(cfg, reg); - if (pci_porten(cfg) && pci_isportmap(cfg, map)) { - u_int32_t iobase; - u_int32_t iosize; - - iobase = cfg->map[map].base; - iosize = 1 << cfg->map[map].ln2size; -#ifdef RESOURCE_CHECK - if (resource_claim(cfg, REST_PORT, RESF_NONE, - iobase, iobase + iosize -1) == 0) -#endif /* RESOURCE_CHECK */ - { - *pa = iobase; - return (1); - } + int rid; + struct resource *res; + + rid = reg; + res = bus_alloc_resource(cfg->dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + if (res) { + *pa = rman_get_start(res); + return (1); } return (0); } int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) { - int map; - - map = pci_mapno(cfg, reg); - if (pci_memen(cfg) && pci_ismemmap(cfg, map)) { - u_int32_t paddr; - u_int32_t psize; - - paddr = cfg->map[map].base; - psize = 1 << cfg->map[map].ln2size; -#ifdef RESOURCE_CHECK - if (resource_claim(cfg, REST_MEM, RESF_NONE, - paddr, paddr + psize -1) == 0) -#endif /* RESOURCE_CHECK */ - { - u_int32_t poffs; - vm_offset_t vaddr; - - poffs = paddr - trunc_page(paddr); -#ifdef __i386__ - vaddr = (vm_offset_t)pmap_mapdev(paddr-poffs, psize+poffs); -#endif -#ifdef __alpha__ - vaddr = paddr-poffs; -#endif - if (vaddr != NULL) { - vaddr += poffs; - *va = vaddr; - *pa = paddr; - return (1); - } - } + int rid; + struct resource *res; + + rid = reg; + res = bus_alloc_resource(cfg->dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + if (res) { + *pa = rman_get_start(res); + *va = (vm_offset_t) rman_get_virtual(res); + return (1); } return (0); } @@ -175,7 +109,7 @@ int pci_map_mem(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) int pci_map_dense(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) { - if(pci_map_mem(cfg, reg, va, pa)){ + if (pci_map_mem(cfg, reg, va, pa)){ #ifdef __alpha__ vm_offset_t dense; @@ -195,7 +129,7 @@ pci_map_dense(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) int pci_map_bwx(pcici_t cfg, u_long reg, vm_offset_t* va, vm_offset_t* pa) { - if(pci_map_mem(cfg, reg, va, pa)){ + if (pci_map_mem(cfg, reg, va, pa)){ #ifdef __alpha__ vm_offset_t bwx; @@ -228,14 +162,42 @@ pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg, #endif if (cfg->intpin != 0) { int irq = cfg->intline; - void *dev_instance = (void *)-1; /* XXX use cfg->devdata */ - void *idesc; + driver_t *driver = device_get_driver(cfg->dev); + int rid = 0; + struct resource *res; + void *ih; + res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid, + irq, irq, 1, RF_SHAREABLE|RF_ACTIVE); + if (!res) { + printf("pci_map_int: can't allocate interrupt\n"); + return 0; + } - idesc = intr_create(dev_instance, irq, handler, arg, maskptr, - flags); - error = intr_connect(idesc); + /* + * This is ugly. Translate the mask into a driver type. + */ + if (maskptr == &tty_imask) + driver->type |= DRIVER_TYPE_TTY; + else if (maskptr == &bio_imask) + driver->type |= DRIVER_TYPE_BIO; + else if (maskptr == &net_imask) + driver->type |= DRIVER_TYPE_NET; + else if (maskptr == &cam_imask) + driver->type |= DRIVER_TYPE_CAM; + + error = BUS_SETUP_INTR(device_get_parent(cfg->dev), cfg->dev, + res, handler, arg, &ih); if (error != 0) return 0; + +#ifdef NEW_BUS_PCI + /* + * XXX this apic stuff looks totally busted. It should + * move to the nexus code which actually registers the + * interrupt. + */ +#endif + #ifdef APIC_IO nextpin = next_apic_irq(irq); @@ -265,11 +227,21 @@ pci_map_int_right(pcici_t cfg, pci_inthand_t *handler, void *arg, nextpin = next_apic_irq(irq); while (nextpin >= 0) { - idesc = intr_create(dev_instance, nextpin, handler, - arg, maskptr, flags); - error = intr_connect(idesc); - if (error != 0) + rid = 0; + res = bus_alloc_resource(cfg->dev, SYS_RES_IRQ, &rid, + nextpin, nextpin, 1, + RF_SHAREABLE|RF_ACTIVE); + if (!res) { + printf("pci_map_int: can't allocate extra interrupt\n"); + return 0; + } + error = BUS_SETUP_INTR(device_get_parent(cfg->dev), + cfg->dev, res, handler, arg, + &ih); + if (error != 0) { + printf("pci_map_int: BUS_SETUP_INTR failed\n"); return 0; + } printf("Registered extra interrupt handler for int %d (in addition to int %d)\n", nextpin, irq); nextpin = next_apic_irq(nextpin); } @@ -284,6 +256,7 @@ pci_unmap_int(pcici_t cfg) return (0); /* not supported, yet, since cfg doesn't know about idesc */ } +#if 0 /* ------------------------------------------------------------------------- */ /* @@ -464,6 +437,7 @@ int pci_register_lkm (struct pci_device *dvp, int if_revision) if (lkm == NULL) { return (-1); } + bzero(lkm, sizeof (*lkm)); lkm->dvp = dvp; lkm->next = pci_lkm_head; @@ -480,5 +454,7 @@ pci_configure(void) /* ------------------------------------------------------------------------- */ +#endif + #endif /* PCI_COMPAT */ #endif /* NPCI > 0 */ diff --git a/sys/pci/pci_if.m b/sys/pci/pci_if.m new file mode 100644 index 0000000..b2fa675 --- /dev/null +++ b/sys/pci/pci_if.m @@ -0,0 +1,44 @@ +# +# Copyright (c) 1998 Doug Rabson +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# +# $Id$ +# + +INTERFACE pci; + +METHOD u_int32_t read_config { + device_t dev; + device_t child; + int reg; + int width; +}; + +METHOD void write_config { + device_t dev; + device_t child; + int reg; + u_int32_t val; + int width; +}; diff --git a/sys/pci/pcireg.h b/sys/pci/pcireg.h index 0adb540..9c0dba0 100644 --- a/sys/pci/pcireg.h +++ b/sys/pci/pcireg.h @@ -26,7 +26,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcireg.h,v 1.19 1997/09/20 07:41:58 dyson Exp $ + * $Id: pcireg.h,v 1.20 1998/10/07 03:40:51 gibbs Exp $ * */ @@ -173,7 +173,7 @@ #define PCIS_MEMORY_OTHER 0x80 #define PCIC_BRIDGE 0x06 -#define PCIS_BRDIGE_HOST 0x00 +#define PCIS_BRIDGE_HOST 0x00 #define PCIS_BRIDGE_ISA 0x01 #define PCIS_BRIDGE_EISA 0x02 #define PCIS_BRIDGE_MCA 0x03 diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c index b292c92..1fe5f1e 100644 --- a/sys/pci/pcisupport.c +++ b/sys/pci/pcisupport.c @@ -1,6 +1,6 @@ /************************************************************************** ** -** $Id: pcisupport.c,v 1.94 1999/02/21 11:39:37 dfr Exp $ +** $Id: pcisupport.c,v 1.95 1999/04/07 03:59:13 msmith Exp $ ** ** Device driver for DEC/INTEL PCI chipsets. ** @@ -41,6 +41,7 @@ *************************************************************************** */ +#include "opt_bus.h" #include "opt_pci.h" #include "opt_smp.h" #include "intpm.h" @@ -50,6 +51,7 @@ #include <sys/systm.h> #include <sys/malloc.h> #include <sys/kernel.h> +#include <sys/bus.h> #include <pci/pcivar.h> #include <pci/pcireg.h> @@ -65,19 +67,7 @@ **--------------------------------------------------------- */ -static const char* chipset_probe (pcici_t tag, pcidi_t type); -static void chipset_attach(pcici_t tag, int unit); -static u_long chipset_count; - -static struct pci_device chipset_device = { - "chip", - chipset_probe, - chipset_attach, - &chipset_count, - NULL -}; - -DATA_SET (pcidevice_set, chipset_device); +static void chipset_attach(device_t dev, int unit); struct condmsg { unsigned char port; @@ -127,20 +117,22 @@ generic_pci_bridge (pcici_t tag) */ static void -fixbushigh_orion(pcici_t tag) +fixbushigh_orion(device_t dev) { - tag->secondarybus = pci_cfgread(tag, 0x4a, 1); - tag->subordinatebus = pci_cfgread(tag, 0x4b, 1); + pci_set_secondarybus(dev, pci_read_config(dev, 0x4a, 1)); + pci_set_subordinatebus(dev, pci_read_config(dev, 0x4b, 1)); } static void -fixbushigh_i1225(pcici_t tag) +fixbushigh_i1225(device_t dev) { int sublementarybus; - sublementarybus = pci_cfgread(tag, 0x41, 1); - if (sublementarybus != 0xff) - tag->secondarybus = tag->subordinatebus = sublementarybus +1; + sublementarybus = pci_read_config(dev, 0x41, 1); + if (sublementarybus != 0xff) { + pci_set_secondarybus(dev, sublementarybus + 1); + pci_set_subordinatebus(dev, sublementarybus + 1); + } } @@ -158,7 +150,7 @@ fixbushigh_i1225(pcici_t tag) * most sense. */ static void -fixbushigh_450nx(pcici_t tag) +fixbushigh_450nx(device_t dev) { int subordinatebus; unsigned long devmap; @@ -170,7 +162,7 @@ fixbushigh_450nx(pcici_t tag) * If this doesn't find all the PCI busses, complain to the * BIOS vendor. There is nothing more we can do. */ - devmap = pci_cfgread(tag, 0xd6, 2) & 0x3c; + devmap = pci_read_config(dev, 0xd6, 2) & 0x3c; if (!devmap) panic("450NX MIOC: No host to PCI bridges marked present.\n"); /* @@ -178,13 +170,13 @@ fixbushigh_450nx(pcici_t tag) * find the highest bus, and use those numbers. */ if (devmap & 0x20) { /* B1 */ - subordinatebus = pci_cfgread(tag, 0xd5, 1); + subordinatebus = pci_read_config(dev, 0xd5, 1); } else if (devmap & 0x10) { /* A1 */ - subordinatebus = pci_cfgread(tag, 0xd4, 1); + subordinatebus = pci_read_config(dev, 0xd4, 1); } else if (devmap & 0x8) { /* B0 */ - subordinatebus = pci_cfgread(tag, 0xd2, 1); + subordinatebus = pci_read_config(dev, 0xd2, 1); } else /* if (devmap & 0x4) */ { /* A0 */ - subordinatebus = pci_cfgread(tag, 0xd1, 1); + subordinatebus = pci_read_config(dev, 0xd1, 1); } if (subordinatebus == 255) { printf("fixbushigh_450nx: bogus highest PCI bus %d", @@ -201,214 +193,44 @@ fixbushigh_450nx(pcici_t tag) printf("fixbushigh_450nx: subordinatebus is %d\n", subordinatebus); - tag->secondarybus = tag->subordinatebus = subordinatebus; + pci_set_secondarybus(dev, subordinatebus); + pci_set_subordinatebus(dev, subordinatebus); } static void -fixbushigh_Ross(pcici_t tag) +fixbushigh_Ross(device_t dev) { int secondarybus; /* just guessing the secondary bus register number ... */ - secondarybus = pci_cfgread(tag, 0x45, 1); - if (secondarybus != 0) - tag->secondarybus = tag->subordinatebus = secondarybus + 1; + secondarybus = pci_read_config(dev, 0x45, 1); + if (secondarybus != 0) { + pci_set_secondarybus(dev, secondarybus + 1); + pci_set_subordinatebus(dev, secondarybus + 1); + } } static void -fixwsc_natoma(pcici_t tag) +fixwsc_natoma(device_t dev) { int pmccfg; - pmccfg = pci_cfgread(tag, 0x50, 2); + pmccfg = pci_read_config(dev, 0x50, 2); #if defined(SMP) if (pmccfg & 0x8000) { printf("Correcting Natoma config for SMP\n"); pmccfg &= ~0x8000; - pci_cfgwrite(tag, 0x50, 2, pmccfg); + pci_write_config(dev, 0x50, 2, pmccfg); } #else if ((pmccfg & 0x8000) == 0) { printf("Correcting Natoma config for non-SMP\n"); pmccfg |= 0x8000; - pci_cfgwrite(tag, 0x50, 2, pmccfg); + pci_write_config(dev, 0x50, 2, pmccfg); } #endif } - -static const char* -chipset_probe (pcici_t tag, pcidi_t type) -{ - unsigned rev; - char *descr; - - switch (type) { - case 0x00088086: - /* Silently ignore this one! What is it, anyway ??? */ - return (""); - case 0x04868086: - return ("Intel 82425EX PCI system controller"); - case 0x04848086: - rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff; - if (rev == 3) - return ("Intel 82378ZB PCI to ISA bridge"); - return ("Intel 82378IB PCI to ISA bridge"); - case 0x04838086: - return ("Intel 82424ZX (Saturn) cache DRAM controller"); - case 0x04828086: - return ("Intel 82375EB PCI-EISA bridge"); - case 0x04a38086: - rev = (unsigned) pci_conf_read (tag, PCI_CLASS_REG) & 0xff; - if (rev == 16 || rev == 17) - return ("Intel 82434NX (Neptune) PCI cache memory controller"); - return ("Intel 82434LX (Mercury) PCI cache memory controller"); - case 0x12258086: - fixbushigh_i1225(tag); - return ("Intel 824?? host to PCI bridge"); - case 0x122d8086: - return ("Intel 82437FX PCI cache memory controller"); - case 0x122e8086: - return ("Intel 82371FB PCI to ISA bridge"); - case 0x12348086: - return ("Intel 82371MX mobile PCI I/O IDE accelerator (MPIIX)"); - case 0x12358086: - return ("Intel 82437MX mobile PCI cache memory controller"); - case 0x12508086: - return ("Intel 82439"); - case 0x70008086: - return ("Intel 82371SB PCI to ISA bridge"); - case 0x70308086: - return ("Intel 82437VX PCI cache memory controller"); - case 0x71008086: - return ("Intel 82439TX System Controller (MTXC)"); - case 0x71108086: - return ("Intel 82371AB PCI to ISA bridge"); - case 0x71138086: -#if NINTPM > 0 - return NULL; /* Need to stop generic_pci_bridge() */ -#else - return ("Intel 82371AB Power management controller"); -#endif - case 0x71908086: - return ("Intel 82443BX host to PCI bridge"); - case 0x71918086: - return ("Intel 82443BX host to AGP bridge"); - case 0x71928086: - return ("Intel 82443BX host to PCI bridge (AGP disabled)"); - case 0x12378086: - fixwsc_natoma(tag); - return ("Intel 82440FX (Natoma) PCI and memory controller"); - case 0x84c48086: - fixbushigh_orion(tag); - return ("Intel 82454KX/GX (Orion) host to PCI bridge"); - case 0x84c58086: - return ("Intel 82453KX/GX (Orion) PCI memory controller"); - case 0x84ca8086: - fixbushigh_450nx(tag); - return ("Intel 82451NX Memory and I/O Controller"); - case 0x84cb8086: - return ("Intel 82454NX PCI Expander Bridge"); - case 0x00221014: - return ("IBM 82351 PCI-PCI bridge"); - case 0x00011011: - return ("DEC 21050 PCI-PCI bridge"); - case 0x124b8086: - return ("Intel 82380FB mobile PCI to PCI bridge"); - /* SiS -- vendor 0x1039 */ - case 0x04961039: - return ("SiS 85c496"); - case 0x04061039: - return ("SiS 85c501"); - case 0x00081039: - return ("SiS 85c503"); - case 0x06011039: - return ("SiS 85c601"); - - /* VLSI -- vendor 0x1004 */ - case 0x00051004: - return ("VLSI 82C592 Host to PCI bridge"); - case 0x00061004: - return ("VLSI 82C593 PCI to ISA bridge"); - case 0x01011004: - return ("VLSI 82C532 Eagle II Peripheral Controller"); - case 0x01021004: - return ("VLSI 82C534 Eagle II PCI Bus bridge"); - case 0x01031004: - return ("VLSI 82C538 Eagle II PCI Docking bridge"); - case 0x01041004: - return ("VLSI 82C535 Eagle II System Controller"); - case 0x01051004: - return ("VLSI 82C147 IrDA Controller"); - - /* VIA Technologies -- vendor 0x1106 - * Note that the old Apollo Master chipset is not in here, as VIA - * does not seem to have any docs on their website for it, and I do - * not have a Master board in my posession. -LC */ - - case 0x05851106: - return("VIA 82C585 (Apollo VP1/VPX) system controller"); - case 0x05861106: /* south bridge section -- IDE is covered in ide_pci.c */ - return("VIA 82C586 PCI-ISA bridge"); - case 0x05951106: - case 0x15951106: - return("VIA 82C595 (Apollo VP2) system controller"); - case 0x05971106: - return("VIA 82C597 (Apollo VP3) system controller"); - /* XXX need info on the MVP3 -- any takers? */ - case 0x30401106: - return("VIA 82C586B ACPI interface"); - /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ - /* totally. Please let me know if anything wrong. -F */ - case 0x05981106: - return("VIA 82C598MVP (Apollo MVP3) host bridge"); - case 0x85981106: - return("VIA 82C598MVP (Apollo MVP3) PCI-PCI bridge"); - - /* AcerLabs -- vendor 0x10b9 */ - /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ - /* id is '10b9" but the register always shows "10b9". -Foxfair */ - case 0x154110b9: - return("AcerLabs M1541 (Aladdin-V) PCI host bridge"); - case 0x153310b9: - return("AcerLabs M1533 portable PCI-ISA bridge"); - case 0x154310b9: - return("AcerLabs M1543 desktop PCI-ISA bridge"); - case 0x524710b9: - return("AcerLabs M5247 PCI-PCI(AGP Supported) bridge"); - case 0x524310b9:/* 5243 seems like 5247, need more info to divide*/ - return("AcerLabs M5243 PCI-PCI bridge"); - case 0x710110b9: -#if NALPM > 0 - return NULL; /* Need to stop generic_pci_bridge() */ -#else - return("AcerLabs M15x3 Power Management Unit"); -#endif - - /* NEC -- vendor 0x1033 */ - case 0x00011033: - return ("NEC 0001 PCI to PC-98 C-bus bridge"); - case 0x00021033: - return ("NEC 0002 PCI to PC-98 local bus bridge"); - case 0x00161033: - return ("NEC 0016 PCI to PC-98 local bus bridge"); - case 0x002c1033: - return ("NEC 002C PCI to PC-98 C-bus bridge"); - case 0x003b1033: - return ("NEC 003B PCI to PC-98 C-bus bridge"); - - /* Ross (?) -- vendor 0x1166 */ - case 0x00051166: - fixbushigh_Ross(tag); - return ("Ross (?) host to PCI bridge"); - }; - - if ((descr = generic_pci_bridge(tag)) != NULL) - return descr; - - return NULL; -} - #ifndef PCI_QUIET #define M_XX 0 /* end of list */ @@ -848,17 +670,8 @@ static const struct condmsg conf82371fb2[] = { 0 } }; -static char confread (pcici_t config_id, int port) -{ - unsigned long portw = port & ~3; - unsigned long ports = (port - portw) << 3; - - unsigned long l = pci_conf_read (config_id, portw); - return (l >> ports); -} - static void -writeconfig (pcici_t config_id, const struct condmsg *tbl) +writeconfig (device_t dev, const struct condmsg *tbl) { while (tbl->flags != M_XX) { const char *text = 0; @@ -866,7 +679,7 @@ writeconfig (pcici_t config_id, const struct condmsg *tbl) if (tbl->flags == M_TR) { text = tbl->text; } else { - unsigned char v = (unsigned char) confread(config_id, tbl->port); + unsigned char v = pci_read_config(dev, tbl->port, 1); switch (tbl->flags) { case M_EQ: if ((v & tbl->mask) == tbl->value) text = tbl->text; @@ -888,14 +701,14 @@ writeconfig (pcici_t config_id, const struct condmsg *tbl) #ifdef DUMPCONFIGSPACE static void -dumpconfigspace (pcici_t tag) +dumpconfigspace (device_t dev) { int reg; printf ("configuration space registers:"); for (reg = 0; reg < 0x100; reg+=4) { if ((reg & 0x0f) == 0) printf ("\n%02x:\t", reg); - printf ("%08x ", pci_conf_read (tag, reg)); + printf ("%08x ", pci_read_config(dev, reg, 4)); } printf ("\n"); } @@ -904,49 +717,448 @@ dumpconfigspace (pcici_t tag) #endif /* PCI_QUIET */ static void -chipset_attach (pcici_t config_id, int unit) +chipset_attach (device_t dev, int unit) { #ifndef PCI_QUIET if (!bootverbose) return; - switch (pci_conf_read (config_id, PCI_ID_REG)) { + switch (pci_get_devid(dev)) { case 0x04868086: - writeconfig (config_id, conf82425ex); + writeconfig (dev, conf82425ex); break; case 0x04838086: - writeconfig (config_id, conf82424zx); + writeconfig (dev, conf82424zx); break; case 0x04a38086: - writeconfig (config_id, conf82434lx); + writeconfig (dev, conf82434lx); break; case 0x04848086: - writeconfig (config_id, conf82378); + writeconfig (dev, conf82378); break; case 0x122d8086: - writeconfig (config_id, conf82437fx); + writeconfig (dev, conf82437fx); break; case 0x70308086: - writeconfig (config_id, conf82437vx); + writeconfig (dev, conf82437vx); break; case 0x70008086: case 0x122e8086: - writeconfig (config_id, conf82371fb); + writeconfig (dev, conf82371fb); break; case 0x70108086: case 0x12308086: - writeconfig (config_id, conf82371fb2); + writeconfig (dev, conf82371fb2); break; #if 0 case 0x00011011: /* DEC 21050 */ case 0x00221014: /* IBM xxx */ - writeconfig (config_id, conf_pci2pci); + writeconfig (dev, conf_pci2pci); break; #endif }; #endif /* PCI_QUIET */ } +static const char * +pci_bridge_type(device_t dev) +{ + char *descr, tmpbuf[120]; + + if (pci_get_class(dev) != PCIC_BRIDGE) + return NULL; + + switch (pci_get_subclass(dev)) { + case PCIS_BRIDGE_HOST: strcpy(tmpbuf, "Host to PCI"); break; + case PCIS_BRIDGE_ISA: strcpy(tmpbuf, "PCI to ISA"); break; + case PCIS_BRIDGE_EISA: strcpy(tmpbuf, "PCI to EISA"); break; + case PCIS_BRIDGE_MCA: strcpy(tmpbuf, "PCI to MCA"); break; + case PCIS_BRIDGE_PCI: strcpy(tmpbuf, "PCI to PCI"); break; + case PCIS_BRIDGE_PCMCIA: strcpy(tmpbuf, "PCI to PCMCIA"); break; + case PCIS_BRIDGE_NUBUS: strcpy(tmpbuf, "PCI to NUBUS"); break; + case PCIS_BRIDGE_CARDBUS: strcpy(tmpbuf, "PCI to CardBus"); break; + default: + snprintf(tmpbuf, sizeof(tmpbuf), + "PCI to 0x%x", pci_get_subclass(dev)); + break; + } + snprintf(tmpbuf+strlen(tmpbuf), sizeof(tmpbuf)-strlen(tmpbuf), + " bridge (vendor=%04x device=%04x)", + pci_get_vendor(dev), pci_get_device(dev)); + descr = malloc (strlen(tmpbuf) +1, M_DEVBUF, M_WAITOK); + strcpy(descr, tmpbuf); + return descr; +} + +static const char* +pcib_match(device_t dev) +{ + switch (pci_get_devid(dev)) { + case 0x84cb8086: + return ("Intel 82454NX PCI Expander Bridge"); + case 0x00221014: + return ("IBM 82351 PCI-PCI bridge"); + case 0x00011011: + return ("DEC 21050 PCI-PCI bridge"); + case 0x124b8086: + return ("Intel 82380FB mobile PCI to PCI bridge"); + + /* VLSI -- vendor 0x1004 */ + case 0x01021004: + return ("VLSI 82C534 Eagle II PCI Bus bridge"); + case 0x01031004: + return ("VLSI 82C538 Eagle II PCI Docking bridge"); + + /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ + /* totally. Please let me know if anything wrong. -F */ + case 0x85981106: + return("VIA 82C598MVP (Apollo MVP3) PCI-PCI bridge"); + + /* AcerLabs -- vendor 0x10b9 */ + /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ + /* id is '10b9" but the register always shows "10b9". -Foxfair */ + case 0x524710b9: + return("AcerLabs M5247 PCI-PCI(AGP Supported) bridge"); + case 0x524310b9:/* 5243 seems like 5247, need more info to divide*/ + return("AcerLabs M5243 PCI-PCI bridge"); + + }; + + if (pci_get_class(dev) == PCIC_BRIDGE + && pci_get_subclass(dev) == PCIS_BRIDGE_PCI) + return pci_bridge_type(dev); + + return NULL; +} + +static int pcib_probe(device_t dev) +{ + const char *desc; + + desc = pcib_match(dev); + if (desc) { + device_set_desc_copy(dev, desc); + return 0; + } + + return ENXIO; +} + +static int pcib_attach(device_t dev) +{ + struct pci_devinfo *dinfo; + pcicfgregs *cfg; + + dinfo = device_get_ivars(dev); + cfg = &dinfo->cfg; + + chipset_attach(dev, device_get_unit(dev)); + + if (cfg->secondarybus) { + device_add_child(dev, "pci", cfg->secondarybus, 0); + return bus_generic_attach(dev); + } else + return 0; +} + +static device_method_t pcib_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, pcib_probe), + DEVMETHOD(device_attach, pcib_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t pcib_driver = { + "pcib", + pcib_methods, + DRIVER_TYPE_MISC, + 1, +}; + +static devclass_t pcib_devclass; + +DRIVER_MODULE(pcib, pci, pcib_driver, pcib_devclass, 0, 0); + +static const char * +isab_match(device_t dev) +{ + unsigned rev; + + switch (pci_get_devid(dev)) { + case 0x04848086: + rev = pci_get_revid(dev); + if (rev == 3) + return ("Intel 82378ZB PCI to ISA bridge"); + return ("Intel 82378IB PCI to ISA bridge"); + case 0x04828086: + return ("Intel 82375EB PCI-EISA bridge"); + case 0x122e8086: + return ("Intel 82371FB PCI to ISA bridge"); + case 0x70008086: + return ("Intel 82371SB PCI to ISA bridge"); + case 0x71108086: + return ("Intel 82371AB PCI to ISA bridge"); + + /* VLSI -- vendor 0x1004 */ + case 0x00061004: + return ("VLSI 82C593 PCI to ISA bridge"); + + /* VIA Technologies -- vendor 0x1106 + * Note that the old Apollo Master chipset is not in here, as VIA + * does not seem to have any docs on their website for it, and I do + * not have a Master board in my posession. -LC */ + + case 0x05861106: /* south bridge section -- IDE is covered in ide_pci.c */ + return("VIA 82C586 PCI-ISA bridge"); + + /* AcerLabs -- vendor 0x10b9 */ + /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ + /* id is '10b9" but the register always shows "10b9". -Foxfair */ + case 0x153310b9: + return("AcerLabs M1533 portable PCI-ISA bridge"); + case 0x154310b9: + return("AcerLabs M1543 desktop PCI-ISA bridge"); + } + + if (pci_get_class(dev) == PCIC_BRIDGE + && (pci_get_subclass(dev) == PCIS_BRIDGE_ISA + || pci_get_subclass(dev) == PCIS_BRIDGE_EISA)) + return pci_bridge_type(dev); + + return NULL; +} + +static int +isab_probe(device_t dev) +{ + const char *desc; + + desc = isab_match(dev); + if (desc) { + device_set_desc_copy(dev, desc); + /* Don't bother adding more than one ISA bus */ + if (!devclass_get_device(devclass_find("isa"), 0)) + device_add_child(dev, "isa", -1, 0); + return 0; + } + + return ENXIO; +} + +static device_method_t isab_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, isab_probe), + DEVMETHOD(device_attach, bus_generic_attach), + DEVMETHOD(device_shutdown, bus_generic_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t isab_driver = { + "isab", + isab_methods, + DRIVER_TYPE_MISC, + 1, +}; + +static devclass_t isab_devclass; + +DRIVER_MODULE(isab, pci, isab_driver, isab_devclass, 0, 0); + +static const char* +chip_match(device_t dev) +{ + unsigned rev; + + switch (pci_get_devid(dev)) { + case 0x00088086: + /* Silently ignore this one! What is it, anyway ??? */ + return (""); + case 0x71108086: + /* + * On my laptop (Tecra 8000DVD), this device has a + * bogus subclass 0x80 so make sure that it doesn't + * match the generic 'chip' driver by accident. + */ + return NULL; + case 0x12258086: + fixbushigh_i1225(dev); + return ("Intel 824?? host to PCI bridge"); + case 0x71908086: + return ("Intel 82443BX host to PCI bridge"); + case 0x71918086: + return ("Intel 82443BX host to AGP bridge"); + case 0x71928086: + return ("Intel 82443BX host to PCI bridge (AGP disabled)"); + case 0x84c48086: + fixbushigh_orion(dev); + return ("Intel 82454KX/GX (Orion) host to PCI bridge"); + case 0x84ca8086: + fixbushigh_450nx(dev); + return ("Intel 82451NX Memory and I/O Controller"); + case 0x04868086: + return ("Intel 82425EX PCI system controller"); + case 0x04838086: + return ("Intel 82424ZX (Saturn) cache DRAM controller"); + case 0x04a38086: + rev = pci_get_revid(dev); + if (rev == 16 || rev == 17) + return ("Intel 82434NX (Neptune) PCI cache memory controller"); + return ("Intel 82434LX (Mercury) PCI cache memory controller"); + case 0x122d8086: + return ("Intel 82437FX PCI cache memory controller"); + case 0x12348086: + return ("Intel 82371MX mobile PCI I/O IDE accelerator (MPIIX)"); + case 0x12358086: + return ("Intel 82437MX mobile PCI cache memory controller"); + case 0x12508086: + return ("Intel 82439"); + case 0x70308086: + return ("Intel 82437VX PCI cache memory controller"); + case 0x71008086: + return ("Intel 82439TX System Controller (MTXC)"); + + case 0x71138086: + return ("Intel 82371AB Power management controller"); + case 0x12378086: + fixwsc_natoma(dev); + return ("Intel 82440FX (Natoma) PCI and memory controller"); + case 0x84c58086: + return ("Intel 82453KX/GX (Orion) PCI memory controller"); + /* SiS -- vendor 0x1039 */ + case 0x04961039: + return ("SiS 85c496"); + case 0x04061039: + return ("SiS 85c501"); + case 0x00081039: + return ("SiS 85c503"); + case 0x06011039: + return ("SiS 85c601"); + + /* VLSI -- vendor 0x1004 */ + case 0x00051004: + return ("VLSI 82C592 Host to PCI bridge"); + case 0x01011004: + return ("VLSI 82C532 Eagle II Peripheral Controller"); + case 0x01041004: + return ("VLSI 82C535 Eagle II System Controller"); + case 0x01051004: + return ("VLSI 82C147 IrDA Controller"); + + /* VIA Technologies -- vendor 0x1106 + * Note that the old Apollo Master chipset is not in here, as VIA + * does not seem to have any docs on their website for it, and I do + * not have a Master board in my posession. -LC */ + + case 0x05851106: + return("VIA 82C585 (Apollo VP1/VPX) system controller"); + case 0x05951106: + case 0x15951106: + return("VIA 82C595 (Apollo VP2) system controller"); + case 0x05971106: + return("VIA 82C597 (Apollo VP3) system controller"); + /* XXX Here is MVP3, I got the datasheet but NO M/B to test it */ + /* totally. Please let me know if anything wrong. -F */ + /* XXX need info on the MVP3 -- any takers? */ + case 0x05981106: + return("VIA 82C598MVP (Apollo MVP3) host bridge"); + case 0x30401106: + return("VIA 82C586B ACPI interface"); +#if 0 + /* XXX New info added-in */ + case 0x05711106: + return("VIA 82C586B IDE controller"); + case 0x30381106: + return("VIA 82C586B USB controller"); +#endif + + /* NEC -- vendor 0x1033 */ + case 0x00011033: + return ("NEC 0001 PCI to PC-98 C-bus bridge"); + case 0x00021033: + return ("NEC 0002 PCI to PC-98 local bus bridge"); + case 0x00161033: + return ("NEC 0016 PCI to PC-98 local bus bridge"); + case 0x002c1033: + return ("NEC 002C PCI to PC-98 C-bus bridge"); + case 0x003b1033: + return ("NEC 003B PCI to PC-98 C-bus bridge"); + + /* AcerLabs -- vendor 0x10b9 */ + /* Funny : The datasheet told me vendor id is "10b8",sub-vendor */ + /* id is '10b9" but the register always shows "10b9". -Foxfair */ + case 0x154110b9: + return("AcerLabs M1541 (Aladdin-V) PCI host bridge"); + }; + + if (pci_get_class(dev) == PCIC_BRIDGE + && pci_get_subclass(dev) != PCIS_BRIDGE_PCI + && pci_get_subclass(dev) != PCIS_BRIDGE_ISA + && pci_get_subclass(dev) != PCIS_BRIDGE_EISA) + return pci_bridge_type(dev); + + return NULL; +} + +static int chip_probe(device_t dev) +{ + const char *desc; + + desc = chip_match(dev); + if (desc) { + device_set_desc_copy(dev, desc); + return 0; + } + + return ENXIO; +} + +static int chip_attach(device_t dev) +{ + chipset_attach(dev, device_get_unit(dev)); + + return 0; +} + +static device_method_t chip_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, chip_probe), + DEVMETHOD(device_attach, chip_attach), + + { 0, 0 } +}; + +static driver_t chip_driver = { + "chip", + chip_methods, + DRIVER_TYPE_MISC, + 1, +}; + +static devclass_t chip_devclass; + +DRIVER_MODULE(chip, pci, chip_driver, chip_devclass, 0, 0); + /*--------------------------------------------------------- ** ** Catchall driver for VGA devices @@ -957,29 +1169,16 @@ chipset_attach (pcici_t config_id, int unit) **--------------------------------------------------------- */ -static const char* vga_probe (pcici_t tag, pcidi_t type); -static void vga_attach (pcici_t tag, int unit); -static u_long vga_count; - -static struct pci_device vga_device = { - "vga", - vga_probe, - vga_attach, - &vga_count, - NULL -}; - -DATA_SET (pcidevice_set, vga_device); - -static const char* vga_probe (pcici_t tag, pcidi_t typea) +static const char* vga_match(device_t dev) { - int data = pci_conf_read(tag, PCI_CLASS_REG); - u_int id = pci_conf_read(tag, PCI_ID_REG); + /* int data = pci_conf_read(tag, PCI_CLASS_REG); */ + u_int id = pci_get_devid(dev); const char *vendor, *chip, *type; - vendor = chip = type = 0; + return 0; /* XXX interferes with syscons */ - switch (id & 0xffff) { + vendor = chip = type = 0; + switch (id) { case 0x10c8: vendor = "NeoMagic"; switch (id >> 16) { @@ -1209,20 +1408,18 @@ static const char* vga_probe (pcici_t tag, pcidi_t typea) return buf; } - switch (data & PCI_CLASS_MASK) { + switch (pci_get_class(dev)) { - case PCI_CLASS_PREHISTORIC: - if ((data & PCI_SUBCLASS_MASK) - != PCI_SUBCLASS_PREHISTORIC_VGA) + case PCIC_OLD: + if (pci_get_subclass(dev) != PCIS_OLD_VGA) return 0; if (type == 0) type = "VGA-compatible display device"; break; - case PCI_CLASS_DISPLAY: + case PCIC_DISPLAY: if (type == 0) { - if ((data & PCI_SUBCLASS_MASK) - == PCI_SUBCLASS_DISPLAY_VGA) + if (pci_get_subclass(dev) != PCIS_DISPLAY_VGA) type = "VGA-compatible display device"; else { /* @@ -1260,7 +1457,20 @@ static const char* vga_probe (pcici_t tag, pcidi_t typea) return type; } -static void vga_attach (pcici_t tag, int unit) +static int vga_probe(device_t dev) +{ + const char *desc; + + desc = vga_match(dev); + if (desc) { + device_set_desc(dev, desc); + return 0; + } + + return ENXIO; +} + +static int vga_attach(device_t dev) { /* ** If the assigned addresses are remapped, @@ -1273,42 +1483,27 @@ static void vga_attach (pcici_t tag, int unit) for (reg = PCI_MAP_REG_START; reg < PCI_MAP_REG_END; reg += 4) (void) pci_map_mem (tag, reg, &va, &pa); #endif + return 0; } -/*--------------------------------------------------------- -** -** Hook for loadable pci drivers -** -**--------------------------------------------------------- -*/ - -static const char* lkm_probe (pcici_t tag, pcidi_t type); -static void lkm_attach (pcici_t tag, int unit); -static u_long lkm_count; +static device_method_t vga_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, vga_probe), + DEVMETHOD(device_attach, vga_attach), -static struct pci_device lkm_device = { - "lkm", - lkm_probe, - lkm_attach, - &lkm_count, - NULL + { 0, 0 } }; -DATA_SET (pcidevice_set, lkm_device); +static driver_t vga_driver = { + "vga", + vga_methods, + DRIVER_TYPE_MISC, + 1, +}; -static const char* -lkm_probe (pcici_t tag, pcidi_t type) -{ - /* - ** Not yet! - ** (Should try to load a matching driver) - */ - return ((char*)0); -} +static devclass_t vga_devclass; -static void -lkm_attach (pcici_t tag, int unit) -{} +DRIVER_MODULE(vga, pci, vga_driver, vga_devclass, 0, 0); /*--------------------------------------------------------- ** @@ -1317,32 +1512,39 @@ lkm_attach (pcici_t tag, int unit) **--------------------------------------------------------- */ -static const char* ign_probe (pcici_t tag, pcidi_t type); -static void ign_attach (pcici_t tag, int unit); -static u_long ign_count; - -static struct pci_device ign_device = { - NULL, - ign_probe, - ign_attach, - &ign_count, - NULL -}; - -DATA_SET (pcidevice_set, ign_device); - -static const char* -ign_probe (pcici_t tag, pcidi_t type) +static int +ign_probe (device_t dev) { - switch (type) { + switch (pci_get_devid(dev)) { case 0x10001042ul: /* wd */ - return (""); + return 0; /* return ("SMC FDC 37c665");*/ }; - return ((char*)0); + return ENXIO; } -static void -ign_attach (pcici_t tag, int unit) -{} +static int +ign_attach (device_t dev) +{ + return 0; +} + +static device_method_t ign_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, ign_probe), + DEVMETHOD(device_attach, ign_attach), + + { 0, 0 } +}; + +static driver_t ign_driver = { + "ign", + ign_methods, + DRIVER_TYPE_MISC, + 1, +}; + +static devclass_t ign_devclass; + +DRIVER_MODULE(ign, pci, ign_driver, ign_devclass, 0, 0); diff --git a/sys/pci/pcivar.h b/sys/pci/pcivar.h index 7843e3a..55f72a1 100644 --- a/sys/pci/pcivar.h +++ b/sys/pci/pcivar.h @@ -23,7 +23,7 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * - * $Id: pcivar.h,v 1.24 1999/01/13 04:59:19 bde Exp $ + * $Id: pcivar.h,v 1.25 1999/01/19 23:29:20 se Exp $ * */ @@ -67,13 +67,17 @@ typedef struct { u_int8_t ln2size; u_int8_t ln2range; u_int8_t reg; /* offset of map register in config space */ +/* u_int8_t dummy;*/ + struct resource *res; /* handle from resource manager */ } pcimap; /* config header information common to all header types */ typedef struct pcicfg { + struct device *dev; /* device which owns this */ pcimap *map; /* pointer to array of PCI maps */ void *hdrspec; /* pointer to header type specific data */ + struct resource *irqres; /* resource descriptor for interrupt mapping */ u_int16_t subvendor; /* card vendor ID */ u_int16_t subdevice; /* card device ID, assigned by card vendor */ @@ -182,6 +186,79 @@ void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes); vm_offset_t pci_cvt_to_dense (vm_offset_t); vm_offset_t pci_cvt_to_bwx (vm_offset_t); #endif /* __alpha__ */ + +#ifdef _SYS_BUS_H_ + +#include "pci_if.h" + +enum pci_device_ivars { + PCI_IVAR_SUBVENDOR, + PCI_IVAR_SUBDEVICE, + PCI_IVAR_VENDOR, + PCI_IVAR_DEVICE, + PCI_IVAR_DEVID, + PCI_IVAR_CLASS, + PCI_IVAR_SUBCLASS, + PCI_IVAR_PROGIF, + PCI_IVAR_REVID, + PCI_IVAR_INTPIN, + PCI_IVAR_IRQ, + PCI_IVAR_BUS, + PCI_IVAR_SLOT, + PCI_IVAR_FUNCTION, + PCI_IVAR_SECONDARYBUS, + PCI_IVAR_SUBORDINATEBUS, +}; + +/* + * Simplified accessors for pci devices + */ +#define PCI_ACCESSOR(A, B, T) \ + \ +static __inline T pci_get_ ## A(device_t dev) \ +{ \ + uintptr_t v; \ + BUS_READ_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, &v); \ + return (T) v; \ +} \ + \ +static __inline void pci_set_ ## A(device_t dev, T t) \ +{ \ + u_long v = (u_long) t; \ + BUS_WRITE_IVAR(device_get_parent(dev), dev, PCI_IVAR_ ## B, v); \ +} + +PCI_ACCESSOR(subvendor, SUBVENDOR, u_int16_t) +PCI_ACCESSOR(subdevice, SUBDEVICE, u_int16_t) +PCI_ACCESSOR(vendor, VENDOR, u_int16_t) +PCI_ACCESSOR(device, DEVICE, u_int16_t) +PCI_ACCESSOR(devid, DEVID, u_int32_t) +PCI_ACCESSOR(class, CLASS, u_int8_t) +PCI_ACCESSOR(subclass, SUBCLASS, u_int8_t) +PCI_ACCESSOR(progif, PROGIF, u_int8_t) +PCI_ACCESSOR(revid, REVID, u_int8_t) +PCI_ACCESSOR(intpin, INTPIN, u_int8_t) +PCI_ACCESSOR(irq, IRQ, u_int8_t) +PCI_ACCESSOR(bus, BUS, u_int8_t) +PCI_ACCESSOR(slot, SLOT, u_int8_t) +PCI_ACCESSOR(function, FUNCTION, u_int8_t) +PCI_ACCESSOR(secondarybus, SECONDARYBUS, u_int8_t) +PCI_ACCESSOR(subordinatebus, SUBORDINATEBUS, u_int8_t) + +static __inline u_int32_t +pci_read_config(device_t dev, int reg, int width) +{ + return PCI_READ_CONFIG(device_get_parent(dev), dev, reg, width); +} + +static __inline void +pci_write_config(device_t dev, int reg, u_int32_t val, int width) +{ + PCI_WRITE_CONFIG(device_get_parent(dev), dev, reg, val, width); +} + +#endif + /* for compatibility to FreeBSD-2.2 version of PCI code */ #ifdef PCI_COMPAT diff --git a/sys/pci/uhci_pci.c b/sys/pci/uhci_pci.c index 6ed3cee..4bddf8b 100644 --- a/sys/pci/uhci_pci.c +++ b/sys/pci/uhci_pci.c @@ -1,4 +1,4 @@ -/* FreeBSD $Id: uhci_pci.c,v 1.4 1999/04/06 23:09:58 n_hibma Exp $ */ +/* FreeBSD $Id: uhci_pci.c,v 1.5 1999/04/11 14:24:20 n_hibma Exp $ */ /* * Copyright (c) 1998 The NetBSD Foundation, Inc. @@ -37,6 +37,8 @@ * POSSIBILITY OF SUCH DAMAGE. */ +#include "opt_bus.h" + #include <sys/param.h> #include <sys/systm.h> #include <sys/kernel.h> @@ -45,23 +47,13 @@ #include <sys/device.h> #include <sys/proc.h> #include <sys/queue.h> +#include <machine/bus.h> +#include <sys/rman.h> +#include <machine/resource.h> #include <pci/pcivar.h> #include <pci/pcireg.h> -#define PCI_CLASS_SERIALBUS 0x0c000000 -#define PCI_SUBCLASS_COMMUNICATIONS_SERIAL 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_FIREWIRE 0x00000000 -#define PCI_SUBCLASS_SERIALBUS_ACCESS 0x00010000 -#define PCI_SUBCLASS_SERIALBUS_SSA 0x00020000 -#define PCI_SUBCLASS_SERIALBUS_USB 0x00030000 -#define PCI_SUBCLASS_SERIALBUS_FIBER 0x00040000 - -#define PCI_INTERFACE(d) (((d)>>8)&0xff) -#define PCI_SUBCLASS(d) ((d)&PCI_SUBCLASS_MASK) -#define PCI_CLASS(d) ((d)&PCI_CLASS_MASK) - - #include <dev/usb/usb.h> #include <dev/usb/usbdi.h> #include <dev/usb/usbdivar.h> @@ -70,7 +62,6 @@ #include <dev/usb/uhcireg.h> #include <dev/usb/uhcivar.h> - #define PCI_UHCI_VENDORID_INTEL 0x8086 #define PCI_UHCI_VENDORID_VIA 0x1106 @@ -85,26 +76,10 @@ static const char *uhci_device_generic = "UHCI (generic) USB Controller"; #define PCI_UHCI_BASE_REG 0x20 -static const char *uhci_pci_probe __P((pcici_t, pcidi_t)); -static void uhci_pci_attach __P((pcici_t, int)); - -static u_long uhci_count = 0; - -static struct pci_device uhci_pci_device = { - "uhci", - uhci_pci_probe, - uhci_pci_attach, - &uhci_count, - NULL -}; - -DATA_SET(pcidevice_set, uhci_pci_device); - - static const char * -uhci_pci_probe(pcici_t config_id, pcidi_t device_id) +uhci_pci_match(device_t dev) { - u_int32_t class; + u_int32_t device_id = pci_get_devid(dev); if (device_id == PCI_UHCI_DEVICEID_PIIX3) { return (uhci_device_piix3); @@ -113,10 +88,9 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id) } else if (device_id == PCI_UHCI_DEVICEID_VT83C572) { return (uhci_device_vt83c572); } else { - class = pci_conf_read(config_id, PCI_CLASS_REG); - if ( PCI_CLASS(class) == PCI_CLASS_SERIALBUS - && PCI_SUBCLASS(class) == PCI_SUBCLASS_SERIALBUS_USB - && PCI_INTERFACE(class) == PCI_INTERFACE_UHCI) { + if ( pci_get_class(dev) == PCIC_SERIALBUS + && pci_get_subclass(dev) == PCIS_SERIALBUS_USB + && pci_get_progif(dev) == PCI_INTERFACE_UHCI) { return (uhci_device_generic); } } @@ -124,42 +98,64 @@ uhci_pci_probe(pcici_t config_id, pcidi_t device_id) return NULL; /* dunno... */ } -static void -uhci_pci_attach(pcici_t config_id, int unit) +static int +uhci_pci_probe(device_t dev) +{ + const char *desc = uhci_pci_match(dev); + if (desc) { + device_set_desc(dev, desc); + return 0; + } else { + return ENXIO; + } +} + +static int +uhci_pci_attach(device_t dev) { - int id, legsup; + int unit = device_get_unit(dev); + int legsup; char *typestr; usbd_status err; - uhci_softc_t *sc = NULL; device_t usbus; - - sc = malloc(sizeof(uhci_softc_t), M_DEVBUF, M_NOWAIT); - /* Do not free it below, intr might use the sc */ - if ( sc == NULL ) { - printf("uhci%d: could not allocate memory", unit); - return; + uhci_softc_t *sc = device_get_softc(dev); + int rid; + struct resource *res; + void *ih; + int error; + + rid = PCI_UHCI_BASE_REG; + res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid, + 0, ~0, 1, RF_ACTIVE); + if (!res) { + device_printf(dev, "could not map ports\n"); + return ENXIO; + } + + sc->iot = rman_get_bustag(res); + sc->ioh = rman_get_bushandle(res); + + rid = 0; + res = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + if (res == NULL) { + device_printf(dev, "could not allocate irq\n"); + return ENOMEM; } - memset(sc, 0, sizeof(uhci_softc_t)); - - if ( !pci_map_port(config_id, PCI_UHCI_BASE_REG, &sc->sc_iobase) ) { - printf("uhci%d: could not map port\n", unit); - return; - } - - if ( !pci_map_int(config_id, (pci_inthand_t *)uhci_intr, - (void *) sc, &bio_imask)) { - printf("uhci%d: could not map irq\n", unit); - return; + + error = bus_setup_intr(dev, res, (driver_intr_t *) uhci_intr, sc, &ih); + if (error) { + device_printf(dev, "could not setup irq\n"); + return error; } - usbus = device_add_child(root_bus, "usb", -1, sc); + usbus = device_add_child(dev, "usb", -1, sc); if (!usbus) { - printf("usb%d: could not add USB device to root bus\n", unit); - return; + printf("usb%d: could not add USB device\n", unit); + return ENOMEM; } - id = pci_conf_read(config_id, PCI_ID_REG); - switch (id) { + switch (pci_get_devid(dev)) { case PCI_UHCI_DEVICEID_PIIX3: device_set_desc(usbus, uhci_device_piix3); sprintf(sc->sc_vendor, "Intel"); @@ -173,13 +169,13 @@ uhci_pci_attach(pcici_t config_id, int unit) sprintf(sc->sc_vendor, "VIA"); break; default: - printf("(New UHCI DeviceId=0x%08x)\n", id); + printf("(New UHCI DeviceId=0x%08x)\n", pci_get_devid(dev)); device_set_desc(usbus, uhci_device_generic); - sprintf(sc->sc_vendor, "(0x%08x)", id); + sprintf(sc->sc_vendor, "(0x%08x)", pci_get_devid(dev)); } if (bootverbose) { - switch(pci_conf_read(config_id, PCI_USBREV) & PCI_USBREV_MASK) { + switch(pci_read_config(dev, PCI_USBREV, 4) & PCI_USBREV_MASK) { case PCI_USBREV_PRE_1_0: typestr = "pre 1.0"; break; @@ -191,25 +187,53 @@ uhci_pci_attach(pcici_t config_id, int unit) break; } printf("uhci%d: USB version %s, chip rev. %d\n", unit, typestr, - (int) pci_conf_read(config_id, PCIR_REVID) & 0xff); + pci_get_revid(dev)); } - legsup = pci_conf_read(config_id, PCI_LEGSUP); + legsup = pci_read_config(dev, PCI_LEGSUP, 4); if ( !(legsup & PCI_LEGSUP_USBPIRQDEN) ) { #if ! (defined(USBVERBOSE) || defined(USB_DEBUG)) if (bootverbose) #endif printf("uhci%d: PIRQD enable not set\n", unit); legsup |= PCI_LEGSUP_USBPIRQDEN; - pci_conf_write(config_id, PCI_LEGSUP, legsup); + pci_write_config(dev, PCI_LEGSUP, legsup, 4); } sc->sc_bus.bdev = usbus; err = uhci_init(sc); if (err != USBD_NORMAL_COMPLETION) { printf("uhci%d: init failed, error=%d\n", unit, err); - device_delete_child(root_bus, usbus); + device_delete_child(dev, usbus); } - return; + return device_probe_and_attach(sc->sc_bus.bdev); } + +static device_method_t uhci_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, uhci_pci_probe), + DEVMETHOD(device_attach, uhci_pci_attach), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), + DEVMETHOD(bus_release_resource, bus_generic_release_resource), + DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), + DEVMETHOD(bus_deactivate_resource, bus_generic_deactivate_resource), + DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), + DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + + { 0, 0 } +}; + +static driver_t uhci_driver = { + "uhci", + uhci_methods, + DRIVER_TYPE_BIO, + sizeof(uhci_softc_t), +}; + +static devclass_t uhci_devclass; + +DRIVER_MODULE(uhci, pci, uhci_driver, uhci_devclass, 0, 0); diff --git a/sys/sys/bus.h b/sys/sys/bus.h index 3c7f9de..9095d7e 100644 --- a/sys/sys/bus.h +++ b/sys/sys/bus.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bus.h,v 1.9 1999/03/06 16:52:04 bde Exp $ + * $Id: bus.h,v 1.10 1999/03/29 08:54:19 dfr Exp $ */ #ifndef _SYS_BUS_H_ @@ -75,6 +75,7 @@ struct driver { size_t softc; /* size of device softc struct */ void *priv; /* driver private data */ device_ops_t ops; /* compiled method table */ + int refs; /* # devclasses containing driver */ }; typedef enum device_state { @@ -106,6 +107,7 @@ int bus_generic_attach(device_t dev); int bus_generic_deactivate_resource(device_t dev, device_t child, int type, int rid, struct resource *r); int bus_generic_detach(device_t dev); +void bus_generic_driver_added(device_t dev, driver_t *driver); void bus_generic_print_child(device_t dev, device_t child); int bus_generic_read_ivar(device_t dev, device_t child, int which, uintptr_t *result); @@ -195,6 +197,7 @@ int devclass_get_maxunit(devclass_t dc); /* * Access functions for device resources. */ + int resource_int_value(const char *name, int unit, char *resname, int *result); int resource_long_value(const char *name, int unit, char *resname, @@ -204,6 +207,11 @@ int resource_string_value(const char *name, int unit, char *resname, int resource_query_string(int i, char *resname, char *value); char *resource_query_name(int i); int resource_query_unit(int i); +int resource_locate(int i, char *resname); +int resource_set_int(int i, char *resname, int value); +int resource_set_long(int i, char *resname, long value); +int resource_set_string(int i, char *resname, char *value); +int resource_count(void); /* * Shorthand for constructing method tables. diff --git a/sys/sys/bus_private.h b/sys/sys/bus_private.h index 8ac9944..9c138c5 100644 --- a/sys/sys/bus_private.h +++ b/sys/sys/bus_private.h @@ -23,7 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id: bus_private.h,v 1.4 1998/11/14 21:58:41 wollman Exp $ + * $Id: bus_private.h,v 1.5 1999/03/29 08:54:19 dfr Exp $ */ #ifndef _SYS_BUS_PRIVATE_H_ @@ -138,6 +138,7 @@ struct device { struct device_op_desc { unsigned int offset; /* offset in driver ops */ + struct method* method; /* internal method implementation */ const char* name; /* unique name (for registration) */ }; diff --git a/sys/sys/rman.h b/sys/sys/rman.h index 224d9ed..278e33c 100644 --- a/sys/sys/rman.h +++ b/sys/sys/rman.h @@ -26,7 +26,7 @@ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $Id$ + * $Id: rman.h,v 1.1 1998/10/29 01:48:30 wollman Exp $ */ #ifndef _SYS_RMAN_H_ @@ -51,6 +51,8 @@ struct resource { u_long r_end; /* index of the last entry (inclusive) */ u_int r_flags; void *r_virtual; /* virtual address of this resource */ + bus_space_tag_t r_bustag; /* bus_space tag */ + bus_space_handle_t r_bushandle; /* bus_space handle */ struct device *r_dev; /* device which has allocated this resource */ struct rman *r_rm; /* resource manager from whence this came */ }; @@ -88,8 +90,15 @@ struct resource *rman_reserve_resource(struct rman *rm, u_long start, u_long end, u_long count, u_int flags, struct device *dev); +#define rman_get_start(r) ((r)->r_start) +#define rman_get_end(r) ((r)->r_end) +#define rman_get_flags(r) ((r)->r_flags) #define rman_set_virtual(r,v) ((r)->r_virtual = (v)) #define rman_get_virtual(r) ((r)->r_virtual) +#define rman_set_bustag(r,t) ((r)->r_bustag = (t)) +#define rman_get_bustag(r) ((r)->r_bustag) +#define rman_set_bushandle(r,h) ((r)->r_bushandle = (h)) +#define rman_get_bushandle(r) ((r)->r_bushandle) extern struct rman_head rman_head; #endif /* KERNEL */ |