Subversion Repositories HelenOS-historic

Rev

Rev 1302 | Go to most recent revision | Only display areas with differences | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

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