diff options
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/ide_pci.c | 5 | ||||
-rw-r--r-- | sys/pci/if_fxp.c | 186 | ||||
-rw-r--r-- | sys/pci/if_fxpvar.h | 5 | ||||
-rw-r--r-- | sys/pci/if_pn.c | 10 | ||||
-rw-r--r-- | sys/pci/if_xl.c | 12 | ||||
-rw-r--r-- | sys/pci/ohci_pci.c | 154 | ||||
-rw-r--r-- | sys/pci/pci.c | 653 | ||||
-rw-r--r-- | sys/pci/pci_compat.c | 192 | ||||
-rw-r--r-- | sys/pci/pci_if.m | 44 | ||||
-rw-r--r-- | sys/pci/pcireg.h | 4 | ||||
-rw-r--r-- | sys/pci/pcisupport.c | 824 | ||||
-rw-r--r-- | sys/pci/pcivar.h | 79 | ||||
-rw-r--r-- | sys/pci/uhci_pci.c | 166 |
13 files changed, 1597 insertions, 737 deletions
diff --git a/sys/pci/ide_pci.c b/sys/pci/ide_pci.c index 524b873417da7..6faef01500883 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 77f0ade1d5af6..53b8d4db00c68 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 ce8d8fe9de6d7..042d2df962841 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 425195e679ef1..3209051739d36 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 d9b9e61c43830..e848418da2ccc 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 3c20ff723e05d..1aea5f1db15db 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 e449fc25e50fa..889550c9bc95a 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 f107e54608f2f..bfa1d59a3cd46 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 0000000000000..b2fa6758fef6a --- /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 0adb5404021e2..9c0dba09331d2 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 b292c92d8d1a3..1fe5f1e2ed31e 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 7843e3a6d656b..55f72a16b875f 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 6ed3cee0381f1..4bddf8b327869 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); |