~ubuntu-branches/ubuntu/oneiric/seabios/oneiric

« back to all changes in this revision

Viewing changes to .pc/0053-seabios-pciinit-use-pci-device-initializer-helper-fu.patch/src/pciinit.c

  • Committer: Bazaar Package Importer
  • Author(s): Serge Hallyn
  • Date: 2010-10-22 11:04:31 UTC
  • Revision ID: james.westby@ubuntu.com-20101022110431-fnfj73ra6xkq623n
Tags: 0.6.0-0ubuntu2
Add all patches which were included in qemu-0.13.0-rc2 (per
commit on Jul 13, 2010).

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// Initialize PCI devices (on emulators)
 
2
//
 
3
// Copyright (C) 2008  Kevin O'Connor <kevin@koconnor.net>
 
4
// Copyright (C) 2006 Fabrice Bellard
 
5
//
 
6
// This file may be distributed under the terms of the GNU LGPLv3 license.
 
7
 
 
8
#include "util.h" // dprintf
 
9
#include "pci.h" // pci_config_readl
 
10
#include "biosvar.h" // GET_EBDA
 
11
#include "pci_ids.h" // PCI_VENDOR_ID_INTEL
 
12
#include "pci_regs.h" // PCI_COMMAND
 
13
 
 
14
#define PCI_ROM_SLOT 6
 
15
#define PCI_NUM_REGIONS 7
 
16
 
 
17
static void pci_bios_init_device_in_bus(int bus);
 
18
 
 
19
static u32 pci_bios_io_addr;
 
20
static u32 pci_bios_mem_addr;
 
21
static u32 pci_bios_prefmem_addr;
 
22
/* host irqs corresponding to PCI irqs A-D */
 
23
static u8 pci_irqs[4] = {
 
24
    10, 10, 11, 11
 
25
};
 
26
 
 
27
static u32 pci_bar(u16 bdf, int region_num)
 
28
{
 
29
    if (region_num != PCI_ROM_SLOT) {
 
30
        return PCI_BASE_ADDRESS_0 + region_num * 4;
 
31
    }
 
32
 
 
33
#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 
34
    u8 type = pci_config_readb(bdf, PCI_HEADER_TYPE);
 
35
    type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
 
36
    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
 
37
}
 
38
 
 
39
static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 
40
{
 
41
    u32 ofs, old_addr;
 
42
 
 
43
    ofs = pci_bar(bdf, region_num);
 
44
 
 
45
    old_addr = pci_config_readl(bdf, ofs);
 
46
 
 
47
    pci_config_writel(bdf, ofs, addr);
 
48
    dprintf(1, "region %d: 0x%08x\n", region_num, addr);
 
49
}
 
50
 
 
51
/*
 
52
 * return value
 
53
 *      0:     32bit BAR
 
54
 *      non 0: 64bit BAR
 
55
 */
 
56
static int pci_bios_allocate_region(u16 bdf, int region_num)
 
