diff options
Diffstat (limited to 'pcidev.c')
-rw-r--r-- | pcidev.c | 77 |
1 files changed, 73 insertions, 4 deletions
@@ -19,7 +19,7 @@ #include <string.h> #include "flash.h" #include "programmer.h" -#include "hwaccess.h" +#include "platform/pci.h" struct pci_access *pacc; @@ -148,6 +148,75 @@ uintptr_t pcidev_readbar(struct pci_dev *dev, int bar) return (uintptr_t)addr; } +struct pci_dev *pcidev_scandev(struct pci_filter *filter, struct pci_dev *start) +{ + struct pci_dev *temp; + for (temp = start ? start->next : pacc->devices; temp; temp = temp->next) { + if (pci_filter_match(filter, temp)) { + pci_fill_info(temp, PCI_FILL_IDENT); + return temp; + } + } + return NULL; +} + +struct pci_dev *pcidev_card_find(uint16_t vendor, uint16_t device, + uint16_t card_vendor, uint16_t card_device) +{ + struct pci_dev *temp = NULL; + struct pci_filter filter; + + pci_filter_init(NULL, &filter); + filter.vendor = vendor; + filter.device = device; + + while ((temp = pcidev_scandev(&filter, temp))) { + if ((card_vendor == pci_read_word(temp, PCI_SUBSYSTEM_VENDOR_ID)) + && (card_device == pci_read_word(temp, PCI_SUBSYSTEM_ID))) + return temp; + } + + return NULL; +} + +struct pci_dev *pcidev_find(uint16_t vendor, uint16_t device) +{ + struct pci_filter filter; + + pci_filter_init(NULL, &filter); + filter.vendor = vendor; + filter.device = device; + + return pcidev_scandev(&filter, NULL); +} + +struct pci_dev *pcidev_getdevfn(struct pci_dev *dev, const int func) +{ + struct pci_dev *const new = pci_get_dev(pacc, dev->domain, dev->bus, dev->dev, func); + if (new) + pci_fill_info(new, PCI_FILL_IDENT); + return new; +} + +struct pci_dev *pcidev_find_vendorclass(uint16_t vendor, uint16_t devclass) +{ + struct pci_dev *temp = NULL; + struct pci_filter filter; + uint16_t tmp2; + + pci_filter_init(NULL, &filter); + filter.vendor = vendor; + + while ((temp = pcidev_scandev(&filter, temp))) { + /* Read PCI class */ + tmp2 = pci_read_word(temp, PCI_CLASS_DEVICE); + if (tmp2 == devclass) + return temp; + } + + return NULL; +} + static int pcidev_shutdown(void *data) { if (pacc == NULL) { @@ -180,7 +249,7 @@ int pci_init_common(void) * also matches the specified bus:device.function. * For convenience, this function also registers its own undo handlers. */ -struct pci_dev *pcidev_init(const struct dev_entry *devs, int bar) +struct pci_dev *pcidev_init(const struct programmer_cfg *cfg, const struct dev_entry *devs, int bar) { struct pci_dev *dev; struct pci_dev *found_dev = NULL; @@ -195,7 +264,7 @@ struct pci_dev *pcidev_init(const struct dev_entry *devs, int bar) pci_filter_init(pacc, &filter); /* Filter by bb:dd.f (if supplied by the user). */ - pcidev_bdf = extract_programmer_param("pci"); + pcidev_bdf = extract_programmer_param_str(cfg, "pci"); if (pcidev_bdf != NULL) { if ((msg = pci_filter_parse_slot(&filter, pcidev_bdf))) { msg_perr("Error: %s\n", msg); @@ -296,7 +365,7 @@ static int undo_pci_write(void *p) #define register_undo_pci_write(a, b, c) \ { \ struct undo_pci_write_data *undo_pci_write_data; \ - undo_pci_write_data = malloc(sizeof(struct undo_pci_write_data)); \ + undo_pci_write_data = malloc(sizeof(*undo_pci_write_data)); \ if (!undo_pci_write_data) { \ msg_gerr("Out of memory!\n"); \ exit(1); \ |