Subversion Repositories HelenOS

Rev

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