57
{
 
58
    u32 *paddr;
 
59
    u32 ofs = pci_bar(bdf, region_num);
 
60
 
 
61
    u32 old = pci_config_readl(bdf, ofs);
 
62
    u32 mask;
 
63
    if (region_num == PCI_ROM_SLOT) {
 
64
        mask = PCI_ROM_ADDRESS_MASK;
 
65
        pci_config_writel(bdf, ofs, mask);
 
66
    } else {
 
67
        if (old & PCI_BASE_ADDRESS_SPACE_IO)
 
68
            mask = PCI_BASE_ADDRESS_IO_MASK;
 
69
        else
 
70
            mask = PCI_BASE_ADDRESS_MEM_MASK;
 
71
        pci_config_writel(bdf, ofs, ~0);
 
72
    }
 
73
    u32 val = pci_config_readl(bdf, ofs);
 
74
    pci_config_writel(bdf, ofs, old);
 
75
 
 
76
    u32 size = (~(val & mask)) + 1;
 
77
    if (val != 0) {
 
78
        if (val & PCI_BASE_ADDRESS_SPACE_IO) {
 
79
            paddr = &pci_bios_io_addr;
 
80
            if (ALIGN(*paddr, size) + size >= 64 * 1024) {
 
81
                dprintf(1,
 
82
                        "io region of (bdf 0x%x bar %d) can't be mapped.\n",
 
83
                        bdf, region_num);
 
84
                size = 0;
 
85
            }
 
86
        } else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
 
87
                 /* keep behaviour on bus = 0 */
 
88
                 pci_bdf_to_bus(bdf) != 0 &&
 
89
                 /* If pci_bios_prefmem_addr == 0, keep old behaviour */
 
90
                 pci_bios_prefmem_addr != 0) {
 
91
            paddr = &pci_bios_prefmem_addr;
 
92
            if (ALIGN(*paddr, size) + size >= BUILD_PCIPREFMEM_END) {
 
93
                dprintf(1,
 
94
                        "prefmem region of (bdf 0x%x bar %d) can't be mapped. "
 
95
                        "decrease BUILD_PCIMEM_SIZE and recompile. size %x\n",
 
96
                        bdf, region_num, BUILD_PCIPREFMEM_SIZE);
 
97
                size = 0;
 
98
            }
 
99
        } else {
 
100
            paddr = &pci_bios_mem_addr;
 
101
            if (ALIGN(*paddr, size) + size >= BUILD_PCIMEM_END) {
 
102
                dprintf(1,
 
103
                        "mem region of (bdf 0x%x bar %d) can't be mapped. "
 
104
                        "increase BUILD_PCIMEM_SIZE and recompile. size %x\n",
 
105
                        bdf, region_num, BUILD_PCIMEM_SIZE);
 
106
                size = 0;
 
107
            }
 
108
        }
 
109
        if (size > 0) {
 
110
            *paddr = ALIGN(*paddr, size);
 
111
            pci_set_io_region_addr(bdf, region_num, *paddr);
 
112
            *paddr += size;
 
113
        }
 
114
    }
 
115
 
 
116
    int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
 
117
        (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
 
118
    if (is_64bit) {
 
119
        if (size > 0) {
 
120
            pci_config_writel(bdf, ofs + 4, 0);
 
121
        } else {
 
122
            pci_config_writel(bdf, ofs + 4, ~0);
 
123
        }
 
124
    }
 
125
    return is_64bit;
 
126
}
 
127
 
 
128
static void pci_bios_allocate_regions(u16 bdf)
 
129
{
 
130
    int i;
 
131
    for (i = 0; i < PCI_NUM_REGIONS; i++) {
 
132
        int is_64bit = pci_bios_allocate_region(bdf, i);
 
133
        if (is_64bit){
 
134
            i++;
 
135
        }
 
136
    }
 
137
}
 
138
 
 
139
/* return the global irq number corresponding to a given device irq
 
140
   pin. We could also use the bus number to have a more precise
 
141
   mapping. */
 
142
static int pci_slot_get_pirq(u16 bdf, int irq_num)
 
143
{
 
144
    int slot_addend = pci_bdf_to_dev(bdf) - 1;
 
145
    return (irq_num + slot_addend) & 3;
 
146
}
 
147
 
 
148
static void pci_bios_init_bridges(u16 bdf)
 
149
{
 
150
    u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
 
151
    u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
 
152
 
 
153
    if (vendor_id == PCI_VENDOR_ID_INTEL
 
154
        && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0
 
155
            || device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
 
156
        int i, irq;
 
157
        u8 elcr[2];
 
158
 
 
159
        /* PIIX3/PIIX4 PCI to ISA bridge */
 
160
 
 
161
        elcr[0] = 0x00;
 
162
        elcr[1] = 0x00;
 
163
        for (i = 0; i < 4; i++) {
 
164
            irq = pci_irqs[i];
 
165
            /* set to trigger level */
 
166
            elcr[irq >> 3] |= (1 << (irq & 7));
 
167
            /* activate irq remapping in PIIX */
 
168
            pci_config_writeb(bdf, 0x60 + i, irq);
 
169
        }
 
170
        outb(elcr[0], 0x4d0);
 
171
        outb(elcr[1], 0x4d1);
 
172
        dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n",
 
173
                elcr[0], elcr[1]);
 
174
    }
 
175
}
 
