Subversion Repositories HelenOS

Rev

Rev 1787 | Details | Compare with Previous | Last modification | View Log | RSS feed

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