-PCI scanning
authoradar <adar>
Thu, 26 May 2005 09:58:10 +0000 (09:58 +0000)
committeradar <adar>
Thu, 26 May 2005 09:58:10 +0000 (09:58 +0000)
-PCI scanning through PCI-to-PCI bridges
-Preliminary USB code
-Tiny changes to pintos script so it'll run better

src/Makefile.build
src/devices/pci.c
src/devices/pci.h
src/devices/usb.c [new file with mode: 0644]
src/devices/usb.h [new file with mode: 0644]
src/threads/init.c
src/utils/pintos

index 97edb71946ca272221f220301b52a3609f8857ac..f080aa2f6d2f3b118a7edfa98fac2ebc71d33202 100644 (file)
@@ -29,6 +29,7 @@ devices_SRC += devices/serial.c               # Serial port device.
 devices_SRC += devices/disk.c          # IDE disk device.
 devices_SRC += devices/intq.c          # Interrupt queue.
 devices_SRC += devices/pci.c            # PCI device.
+devices_SRC += devices/usb.c            # USB device.
 
 # Library code shared between kernel and user programs.
 lib_SRC  = lib/debug.c                 # Debug helpers.
index 1fac33c9b6733dae12a2722e9f4f066ea32f36c4..066588470dae91759e4cb16349c6873b46df7f9f 100755 (executable)
@@ -1,8 +1,14 @@
 #include <debug.h>
+#include <list.h>
 #include <stdbool.h>
 #include <stdio.h>
-#include "threads/io.h"
 #include "devices/pci.h"
+#include "threads/io.h"
+#include "threads/malloc.h"
+
+struct list pci_dev_list;
+
+static void scan_bus(uint8_t bus);
 
 static uint32_t
 pci_read_config (unsigned bus, unsigned dev, unsigned func, unsigned reg) 
@@ -17,56 +23,115 @@ pci_read_config (unsigned bus, unsigned dev, unsigned func, unsigned reg)
   return inl (0xcfc);
 }
 
+static void
+pci_dump_dev (struct pci_dev *dev) 
+{
+  printf ("%04x:%02x:%02x.%x PCI device %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", 
+         dev->base_class, dev->sub_class, dev->interface);
+}
+
 static bool
-scan_device (int bus, int dev, int func) 
+scan_device (uint8_t bus, uint8_t dev, uint8_t func) 
 {
   uint32_t cfg[16];
+  uint8_t *byte_cfg;
   int dev_id, vendor_id;
   int line;
   int reg;
+  struct pci_dev *new_pci_dev;
 
+  byte_cfg = (uint8_t *) cfg;
+
+  /* Read configuration space header */
   for (reg = 0; reg < 16; reg++)
     cfg[reg] = pci_read_config (bus, dev, func, reg);
+  
+  /* Get vendor and device ID */
   dev_id = cfg[0] >> 16;
   vendor_id = cfg[0] & 0xffff;
 
-  if (dev_id == 0 || dev_id == 0xffff
-      || vendor_id == 0 || vendor_id == 0xffff)
+  if (dev_id == 0 || dev_id == PCI_BAD_DEVICE || 
+      vendor_id == 0 || vendor_id == PCI_BAD_DEVICE)
     return 0;
 
-  printf ("%04x:%02x:%02x.%x PCI device %04x:%04x\n",
-          0, bus, dev, func, vendor_id, dev_id);
-  for (line = 0; line < 4; line++) 
+  /* We have a valid PCI device, set it up */
+  new_pci_dev = malloc (sizeof *new_pci_dev);
+  if (!new_pci_dev)
+    PANIC ("couldn't allocate memory for PCI device");
+
+  new_pci_dev->bus_id = bus;
+  new_pci_dev->devfn = (dev << 4) | func;
+  new_pci_dev->ven_id = vendor_id;
+  new_pci_dev->dev_id = dev_id;
+  new_pci_dev->base_class = byte_cfg[PCI_REG_CLASS_BASE];
+  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);
+  
+  /* Debugging output */
+  pci_dump_dev(new_pci_dev);
+  for (line = 0; line < 16; line++) 
     {
       int byte;
-
-      printf ("%02x:", line * 16);
-      for (byte = 0; byte < 16; byte++)
-        printf (" %02x", ((uint8_t *) cfg)[line * 16 + byte]);
+      
+      printf ("%02x:", line * 4);
+      for (byte = 3; byte >= 0; byte--)
+       printf (" %02x", byte_cfg[line * 4 + byte]);
       printf ("\n");
     }
   printf ("\n");
-
-  return cfg[3] & 0x00800000;
+  
+  /* 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 byte_cfg[PCI_REG_HEADER_TYPE] & 0x80;
 }
 
-void
-pci_scan (void) 
+static void
+scan_bus(uint8_t bus)
 {
-  int dev;
+  uint8_t dev;
+
+  printf ("PCI: Scanning bus (%u)\n", bus);
 
-  printf ("PCI BUS: Scanning \n");
-  
   for (dev = 0; dev < 32; dev++) 
     {
-      if (scan_device (0, dev, 0)) 
+      /* Returns true if device is multi-function */
+      if (scan_device (bus, dev, 0)) 
         {
           int func;
 
           for (func = 1; func < 8; func++)
-            scan_device (0, dev, func);
+            scan_device (bus, dev, func);
         }
     }