176
 
 
177
#define PCI_IO_ALIGN            4096
 
178
#define PCI_IO_SHIFT            8
 
179
#define PCI_MEMORY_ALIGN        (1UL << 20)
 
180
#define PCI_MEMORY_SHIFT        16
 
181
#define PCI_PREF_MEMORY_ALIGN   (1UL << 20)
 
182
#define PCI_PREF_MEMORY_SHIFT   16
 
183
 
 
184
static void pci_bios_init_device_bridge(u16 bdf)
 
185
{
 
186
    pci_bios_allocate_region(bdf, 0);
 
187
    pci_bios_allocate_region(bdf, 1);
 
188
    pci_bios_allocate_region(bdf, PCI_ROM_SLOT);
 
189
 
 
190
    u32 io_old = pci_bios_io_addr;
 
191
    u32 mem_old = pci_bios_mem_addr;
 
192
    u32 prefmem_old = pci_bios_prefmem_addr;
 
193
 
 
194
    /* IO BASE is assumed to be 16 bit */
 
195
    pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN);
 
196
    pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN);
 
197
    pci_bios_prefmem_addr =
 
198
        ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN);
 
199
 
 
200
    u32 io_base = pci_bios_io_addr;
 
201
    u32 mem_base = pci_bios_mem_addr;
 
202
    u32 prefmem_base = pci_bios_prefmem_addr;
 
203
 
 
204
    u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
 
205
    if (secbus > 0) {
 
206
        pci_bios_init_device_in_bus(secbus);
 
207
    }
 
208
 
 
209
    pci_bios_io_addr = ALIGN(pci_bios_io_addr, PCI_IO_ALIGN);
 
210
    pci_bios_mem_addr = ALIGN(pci_bios_mem_addr, PCI_MEMORY_ALIGN);
 
211
    pci_bios_prefmem_addr =
 
212
        ALIGN(pci_bios_prefmem_addr, PCI_PREF_MEMORY_ALIGN);
 
213
 
 
214
    u32 io_end = pci_bios_io_addr;
 
215
    if (io_end == io_base) {
 
216
        pci_bios_io_addr = io_old;
 
217
        io_base = 0xffff;
 
218
        io_end = 1;
 
219
    }
 
220
    pci_config_writeb(bdf, PCI_IO_BASE, io_base >> PCI_IO_SHIFT);
 
221
    pci_config_writew(bdf, PCI_IO_BASE_UPPER16, 0);
 
222
    pci_config_writeb(bdf, PCI_IO_LIMIT, (io_end - 1) >> PCI_IO_SHIFT);
 
223
    pci_config_writew(bdf, PCI_IO_LIMIT_UPPER16, 0);
 
224
 
 
225
    u32 mem_end = pci_bios_mem_addr;
 
226
    if (mem_end == mem_base) {
 
227
        pci_bios_mem_addr = mem_old;
 
228
        mem_base = 0xffffffff;
 
229
        mem_end = 1;
 
230
    }
 
231
    pci_config_writew(bdf, PCI_MEMORY_BASE, mem_base >> PCI_MEMORY_SHIFT);
 
232
    pci_config_writew(bdf, PCI_MEMORY_LIMIT, (mem_end -1) >> PCI_MEMORY_SHIFT);
 
233
 
 
234
    u32 prefmem_end = pci_bios_prefmem_addr;
 
235
    if (prefmem_end == prefmem_base) {
 
236
        pci_bios_prefmem_addr = prefmem_old;
 
237
        prefmem_base = 0xffffffff;
 
238
        prefmem_end = 1;
 
239
    }
 
240
    pci_config_writew(bdf, PCI_PREF_MEMORY_BASE,
 
241
                      prefmem_base >> PCI_PREF_MEMORY_SHIFT);
 
242
    pci_config_writew(bdf, PCI_PREF_MEMORY_LIMIT,
 
243
                      (prefmem_end - 1) >> PCI_PREF_MEMORY_SHIFT);
 
244
    pci_config_writel(bdf, PCI_PREF_BASE_UPPER32, 0);
 
245
    pci_config_writel(bdf, PCI_PREF_LIMIT_UPPER32, 0);
 
