X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdevices%2Fpci.c;h=066588470dae91759e4cb16349c6873b46df7f9f;hb=7a3b97675d95d666979d0b5fa0cae966f11ee188;hp=1fac33c9b6733dae12a2722e9f4f066ea32f36c4;hpb=c2edf1dc3e9a634fb7c68519d6cb6534a129e5b1;p=pintos-anon 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); + } }