Subversion Repositories HelenOS

Rev

Rev 3022 | Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.  *  The PCI Library -- Direct Configuration access via i386 Ports
  3.  *
  4.  *  Copyright (c) 1997--2004 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 <unistd.h>
  12. #include <ddi.h>
  13. #include <libarch/ddi.h>
  14.  
  15. #include "internal.h"
  16.  
  17.  
  18. static void conf12_init(struct pci_access *a)
  19. {
  20. }
  21.  
  22. static void conf12_cleanup(struct pci_access *a UNUSED)
  23. {
  24. }
  25.  
  26. /*
  27.  * Before we decide to use direct hardware access mechanisms, we try to do some
  28.  * trivial checks to ensure it at least _seems_ to be working -- we just test
  29.  * whether bus 00 contains a host bridge (this is similar to checking
  30.  * techniques used in XFree86, but ours should be more reliable since we
  31.  * attempt to make use of direct access hints provided by the PCI BIOS).
  32.  *
  33.  * This should be close to trivial, but it isn't, because there are buggy
  34.  * chipsets (yes, you guessed it, by Intel and Compaq) that have no class ID.
  35.  */
  36.  
  37. static int intel_sanity_check(struct pci_access *a, struct pci_methods *m)
  38. {
  39.     struct pci_dev d;
  40.  
  41.     a->debug("...sanity check");
  42.     d.bus = 0;
  43.     d.func = 0;
  44.     for (d.dev = 0; d.dev < 32; d.dev++) {
  45.         u16 class, vendor;
  46.         if (m->read(&d, PCI_CLASS_DEVICE, (byte *) & class,
  47.              sizeof(class))
  48.             && (class == cpu_to_le16(PCI_CLASS_BRIDGE_HOST)
  49.             || class == cpu_to_le16(PCI_CLASS_DISPLAY_VGA))
  50.             || m->read(&d, PCI_VENDOR_ID, (byte *) & vendor,
  51.                    sizeof(vendor))
  52.             && (vendor == cpu_to_le16(PCI_VENDOR_ID_INTEL)
  53.             || vendor == cpu_to_le16(PCI_VENDOR_ID_COMPAQ))) {
  54.             a->debug("...outside the Asylum at 0/%02x/0",
  55.                  d.dev);
  56.             return 1;
  57.         }
  58.     }
  59.     a->debug("...insane");
  60.     return 0;
  61. }
  62.  
  63. /*
  64.  *  Configuration type 1
  65.  */
  66.  
  67. #define CONFIG_CMD(bus, device_fn, where)   (0x80000000 | (bus << 16) | (device_fn << 8) | (where & ~3))
  68.  
  69. static int conf1_detect(struct pci_access *a)
  70. {
  71.     unsigned int tmp;
  72.     int res = 0;
  73.  
  74.     pio_write_8(0xCFB, 0x01);
  75.     tmp = pio_read_32(0xCF8);
  76.     pio_write_32(0xCF8, 0x80000000);
  77.     if (pio_read_32(0xCF8) == 0x80000000) {
  78.         res = 1;
  79.     }
  80.     pio_write_32(0xCF8, tmp);
  81.     if (res) {
  82.         res = intel_sanity_check(a, &pm_intel_conf1);
  83.     }
  84.     return res;
  85. }
  86.  
  87. static int conf1_read(struct pci_dev *d, int pos, byte * buf, int len)
  88. {
  89.     int addr = 0xcfc + (pos & 3);
  90.  
  91.     if (pos >= 256)
  92.         return 0;
  93.  
  94.     pio_write_32(0xcf8, 0x80000000 | ((d->bus & 0xff) << 16) |
  95.          (PCI_DEVFN(d->dev, d->func) << 8) | (pos & ~3));
  96.  
  97.     switch (len) {
  98.     case 1:
  99.         buf[0] = pio_read_8(addr);
  100.         break;
  101.     case 2:
  102.         ((u16 *) buf)[0] = cpu_to_le16(pio_read_16(addr));
  103.         break;
  104.     case 4:
  105.         ((u32 *) buf)[0] = cpu_to_le32(pio_read_32(addr));
  106.         break;
  107.     default:
  108.         return pci_generic_block_read(d, pos, buf, len);
  109.     }
  110.     return 1;
  111. }
  112.  
  113. static int conf1_write(struct pci_dev *d, int pos, byte * buf, int len)
  114. {
  115.     int addr = 0xcfc + (pos & 3);
  116.  
  117.     if (pos >= 256)
  118.         return 0;
  119.  
  120.     pio_write_32(0xcf8, 0x80000000 | ((d->bus & 0xff) << 16) |
  121.          (PCI_DEVFN(d->dev, d->func) << 8) | (pos & ~3));
  122.  
  123.     switch (len) {
  124.     case 1:
  125.         pio_write_8(addr, buf[0]);
  126.         break;
  127.     case 2:
  128.         pio_write_16(addr, le16_to_cpu(((u16 *) buf)[0]));
  129.         break;
  130.     case 4:
  131.         pio_write_32(addr, le32_to_cpu(((u32 *) buf)[0]));
  132.         break;
  133.     default:
  134.         return pci_generic_block_write(d, pos, buf, len);
  135.     }
  136.     return 1;
  137. }
  138.  
  139. /*
  140.  *  Configuration type 2. Obsolete and brain-damaged, but existing.
  141.  */
  142.  
  143. static int conf2_detect(struct pci_access *a)
  144. {
  145.     /* This is ugly and tends to produce false positives. Beware. */
  146.     pio_write_8(0xCFB, 0x00);
  147.     pio_write_8(0xCF8, 0x00);
  148.     pio_write_8(0xCFA, 0x00);
  149.     if (pio_read_8(0xCF8) == 0x00 && pio_read_8(0xCFA) == 0x00)
  150.         return intel_sanity_check(a, &pm_intel_conf2);
  151.     else
  152.         return 0;
  153. }
  154.  
  155. static int conf2_read(struct pci_dev *d, int pos, byte * buf, int len)
  156. {
  157.     int addr = 0xc000 | (d->dev << 8) | pos;
  158.  
  159.     if (pos >= 256)
  160.         return 0;
  161.  
  162.     if (d->dev >= 16)
  163.         /* conf2 supports only 16 devices per bus */
  164.         return 0;
  165.     pio_write_8(0xcf8, (d->func << 1) | 0xf0);
  166.     pio_write_8(0xcfa, d->bus);
  167.     switch (len) {
  168.     case 1:
  169.         buf[0] = pio_read_8(addr);
  170.         break;
  171.     case 2:
  172.         ((u16 *) buf)[0] = cpu_to_le16(pio_read_16(addr));
  173.         break;
  174.     case 4:
  175.         ((u32 *) buf)[0] = cpu_to_le32(pio_read_32(addr));
  176.         break;
  177.     default:
  178.         pio_write_8(0xcf8, 0);
  179.         return pci_generic_block_read(d, pos, buf, len);
  180.     }
  181.     pio_write_8((void *)0xcf8, 0);
  182.     return 1;
  183. }
  184.  
  185. static int conf2_write(struct pci_dev *d, int pos, byte * buf, int len)
  186. {
  187.     int addr = 0xc000 | (d->dev << 8) | pos;
  188.  
  189.     if (pos >= 256)
  190.         return 0;
  191.  
  192.     if (d->dev >= 16)
  193.         d->access->error("conf2_write: only first 16 devices exist.");
  194.     pio_write_8(0xcf8, (d->func << 1) | 0xf0);
  195.     pio_write_8(0xcfa, d->bus);
  196.     switch (len) {
  197.     case 1:
  198.         pio_write_8(addr, buf[0]);
  199.         break;
  200.     case 2:
  201.         pio_write_16(addr, le16_to_cpu(*(u16 *) buf));
  202.         break;
  203.     case 4:
  204.         pio_write_32(addr, le32_to_cpu(*(u32 *) buf));
  205.         break;
  206.     default:
  207.         pio_write_8(0xcf8, 0);
  208.         return pci_generic_block_write(d, pos, buf, len);
  209.     }
  210.     pio_write_8(0xcf8, 0);
  211.     return 1;
  212. }
  213.  
  214. struct pci_methods pm_intel_conf1 = {
  215.     "Intel-conf1",
  216.     NULL,           /* config */
  217.     conf1_detect,
  218.     conf12_init,
  219.     conf12_cleanup,
  220.     pci_generic_scan,
  221.     pci_generic_fill_info,
  222.     conf1_read,
  223.     conf1_write,
  224.     NULL,           /* init_dev */
  225.     NULL            /* cleanup_dev */
  226. };
  227.  
  228. struct pci_methods pm_intel_conf2 = {
  229.     "Intel-conf2",
  230.     NULL,           /* config */
  231.     conf2_detect,
  232.     conf12_init,
  233.     conf12_cleanup,
  234.     pci_generic_scan,
  235.     pci_generic_fill_info,
  236.     conf2_read,
  237.     conf2_write,
  238.     NULL,           /* init_dev */
  239.     NULL            /* cleanup_dev */
  240. };
  241.