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