Subversion Repositories shark

Rev

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

Rev Author Line No. Line
2 pj 1
#include <ll/i386/hw-instr.h>
2
#include <ll/i386/hw-data.h>
3
#include <ll/i386/hw-arch.h>
4
#include <ll/i386/hw-io.h>
5
#include <ll/i386/cons.h>
6
#include <ll/i386/mem.h>
7
#include <ll/stdlib.h>
8
#include <drivers/llpci.h>
9
#include <drivers/pci.h>
10
#include <drivers/linuxpci.h>
16 pj 11
#include <kernel/log.h>
2 pj 12
 
16 pj 13
//#define DEBUG_PCISCAN
14
 
2 pj 15
static struct pci_dev pci_devs[N_MAX_DEVS];
16
 
17
static struct pci_bus pci_root;
18
static struct pci_dev *pci_devices = NULL;
19
 
20
/* scan the bus to find all the connected devices */
21
DWORD pci_scan_bus(struct pci_bus *bus)
22
{
23
    int ndev;
24
    DWORD tmp;
25
    DWORD max;
26
    BYTE hdr, irq1;
27
    int ok;
28
    WORD dev;
29
    struct pci_dev **bus_last;
30
    struct pci_dev *device = NULL;
31
    int present;
32
 
33
    max = bus->secondary;
34
    bus_last = &bus->devices;
35
 
36
    if (pcibios_present() == 0) return -1;
37
    ndev = 0;
38
 
39
    for (dev = 0; dev <= 0xFF; dev++) {
40
        present = 0;
41
        if ((dev & 0x07) == 0) {
42
            present = pcibios_read_config_byte(bus->number, dev, 0x0e, &hdr);
43
        }
44
        if (hdr & 0x80) {
45
            present = 1;
46
        }
47
        if (present) {
48
            ok = pcibios_read_config_dword(bus->number, dev, 0, &tmp);
49
            if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) {
50
                /* Got a PCI Device!!! */
51
                device = &(pci_devs[ndev++]);
52
                device->bus = bus;
53
                device->devfn  = dev;
54
                device->vendor = tmp & 0xffff;
55
                device->device = (tmp >> 16) & 0xffff;
56
 
57
 
58
                /* This is by Luca... We need to set base_addr */
59
                pcibios_read_config_dword(bus->number, dev, PCI_BASE_ADDRESS_0, &(device->base_address[0]));
60
 
61
 
62
                /* ...and also the interrupt number!!! */
63
                pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1);
64
                device->irq = irq1;
65
 
66
#if 0
67
                pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
68
                class >>= 8;                                /* upper 3 bytes */
69
                dev->class = class;
70
                class >>= 8;
71
                dev->hdr_type = hdr;
72
 
73
                switch (hdr_type & 0x7f) {                  /* header type */
74
                case PCI_HEADER_TYPE_NORMAL:                /* standard header */
75
                        if (class == PCI_CLASS_BRIDGE_PCI)
76
                                goto bad;
77
                        /*
78
                         * If the card generates interrupts, read IRQ number
79
                         * (some architectures change it during pcibios_fixup())
80
                         */
81
                        pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
82
                        if (irq)
83
                                pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
84
                        dev->irq = irq;
85
                        /*
86
                         * read base address registers, again pcibios_fixup() can
87
                         * tweak these
88
                         */
89
                        pci_read_bases(dev, 6);
90
                        pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
91
                        dev->rom_address = (l == 0xffffffff) ? 0 : l;
92
                        break;
93
                case PCI_HEADER_TYPE_BRIDGE:                /* bridge header */
94
                        if (class != PCI_CLASS_BRIDGE_PCI)
95
                                goto bad;
96
                        pci_read_bases(dev, 2);
97
                        pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
98
                        dev->rom_address = (l == 0xffffffff) ? 0 : l;
99
                        break;
100
                        case PCI_HEADER_TYPE_CARDBUS:               /* CardBus bridge header */
101
                        if (class != PCI_CLASS_BRIDGE_CARDBUS)
102
                                goto bad;
103
                        pci_read_bases(dev, 1);
104
                        break;
105
                default:                                    /* unknown header */
106
                bad:
107
                        printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
108
                               bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
109
                        continue;
110
                }
111
 
112
                DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device);
113
#endif
114
 
115
                device->next = pci_devices;
116
                pci_devices = device;
117
 
118
                /*
119
                 * Now insert it into the list of devices held
120
                 * by the parent bus.
121
                 */
122
                *bus_last = device;
123
                bus_last = &device->sibling;
124
 
125
 
126
 
127
            }
128
        }
129
    }
130
 
131
 
