Annotation of embedaddon/pciutils/ls-map.c, revision 1.1
1.1 ! misho 1: /*
! 2: * The PCI Utilities -- Bus Mapping Mode
! 3: *
! 4: * Copyright (c) 1997--2008 Martin Mares <mj@ucw.cz>
! 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 dev, func;
! 56: int verbose = pacc->debugging;
! 57: struct bus_info *bi = bus_info + bus;
! 58: struct device *d;
! 59:
! 60: if (verbose)
! 61: printf("Mapping bus %02x\n", bus);
! 62: for (dev = 0; dev < 32; dev++)
! 63: if (filter.slot < 0 || filter.slot == dev)
! 64: {
! 65: int func_limit = 1;
! 66: for (func = 0; func < func_limit; func++)
! 67: if (filter.func < 0 || filter.func == func)
! 68: {
! 69: /* XXX: Bus mapping supports only domain 0 */
! 70: struct pci_dev *p = pci_get_dev(pacc, 0, 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 %02x:%02x.%d\n", 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: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>