legacy_serial.c

来自「LINUX 2.6.17.4的源码」· C语言 代码 · 共 554 行 · 第 1/2 页

C
554
字号
			DBG("stdout is %s\n", stdout->full_name);	} else {		DBG(" no linux,stdout-path !\n");	}	/* First fill our array with SOC ports */	for (np = NULL; (np = of_find_compatible_node(np, "serial", "ns16550")) != NULL;) {		struct device_node *soc = of_get_parent(np);		if (soc && !strcmp(soc->type, "soc")) {			index = add_legacy_soc_port(np, np);			if (index >= 0 && np == stdout)				legacy_serial_console = index;		}		of_node_put(soc);	}	/* First fill our array with ISA ports */	for (np = NULL; (np = of_find_node_by_type(np, "serial"));) {		struct device_node *isa = of_get_parent(np);		if (isa && !strcmp(isa->name, "isa")) {			index = add_legacy_isa_port(np, isa);			if (index >= 0 && np == stdout)				legacy_serial_console = index;		}		of_node_put(isa);	}#ifdef CONFIG_PCI	/* Next, try to locate PCI ports */	for (np = NULL; (np = of_find_all_nodes(np));) {		struct device_node *pci, *parent = of_get_parent(np);		if (parent && !strcmp(parent->name, "isa")) {			of_node_put(parent);			continue;		}		if (strcmp(np->name, "serial") && strcmp(np->type, "serial")) {			of_node_put(parent);			continue;		}		/* Check for known pciclass, and also check wether we have		 * a device with child nodes for ports or not		 */		if (device_is_compatible(np, "pciclass,0700") ||		    device_is_compatible(np, "pciclass,070002"))			pci = np;		else if (device_is_compatible(parent, "pciclass,0700") ||			 device_is_compatible(parent, "pciclass,070002"))			pci = parent;		else {			of_node_put(parent);			continue;		}		index = add_legacy_pci_port(np, pci);		if (index >= 0 && np == stdout)			legacy_serial_console = index;		of_node_put(parent);	}#endif	DBG("legacy_serial_console = %d\n", legacy_serial_console);	if (legacy_serial_console >= 0)		setup_legacy_serial_console(legacy_serial_console);	DBG(" <- find_legacy_serial_port()\n");}static struct platform_device serial_device = {	.name	= "serial8250",	.id	= PLAT8250_DEV_PLATFORM,	.dev	= {		.platform_data = legacy_serial_ports,	},};static void __init fixup_port_irq(int index,				  struct device_node *np,				  struct plat_serial8250_port *port){	DBG("fixup_port_irq(%d)\n", index);	/* Check for interrupts in that node */	if (np->n_intrs > 0) {		port->irq = np->intrs[0].line;		DBG(" port %d (%s), irq=%d\n",		    index, np->full_name, port->irq);		return;	}	/* Check for interrupts in the parent */	np = of_get_parent(np);	if (np == NULL)		return;	if (np->n_intrs > 0) {		port->irq = np->intrs[0].line;		DBG(" port %d (%s), irq=%d\n",		    index, np->full_name, port->irq);	}	of_node_put(np);}static void __init fixup_port_pio(int index,				  struct device_node *np,				  struct plat_serial8250_port *port){#ifdef CONFIG_PCI	struct pci_controller *hose;	DBG("fixup_port_pio(%d)\n", index);	hose = pci_find_hose_for_OF_device(np);	if (hose) {		unsigned long offset = (unsigned long)hose->io_base_virt -#ifdef CONFIG_PPC64			pci_io_base;#else			isa_io_base;#endif		DBG("port %d, IO %lx -> %lx\n",		    index, port->iobase, port->iobase + offset);		port->iobase += offset;	}#endif}static void __init fixup_port_mmio(int index,				   struct device_node *np,				   struct plat_serial8250_port *port){	DBG("fixup_port_mmio(%d)\n", index);	port->membase = ioremap(port->mapbase, 0x100);}/* * This is called as an arch initcall, hopefully before the PCI bus is * probed and/or the 8250 driver loaded since we need to register our * platform devices before 8250 PCI ones are detected as some of them * must properly "override" the platform ones. * * This function fixes up the interrupt value for platform ports as it * couldn't be done earlier before interrupt maps have been parsed. It * also "corrects" the IO address for PIO ports for the same reason, * since earlier, the PHBs virtual IO space wasn't assigned yet. It then * registers all those platform ports for use by the 8250 driver when it * finally loads. */static int __init serial_dev_init(void){	int i;	if (legacy_serial_count == 0)		return -ENODEV;	/*	 * Before we register the platfrom serial devices, we need	 * to fixup their interrutps and their IO ports.	 */	DBG("Fixing serial ports interrupts and IO ports ...\n");	for (i = 0; i < legacy_serial_count; i++) {		struct plat_serial8250_port *port = &legacy_serial_ports[i];		struct device_node *np = legacy_serial_infos[i].np;		if (port->irq == NO_IRQ)			fixup_port_irq(i, np, port);		if (port->iotype == UPIO_PORT)			fixup_port_pio(i, np, port);		if (port->iotype == UPIO_MEM)			fixup_port_mmio(i, np, port);	}	DBG("Registering platform serial ports\n");	return platform_device_register(&serial_device);}arch_initcall(serial_dev_init);/* * This is called very early, as part of console_init() (typically just after * time_init()). This function is respondible for trying to find a good * default console on serial ports. It tries to match the open firmware * default output with one of the available serial console drivers, either * one of the platform serial ports that have been probed earlier by * find_legacy_serial_ports() or some more platform specific ones. */static int __init check_legacy_serial_console(void){	struct device_node *prom_stdout = NULL;	int speed = 0, offset = 0;	char *name;	u32 *spd;	DBG(" -> check_legacy_serial_console()\n");	/* The user has requested a console so this is already set up. */	if (strstr(saved_command_line, "console=")) {		DBG(" console was specified !\n");		return -EBUSY;	}	if (!of_chosen) {		DBG(" of_chosen is NULL !\n");		return -ENODEV;	}	if (legacy_serial_console < 0) {		DBG(" legacy_serial_console not found !\n");		return -ENODEV;	}	/* We are getting a weird phandle from OF ... */	/* ... So use the full path instead */	name = (char *)get_property(of_chosen, "linux,stdout-path", NULL);	if (name == NULL) {		DBG(" no linux,stdout-path !\n");		return -ENODEV;	}	prom_stdout = of_find_node_by_path(name);	if (!prom_stdout) {		DBG(" can't find stdout package %s !\n", name);		return -ENODEV;	}	DBG("stdout is %s\n", prom_stdout->full_name);	name = (char *)get_property(prom_stdout, "name", NULL);	if (!name) {		DBG(" stdout package has no name !\n");		goto not_found;	}	spd = (u32 *)get_property(prom_stdout, "current-speed", NULL);	if (spd)		speed = *spd;	if (0)		;#ifdef CONFIG_SERIAL_8250_CONSOLE	else if (strcmp(name, "serial") == 0) {		int i;		/* Look for it in probed array */		for (i = 0; i < legacy_serial_count; i++) {			if (prom_stdout != legacy_serial_infos[i].np)				continue;			offset = i;			speed = legacy_serial_infos[i].speed;			break;		}		if (i >= legacy_serial_count)			goto not_found;	}#endif /* CONFIG_SERIAL_8250_CONSOLE */#ifdef CONFIG_SERIAL_PMACZILOG_CONSOLE	else if (strcmp(name, "ch-a") == 0)		offset = 0;	else if (strcmp(name, "ch-b") == 0)		offset = 1;#endif /* CONFIG_SERIAL_PMACZILOG_CONSOLE */	else		goto not_found;	of_node_put(prom_stdout);	DBG("Found serial console at ttyS%d\n", offset);	if (speed) {		static char __initdata opt[16];		sprintf(opt, "%d", speed);		return add_preferred_console("ttyS", offset, opt);	} else		return add_preferred_console("ttyS", offset, NULL); not_found:	DBG("No preferred console found !\n");	of_node_put(prom_stdout);	return -ENODEV;}console_initcall(check_legacy_serial_console);

⌨️ 快捷键说明

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