1 /* 2 * The PCI Library -- Capabilities 3 * 4 * Copyright (c) 2008 Martin Mares <[email protected]> 5 * 6 * Can be freely distributed and used under the terms of the GNU GPL. 7 */ 8 9 #include <string.h> 10 11 #include "internal.h" 12 13 static void 14 pci_add_cap(struct pci_dev *d, unsigned int addr, unsigned int id, unsigned int type) 15 { 16 struct pci_cap *cap = pci_malloc(d->access, sizeof(*cap)); 17 18 cap->next = d->first_cap; 19 d->first_cap = cap; 20 cap->addr = addr; 21 cap->id = id; 22 cap->type = type; 23 d->access->debug("%04x:%02x:%02x.%d: Found capability %04x of type %d at %04x\n", 24 d->domain, d->bus, d->dev, d->func, id, type, addr); 25 } 26 27 static void 28 pci_scan_trad_caps(struct pci_dev *d) 29 { 30 word status = pci_read_word(d, PCI_STATUS); 31 byte been_there[256]; 32 int where; 33 34 if (!(status & PCI_STATUS_CAP_LIST)) 35 return; 36 37 memset(been_there, 0, 256); 38 where = pci_read_byte(d, PCI_CAPABILITY_LIST) & ~3; 39 while (where) 40 { 41 byte id = pci_read_byte(d, where + PCI_CAP_LIST_ID); 42 byte next = pci_read_byte(d, where + PCI_CAP_LIST_NEXT) & ~3; 43 if (been_there[where]++) 44 break; 45 if (id == 0xff) 46 break; 47 pci_add_cap(d, where, id, PCI_CAP_NORMAL); 48 where = next; 49 } 50 } 51 52 static void 53 pci_scan_ext_caps(struct pci_dev *d) 54 { 55 byte been_there[0x1000]; 56 int where = 0x100; 57 58 if (!pci_find_cap(d, PCI_CAP_ID_EXP, PCI_CAP_NORMAL)) 59 return; 60 61 memset(been_there, 0, 0x1000); 62 do 63 { 64 u32 header; 65 int id; 66 67 header = pci_read_long(d, where); 68 if (!header || header == 0xffffffff) 69 break; 70 id = header & 0xffff; 71 if (been_there[where]++) 72 break; 73 pci_add_cap(d, where, id, PCI_CAP_EXTENDED); 74 where = (header >> 20) & ~3; 75 } 76 while (where); 77 } 78 79 unsigned int 80 pci_scan_caps(struct pci_dev *d, unsigned int want_fields) 81 { 82 if ((want_fields & PCI_FILL_EXT_CAPS) && !(d->known_fields & PCI_FILL_CAPS)) 83 want_fields |= PCI_FILL_CAPS; 84 85 if (want_fields & PCI_FILL_CAPS) 86 pci_scan_trad_caps(d); 87 if (want_fields & PCI_FILL_EXT_CAPS) 88 pci_scan_ext_caps(d); 89 return want_fields; 90 } 91 92 void 93 pci_free_caps(struct pci_dev *d) 94 { 95 struct pci_cap *cap; 96 97 while (cap = d->first_cap) 98 { 99 d->first_cap = cap->next; 100 pci_mfree(cap); 101 } 102 } 103 104 struct pci_cap * 105 pci_find_cap(struct pci_dev *d, unsigned int id, unsigned int type) 106 { 107 struct pci_cap *c; 108 109 pci_fill_info_v35(d, ((type == PCI_CAP_NORMAL) ? PCI_FILL_CAPS : PCI_FILL_EXT_CAPS)); 110 for (c=d->first_cap; c; c=c->next) 111 if (c->type == type && c->id == id) 112 return c; 113 return NULL; 114 } 115