246
 
 
247
    dprintf(1, "PCI: br io   = [0x%x, 0x%x)\n", io_base, io_end);
 
248
    dprintf(1, "PCI: br mem  = [0x%x, 0x%x)\n", mem_base, mem_end);
 
249
    dprintf(1, "PCI: br pref = [0x%x, 0x%x)\n", prefmem_base, prefmem_end);
 
250
 
 
251
    u16 cmd = pci_config_readw(bdf, PCI_COMMAND);
 
252
    cmd &= ~PCI_COMMAND_IO;
 
253
    if (io_end > io_base) {
 
254
        cmd |= PCI_COMMAND_IO;
 
255
    }
 
256
    cmd &= ~PCI_COMMAND_MEMORY;
 
257
    if (mem_end > mem_base || prefmem_end > prefmem_base) {
 
258
        cmd |= PCI_COMMAND_MEMORY;
 
259
    }
 
260
    cmd |= PCI_COMMAND_MASTER;
 
261
    pci_config_writew(bdf, PCI_COMMAND, cmd);
 
262
 
 
263
    pci_config_maskw(bdf, PCI_BRIDGE_CONTROL, 0, PCI_BRIDGE_CTL_SERR);
 
264
}
 
265
 
 
266
static void pci_bios_init_device(u16 bdf)
 
267
{
 
268
    int class;
 
269
    int pin, pic_irq, vendor_id, device_id;
 
270
 
 
271
    class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
272
    vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
 
273
    device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
 
274
    dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
 
275
            , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf), vendor_id, device_id);
 
276
    switch (class) {
 
277
    case PCI_CLASS_STORAGE_IDE:
 
278
        if (vendor_id == PCI_VENDOR_ID_INTEL
 
279
            && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1
 
280
                || device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
 
281
            /* PIIX3/PIIX4 IDE */
 
282
            pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
 
283
            pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
 
284
            pci_bios_allocate_regions(bdf);
 
285
        } else {
 
286
            /* IDE: we map it as in ISA mode */
 
287
            pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
 
288
            pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
 
289
            pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
 
290
            pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
 
291
        }
 
292
        break;
 
293
    case PCI_CLASS_SYSTEM_PIC:
 
294
        /* PIC */
 
295
        if (vendor_id == PCI_VENDOR_ID_IBM) {
 
296
            /* IBM */
 
297
            if (device_id == 0x0046 || device_id == 0xFFFF) {
 
298
                /* MPIC & MPIC2 */
 
299
                pci_set_io_region_addr(bdf, 0, 0x80800000 + 0x00040000);
 
300
            }
 
301
        }
 
302
        break;
 
303
    case 0xff00:
 
304
        if (vendor_id == PCI_VENDOR_ID_APPLE &&
 
305
            (device_id == 0x0017 || device_id == 0x0022)) {
 
306
            /* macio bridge */
 
307
            pci_set_io_region_addr(bdf, 0, 0x80800000);
 
308
        }
 
309
        break;
 
310
    case PCI_CLASS_BRIDGE_PCI:
 
311
        pci_bios_init_device_bridge(bdf);
 
312
        break;
 
313
    default:
 
314
        /* default memory mappings */
 
315
        pci_bios_allocate_regions(bdf);
 
316
        break;
 
317
    }
 
318
 
 
319
    /* enable memory mappings */
 
320
    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
321
 
 
322
    /* map the interrupt */
 
323
    pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
 
324
    if (pin != 0) {
 
325
        pin = pci_slot_get_pirq(bdf, pin - 1);
 
326
        pic_irq = pci_irqs[pin];
 
327
        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
 
328
    }
 
329
 
 
330
    if (vendor_id == PCI_VENDOR_ID_INTEL
 
331
        && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
 
332
        /* PIIX4 Power Management device (for ACPI) */
 
333
 
 
334
        // acpi sci is hardwired to 9
 
335
        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
 
336
 
 
337
        pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
 
338
        pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
 
339
        pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
 
340
        pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
 
341
    }
 
342
}
 
343
 
 
344
static void pci_bios_init_device_in_bus(int bus)
 
