File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pciutils / ls-map.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Fri Feb 17 15:18:43 2012 UTC (12 years, 4 months ago) by misho
Branches: pciutils, MAIN
CVS tags: v3_1_9, HEAD
pciutils

    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>