From: adar Date: Thu, 26 May 2005 09:58:10 +0000 (+0000) Subject: -PCI scanning X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?p=pintos-anon;a=commitdiff_plain;h=7a3b97675d95d666979d0b5fa0cae966f11ee188 -PCI scanning -PCI scanning through PCI-to-PCI bridges -Preliminary USB code -Tiny changes to pintos script so it'll run better --- diff --git a/src/Makefile.build b/src/Makefile.build index 97edb71..f080aa2 100644 --- a/src/Makefile.build +++ b/src/Makefile.build @@ -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. diff --git a/src/devices/pci.c b/src/devices/pci.c index 1fac33c..0665884 100755 --- a/src/devices/pci.c +++ b/src/devices/pci.c @@ -1,8 +1,14 @@ #include +#include #include #include -#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); + } } diff --git a/src/devices/pci.h b/src/devices/pci.h index 58fe4ea..9a7e4da 100755 --- a/src/devices/pci.h +++ b/src/devices/pci.h @@ -1 +1,35 @@ -void pci_scan (void); +#include "lib/kernel/list.h" + +struct pci_dev { + struct list_elem elem; + + /* 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 index 0000000..df4ead0 --- /dev/null +++ b/src/devices/usb.c @@ -0,0 +1,28 @@ +#include +#include +#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 index 0000000..7e6429a --- /dev/null +++ b/src/devices/usb.h @@ -0,0 +1,4 @@ +#define USB_BASE_CLASS 0x0c +#define USB_SUB_CLASS 0x03 + +void usb_init(void); diff --git a/src/threads/init.c b/src/threads/init.c index 4d1aee8..d8a609d 100644 --- a/src/threads/init.c +++ b/src/threads/init.c @@ -9,8 +9,10 @@ #include #include #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); diff --git a/src/utils/pintos b/src/utils/pintos index 40a240c..47fdb3f 100755 --- a/src/utils/pintos +++ b/src/utils/pintos @@ -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++) {