]> mj.ucw.cz Git - pciutils.git/blob - lib/access.c
343abd8446855282cca1264bb679d1704970e36e
[pciutils.git] / lib / access.c
1 /*
2  *      $Id: access.c,v 1.2 1999/01/24 21:35:35 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                 break;
143               }
144             a->debug("...No.\n");
145           }
146       if (!a->methods)
147         a->error("Cannot find any working access method.");
148     }
149   a->debug("Decided to use %s\n", a->methods->name);
150   a->methods->init(a);
151 }
152
153 void
154 pci_cleanup(struct pci_access *a)
155 {
156   struct pci_dev *d, *e;
157
158   for(d=a->devices; d; d=e)
159     {
160       e = d->next;
161       pci_free_dev(d);
162     }
163   if (a->methods)
164     a->methods->cleanup(a);
165   pci_free_name_list(a);
166   pci_mfree(a);
167 }
168
169 void
170 pci_scan_bus(struct pci_access *a)
171 {
172   a->methods->scan(a);
173 }
174
175 struct pci_dev *
176 pci_alloc_dev(struct pci_access *a)
177 {
178   struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev));
179
180   bzero(d, sizeof(*d));
181   d->access = a;
182   d->methods = a->methods;
183   if (d->methods->init_dev)
184     d->methods->init_dev(d);
185   return d;
186 }
187
188 int
189 pci_link_dev(struct pci_access *a, struct pci_dev *d)
190 {
191   d->next = a->devices;
192   a->devices = d;
193
194   return 1;
195 }
196
197 struct pci_dev *
198 pci_get_dev(struct pci_access *a, int bus, int dev, int func)
199 {
200   struct pci_dev *d = pci_alloc_dev(a);
201
202   d->bus = bus;
203   d->dev = dev;
204   d->func = func;
205   return d;
206 }
207
208 void pci_free_dev(struct pci_dev *d)
209 {
210   if (d->methods->cleanup_dev)
211     d->methods->cleanup_dev(d);
212   pci_mfree(d);
213 }
214
215 static inline void
216 pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
217 {
218   if (pos & (len-1))
219     d->access->error("Unaligned read: pos=%02x, len=%d", pos, len);
220   if (pos + len <= d->cache_len)
221     memcpy(buf, d->cache + pos, len);
222   else if (!d->methods->read(d, pos, buf, len))
223     memset(buf, 0xff, len);
224 }
225
226 byte
227 pci_read_byte(struct pci_dev *d, int pos)
228 {
229   byte buf;
230   pci_read_data(d, &buf, pos, 1);
231   return buf;
232 }
233
234 word
235 pci_read_word(struct pci_dev *d, int pos)
236 {
237   word buf;
238   pci_read_data(d, &buf, pos, 2);
239   return le16_to_cpu(buf);
240 }
241
242 u32
243 pci_read_long(struct pci_dev *d, int pos)
244 {
245   u32 buf;
246   pci_read_data(d, &buf, pos, 4);
247   return le32_to_cpu(buf);
248 }
249
250 int
251 pci_read_block(struct pci_dev *d, int pos, byte *buf, int len)
252 {
253   return d->methods->read(d, pos, buf, len);
254 }
255
256 static inline int
257 pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
258 {
259   if (pos & (len-1))
260     d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
261   if (pos + len <= d->cache_len)
262     memcpy(d->cache + pos, buf, len);
263   return d->methods->write(d, pos, buf, len);
264 }
265
266 int
267 pci_write_byte(struct pci_dev *d, int pos, byte data)
268 {
269   return pci_write_data(d, &data, pos, 1);
270 }
271
272 int
273 pci_write_word(struct pci_dev *d, int pos, word data)
274 {
275   word buf = cpu_to_le16(data);
276   return pci_write_data(d, &buf, pos, 2);
277 }
278
279 int
280 pci_write_long(struct pci_dev *d, int pos, u32 data)
281 {
282   u32 buf = cpu_to_le32(data);
283   return pci_write_data(d, &buf, pos, 4);
284 }
285
286 int
287 pci_write_block(struct pci_dev *d, int pos, byte *buf, int len)
288 {
289   if (pos < d->cache_len)
290     {
291       int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len;
292       memcpy(d->cache + pos, buf, l);
293     }
294   return d->methods->write(d, pos, buf, len);
295 }
296
297 void
298 pci_fill_info(struct pci_dev *d, int flags)
299 {
300   if (flags & PCI_FILL_RESCAN)
301     {
302       flags &= ~PCI_FILL_RESCAN;
303       d->known_fields = 0;
304     }
305   if (flags & ~d->known_fields)
306     d->methods->fill_info(d, flags & ~d->known_fields);
307   d->known_fields |= flags;
308 }
309
310 void
311 pci_setup_cache(struct pci_dev *d, byte *cache, int len)
312 {
313   d->cache = cache;
314   d->cache_len = len;
315 }