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