Subversion Repositories shark

Rev

Details | 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/error.h>
7
#include <ll/i386/mem.h>
8
 
9
#include <ll/stdlib.h>
10
 
11
 
12
 
13
#include <drivers/llpci.h>
14
#include <drivers/pci.h>
15
#include <drivers/linuxpci.h>
16
 
17
static struct pci_dev pci_devs[N_MAX_DEVS];
18
 
19
static struct pci_bus pci_root;
20
static struct pci_dev *pci_devices = NULL;
21
 
22
/* scan the bus to find all the connected devices */
23
DWORD pci_scan_bus(struct pci_bus *bus)
24
{
25
    int ndev;
26
    DWORD tmp;
27
    DWORD max;
28
    BYTE hdr, irq1;
29
    int ok;
30
    WORD dev;
31
    struct pci_dev **bus_last;
32
    struct pci_dev *device = NULL;
33
    int present;
34
 
35
    max = bus->secondary;
36
    bus_last = &bus->devices;
37
 
38
    if (pcibios_present() == 0) return -1;
39
    ndev = 0;
40
 
41
    for (dev = 0; dev <= 0xFF; dev++) {
42
        present = 0;
43
        if ((dev & 0x07) == 0) {
44
            present = pcibios_read_config_byte(bus->number, dev, 0x0e, &hdr);
45
        }
46
        if (hdr & 0x80) {
47
            present = 1;
48
        }
49
        if (present) {
50
            ok = pcibios_read_config_dword(bus->number, dev, 0, &tmp);
51
            if ( ok && (((tmp & 0xFFFF) != 0xFFFF) && ((tmp >> 16) != 0xFFFF))) {
52
                /* Got a PCI Device!!! */
53
                device = &(pci_devs[ndev++]);
54
                device->bus = bus;
55
                device->devfn  = dev;
56
                device->vendor = tmp & 0xffff;
57
                device->device = (tmp >> 16) & 0xffff;
58
 
59
 
60
                /* This is by Luca... We need to set base_addr */
61
                pcibios_read_config_dword(bus->number, dev, PCI_BASE_ADDRESS_0, &(device->base_address[0]));
62
 
63
 
64
                /* ...and also the interrupt number!!! */
65
                pcibios_read_config_byte(bus->number, dev, PCI_INTERRUPT_LINE, &irq1);
66
                device->irq = irq1;
67
 
68
#if 0
69
                pcibios_read_config_dword(bus->number, devfn, PCI_CLASS_REVISION, &class);
70
                class >>= 8;                                /* upper 3 bytes */
71
                dev->class = class;
72
                class >>= 8;
73
                dev->hdr_type = hdr;
74
 
75
                switch (hdr_type & 0x7f) {                  /* header type */
76
                case PCI_HEADER_TYPE_NORMAL:                /* standard header */
77
                        if (class == PCI_CLASS_BRIDGE_PCI)
78
                                goto bad;
79
                        /*
80
                         * If the card generates interrupts, read IRQ number
81
                         * (some architectures change it during pcibios_fixup())
82
                         */
83
                        pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_PIN, &irq);
84
                        if (irq)
85
                                pcibios_read_config_byte(bus->number, dev->devfn, PCI_INTERRUPT_LINE, &irq);
86
                        dev->irq = irq;
87
                        /*
88
                         * read base address registers, again pcibios_fixup() can
89
                         * tweak these
90
                         */
91
                        pci_read_bases(dev, 6);
92
                        pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS, &l);
93
                        dev->rom_address = (l == 0xffffffff) ? 0 : l;
94
                        break;
95
                case PCI_HEADER_TYPE_BRIDGE:                /* bridge header */
96
                        if (class != PCI_CLASS_BRIDGE_PCI)
97
                                goto bad;
98
                        pci_read_bases(dev, 2);
99
                        pcibios_read_config_dword(bus->number, devfn, PCI_ROM_ADDRESS1, &l);
100
                        dev->rom_address = (l == 0xffffffff) ? 0 : l;
101
                        break;
102
                        case PCI_HEADER_TYPE_CARDBUS:               /* CardBus bridge header */
103
                        if (class != PCI_CLASS_BRIDGE_CARDBUS)
104
                                goto bad;
105
                        pci_read_bases(dev, 1);
106
                        break;
107
                default:                                    /* unknown header */
108
                bad:
109
                        printk(KERN_ERR "PCI: %02x:%02x [%04x/%04x/%06x] has unknown header type %02x, ignoring.\n",
110
                               bus->number, dev->devfn, dev->vendor, dev->device, class, hdr_type);
111
                        continue;
112
                }
113
 
114
                DBG("PCI: %02x:%02x [%04x/%04x]\n", bus->number, dev->devfn, dev->vendor, dev->device);
115
#endif
116
 
117
                device->next = pci_devices;
118
                pci_devices = device;
119
 
120
                /*
121
                 * Now insert it into the list of devices held
122
                 * by the parent bus.
123
                 */
124
                *bus_last = device;
125
                bus_last = &device->sibling;
126
 
127
 
128
 
129
            }
130
        }
131
    }
132
 
133
 
134
    for(device = bus->devices; device; device = device->sibling) {
135
#if 0
136
        /*
137
        * If it's a bridge, scan the bus behind it.
138
        */
139
        if ((dev->class >> 8) == PCI_CLASS_BRIDGE_PCI) {
140
            unsigned int buses;
141
            unsigned int devfn = dev->devfn;
142
            unsigned short cr;
143
 
144
            /*
145
             * Insert it into the tree of buses.
146
             */
147
            child = kmalloc(sizeof(*child), GFP_ATOMIC);
148
            if(child==NULL) {
149
            error(KERN_ERR "pci: out of memory for bridge.\n");
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()) {
224
        error("PCI: No PCI bus detected\n");
225
        return;
226
    }
227
 
228
    error("PCI: Probing PCI hardware\n");
229
    memset(&pci_root, 0, sizeof(pci_root));
230
    pci_root.subordinate = pci_scan_bus(&pci_root);
231
}
232
 
233
struct pci_dev *pci_find_device(unsigned int vendor, unsigned int device, struct pci_dev *from)
234
{
235
        if (!from)
236
                from = pci_devices;
237
        else
238
                from = from->next;
239
        while (from && (from->vendor != vendor || from->device != device))
240
                from = from->next;
241
        return from;
242
}
243
 
244
struct pci_dev *pci_find_class(unsigned int class, struct pci_dev *from)
245
{
246
        if (!from)
247
                from = pci_devices;
248
        else
249
                from = from->next;
250
        while (from && from->class != class)
251
                from = from->next;
252
 
253
cprintf("PCI_FIND_CLASS: found %p at bus %d\n", from, from->bus->number);
254
        return from;
255
}
256
 
257
struct pci_dev *
258
pci_find_slot(unsigned int bus, unsigned int devfn)
259
{
260
        struct pci_dev *dev;
261
 
262
        for(dev=pci_devices; dev; dev=dev->next)
263
                if (dev->bus->number == bus && dev->devfn == devfn) {
264
cprintf("FOUND!!!!!!!!!!\n");
265
                        break;
266
                } else {
267
cprintf("NOT FOUND! %d!=%d %d!=%d\n", dev->bus->number, bus, dev->devfn, devfn);
268
}
269
cprintf("PCI_FIND_SLOT: found %p at bus %d\n", dev, dev->bus->number);
270
        return dev;
271
}