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 + -
显示快捷键?