132
    for(device = bus->devices; device; device = device->sibling) {
133
#if 0
134
        /*
135
        * If it's a bridge, scan the bus behind it.
136
        */
137
        if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
138
            unsigned int buses;
139
            unsigned int devfn = dev->devfn;
140
            unsigned short cr;
141
 
142
            /*
143
             * Insert it into the tree of buses.
144
             */
145
            child = kmalloc(sizeof(*child), GFP_ATOMIC);
146
            if(child==NULL) {
16 pj 147
#ifdef DEBUG_PCISCAN
148
            printk(KERN_ERR "pci: out of memory for bridge.\n");
149
#endif
2 pj 150
                continue;
151
            }
152
            memset(child, 0, sizeof(*child));
153
            child->next = bus->children;
154
            bus->children = child;
155
            child->self = dev;
156
            child->parent = bus;
157
 
158
            /*
159
             * Set up the primary, secondary and subordinate
160
             * bus numbers.
161
             */
162
            child->number = child->secondary = ++max;
163
            child->primary = bus->secondary;
164
            child->subordinate = 0xff;
165
            /*
166
             * Clear all status bits and turn off memory,
167
             * I/O and master enables.
168
             */
169
            pcibios_read_config_word(bus->number, devfn, PCI_COMMAND, &cr);
170
            pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, 0x0000);
171
            pcibios_write_config_word(bus->number, devfn, PCI_STATUS, 0xffff);
172
            /*
173
             * Read the existing primary/secondary/subordinate bus
174
             * number configuration to determine if the PCI bridge
175
             * has already been configured by the system.  If so,
176
             * do not modify the configuration, merely note it.
177
             */
178
            pcibios_read_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, &buses);
179
            if ((buses & 0xFFFFFF) != 0) {
180
                unsigned int cmax;
181
 
182
                child->primary = buses & 0xFF;
183
                child->secondary = (buses >> 8) & 0xFF;
184
                child->subordinate = (buses >> 16) & 0xFF;
185
                child->number = child->secondary;
186
                cmax = pci_scan_bus(child);
187
                if (cmax > max) max = cmax;
188
            } else {
189
                /*
190
                 * Configure the bus numbers for this bridge:
191
                 */
192
                buses &= 0xff000000;
193
                buses |= (((unsigned int)(child->primary)     <<  0) |
194
                        ((unsigned int)(child->secondary)   <<  8) |
195
                        ((unsigned int)(child->subordinate) << 16));
196
                pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
197
                /*
198
                 * Now we can scan all subordinate buses:
199
                 */
200
                max = pci_scan_bus(child);
201
                /*
202
                 * Set the subordinate bus number to its real
203
                 * value:
204
                 */
205
                child->subordinate = max;
206
                buses = (buses & 0xff00ffff)
207
                | ((unsigned int)(child->subordinate) << 16);
208
                pcibios_write_config_dword(bus->number, devfn, PCI_PRIMARY_BUS, buses);
209
            }
210
            pcibios_write_config_word(bus->number, devfn, PCI_COMMAND, cr);
211
        }
212
#endif
213
    }
214
 
215
    return max;
216
}
217
 
218
 
219
void linuxpci_init(void)
220
{
221
    pcibios_init();
222
 
223
    if (!pci_present()) {
16 pj 224
#ifdef DEBUG_PCISCAN
225
        printk("PCI: No PCI bus detected\n");
226
#endif
2 pj 227
        return;
228
    }
229
 
16 pj 230
#ifdef DEBUG_PCISCAN
231
    printk("PCI: Probing PCI hardware\n");
232
#endif
2 pj 233
    memset(&pci_root, 0, sizeof(pci_root));
234
    pci_root.subordinate = pci_scan_bus(&pci_root);
235
}
236
 
237
struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
238
{
239
        if (!from)
240
                from = pci_devices;
241
        else
242
                from = from->next;
243
        while (from && (from->vendor != vendor || from->device != device))
244
                from = from->next;
245
        return from;
246
}
247
 
248
struct pci_dev *pci_find_class(unsigned int class, struct pci_dev *from)
249
{
250
        if (!from)
251
                from = pci_devices;
252
        else
253
                from = from->next;
254
        while (from && from->class != class)
255
                from = from->next;
256
 
257
cprintf("PCI_FIND_CLASS: found %p at bus %d\n", from, from->bus->number);
258
        return from;
259
}
260
 
261
struct pci_dev *
262
pci_find_slot(unsigned int bus, unsigned int devfn)
263
{
264
        struct pci_dev *dev;
265
 
266
        for(dev=pci_devices; dev; dev=dev->next)
267
                if (dev->bus->number == bus && dev->devfn == devfn) {
268
cprintf("FOUND!!!!!!!!!!\n");
269
                        break;
270
                } else {
271
cprintf("NOT FOUND! %d!=%d %d!=%d\n", dev->bus->number, bus, dev->devfn, devfn);
272
}
273
cprintf("PCI_FIND_SLOT: found %p at bus %d\n", dev, dev->bus->number);
274
        return dev;
275
}