TTY之register_console

extern void register_console(struct console *);
extern int unregister_console(struct console *);
extern struct console *console_drivers;
 /*
 * The console driver calls this routine during kernel initialization
 * to register the console printing procedure with printk() and to
 * print any messages that were printed by the kernel before the
 * console driver was initialized.
 *
 * This can happen pretty early during the boot process (because of
 * early_printk) - sometimes before setup_arch() completes - be careful
 * of what kernel features are used - they may not be initialised yet.
 *
 * There are two types of consoles - bootconsoles (early_printk) and
 * "real" consoles (everything which is not a bootconsole) which are
 * handled differently.
 *  - Any number of bootconsoles can be registered at any time.
 *  - As soon as a "real" console is registered, all bootconsoles
 *    will be unregistered automatically.
 *  - Once a "real" console is registered, any attempt to register a
 *    bootconsoles will be rejected
 */
void register_console(struct console *newcon)
{
 int i;
 unsigned long flags;
 struct console *bcon = NULL;
 struct console_cmdline *c;

 if (console_drivers)   for_each_console(bcon)    if (WARN(bcon == newcon,      "console '%s%d' already registered\n",      bcon->name, bcon->index))     return;

 /*   * before we register a new CON_BOOT console, make sure we don't   * already have a valid console   */  if (console_drivers && newcon->flags & CON_BOOT) {   /* find the last or real console */   for_each_console(bcon) {    if (!(bcon->flags & CON_BOOT)) {     pr_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;

 if (preferred_console < 0 || bcon || !console_drivers)   preferred_console = selected_console;

 /*   * See if we want to use this console driver. If we   * didn't select a console we take the first one   * that registers here.   */  if (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;    }   }  }

 /*   * See if this console matches one we selected on   * the command line.   */  for (i = 0, c = console_cmdline;       i < MAX_CMDLINECONSOLES && c->name[0];       i++, c++) {   if (!newcon->match ||       newcon->match(newcon, c->name, c->index, c->options) != 0) {    /* default matching */    BUILD_BUG_ON(sizeof(c->name) != sizeof(newcon->name));    if (strcmp(c->name, newcon->name) != 0)     continue;    if (newcon->index >= 0 &&        newcon->index != c->index)     continue;    if (newcon->index < 0)     newcon->index = c->index;

   if (_braille_register_console(newcon, c))     return;

   if (newcon->setup &&        newcon->setup(newcon, c->options) != 0)     break;   }

  newcon->flags |= CON_ENABLED;   if (i == selected_console) {    newcon->flags |= CON_CONSDEV;    preferred_console = selected_console;   }   break;  }

 if (!(newcon->flags & CON_ENABLED))   return;

 /*   * If we have a bootconsole, and are switching to a real console,   * don't print everything out again, since when the boot console, and   * the real console are the same physical device, it's annoying to   * see the beginning boot messages twice   */  if (bcon && ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV))   newcon->flags &= ~CON_PRINTBUFFER;

 /*   * Put this console in the list - keep the   * preferred driver at the head of the list.   */  console_lock();  if ((newcon->flags & CON_CONSDEV) || console_drivers == NULL) {   newcon->next = console_drivers;   console_drivers = newcon;   if (newcon->next)    newcon->next->flags &= ~CON_CONSDEV;  } else {   newcon->next = console_drivers->next;   console_drivers->next = newcon;  }

 if (newcon->flags & CON_EXTENDED)   if (!nr_ext_console_drivers++)    pr_info("printk: continuation disabled due to ext consoles, expect more fragments in /dev/kmsg\n");

 if (newcon->flags & CON_PRINTBUFFER) {   /*    * console_unlock(); will print out the buffered messages    * for us.    */   raw_spin_lock_irqsave(&logbuf_lock, flags);   console_seq = syslog_seq;   console_idx = syslog_idx;   console_prev = syslog_prev;   raw_spin_unlock_irqrestore(&logbuf_lock, flags);   /*    * We're about to replay the log buffer.  Only do this to the    * just-registered console to avoid excessive message spam to    * the already-registered consoles.    */   exclusive_console = newcon;  }  console_unlock();  console_sysfs_notify();

 /*   * By unregistering the bootconsoles after we enable the real console   * we get the "console xxx enabled" message on all the consoles -   * boot consoles, real consoles, etc - this is to ensure that end   * users know there might be something in the kernel's log buffer that   * went to the bootconsole (that they do not see on the real console)   */  pr_info("%sconsole [%s%d] enabled\n",   (newcon->flags & CON_BOOT) ? "boot" : "" ,   newcon->name, newcon->index);  if (bcon &&      ((newcon->flags & (CON_CONSDEV | CON_BOOT)) == CON_CONSDEV) &&      !keep_bootcon) {   /* We need to iterate through all boot consoles, to make    * sure we print everything out, before we unregister them.    */   for_each_console(bcon)    if (bcon->flags & CON_BOOT)     unregister_console(bcon);  } }

 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值