PERFORCE change 189677 for review
John Baldwin
jhb at FreeBSD.org
Mon Mar 7 18:45:47 UTC 2011
http://p4web.freebsd.org/@@189677?ac=10
Change 189677 by jhb at jhb_jhbbsd on 2011/03/07 18:45:39
- Properly handle expansion ROM BARs for PCI-PCI bridges (they are
at a different config space offset) and for Cardbus bridges
(they don't exist).
- Various compile fixes.
Affected files ...
.. //depot/projects/pci/sys/dev/pci/pci.c#6 edit
.. //depot/projects/pci/sys/dev/pci/pci_private.h#4 edit
.. //depot/projects/pci/sys/dev/pci/pci_user.c#4 edit
.. //depot/projects/pci/sys/dev/pci/pcireg.h#2 edit
.. //depot/projects/pci/sys/dev/pci/pcivar.h#3 edit
Differences ...
==== //depot/projects/pci/sys/dev/pci/pci.c#6 (text+ko) ====
@@ -69,6 +69,11 @@
#include "pcib_if.h"
#include "pci_if.h"
+#define PCIR_IS_BIOS(cfg, reg) \
+ (((cfg)->hdrtype == PCIM_HDRTYPE_NORMAL && reg == PCIR_BIOS) || \
+ ((cfg)->hdrtype == PCIM_HDRTYPE_BRIDGE && reg == PCIR_BIOS_1))
+
+
static pci_addr_t pci_mapbase(uint64_t mapreg);
static const char *pci_maptype(uint64_t mapreg);
static int pci_mapsize(uint64_t testval);
@@ -2376,6 +2381,7 @@
static void
pci_read_bar(device_t dev, int reg, pci_addr_t *mapp, pci_addr_t *testvalp)
{
+ struct pci_devinfo *dinfo;
pci_addr_t map, testval;
int ln2range;
uint16_t cmd;
@@ -2385,7 +2391,8 @@
* memory BAR. Bit 0 is special and should not be set when
* sizing the BAR.
*/
- if (reg == PCIR_BIOS) {
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, reg)) {
map = pci_read_config(dev, reg, 4);
pci_write_config(dev, reg, 0xfffffffe, 4);
testval = pci_read_config(dev, reg, 4);
@@ -2438,10 +2445,12 @@
static void
pci_write_bar(device_t dev, struct pci_map *pm, pci_addr_t base)
{
+ struct pci_devinfo *dinfo;
int ln2range;
/* The device ROM BAR is always a 32-bit memory BAR. */
- if (pm->pm_reg == PCIR_BIOS)
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg))
ln2range = 32;
else
ln2range = pci_maprange(pm->pm_value);
@@ -2461,7 +2470,7 @@
dinfo = device_get_ivars(dev);
STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) {
- if (pm->pm_reg == bio->pbi_reg)
+ if (pm->pm_reg == reg)
return (pm);
}
return (NULL);
@@ -2470,18 +2479,21 @@
int
pci_bar_enabled(device_t dev, struct pci_map *pm)
{
+ struct pci_devinfo *dinfo;
uint16_t cmd;
- if (pm->pm_reg == PCIR_BIOS && !(pm->pm_value & PCIM_BIOS_ENABLE))
+ dinfo = device_get_ivars(dev);
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) &&
+ !(pm->pm_value & PCIM_BIOS_ENABLE))
return (0);
cmd = pci_read_config(dev, PCIR_COMMAND, 2);
- if (pm->pm_reg == PCIR_BIOS || PCI_BAR_MEM(pm->pm_value))
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg) || PCI_BAR_MEM(pm->pm_value))
return ((cmd & PCIM_CMD_MEMEN) != 0);
else
return ((cmd & PCIM_CMD_PORTEN) != 0);
}
-struct pci_map *
+static struct pci_map *
pci_add_bar(device_t dev, int reg, pci_addr_t value, pci_addr_t size)
{
struct pci_devinfo *dinfo;
@@ -2495,8 +2507,8 @@
STAILQ_FOREACH(prev, &dinfo->cfg.maps, pm_link) {
KASSERT(prev->pm_reg != pm->pm_reg, ("duplicate map %02x",
reg));
- if (STAILQ_NEXT(prev) == NULL || STAILQ_NEXT(prev)->pm_reg >
- pm->pm_reg)
+ if (STAILQ_NEXT(prev, pm_link) == NULL ||
+ STAILQ_NEXT(prev, pm_link)->pm_reg > pm->pm_reg)
break;
}
if (prev != NULL)
@@ -2514,14 +2526,15 @@
int ln2range;
dinfo = device_get_ivars(dev);
- STAILQ_FOREACH(prev, &dinfo->cfg.maps, pm_link) {
- if (pm->pm_reg == PCIR_BIOS)
+ STAILQ_FOREACH(pm, &dinfo->cfg.maps, pm_link) {
+ if (PCIR_IS_BIOS(&dinfo->cfg, pm->pm_reg))
ln2range = 32;
else
ln2range = pci_maprange(pm->pm_value);
pci_write_config(dev, pm->pm_reg, pm->pm_value, 4);
if (ln2range == 64)
- pci_write_config(dev, pm->pm_reg + 4, pm->pm_value >> 32, 4);
+ pci_write_config(dev, pm->pm_reg + 4,
+ pm->pm_value >> 32, 4);
}
}
@@ -3820,7 +3833,7 @@
* Determine the size of the BAR and ignore BARs with a size
* of 0. Device ROM BARs use a different mask value.
*/
- if (*rid == PCIR_BIOS)
+ if (PCIR_IS_BIOS(&dinfo->cfg, *rid))
mapsize = pci_romsize(testval);
else
mapsize = pci_mapsize(testval);
@@ -3829,7 +3842,7 @@
pm = pci_add_bar(child, *rid, map, mapsize);
}
- if (PCI_BAR_MEM(map) || *rid == PCIR_BIOS) {
+ if (PCI_BAR_MEM(map) || PCIR_IS_BIOS(&dinfo->cfg, *rid)) {
if (type != SYS_RES_MEMORY) {
if (bootverbose)
device_printf(dev,
@@ -3949,6 +3962,7 @@
pci_activate_resource(device_t dev, device_t child, int type, int rid,
struct resource *r)
{
+ struct pci_devinfo *dinfo;
int error;
error = bus_generic_activate_resource(dev, child, type, rid, r);
@@ -3958,8 +3972,9 @@
/* Enable decoding in the command register when activating BARs. */
if (device_get_parent(child) == dev) {
/* Device ROMs need their decoding explicitly enabled. */
- if (rid == PCIR_BIOS)
- pci_write_bar(child, pci_get_bar(child, PCIR_BIOS),
+ dinfo = device_get_ivars(child);
+ if (PCIR_IS_BIOS(&dinfo->cfg, rid))
+ pci_write_bar(child, pci_find_bar(child, rid),
rman_get_start(r) | PCIM_BIOS_ENABLE);
switch (type) {
case SYS_RES_IOPORT:
@@ -3975,16 +3990,20 @@
pci_deactivate_resource(device_t dev, device_t child, int type,
int rid, struct resource *r)
{
- struct pci_map *pm;
+ struct pci_devinfo *dinfo;
int error;
error = bus_generic_deactivate_resource(dev, child, type, rid, r);
if (error)
return (error);
- /* Disable decoding for device ROMs. */
- if (rid == PCIR_BIOS)
- pci_write_bar(child, pci_get_bar(child, PCIR_BIOS), rman_get_start(r));
+ /* Disable decoding for device ROMs. */
+ if (device_get_parent(child) == dev) {
+ dinfo = device_get_ivars(child);
+ if (PCIR_IS_BIOS(&dinfo->cfg, rid))
+ pci_write_bar(child, pci_find_bar(child, rid),
+ rman_get_start(r));
+ }
return (0);
}
@@ -4062,7 +4081,7 @@
switch (type) {
case SYS_RES_IOPORT:
case SYS_RES_MEMORY:
- pci_write_bar(child, pci_get_bar(child, rid), 0);
+ pci_write_bar(child, pci_find_bar(child, rid), 0);
break;
}
#endif
@@ -4161,7 +4180,9 @@
void
pci_cfg_restore(device_t dev, struct pci_devinfo *dinfo)
{
+#if 0
int i;
+#endif
/*
* Only do header type 0 devices. Type 1 devices are bridges,
@@ -4209,7 +4230,9 @@
void
pci_cfg_save(device_t dev, struct pci_devinfo *dinfo, int setstate)
{
+#if 0
int i;
+#endif
uint32_t cls;
int ps;
==== //depot/projects/pci/sys/dev/pci/pci_private.h#4 (text+ko) ====
@@ -104,8 +104,6 @@
int pci_assign_interrupt_method(device_t dev, device_t child);
int pci_resume(device_t dev);
int pci_suspend(device_t dev);
-struct pci_map *pci_find_bar(device_t dev, int reg);
-int pci_bar_enabled(device_t dev, struct pci_map *pm);
/** Restore the config register state. The state must be previously
* saved with pci_cfg_save. However, the pci bus driver takes care of
==== //depot/projects/pci/sys/dev/pci/pci_user.c#4 (text+ko) ====
@@ -309,7 +309,6 @@
struct pci_io *io;
struct pci_bar_io *bio;
struct pci_match_conf *pattern_buf;
- struct resource_list_entry *rle;
struct pci_map *pm;
size_t confsz, iolen, pbufsz;
int error, ionum, i, num_patterns;
@@ -685,7 +684,7 @@
error = ENODEV;
break;
}
- pm = pci_find_bar(pcidev, reg);
+ pm = pci_find_bar(pcidev, bio->pbi_reg);
if (pm == NULL) {
error = EINVAL;
break;
==== //depot/projects/pci/sys/dev/pci/pcireg.h#2 (text+ko) ====
@@ -212,6 +212,7 @@
#define PCIM_BRPM_64 0x1
#define PCIM_BRPM_MASK 0xf
+#define PCIR_BIOS_1 0x38
#define PCIR_BRIDGECTL_1 0x3e
/* config registers for header type 2 (CardBus) devices */
==== //depot/projects/pci/sys/dev/pci/pcivar.h#3 (text+ko) ====
@@ -477,4 +477,7 @@
extern struct devlist pci_devq;
extern uint32_t pci_generation;
+struct pci_map *pci_find_bar(device_t dev, int reg);
+int pci_bar_enabled(device_t dev, struct pci_map *pm);
+
#endif /* _PCIVAR_H_ */
More information about the p4-projects
mailing list