[OpenBIOS] r507 - trunk/openbios-devel/drivers

svn at openbios.org svn at openbios.org
Sat Jul 11 14:23:24 CEST 2009


Author: blueswirl
Date: 2009-07-11 14:23:24 +0200 (Sat, 11 Jul 2009)
New Revision: 507

Modified:
   trunk/openbios-devel/drivers/pci.c
   trunk/openbios-devel/drivers/pci.h
Log:
Improve PCI BAR handling (Igor Kovalenko)

Signed-off-by: igor.v.kovalenko at gmail.com


Modified: trunk/openbios-devel/drivers/pci.c
===================================================================
--- trunk/openbios-devel/drivers/pci.c	2009-07-11 12:20:20 UTC (rev 506)
+++ trunk/openbios-devel/drivers/pci.c	2009-07-11 12:23:24 UTC (rev 507)
@@ -323,7 +323,7 @@
 			     ncells * sizeof(cell));
 }
 
-static void pci_set_assigned_addresses(const pci_config_t *config)
+static void pci_set_assigned_addresses(const pci_config_t *config, int num_bars)
 {
 	phandle_t dev = get_cur_dev();
 	u32 props[32];
@@ -333,7 +333,7 @@
 	int flags, space_code;
 
 	ncells = 0;
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < num_bars; i++) {
 		if (!config->assigned[i] || !config->sizes[i])
 			continue;
 		pci_decode_pci_addr(config->assigned[i],
@@ -353,7 +353,7 @@
 			     ncells * sizeof(props[0]));
 }
 
-static void pci_set_reg(const pci_config_t *config)
+static void pci_set_reg(const pci_config_t *config, int num_bars)
 {
 	phandle_t dev = get_cur_dev();
 	u32 props[38];
@@ -370,7 +370,7 @@
 	props[ncells++] = 0x00000000;
 	props[ncells++] = 0x00000000;
 
-	for (i = 0; i < 6; i++) {
+	for (i = 0; i < num_bars; i++) {
 		if (!config->assigned[i] || !config->sizes[i])
 			continue;
 
@@ -474,7 +474,7 @@
 }
 
 static void ob_pci_add_properties(pci_addr addr, const pci_dev_t *pci_dev,
-                                  const pci_config_t *config)
+                                  const pci_config_t *config, int num_bars)
 {
 	phandle_t dev=get_cur_dev();
 	int status,id;
@@ -553,8 +553,8 @@
 					      pci_dev->icells);
 	}
 
-	pci_set_reg(config);
-	pci_set_assigned_addresses(config);
+	pci_set_reg(config, num_bars);
+	pci_set_assigned_addresses(config, num_bars);
 	OLDWORLD(pci_set_AAPL_address(config));
 
 #ifdef CONFIG_DEBUG_PCI
@@ -604,91 +604,112 @@
 }
 #endif
 
