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

« back to all changes in this revision

Viewing changes to .pc/0049-seabios-pciinit-pci-bridge-bus-initialization.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 u32 pci_bios_io_addr;
 
18
static u32 pci_bios_mem_addr;
 
19
static u32 pci_bios_prefmem_addr;
 
20
/* host irqs corresponding to PCI irqs A-D */
 
21
static u8 pci_irqs[4] = {
 
22
    10, 10, 11, 11
 
23
};
 
24
 
 
25
static u32 pci_bar(u16 bdf, int region_num)
 
26
{
 
27
    if (region_num != PCI_ROM_SLOT) {
 
28
        return PCI_BASE_ADDRESS_0 + region_num * 4;
 
29
    }
 
30
 
 
31
#define PCI_HEADER_TYPE_MULTI_FUNCTION 0x80
 
32
    u8 type = pci_config_readb(bdf, PCI_HEADER_TYPE);
 
33
    type &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
 
34
    return type == PCI_HEADER_TYPE_BRIDGE ? PCI_ROM_ADDRESS1 : PCI_ROM_ADDRESS;
 
35
}
 
36
 
 
37
static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
 
38
{
 
39
    u32 ofs, old_addr;
 
40
 
 
41
    ofs = pci_bar(bdf, region_num);
 
42
 
 
43
    old_addr = pci_config_readl(bdf, ofs);
 
44
 
 
45
    pci_config_writel(bdf, ofs, addr);
 
46
    dprintf(1, "region %d: 0x%08x\n", region_num, addr);
 
47
}
 
48
 
 
49
/*
 
50
 * return value
 
51
 *      0:     32bit BAR
 
52
 *      non 0: 64bit BAR
 
53
 */
 
54
static int pci_bios_allocate_region(u16 bdf, int region_num)
 
55
{
 
56
    u32 *paddr;
 
57
    u32 ofs = pci_bar(bdf, region_num);
 
58
 
 
59
    u32 old = pci_config_readl(bdf, ofs);
 
60
    u32 mask;
 
61
    if (region_num == PCI_ROM_SLOT) {
 
62
        mask = PCI_ROM_ADDRESS_MASK;
 
63
        pci_config_writel(bdf, ofs, mask);
 
64
    } else {
 
65
        if (old & PCI_BASE_ADDRESS_SPACE_IO)
 
66
            mask = PCI_BASE_ADDRESS_IO_MASK;
 
67
        else
 
68
            mask = PCI_BASE_ADDRESS_MEM_MASK;
 
69
        pci_config_writel(bdf, ofs, ~0);
 
70
    }
 
71
    u32 val = pci_config_readl(bdf, ofs);
 
72
    pci_config_writel(bdf, ofs, old);
 
73
 
 
74
    u32 size = (~(val & mask)) + 1;
 
75
    if (val != 0) {
 
76
        if (val & PCI_BASE_ADDRESS_SPACE_IO) {
 
77
            paddr = &pci_bios_io_addr;
 
78
            if (ALIGN(*paddr, size) + size >= 64 * 1024) {
 
79
                dprintf(1,
 
80
                        "io region of (bdf 0x%x bar %d) can't be mapped.\n",
 
81
                        bdf, region_num);
 
82
                size = 0;
 
83
            }
 
84
        } else if ((val & PCI_BASE_ADDRESS_MEM_PREFETCH) &&
 
85
                 /* keep behaviour on bus = 0 */
 
86
                 pci_bdf_to_bus(bdf) != 0 &&
 
87
                 /* If pci_bios_prefmem_addr == 0, keep old behaviour */
 
88
                 pci_bios_prefmem_addr != 0) {
 
89
            paddr = &pci_bios_prefmem_addr;
 
90
            if (ALIGN(*paddr, size) + size >= BUILD_PCIPREFMEM_END) {
 
91
                dprintf(1,
 
92
                        "prefmem region of (bdf 0x%x bar %d) can't be mapped. "
 
93
                        "decrease BUILD_PCIMEM_SIZE and recompile. size %x\n",
 
94
                        bdf, region_num, BUILD_PCIPREFMEM_SIZE);
 
95
                size = 0;
 
96
            }
 
97
        } else {
 
98
            paddr = &pci_bios_mem_addr;
 
99
            if (ALIGN(*paddr, size) + size >= BUILD_PCIMEM_END) {
 
100
                dprintf(1,
 
101
                        "mem region of (bdf 0x%x bar %d) can't be mapped. "
 
102
                        "increase BUILD_PCIMEM_SIZE and recompile. size %x\n",
 
103
                        bdf, region_num, BUILD_PCIMEM_SIZE);
 
104
                size = 0;
 
105
            }
 
106
        }
 
107
        if (size > 0) {
 
108
            *paddr = ALIGN(*paddr, size);
 
109
            pci_set_io_region_addr(bdf, region_num, *paddr);
 
110
            *paddr += size;
 
111
        }
 
112
    }
 
113
 
 
114
    int is_64bit = !(val & PCI_BASE_ADDRESS_SPACE_IO) &&
 
115
        (val & PCI_BASE_ADDRESS_MEM_TYPE_MASK) == PCI_BASE_ADDRESS_MEM_TYPE_64;
 
116
    if (is_64bit) {
 
117
        if (size > 0) {
 
118
            pci_config_writel(bdf, ofs + 4, 0);
 
119
        } else {
 
120
            pci_config_writel(bdf, ofs + 4, ~0);
 
121
        }
 
122
    }
 
123
    return is_64bit;
 
124
}
 
