changeset 1366:97946fc092d5

* src/pci.c : Additional changes in cyg_pci_get_device_info, cyg_pci_set_device_info and cyg_pci_configure_device to be able to support non-contiguous BARs.
author asl
date Wed, 19 Nov 2003 20:39:44 +0000
parents 1e45895acdfa
children c538173ceffb
files packages/io/pci/current/ChangeLog packages/io/pci/current/src/pci.c
diffstat 2 files changed, 34 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/packages/io/pci/current/ChangeLog
+++ b/packages/io/pci/current/ChangeLog
@@ -1,3 +1,9 @@
+2003-11-18  Manu Sharma  <manu.sharma@ascom.com>
+
+        * src/pci.c : Additional changes in cyg_pci_get_device_info, 
+        cyg_pci_set_device_info and cyg_pci_configure_device to be able
+        to support non-contiguous BARs.
+
 2003-09-29  Nick Garnett  <nickg@balti.calivar.com>
 
 	* src/pci.c (cyg_pci_get_device_info): Removed check for inactive
--- a/packages/io/pci/current/src/pci.c
+++ b/packages/io/pci/current/src/pci.c
@@ -91,6 +91,7 @@ void
 cyg_pci_get_device_info ( cyg_pci_device_id devid, cyg_pci_device *dev_info )
 {
     int i;
+    unsigned char bar_count;
     cyg_uint8 bus = CYG_PCI_DEV_GET_BUS(devid);
     cyg_uint8 devfn = CYG_PCI_DEV_GET_DEVFN(devid);
     cyg_uint8 header_type;
@@ -138,6 +139,7 @@ cyg_pci_get_device_info ( cyg_pci_device
     // If device is disabled, probe BARs for sizes.
     if ((dev_info->command & CYG_PCI_CFG_COMMAND_ACTIVE) == 0) {
 
+        bar_count = 0;
         for (i = 0; i < dev_info->num_bars; i++){
             cyg_uint32 size;
 
@@ -150,6 +152,12 @@ cyg_pci_get_device_info ( cyg_pci_device
             dev_info->base_size[i] = size;
             dev_info->base_map[i] = 0xffffffff;
 
+	    // Increment BAR count only if it has valid entry. BARs may not
+            // be in contiguous locations. 
+	    if (size != 0) {
+                ++bar_count;
+	    }
+
             // Check for a 64bit memory region.
             if (CYG_PCI_CFG_BAR_SPACE_MEM == 
                 (size & CYG_PCI_CFG_BAR_SPACE_MASK)) {
@@ -161,17 +169,25 @@ cyg_pci_get_device_info ( cyg_pci_device
                 }
             }
         }
+        dev_info->num_bars = bar_count;
     } else {
 	// If the device is already configured. Fill in the base_map.
 	CYG_PCI_ADDRESS64 tmp_addr;
 	cyg_uint32 bar;
 
+        bar_count = 0;
         for (i = 0; i < dev_info->num_bars; i++){
 
 	    dev_info->base_size[i] = 0;
 
             bar = dev_info->base_address[i];
 
+	    // Increment BAR count only if it has valid entry. BARs may not
+            // be in contiguous locations. 
+	    if (bar != 0) {
+                ++bar_count;
+	    }
+
 	    if ((bar & CYG_PCI_CFG_BAR_SPACE_MASK) == CYG_PCI_CFG_BAR_SPACE_IO) {
 		dev_info->base_map[i] = (bar & CYG_PRI_CFG_BAR_IO_MASK) + HAL_PCI_PHYSICAL_IO_BASE;
 		bar &= CYG_PRI_CFG_BAR_IO_MASK;
@@ -203,6 +219,7 @@ cyg_pci_get_device_info ( cyg_pci_device
 		    dev_info->base_map[++i] = tmp_addr >> 32;
 	    }
         }
+        dev_info->num_bars = bar_count;
     }
             
 
@@ -296,9 +313,13 @@ cyg_pci_set_device_info ( cyg_pci_device
     cyg_pcihw_write_config_uint8(bus, devfn, CYG_PCI_CFG_BIST,
                                  dev_info->bist);
 
-    for (i = 0; i < dev_info->num_bars; i++) {
-	cyg_pcihw_write_config_uint32(bus, devfn, CYG_PCI_CFG_BAR_BASE+4*i,
-				      dev_info->base_address[i]);
+    // Check for all possible BARs because they may be non-contiguous
+    for (i = 0; i < CYG_PCI_MAX_BAR; i++) {
+        if (dev_info->base_address[i]) {
+	    cyg_pcihw_write_config_uint32 (bus, devfn, 
+                                           CYG_PCI_CFG_BAR_BASE+4*i,
+				           dev_info->base_address[i]);
+        }
     }
 
     switch (dev_info->header_type & CYG_PCI_CFG_HEADER_TYPE_MASK) {
@@ -630,7 +651,10 @@ cyg_pci_configure_device( cyg_pci_device
 	return true;
 
     if (dev_info->num_bars > 0) {
-	for (bar = 0; bar < dev_info->num_bars; bar++) {
+        for (bar = 0; bar < CYG_PCI_MAX_BAR; bar++) {
+            if (!dev_info->base_address[bar]) {
+                continue;
+            }
 	    flags = dev_info->base_size[bar];
 
 	    ret = false;