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