-static void
-ob_pci_configure(pci_addr addr, pci_config_t *config, unsigned long *mem_base,
-                 unsigned long *io_base)
-
+static void ob_pci_configure_bar(pci_addr addr, pci_config_t *config,
+                                 int reg, int config_addr,
+                                 uint32_t *p_omask,
+                                 unsigned long *mem_base,
+                                 unsigned long *io_base)
 {
-	uint32_t smask, omask, amask, size, reloc, min_align;
+        uint32_t smask, amask, size, reloc, min_align;
         unsigned long base;
-	pci_addr config_addr;
-	int reg;
-	uint8_t irq_pin, irq_line;
 
-	irq_pin =  pci_config_read8(addr, PCI_INTERRUPT_PIN);
-	if (irq_pin) {
-		config->irq_pin = irq_pin;
-		irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
-		irq_line = arch->irqs[irq_pin];
-		pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
-		config->irq_line = irq_line;
-	} else
-		config->irq_line = -1;
+        config->assigned[reg] = 0x00000000;
+        config->sizes[reg] = 0x00000000;
 
-	omask = 0x00000000;
-	for (reg = 0; reg < 7; reg++) {
+        if ((*p_omask & 0x0000000f) == 0x4) {
+                /* 64 bits memory mapping */
+                return;
+        }
 
-		config->assigned[reg] = 0x00000000;
-		config->sizes[reg] = 0x00000000;
+        config->regions[reg] = pci_config_read32(addr, config_addr);
 
-		if ((omask & 0x0000000f) == 0x4) {
-			/* 64 bits memory mapping */
-			continue;
-		}
+        /* get region size */
 
-		if (reg == 6)
-			config_addr = PCI_ROM_ADDRESS;
-		else
-			config_addr = PCI_BASE_ADDR_0 + reg * 4;
+        pci_config_write32(addr, config_addr, 0xffffffff);
+        smask = pci_config_read32(addr, config_addr);
+        if (smask == 0x00000000 || smask == 0xffffffff)
+                return;
 
-		config->regions[reg] = pci_config_read32(addr, config_addr);
+        if (smask & 0x00000001 && reg != 6) {
+                /* I/O space */
+                base = *io_base;
+                min_align = 1 << 7;
+                amask = 0x00000001;
+                pci_config_write16(addr, PCI_COMMAND,
+                                   pci_config_read16(addr,
+                                                     PCI_COMMAND) |
+                                   PCI_COMMAND_IO);
+        } else {
+                /* Memory Space */
+                base = *mem_base;
+                min_align = 1 << 16;
+                amask = 0x0000000F;
+                if (reg == 6) {
+                        smask |= 1; /* ROM */
+                }
+                pci_config_write16(addr, PCI_COMMAND,
+                                   pci_config_read16(addr,
+                                                     PCI_COMMAND) |
+                                   PCI_COMMAND_MEMORY);
+        }
+        *p_omask = smask & amask;
+        smask &= ~amask;
+        size = (~smask) + 1;
+        config->sizes[reg] = size;
+        reloc = base;
+        if (size < min_align)
+                size = min_align;
+        reloc = (reloc + size -1) & ~(size - 1);
+        if (*io_base == base) {
+                *io_base = reloc + size;
+                reloc -= arch->io_base;
+        } else {
+                *mem_base = reloc + size;
+        }
+        pci_config_write32(addr, config_addr, reloc | *p_omask);
+        config->assigned[reg] = reloc | *p_omask;
+}
 
-		/* get region size */
+static void ob_pci_configure_irq(pci_addr addr, pci_config_t *config)
+{
+        uint8_t irq_pin, irq_line;
 
-		pci_config_write32(addr, config_addr, 0xffffffff);
-		smask = pci_config_read32(addr, config_addr);
-		if (smask == 0x00000000 || smask == 0xffffffff)
-			continue;
+        irq_pin =  pci_config_read8(addr, PCI_INTERRUPT_PIN);
+        if (irq_pin) {
+                config->irq_pin = irq_pin;
+                irq_pin = (((config->dev >> 11) & 0x1F) + irq_pin - 1) & 3;
+                irq_line = arch->irqs[irq_pin];
+                pci_config_write8(addr, PCI_INTERRUPT_LINE, irq_line);
+                config->irq_line = irq_line;
+        } else
+                config->irq_line = -1;
+}
 
-		if (smask & 0x00000001 && reg != 6) {
-			/* I/O space */
-			base = *io_base;
-			min_align = 1 << 7;
-			amask = 0x00000001;
-			pci_config_write16(addr, PCI_COMMAND,
-					   pci_config_read16(addr,
-					   		     PCI_COMMAND) |
-							     PCI_COMMAND_IO);
-		} else {
-			/* Memory Space */
-			base = *mem_base;
-			min_align = 1 << 16;
-			amask = 0x0000000F;
-			if (reg == 6) {
-				smask |= 1; /* ROM */
-			}
-			pci_config_write16(addr, PCI_COMMAND,
-					   pci_config_read16(addr,
-					   		    PCI_COMMAND) |
-							    PCI_COMMAND_MEMORY);
-		}
-		omask = smask & amask;
-		smask &= ~amask;
-		size = (~smask) + 1;
-		config->sizes[reg] = size;
-		reloc = base;
-		if (size < min_align)
-			size = min_align;
-		reloc = (reloc + size -1) & ~(size - 1);
-		if (*io_base == base) {
-			*io_base = reloc + size;
-			reloc -= arch->io_base;
-		} else {
-			*mem_base = reloc + size;
-		}
-		pci_config_write32(addr, config_addr, reloc | omask);
-		config->assigned[reg] = reloc | omask;
-	}
+static void
+ob_pci_configure(pci_addr addr, pci_config_t *config, int num_regs, int rom_bar,
+                 unsigned long *mem_base, unsigned long *io_base)
+
+{
+        uint32_t omask;
+        int reg;
+        pci_addr config_addr;
+
+        ob_pci_configure_irq(addr, config);
+
+        omask = 0x00000000;
+        for (reg = 0; reg < num_regs; ++reg) {
+                config_addr = PCI_BASE_ADDR_0 + reg * 4;
+
+                ob_pci_configure_bar(addr, config, reg, config_addr,
+                                     &omask, mem_base,
+                                     io_base);
+        }
+
+        if (rom_bar) {
+                config_addr = rom_bar;
+                ob_pci_configure_bar(addr, config, reg, config_addr,
+                                     &omask, mem_base, io_base);
+        }
 }
 
 static void ob_scan_pci_bus(int bus, unsigned long *mem_base,
@@ -701,6 +722,7 @@
         const pci_dev_t *pci_dev;
 	uint32_t ccode;
 	uint8_t class, subclass, iface, rev;
+	int num_bars, rom_bar;
 
 	activate_device("/");
 	for (devnum = 0; devnum < 32; devnum++) {
@@ -754,9 +776,18 @@
 
 			activate_device(config.path);
 
-                        ob_pci_configure(addr, &config, mem_base, io_base);
-			ob_pci_add_properties(addr, pci_dev, &config);
+			if (htype & PCI_HEADER_TYPE_BRIDGE) {
+				num_bars = 2;
+				rom_bar  = PCI_ROM_ADDRESS1;
+			} else {
+				num_bars = 6;
+				rom_bar  = PCI_ROM_ADDRESS;
+			}
 
+			ob_pci_configure(addr, &config, num_bars, rom_bar,
+                                         mem_base, io_base);
+			ob_pci_add_properties(addr, pci_dev, &config, num_bars);
+
                         if (class == PCI_BASE_CLASS_BRIDGE &&
                             (subclass == PCI_SUBCLASS_BRIDGE_HOST ||
                              subclass == PCI_SUBCLASS_BRIDGE_PCI)) {

Modified: trunk/openbios-devel/drivers/pci.h
===================================================================
--- trunk/openbios-devel/drivers/pci.h	2009-07-11 12:20:20 UTC (rev 506)
+++ trunk/openbios-devel/drivers/pci.h	2009-07-11 12:23:24 UTC (rev 507)
@@ -48,6 +48,7 @@
 #define PCI_ROM_ADDRESS		0x30    /* Bits 31..11 are address, 10..1 reserved */
 #define PCI_ROM_ADDRESS_ENABLE	0x01
 #define PCI_ROM_ADDRESS_MASK	(~0x7ffUL)
+#define PCI_ROM_ADDRESS1	0x38    /* ROM_ADDRESS in bridge header */
 
 #define PCI_INTERRUPT_LINE      0x3c    /* 8 bits */
 #define PCI_INTERRUPT_PIN       0x3d    /* 8 bits */




More information about the OpenBIOS mailing list