-Tinkered with formatting
authoradar <adar>
Fri, 27 May 2005 13:52:47 +0000 (13:52 +0000)
committeradar <adar>
Fri, 27 May 2005 13:52:47 +0000 (13:52 +0000)
-Added resource.h for specifying resource ranges
-Added BAR code to PCI

src/devices/pci.c
src/devices/pci.h
src/devices/resource.h [new file with mode: 0644]
src/devices/usb.c
src/devices/usb.h

index 066588470dae91759e4cb16349c6873b46df7f9f..8097c346c5d7888578824f6cb948458d7399bed4 100755 (executable)
@@ -23,14 +23,111 @@ pci_read_config (unsigned bus, unsigned dev, unsigned func, unsigned reg)
   return inl (0xcfc);
 }
 
+static void
+pci_write_config (unsigned bus, unsigned dev, unsigned func, unsigned reg, 
+                 unsigned data)
+{
+  ASSERT (bus < 256);
+  ASSERT (dev < 32);
+  ASSERT (func < 8);
+  ASSERT (reg < 64);
+
+  outl (0xcf8,
+        0x80000000 | (bus << 16) | (dev << 11) | (func << 8) | (reg << 2));
+  outl (0xcfc, data);
+}
+
 static void
 pci_dump_dev (struct pci_dev *dev) 
 {
-  printf ("%04x:%02x:%02x.%x PCI device %04x:%04x\n", 
+  int bar;
+
+  printf ("PCI: Device %04x:%02x:%02x.%x %04x:%04x\n", 
          0, dev->bus_id, dev->devfn >> 4, dev->devfn & 0xf, 
          dev->ven_id, dev->dev_id);
-  printf ("Class: %02x:%02x:%02x\n", 
+  printf ("PCI: Class %02x:%02x:%02x\n", 
          dev->base_class, dev->sub_class, dev->interface);
+
+  for (bar = 0; bar < PCI_NUM_BARS; bar++)
+    {
+      if (dev->resources[bar].start != 0 ||
+         dev->resources[bar].end != 0)
+       {
+         printf ("PCI: %s ", 
+                 dev->resources[bar].type == PCI_BAR_TYPE_MEM 
+                 ? "Memory" : "IO");
+         printf ("range %d: %08x-%08x\n", 
+                 bar, dev->resources[bar].start, dev->resources[bar].end);
+       }
+    }
+}
+
+static void
+pci_setup_bases (struct pci_dev *dev) 
+{
+  int bar;
+  unsigned bar_reg;
+  uint32_t base, size;
+  struct resource *res;
+
+  for (bar = 0; bar < PCI_NUM_BARS; bar++)
+    {
+      bar_reg = PCI_REGNUM_BASE_ADDRESS + bar;
+
+      res = &dev->resources[bar];
+      res->start = 0;
+      res->end = 0;
+      
+      /* Get the base address out of the BAR */
+      base = pci_read_config(dev->bus_id,
+                            dev->devfn >> 4, 
+                            dev->devfn & 0xf, 
+                            bar_reg);
+
+      /* Write 1's and get the size from the BAR */
+      pci_write_config(dev->bus_id, 
+                      dev->devfn >> 4, 
+                      dev->devfn & 0xf, 
+                      bar_reg,
+                      ~0);
+      size = pci_read_config(dev->bus_id, 
+                            dev->devfn >> 4, 
+                            dev->devfn & 0xf, 
+                            bar_reg);
+
+      /* Put the base address back in the BAR */
+      pci_write_config(dev->bus_id, 
+                      dev->devfn >> 4, 
+                      dev->devfn & 0xf, 
+                      bar_reg,
+                      base);
+
+      /* If the size is unreasonable, skip this BAR.
+         Is this redundant for Pintos? */
+      if (!size || size == 0xffffffff) {
+       continue;
+      }
+
+      /* Broken hardware that requests a base at the end? 
+        Maybe redundant for Pintos? */
+      if (base == 0xffffffff) {
+       base = 0;
+      }
+
+      /* Make a new resource, tag it for I/O vs. memory */
+      res->type = base & PCI_BAR_TYPE_MASK;
+      if (res->type == PCI_BAR_TYPE_MEM) 
+       {
+         res->start = base & PCI_BAR_MASK_MEM;
+         size = size & PCI_BAR_MASK_MEM;
+       }
+      else
+       {
+         res->start = base & PCI_BAR_MASK_IO;
+         size = size & PCI_BAR_MASK_IO;
+       }
+      res->end = res->start + size;
+    }
 }
 
 static bool
@@ -70,26 +167,36 @@ scan_device (uint8_t bus, uint8_t dev, uint8_t func)
   new_pci_dev->sub_class = byte_cfg[PCI_REG_CLASS_SUB];
   new_pci_dev->interface = byte_cfg[PCI_REG_CLASS_INTERFACE];
   list_push_front (&pci_dev_list, &new_pci_dev->elem);
-  
+    
+  /* If device is PCI-to-PCI bridge, scan the bus behind it */
+  if (new_pci_dev->base_class == PCI_BRIDGE_BASE_CLASS &&
+      new_pci_dev->sub_class == PCI_BRIDGE_SUB_CLASS &&
+      (byte_cfg[PCI_REG_HEADER_TYPE] & 0x3f) == PCI_BRIDGE_HEADER_TYPE)
+    {
+      scan_bus(byte_cfg[PCI_BRIDGE_REG_SBUS]);
+    }
+
+  /* For normal devices, set up the BARs */
+  else 
+    {
+      pci_setup_bases (new_pci_dev);
+    }
+
   /* Debugging output */
   pci_dump_dev(new_pci_dev);
-  for (line = 0; line < 16; line++) 
+  /*for (line = 0; line < 16; line++) 
     {
       int byte;
       
-      printf ("%02x:", line * 4);
+      printf ("PCI: %02x:", line * 4);
       for (byte = 3; byte >= 0; byte--)
        printf (" %02x", byte_cfg[line * 4 + byte]);
       printf ("\n");
-    }
+      }*/
   printf ("\n");
+
   
-  /* If device is PCI-to-PCI bridge, scan the bus behind it */
-  if (new_pci_dev->base_class == PCI_BRIDGE_BASE_CLASS &&
-      new_pci_dev->sub_class == PCI_BRIDGE_SUB_CLASS &&
-      (byte_cfg[PCI_REG_HEADER_TYPE] & 0x3f) == PCI_BRIDGE_HEADER_TYPE)
-    scan_bus(byte_cfg[PCI_BRIDGE_REG_SBUS]);
-  
+  /* Return if we're a multifunction device */
   return byte_cfg[PCI_REG_HEADER_TYPE] & 0x80;
 }
 
@@ -99,6 +206,7 @@ scan_bus(uint8_t bus)
   uint8_t dev;
 
   printf ("PCI: Scanning bus (%u)\n", bus);
+  printf ("\n");
 
   for (dev = 0; dev < 32; dev++) 
     {
@@ -112,11 +220,13 @@ scan_bus(uint8_t bus)
         }
     }
   printf ("PCI: Done (%u)\n", bus);
