[PATCH] i386: i386 create e820.c to handle standard io/mem resources
[pandora-kernel.git] / arch / i386 / kernel / e820.c
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);