使用dmesg打印所有日志( 五 )

< 0)return err;/*static struct console early_serial8250_console __initdata = http://www.kingceram.com/post/{.name="uart",.write= early_serial8250_write,.flags= CON_PRINTBUFFER | CON_BOOT,//所用具有CON_BOOT属性的console都会在内核初始化到late initcall阶段被注销,相互消他们的函数是.index= -1,};*///注册一个早期的console,到真正的console_init时,此console会被注销,因为设置了CON_BOOT标志register_console(&early_serial8250_console);return 0;}static int __init early_serial8250_setup(char *options){struct early_serial8250_device *device = &early_device;int err;if (device->port.membase || device->port.iobase)//early_device设备的端口地址若配置过则返回return 0;err = parse_options(device, options);//解析参数并配置early_device设备对应的uart_port结构if (err < 0)return err;init_port(device);//early_device设备对应的初始化uart_port结构return 0;}static int __init parse_options(struct early_serial8250_device *device,char *options){struct uart_port *port = &device->port;//找到early_device设备对应的uart_port结构int mmio, mmio32, length;if (!options)return -ENODEV;port->uartclk = BASE_BAUD * 16;//串口时钟mmio = !strncmp(options, "mmio,", 5);//查找"mmio,"字符串,找到mmio=1mmio32 = !strncmp(options, "mmio32,", 7);//mmio32=0if (mmio || mmio32) {port->iotype = (mmio ? UPIO_MEM : UPIO_MEM32);//串口类型设为UPIO_MEM=2port->mapbase = simple_strtoul(options + (mmio ? 5 : 7),&options, 0);//获得串口的配置寄存器基础地址(物理地址),这里是得到0xff5e0000if (mmio32)port->regshift = 2;#ifdef CONFIG_FIX_EARLYCON_MEMset_fixmap_nocache(FIX_EARLYCON_MEM_BASE,port->mapbase & PAGE_MASK);port->membase =(void __iomem *)__fix_to_virt(FIX_EARLYCON_MEM_BASE);port->membase += port->mapbase & ~PAGE_MASK;#elseport->membase = ioremap_nocache(port->mapbase, 64);//映射到内存的配置寄存器基础地址if (!port->membase) {printk(KERN_ERR "%s: Couldn't ioremap 0x%llx\n",__func__,(unsigned long long) port->mapbase);return -ENOMEM;}#endif} else if (!strncmp(options, "io,", 3)) {port->iotype = UPIO_PORT;port->iobase = simple_strtoul(options + 3, &options, 0);mmio = 0;} elsereturn -EINVAL;options = strchr(options, ',');//指针移到“115200n8”字符串处if (options) {//存在options++;device->baud = simple_strtoul(options, NULL, 0);//取得波特率115200length = min(strcspn(options, " "), sizeof(device->options));strncpy(device->options, options, length);//将字符串115200n8拷贝到设备的device->options字段中} else {device->baud = probe_baud(port);snprintf(device->options, sizeof(device->options), "%u",device->baud);}if (mmio || mmio32)printk(KERN_INFO "Early serial console at MMIO%s 0x%llx (options '%s')\n",mmio32 ? "32" : "",(unsigned long long)port->mapbase,device->options);elseprintk(KERN_INFO"Early serial console at I/O port 0x%lx (options '%s')\n",port->iobase,device->options);return 0;}static void __init init_port(struct early_serial8250_device *device){struct uart_port *port = &device->port;unsigned int divisor;unsigned char c;serial_out(port, UART_LCR, 0x3);/* 8n1 */serial_out(port, UART_IER, 0);/* no interrupt */serial_out(port, UART_FCR, 0);/* no fifo */serial_out(port, UART_MCR, 0x3);/* DTR + RTS */divisor = port->uartclk / (16 * device->baud);//根据波特率设置分频c = serial_in(port, UART_LCR);serial_out(port, UART_LCR, c | UART_LCR_DLAB);serial_out(port, UART_DLL, divisor & 0xff);serial_out(port, UART_DLM, (divisor >> 8) & 0xff);serial_out(port, UART_LCR, c & ~UART_LCR_DLAB);}void register_console(struct console *newcon){int i;unsigned long flags;struct console *bcon = NULL;/*现在是注册一个early console,即static struct console early_serial8250_console __initdata = http://www.kingceram.com/post/{.name="uart",.write= early_serial8250_write,.flags= CON_PRINTBUFFER | CON_BOOT,//所用具有CON_BOOT属性的console都会在内核初始化到late initcall阶段被注销,相互消他们的函数是.index= -1,};*/if (console_drivers && newcon->flags & CON_BOOT) {//注册的是否是引导控制台 。early console的CON_BOOT置位,表示只是一个引导控制台,以后会被注销for_each_console(bcon) {遍历全局console_drivers数组if (!(bcon->flags & CON_BOOT)) {//判断是否已经有引导控制台了,有了的话就直接退出printk(KERN_INFO "Too late to register bootconsole %s%d\n",newcon->name, newcon->index);return;}}}if (console_drivers && console_drivers->flags & CON_BOOT)//如果注册的是引导控制台bcon = console_drivers;//让bcon指向全局console_driversif (preferred_console