⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pcdp.c

📁 xen虚拟机源代码安装包
💻 C
字号:
/* * Parse the EFI PCDP table to locate the console device. * * (c) Copyright 2002, 2003, 2004 Hewlett-Packard Development Company, L.P. *	Khalid Aziz <khalid.aziz@hp.com> *	Alex Williamson <alex.williamson@hp.com> *	Bjorn Helgaas <bjorn.helgaas@hp.com> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. */#include <linux/acpi.h>#include <linux/console.h>#include <linux/efi.h>#include <linux/serial.h>#ifdef XEN#include <linux/efi.h>#include <linux/errno.h>#include <asm/io.h>#include <asm/iosapic.h>#include <asm/system.h>#include <acpi/acpi.h>#endif#include "pcdp.h"#ifdef XENextern struct ns16550_defaults ns16550_com1;extern unsigned int ns16550_com1_gsi;extern unsigned int ns16550_com1_polarity;extern unsigned int ns16550_com1_trigger;/* * This is kind of ugly, but older rev HCDP tables don't provide interrupt * polarity and trigger information.  Linux/ia64 discovers these properties * later via ACPI names, but we don't have that luxury in Xen/ia64.  Since * all future platforms should have newer PCDP tables, this should be a * fixed list of boxes in the field, so we can hardcode based on the model. */static void __initpcdp_hp_irq_fixup(struct pcdp *pcdp, struct pcdp_uart *uart){	efi_system_table_t *systab;	efi_config_table_t *tables;	struct acpi_table_rsdp *rsdp = NULL;	struct acpi_table_xsdt *xsdt;	struct acpi_table_header *hdr;	int i;	if (pcdp->rev >= 3 || strcmp((char *)pcdp->oemid, "HP"))		return;	/*	 * Manually walk firmware provided tables to get to the XSDT.	 * The OEM table ID on the XSDT is the platform model string.	 * We only care about ACPI 2.0 tables as that's all HP provides.	 */	systab = __va(ia64_boot_param->efi_systab);	if (!systab || systab->hdr.signature != EFI_SYSTEM_TABLE_SIGNATURE)		return;	tables = __va(systab->tables);	for (i = 0 ; i < (int)systab->nr_tables && !rsdp ; i++) {		if (efi_guidcmp(tables[i].guid, ACPI_20_TABLE_GUID) == 0)			rsdp =			     (struct acpi_table_rsdp *)__va(tables[i].table);	}	if (!rsdp ||	    strncmp(rsdp->signature, ACPI_SIG_RSDP, sizeof(ACPI_SIG_RSDP) - 1))		return;	xsdt = (struct acpi_table_xsdt *)__va(rsdp->xsdt_physical_address);	hdr = &xsdt->header;	if (strncmp(hdr->signature, ACPI_SIG_XSDT, sizeof(ACPI_SIG_XSDT) - 1))		return;	/* Sanity check; are we still looking at HP firmware tables? */	if (strcmp(hdr->oem_id, "HP"))		return;	if (!strcmp(hdr->oem_table_id, "zx2000") ||	    !strcmp(hdr->oem_table_id, "zx6000") ||	    !strcmp(hdr->oem_table_id, "rx2600") ||	    !strcmp(hdr->oem_table_id, "cx2600")) {		ns16550_com1.irq = ns16550_com1_gsi = uart->gsi;		ns16550_com1_polarity = IOSAPIC_POL_HIGH;		ns16550_com1_trigger = IOSAPIC_EDGE;	} else if (!strcmp(hdr->oem_table_id, "rx2620") ||	           !strcmp(hdr->oem_table_id, "cx2620") ||	           !strcmp(hdr->oem_table_id, "rx1600") ||	           !strcmp(hdr->oem_table_id, "rx1620")) {		ns16550_com1.irq = ns16550_com1_gsi = uart->gsi;		ns16550_com1_polarity = IOSAPIC_POL_LOW;		ns16550_com1_trigger = IOSAPIC_LEVEL;	}}static void __initsetup_pcdp_irq(struct pcdp *pcdp, struct pcdp_uart *uart){	/* PCDP provides full interrupt info */	if (pcdp->rev >= 3) {		if (uart->flags & PCDP_UART_IRQ) {			ns16550_com1.irq = ns16550_com1_gsi = uart->gsi,			ns16550_com1_polarity =			               uart->flags & PCDP_UART_ACTIVE_LOW ?		                       IOSAPIC_POL_LOW : IOSAPIC_POL_HIGH;			ns16550_com1_trigger =			               uart->flags & PCDP_UART_EDGE_SENSITIVE ?		                       IOSAPIC_EDGE : IOSAPIC_LEVEL;		}		return;	}	/* HCDP support */	if (uart->pci_func & PCDP_UART_IRQ) {		/*		 * HCDP tables don't provide interrupt polarity/trigger		 * info.  If the UART is a PCI device, we know to program		 * it as low/level.  Otherwise rely on platform hacks or		 * default to polling (irq = 0).		 */		if (uart->pci_func & PCDP_UART_PCI) {			ns16550_com1.irq = ns16550_com1_gsi = uart->gsi;			ns16550_com1_polarity = IOSAPIC_POL_LOW;			ns16550_com1_trigger = IOSAPIC_LEVEL;		} else if (!strcmp((char *)pcdp->oemid, "HP"))			pcdp_hp_irq_fixup(pcdp, uart);	}}static int __initsetup_serial_console(struct pcdp_uart *uart){	ns16550_com1.baud = uart->baud ? uart->baud : BAUD_AUTO;	ns16550_com1.io_base = uart->addr.address;	if (uart->bits)		ns16550_com1.data_bits = uart->bits;#ifndef XEN	setup_pcdp_irq(efi.hcdp, uart);	/* Hide the HCDP table from dom0, xencons will be the console */	efi.hcdp = NULL;#else	setup_pcdp_irq(__va(efi.hcdp), uart);	/* Hide the HCDP table from dom0, xencons will be the console */	efi.hcdp = EFI_INVALID_TABLE_ADDR;#endif	return 0;}static int __initsetup_vga_console(struct pcdp_vga *vga){#ifdef CONFIG_VGA	/*	 * There was no console= in the original cmdline, and the PCDP	 * is telling us VGA is the primary console.  We can call	 * cmdline_parse() manually to make things appear automagic.	 *	 * NB - cmdline_parse() expects the first part of the cmdline	 * to be the image name.  So "pcdp" below is just filler.	 */	char *console_cmdline = "pcdp console=vga";	cmdline_parse(console_cmdline);	/*	 * Leave efi.hcdp intact since dom0 will take ownership.	 * vga=keep is handled in start_kernel().	 */	return 0;#else	return -ENODEV;#endif}#else /* XEN */static int __initsetup_serial_console(struct pcdp_uart *uart){#ifdef CONFIG_SERIAL_8250_CONSOLE	int mmio;	static char options[64];	mmio = (uart->addr.address_space_id == ACPI_ADR_SPACE_SYSTEM_MEMORY);	snprintf(options, sizeof(options), "console=uart,%s,0x%lx,%lun%d",		mmio ? "mmio" : "io", uart->addr.address, uart->baud,		uart->bits ? uart->bits : 8);	return early_serial_console_init(options);#else	return -ENODEV;#endif}static int __initsetup_vga_console(struct pcdp_vga *vga){#if defined(CONFIG_VT) && defined(CONFIG_VGA_CONSOLE)	if (efi_mem_type(0xA0000) == EFI_CONVENTIONAL_MEMORY) {		printk(KERN_ERR "PCDP: VGA selected, but frame buffer is not MMIO!\n");		return -ENODEV;	}	conswitchp = &vga_con;	printk(KERN_INFO "PCDP: VGA console\n");	return 0;#else	return -ENODEV;#endif}#endif /* XEN */int __initefi_setup_pcdp_console(char *cmdline){	struct pcdp *pcdp;	struct pcdp_uart *uart;	struct pcdp_device *dev, *end;	int i, serial = 0;#ifndef XEN	pcdp = efi.hcdp;	if (!pcdp)		return -ENODEV;#else	if (efi.hcdp == EFI_INVALID_TABLE_ADDR)		return -ENODEV;	pcdp = __va(efi.hcdp);#endif	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;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -