#include <linux/acpi.h>
#include <linux/console.h>
#include <linux/efi.h>
-#include <linux/tty.h>
#include <linux/serial.h>
-#include <linux/serial_core.h>
-#include <asm/io.h>
-#include <asm/serial.h>
+#include <asm/vga.h>
#include "pcdp.h"
-static inline int
-uart_irq_supported(int rev, struct pcdp_uart *uart)
+static int __init
+setup_serial_console(struct pcdp_uart *uart)
{
- if (rev < 3)
- return uart->pci_func & PCDP_UART_IRQ;
- return uart->flags & PCDP_UART_IRQ;
-}
-
-static inline int
-uart_pci(int rev, struct pcdp_uart *uart)
-{
- if (rev < 3)
- return uart->pci_func & PCDP_UART_PCI;
- return uart->flags & PCDP_UART_PCI;
-}
-
-static inline int
-uart_active_high_low(int rev, struct pcdp_uart *uart)
-{
- if (uart_pci(rev, uart) || uart->flags & PCDP_UART_ACTIVE_LOW)
- return ACPI_ACTIVE_LOW;
- return ACPI_ACTIVE_HIGH;
-}
+#ifdef CONFIG_SERIAL_8250_CONSOLE
+ int mmio;
+ static char options[64], *p = options;
+ char parity;
+
+ mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);
+ p += sprintf(p, "console=uart,%s,0x%lx",
+ mmio ? "mmio" : "io", uart->addr.address);
+ if (uart->baud) {
+ p += sprintf(p, ",%lu", uart->baud);
+ if (uart->bits) {
+ switch (uart->parity) {
+ case 0x2: parity = 'e'; break;
+ case 0x3: parity = 'o'; break;
+ default: parity = 'n';
+ }
+ p += sprintf(p, "%c%d", parity, uart->bits);
+ }
+ }
-static inline int
-uart_edge_level(int rev, struct pcdp_uart *uart)
-{
- if (uart_pci(rev, uart))
- return ACPI_LEVEL_SENSITIVE;
- if (rev < 3 || uart->flags & PCDP_UART_EDGE_SENSITIVE)
- return ACPI_EDGE_SENSITIVE;
- return ACPI_LEVEL_SENSITIVE;
+ return early_serial_console_init(options);
+#else
+ return -ENODEV;
+#endif
}
-static void __init
-setup_serial_console(int rev, struct pcdp_uart *uart)
+static int __init
+setup_vga_console(struct pcdp_device *dev)
{
-#ifdef CONFIG_SERIAL_8250_CONSOLE
- struct uart_port port;
- static char options[16];
- int mapsize = 64;
-
- memset(&port, 0, sizeof(port));
- port.uartclk = uart->clock_rate;
- if (!port.uartclk) /* some FW doesn't supply this */
- port.uartclk = BASE_BAUD * 16;
-
- if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY) {
- port.mapbase = uart->addr.address;
- port.membase = ioremap(port.mapbase, mapsize);
- if (!port.membase) {
- printk(KERN_ERR "%s: couldn't ioremap 0x%lx-0x%lx\n",
- __FUNCTION__, port.mapbase, port.mapbase + mapsize);
- return;
- }
- port.iotype = UPIO_MEM;
- } else if (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_IO) {
- port.iobase = uart->addr.address;
- port.iotype = UPIO_PORT;
- } else
- return;
-
- switch (uart->pci_prog_intfc) {
- case 0x0: port.type = PORT_8250; break;
- case 0x1: port.type = PORT_16450; break;
- case 0x2: port.type = PORT_16550; break;
- case 0x3: port.type = PORT_16650; break;
- case 0x4: port.type = PORT_16750; break;
- case 0x5: port.type = PORT_16850; break;
- case 0x6: port.type = PORT_16C950; break;
- default: port.type = PORT_UNKNOWN; break;
- }
+#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)
+ u8 *if_ptr;
- port.flags = UPF_SKIP_TEST | UPF_BOOT_AUTOCONF;
+ if_ptr = ((u8 *)dev + sizeof(struct pcdp_device));
+ if (if_ptr[0] == PCDP_IF_PCI) {
+ struct pcdp_if_pci if_pci;
- if (uart_irq_supported(rev, uart)) {
- port.irq = acpi_register_gsi(uart->gsi,
- uart_active_high_low(rev, uart),
- uart_edge_level(rev, uart));
- port.flags |= UPF_AUTO_IRQ; /* some FW reported wrong GSI */
- if (uart_pci(rev, uart))
- port.flags |= UPF_SHARE_IRQ;
- }
+ /* struct copy since ifptr might not be correctly aligned */
- if (early_serial_setup(&port) < 0)
- return;
+ memcpy(&if_pci, if_ptr, sizeof(if_pci));
- snprintf(options, sizeof(options), "%lun%d", uart->baud,
- uart->bits ? uart->bits : 8);
- add_preferred_console("ttyS", port.line, options);
+ if (if_pci.trans & PCDP_PCI_TRANS_IOPORT)
+ vga_console_iobase = if_pci.ioport_tra;
- printk(KERN_INFO "PCDP: serial console at %s 0x%lx (ttyS%d, options %s)\n",
- port.iotype == UPIO_MEM ? "MMIO" : "I/O",
- uart->addr.address, port.line, options);
-#endif
-}
+ if (if_pci.trans & PCDP_PCI_TRANS_MMIO)
+ vga_console_membase = if_pci.mmio_tra;
+ }
-static void __init
-setup_vga_console(struct pcdp_vga *vga)
-{
-#ifdef CONFIG_VT
-#ifdef CONFIG_VGA_CONSOLE
- if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) {
+ if (efi_mem_type(vga_console_membase + 0xA0000) == EFI_CONVENTIONAL_MEMORY) {
printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");
- return;
+ return -ENODEV;
}
conswitchp = &vga_con;
printk(KERN_INFO "PCDP: VGA console\n");
-#endif
+ return 0;
+#else
+ return -ENODEV;
#endif
}
-void __init
+int __init
efi_setup_pcdp_console(char *cmdline)
{
struct pcdp *pcdp;
struct pcdp_uart *uart;
struct pcdp_device *dev, *end;
int i, serial = 0;
+ int rc = -ENODEV;
- pcdp = efi.hcdp;
- if (!pcdp)
- return;
+ if (efi.hcdp == EFI_INVALID_TABLE_ADDR)
+ return -ENODEV;
- printk(KERN_INFO "PCDP: v%d at 0x%p\n", pcdp->rev, pcdp);
+ pcdp = ioremap(efi.hcdp, 4096);
+ printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp);
- if (pcdp->rev < 3) {
- if (strstr(cmdline, "console=ttyS0") || efi_uart_console_only())
+ if (strstr(cmdline, "console=hcdp")) {
+ if (pcdp->rev < 3)
serial = 1;
+ } else if (strstr(cmdline, "console=")) {
+ printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n");
+ goto out;
}
+ if (pcdp->rev < 3 && efi_uart_console_only())
+ serial = 1;
+
for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
if (uart->flags & PCDP_UART_PRIMARY_CONSOLE || serial) {
if (uart->type == PCDP_CONSOLE_UART) {
- setup_serial_console(pcdp->rev, uart);
- return;
+ rc = setup_serial_console(uart);
+ goto out;
}
}
}
dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) {
if (dev->flags & PCDP_PRIMARY_CONSOLE) {
if (dev->type == PCDP_CONSOLE_VGA) {
- setup_vga_console((struct pcdp_vga *) dev);
- return;
+ rc = setup_vga_console(dev);
+ goto out;
}
}
}
-}
-
-#ifdef CONFIG_IA64_EARLY_PRINTK_UART
-unsigned long
-hcdp_early_uart (void)
-{
- efi_system_table_t *systab;
- efi_config_table_t *config_tables;
- unsigned long addr = 0;
- struct pcdp *pcdp = 0;
- struct pcdp_uart *uart;
- int i;
-
- systab = (efi_system_table_t *) ia64_boot_param->efi_systab;
- if (!systab)
- return 0;
- systab = __va(systab);
-
- config_tables = (efi_config_table_t *) systab->tables;
- if (!config_tables)
- return 0;
- config_tables = __va(config_tables);
-
- for (i = 0; i < systab->nr_tables; i++) {
- if (efi_guidcmp(config_tables[i].guid, HCDP_TABLE_GUID) == 0) {
- pcdp = (struct pcdp *) config_tables[i].table;
- break;
- }
- }
- if (!pcdp)
- return 0;
- pcdp = __va(pcdp);
- for (i = 0, uart = pcdp->uart; i < pcdp->num_uarts; i++, uart++) {
- if (uart->type == PCDP_CONSOLE_UART) {
- addr = uart->addr.address;
- break;
- }
- }
- return addr;
+out:
+ iounmap(pcdp);
+ return rc;
}
-#endif /* CONFIG_IA64_EARLY_PRINTK_UART */