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