|
|
1.1 root 1: // Initialize PCI devices (on emulators)
2: //
3: // Copyright (C) 2008 Kevin O'Connor <[email protected]>
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: /* host irqs corresponding to PCI irqs A-D */
20: static u8 pci_irqs[4] = {
21: 10, 10, 11, 11
22: };
23:
24: static void pci_set_io_region_addr(u16 bdf, int region_num, u32 addr)
25: {
26: u32 ofs, old_addr;
27:
28: if (region_num == PCI_ROM_SLOT) {
29: ofs = PCI_ROM_ADDRESS;
30: } else {
31: ofs = PCI_BASE_ADDRESS_0 + region_num * 4;
32: }
33:
34: old_addr = pci_config_readl(bdf, ofs);
35:
36: pci_config_writel(bdf, ofs, addr);
37: dprintf(1, "region %d: 0x%08x\n", region_num, addr);
38: }
39:
40: /* return the global irq number corresponding to a given device irq
41: pin. We could also use the bus number to have a more precise
42: mapping. */
43: static int pci_slot_get_pirq(u16 bdf, int irq_num)
44: {
45: int slot_addend = pci_bdf_to_dev(bdf) - 1;
46: return (irq_num + slot_addend) & 3;
47: }
48:
49: static void pci_bios_init_bridges(u16 bdf)
50: {
51: u16 vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
52: u16 device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
53:
54: if (vendor_id == PCI_VENDOR_ID_INTEL
55: && (device_id == PCI_DEVICE_ID_INTEL_82371SB_0
56: || device_id == PCI_DEVICE_ID_INTEL_82371AB_0)) {
57: int i, irq;
58: u8 elcr[2];
59:
60: /* PIIX3/PIIX4 PCI to ISA bridge */
61:
62: elcr[0] = 0x00;
63: elcr[1] = 0x00;
64: for (i = 0; i < 4; i++) {
65: irq = pci_irqs[i];
66: /* set to trigger level */
67: elcr[irq >> 3] |= (1 << (irq & 7));
68: /* activate irq remapping in PIIX */
69: pci_config_writeb(bdf, 0x60 + i, irq);
70: }
71: outb(elcr[0], 0x4d0);
72: outb(elcr[1], 0x4d1);
73: dprintf(1, "PIIX3/PIIX4 init: elcr=%02x %02x\n",
74: elcr[0], elcr[1]);
75: }
76: }
77:
78: static void pci_bios_init_device(u16 bdf)
79: {
80: int class;
81: u32 *paddr;
82: int i, pin, pic_irq, vendor_id, device_id;
83:
84: class = pci_config_readw(bdf, PCI_CLASS_DEVICE);
85: vendor_id = pci_config_readw(bdf, PCI_VENDOR_ID);
86: device_id = pci_config_readw(bdf, PCI_DEVICE_ID);
87: dprintf(1, "PCI: bus=%d devfn=0x%02x: vendor_id=0x%04x device_id=0x%04x\n"
88: , pci_bdf_to_bus(bdf), pci_bdf_to_devfn(bdf), vendor_id, device_id);
89: switch (class) {
90: case PCI_CLASS_STORAGE_IDE:
91: if (vendor_id == PCI_VENDOR_ID_INTEL
92: && (device_id == PCI_DEVICE_ID_INTEL_82371SB_1
93: || device_id == PCI_DEVICE_ID_INTEL_82371AB)) {
94: /* PIIX3/PIIX4 IDE */
95: pci_config_writew(bdf, 0x40, 0x8000); // enable IDE0
96: pci_config_writew(bdf, 0x42, 0x8000); // enable IDE1
97: goto default_map;
98: } else {
99: /* IDE: we map it as in ISA mode */
100: pci_set_io_region_addr(bdf, 0, PORT_ATA1_CMD_BASE);
101: pci_set_io_region_addr(bdf, 1, PORT_ATA1_CTRL_BASE);
102: pci_set_io_region_addr(bdf, 2, PORT_ATA2_CMD_BASE);
103: pci_set_io_region_addr(bdf, 3, PORT_ATA2_CTRL_BASE);
104: }
105: break;
106: case PCI_CLASS_SYSTEM_PIC:
107: /* PIC */
108: if (vendor_id == PCI_VENDOR_ID_IBM) {
109: /* IBM */
110: if (device_id == 0x0046 || device_id == 0xFFFF) {
111: /* MPIC & MPIC2 */
112: pci_set_io_region_addr(bdf, 0, 0x80800000 + 0x00040000);
113: }
114: }
115: break;
116: case 0xff00:
117: if (vendor_id == PCI_VENDOR_ID_APPLE &&
118: (device_id == 0x0017 || device_id == 0x0022)) {
119: /* macio bridge */
120: pci_set_io_region_addr(bdf, 0, 0x80800000);
121: }
122: break;
123: default:
124: default_map:
125: /* default memory mappings */
126: for (i = 0; i < PCI_NUM_REGIONS; i++) {
127: int ofs;
128: if (i == PCI_ROM_SLOT)
129: ofs = PCI_ROM_ADDRESS;
130: else
131: ofs = PCI_BASE_ADDRESS_0 + i * 4;
132:
133: u32 old = pci_config_readl(bdf, ofs);
134: u32 mask;
135: if (i == PCI_ROM_SLOT) {
136: mask = PCI_ROM_ADDRESS_MASK;
137: pci_config_writel(bdf, ofs, mask);
138: } else {
139: if (old & PCI_BASE_ADDRESS_SPACE_IO)
140: mask = PCI_BASE_ADDRESS_IO_MASK;
141: else
142: mask = PCI_BASE_ADDRESS_MEM_MASK;
143: pci_config_writel(bdf, ofs, ~0);
144: }
145: u32 val = pci_config_readl(bdf, ofs);
146: pci_config_writel(bdf, ofs, old);
147:
148: if (val != 0) {
149: u32 size = (~(val & mask)) + 1;
150: if (val & PCI_BASE_ADDRESS_SPACE_IO)
151: paddr = &pci_bios_io_addr;
152: else
153: paddr = &pci_bios_mem_addr;
154: *paddr = ALIGN(*paddr, size);
155: pci_set_io_region_addr(bdf, i, *paddr);
156: *paddr += size;
157: }
158: }
159: break;
160: }
161:
162: /* enable memory mappings */
163: pci_config_maskw(bdf, PCI_COMMAND, 0, PCI_COMMAND_IO | PCI_COMMAND_MEMORY);
164:
165: /* map the interrupt */
166: pin = pci_config_readb(bdf, PCI_INTERRUPT_PIN);
167: if (pin != 0) {
168: pin = pci_slot_get_pirq(bdf, pin - 1);
169: pic_irq = pci_irqs[pin];
170: pci_config_writeb(bdf, PCI_INTERRUPT_LINE, pic_irq);
171: }
172:
173: if (vendor_id == PCI_VENDOR_ID_INTEL
174: && device_id == PCI_DEVICE_ID_INTEL_82371AB_3) {
175: /* PIIX4 Power Management device (for ACPI) */
176:
177: // acpi sci is hardwired to 9
178: pci_config_writeb(bdf, PCI_INTERRUPT_LINE, 9);
179:
180: pci_config_writel(bdf, 0x40, PORT_ACPI_PM_BASE | 1);
181: pci_config_writeb(bdf, 0x80, 0x01); /* enable PM io space */
182: pci_config_writel(bdf, 0x90, PORT_SMB_BASE | 1);
183: pci_config_writeb(bdf, 0xd2, 0x09); /* enable SMBus io space */
184: }
185: }
186:
187: void
188: pci_setup(void)
189: {
190: if (CONFIG_COREBOOT)
191: // Already done by coreboot.
192: return;
193:
194: dprintf(3, "pci setup\n");
195:
196: pci_bios_io_addr = 0xc000;
1.1.1.3 ! root 197: pci_bios_mem_addr = BUILD_PCIMEM_START;
1.1 root 198:
199: int bdf, max;
200: foreachpci(bdf, max) {
201: pci_bios_init_bridges(bdf);
202: }
203: foreachpci(bdf, max) {
204: pci_bios_init_device(bdf);
205: }
206: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.