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; if (efi.hcdp == EFI_INVALID_TABLE_ADDR) return -ENODEV; pcdp = ioremap(efi.hcdp, 4096); printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, efi.hcdp); 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) { rc = setup_serial_console(uart); goto out; } } } end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length); for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts); dev < end; dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { rc = setup_vga_console(dev); goto out; } } } out: iounmap(pcdp); return rc; }
int __init efi_setup_pcdp_console(char *cmdline) { struct pcdp *pcdp; struct pcdp_uart *uart; struct pcdp_device *dev, *end; int i, serial = 0; pcdp = efi.hcdp; if (!pcdp) return -ENODEV; printk(KERN_INFO "PCDP: v%d at 0x%lx\n", pcdp->rev, __pa(pcdp)); if (strstr(cmdline, "console=hcdp")) { if (pcdp->rev < 3) serial = 1; } else if (strstr(cmdline, "console=")) { printk(KERN_INFO "Explicit \"console=\"; ignoring PCDP\n"); return -ENODEV; } 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) { return setup_serial_console(uart); } } } end = (struct pcdp_device *) ((u8 *) pcdp + pcdp->length); for (dev = (struct pcdp_device *) (pcdp->uart + pcdp->num_uarts); dev < end; dev = (struct pcdp_device *) ((u8 *) dev + dev->length)) { if (dev->flags & PCDP_PRIMARY_CONSOLE) { if (dev->type == PCDP_CONSOLE_VGA) { return setup_vga_console((struct pcdp_vga *) dev); } } } return -ENODEV; }
/* * Parse the HCDP table to find descriptions for headless console and debug * serial ports and add them to rs_table[]. A pointer to HCDP table is * passed as parameter. This function should be called before * serial_console_init() is called to make sure the HCDP serial console will * be available for use. IA-64 kernel calls this function from setup_arch() * after the EFI and ACPI tables have been parsed. */ void __init setup_serial_hcdp(void *tablep) { hcdp_dev_t *hcdp_dev; struct uart_port port; unsigned long iobase; hcdp_t hcdp; int gsi, nr; static char options[16]; #if 0 static int shift_once = 1; #endif #ifdef SERIAL_DEBUG_HCDP printk("Entering setup_serial_hcdp()\n"); #endif /* Verify we have a valid table pointer */ if (!tablep) return; memset(&port, 0, sizeof(port)); /* * Don't trust firmware to give us a table starting at an aligned * address. Make a local copy of the HCDP table with aligned * structures. */ memcpy(&hcdp, tablep, sizeof(hcdp)); /* * Perform a sanity check on the table. Table should have a signature * of "HCDP" and it should be atleast 82 bytes long to have any * useful information. */ if ((strncmp(hcdp.signature, HCDP_SIGNATURE, HCDP_SIG_LEN) != 0)) return; if (hcdp.len < 82) return; #ifdef SERIAL_DEBUG_HCDP printk("setup_serial_hcdp(): table pointer = 0x%p, sig = '%.4s'\n", tablep, hcdp.signature); printk(" length = %d, rev = %d, ", hcdp.len, hcdp.rev); printk("OEM ID = %.6s, # of entries = %d\n", hcdp.oemid, hcdp.num_entries); #endif /* * Parse each device entry */ for (nr = 0; nr < hcdp.num_entries; nr++) { hcdp_dev = hcdp.hcdp_dev + nr; /* * We will parse only the primary console device which is * the first entry for these devices. We will ignore rest * of the entries for the same type device that has already * been parsed and initialized */ if (hcdp_dev->type != HCDP_DEV_CONSOLE) continue; iobase = ((u64) hcdp_dev->base_addr.addrhi << 32) | hcdp_dev->base_addr.addrlo; gsi = hcdp_dev->global_int; /* See PCI spec v2.2, Appendix D (Class Codes): */ switch (hcdp_dev->pci_prog_intfc) { case 0x00: port.type = PORT_8250; break; case 0x01: port.type = PORT_16450; break; case 0x02: port.type = PORT_16550; break; case 0x03: port.type = PORT_16650; break; case 0x04: port.type = PORT_16750; break; case 0x05: port.type = PORT_16850; break; case 0x06: port.type = PORT_16C950; break; default: printk(KERN_WARNING "warning: EFI HCDP table reports " "unknown serial programming interface 0x%02x; " "will autoprobe.\n", hcdp_dev->pci_prog_intfc); port.type = PORT_UNKNOWN; break; } #ifdef SERIAL_DEBUG_HCDP printk(" type = %s, uart = %d\n", ((hcdp_dev->type == HCDP_DEV_CONSOLE) ? "Headless Console" : ((hcdp_dev->type == HCDP_DEV_DEBUG) ? "Debug port" : "Huh????")), port.type); printk(" base address space = %s, base address = 0x%lx\n", ((hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) ? "Memory Space" : ((hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) ? "I/O space" : "PCI space")), iobase); printk(" gsi = %d, baud rate = %lu, bits = %d, clock = %d\n", gsi, (unsigned long) hcdp_dev->baud, hcdp_dev->bits, hcdp_dev->clock_rate); if (HCDP_PCI_UART(hcdp_dev)) printk(" PCI id: %02x:%02x:%02x, vendor ID=0x%x, " "dev ID=0x%x\n", hcdp_dev->pci_seg, hcdp_dev->pci_bus, hcdp_dev->pci_dev, hcdp_dev->pci_vendor_id, hcdp_dev->pci_dev_id); #endif /* * Now fill in a port structure to update the 8250 port table.. */ if (hcdp_dev->clock_rate) port.uartclk = hcdp_dev->clock_rate; else port.uartclk = BASE_BAUD * 16; /* * Check if this is an I/O mapped address or a memory mapped * address */ if (hcdp_dev->base_addr.space_id == ACPI_MEM_SPACE) { port.iobase = 0; port.mapbase = iobase; port.membase = ioremap(iobase, 64); port.iotype = SERIAL_IO_MEM; } else if (hcdp_dev->base_addr.space_id == ACPI_IO_SPACE) { port.iobase = iobase; port.mapbase = 0; port.membase = NULL; port.iotype = SERIAL_IO_PORT; } else if (hcdp_dev->base_addr.space_id == ACPI_PCICONF_SPACE) { printk(KERN_WARNING"warning: No support for PCI serial console\n"); return; } if (HCDP_IRQ_SUPPORTED(hcdp_dev)) { #ifdef CONFIG_IA64 if (HCDP_PCI_UART(hcdp_dev)) port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_LOW, ACPI_LEVEL_SENSITIVE); else port.irq = acpi_register_irq(gsi, ACPI_ACTIVE_HIGH, ACPI_EDGE_SENSITIVE); #else port.irq = gsi; #endif port.flags |= UPF_AUTO_IRQ; if (HCDP_PCI_UART(hcdp_dev)) port.flags |= UPF_SHARE_IRQ; } port.flags |= UPF_SKIP_TEST | UPF_BOOT_AUTOCONF | UPF_RESOURCES; /* * Note: the above memset() initializes port.line to 0, * so we register this port as ttyS0. */ if (early_serial_setup(&port) < 0) { printk("setup_serial_hcdp(): early_serial_setup() " "for HCDP serial console port failed. " "Will try any additional consoles in HCDP.\n"); memset(&port, 0, sizeof(port)); continue; } if (efi_uart_console_only()) { snprintf(options, sizeof(options), "%lun%d", hcdp_dev->baud, hcdp_dev->bits); add_preferred_console("ttyS", port.line, options); } break; } #ifdef SERIAL_DEBUG_HCDP printk("Leaving setup_serial_hcdp()\n"); #endif }