From 0d59f33ca7a5512305b2ab099d91031e1b3e4e4c Mon Sep 17 00:00:00 2001 From: adar Date: Fri, 27 May 2005 13:52:47 +0000 Subject: [PATCH] -Tinkered with formatting -Added resource.h for specifying resource ranges -Added BAR code to PCI --- src/devices/pci.c | 134 +++++++++++++++++++++++++++++++++++++---- src/devices/pci.h | 49 ++++++++++----- src/devices/resource.h | 14 +++++ src/devices/usb.c | 2 + src/devices/usb.h | 5 ++ 5 files changed, 177 insertions(+), 27 deletions(-) create mode 100644 src/devices/resource.h 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); diff --git a/src/devices/pci.h b/src/devices/pci.h index 9a7e4da..a66ac76 100755 --- a/src/devices/pci.h +++ b/src/devices/pci.h @@ -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; /* 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 index 0000000..41e8224 --- /dev/null +++ b/src/devices/resource.h @@ -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 */ diff --git a/src/devices/usb.c b/src/devices/usb.c index df4ead0..faca88b 100644 --- a/src/devices/usb.c +++ b/src/devices/usb.c @@ -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"); } diff --git a/src/devices/usb.h b/src/devices/usb.h index 7e6429a..dde4cc7 100644 --- a/src/devices/usb.h +++ b/src/devices/usb.h @@ -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 */ -- 2.30.2