Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 7 Mar 2011 18:45:46 GMT
From:      John Baldwin <jhb@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 189677 for review
Message-ID:  <201103071845.p27Ijk6X049465@skunkworks.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://p4web.freebsd.org/@@189677?ac=10

Change 189677 by jhb@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_ */



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201103071845.p27Ijk6X049465>