1 /* 2 * The PCI Utilities -- Bus Mapping Mode 3 * 4 * Copyright (c) 1997--2008 Martin Mares <[email protected]> 5 * 6 * Can be freely distributed and used under the terms of the GNU GPL. 7 */ 8 9 #include <stdio.h> 10 #include <string.h> 11 #include <stdlib.h> 12 13 #include "lspci.h" 14 15 struct bus_bridge { 16 struct bus_bridge *next; 17 byte this, dev, func, first, last, bug; 18 }; 19 20 struct bus_info { 21 byte exists; 22 byte guestbook; 23 struct bus_bridge *bridges, *via; 24 }; 25 26 static struct bus_info *bus_info; 27 28 static void 29 map_bridge(struct bus_info *bi, struct device *d, int np, int ns, int nl) 30 { 31 struct bus_bridge *b = xmalloc(sizeof(struct bus_bridge)); 32 struct pci_dev *p = d->dev; 33 34 b->next = bi->bridges; 35 bi->bridges = b; 36 b->this = get_conf_byte(d, np); 37 b->dev = p->dev; 38 b->func = p->func; 39 b->first = get_conf_byte(d, ns); 40 b->last = get_conf_byte(d, nl); 41 printf("## %02x:%02x.%d is a bridge from %02x to %02x-%02x\n", 42 p->bus, p->dev, p->func, b->this, b->first, b->last); 43 if (b->this != p->bus) 44 printf("!!! Bridge points to invalid primary bus.\n"); 45 if (b->first > b->last) 46 { 47 printf("!!! Bridge points to invalid bus range.\n"); 48 b->last = b->first; 49 } 50 } 51 52 static void 53 do_map_bus(int bus) 54 { 55 int domain = (filter.domain >= 0 ? filter.domain : 0); 56 int dev, func; 57 int verbose = pacc->debugging; 58 struct bus_info *bi = bus_info + bus; 59 struct device *d; 60 61 if (verbose) 62 printf("Mapping bus %04x:%02x\n", domain, bus); 63 for (dev = 0; dev < 32; dev++) 64 if (filter.slot < 0 || filter.slot == dev) 65 { 66 int func_limit = 1; 67 for (func = 0; func < func_limit; func++) 68 if (filter.func < 0 || filter.func == func) 69 { 70 struct pci_dev *p = pci_get_dev(pacc, domain, bus, dev, func); 71 u16 vendor = pci_read_word(p, PCI_VENDOR_ID); 72 if (vendor && vendor != 0xffff) 73 { 74 if (!func && (pci_read_byte(p, PCI_HEADER_TYPE) & 0x80)) 75 func_limit = 8; 76 if (verbose) 77 printf("Discovered device %04x:%02x:%02x.%d\n", domain, bus, dev, func); 78 bi->exists = 1; 79 if (d = scan_device(p)) 80 { 81 show_device(d); 82 switch (get_conf_byte(d, PCI_HEADER_TYPE) & 0x7f) 83 { 84 case PCI_HEADER_TYPE_BRIDGE: 85 map_bridge(bi, d, PCI_PRIMARY_BUS, PCI_SECONDARY_BUS, PCI_SUBORDINATE_BUS); 86 break; 87 case PCI_HEADER_TYPE_CARDBUS: 88 map_bridge(bi, d, PCI_CB_PRIMARY_BUS, PCI_CB_CARD_BUS, PCI_CB_SUBORDINATE_BUS); 89 break; 90 } 91 free(d); 92 } 93 else if (verbose) 94 printf("But it was filtered out.\n"); 95 } 96 pci_free_dev(p); 97 } 98 } 99 } 100 101 static void 102 do_map_bridges(int bus, int min, int max) 103 { 104 struct bus_info *bi = bus_info + bus; 105 struct bus_bridge *b; 106 107 bi->guestbook = 1; 108 for (b=bi->bridges; b; b=b->next) 109 { 110 if (bus_info[b->first].guestbook) 111 b->bug = 1; 112 else if (b->first < min || b->last > max) 113 b->bug = 2; 114 else 115 { 116 bus_info[b->first].via = b; 117 do_map_bridges(b->first, b->first, b->last); 118 } 119 } 120 } 121 122 static void 123 map_bridges(void) 124 { 125 int i; 126 127 printf("\nSummary of buses:\n\n"); 128 for (i=0; i<256; i++) 129 if (bus_info[i].exists && !bus_info[i].guestbook) 130 do_map_bridges(i, 0, 255); 131 for (i=0; i<256; i++) 132 { 133 struct bus_info *bi = bus_info + i; 134 struct bus_bridge *b = bi->via; 135 136 if (bi->exists) 137 { 138 printf("%02x: ", i); 139 if (b) 140 printf("Entered via %02x:%02x.%d\n", b->this, b->dev, b->func); 141 else if (!i) 142 printf("Primary host bus\n"); 143 else 144 printf("Secondary host bus (?)\n"); 145 } 146 for (b=bi->bridges; b; b=b->next) 147 { 148 printf("\t%02x.%d Bridge to %02x-%02x", b->dev, b->func, b->first, b->last); 149 switch (b->bug) 150 { 151 case 1: 152 printf(" <overlap bug>"); 153 break; 154 case 2: 155 printf(" <crossing bug>"); 156 break; 157 } 158 putchar('\n'); 159 } 160 } 161 } 162 163 void 164 map_the_bus(void) 165 { 166 if (pacc->method == PCI_ACCESS_PROC_BUS_PCI || 167 pacc->method == PCI_ACCESS_SYS_BUS_PCI || 168 pacc->method == PCI_ACCESS_DUMP) 169 printf("WARNING: Bus mapping can be reliable only with direct hardware access enabled.\n\n"); 170 bus_info = xmalloc(sizeof(struct bus_info) * 256); 171 memset(bus_info, 0, sizeof(struct bus_info) * 256); 172 if (filter.bus >= 0) 173 do_map_bus(filter.bus); 174 else 175 { 176 int bus; 177 for (bus=0; bus<256; bus++) 178 do_map_bus(bus); 179 } 180 map_bridges(); 181 } 182