File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / pciutils / lib / generic.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 (13 years, 1 month ago) by misho
Branches: pciutils, MAIN
CVS tags: v3_1_9, HEAD
pciutils

    1: /*
    2:  *	The PCI Library -- Generic Direct Access Functions
    3:  *
    4:  *	Copyright (c) 1997--2000 Martin Mares <mj@ucw.cz>
    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: void
   14: pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
   15: {
   16:   int dev, multi, ht;
   17:   struct pci_dev *t;
   18: 
   19:   a->debug("Scanning bus %02x for devices...\n", bus);
   20:   if (busmap[bus])
   21:     {
   22:       a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
   23:       return;
   24:     }
   25:   busmap[bus] = 1;
   26:   t = pci_alloc_dev(a);
   27:   t->bus = bus;
   28:   for (dev=0; dev<32; dev++)
   29:     {
   30:       t->dev = dev;
   31:       multi = 0;
   32:       for (t->func=0; !t->func || multi && t->func<8; t->func++)
   33: 	{
   34: 	  u32 vd = pci_read_long(t, PCI_VENDOR_ID);
   35: 	  struct pci_dev *d;
   36: 
   37: 	  if (!vd || vd == 0xffffffff)
   38: 	    continue;
   39: 	  ht = pci_read_byte(t, PCI_HEADER_TYPE);
   40: 	  if (!t->func)
   41: 	    multi = ht & 0x80;
   42: 	  ht &= 0x7f;
   43: 	  d = pci_alloc_dev(a);
   44: 	  d->bus = t->bus;
   45: 	  d->dev = t->dev;
   46: 	  d->func = t->func;
   47: 	  d->vendor_id = vd & 0xffff;
   48: 	  d->device_id = vd >> 16U;
   49: 	  d->known_fields = PCI_FILL_IDENT;
   50: 	  d->hdrtype = ht;
   51: 	  pci_link_dev(a, d);
   52: 	  switch (ht)
   53: 	    {
   54: 	    case PCI_HEADER_TYPE_NORMAL:
   55: 	      break;
   56: 	    case PCI_HEADER_TYPE_BRIDGE:
   57: 	    case PCI_HEADER_TYPE_CARDBUS:
   58: 	      pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
   59: 	      break;
   60: 	    default:
   61: 	      a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
   62: 	    }
   63: 	}
   64:     }
   65:   pci_free_dev(t);
   66: }
   67: 
   68: void
   69: pci_generic_scan(struct pci_access *a)
   70: {
   71:   byte busmap[256];
   72: 
   73:   memset(busmap, 0, sizeof(busmap));
   74:   pci_generic_scan_bus(a, busmap, 0);
   75: }
   76: 
   77: int
   78: pci_generic_fill_info(struct pci_dev *d, int flags)
   79: {
   80:   struct pci_access *a = d->access;
   81: 
   82:   if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
   83:     d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
   84:   if (flags & PCI_FILL_IDENT)
   85:     {
   86:       d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
   87:       d->device_id = pci_read_word(d, PCI_DEVICE_ID);
   88:     }
   89:   if (flags & PCI_FILL_CLASS)
   90:       d->device_class = pci_read_word(d, PCI_CLASS_DEVICE);
   91:   if (flags & PCI_FILL_IRQ)
   92:     d->irq = pci_read_byte(d, PCI_INTERRUPT_LINE);
   93:   if (flags & PCI_FILL_BASES)
   94:     {
   95:       int cnt = 0, i;
   96:       memset(d->base_addr, 0, sizeof(d->base_addr));
   97:       switch (d->hdrtype)
   98: 	{
   99: 	case PCI_HEADER_TYPE_NORMAL:
  100: 	  cnt = 6;
  101: 	  break;
  102: 	case PCI_HEADER_TYPE_BRIDGE:
  103: 	  cnt = 2;
  104: 	  break;
  105: 	case PCI_HEADER_TYPE_CARDBUS:
  106: 	  cnt = 1;
  107: 	  break;
  108: 	}
  109:       if (cnt)
  110: 	{
  111: 	  for (i=0; i<cnt; i++)
  112: 	    {
  113: 	      u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i*4);
  114: 	      if (!x || x == (u32) ~0)
  115: 		continue;
  116: 	      if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
  117: 		d->base_addr[i] = x;
  118: 	      else
  119: 		{
  120: 		  if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)
  121: 		    d->base_addr[i] = x;
  122: 		  else if (i >= cnt-1)
  123: 		    a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.", d->domain, d->bus, d->dev, d->func, i);
  124: 		  else
  125: 		    {
  126: 		      u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i)*4);
  127: #ifdef PCI_HAVE_64BIT_ADDRESS
  128: 		      d->base_addr[i-1] = x | (((pciaddr_t) y) << 32);
  129: #else
  130: 		      if (y)
  131: 			a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.", d->domain, d->bus, d->dev, d->func);
  132: 		      else
  133: 			d->base_addr[i-1] = x;
  134: #endif
  135: 		    }
  136: 		}
  137: 	    }
  138: 	}
  139:     }
  140:   if (flags & PCI_FILL_ROM_BASE)
  141:     {
  142:       int reg = 0;
  143:       d->rom_base_addr = 0;
  144:       switch (d->hdrtype)
  145: 	{
  146: 	case PCI_HEADER_TYPE_NORMAL:
  147: 	  reg = PCI_ROM_ADDRESS;
  148: 	  break;
  149: 	case PCI_HEADER_TYPE_BRIDGE:
  150: 	  reg = PCI_ROM_ADDRESS1;
  151: 	  break;
  152: 	}
  153:       if (reg)
  154: 	{
  155: 	  u32 u = pci_read_long(d, reg);
  156: 	  if (u != 0xffffffff)
  157: 	    d->rom_base_addr = u;
  158: 	}
  159:     }
  160:   if (flags & (PCI_FILL_CAPS | PCI_FILL_EXT_CAPS))
  161:     flags |= pci_scan_caps(d, flags);
  162:   return flags & ~PCI_FILL_SIZES;
  163: }
  164: 
  165: static int
  166: pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
  167: 		 int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
  168: {
  169:   if ((pos & 1) && len >= 1)
  170:     {
  171:       if (!r(d, pos, buf, 1))
  172: 	return 0;
  173:       pos++; buf++; len--;
  174:     }
  175:   if ((pos & 3) && len >= 2)
  176:     {
  177:       if (!r(d, pos, buf, 2))
  178: 	return 0;
  179:       pos += 2; buf += 2; len -= 2;
  180:     }
  181:   while (len >= 4)
  182:     {
  183:       if (!r(d, pos, buf, 4))
  184: 	return 0;
  185:       pos += 4; buf += 4; len -= 4;
  186:     }
  187:   if (len >= 2)
  188:     {
  189:       if (!r(d, pos, buf, 2))
  190: 	return 0;
  191:       pos += 2; buf += 2; len -= 2;
  192:     }
  193:   if (len && !r(d, pos, buf, 1))
  194:     return 0;
  195:   return 1;
  196: }
  197: 
  198: int
  199: pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
  200: {
  201:   return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
  202: }
  203: 
  204: int
  205: pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
  206: {
  207:   return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
  208: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>