+  printf ("\n");
 }
 
 void
 pci_init (void) 
 {
+  printf ("\n");
   printf ("PCI: Initializating\n");
   list_init (&pci_dev_list);
   scan_bus(0);  
index 9a7e4da99181a8c0d174b515473a5765d9dedc87..a66ac76f14718aaa8ac6bf954399509040e14492 100755 (executable)
@@ -1,6 +1,34 @@
+#ifndef DEVICES_PCI_H
+#define DEVICES_PCI_H
+
+#include "devices/resource.h"
 #include "lib/kernel/list.h"
 
-struct pci_dev {
+#define PCI_BAD_DEVICE 0xffff
+
+/* PCI-to-PCI bridge related numbers */
+#define PCI_BRIDGE_BASE_CLASS 0x06
+#define PCI_BRIDGE_SUB_CLASS 0x04
+#define PCI_BRIDGE_REG_SBUS 0x19
+#define PCI_BRIDGE_HEADER_TYPE 0x01
+
+/* Locations of registers in the configuration space */
+#define PCI_REG_CLASS_INTERFACE 0x09
+#define PCI_REG_CLASS_SUB 0x0a
+#define PCI_REG_CLASS_BASE 0x0b
+#define PCI_REG_HEADER_TYPE 0x0e
+#define PCI_REGNUM_BASE_ADDRESS 4
+
+/* Base address related numbers */
+#define PCI_NUM_BARS 6
+#define PCI_BAR_TYPE_MASK 0x1
+#define PCI_BAR_TYPE_MEM 0x0
+#define PCI_BAR_TYPE_IO 0x1
+#define PCI_BAR_MASK_MEM 0xfffffff0
+#define PCI_BAR_MASK_IO 0xfffffffc
+
+struct pci_dev 
+{
   struct list_elem elem;
 
   /* <Bus, Device, Function> logically identify a unique PCI device */
@@ -15,21 +43,12 @@ struct pci_dev {
   uint8_t base_class;
   uint8_t sub_class;
   uint8_t interface;
-};
 
-#define PCI_BAD_DEVICE 0xffff
-
-/* PCI-to-PCI bridge related numbers */
-#define PCI_BRIDGE_BASE_CLASS 0x06
-#define PCI_BRIDGE_SUB_CLASS 0x04
-#define PCI_BRIDGE_REG_SBUS 0x19
-#define PCI_BRIDGE_HEADER_TYPE 0x01
-
-/* Locations of registers in the typical configuration space */
-#define PCI_REG_CLASS_INTERFACE 0x09
-#define PCI_REG_CLASS_SUB 0x0a
-#define PCI_REG_CLASS_BASE 0x0b
-#define PCI_REG_HEADER_TYPE 0x0e
+  /* Resource space */
+  struct resource resources[PCI_NUM_BARS];
+};
 
 void pci_init (void);
 void pci_dump (void);
+
+#endif /* devices/pci.h */
diff --git a/src/devices/resource.h b/src/devices/resource.h
new file mode 100644 (file)
index 0000000..41e8224
--- /dev/null
@@ -0,0 +1,14 @@
+#ifndef DEVICE_RESOURCE_H
+#define DEVICE_RESOURCE_H
+
+struct resource
+{
+  uint32_t start;
+  uint32_t end;
+  uint8_t type;
+};
+
+#define RESOURCE_TYPE_MEM 0x0
+#define RESOURCE_TYPE_IO 0x1
+
+#endif /* device/resource.h */
index df4ead0cd87e208955ed11f174dd92795720683d..faca88bd04fb6bb62bb0f1b338d524738575b717 100644 (file)
@@ -7,6 +7,7 @@ extern struct list pci_dev_list;
 
 void usb_init(void)
 {
+  printf ("\n");
   printf ("USB: Initializing\n");
 
   /* Scan PCI devices for USB controllers */
@@ -25,4 +26,5 @@ void usb_init(void)
        }
     }
   printf ("USB: Initialization done\n");
+  printf ("\n");
 }
index 7e6429aef9fba6f4784dc529e26630c53b536ca7..dde4cc725b5af76c31a2386772cc96b044bd4c65 100644 (file)
@@ -1,4 +1,9 @@
+#ifndef DEVICES_USB_H
+#define DEVICES_USB_H
+
 #define USB_BASE_CLASS 0x0c
 #define USB_SUB_CLASS 0x03
 
 void usb_init(void);
+
+#endif /* devices/usb.h */