X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=src%2Fdevices%2Fpci.c;fp=src%2Fdevices%2Fpci.c;h=8097c346c5d7888578824f6cb948458d7399bed4;hb=0d59f33ca7a5512305b2ab099d91031e1b3e4e4c;hp=066588470dae91759e4cb16349c6873b46df7f9f;hpb=7a3b97675d95d666979d0b5fa0cae966f11ee188;p=pintos-anon diff --git a/src/devices/pci.c b/src/devices/pci.c index 0665884..8097c34 100755 --- a/src/devices/pci.c +++ b/src/devices/pci.c @@ -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);