345
{
 
346
    int bdf, max;
 
347
    foreachpci_in_bus(bdf, max, bus) {
 
348
        pci_bios_init_device(bdf);
 
349
    }
 
350
}
 
351
 
 
352
static void
 
353
pci_bios_init_bus_rec(int bus, u8 *pci_bus)
 
354
{
 
355
    int bdf, max;
 
356
    u16 class;
 
357
 
 
358
    dprintf(1, "PCI: %s bus = 0x%x\n", __func__, bus);
 
359
 
 
360
    /* prevent accidental access to unintended devices */
 
361
    foreachpci_in_bus(bdf, max, bus) {
 
362
        class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
363
        if (class == PCI_CLASS_BRIDGE_PCI) {
 
364
            pci_config_writeb(bdf, PCI_SECONDARY_BUS, 255);
 
365
            pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 0);
 
366
        }
 
367
    }
 
368
 
 
369
    foreachpci_in_bus(bdf, max, bus) {
 
370
        class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
371
        if (class != PCI_CLASS_BRIDGE_PCI) {
 
372
            continue;
 
373
        }
 
374
        dprintf(1, "PCI: %s bdf = 0x%x\n", __func__, bdf);
 
375
 
 
376
        u8 pribus = pci_config_readb(bdf, PCI_PRIMARY_BUS);
 
377
        if (pribus != bus) {
 
378
            dprintf(1, "PCI: primary bus = 0x%x -> 0x%x\n", pribus, bus);
 
379
            pci_config_writeb(bdf, PCI_PRIMARY_BUS, bus);
 
380
        } else {
 
381
            dprintf(1, "PCI: primary bus = 0x%x\n", pribus);
 
382
        }
 
383
 
 
384
        u8 secbus = pci_config_readb(bdf, PCI_SECONDARY_BUS);
 
385
        (*pci_bus)++;
 
386
        if (*pci_bus != secbus) {
 
387
            dprintf(1, "PCI: secondary bus = 0x%x -> 0x%x\n",
 
388
                    secbus, *pci_bus);
 
389
            secbus = *pci_bus;
 
390
            pci_config_writeb(bdf, PCI_SECONDARY_BUS, secbus);
 
391
        } else {
 
392
            dprintf(1, "PCI: secondary bus = 0x%x\n", secbus);
 
393
        }
 
394
 
 
395
        /* set to max for access to all subordinate buses.
 
396
           later set it to accurate value */
 
397
        u8 subbus = pci_config_readb(bdf, PCI_SUBORDINATE_BUS);
 
398
        pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, 255);
 
399
 
 
400
        pci_bios_init_bus_rec(secbus, pci_bus);
 
401
 
 
402
        if (subbus != *pci_bus) {
 
403
            dprintf(1, "PCI: subordinate bus = 0x%x -> 0x%x\n",
 
404
                    subbus, *pci_bus);
 
405
            subbus = *pci_bus;
 
406
        } else {
 
407
            dprintf(1, "PCI: subordinate bus = 0x%x\n", subbus);
 
408
        }
 
409
        pci_config_writeb(bdf, PCI_SUBORDINATE_BUS, subbus);
 
410
    }
 
411
}
 
412
 
 
413
static void
 
414
pci_bios_init_bus(void)
 
415
{
 
416
    u8 pci_bus = 0;
 
417
    pci_bios_init_bus_rec(0 /* host bus */, &pci_bus);
 
418
}
 
419
 
 
420
void
 
421
pci_setup(void)
 
422
{
 
423
    if (CONFIG_COREBOOT)
 
424
        // Already done by coreboot.
 
425
        return;
 
426
 
 
427
    dprintf(3, "pci setup\n");
 
428
 
 
429
    pci_bios_io_addr = 0xc000;
 
430
    pci_bios_mem_addr = BUILD_PCIMEM_START;
 
431
    pci_bios_prefmem_addr = BUILD_PCIPREFMEM_START;
 
432
 
 
433
    pci_bios_init_bus();
 
434
 
 
435
    int bdf, max;
 
436
    foreachpci(bdf, max) {
 
437
        pci_bios_init_bridges(bdf);
 
438
    }
 
439
    pci_bios_init_device_in_bus(0 /* host bus */);
 
440
}