Subversion Repositories HelenOS

Rev

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

  1. /*
  2.  *  The PCI Library -- User Access
  3.  *
  4.  *  Copyright (c) 1997--2003 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 <stdio.h>
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14. #include <string.h>
  15.  
  16. #include "internal.h"
  17.  
  18. static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
  19.   &pm_intel_conf1,
  20.   &pm_intel_conf2,
  21. };
  22.  
  23. struct pci_access *
  24. pci_alloc(void)
  25. {
  26.   struct pci_access *a = malloc(sizeof(struct pci_access));
  27.   int i;
  28.  
  29.   bzero(a, sizeof(*a));
  30.   for(i=0; i<PCI_ACCESS_MAX; i++)
  31.     if (pci_methods[i] && pci_methods[i]->config)
  32.       pci_methods[i]->config(a);
  33.   return a;
  34. }
  35.  
  36. void *
  37. pci_malloc(struct pci_access *a, int size)
  38. {
  39.   void *x = malloc(size);
  40.  
  41.   if (!x)
  42.     a->error("Out of memory (allocation of %d bytes failed)", size);
  43.   return x;
  44. }
  45.  
  46. void
  47. pci_mfree(void *x)
  48. {
  49.   if (x)
  50.     free(x);
  51. }
  52.  
  53. static void
  54. pci_generic_error(char *msg, ...)
  55. {
  56.   va_list args;
  57.  
  58.   va_start(args, msg);
  59.   puts("pcilib: ");
  60.   vprintf(msg, args);
  61.   putchar('\n');
  62.   exit(1);
  63. }
  64.  
  65. static void
  66. pci_generic_warn(char *msg, ...)
  67. {
  68.   va_list args;
  69.  
  70.   va_start(args, msg);
  71.   puts("pcilib: ");
  72.   vprintf(msg, args);
  73.   putchar('\n');
  74. }
  75.  
  76. static void
  77. pci_generic_debug(char *msg, ...)
  78. {
  79.   va_list args;
  80.  
  81.   va_start(args, msg);
  82.   vprintf(msg, args);
  83.   va_end(args);
  84. }
  85.  
  86. static void
  87. pci_null_debug(char *msg UNUSED, ...)
  88. {
  89. }
  90.  
  91. void
  92. pci_init(struct pci_access *a)
  93. {
  94.   if (!a->error)
  95.     a->error = pci_generic_error;
  96.   if (!a->warning)
  97.     a->warning = pci_generic_warn;
  98.   if (!a->debug)
  99.     a->debug = pci_generic_debug;
  100.   if (!a->debugging)
  101.     a->debug = pci_null_debug;
  102.  
  103.   if (a->method)
  104.     {
  105.       if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
  106.     a->error("This access method is not supported.");
  107.       a->methods = pci_methods[a->method];
  108.     }
  109.   else
  110.     {
  111.       unsigned int i;
  112.       for(i=0; i<PCI_ACCESS_MAX; i++)
  113.     if (pci_methods[i])
  114.       {
  115.         a->debug("Trying method %d...", i);
  116.         if (pci_methods[i]->detect(a))
  117.           {
  118.         a->debug("...OK\n");
  119.         a->methods = pci_methods[i];
  120.         a->method = i;
  121.         break;
  122.           }
  123.         a->debug("...No.\n");
  124.       }
  125.       if (!a->methods)
  126.     a->error("Cannot find any working access method.");
  127.     }
  128.   a->debug("Decided to use %s\n", a->methods->name);
  129.   a->methods->init(a);
  130. }
  131.  
  132. void
  133. pci_cleanup(struct pci_access *a)
  134. {
  135.   struct pci_dev *d, *e;
  136.  
  137.   for(d=a->devices; d; d=e)
  138.     {
  139.       e = d->next;
  140.       pci_free_dev(d);
  141.     }
  142.   if (a->methods)
  143.     a->methods->cleanup(a);
  144.   pci_free_name_list(a);
  145.   pci_mfree(a);
  146. }
  147.  
  148. void
  149. pci_scan_bus(struct pci_access *a)
  150. {
  151.   a->methods->scan(a);
  152. }
  153.  
  154. struct pci_dev *
  155. pci_alloc_dev(struct pci_access *a)
  156. {
  157.   struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev));
  158.  
  159.   bzero(d, sizeof(*d));
  160.   d->access = a;
  161.   d->methods = a->methods;
  162.   d->hdrtype = -1;
  163.   if (d->methods->init_dev)
  164.     d->methods->init_dev(d);
  165.   return d;
  166. }
  167.  
  168. int
  169. pci_link_dev(struct pci_access *a, struct pci_dev *d)
  170. {
  171.   d->next = a->devices;
  172.   a->devices = d;
  173.  
  174.   return 1;
  175. }
  176.  
  177. struct pci_dev *
  178. pci_get_dev(struct pci_access *a, int domain, int bus, int dev, int func)
  179. {
  180.   struct pci_dev *d = pci_alloc_dev(a);
  181.  
  182.   d->domain = domain;
  183.   d->bus = bus;
  184.   d->dev = dev;
  185.   d->func = func;
  186.   return d;
  187. }
  188.  
  189. void pci_free_dev(struct pci_dev *d)
  190. {
  191.   if (d->methods->cleanup_dev)
  192.     d->methods->cleanup_dev(d);
  193.   pci_mfree(d);
  194. }
  195.  
  196. static inline void
  197. pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
  198. {
  199.   if (pos & (len-1))
  200.     d->access->error("Unaligned read: pos=%02x, len=%d", pos, len);
  201.   if (pos + len <= d->cache_len)
  202.     memcpy(buf, d->cache + pos, len);
  203.   else if (!d->methods->read(d, pos, buf, len))
  204.     memset(buf, 0xff, len);
  205. }
  206.  
  207. byte
  208. pci_read_byte(struct pci_dev *d, int pos)
  209. {
  210.   byte buf;
  211.   pci_read_data(d, &buf, pos, 1);
  212.   return buf;
  213. }
  214.  
  215. word
  216. pci_read_word(struct pci_dev *d, int pos)
  217. {
  218.   word buf;
  219.   pci_read_data(d, &buf, pos, 2);
  220.   return le16_to_cpu(buf);
  221. }
  222.  
  223. u32
  224. pci_read_long(struct pci_dev *d, int pos)
  225. {
  226.   u32 buf;
  227.   pci_read_data(d, &buf, pos, 4);
  228.   return le32_to_cpu(buf);
  229. }
  230.  
  231. int
  232. pci_read_block(struct pci_dev *d, int pos, byte *buf, int len)
  233. {
  234.   return d->methods->read(d, pos, buf, len);
  235. }
  236.  
  237. static inline int
  238. pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
  239. {
  240.   if (pos & (len-1))
  241.     d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
  242.   if (pos + len <= d->cache_len)
  243.     memcpy(d->cache + pos, buf, len);
  244.   return d->methods->write(d, pos, buf, len);
  245. }
  246.  
  247. int
  248. pci_write_byte(struct pci_dev *d, int pos, byte data)
  249. {
  250.   return pci_write_data(d, &data, pos, 1);
  251. }
  252.  
  253. int
  254. pci_write_word(struct pci_dev *d, int pos, word data)
  255. {
  256.   word buf = cpu_to_le16(data);
  257.   return pci_write_data(d, &buf, pos, 2);
  258. }
  259.  
  260. int
  261. pci_write_long(struct pci_dev *d, int pos, u32 data)
  262. {
  263.   u32 buf = cpu_to_le32(data);
  264.   return pci_write_data(d, &buf, pos, 4);
  265. }
  266.  
  267. int
  268. pci_write_block(struct pci_dev *d, int pos, byte *buf, int len)
  269. {
  270.   if (pos < d->cache_len)
  271.     {
  272.       int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len;
  273.       memcpy(d->cache + pos, buf, l);
  274.     }
  275.   return d->methods->write(d, pos, buf, len);
  276. }
  277.  
  278. int
  279. pci_fill_info(struct pci_dev *d, int flags)
  280. {
  281.   if (flags & PCI_FILL_RESCAN)
  282.     {
  283.       flags &= ~PCI_FILL_RESCAN;
  284.       d->known_fields = 0;
  285.     }
  286.   if (flags & ~d->known_fields)
  287.     d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
  288.   return d->known_fields;
  289. }
  290.  
  291. void
  292. pci_setup_cache(struct pci_dev *d, byte *cache, int len)
  293. {
  294.   d->cache = cache;
  295.   d->cache_len = len;
  296. }
  297.