歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux基礎 >> 關於Linux

Linux console(控制台)代碼

//在/kernel/drivers/serial/samsung.c 中 /* Console code */
  #ifdef CONFIG_SERIAL_SAMSUNG_CONSOLE
  static struct uart_port *cons_uart;
  static int s3c24xx_serial_console_txrdy(struct uart_port *port, unsigned int ufcon)//准備發送 { struct s3c24xx_uart_info *info = s3c24xx_port_to_info(port); unsigned long ufstat, utrstat;
  if (ufcon & S3C2410_UFCON_FIFOMODE) { /* fifo mode - check ammount of data in fifo registers... */
  ufstat = rd_regl(port, S3C2410_UFSTAT); return (ufstat & info->tx_fifofull) ? 0 : 1; }
  /* in non-fifo mode, we go and use the tx buffer empty */
  utrstat = rd_regl(port, S3C2410_UTRSTAT); return (utrstat & S3C2410_UTRSTAT_TXE) ? 1 : 0; }
  static void s3c24xx_serial_console_putchar(struct uart_port *port, int ch)//是最底層的函數 { unsigned int ufcon = rd_regl(cons_uart, S3C2410_UFCON); while (!s3c24xx_serial_console_txrdy(port, ufcon)) barrier(); wr_regb(cons_uart, S3C2410_UTXH, ch); }
  static void s3c24xx_serial_console_write(struct console *co, const char *s, unsigned int count) { //通過調用上面的s3c24xx_serial_console_putchar輸出字符 uart_console_write(cons_uart, s, count, s3c24xx_serial_console_putchar);   }
  static void __init s3c24xx_serial_get_options(struct uart_port *port, int *baud, int *parity, int *bits) { struct s3c24xx_uart_clksrc clksrc; struct clk *clk; unsigned int ulcon; unsigned int ucon; unsigned int ubrdiv; unsigned long rate;
  ulcon = rd_regl(port, S3C2410_ULCON); ucon = rd_regl(port, S3C2410_UCON); ubrdiv = rd_regl(port, S3C2410_UBRDIV);
  dbg("s3c24xx_serial_get_options: port=%p\n" "registers: ulcon=%08x, ucon=%08x, ubdriv=%08x\n", port, ulcon, ucon, ubrdiv);
  if ((ucon & 0xf) != 0) { /* consider the serial port configured if the tx/rx mode set */
  switch (ulcon & S3C2410_LCON_CSMASK) { case S3C2410_LCON_CS5: *bits = 5; break; case S3C2410_LCON_CS6: *bits = 6; break; case S3C2410_LCON_CS7: *bits = 7; break; default: case S3C2410_LCON_CS8: *bits = 8; break; }
  switch (ulcon & S3C2410_LCON_PMASK) { case S3C2410_LCON_PEVEN: *parity = 'e'; break;
  case S3C2410_LCON_PODD: *parity = 'o'; break;
  case S3C2410_LCON_PNONE: default: *parity = 'n'; }
  /* now calculate the baud rate */
  s3c24xx_serial_getsource(port, &clksrc);
  clk = clk_get(port->dev, clksrc.name); if (!IS_ERR(clk) && clk != NULL) rate = clk_get_rate(clk) / clksrc.divisor; else rate = 1;
 
  *baud = rate / (16 * (ubrdiv + 1)); dbg("calculated baud %d\n", *baud); }
  }
  /* s3c24xx_serial_init_ports * * initialise the serial ports from the machine provided initialisation * data. */
  static int s3c24xx_serial_init_ports(struct s3c24xx_uart_info **info) { struct s3c24xx_uart_port *ptr = s3c24xx_serial_ports; struct platform_device **platdev_ptr; int i;
  dbg("s3c24xx_serial_init_ports: initialising ports...\n");
  platdev_ptr = s3c24xx_uart_devs;
  for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++, ptr++, platdev_ptr++) { s3c24xx_serial_init_port(ptr, info[i], *platdev_ptr); }
  return 0; }
  static int __init s3c24xx_serial_console_setup(struct console *co, char *options) { struct uart_port *port; int baud = 9600; int bits = 8; int parity = 'n'; int flow = 'n';
  dbg("s3c24xx_serial_console_setup: co=%p (%d), %s\n", co, co->index, options);
  /* is this a valid port */
  if (co->index == -1 || co->index >= CONFIG_SERIAL_SAMSUNG_UARTS) co->index = 0;
  port = &s3c24xx_serial_ports[co->index].port;
  /* is the port configured? */
  if (port->mapbase == 0x0) { co->index = 0; port = &s3c24xx_serial_ports[co->index].port; }
  cons_uart = port;
  dbg("s3c24xx_serial_console_setup: port=%p (%d)\n", port, co->index);
  /* * Check whether an invalid uart number has been specified, and * if so, search for the first available port that does have * console support. */ if (options) uart_parse_options(options, &baud, &parity, &bits, &flow); else s3c24xx_serial_get_options(port, &baud, &parity, &bits);
  dbg("s3c24xx_serial_console_setup: baud %d\n", baud);
  return uart_set_options(port, co, baud, parity, bits, flow); }
  /* s3c24xx_serial_initconsole * * initialise the console from one of the uart drivers */
  static struct console s3c24xx_serial_console = { .name = S3C24XX_SERIAL_NAME, //名字 .device = uart_console_device, //init進行、用戶進程打開/dev/console時用到 .flags = CON_PRINTBUFFER, //打印先前在log_buf中保存的信息 .index = -1, //表示使用哪個串口由命令行參數決定 .write = s3c24xx_serial_console_write,//控制台輸出函數 .setup = s3c24xx_serial_console_setup//控制台設置函數 };
  int s3c24xx_serial_initconsole(struct platform_driver *drv, struct s3c24xx_uart_info **info)
  { struct platform_device *dev = s3c24xx_uart_devs[0];
  dbg("s3c24xx_serial_initconsole\n");
  /* select driver based on the cpu */
  if (dev == NULL) { printk(KERN_ERR "s3c24xx: no devices for console init\n"); return 0; }
  if (strcmp(dev->name, drv->driver.name) != 0) return 0;
  s3c24xx_serial_console.data = &s3c24xx_uart_drv;//這是控制台的驅動
  s3c24xx_serial_init_ports(info);
  register_console(&s3c24xx_serial_console);//注冊 return 0; }
  #endif /* CONFIG_SERIAL_SAMSUNG_CONSOLE */
 
 
 
  //在/kernel/drivers/serial/samsung.h中
  #define s3c24xx_console_init(__drv, __inf) \ static int __init s3c_serial_console_init(void) \ { \ struct s3c24xx_uart_info *uinfo[CONFIG_SERIAL_SAMSUNG_UARTS]; \ int i; \ \ for (i = 0; i < CONFIG_SERIAL_SAMSUNG_UARTS; i++) \ uinfo[i] = __inf; \ return s3c24xx_serial_initconsole(__drv, uinfo); \ } \ \ console_initcall(s3c_serial_console_init) //放入.con_initcall.init代碼段
 
  在tty_io.c中 /* * Initialize the console device. This is called *early*, so * we can't necessarily depend on lots of kernel help here. * Just do some early initializations, and do the complex setup * later. */ void __init console_init(void)//在start_kernel中被調用 { initcall_t *call;
  /* Setup the default TTY line discipline. */ tty_ldisc_begin();
  /* * set up the console device so that later boot sequences can * inform about problems etc.. */ call = __con_initcall_start; while (call < __con_initcall_end) { (*call)(); call++; } }

Copyright © Linux教程網 All Rights Reserved