source: mainline/uspace/lib/libpci/access.c@ e5773c6

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since e5773c6 was e5773c6, checked in by Jiri Svoboda <jiri@…>, 15 years ago

Extract common makefile part for apps and servers, use for all apps and most servers.

  • Property mode set to 100644
File size: 5.2 KB
Line 
1/*
2 * The PCI Library -- User Access
3 *
4 * Copyright (c) 1997--2003 Martin Mares <mj@ucw.cz>
5 *
6 * May 8, 2006 - Modified and ported to HelenOS by Jakub Jermar.
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
18static struct pci_methods *pci_methods[PCI_ACCESS_MAX] = {
19 &pm_intel_conf1,
20 &pm_intel_conf2,
21};
22
23struct pci_access *pci_alloc(void)
24{
25 struct pci_access *a = malloc(sizeof(struct pci_access));
26 int i;
27
28 if (!a)
29 return NULL;
30
31 bzero(a, sizeof(*a));
32 for (i = 0; i < PCI_ACCESS_MAX; i++)
33 if (pci_methods[i] && pci_methods[i]->config)
34 pci_methods[i]->config(a);
35 return a;
36}
37
38void *pci_malloc(struct pci_access *a, int size)
39{
40 void *x = malloc(size);
41
42 if (!x)
43 a->error("Out of memory (allocation of %d bytes failed)", size);
44 return x;
45}
46
47void pci_mfree(void *x)
48{
49 if (x)
50 free(x);
51}
52
53static void pci_generic_error(char *msg, ...)
54{
55 va_list args;
56
57 va_start(args, msg);
58 puts("pcilib: ");
59 vprintf(msg, args);
60 putchar('\n');
61 exit(1);
62}
63
64static void pci_generic_warn(char *msg, ...)
65{
66 va_list args;
67
68 va_start(args, msg);
69 puts("pcilib: ");
70 vprintf(msg, args);
71 putchar('\n');
72}
73
74static void pci_generic_debug(char *msg, ...)
75{
76 va_list args;
77
78 va_start(args, msg);
79 vprintf(msg, args);
80 va_end(args);
81}
82
83static void pci_null_debug(char *msg UNUSED, ...)
84{
85}
86
87void pci_init(struct pci_access *a)
88{
89 if (!a->error)
90 a->error = pci_generic_error;
91 if (!a->warning)
92 a->warning = pci_generic_warn;
93 if (!a->debug)
94 a->debug = pci_generic_debug;
95 if (!a->debugging)
96 a->debug = pci_null_debug;
97
98 if (a->method) {
99 if (a->method >= PCI_ACCESS_MAX || !pci_methods[a->method])
100 a->error("This access method is not supported.");
101 a->methods = pci_methods[a->method];
102 } else {
103 unsigned int i;
104 for (i = 0; i < PCI_ACCESS_MAX; i++)
105 if (pci_methods[i]) {
106 a->debug("Trying method %d...", i);
107 if (pci_methods[i]->detect(a)) {
108 a->debug("...OK\n");
109 a->methods = pci_methods[i];
110 a->method = i;
111 break;
112 }
113 a->debug("...No.\n");
114 }
115 if (!a->methods)
116 a->error("Cannot find any working access method.");
117 }
118 a->debug("Decided to use %s\n", a->methods->name);
119 a->methods->init(a);
120}
121
122void pci_cleanup(struct pci_access *a)
123{
124 struct pci_dev *d, *e;
125
126 for (d = a->devices; d; d = e) {
127 e = d->next;
128 pci_free_dev(d);
129 }
130 if (a->methods)
131 a->methods->cleanup(a);
132 pci_free_name_list(a);
133 pci_mfree(a);
134}
135
136void pci_scan_bus(struct pci_access *a)
137{
138 a->methods->scan(a);
139}
140
141struct pci_dev *pci_alloc_dev(struct pci_access *a)
142{
143 struct pci_dev *d = pci_malloc(a, sizeof(struct pci_dev));
144
145 bzero(d, sizeof(*d));
146 d->access = a;
147 d->methods = a->methods;
148 d->hdrtype = -1;
149 if (d->methods->init_dev)
150 d->methods->init_dev(d);
151 return d;
152}
153
154int pci_link_dev(struct pci_access *a, struct pci_dev *d)
155{
156 d->next = a->devices;
157 a->devices = d;
158
159 return 1;
160}
161
162struct pci_dev *pci_get_dev(struct pci_access *a, int domain, int bus,
163 int dev, int func)
164{
165 struct pci_dev *d = pci_alloc_dev(a);
166
167 d->domain = domain;
168 d->bus = bus;
169 d->dev = dev;
170 d->func = func;
171 return d;
172}
173
174void pci_free_dev(struct pci_dev *d)
175{
176 if (d->methods->cleanup_dev)
177 d->methods->cleanup_dev(d);
178 pci_mfree(d);
179}
180
181static inline void
182pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
183{
184 if (pos & (len - 1))
185 d->access->error("Unaligned read: pos=%02x, len=%d", pos,
186 len);
187 if (pos + len <= d->cache_len)
188 memcpy(buf, d->cache + pos, len);
189 else if (!d->methods->read(d, pos, buf, len))
190 memset(buf, 0xff, len);
191}
192
193byte pci_read_byte(struct pci_dev *d, int pos)
194{
195 byte buf;
196 pci_read_data(d, &buf, pos, 1);
197 return buf;
198}
199
200word pci_read_word(struct pci_dev * d, int pos)
201{
202 word buf;
203 pci_read_data(d, &buf, pos, 2);
204 return le16_to_cpu(buf);
205}
206
207u32 pci_read_long(struct pci_dev * d, int pos)
208{
209 u32 buf;
210 pci_read_data(d, &buf, pos, 4);
211 return le32_to_cpu(buf);
212}
213
214int pci_read_block(struct pci_dev *d, int pos, byte * buf, int len)
215{
216 return d->methods->read(d, pos, buf, len);
217}
218
219static inline int
220pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
221{
222 if (pos & (len - 1))
223 d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
224 if (pos + len <= d->cache_len)
225 memcpy(d->cache + pos, buf, len);
226 return d->methods->write(d, pos, buf, len);
227}
228
229int pci_write_byte(struct pci_dev *d, int pos, byte data)
230{
231 return pci_write_data(d, &data, pos, 1);
232}
233
234int pci_write_word(struct pci_dev *d, int pos, word data)
235{
236 word buf = cpu_to_le16(data);
237 return pci_write_data(d, &buf, pos, 2);
238}
239
240int pci_write_long(struct pci_dev *d, int pos, u32 data)
241{
242 u32 buf = cpu_to_le32(data);
243 return pci_write_data(d, &buf, pos, 4);
244}
245
246int pci_write_block(struct pci_dev *d, int pos, byte * buf, int len)
247{
248 if (pos < d->cache_len) {
249 int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len;
250 memcpy(d->cache + pos, buf, l);
251 }
252 return d->methods->write(d, pos, buf, len);
253}
254
255int pci_fill_info(struct pci_dev *d, int flags)
256{
257 if (flags & PCI_FILL_RESCAN) {
258 flags &= ~PCI_FILL_RESCAN;
259 d->known_fields = 0;
260 }
261 if (flags & ~d->known_fields)
262 d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
263 return d->known_fields;
264}
265
266void pci_setup_cache(struct pci_dev *d, byte * cache, int len)
267{
268 d->cache = cache;
269 d->cache_len = len;
270}
Note: See TracBrowser for help on using the repository browser.