From e9d467b3917e60b4523fcaa22f7bb6abaff7845d Mon Sep 17 00:00:00 2001 From: Joshua Wise Date: Thu, 2 Oct 2008 18:25:40 -0400 Subject: [PATCH] Add a 'pci_driver' probe function. --- aseg/3c905.c | 4 +- include/pci.h | 20 ++++++++- pci/pci.c | 111 ++++++++++++++++++++++++++++++-------------------- 3 files changed, 86 insertions(+), 49 deletions(-) diff --git a/aseg/3c905.c b/aseg/3c905.c index 82ad695..b89abe2 100644 --- a/aseg/3c905.c +++ b/aseg/3c905.c @@ -4,7 +4,7 @@ static int found = 0, _bus, _dev, _fn; -static int bother_3c905(pci_dev_t *dev) +static int bother_3c905(pci_dev_t *dev, void *nutrinus) { if (dev->vid == 0x10B7 || dev->did == 0x9200) { @@ -32,5 +32,5 @@ void eth_poll() void eth_init() { - pci_probe(bother_3c905); + pci_probe(bother_3c905, 0x0); } diff --git a/include/pci.h b/include/pci.h index 313b3e0..9f7e6b9 100644 --- a/include/pci.h +++ b/include/pci.h @@ -36,9 +36,25 @@ typedef struct pci_dev { pci_bar_t bars[6]; } pci_dev_t; -typedef int (*pci_probe_fn_t)(pci_dev_t *); +typedef int (*pci_probe_fn_t)(pci_dev_t *, void *data); void pci_bus_enum(); -int pci_probe(pci_probe_fn_t probe); +int pci_probe(pci_probe_fn_t probe, void *data); + +typedef struct pci_id { + unsigned short vid, did; + const char *name, *friendlyname; +} pci_id_t; + +#define PCI_ROM(a,b,c,d) {(a),(b),(c),(d)} + +typedef struct pci_driver { + const char *name; + pci_probe_fn_t probe; + pci_id_t *ids; + int id_count; +} pci_driver_t; + +int pci_probe_driver(pci_driver_t driver); #endif diff --git a/pci/pci.c b/pci/pci.c index e5ab816..c7385de 100644 --- a/pci/pci.c +++ b/pci/pci.c @@ -1,7 +1,7 @@ #include #include -int pci_probe(pci_probe_fn_t probe) +int pci_probe(pci_probe_fn_t probe, void *data) { int devsfound = 0; pci_dev_t pdev; @@ -11,62 +11,65 @@ int pci_probe(pci_probe_fn_t probe) for (bus = 0; bus < 0x100; bus++) for (dev = 0; dev < 0x20; dev++) - if (pci_read32(bus, dev, 0, 0) != 0xFFFFFFFF) - for (fn = 0; fn < 8; fn++) + { + if (pci_read32(bus, dev, 0, 0) == 0xFFFFFFFF) + continue; + for (fn = 0; fn < 8; fn++) + { + int bar; + + if (pci_read32(bus, dev, fn, 0) == 0xFFFFFFFF) + continue; + + if ((fn != 0) && !(pci_read8(bus, dev, 0, 0x0E) & 0x80)) + continue; + + pdev.bus = bus; + pdev.dev = dev; + pdev.fn = fn; + pdev.vid = pci_read16(bus, dev, fn, 0); + pdev.did = pci_read16(bus, dev, fn, 2); + + for (bar = 0; bar < 6; bar++) { - int bar; - - if (pci_read32(bus, dev, fn, 0) == 0xFFFFFFFF) - continue; - - if ((fn != 0) && !(pci_read8(bus, dev, 0, 0x0E) & 0x80)) + unsigned long bardat = pci_read32(bus, dev, fn, 0x10 + bar*4); + if (bardat == 0) + { + pdev.bars[bar].type = PCI_BAR_NONE; continue; - - pdev.bus = bus; - pdev.dev = dev; - pdev.fn = fn; - pdev.vid = pci_read16(bus, dev, fn, 0); - pdev.did = pci_read16(bus, dev, fn, 2); - - for (bar = 0; bar < 6; bar++) + } + if (bardat & 1) { - unsigned long bardat = pci_read32(bus, dev, fn, 0x10 + bar*4); - if (bardat == 0) + pdev.bars[bar].type = PCI_BAR_IO; + pdev.bars[bar].addr = bardat & ~0x3; + } else { + pdev.bars[bar].prefetchable = (bardat >> 3) & 1; + switch ((bardat >> 1) & 0x3) { + case 0: + pdev.bars[bar].type = PCI_BAR_MEMORY32; + pdev.bars[bar].addr = bardat & ~0xF; + break; + case 2: + pdev.bars[bar].type = PCI_BAR_MEMORY64; + bar++; + pdev.bars[bar].type = PCI_BAR_NONE; + break; + default: pdev.bars[bar].type = PCI_BAR_NONE; continue; } - if (bardat & 1) - { - pdev.bars[bar].type = PCI_BAR_IO; - pdev.bars[bar].addr = bardat & ~0x3; - } else { - pdev.bars[bar].prefetchable = (bardat >> 3) & 1; - switch ((bardat >> 1) & 0x3) - { - case 0: - pdev.bars[bar].type = PCI_BAR_MEMORY32; - pdev.bars[bar].addr = bardat & ~0xF; - break; - case 2: - pdev.bars[bar].type = PCI_BAR_MEMORY64; - bar++; - pdev.bars[bar].type = PCI_BAR_NONE; - break; - default: - pdev.bars[bar].type = PCI_BAR_NONE; - continue; - } - } } - - devsfound += probe(&pdev); } + + devsfound += probe(&pdev, data); + } + } return devsfound; } -static int _enumfn(pci_dev_t *pdev) +static int _enumfn(pci_dev_t *pdev, void *data) { int bar; @@ -95,6 +98,24 @@ static int _enumfn(pci_dev_t *pdev) void pci_bus_enum() { - pci_probe(_enumfn); + pci_probe(_enumfn, 0x0); } +static int _probefn(pci_dev_t *dev, void *d) +{ + pci_driver_t *driver = d; + int i; + + for (i = 0; i < driver->id_count; i++) + if ((dev->vid == driver->ids[i].vid) && (dev->did == driver->ids[i].did)) + { + outputf("Probing PCI device: %s (%s)", driver->ids[i].name ? driver->ids[i].name : driver->name, driver->ids[i].friendlyname ? driver->ids[i].friendlyname : "no friendly name"); + return driver->probe(dev, d); + } + return 0; +} + +int pci_probe_driver(pci_driver_t driver) +{ + return pci_probe(_probefn, &driver); +} -- 2.39.2