+  printf ("PCI: Done (%u)\n", bus);
+}
+
+void
+pci_init (void) 
+{
+  printf ("PCI: Initializating\n");
+  list_init (&pci_dev_list);
+  scan_bus(0);  
+  printf ("PCI: Initialization done\n");
+}
 
-  printf ("PCI BUS: Done \n");
+void
+pci_dump (void)
+{
+  struct list_elem *e;
+
+  for (e = list_begin (&pci_dev_list); e != list_end (&pci_dev_list);
+       e = list_next (e))
+    {
+      struct pci_dev *dev = list_entry (e, struct pci_dev, elem);
+      pci_dump_dev(dev);
+    }
 }
index 58fe4ea3cb22f43e58458f7c9bfb2b624d1c4fcd..9a7e4da99181a8c0d174b515473a5765d9dedc87 100755 (executable)
@@ -1 +1,35 @@
-void pci_scan (void);
+#include "lib/kernel/list.h"
+
+struct pci_dev {
+  struct list_elem elem;
+
+  /* <Bus, Device, Function> logically identify a unique PCI device */
+  uint8_t bus_id;
+  uint8_t devfn;
+
+  /* Vendor and Device ID */
+  uint16_t ven_id;
+  uint16_t dev_id;
+
+  /* Class code */
+  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
+
+void pci_init (void);
+void pci_dump (void);
diff --git a/src/devices/usb.c b/src/devices/usb.c
new file mode 100644 (file)
index 0000000..df4ead0
--- /dev/null
@@ -0,0 +1,28 @@
+#include <list.h>
+#include <stdio.h>
+#include "devices/pci.h"
+#include "devices/usb.h"
+
+extern struct list pci_dev_list;
+
+void usb_init(void)
+{
+  printf ("USB: Initializing\n");
+
+  /* Scan PCI devices for USB controllers */
+  struct list_elem *e;
+
+  for (e = list_begin (&pci_dev_list); e != list_end (&pci_dev_list);
+       e = list_next (e))
+    {
+      struct pci_dev *dev = list_entry (e, struct pci_dev, elem);
+
+      if (dev->base_class == USB_BASE_CLASS &&
+         dev->sub_class == USB_SUB_CLASS)
+       {
+         printf ("USB: Found controller at %04x:%02x:%02x.%x\n",
+                 0, dev->bus_id, dev->devfn >> 4, dev->devfn & 0xf);
+       }
+    }
+  printf ("USB: Initialization done\n");
+}
diff --git a/src/devices/usb.h b/src/devices/usb.h
new file mode 100644 (file)
index 0000000..7e6429a
--- /dev/null
@@ -0,0 +1,4 @@
+#define USB_BASE_CLASS 0x0c
+#define USB_SUB_CLASS 0x03
+
+void usb_init(void);
index 4d1aee8931dfcfbec1a926ef80cc75a09f2210c3..d8a609d071f2f0f266d5e87b210e2daa7281a112 100644 (file)
@@ -9,8 +9,10 @@
 #include <stdlib.h>
 #include <string.h>
 #include "devices/kbd.h"
+#include "devices/pci.h"
 #include "devices/serial.h"
 #include "devices/timer.h"
+#include "devices/usb.h"
 #include "devices/vga.h"
 #include "threads/interrupt.h"
 #include "threads/io.h"
@@ -28,7 +30,6 @@
 #include "userprog/tss.h"
 #endif
 #ifdef FILESYS
-#include "devices/pci.h"
 #include "devices/disk.h"
 #include "filesys/filesys.h"
 #include "filesys/fsutil.h"
@@ -110,6 +111,13 @@ main (void)
   intr_init ();
   timer_init ();
   kbd_init ();
+
+  /* Initialize PCI devices */
+  pci_init ();
+
+  /* Initialize USB controllers */
+  usb_init ();
+
 #ifdef USERPROG
   exception_init ();
   syscall_init ();
@@ -121,8 +129,6 @@ main (void)
   timer_calibrate ();
 
 #ifdef FILESYS
-  pci_scan ();
-
   /* Initialize filesystem. */
   disk_init ();
   filesys_init (format_filesys);
index 40a240ce974a66c0d590597be4bed25bed0e52dd..47fdb3ff73c307b15d9ee512ae50481c702215f1 100755 (executable)
@@ -327,8 +327,8 @@ sub run_vm {
        print VMX "serial0.fileName = \"pintos.out\"\n";
 
        if (! -e 'null.bin') {
-           open (NULL, ">null.bin") or die "null.bin: create: $!\n";
-           close (NULL);
+           open (NULLY, ">null.bin") or die "null.bin: create: $!\n";
+           close (NULLY);
        }
 
        for (my ($i) = 0; $i < 4; $i++) {