summaryrefslogtreecommitdiff
path: root/src/devices/pci_device.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/pci_device.c')
-rw-r--r--src/devices/pci_device.c80
1 files changed, 72 insertions, 8 deletions
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 2b309a9ae1..dd24bac072 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -13,9 +13,10 @@
#include <stdlib.h>
#include <stdint.h>
#include <bitops.h>
-#include <pci.h>
-#include <pci_ids.h>
#include <string.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
static unsigned int pci_scan_bridge(struct device *bus, unsigned int max);
@@ -219,7 +220,7 @@ static void pci_bridge_read_bases(struct device *dev)
}
-static void pci_dev_read_resources(struct device *dev)
+void pci_dev_read_resources(struct device *dev)
{
uint32_t addr;
dev->resources = 0;
@@ -229,7 +230,7 @@ static void pci_dev_read_resources(struct device *dev)
dev->rom_address = (addr == 0xffffffff)? 0 : addr;
}
-static void pci_bus_read_resources(struct device *dev)
+void pci_bus_read_resources(struct device *dev)
{
uint32_t addr;
dev->resources = 0;
@@ -345,7 +346,7 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
return;
}
-static void pci_dev_set_resources(struct device *dev)
+void pci_dev_set_resources(struct device *dev)
{
struct resource *resource, *last;
uint8_t line;
@@ -399,9 +400,16 @@ static void set_pci_ops(struct device *dev)
*/
for(driver = &pci_drivers[0]; driver != &epci_drivers[0]; driver++) {
if ((driver->vendor == dev->vendor) &&
- (driver->device = dev->device)) {
+ (driver->device == dev->device)) {
dev->ops = driver->ops;
- break;
+#if 1
+ printk_debug("PCI: %02x:%02x.%01x [%04x/%04x] ops\n",
+ dev->bus->secondary,
+ PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn),
+ driver->vendor, driver->device
+ );
+#endif
+ return;
}
}
/* If I don't have a specific driver use the default operations */
@@ -450,6 +458,7 @@ static struct device *pci_scan_get_dev(struct device **list, unsigned int devfn)
}
+#define HYPERTRANSPORT_SUPPORT 1
/** Scan the pci bus devices and bridges.
* @param pci_bus pointer to the bus structure
* @param max current bus number
@@ -461,6 +470,9 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
struct device *dev, **bus_last;
struct device *old_devices;
struct device *child;
+#if HYPERTRANSPORT_SUPPORT
+ unsigned next_unitid, last_unitid;
+#endif
printk_debug("PCI: pci_scan_bus for bus %d\n", bus->secondary);
@@ -471,6 +483,58 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
post_code(0x24);
+#if HYPERTRANSPORT_SUPPORT
+ /* If present assign unitid to a hypertransport chain */
+ next_unitid = 1;
+ do {
+ struct device dummy;
+ uint32_t id;
+ uint8_t hdr_type, pos;
+ last_unitid = next_unitid;
+
+ dummy.bus = bus;
+ dummy.devfn = 0;
+ pci_read_config_dword(&dummy, PCI_VENDOR_ID, &id);
+ if (id == 0xffffffff || id == 0x00000000 ||
+ id == 0x0000ffff || id == 0xffff0000) {
+ break;
+ }
+ pci_read_config_byte(&dummy, PCI_HEADER_TYPE, &hdr_type);
+ pos = 0;
+ switch(hdr_type & 0x7f) {
+ case PCI_HEADER_TYPE_NORMAL:
+ case PCI_HEADER_TYPE_BRIDGE:
+ pos = PCI_CAPABILITY_LIST;
+ break;
+ }
+ if (pos > PCI_CAP_LIST_NEXT) {
+ pci_read_config_byte(&dummy, pos, &pos);
+ }
+ while(pos != 0) {
+ uint8_t cap;
+ pci_read_config_byte(&dummy, pos + PCI_CAP_LIST_ID, &cap);
+ printk_debug("Capability: 0x%02x @ 0x%02x\n", cap, pos);
+ if (cap == PCI_CAP_ID_HT) {
+ uint16_t flags;
+ pci_read_config_word(&dummy, pos + PCI_CAP_FLAGS, &flags);
+ printk_debug("flags: 0x%04x\n", (unsigned)flags);
+ if ((flags >> 13) == 0) {
+ unsigned count;
+ flags &= ~0x1f;
+ flags |= next_unitid & 0x1f;
+ count = (flags >> 5) & 0x1f;
+ printk_debug("unitid: 0x%02x, count: 0x%02x\n",
+ next_unitid, count);
+ pci_write_config_word(&dummy, pos + PCI_CAP_FLAGS, flags);
+ next_unitid += count;
+ break;
+ }
+ }
+ pci_read_config_byte(&dummy, pos + PCI_CAP_LIST_NEXT, &pos);
+ }
+ } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+#endif /* HYPERTRANSPORT_SUPPORT */
+
/* probe all devices on this bus with some optimization for non-existance and
single funcion devices */
for (devfn = 0; devfn < 0xff; devfn++) {
@@ -575,7 +639,7 @@ unsigned int pci_scan_bus(struct device *bus, unsigned int max)
* @param pci_bus pointer to the bus structure
* @return The maximum bus number found, after scanning all subordinate busses
*/
-static unsigned int pci_scan_bridge(struct device *bus, unsigned int max)
+unsigned int pci_scan_bridge(struct device *bus, unsigned int max)
{
uint32_t buses;
uint16_t cr;