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

< ARRAY_SIZE(old_serial_port) && i < nr_uarts;i++, up++) {/*up->port.iobase= old_serial_port[i].port;up->port.irq= irq_canonicalize(old_serial_port[i].irq);up->port.irqflags = old_serial_port[i].irqflags;up->port.uartclk= old_serial_port[i].baud_base * 16;up->port.flags= old_serial_port[i].flags;up->port.hub6= old_serial_port[i].hub6;up->port.membase= old_serial_port[i].iomem_base;up->port.iotype= old_serial_port[i].io_type;up->port.regshift = old_serial_port[i].iomem_reg_shift;set_io_from_upio(&up->port);up->port.irqflags |= irqflag;if (serial8250_isa_config != NULL)serial8250_isa_config(i, &up->port, &up->capabilities);*/}}//下边再次调用register_console()注册serial8250_console真正的console终端void register_console(struct console *newcon){int i;unsigned long flags;struct console *bcon = NULL;/*现在是注册一个serial8250_console,即static struct console serial8250_console = {.name= "ttyS",.write= serial8250_console_write,//写方法.device= uart_console_device,//tty驱动.setup= serial8250_console_setup,//设置串口波特率,也就是设置串口 。很重要,里面涉及到平台特性,波特率相关 。.early_setup= serial8250_console_early_setup,.flags= CON_PRINTBUFFER | CON_ANYTIME,.index= -1,.data= http://www.kingceram.com/post/&serial8250_reg,};*/if (console_drivers && newcon->flags & CON_BOOT) {//注册的是serial8250_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)//如果注册的是引导控制台,serial8250_console不是引导控制台bcon = console_drivers;//这里不执行 if (preferred_console < 0 || bcon || !console_drivers)preferred_console = selected_console;//设置preferred_console为uboot命令选择的selected_console(即在Uboot传入的参数“console=ttyS2,115200n8”在console_cmdline[]数组中的索引)//这里preferred_console =0if (newcon->early_setup)//serial8250_console初始化early_setup字段newcon->early_setup();//调用serial8250_console_early_setup()if (preferred_console < 0) {//由于preferred_console =0,不会进入下边if (newcon->index < 0)newcon->index = 0;if (newcon->setup == NULL ||newcon->setup(newcon, NULL) == 0) {newcon->flags |= CON_ENABLED;if (newcon->device) {newcon->flags |= CON_CONSDEV;preferred_console = 0;}}}//传给内核参数://Kernel command line: console=ttyS2,115200n8 rw root=/dev/ram0 initrd=0xc2000000,20M mem=128M ip=192.168.1.220::192.168.1.1:255.255.255.0::eth0:off//所以这里将根据传参console=ttyS2,115200来配置作为console的ttyS2串口for (i = 0; i < MAX_CMDLINECONSOLES && console_cmdline[i].name[0];i++) {//遍历全局console_cmdline找到匹配的,i=0就是匹配的“ttyS2”if (strcmp(console_cmdline[i].name, newcon->name) != 0)//比较终端名称“ttyS”continue;if (newcon->index >= 0 &&newcon->index != console_cmdline[i].index)//console_cmdline[i].index=2 。//比较次设备号continue;if (newcon->index < 0)newcon->index = console_cmdline[i].index;//将终端号赋值给serial8250_console->index,这里是2//console_cmdline[i].options = "115200n8",对于serial8250_console而言setup字段已初始化if (newcon->setup && newcon->setup(newcon, console_cmdline[i].options) != 0)//调用serial8250_console_setup()对终端进行配置,调用不成功break;//在这里注册serial8250_console时,调用serial8250_console_setup()由于port->iobase和port->membase不是有效值,//故返回错误,这样下边的操作不会执行,直接break跳出,从flag1出跳出函数 。即在这里serial8250_console没有注册成功//由于内核在下边的操作队串口进行初始化时,还会调用register_console()来注册serial8250_console,在那时注册就会成功newcon->flags |= CON_ENABLED; //设置标志为CON_ENABLE,表示console使能(这个在printk调用中使用到) newcon->index = console_cmdline[i].index;//设置索引号if (i == selected_console) { //索引号和uboot指定的console的一样 newcon->flags |= CON_CONSDEV;//设置标志CON_CONSDEV(全局console_drivers链表中靠前) preferred_console = selected_console;}break;}//for循环作用大致是查看注册的console是否是uboot知道的引导console,是则设置相关标志和preferred_console//flag1:if (!(newcon->flags & CON_ENABLED))//若前边没有设置CON_ENABLED标志,就退出return;if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))//防止重复打印newcon->flags &= ~CON_PRINTBUFFER;acquire_console_sem();if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {//如果是preferred控制台newcon->next = console_drivers;console_drivers = newcon;//添加进全局console_drivers链表前面位置(printk中会遍历该表调用合适的console的write方法打印信息)if (newcon->next)newcon->next->flags &= ~CON_CONSDEV;} else {//如果不是preferred控制台 newcon->next = console_drivers->next;console_drivers->next = newcon; //添加进全局console_drivers链表后面位置}//主册console主要是刷选preferred_console放置在全局console_drivers链表前面,剩下的console放置链表靠后的位置,并设置相应的flags,//console_drivers最终会在printk函数的层层调用中遍历到,并调用console的write方法将信息打印出来if (newcon->flags & CON_PRINTBUFFER) {spin_lock_irqsave(&logbuf_lock, flags);con_start = log_start;spin_unlock_irqrestore(&logbuf_lock, flags);}release_console_sem();if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV)) {printk(KERN_INFO "console [%s%d] enabled, bootconsole disabled\n",newcon->name, newcon->index);for_each_console(bcon)if (bcon->flags & CON_BOOT)unregister_console(bcon);} else {//调用这里printk(KERN_INFO "%sconsole [%s%d] enabled\n",(newcon->flags & CON_BOOT) ? "boot" : "" ,newcon->name, newcon->index);}}//serial8250_console_early_setup()-->serial8250_find_port_for_earlycon()int serial8250_find_port_for_earlycon(void){struct early_serial8250_device *device = &early_device;//early console初始化时对early_device结构的初始化struct uart_port *port = &device->port;int line;int ret;if (!device->port.membase && !device->port.iobase)//early_device结构初始化时已经配置好return -ENODEV;//early console注册时不会调用此函数 。//当真正的console初始化时,会调用此函数 。//真正的console初始化时,会查找early console注册时用的是哪一个串口号,从serial8250_ports[]中根据uart_port->mapbase地址来比对line = serial8250_find_port(port);//根据uart_port结构找到串口号,比对没有找到串口号,line返回负值if (line