source: mainline/uspace/pci/libpci/access.c@ 14de0dd8

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 14de0dd8 was 0166e99, checked in by jermar <jermar@…>, 17 years ago

Merge the uspace branch.

  • Property mode set to 100644
File size: 5.2 KB
RevLine 
[4a7c273]1/*
2 * The PCI Library -- User Access
3 *
4 * Copyright (c) 1997--2003 Martin Mares <mj@ucw.cz>
5 *
[8071af9f]6 * May 8, 2006 - Modified and ported to HelenOS by Jakub Jermar.
[4a7c273]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] = {
[20a9b85]19 &pm_intel_conf1,
20 &pm_intel_conf2,
[4a7c273]21};
22
[20a9b85]23struct pci_access *pci_alloc(void)
[4a7c273]24{
[20a9b85]25 struct pci_access *a = malloc(sizeof(struct pci_access));
26 int i;
27
[46ec2c06]28 if (!a)
29 return NULL;
30
[20a9b85]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;
[4a7c273]36}
37
[20a9b85]38void *pci_malloc(struct pci_access *a, int size)
[4a7c273]39{
[20a9b85]40 void *x = malloc(size);
[4a7c273]41
[20a9b85]42 if (!x)
[46ec2c06]43 a->error("Out of memory (allocation of %d bytes failed)", size);
[20a9b85]44 return x;
[4a7c273]45}
46
[20a9b85]47void pci_mfree(void *x)
[4a7c273]48{
[20a9b85]49 if (x)
50 free(x);
[4a7c273]51}
52
[20a9b85]53static void pci_generic_error(char *msg, ...)
[4a7c273]54{
[20a9b85]55 va_list args;
[4a7c273]56
[20a9b85]57 va_start(args, msg);
58 puts("pcilib: ");
59 vprintf(msg, args);
60 putchar('\n');
61 exit(1);
[4a7c273]62}
63
[20a9b85]64static void pci_generic_warn(char *msg, ...)
[4a7c273]65{
[20a9b85]66 va_list args;
[4a7c273]67
[20a9b85]68 va_start(args, msg);
69 puts("pcilib: ");
70 vprintf(msg, args);
71 putchar('\n');
[4a7c273]72}
73
[20a9b85]74static void pci_generic_debug(char *msg, ...)
[4a7c273]75{
[20a9b85]76 va_list args;
[4a7c273]77
[20a9b85]78 va_start(args, msg);
79 vprintf(msg, args);
80 va_end(args);
[4a7c273]81}
82
[20a9b85]83static void pci_null_debug(char *msg UNUSED, ...)
[4a7c273]84{
85}
86
[20a9b85]87void pci_init(struct pci_access *a)
[4a7c273]88{
[20a9b85]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);
[4a7c273]120}
121
[20a9b85]122void pci_cleanup(struct pci_access *a)
[4a7c273]123{
[20a9b85]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);
[4a7c273]134}
135
[20a9b85]136void pci_scan_bus(struct pci_access *a)
[4a7c273]137{
[20a9b85]138 a->methods->scan(a);
[4a7c273]139}
140
[20a9b85]141struct pci_dev *pci_alloc_dev(struct pci_access *a)
[4a7c273]142{
[20a9b85]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;
[4a7c273]152}
153
[20a9b85]154int pci_link_dev(struct pci_access *a, struct pci_dev *d)
[4a7c273]155{
[20a9b85]156 d->next = a->devices;
157 a->devices = d;
[4a7c273]158
[20a9b85]159 return 1;
[4a7c273]160}
161
[20a9b85]162struct pci_dev *pci_get_dev(struct pci_access *a, int domain, int bus,
163 int dev, int func)
[4a7c273]164{
[20a9b85]165 struct pci_dev *d = pci_alloc_dev(a);
[4a7c273]166
[20a9b85]167 d->domain = domain;
168 d->bus = bus;
169 d->dev = dev;
170 d->func = func;
171 return d;
[4a7c273]172}
173
174void pci_free_dev(struct pci_dev *d)
175{
[20a9b85]176 if (d->methods->cleanup_dev)
177 d->methods->cleanup_dev(d);
178 pci_mfree(d);
[4a7c273]179}
180
181static inline void
182pci_read_data(struct pci_dev *d, void *buf, int pos, int len)
183{
[20a9b85]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);
[4a7c273]191}
192
[20a9b85]193byte pci_read_byte(struct pci_dev *d, int pos)
[4a7c273]194{
[20a9b85]195 byte buf;
196 pci_read_data(d, &buf, pos, 1);
197 return buf;
[4a7c273]198}
199
[20a9b85]200word pci_read_word(struct pci_dev * d, int pos)
[4a7c273]201{
[20a9b85]202 word buf;
203 pci_read_data(d, &buf, pos, 2);
204 return le16_to_cpu(buf);
[4a7c273]205}
206
[20a9b85]207u32 pci_read_long(struct pci_dev * d, int pos)
[4a7c273]208{
[20a9b85]209 u32 buf;
210 pci_read_data(d, &buf, pos, 4);
211 return le32_to_cpu(buf);
[4a7c273]212}
213
[20a9b85]214int pci_read_block(struct pci_dev *d, int pos, byte * buf, int len)
[4a7c273]215{
[20a9b85]216 return d->methods->read(d, pos, buf, len);
[4a7c273]217}
218
219static inline int
220pci_write_data(struct pci_dev *d, void *buf, int pos, int len)
221{
[20a9b85]222 if (pos & (len - 1))
[46ec2c06]223 d->access->error("Unaligned write: pos=%02x,len=%d", pos, len);
[20a9b85]224 if (pos + len <= d->cache_len)
225 memcpy(d->cache + pos, buf, len);
226 return d->methods->write(d, pos, buf, len);
[4a7c273]227}
228
[20a9b85]229int pci_write_byte(struct pci_dev *d, int pos, byte data)
[4a7c273]230{
[20a9b85]231 return pci_write_data(d, &data, pos, 1);
[4a7c273]232}
233
[20a9b85]234int pci_write_word(struct pci_dev *d, int pos, word data)
[4a7c273]235{
[20a9b85]236 word buf = cpu_to_le16(data);
237 return pci_write_data(d, &buf, pos, 2);
[4a7c273]238}
239
[20a9b85]240int pci_write_long(struct pci_dev *d, int pos, u32 data)
[4a7c273]241{
[20a9b85]242 u32 buf = cpu_to_le32(data);
243 return pci_write_data(d, &buf, pos, 4);
[4a7c273]244}
245
[20a9b85]246int pci_write_block(struct pci_dev *d, int pos, byte * buf, int len)
[4a7c273]247{
[20a9b85]248 if (pos < d->cache_len) {
[46ec2c06]249 int l = (pos + len >= d->cache_len) ? (d->cache_len - pos) : len;
[20a9b85]250 memcpy(d->cache + pos, buf, l);
251 }
252 return d->methods->write(d, pos, buf, len);
[4a7c273]253}
254
[20a9b85]255int pci_fill_info(struct pci_dev *d, int flags)
[4a7c273]256{
[20a9b85]257 if (flags & PCI_FILL_RESCAN) {
258 flags &= ~PCI_FILL_RESCAN;
259 d->known_fields = 0;
260 }
261 if (flags & ~d->known_fields)
[46ec2c06]262 d->known_fields |= d->methods->fill_info(d, flags & ~d->known_fields);
[20a9b85]263 return d->known_fields;
[4a7c273]264}
265
[20a9b85]266void pci_setup_cache(struct pci_dev *d, byte * cache, int len)
[4a7c273]267{
[20a9b85]268 d->cache = cache;
269 d->cache_len = len;
[4a7c273]270}
Note: See TracBrowser for help on using the repository browser.