269c2d81 |
1 | #include <linux/kernel.h> |
2 | #include <linux/types.h> |
3 | #include <linux/init.h> |
4 | #include <linux/bootmem.h> |
5 | #include <linux/ioport.h> |
6 | #include <linux/string.h> |
7 | #include <linux/kexec.h> |
8 | #include <linux/module.h> |
9 | #include <linux/mm.h> |
10 | #include <linux/efi.h> |
11 | |
12 | #include <asm/pgtable.h> |
13 | #include <asm/page.h> |
14 | #include <asm/e820.h> |
15 | |
16 | #ifdef CONFIG_EFI |
17 | int efi_enabled = 0; |
18 | EXPORT_SYMBOL(efi_enabled); |
19 | #endif |
20 | |
21 | struct e820map e820; |
22 | struct resource data_resource = { |
23 | .name = "Kernel data", |
24 | .start = 0, |
25 | .end = 0, |
26 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM |
27 | }; |
28 | |
29 | struct resource code_resource = { |
30 | .name = "Kernel code", |
31 | .start = 0, |
32 | .end = 0, |
33 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM |
34 | }; |
35 | |
36 | static struct resource system_rom_resource = { |
37 | .name = "System ROM", |
38 | .start = 0xf0000, |
39 | .end = 0xfffff, |
40 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
41 | }; |
42 | |
43 | static struct resource extension_rom_resource = { |
44 | .name = "Extension ROM", |
45 | .start = 0xe0000, |
46 | .end = 0xeffff, |
47 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
48 | }; |
49 | |
50 | static struct resource adapter_rom_resources[] = { { |
51 | .name = "Adapter ROM", |
52 | .start = 0xc8000, |
53 | .end = 0, |
54 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
55 | }, { |
56 | .name = "Adapter ROM", |
57 | .start = 0, |
58 | .end = 0, |
59 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
60 | }, { |
61 | .name = "Adapter ROM", |
62 | .start = 0, |
63 | .end = 0, |
64 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
65 | }, { |
66 | .name = "Adapter ROM", |
67 | .start = 0, |
68 | .end = 0, |
69 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
70 | }, { |
71 | .name = "Adapter ROM", |
72 | .start = 0, |
73 | .end = 0, |
74 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
75 | }, { |
76 | .name = "Adapter ROM", |
77 | .start = 0, |
78 | .end = 0, |
79 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
80 | } }; |
81 | |
82 | static struct resource video_rom_resource = { |
83 | .name = "Video ROM", |
84 | .start = 0xc0000, |
85 | .end = 0xc7fff, |
86 | .flags = IORESOURCE_BUSY | IORESOURCE_READONLY | IORESOURCE_MEM |
87 | }; |
88 | |
89 | static struct resource video_ram_resource = { |
90 | .name = "Video RAM area", |
91 | .start = 0xa0000, |
92 | .end = 0xbffff, |
93 | .flags = IORESOURCE_BUSY | IORESOURCE_MEM |
94 | }; |
95 | |
96 | static struct resource standard_io_resources[] = { { |
97 | .name = "dma1", |
98 | .start = 0x0000, |
99 | .end = 0x001f, |
100 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
101 | }, { |
102 | .name = "pic1", |
103 | .start = 0x0020, |
104 | .end = 0x0021, |
105 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
106 | }, { |
107 | .name = "timer0", |
108 | .start = 0x0040, |
109 | .end = 0x0043, |
110 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
111 | }, { |
112 | .name = "timer1", |
113 | .start = 0x0050, |
114 | .end = 0x0053, |
115 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
116 | }, { |
117 | .name = "keyboard", |
118 | .start = 0x0060, |
119 | .end = 0x006f, |
120 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
121 | }, { |
122 | .name = "dma page reg", |
123 | .start = 0x0080, |
124 | .end = 0x008f, |
125 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
126 | }, { |
127 | .name = "pic2", |
128 | .start = 0x00a0, |
129 | .end = 0x00a1, |
130 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
131 | }, { |
132 | .name = "dma2", |
133 | .start = 0x00c0, |
134 | .end = 0x00df, |
135 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
136 | }, { |
137 | .name = "fpu", |
138 | .start = 0x00f0, |
139 | .end = 0x00ff, |
140 | .flags = IORESOURCE_BUSY | IORESOURCE_IO |
141 | } }; |
142 | |
143 | #define romsignature(x) (*(unsigned short *)(x) == 0xaa55) |
144 | |
145 | static int __init romchecksum(unsigned char *rom, unsigned long length) |
146 | { |
147 | unsigned char *p, sum = 0; |
148 | |
149 | for (p = rom; p < rom + length; p++) |
150 | sum += *p; |
151 | return sum == 0; |
152 | } |
153 | |
154 | static void __init probe_roms(void) |
155 | { |
156 | unsigned long start, length, upper; |
157 | unsigned char *rom; |
158 | int i; |
159 | |
160 | /* video rom */ |
161 | upper = adapter_rom_resources[0].start; |
162 | for (start = video_rom_resource.start; start < upper; start += 2048) { |
163 | rom = isa_bus_to_virt(start); |
164 | if (!romsignature(rom)) |
165 | continue; |
166 | |
167 | video_rom_resource.start = start; |
168 | |
169 | /* 0 < length <= 0x7f * 512, historically */ |
170 | length = rom[2] * 512; |
171 | |
172 | /* if checksum okay, trust length byte */ |
173 | if (length && romchecksum(rom, length)) |
174 | video_rom_resource.end = start + length - 1; |
175 | |
176 | request_resource(&iomem_resource, &video_rom_resource); |
177 | break; |
178 | } |
179 | |
180 | start = (video_rom_resource.end + 1 + 2047) & ~2047UL; |
181 | if (start < upper) |
182 | start = upper; |
183 | |
184 | /* system rom */ |
185 | request_resource(&iomem_resource, &system_rom_resource); |
186 | upper = system_rom_resource.start; |
187 | |
188 | /* check for extension rom (ignore length byte!) */ |
189 | rom = isa_bus_to_virt(extension_rom_resource.start); |
190 | if (romsignature(rom)) { |
191 | length = extension_rom_resource.end - extension_rom_resource.start + 1; |
192 | if (romchecksum(rom, length)) { |
193 | request_resource(&iomem_resource, &extension_rom_resource); |
194 | upper = extension_rom_resource.start; |
195 | } |
196 | } |
197 | |
198 | /* check for adapter roms on 2k boundaries */ |
199 | for (i = 0; i < ARRAY_SIZE(adapter_rom_resources) && start < upper; start += 2048) { |
200 | rom = isa_bus_to_virt(start); |
201 | if (!romsignature(rom)) |
202 | continue; |
203 | |
204 | /* 0 < length <= 0x7f * 512, historically */ |
205 | length = rom[2] * 512; |
206 | |
207 | /* but accept any length that fits if checksum okay */ |
208 | if (!length || start + length > upper || !romchecksum(rom, length)) |
209 | continue; |
210 | |
211 | adapter_rom_resources[i].start = start; |
212 | adapter_rom_resources[i].end = start + length - 1; |
213 | request_resource(&iomem_resource, &adapter_rom_resources[i]); |
214 | |
215 | start = adapter_rom_resources[i++].end & ~2047UL; |
216 | } |
217 | } |
218 | |
219 | /* |
220 | * Request address space for all standard RAM and ROM resources |
221 | * and also for regions reported as reserved by the e820. |
222 | */ |
223 | static void __init |
224 | legacy_init_iomem_resources(struct resource *code_resource, struct resource *data_resource) |
225 | { |
226 | int i; |
227 | |
228 | probe_roms(); |
229 | for (i = 0; i < e820.nr_map; i++) { |
230 | struct resource *res; |
231 | #ifndef CONFIG_RESOURCES_64BIT |
232 | if (e820.map[i].addr + e820.map[i].size > 0x100000000ULL) |
233 | continue; |
234 | #endif |
235 | res = kzalloc(sizeof(struct resource), GFP_ATOMIC); |
236 | switch (e820.map[i].type) { |
237 | case E820_RAM: res->name = "System RAM"; break; |
238 | case E820_ACPI: res->name = "ACPI Tables"; break; |
239 | case E820_NVS: res->name = "ACPI Non-volatile Storage"; break; |
240 | default: res->name = "reserved"; |
241 | } |
242 | res->start = e820.map[i].addr; |
243 | res->end = res->start + e820.map[i].size - 1; |
244 | res->flags = IORESOURCE_MEM | IORESOURCE_BUSY; |
245 | if (request_resource(&iomem_resource, res)) { |
246 | kfree(res); |
247 | continue; |
248 | } |
249 | if (e820.map[i].type == E820_RAM) { |
250 | /* |
251 | * We don't know which RAM region contains kernel data, |
252 | * so we try it repeatedly and let the resource manager |
253 | * test it. |
254 | */ |
255 | request_resource(res, code_resource); |
256 | request_resource(res, data_resource); |
257 | #ifdef CONFIG_KEXEC |
258 | request_resource(res, &crashk_res); |
259 | #endif |
260 | } |
261 | } |
262 | } |
263 | |
264 | /* |
265 | * Request address space for all standard resources |
266 | * |
267 | * This is called just before pcibios_init(), which is also a |
268 | * subsys_initcall, but is linked in later (in arch/i386/pci/common.c). |
269 | */ |
270 | static int __init request_standard_resources(void) |
271 | { |
272 | int i; |
273 | |
274 | printk("Setting up standard PCI resources\n"); |
275 | if (efi_enabled) |
276 | efi_initialize_iomem_resources(&code_resource, &data_resource); |
277 | else |
278 | legacy_init_iomem_resources(&code_resource, &data_resource); |
279 | |
280 | /* EFI systems may still have VGA */ |
281 | request_resource(&iomem_resource, &video_ram_resource); |
282 | |
283 | /* request I/O space for devices used on all i[345]86 PCs */ |
284 | for (i = 0; i < ARRAY_SIZE(standard_io_resources); i++) |
285 | request_resource(&ioport_resource, &standard_io_resources[i]); |
286 | return 0; |
287 | } |
288 | |
289 | subsys_initcall(request_standard_resources); |