summaryrefslogtreecommitdiffstats
path: root/sys/dev/pci
diff options
context:
space:
mode:
authordfr <dfr@FreeBSD.org>2000-08-28 21:48:13 +0000
committerdfr <dfr@FreeBSD.org>2000-08-28 21:48:13 +0000
commitdd8b44b3958fa67d802cbbec7c7d82f7fb476229 (patch)
tree61496c144b3ecd15192a2e07e755754e18346bc9 /sys/dev/pci
parent9ed8ded4d312c58a27de9402fd9802e78a591cb9 (diff)
downloadFreeBSD-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/dev/pci')
-rw-r--r--sys/dev/pci/pci.c351
-rw-r--r--sys/dev/pci/pcib_if.m71
-rw-r--r--sys/dev/pci/pcivar.h8
3 files changed, 248 insertions, 182 deletions
diff --git a/sys/dev/pci/pci.c b/sys/dev/pci/pci.c
index cfda6c7..b31667c 100644
--- a/sys/dev/pci/pci.c
+++ b/sys/dev/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/dev/pci/pcib_if.m b/sys/dev/pci/pcib_if.m
new file mode 100644
index 0000000..b50df4b
--- /dev/null
+++ b/sys/dev/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/dev/pci/pcivar.h b/sys/dev/pci/pcivar.h
index b767616..34df379 100644
--- a/sys/dev/pci/pcivar.h
+++ b/sys/dev/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
OpenPOWER on IntegriCloud