diff options
Diffstat (limited to 'arch/ia64')
-rw-r--r-- | arch/ia64/sn/kernel/setup.c | 157 |
1 files changed, 153 insertions, 4 deletions
diff --git a/arch/ia64/sn/kernel/setup.c b/arch/ia64/sn/kernel/setup.c index 0fb579ef18c2..e510dce9971f 100644 --- a/arch/ia64/sn/kernel/setup.c +++ b/arch/ia64/sn/kernel/setup.c | |||
@@ -30,6 +30,7 @@ | |||
30 | #include <linux/root_dev.h> | 30 | #include <linux/root_dev.h> |
31 | #include <linux/nodemask.h> | 31 | #include <linux/nodemask.h> |
32 | #include <linux/pm.h> | 32 | #include <linux/pm.h> |
33 | #include <linux/efi.h> | ||
33 | 34 | ||
34 | #include <asm/io.h> | 35 | #include <asm/io.h> |
35 | #include <asm/sal.h> | 36 | #include <asm/sal.h> |
@@ -242,6 +243,135 @@ static void __init sn_check_for_wars(void) | |||
242 | } | 243 | } |
243 | } | 244 | } |
244 | 245 | ||
246 | /* | ||
247 | * Scan the EFI PCDP table (if it exists) for an acceptable VGA console | ||
248 | * output device. If one exists, pick it and set sn_legacy_{io,mem} to | ||
249 | * reflect the bus offsets needed to address it. | ||
250 | * | ||
251 | * Since pcdp support in SN is not supported in the 2.4 kernel (or at least | ||
252 | * the one lbs is based on) just declare the needed structs here. | ||
253 | * | ||
254 | * Reference spec http://www.dig64.org/specifications/DIG64_PCDPv20.pdf | ||
255 | * | ||
256 | * Returns 0 if no acceptable vga is found, !0 otherwise. | ||
257 | * | ||
258 | * Note: This stuff is duped here because Altix requires the PCDP to | ||
259 | * locate a usable VGA device due to lack of proper ACPI support. Structures | ||
260 | * could be used from drivers/firmware/pcdp.h, but it was decided that moving | ||
261 | * this file to a more public location just for Altix use was undesireable. | ||
262 | */ | ||
263 | |||
264 | struct hcdp_uart_desc { | ||
265 | u8 pad[45]; | ||
266 | }; | ||
267 | |||
268 | struct pcdp { | ||
269 | u8 signature[4]; /* should be 'HCDP' */ | ||
270 | u32 length; | ||
271 | u8 rev; /* should be >=3 for pcdp, <3 for hcdp */ | ||
272 | u8 sum; | ||
273 | u8 oem_id[6]; | ||
274 | u64 oem_tableid; | ||
275 | u32 oem_rev; | ||
276 | u32 creator_id; | ||
277 | u32 creator_rev; | ||
278 | u32 num_type0; | ||
279 | struct hcdp_uart_desc uart[0]; /* num_type0 of these */ | ||
280 | /* pcdp descriptors follow */ | ||
281 | } __attribute__((packed)); | ||
282 | |||
283 | struct pcdp_device_desc { | ||
284 | u8 type; | ||
285 | u8 primary; | ||
286 | u16 length; | ||
287 | u16 index; | ||
288 | /* interconnect specific structure follows */ | ||
289 | /* device specific structure follows that */ | ||
290 | } __attribute__((packed)); | ||
291 | |||
292 | struct pcdp_interface_pci { | ||
293 | u8 type; /* 1 == pci */ | ||
294 | u8 reserved; | ||
295 | u16 length; | ||
296 | u8 segment; | ||
297 | u8 bus; | ||
298 | u8 dev; | ||
299 | u8 fun; | ||
300 | u16 devid; | ||
301 | u16 vendid; | ||
302 | u32 acpi_interrupt; | ||
303 | u64 mmio_tra; | ||
304 | u64 ioport_tra; | ||
305 | u8 flags; | ||
306 | u8 translation; | ||
307 | } __attribute__((packed)); | ||
308 | |||
309 | struct pcdp_vga_device { | ||
310 | u8 num_eas_desc; | ||
311 | /* ACPI Extended Address Space Desc follows */ | ||
312 | } __attribute__((packed)); | ||
313 | |||
314 | /* from pcdp_device_desc.primary */ | ||
315 | #define PCDP_PRIMARY_CONSOLE 0x01 | ||
316 | |||
317 | /* from pcdp_device_desc.type */ | ||
318 | #define PCDP_CONSOLE_INOUT 0x0 | ||
319 | #define PCDP_CONSOLE_DEBUG 0x1 | ||
320 | #define PCDP_CONSOLE_OUT 0x2 | ||
321 | #define PCDP_CONSOLE_IN 0x3 | ||
322 | #define PCDP_CONSOLE_TYPE_VGA 0x8 | ||
323 | |||
324 | #define PCDP_CONSOLE_VGA (PCDP_CONSOLE_TYPE_VGA | PCDP_CONSOLE_OUT) | ||
325 | |||
326 | /* from pcdp_interface_pci.type */ | ||
327 | #define PCDP_IF_PCI 1 | ||
328 | |||
329 | /* from pcdp_interface_pci.translation */ | ||
330 | #define PCDP_PCI_TRANS_IOPORT 0x02 | ||
331 | #define PCDP_PCI_TRANS_MMIO 0x01 | ||
332 | |||
333 | static void | ||
334 | sn_scan_pcdp(void) | ||
335 | { | ||
336 | u8 *bp; | ||
337 | struct pcdp *pcdp; | ||
338 | struct pcdp_device_desc device; | ||
339 | struct pcdp_interface_pci if_pci; | ||
340 | extern struct efi efi; | ||
341 | |||
342 | pcdp = efi.hcdp; | ||
343 | if (! pcdp) | ||
344 | return; /* no hcdp/pcdp table */ | ||
345 | |||
346 | if (pcdp->rev < 3) | ||
347 | return; /* only support PCDP (rev >= 3) */ | ||
348 | |||
349 | for (bp = (u8 *)&pcdp->uart[pcdp->num_type0]; | ||
350 | bp < (u8 *)pcdp + pcdp->length; | ||
351 | bp += device.length) { | ||
352 | memcpy(&device, bp, sizeof(device)); | ||
353 | if (! (device.primary & PCDP_PRIMARY_CONSOLE)) | ||
354 | continue; /* not primary console */ | ||
355 | |||
356 | if (device.type != PCDP_CONSOLE_VGA) | ||
357 | continue; /* not VGA descriptor */ | ||
358 | |||
359 | memcpy(&if_pci, bp+sizeof(device), sizeof(if_pci)); | ||
360 | if (if_pci.type != PCDP_IF_PCI) | ||
361 | continue; /* not PCI interconnect */ | ||
362 | |||
363 | if (if_pci.translation & PCDP_PCI_TRANS_IOPORT) | ||
364 | vga_console_iobase = | ||
365 | if_pci.ioport_tra | __IA64_UNCACHED_OFFSET; | ||
366 | |||
367 | if (if_pci.translation & PCDP_PCI_TRANS_MMIO) | ||
368 | vga_console_membase = | ||
369 | if_pci.mmio_tra | __IA64_UNCACHED_OFFSET; | ||
370 | |||
371 | break; /* once we find the primary, we're done */ | ||
372 | } | ||
373 | } | ||
374 | |||
245 | /** | 375 | /** |
246 | * sn_setup - SN platform setup routine | 376 | * sn_setup - SN platform setup routine |
247 | * @cmdline_p: kernel command line | 377 | * @cmdline_p: kernel command line |
@@ -263,16 +393,35 @@ void __init sn_setup(char **cmdline_p) | |||
263 | 393 | ||
264 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) | 394 | #if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE) |
265 | /* | 395 | /* |
266 | * If there was a primary vga adapter identified through the | 396 | * Handle SN vga console. |
267 | * EFI PCDP table, make it the preferred console. Otherwise | 397 | * |
268 | * zero out conswitchp. | 398 | * SN systems do not have enough ACPI table information |
399 | * being passed from prom to identify VGA adapters and the legacy | ||
400 | * addresses to access them. Until that is done, SN systems rely | ||
401 | * on the PCDP table to identify the primary VGA console if one | ||
402 | * exists. | ||
403 | * | ||
404 | * However, kernel PCDP support is optional, and even if it is built | ||
405 | * into the kernel, it will not be used if the boot cmdline contains | ||
406 | * console= directives. | ||
407 | * | ||
408 | * So, to work around this mess, we duplicate some of the PCDP code | ||
409 | * here so that the primary VGA console (as defined by PCDP) will | ||
410 | * work on SN systems even if a different console (e.g. serial) is | ||
411 | * selected on the boot line (or CONFIG_EFI_PCDP is off). | ||
269 | */ | 412 | */ |
270 | 413 | ||
414 | if (! vga_console_membase) | ||
415 | sn_scan_pcdp(); | ||
416 | |||
271 | if (vga_console_membase) { | 417 | if (vga_console_membase) { |
272 | /* usable vga ... make tty0 the preferred default console */ | 418 | /* usable vga ... make tty0 the preferred default console */ |
273 | add_preferred_console("tty", 0, NULL); | 419 | if (!strstr(*cmdline_p, "console=")) |
420 | add_preferred_console("tty", 0, NULL); | ||
274 | } else { | 421 | } else { |
275 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); | 422 | printk(KERN_DEBUG "SGI: Disabling VGA console\n"); |
423 | if (!strstr(*cmdline_p, "console=")) | ||
424 | add_preferred_console("ttySG", 0, NULL); | ||
276 | #ifdef CONFIG_DUMMY_CONSOLE | 425 | #ifdef CONFIG_DUMMY_CONSOLE |
277 | conswitchp = &dummy_con; | 426 | conswitchp = &dummy_con; |
278 | #else | 427 | #else |