diff options
author | dfr <dfr@FreeBSD.org> | 2000-08-28 21:48:13 +0000 |
---|---|---|
committer | dfr <dfr@FreeBSD.org> | 2000-08-28 21:48:13 +0000 |
commit | dd8b44b3958fa67d802cbbec7c7d82f7fb476229 (patch) | |
tree | 61496c144b3ecd15192a2e07e755754e18346bc9 /sys/pci | |
parent | 9ed8ded4d312c58a27de9402fd9802e78a591cb9 (diff) | |
download | FreeBSD-src-dd8b44b3958fa67d802cbbec7c7d82f7fb476229.zip FreeBSD-src-dd8b44b3958fa67d802cbbec7c7d82f7fb476229.tar.gz |
* Completely rewrite the alpha busspace to hide the implementation from
the drivers.
* Remove legacy inx/outx support from chipset and replace with macros
which call busspace.
* Rework pci config accesses to route through the pcib device instead of
calling a MD function directly.
With these changes it is possible to cleanly support machines which have
more than one independantly numbered PCI busses. As a bonus, the new
busspace implementation should be measurably faster than the old one.
Diffstat (limited to 'sys/pci')
-rw-r--r-- | sys/pci/if_ti.c | 18 | ||||
-rw-r--r-- | sys/pci/isp_pci.c | 9 | ||||
-rw-r--r-- | sys/pci/pci.c | 351 | ||||
-rw-r--r-- | sys/pci/pci_compat.c | 12 | ||||
-rw-r--r-- | sys/pci/pcib_if.m | 71 | ||||
-rw-r--r-- | sys/pci/pcisupport.c | 65 | ||||
-rw-r--r-- | sys/pci/pcivar.h | 8 |
7 files changed, 318 insertions, 216 deletions
diff --git a/sys/pci/if_ti.c b/sys/pci/if_ti.c index 56847f4..f1cfee5 100644 --- a/sys/pci/if_ti.c +++ b/sys/pci/if_ti.c @@ -1505,7 +1505,7 @@ static int ti_attach(dev) rid = TI_PCI_LOMEM; sc->ti_res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, - 0, ~0, 1, RF_ACTIVE); + 0, ~0, 1, RF_ACTIVE|PCI_RF_DENSE); if (sc->ti_res == NULL) { printf ("ti%d: couldn't map memory\n", unit); @@ -1517,22 +1517,6 @@ static int ti_attach(dev) sc->ti_bhandle = rman_get_bushandle(sc->ti_res); sc->ti_vhandle = (vm_offset_t)rman_get_virtual(sc->ti_res); - /* - * XXX FIXME: rman_get_virtual() on the alpha is currently - * broken and returns a physical address instead of a kernel - * virtual address. Consequently, we need to do a little - * extra mangling of the vhandle on the alpha. This should - * eventually be fixed! The whole idea here is to get rid - * of platform dependencies. - */ -#ifdef __alpha__ - if (pci_cvt_to_bwx(sc->ti_vhandle)) - sc->ti_vhandle = pci_cvt_to_bwx(sc->ti_vhandle); - else - sc->ti_vhandle = pci_cvt_to_dense(sc->ti_vhandle); - sc->ti_vhandle = ALPHA_PHYS_TO_K0SEG(sc->ti_vhandle); -#endif - /* Allocate interrupt */ rid = 0; diff --git a/sys/pci/isp_pci.c b/sys/pci/isp_pci.c index 6189077..86ee964 100644 --- a/sys/pci/isp_pci.c +++ b/sys/pci/isp_pci.c @@ -216,15 +216,6 @@ static struct ispmdvec mdvec_2200 = { static int isp_pci_probe (device_t); static int isp_pci_attach (device_t); -/* This distinguishing define is not right, but it does work */ -#ifdef __alpha__ -#define IO_SPACE_MAPPING ALPHA_BUS_SPACE_IO -#define MEM_SPACE_MAPPING ALPHA_BUS_SPACE_MEM -#else -#define IO_SPACE_MAPPING I386_BUS_SPACE_IO -#define MEM_SPACE_MAPPING I386_BUS_SPACE_MEM -#endif - struct isp_pcisoftc { struct ispsoftc pci_isp; device_t pci_dev; diff --git a/sys/pci/pci.c b/sys/pci/pci.c index cfda6c7..b31667c 100644 --- a/sys/pci/pci.c +++ b/sys/pci/pci.c @@ -56,6 +56,8 @@ #include <pci/pcireg.h> #include <pci/pcivar.h> +#include "pcib_if.h" + #ifdef __alpha__ #include <machine/rpb.h> #endif @@ -64,6 +66,8 @@ #include <machine/smp.h> #endif /* APIC_IO */ +static devclass_t pci_devclass; + struct pci_quirk { u_int32_t devid; /* Vendor/device of the card */ int type; @@ -177,7 +181,7 @@ pci_fixancient(pcicfgregs *cfg) /* read config data specific to header type 1 device (PCI to PCI bridge) */ static void * -pci_readppb(pcicfgregs *cfg) +pci_readppb(device_t pcib, int b, int s, int f) { pcih1cfgregs *p; @@ -187,35 +191,43 @@ pci_readppb(pcicfgregs *cfg) bzero(p, sizeof *p); - p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_1, 2); - p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_1, 2); + p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_1, 2); + p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_1, 2); - p->seclat = pci_cfgread(cfg, PCIR_SECLAT_1, 1); + p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_1, 1); - p->iobase = PCI_PPBIOBASE (pci_cfgread(cfg, PCIR_IOBASEH_1, 2), - pci_cfgread(cfg, PCIR_IOBASEL_1, 1)); - p->iolimit = PCI_PPBIOLIMIT (pci_cfgread(cfg, PCIR_IOLIMITH_1, 2), - pci_cfgread(cfg, PCIR_IOLIMITL_1, 1)); + p->iobase = PCI_PPBIOBASE (PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_IOBASEH_1, 2), + PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_IOBASEL_1, 1)); + p->iolimit = PCI_PPBIOLIMIT (PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_IOLIMITH_1, 2), + PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_IOLIMITL_1, 1)); p->membase = PCI_PPBMEMBASE (0, - pci_cfgread(cfg, PCIR_MEMBASE_1, 2)); + PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_MEMBASE_1, 2)); p->memlimit = PCI_PPBMEMLIMIT (0, - pci_cfgread(cfg, PCIR_MEMLIMIT_1, 2)); + PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_MEMLIMIT_1, 2)); p->pmembase = PCI_PPBMEMBASE ( - (pci_addr_t)pci_cfgread(cfg, PCIR_PMBASEH_1, 4), - pci_cfgread(cfg, PCIR_PMBASEL_1, 2)); + (pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEH_1, 4), + PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMBASEL_1, 2)); p->pmemlimit = PCI_PPBMEMLIMIT ( - (pci_addr_t)pci_cfgread(cfg, PCIR_PMLIMITH_1, 4), - pci_cfgread(cfg, PCIR_PMLIMITL_1, 2)); + (pci_addr_t)PCIB_READ_CONFIG(pcib, b, s, f, + PCIR_PMLIMITH_1, 4), + PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PMLIMITL_1, 2)); + return (p); } /* read config data specific to header type 2 device (PCI to CardBus bridge) */ static void * -pci_readpcb(pcicfgregs *cfg) +pci_readpcb(device_t pcib, int b, int s, int f) { pcih2cfgregs *p; @@ -225,60 +237,63 @@ pci_readpcb(pcicfgregs *cfg) bzero(p, sizeof *p); - p->secstat = pci_cfgread(cfg, PCIR_SECSTAT_2, 2); - p->bridgectl = pci_cfgread(cfg, PCIR_BRIDGECTL_2, 2); + p->secstat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECSTAT_2, 2); + p->bridgectl = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_BRIDGECTL_2, 2); - p->seclat = pci_cfgread(cfg, PCIR_SECLAT_2, 1); + p->seclat = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_SECLAT_2, 1); - p->membase0 = pci_cfgread(cfg, PCIR_MEMBASE0_2, 4); - p->memlimit0 = pci_cfgread(cfg, PCIR_MEMLIMIT0_2, 4); - p->membase1 = pci_cfgread(cfg, PCIR_MEMBASE1_2, 4); - p->memlimit1 = pci_cfgread(cfg, PCIR_MEMLIMIT1_2, 4); + p->membase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE0_2, 4); + p->memlimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT0_2, 4); + p->membase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMBASE1_2, 4); + p->memlimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_MEMLIMIT1_2, 4); - p->iobase0 = pci_cfgread(cfg, PCIR_IOBASE0_2, 4); - p->iolimit0 = pci_cfgread(cfg, PCIR_IOLIMIT0_2, 4); - p->iobase1 = pci_cfgread(cfg, PCIR_IOBASE1_2, 4); - p->iolimit1 = pci_cfgread(cfg, PCIR_IOLIMIT1_2, 4); + p->iobase0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE0_2, 4); + p->iolimit0 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT0_2, 4); + p->iobase1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOBASE1_2, 4); + p->iolimit1 = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_IOLIMIT1_2, 4); - p->pccardif = pci_cfgread(cfg, PCIR_PCCARDIF_2, 4); + p->pccardif = PCIB_READ_CONFIG(pcib, b, s, f, PCIR_PCCARDIF_2, 4); return p; } /* extract header type specific config data */ static void -pci_hdrtypedata(pcicfgregs *cfg) +pci_hdrtypedata(device_t pcib, int b, int s, int f, pcicfgregs *cfg) { +#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) switch (cfg->hdrtype) { case 0: - cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_0, 2); - cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_0, 2); + cfg->subvendor = REG(PCIR_SUBVEND_0, 2); + cfg->subdevice = REG(PCIR_SUBDEV_0, 2); cfg->nummaps = PCI_MAXMAPS_0; break; case 1: - cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_1, 2); - cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_1, 2); - cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_1, 1); - cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_1, 1); + cfg->subvendor = REG(PCIR_SUBVEND_1, 2); + cfg->subdevice = REG(PCIR_SUBDEV_1, 2); + cfg->secondarybus = REG(PCIR_SECBUS_1, 1); + cfg->subordinatebus = REG(PCIR_SUBBUS_1, 1); cfg->nummaps = PCI_MAXMAPS_1; - cfg->hdrspec = pci_readppb(cfg); + cfg->hdrspec = pci_readppb(pcib, b, s, f); break; case 2: - cfg->subvendor = pci_cfgread(cfg, PCIR_SUBVEND_2, 2); - cfg->subdevice = pci_cfgread(cfg, PCIR_SUBDEV_2, 2); - cfg->secondarybus = pci_cfgread(cfg, PCIR_SECBUS_2, 1); - cfg->subordinatebus = pci_cfgread(cfg, PCIR_SUBBUS_2, 1); + cfg->subvendor = REG(PCIR_SUBVEND_2, 2); + cfg->subdevice = REG(PCIR_SUBDEV_2, 2); + cfg->secondarybus = REG(PCIR_SECBUS_2, 1); + cfg->subordinatebus = REG(PCIR_SUBBUS_2, 1); cfg->nummaps = PCI_MAXMAPS_2; - cfg->hdrspec = pci_readpcb(cfg); + cfg->hdrspec = pci_readpcb(pcib, b, s, f); break; } +#undef REG } /* read configuration header into pcicfgrect structure */ static struct pci_devinfo * -pci_readcfg(pcicfgregs *probe) +pci_read_device(device_t pcib, int b, int s, int f) { +#define REG(n, w) PCIB_READ_CONFIG(pcib, b, s, f, n, w) pcicfgregs *cfg = NULL; struct pci_devinfo *devlist_entry; struct devlist *devlist_head; @@ -287,8 +302,7 @@ pci_readcfg(pcicfgregs *probe) devlist_entry = NULL; - if (pci_cfgread(probe, PCIR_DEVVENDOR, 4) != -1) { - + if (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_DEVVENDOR, 4) != -1) { devlist_entry = malloc(sizeof(struct pci_devinfo), M_DEVBUF, M_WAITOK); if (devlist_entry == NULL) @@ -297,23 +311,22 @@ pci_readcfg(pcicfgregs *probe) cfg = &devlist_entry->cfg; - cfg->hose = probe->hose; - cfg->bus = probe->bus; - cfg->slot = probe->slot; - cfg->func = probe->func; - cfg->vendor = pci_cfgread(cfg, PCIR_VENDOR, 2); - cfg->device = pci_cfgread(cfg, PCIR_DEVICE, 2); - cfg->cmdreg = pci_cfgread(cfg, PCIR_COMMAND, 2); - cfg->statreg = pci_cfgread(cfg, PCIR_STATUS, 2); - cfg->baseclass = pci_cfgread(cfg, PCIR_CLASS, 1); - cfg->subclass = pci_cfgread(cfg, PCIR_SUBCLASS, 1); - cfg->progif = pci_cfgread(cfg, PCIR_PROGIF, 1); - cfg->revid = pci_cfgread(cfg, PCIR_REVID, 1); - cfg->hdrtype = pci_cfgread(cfg, PCIR_HEADERTYPE, 1); - cfg->cachelnsz = pci_cfgread(cfg, PCIR_CACHELNSZ, 1); - cfg->lattimer = pci_cfgread(cfg, PCIR_LATTIMER, 1); - cfg->intpin = pci_cfgread(cfg, PCIR_INTPIN, 1); - cfg->intline = pci_cfgread(cfg, PCIR_INTLINE, 1); + cfg->bus = b; + cfg->slot = s; + cfg->func = f; + cfg->vendor = REG(PCIR_VENDOR, 2); + cfg->device = REG(PCIR_DEVICE, 2); + cfg->cmdreg = REG(PCIR_COMMAND, 2); + cfg->statreg = REG(PCIR_STATUS, 2); + cfg->baseclass = REG(PCIR_CLASS, 1); + cfg->subclass = REG(PCIR_SUBCLASS, 1); + cfg->progif = REG(PCIR_PROGIF, 1); + cfg->revid = REG(PCIR_REVID, 1); + cfg->hdrtype = REG(PCIR_HEADERTYPE, 1); + cfg->cachelnsz = REG(PCIR_CACHELNSZ, 1); + cfg->lattimer = REG(PCIR_LATTIMER, 1); + cfg->intpin = REG(PCIR_INTPIN, 1); + cfg->intline = REG(PCIR_INTLINE, 1); #ifdef __alpha__ alpha_platform_assign_pciintr(cfg); #endif @@ -346,14 +359,14 @@ pci_readcfg(pcicfgregs *probe) } #endif /* APIC_IO */ - cfg->mingnt = pci_cfgread(cfg, PCIR_MINGNT, 1); - cfg->maxlat = pci_cfgread(cfg, PCIR_MAXLAT, 1); + cfg->mingnt = REG(PCIR_MINGNT, 1); + cfg->maxlat = REG(PCIR_MAXLAT, 1); cfg->mfdev = (cfg->hdrtype & PCIM_MFDEV) != 0; cfg->hdrtype &= ~PCIM_MFDEV; pci_fixancient(cfg); - pci_hdrtypedata(cfg); + pci_hdrtypedata(pcib, b, s, f, cfg); STAILQ_INSERT_TAIL(devlist_head, devlist_entry, pci_links); @@ -376,6 +389,7 @@ pci_readcfg(pcicfgregs *probe) pci_generation++; } return (devlist_entry); +#undef REG } #if 0 @@ -541,6 +555,7 @@ pci_devlist_get_parent(pcicfgregs *cfg) static int pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) { + device_t pci, pcib; struct pci_io *io; const char *name; int error; @@ -782,17 +797,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case PCIOCREAD: io = (struct pci_io *)data; switch(io->pi_width) { - pcicfgregs probe; case 4: case 2: case 1: - probe.hose = -1; - probe.bus = io->pi_sel.pc_bus; - probe.slot = io->pi_sel.pc_dev; - probe.func = io->pi_sel.pc_func; - io->pi_data = pci_cfgread(&probe, - io->pi_reg, io->pi_width); - error = 0; + /* + * Assume that the user-level bus number is + * actually the pciN instance number. We map + * from that to the real pcib+bus combination. + */ + pci = devclass_get_device(pci_devclass, + io->pi_sel.pc_bus); + if (pci) { + int b = pcib_get_bus(pci); + pcib = device_get_parent(pci); + io->pi_data = + PCIB_READ_CONFIG(pcib, + b, + io->pi_sel.pc_dev, + io->pi_sel.pc_func, + io->pi_reg, + io->pi_width); + error = 0; + } else { + error = ENODEV; + } break; default: error = ENODEV; @@ -803,17 +831,30 @@ pci_ioctl(dev_t dev, u_long cmd, caddr_t data, int flag, struct proc *p) case PCIOCWRITE: io = (struct pci_io *)data; switch(io->pi_width) { - pcicfgregs probe; case 4: case 2: case 1: - probe.hose = -1; - probe.bus = io->pi_sel.pc_bus; - probe.slot = io->pi_sel.pc_dev; - probe.func = io->pi_sel.pc_func; - pci_cfgwrite(&probe, - io->pi_reg, io->pi_data, io->pi_width); - error = 0; + /* + * Assume that the user-level bus number is + * actually the pciN instance number. We map + * from that to the real pcib+bus combination. + */ + pci = devclass_get_device(pci_devclass, + io->pi_sel.pc_bus); + if (pci) { + int b = pcib_get_bus(pci); + pcib = device_get_parent(pci); + PCIB_WRITE_CONFIG(pcib, + b, + io->pi_sel.pc_dev, + io->pi_sel.pc_func, + io->pi_reg, + io->pi_data, + io->pi_width); + error = 0; + } else { + error = ENODEV; + } break; default: error = ENODEV; @@ -850,7 +891,6 @@ static struct cdevsw pcicdev = { #include "pci_if.h" - /* * 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. @@ -882,15 +922,17 @@ pci_print_verbose(struct pci_devinfo *dinfo) } static int -pci_porten(pcicfgregs *cfg) +pci_porten(device_t pcib, int b, int s, int f) { - return ((cfg->cmdreg & PCIM_CMD_PORTEN) != 0); + return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2) + & PCIM_CMD_PORTEN) != 0; } static int -pci_memen(pcicfgregs *cfg) +pci_memen(device_t pcib, int b, int s, int f) { - return ((cfg->cmdreg & PCIM_CMD_MEMEN) != 0); + return (PCIB_READ_CONFIG(pcib, b, s, f, PCIR_COMMAND, 2) + & PCIM_CMD_MEMEN) != 0; } /* @@ -898,10 +940,9 @@ pci_memen(pcicfgregs *cfg) * register is a 32bit map register or 2 if it is a 64bit register. */ static int -pci_add_map(device_t dev, pcicfgregs* cfg, int reg) +pci_add_map(device_t pcib, int b, int s, int f, int reg, + struct resource_list *rl) { - struct pci_devinfo *dinfo = device_get_ivars(dev); - struct resource_list *rl = &dinfo->resources; u_int32_t map; u_int64_t base; u_int8_t ln2size; @@ -910,14 +951,14 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg) int type; - map = pci_cfgread(cfg, reg, 4); + map = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4); if (map == 0 || map == 0xffffffff) return 1; /* skip invalid entry */ - pci_cfgwrite(cfg, reg, 0xffffffff, 4); - testval = pci_cfgread(cfg, reg, 4); - pci_cfgwrite(cfg, reg, map, 4); + PCIB_WRITE_CONFIG(pcib, b, s, f, reg, 0xffffffff, 4); + testval = PCIB_READ_CONFIG(pcib, b, s, f, reg, 4); + PCIB_WRITE_CONFIG(pcib, b, s, f, reg, map, 4); base = pci_mapbase(map); if (pci_maptype(map) & PCI_MAPMEM) @@ -928,72 +969,24 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg) ln2range = pci_maprange(testval); if (ln2range == 64) { /* Read the other half of a 64bit map register */ - base |= (u_int64_t) pci_cfgread(cfg, reg + 4, 4) << 32; + base |= (u_int64_t) PCIB_READ_CONFIG(pcib, b, s, f, reg + 4, 4) << 32; } -#ifdef __alpha__ - /* - * XXX: encode hose number in the base addr, - * This will go away once the bus_space functions - * can deal with multiple hoses - */ - - if (cfg->hose) { - u_int32_t mask, shift, maxh; - - switch (hwrpb->rpb_type) { - case ST_DEC_4100: - mask = 0xc0000000; - shift = 30; - maxh = 4; /* not a hose. MCPCIA instance # */ - break; - case ST_DEC_21000: - mask = 0xf8000000; - shift = 27; - maxh = 32; - break; - case ST_DEC_6600: - mask = 0x80000000; - shift = 31; - maxh = 2; - break; - default: - mask = 0; - shift = 0; - maxh = 0; - break; - } - if (base & mask) { - printf("base addr = 0x%llx\n", (long long) base); - printf("mask addr = 0x%lx\n", (long) mask); - printf("hacked addr = 0x%llx\n", (long long) - (base | ((u_int64_t)cfg->hose << shift))); - panic("hose encoding hack would clobber base addr"); - /* NOTREACHED */ - } - if (cfg->hose >= maxh) { - panic("Hose %d - can only encode %d hose(s)", - cfg->hose, maxh); - /* NOTREACHED */ - } - base |= ((u_int64_t)cfg->hose << shift); - } -#endif if (bootverbose) { printf("\tmap[%02x]: type %x, range %2d, base %08x, size %2d", reg, pci_maptype(map), ln2range, (unsigned int) base, ln2size); - if (type == SYS_RES_IOPORT && !pci_porten(cfg)) + if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f)) printf(", port disabled\n"); - else if (type == SYS_RES_MEMORY && !pci_memen(cfg)) + else if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f)) printf(", memory disabled\n"); else printf(", enabled\n"); } - if (type == SYS_RES_IOPORT && !pci_porten(cfg)) + if (type == SYS_RES_IOPORT && !pci_porten(pcib, b, s, f)) return 1; - if (type == SYS_RES_MEMORY && !pci_memen(cfg)) + if (type == SYS_RES_MEMORY && !pci_memen(pcib, b, s, f)) return 1; resource_list_add(rl, type, reg, @@ -1004,21 +997,22 @@ pci_add_map(device_t dev, pcicfgregs* cfg, int reg) } static void -pci_add_resources(device_t dev, pcicfgregs* cfg) +pci_add_resources(device_t pcib, int b, int s, int f, device_t dev) { struct pci_devinfo *dinfo = device_get_ivars(dev); + pcicfgregs *cfg = &dinfo->cfg; struct resource_list *rl = &dinfo->resources; struct pci_quirk *q; int i; for (i = 0; i < cfg->nummaps;) { - i += pci_add_map(dev, cfg, PCIR_MAPS + i*4); + i += pci_add_map(pcib, b, s, f, PCIR_MAPS + i*4, rl); } for (q = &pci_quirks[0]; q->devid; q++) { if (q->devid == ((cfg->device << 16) | cfg->vendor) && q->type == PCI_QUIRK_MAP_REG) - pci_add_map(dev, cfg, q->arg1); + pci_add_map(pcib, b, s, f, q->arg1, rl); } if (cfg->intpin > 0 && cfg->intline != 255) @@ -1029,26 +1023,17 @@ pci_add_resources(device_t dev, pcicfgregs* cfg) static void pci_add_children(device_t dev, int busno) { - pcicfgregs probe; - -#ifdef SIMOS -#undef PCI_SLOTMAX -#define PCI_SLOTMAX 0 -#endif + device_t pcib = device_get_parent(dev); + int maxslots; + int s, f; - bzero(&probe, sizeof probe); -#ifdef __alpha__ - probe.hose = pcib_get_hose(dev); -#endif -#ifdef __i386__ - probe.hose = 0; -#endif - probe.bus = busno; - - for (probe.slot = 0; probe.slot <= PCI_SLOTMAX; probe.slot++) { + maxslots = PCIB_MAXSLOTS(pcib); + + for (s = 0; s <= maxslots; s++) { int pcifunchigh = 0; - for (probe.func = 0; probe.func <= pcifunchigh; probe.func++) { - struct pci_devinfo *dinfo = pci_readcfg(&probe); + for (f = 0; f <= pcifunchigh; f++) { + struct pci_devinfo *dinfo = + pci_read_device(pcib, busno, s, f); if (dinfo != NULL) { if (dinfo->cfg.mfdev) pcifunchigh = 7; @@ -1056,19 +1041,31 @@ pci_add_children(device_t dev, int busno) pci_print_verbose(dinfo); dinfo->cfg.dev = device_add_child(dev, NULL, -1); device_set_ivars(dinfo->cfg.dev, dinfo); - pci_add_resources(dinfo->cfg.dev, &dinfo->cfg); + pci_add_resources(pcib, busno, s, f, + dinfo->cfg.dev); } } } } static int -pci_new_probe(device_t dev) +pci_probe(device_t dev) { static int once; device_set_desc(dev, "PCI bus"); - pci_add_children(dev, device_get_unit(dev)); + + if (bootverbose) + device_printf(dev, "physical bus=%d\n", pcib_get_bus(dev)); + + /* + * Since there can be multiple independantly numbered PCI + * busses on some large alpha systems, we can't use the unit + * number to decide what bus we are probing. We ask the parent + * pcib what our bus number is. + */ + pci_add_children(dev, pcib_get_bus(dev)); + if (!once) { make_dev(&pcicdev, 0, UID_ROOT, GID_WHEEL, 0644, "pci"); once++; @@ -1227,12 +1224,6 @@ pci_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) case PCI_IVAR_SUBORDINATEBUS: *result = cfg->subordinatebus; break; - case PCI_IVAR_HOSE: - /* - * Pass up to parent bridge. - */ - *result = pcib_get_hose(dev); - break; default: return ENOENT; } @@ -1340,7 +1331,10 @@ 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); + + return PCIB_READ_CONFIG(device_get_parent(dev), + cfg->bus, cfg->slot, cfg->func, + reg, width); } static void @@ -1349,7 +1343,10 @@ pci_write_config_method(device_t dev, device_t child, int reg, { struct pci_devinfo *dinfo = device_get_ivars(child); pcicfgregs *cfg = &dinfo->cfg; - pci_cfgwrite(cfg, reg, val, width); + + PCIB_WRITE_CONFIG(device_get_parent(dev), + cfg->bus, cfg->slot, cfg->func, + reg, val, width); } static int @@ -1369,7 +1366,7 @@ pci_modevent(module_t mod, int what, void *arg) static device_method_t pci_methods[] = { /* Device interface */ - DEVMETHOD(device_probe, pci_new_probe), + DEVMETHOD(device_probe, pci_probe), DEVMETHOD(device_attach, bus_generic_attach), DEVMETHOD(device_shutdown, bus_generic_shutdown), DEVMETHOD(device_suspend, bus_generic_suspend), diff --git a/sys/pci/pci_compat.c b/sys/pci/pci_compat.c index 4635342..bf833b1 100644 --- a/sys/pci/pci_compat.c +++ b/sys/pci/pci_compat.c @@ -73,6 +73,18 @@ pci_conf_write(pcici_t cfg, u_long reg, u_long data) } int +pci_cfgread (pcicfgregs *cfg, int reg, int bytes) +{ + return (pci_read_config(cfg->dev, reg, bytes)); +} + +void +pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes) +{ + pci_write_config(cfg->dev, reg, data, bytes); +} + +int pci_map_port(pcici_t cfg, u_long reg, pci_port_t* pa) { int rid; diff --git a/sys/pci/pcib_if.m b/sys/pci/pcib_if.m new file mode 100644 index 0000000..b50df4b --- /dev/null +++ b/sys/pci/pcib_if.m @@ -0,0 +1,71 @@ +# +# Copyright (c) 2000 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. +# +# $FreeBSD$ +# + +#include <sys/bus.h> + +INTERFACE pcib; + +# +# Return the number of slots on the attached PCI bus. +# +METHOD int maxslots { + device_t dev; +}; + +# +# Read configuration space on the PCI bus. The bus, slot and func +# arguments determine the device which is being read and the reg +# argument is a byte offset into configuration space for that +# device. The width argument (which should be 1, 2 or 4) specifies how +# many byte of configuration space to read from that offset. +# +METHOD u_int32_t read_config { + device_t dev; + int bus; + int slot; + int func; + int reg; + int width; +}; + +# +# Write configuration space on the PCI bus. The bus, slot and func +# arguments determine the device which is being written and the reg +# argument is a byte offset into configuration space for that +# device. The value field is written to the configuration space, with +# the number of bytes written depending on the width argument. +# +METHOD void write_config { + device_t dev; + int bus; + int slot; + int func; + int reg; + u_int32_t value; + int width; +}; diff --git a/sys/pci/pcisupport.c b/sys/pci/pcisupport.c index e0a72e1..374a168 100644 --- a/sys/pci/pcisupport.c +++ b/sys/pci/pcisupport.c @@ -58,6 +58,8 @@ #include <vm/vm_object.h> #include <vm/pmap.h> +#include "pcib_if.h" + /*--------------------------------------------------------- ** ** Intel chipsets for 486 / Pentium processor @@ -762,7 +764,9 @@ static int pcib_attach(device_t dev) secondary = pci_get_secondarybus(dev); if (secondary) { - device_add_child(dev, "pci", secondary); + device_t child; + child = device_add_child(dev, "pci", -1); + pcib_set_bus(child, secondary); return bus_generic_attach(dev); } else return 0; @@ -771,16 +775,55 @@ static int pcib_attach(device_t dev) static int pcib_read_ivar(device_t dev, device_t child, int which, uintptr_t *result) { - if (which == PCIB_IVAR_HOSE) { - /* - * Pass up to parent bus. - */ - *result = pci_get_hose(dev); - return(0); + switch (which) { + case PCIB_IVAR_BUS: + *result = *(int*) device_get_softc(dev); + return 0; + } + return ENOENT; +} + +static int +pcib_write_ivar(device_t dev, device_t child, int which, uintptr_t value) +{ + switch (which) { + case PCIB_IVAR_BUS: + *(int*) device_get_softc(dev) = value; + return 0; } return ENOENT; } +static int +pcib_maxslots(device_t dev) +{ + return 31; +} + +static u_int32_t +pcib_read_config(device_t dev, int b, int s, int f, + int reg, int width) +{ + /* + * Pass through to the next ppb up the chain (i.e. our + * grandparent). + */ + return PCIB_READ_CONFIG(device_get_parent(device_get_parent(dev)), + b, s, f, reg, width); +} + +static void +pcib_write_config(device_t dev, int b, int s, int f, + int reg, u_int32_t val, int width) +{ + /* + * Pass through to the next ppb up the chain (i.e. our + * grandparent). + */ + PCIB_WRITE_CONFIG(device_get_parent(device_get_parent(dev)), + b, s, f, reg, val, width); +} + static device_method_t pcib_methods[] = { /* Device interface */ DEVMETHOD(device_probe, pcib_probe), @@ -792,6 +835,7 @@ static device_method_t pcib_methods[] = { /* Bus interface */ DEVMETHOD(bus_print_child, bus_generic_print_child), DEVMETHOD(bus_read_ivar, pcib_read_ivar), + DEVMETHOD(bus_write_ivar, pcib_write_ivar), DEVMETHOD(bus_alloc_resource, bus_generic_alloc_resource), DEVMETHOD(bus_release_resource, bus_generic_release_resource), DEVMETHOD(bus_activate_resource, bus_generic_activate_resource), @@ -799,13 +843,18 @@ static device_method_t pcib_methods[] = { DEVMETHOD(bus_setup_intr, bus_generic_setup_intr), DEVMETHOD(bus_teardown_intr, bus_generic_teardown_intr), + /* pcib interface */ + DEVMETHOD(pcib_maxslots, pcib_maxslots), + DEVMETHOD(pcib_read_config, pcib_read_config), + DEVMETHOD(pcib_write_config, pcib_write_config), + { 0, 0 } }; static driver_t pcib_driver = { "pcib", pcib_methods, - 1, + sizeof(int), }; static devclass_t pcib_devclass; diff --git a/sys/pci/pcivar.h b/sys/pci/pcivar.h index b767616..34df379 100644 --- a/sys/pci/pcivar.h +++ b/sys/pci/pcivar.h @@ -82,7 +82,6 @@ typedef struct pcicfg { u_int8_t mfdev; /* multi-function device (from hdrtype reg) */ u_int8_t nummaps; /* actual number of PCI maps used */ - u_int8_t hose; /* hose which bus is attached to */ u_int8_t bus; /* config space bus address */ u_int8_t slot; /* config space slot address */ u_int8_t func; /* config space function number */ @@ -156,6 +155,7 @@ const char *pci_chip_match(struct device *dev); int pci_cfgread (pcicfgregs *cfg, int reg, int bytes); void pci_cfgwrite (pcicfgregs *cfg, int reg, int data, int bytes); + #ifdef __alpha__ vm_offset_t pci_cvt_to_dense (vm_offset_t); vm_offset_t pci_cvt_to_bwx (vm_offset_t); @@ -192,7 +192,6 @@ enum pci_device_ivars { PCI_IVAR_FUNCTION, PCI_IVAR_SECONDARYBUS, PCI_IVAR_SUBORDINATEBUS, - PCI_IVAR_HOSE, }; /* @@ -229,7 +228,6 @@ 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) -PCI_ACCESSOR(hose, HOSE, u_int32_t) static __inline u_int32_t pci_read_config(device_t dev, int reg, int width) @@ -249,7 +247,7 @@ pci_write_config(device_t dev, int reg, u_int32_t val, int width) /*typedef enum pci_device_ivars pcib_device_ivars;*/ enum pcib_device_ivars { - PCIB_IVAR_HOSE, + PCIB_IVAR_BUS }; #define PCIB_ACCESSOR(A, B, T) \ @@ -267,7 +265,7 @@ static __inline void pcib_set_ ## A(device_t dev, T t) \ BUS_WRITE_IVAR(device_get_parent(dev), dev, PCIB_IVAR_ ## B, v); \ } -PCIB_ACCESSOR(hose, HOSE, u_int32_t) +PCIB_ACCESSOR(bus, BUS, u_int32_t) #endif |