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;
}
Example #2
0
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;
}
Example #3
0
/*
 * 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
}