Subversion Repositories HelenOS

Rev

Rev 2787 | 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.  *  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.             switch (ht) {
  53.             case PCI_HEADER_TYPE_NORMAL:
  54.                 break;
  55.             case PCI_HEADER_TYPE_BRIDGE:
  56.             case PCI_HEADER_TYPE_CARDBUS:
  57.                 pci_generic_scan_bus(a, busmap,
  58.                              pci_read_byte(t,
  59.                                    PCI_SECONDARY_BUS));
  60.                 break;
  61.             default:
  62.                 a->debug
  63.                     ("Device %04x:%02x:%02x.%d has unknown header type %02x.\n",
  64.                      d->domain, d->bus, d->dev, d->func,
  65.                      ht);
  66.             }
  67.         }
  68.     }
  69.     pci_free_dev(t);
  70. }
  71.  
  72. void pci_generic_scan(struct pci_access *a)
  73. {
  74.     byte busmap[256];
  75.  
  76.     bzero(busmap, sizeof(busmap));
  77.     pci_generic_scan_bus(a, busmap, 0);
  78. }
  79.  
  80. int 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))
  85.         && d->hdrtype < 0)
  86.         d->hdrtype = pci_read_byte(d, PCI_HEADER_TYPE) & 0x7f;
  87.     if (flags & PCI_FILL_IDENT) {
  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.         int cnt = 0, i;
  95.         bzero(d->base_addr, sizeof(d->base_addr));
  96.         switch (d->hdrtype) {
  97.         case PCI_HEADER_TYPE_NORMAL:
  98.             cnt = 6;
  99.             break;
  100.         case PCI_HEADER_TYPE_BRIDGE:
  101.             cnt = 2;
  102.             break;
  103.         case PCI_HEADER_TYPE_CARDBUS:
  104.             cnt = 1;
  105.             break;
  106.         }
  107.         if (cnt) {
  108.             for (i = 0; i < cnt; i++) {
  109.                 u32 x = pci_read_long(d, PCI_BASE_ADDRESS_0 + i * 4);
  110.                 if (!x || x == (u32) ~ 0)
  111.                     continue;
  112.                 if ((x & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO)
  113.                     d->base_addr[i] = x;
  114.                 else {
  115.                     if ((x & PCI_BASE_ADDRESS_MEM_TYPE_MASK) != PCI_BASE_ADDRESS_MEM_TYPE_64)
  116.                         d->base_addr[i] = x;
  117.                     else if (i >= cnt - 1)
  118.                         a->warning("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.",
  119.                              d->domain, d->bus,
  120.                              d->dev, d->func, i);
  121.                     else {
  122.                         u32 y = pci_read_long(d, PCI_BASE_ADDRESS_0 + (++i) * 4);
  123. #ifdef PCI_HAVE_64BIT_ADDRESS
  124.                         d->base_addr[i - 1] = x | (((pciaddr_t) y) << 32);
  125. #else
  126.                         if (y)
  127.                             a->warning("%04x:%02x:%02x.%d 64-bit device address ignored.",
  128.                                  d->domain,
  129.                                  d->bus,
  130.                                  d->dev,
  131.                                  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.         int reg = 0;
  142.         d->rom_base_addr = 0;
  143.         switch (d->hdrtype) {
  144.         case PCI_HEADER_TYPE_NORMAL:
  145.             reg = PCI_ROM_ADDRESS;
  146.             break;
  147.         case PCI_HEADER_TYPE_BRIDGE:
  148.             reg = PCI_ROM_ADDRESS1;
  149.             break;
  150.         }
  151.         if (reg) {
  152.             u32 u = pci_read_long(d, reg);
  153.             if (u != 0xffffffff)
  154.                 d->rom_base_addr = u;
  155.         }
  156.     }
  157.     return flags & ~PCI_FILL_SIZES;
  158. }
  159.  
  160. static int
  161. pci_generic_block_op(struct pci_dev *d, int pos, byte * buf, int len,
  162.              int (*r) (struct pci_dev * d, int pos, byte * buf,
  163.                    int len))
  164. {
  165.     if ((pos & 1) && len >= 1) {
  166.         if (!r(d, pos, buf, 1))
  167.             return 0;
  168.         pos++;
  169.         buf++;
  170.         len--;
  171.     }
  172.     if ((pos & 3) && len >= 2) {
  173.         if (!r(d, pos, buf, 2))
  174.             return 0;
  175.         pos += 2;
  176.         buf += 2;
  177.         len -= 2;
  178.     }
  179.     while (len >= 4) {
  180.         if (!r(d, pos, buf, 4))
  181.             return 0;
  182.         pos += 4;
  183.         buf += 4;
  184.         len -= 4;
  185.     }
  186.     if (len >= 2) {
  187.         if (!r(d, pos, buf, 2))
  188.             return 0;
  189.         pos += 2;
  190.         buf += 2;
  191.         len -= 2;
  192.     }
  193.     if (len && !r(d, pos, buf, 1))
  194.         return 0;
  195.     return 1;
  196. }
  197.  
  198. int pci_generic_block_read(struct pci_dev *d, int pos, byte * buf, int len)
  199. {
  200.     return pci_generic_block_op(d, pos, buf, len, d->access->methods->read);
  201. }
  202.  
  203. int 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.