Subversion Repositories HelenOS-historic

Rev

Rev 1302 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  The PCI Library -- Generic Direct Access Functions
  3.  *
  4.  *  Copyright (c) 1997--2000 Martin Mares <mj@ucw.cz>
  5.  *
  6.  *  Modified and ported to HelenOS by Jakub Jermar.
  7.  *
  8.  *  Can be freely distributed and used under the terms of the GNU GPL.
  9.  */
  10.  
  11. #include <string.h>
  12.  
  13. #include "internal.h"
  14.  
  15. void
  16. pci_generic_scan_bus(struct pci_access *a, byte *busmap, int bus)
  17. {
  18.   int dev, multi, ht;
  19.   struct pci_dev *t;
  20.  
  21.   a->debug("Scanning bus %02x for devices...\n", bus);
  22.   if (busmap[bus])
  23.     {
  24.       a->warning("Bus %02x seen twice (firmware bug). Ignored.", bus);
  25.       return;
  26.     }
  27.   busmap[bus] = 1;
  28.   t = pci_alloc_dev(a);
  29.   t->bus = bus;
  30.   for(dev=0; dev<32; dev++)
  31.     {
  32.       t->dev = dev;
  33.       multi = 0;
  34.       for(t->func=0; !t->func || multi && t->func<8; t->func++)
  35.     {
  36.       u32 vd = pci_read_long(t, PCI_VENDOR_ID);
  37.       struct pci_dev *d;
  38.  
  39.       if (!vd || vd == 0xffffffff)
  40.         continue;
  41.       ht = pci_read_byte(t, PCI_HEADER_TYPE);
  42.       if (!t->func)
  43.         multi = ht & 0x80;
  44.       ht &= 0x7f;
  45.       d = pci_alloc_dev(a);
  46.       d->bus = t->bus;
  47.       d->dev = t->dev;
  48.       d->func = t->func;
  49.       d->vendor_id = vd & 0xffff;
  50.       d->device_id = vd >> 16U;
  51.       d->known_fields = PCI_FILL_IDENT;
  52.       d->hdrtype = ht;
  53.       pci_link_dev(a, d);
  54.       switch (ht)
  55.         {
  56.         case PCI_HEADER_TYPE_NORMAL:
  57.           break;
  58.         case PCI_HEADER_TYPE_BRIDGE:
  59.         case PCI_HEADER_TYPE_CARDBUS:
  60.           pci_generic_scan_bus(a, busmap, pci_read_byte(t, PCI_SECONDARY_BUS));
  61.           break;
  62.         default:
  63.           a->debug("Device %04x:%02x:%02x.%d has unknown header type %02x.\n", d->domain, d->bus, d->dev, d->func, ht);
  64.         }
  65.     }
  66.     }
  67.   pci_free_dev(t);
  68. }
  69.  
  70. void
  71. pci_generic_scan(struct pci_access *a)
  72. {
  73.   byte busmap[256];
  74.  
  75.   bzero(busmap, sizeof(busmap));
  76.   pci_generic_scan_bus(a, busmap, 0);
  77. }
  78.  
  79. int
  80. pci_generic_fill_info(struct pci_dev *d, int flags)
  81. {
  82.   struct pci_access *a = d->access;
  83.  
  84.   if ((flags & (PCI_FILL_BASES | PCI_FILL_ROM_BASE)) && d->hdrtype < 0)
  85.     d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
  86.   if (flags & PCI_FILL_IDENT)
  87.     {
  88.       d->vendor_id = pci_read_word(d, PCI_VENDOR_ID);
  89.       d->device_id = pci_read_word(d, PCI_DEVICE_ID);
  90.     }
  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.       bzero(d->base_addr, 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.   return flags & ~PCI_FILL_SIZES;
  161. }
  162.  
  163. static int
  164. pci_generic_block_op(struct pci_dev *d, int pos, byte *buf, int len,
  165.          int (*r)(struct pci_dev *d, int pos, byte *buf, int len))
  166. {
  167.   if ((pos & 1) && len >= 1)
  168.     {
  169.       if (!r(d, pos, buf, 1))
  170.     return 0;
  171.       pos++; buf++; len--;
  172.     }
  173.   if ((pos & 3) && len >= 2)
  174.     {
  175.       if (!r(d, pos, buf, 2))
  176.     return 0;
  177.       pos += 2; buf += 2; len -= 2;
  178.     }
  179.   while (len >= 4)
  180.     {
  181.       if (!r(d, pos, buf, 4))
  182.     return 0;
  183.       pos += 4; buf += 4; len -= 4;
  184.     }
  185.   if (len >= 2)
  186.     {
  187.       if (!r(d, pos, buf, 2))
  188.     return 0;
  189.       pos += 2; buf += 2; len -= 2;
  190.     }
  191.   if (len && !r(d, pos, buf, 1))
  192.     return 0;
  193.   return 1;
  194. }
  195.  
  196. int
  197. pci_generic_block_read(struct pci_dev *d, int pos, byte *buf, int len)
  198. {
  199.   return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
  200. }
  201.  
  202. int
  203. pci_generic_block_write(struct pci_dev *d, int pos, byte *buf, int len)
  204. {
  205.   return pci_generic_block_op(d, pos, buf, len, d->access->methods->write);
  206. }
  207.