125
 
 
126
static void pci_bios_allocate_regions(u16 bdf)
 
127
{
 
128
    int i;
 
129
    for (i = 0; i < PCI_NUM_REGIONS; i++) {
 
130
        int is_64bit = pci_bios_allocate_region(bdf, i);
 
131
        if (is_64bit){
 
132
            i++;
 
133
        }
 
134
    }
 
135
}
 
136
 
 
137
/* return the global irq number corresponding to a given device irq
 
138
   pin. We could also use the bus number to have a more precise
 
139
   mapping. */
 
140
static int pci_slot_get_pirq(u16 bdf, int irq_num)
 
141
{
 
142
    int slot_addend = pci_bdf_to_dev(bdf) - 1;
 
143
    return (irq_num + slot_addend) & 3;
 
144
}
 
145
 
 
146
static void pci_bios_init_bridges(u16 bdf)
 
147
{
 
148
    u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
 
149
    u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
 
150
 
 
151
    if (vendor_id == PCI_VENDOR_ID_INTEL
 
152
        && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0
 
153
            || device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
 
154
        int i, irq;
 
155
        u8 elcr[2];
 
156
 
 
157
        /* PIIX3/PIIX4 PCI to ISA bridge */
 
158
 
 
159
        elcr[0] = 0x00;
 
160
        elcr[1] = 0x00;
 
161
        for (i = 0; i < 4; i++) {
 
162
            irq = pci_irqs[i];
 
163
            /* set to trigger level */
 
164
            elcr[irq >> 3] |= (1 << (irq & 7));
 
165
            /* activate irq remapping in PIIX */
 
166
            pci_config_writeb(bdf, 0x60 + i, irq);
 
167
        }
 
168
        outb(elcr[0], 0x4d0);
 
169
        outb(elcr[1], 0x4d1);
 
170
        dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n",
 
171
                elcr[0], elcr[1]);
 
172
    }
 
173
}
 
174
 
 
175
static void pci_bios_init_device(u16 bdf)
 
176
{
 
177
    int class;
 
178
    int pin, pic_irq, vendor_id, device_id;
 
179
 
 
180
    class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
 
181
    vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
 
182
    device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
 
183
    dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
 
184
            , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf), vendor_id, device_id);
 
185
    switch (class) {
 
186
    case PCI_CLASS_STORAGE_IDE:
 
187
        if (vendor_id == PCI_VENDOR_ID_INTEL
 
188
            && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1
 
189
                || device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
 
190
            /* PIIX3/PIIX4 IDE */
 
191
            pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
 
192
            pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
 
193
            pci_bios_allocate_regions(bdf);
 
194
        } else {
 
195
            /* IDE: we map it as in ISA mode */
 
196
            pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
 
197
            pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
 
198
            pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
 
199
            pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
 
200
        }
 
201
        break;
 
202
    case PCI_CLASS_SYSTEM_PIC:
 
203
        /* PIC */
 
204
        if (vendor_id == PCI_VENDOR_ID_IBM) {
 
205
            /* IBM */
 
206
            if (device_id == 0x0046 || device_id == 0xFFFF) {
 
207
                /* MPIC & MPIC2 */
 
208
                pci_set_io_region_addr(bdf, 0, 0x80800000 + 0x00040000);
 
209
            }
 
210
        }
 
211
        break;
 
212
    case 0xff00:
 
213
        if (vendor_id == PCI_VENDOR_ID_APPLE &&
 
214
            (device_id == 0x0017 || device_id == 0x0022)) {
 
215
            /* macio bridge */
 
216
            pci_set_io_region_addr(bdf, 0, 0x80800000);
 
217
        }
 
218
        break;
 
219
    default:
 
220
        /* default memory mappings */
 
221
        pci_bios_allocate_regions(bdf);
 
222
        break;
 
223
    }
 
224
 
 
225
    /* enable memory mappings */
 
226
    pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
 
227
 
 
228
    /* map the interrupt */
 
229
    pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
 
230
    if (pin != 0) {
 
231
        pin = pci_slot_get_pirq(bdf, pin - 1);
 
232
        pic_irq = pci_irqs[pin];
 
233
        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
 
234
    }
 
235
 
 
236
    if (vendor_id == PCI_VENDOR_ID_INTEL
 
237
        && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
 
238
        /* PIIX4 Power Management device (for ACPI) */
 
239
 
 
240
        // acpi sci is hardwired to 9
 
241
        pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
 
242
 
 
243
        pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
 
244
        pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
 
245
        pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
 
246
        pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
 
247
    }
 
248
}
 
249
 
 
250
void
 
251
pci_setup(void)
 
252
{
 
253
    if (CONFIG_COREBOOT)
 
254
        // Already done by coreboot.
 
255
        return;
 
256
 
 
257
    dprintf(3, "pci setup\n");
 
258
 
 
259
    pci_bios_io_addr = 0xc000;
 
260
    pci_bios_mem_addr = BUILD_PCIMEM_START;
 
261
    pci_bios_prefmem_addr = BUILD_PCIPREFMEM_START;
 
262
 
 
263
    int bdf, max;
 
264
    foreachpci(bdf, max) {
 
265
        pci_bios_init_bridges(bdf);
 
266
    }
 
267
    foreachpci(bdf, max) {
 
268
        pci_bios_init_device(bdf);
 
269
    }
 
270
}