>From 49bc5d322d26352945591c446643cd5275cd3189 Mon Sep 17 00:00:00 2001
From: Henry Zhao <[email protected]>
Date: Fri, 6 Apr 2012 16:52:42 -0700
Subject: [PATCH] libpciaccess: sparc rom read fix

Get rom address and size from device's "assigned-addresses" property
if they exist.

Signed-off-by: Henry Zhao <[email protected]>

---
 src/solx_devfs.c |  126 ++++++++++++++++++++++++++----------------------------
 1 files changed, 61 insertions(+), 65 deletions(-)

diff --git a/src/solx_devfs.c b/src/solx_devfs.c
index 2079df0..3cb824c 100644
--- a/src/solx_devfs.c
+++ b/src/solx_devfs.c
@@ -763,6 +763,8 @@ pci_device_solx_devfs_probe( struct pci_device * dev )
     int i;
     int len = 0;
     uint ent = 0;
+    struct pci_device_private *priv =
+	(struct pci_device_private *) dev;
     nexus_t *nexus;
 
 #ifdef __sparc
@@ -818,83 +820,70 @@ pci_device_solx_devfs_probe( struct pci_device * dev )
     if (len <= 0)
 	goto cleanup;
 
-
-    /*
-     * how to find the size of rom???
-     * if the device has expansion rom,
-     * it must be listed in the last
-     * cells because solaris find probe
-     * the base address from offset 0x10
-     * to 0x30h. So only check the last
-     * item.
-     */
-    reg = (pci_regspec_t *)&regbuf[len - CELL_NUMS_1275];
-    if (PCI_REG_REG_G(reg->pci_phys_hi) == PCI_CONF_ROM) {
-	/*
-	 * rom can only be 32 bits
-	 */
-	dev->rom_size = reg->pci_size_low;
-	len = len - CELL_NUMS_1275;
-    }
-    else {
-	/*
-	 * size default to 64K and base address
-	 * default to 0xC0000
-	 */
-	dev->rom_size = 0x10000;
-    }
-
     /*
-     * Solaris has its own BAR index.
+     * Each BAR address get its own region slot in sequence.
+     * 32 bit BAR:
+     * BAR 0x10 -> slot0, BAR 0x14 -> slot1...
+     * 64 bit BAR:
+     * BAR 0x10 -> slot0, BAR 0x18 -> slot2...,
+     * slot1 is part of BAR 0x10
      * Linux give two region slot for 64 bit address.
      */
     for (i = 0; i < len; i = i + CELL_NUMS_1275) {
 
 	reg = (pci_regspec_t *)&regbuf[i];
 	ent = reg->pci_phys_hi & 0xff;
+
+	if (ent > PCI_CONF_ROM) {
+		fprintf(stderr, "error ent = %d\n", ent);
+		break;
+	}
 	/*
 	 * G35 broken in BAR0
 	 */
-	ent = (ent - PCI_CONF_BASE0) >> 2;
-	if (ent >= 6) {
-	    fprintf(stderr, "error ent = %d\n", ent);
-	    break;
-	}
-
+	if (ent < PCI_CONF_BASE0) {
 	/*
-	 * non relocatable resource is excluded
-	 * such like 0xa0000, 0x3b0. If it is met,
-	 * the loop is broken;
-	 */
-	if (!PCI_REG_REG_G(reg->pci_phys_hi))
-	    break;
+	 * VGA resource here and ignore it
+	 */                                                             
+		break;
+	} else if (ent == PCI_CONF_ROM) {
+		priv->rom_base = reg->pci_phys_low |
+		    ((uint64_t)reg->pci_phys_mid << 32);
+		dev->rom_size = reg->pci_size_low; 
+	} else {
+		ent = (ent - PCI_CONF_BASE0) >> 2;
+		/*
+	 	 * non relocatable resource is excluded
+	 	 * such like 0xa0000, 0x3b0. If it is met,
+	 	 * the loop is broken;
+	 	 */
+		if (!PCI_REG_REG_G(reg->pci_phys_hi))
+	    	    break;
+
+		if (reg->pci_phys_hi & PCI_PREFETCH_B) {
+		    dev->regions[ent].is_prefetchable = 1;
+		}
 
-	if (reg->pci_phys_hi & PCI_PREFETCH_B) {
-	    dev->regions[ent].is_prefetchable = 1;
-	}
 
+		dev->regions[ent].base_addr = reg->pci_phys_low |
+	    	    ((uint64_t)reg->pci_phys_mid << 32);
+		dev->regions[ent].size = reg->pci_size_low |
+	    	    ((uint64_t)reg->pci_size_hi << 32);
+
+		switch (reg->pci_phys_hi & PCI_REG_ADDR_M) {
+	    	    case PCI_ADDR_IO:
+			dev->regions[ent].is_IO = 1;
+			break;
+	    	    case PCI_ADDR_MEM32:
+			break;
+		    case PCI_ADDR_MEM64:
+			dev->regions[ent].is_64 = 1;
+			/*
+		 	 * Skip one slot for 64 bit address
+		 	 */
+			break;
+		}
 
-	/*
-	 * We split the shift count 32 into two 16 to
-	 * avoid the complaining of the compiler
-	 */
-	dev->regions[ent].base_addr = reg->pci_phys_low +
-	    ((reg->pci_phys_mid << 16) << 16);
-	dev->regions[ent].size = reg->pci_size_low +
-	    ((reg->pci_size_hi << 16) << 16);
-
-	switch (reg->pci_phys_hi & PCI_REG_ADDR_M) {
-	    case PCI_ADDR_IO:
-		dev->regions[ent].is_IO = 1;
-		break;
-	    case PCI_ADDR_MEM32:
-		break;
-	    case PCI_ADDR_MEM64:
-		dev->regions[ent].is_64 = 1;
-		/*
-		 * Skip one slot for 64 bit address
-		 */
-		break;
 	}
     }
 
@@ -978,15 +967,22 @@ pci_device_solx_devfs_read_rom( struct pci_device * dev, void * buffer )
     int err;
     struct pci_device_mapping prom = {
 	.base = 0xC0000,
-	.size = dev->rom_size,
+	.size = 0x10000,
 	.flags = 0
     };
+    struct pci_device_private *priv =
+	(struct pci_device_private *) dev;
+
+    if (priv->rom_base) {
+	prom.base = priv->rom_base;
+	prom.size = dev->rom_size;
+    }
 
     err = pci_device_solx_devfs_map_range(dev, &prom);
     if (err == 0) {
 	(void) bcopy(prom.memory, buffer, dev->rom_size);
 
-	if (munmap(prom.memory, dev->rom_size) == -1) {
+	if (munmap(prom.memory, prom.size) == -1) {
 	    err = errno;
 	}
     }
-- 
1.5.6.5

_______________________________________________
[email protected]: X.Org development
Archives: http://lists.x.org/archives/xorg-devel
Info: http://lists.x.org/mailman/listinfo/xorg-devel

Reply via email to