Subversion Repositories HelenOS-historic

Rev

Rev 1301 | 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 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 =
  110.                     pci_read_long(d,
  111.                           PCI_BASE_ADDRESS_0 +
  112.                           i * 4);
  113.                 if (!x || x == (u32) ~ 0)
  114.                     continue;
  115.                 if ((x & PCI_BASE_ADDRESS_SPACE) ==
  116.                     PCI_BASE_ADDRESS_SPACE_IO)
  117.                     d->base_addr[i] = x;
  118.                 else {
  119.                     if ((x &
  120.                          PCI_BASE_ADDRESS_MEM_TYPE_MASK)
  121.                         !=
  122.                         PCI_BASE_ADDRESS_MEM_TYPE_64)
  123.                         d->base_addr[i] = x;
  124.                     else if (i >= cnt - 1)
  125.                         a->warning
  126.                             ("%04x:%02x:%02x.%d: Invalid 64-bit address seen for BAR %d.",
  127.                              d->domain, d->bus,
  128.                              d->dev, d->func, i);
  129.                     else {
  130.                         u32 y =
  131.                             pci_read_long(d,
  132.                                   PCI_BASE_ADDRESS_0
  133.                                   +
  134.                                   (++i) *
  135.                                   4);
  136. #ifdef PCI_HAVE_64BIT_ADDRESS
  137.                         d->base_addr[i - 1] =
  138.                             x | (((pciaddr_t) y) <<
  139.                              32);
  140. #else
  141.                         if (y)
  142.                             a->warning
  143.                                 ("%04x:%02x:%02x.%d 64-bit device address ignored.",
  144.                                  d->domain,
  145.                                  d->bus,
  146.                                  d->dev,
  147.                                  d->func);
  148.                         else
  149.                             d->base_addr[i -
  150.                                      1] =
  151.                                 x;
  152. #endif
  153.                     }
  154.                 }
  155.             }
  156.         }
  157.     }
  158.     if (flags & PCI_FILL_ROM_BASE) {
  159.         int reg = 0;
  160.         d->rom_base_addr = 0;
  161.         switch (d->hdrtype) {
  162.         case PCI_HEADER_TYPE_NORMAL:
  163.             reg = PCI_ROM_ADDRESS;
  164.             break;
  165.         case PCI_HEADER_TYPE_BRIDGE:
  166.             reg = PCI_ROM_ADDRESS1;
  167.             break;
  168.         }
  169.         if (reg) {
  170.             u32 u = pci_read_long(d, reg);
  171.             if (u != 0xffffffff)
  172.                 d->rom_base_addr = u;
  173.         }
  174.     }
  175.     return flags & ~PCI_FILL_SIZES;
  176. }
  177.  
  178. static int
  179. pci_generic_block_op(struct pci_dev *d, int pos, byte * buf, int len,
  180.              int (*r) (struct pci_dev * d, int pos, byte * buf,
  181.                    int len))
  182. {
  183.     if ((pos & 1) && len >= 1) {
  184.         if (!r(d, pos, buf, 1))
  185.             return 0;
  186.         pos++;
  187.         buf++;
  188.         len--;
  189.     }
  190.     if ((pos & 3) && len >= 2) {
  191.         if (!r(d, pos, buf, 2))
  192.             return 0;
  193.         pos += 2;
  194.         buf += 2;
  195.         len -= 2;
  196.     }
  197.     while (len >= 4) {
  198.         if (!r(d, pos, buf, 4))
  199.             return 0;
  200.         pos += 4;
  201.         buf += 4;
  202.         len -= 4;
  203.     }
  204.     if (len >= 2) {
  205.         if (!r(d, pos, buf, 2))
  206.             return 0;
  207.         pos += 2;
  208.         buf += 2;
  209.         len -= 2;
  210.     }
  211.     if (len && !r(d, pos, buf, 1))
  212.         return 0;
  213.     return 1;
  214. }
  215.  
  216. int pci_generic_block_read(struct pci_dev *d, int pos, byte * buf, int len)
  217. {
  218.     return pci_generic_block_op(d, pos, buf, len,
  219.                     d->access->methods->read);
  220. }
  221.  
  222. int pci_generic_block_write(struct pci_dev *d, int pos, byte * buf, int len)
  223. {
  224.     return pci_generic_block_op(d, pos, buf, len,
  225.                     d->access->methods->write);
  226. }
  227.