📄 console.c
字号:
int currcons = fg_console; unsigned char c; static unsigned long printing; const ushort *start; ushort cnt = 0; ushort myx; /* console busy or not yet initialized */ if (!printable || test_and_set_bit(0, &printing)) return;#ifdef CONFIG_CONSOLE_PM // bushi pm_access(pm_con);#endif if (kmsg_redirect && vc_cons_allocated(kmsg_redirect - 1)) currcons = kmsg_redirect - 1; /* read `x' only after setting currcons properly (otherwise the `x' macro will read the x of the foreground console). */ myx = x; if (!vc_cons_allocated(currcons)) { /* impossible */ /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */ goto quit; } if (vcmode != KD_TEXT) goto quit; /* undraw cursor first */ if (IS_FG) hide_cursor(currcons); start = (ushort *)pos; /* Contrived structure to try to emulate original need_wrap behaviour * Problems caused when we have need_wrap set on '\n' character */ while (count--) { c = *b++; if (c == 10 || c == 13 || c == 8 || need_wrap) { if (cnt > 0) { if (IS_VISIBLE) sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x); x += cnt; if (need_wrap) x--; cnt = 0; } if (c == 8) { /* backspace */ bs(currcons); start = (ushort *)pos; myx = x; continue; } if (c != 13) lf(currcons); cr(currcons); start = (ushort *)pos; myx = x; if (c == 10 || c == 13) continue; } scr_writew((attr << 8) + c, (unsigned short *) pos); cnt++; if (myx == video_num_columns - 1) { need_wrap = 1; continue; } pos+=2; myx++; } if (cnt > 0) { if (IS_VISIBLE) sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x); x += cnt; if (x == video_num_columns) { x--; need_wrap = 1; } } set_cursor(currcons);#ifdef CONFIG_CONSOLE_PM // bushi if (!oops_in_progress) poke_blanked_console();#endifquit: clear_bit(0, &printing);}static kdev_t vt_console_device(struct console *c){ return MKDEV(TTY_MAJOR, c->index ? c->index : fg_console + 1);}struct console vt_console_driver = { name: "tty", write: vt_console_print, device: vt_console_device, wait_key: keyboard_wait_for_keypress,#ifdef CONFIG_CONSOLE_PM // bushi unblank: unblank_screen,#endif flags: CON_PRINTBUFFER, index: -1,};#endif/* * Handling of Linux-specific VC ioctls *//* * Generally a bit racy with respect to console_sem(). * * There are some functions which don't need it. * * There are some functions which can sleep for arbitrary periods (paste_selection) * but we don't need the lock there anyway. * * set_selection has locking, and definitely needs it */int tioclinux(struct tty_struct *tty, unsigned long arg){ char type, data; int ret; if (tty->driver.type != TTY_DRIVER_TYPE_CONSOLE) return -EINVAL; if (current->tty != tty && !capable(CAP_SYS_ADMIN)) return -EPERM; if (get_user(type, (char *)arg)) return -EFAULT; ret = 0; switch (type) { case 2: acquire_console_sem(); ret = set_selection(arg, tty, 1); release_console_sem(); break; case 3: ret = paste_selection(tty); break; case 4:#ifdef CONFIG_CONSOLE_PM // bushi unblank_screen();#endif break; case 5: ret = sel_loadlut(arg); break; case 6: /* * Make it possible to react to Shift+Mousebutton. * Note that 'shift_state' is an undocumented * kernel-internal variable; programs not closely * related to the kernel should not use this. */ data = shift_state; ret = __put_user(data, (char *) arg); break; case 7: data = mouse_reporting(); ret = __put_user(data, (char *) arg); break; case 10:#ifdef CONFIG_CONSOLE_PM //bushi set_vesa_blanking(arg);#endif break;; case 11: /* set kmsg redirect */ if (!capable(CAP_SYS_ADMIN)) { ret = -EPERM; } else { if (get_user(data, (char *)arg+1)) ret = -EFAULT; else kmsg_redirect = data; } break; case 12: /* get fg_console */ ret = fg_console; break; default: ret = -EINVAL; break; } return ret;}/* * /dev/ttyN handling */static int con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ int retval;#ifdef CONFIG_CONSOLE_PM // bushi pm_access(pm_con);#endif retval = do_con_write(tty, from_user, buf, count); con_flush_chars(tty); return retval;}static void con_put_char(struct tty_struct *tty, unsigned char ch){ if (in_interrupt()) return; /* n_r3964 calls put_char() from interrupt context */#ifdef CONFIG_CONSOLE_PM // bushi pm_access(pm_con);#endif do_con_write(tty, 0, &ch, 1);}static int con_write_room(struct tty_struct *tty){ if (tty->stopped) return 0; return 4096; /* No limit, really; we're not buffering */}static int con_chars_in_buffer(struct tty_struct *tty){ return 0; /* we're not buffering */}/* * con_throttle and con_unthrottle are only used for * paste_selection(), which has to stuff in a large number of * characters... */static void con_throttle(struct tty_struct *tty){}static void con_unthrottle(struct tty_struct *tty){ struct vt_struct *vt = (struct vt_struct *) tty->driver_data; wake_up_interruptible(&vt->paste_wait);}/* * Turn the Scroll-Lock LED on when the tty is stopped */static void con_stop(struct tty_struct *tty){ int console_num; if (!tty) return; console_num = MINOR(tty->device) - (tty->driver.minor_start); if (!vc_cons_allocated(console_num)) return; set_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); set_leds();}/* * Turn the Scroll-Lock LED off when the console is started */static void con_start(struct tty_struct *tty){ int console_num; if (!tty) return; console_num = MINOR(tty->device) - (tty->driver.minor_start); if (!vc_cons_allocated(console_num)) return; clr_vc_kbd_led(kbd_table + console_num, VC_SCROLLOCK); set_leds();}/* * we can race here against con_close, so we grab the bkl * and check the pointer before calling set_cursor */static void con_flush_chars(struct tty_struct *tty){ struct vt_struct *vt; if (in_interrupt()) /* from flush_to_ldisc */ return;#if 0 pm_access(pm_con);#endif lock_kernel(); acquire_console_sem(); vt = (struct vt_struct *)tty->driver_data; if (vt) set_cursor(vt->vc_num); release_console_sem(); unlock_kernel();}/* * Allocate the console screen memory. */static int con_open(struct tty_struct *tty, struct file * filp){ unsigned int currcons; int i; currcons = MINOR(tty->device) - tty->driver.minor_start; i = vc_allocate(currcons); if (i) return i; vt_cons[currcons]->vc_num = currcons; tty->driver_data = vt_cons[currcons]; if (!tty->winsize.ws_row && !tty->winsize.ws_col) { tty->winsize.ws_row = video_num_lines; tty->winsize.ws_col = video_num_columns; } if (tty->count == 1) vcs_make_devfs (currcons, 0); return 0;}static void con_close(struct tty_struct *tty, struct file * filp){ if (!tty) return; if (tty->count != 1) return; vcs_make_devfs (MINOR (tty->device) - tty->driver.minor_start, 1); tty->driver_data = 0;}static void vc_init(unsigned int currcons, unsigned int rows, unsigned int cols, int do_clear){ int j, k ; video_num_columns = cols; video_num_lines = rows; video_size_row = cols<<1; screenbuf_size = video_num_lines * video_size_row; set_origin(currcons); pos = origin; reset_vc(currcons); for (j=k=0; j<16; j++) { vc_cons[currcons].d->vc_palette[k++] = default_red[j] ; vc_cons[currcons].d->vc_palette[k++] = default_grn[j] ; vc_cons[currcons].d->vc_palette[k++] = default_blu[j] ; } def_color = 0x07; /* white */ ulcolor = 0x0f; /* bold white */ halfcolor = 0x08; /* grey */ init_waitqueue_head(&vt_cons[currcons]->paste_wait); reset_terminal(currcons, do_clear);}/* * This routine initializes console interrupts, and does nothing * else. If you want the screen to clear, call tty_write with * the appropriate escape-sequence. */struct tty_driver console_driver;static int console_refcount;void __init con_init(void){ const char *display_desc = NULL; unsigned int currcons = 0; if (conswitchp) display_desc = conswitchp->con_startup(); if (!display_desc) { fg_console = 0; return; } memset(&console_driver, 0, sizeof(struct tty_driver)); console_driver.magic = TTY_DRIVER_MAGIC; console_driver.name = "vc/%d"; console_driver.name_base = 1; console_driver.major = TTY_MAJOR; console_driver.minor_start = 1; console_driver.num = MAX_NR_CONSOLES; console_driver.type = TTY_DRIVER_TYPE_CONSOLE; console_driver.init_termios = tty_std_termios; console_driver.flags = TTY_DRIVER_REAL_RAW | TTY_DRIVER_RESET_TERMIOS; /* Tell tty_register_driver() to skip consoles because they are * registered before kmalloc() is ready. We'll patch them in later. * See comments at console_init(); see also con_init_devfs(). */ console_driver.flags |= TTY_DRIVER_NO_DEVFS; console_driver.refcount = &console_refcount; console_driver.table = console_table; console_driver.termios = console_termios; console_driver.termios_locked = console_termios_locked; console_driver.open = con_open; console_driver.close = con_close; console_driver.write = con_write; console_driver.write_room = con_write_room; console_driver.put_char = con_put_char; console_driver.flush_chars = con_flush_chars; console_driver.chars_in_buffer = con_chars_in_buffer; console_driver.ioctl = vt_ioctl; console_driver.stop = con_stop; console_driver.start = con_start; console_driver.throttle = con_throttle; console_driver.unthrottle = con_unthrottle; if (tty_register_driver(&console_driver)) panic("Couldn't register console driver\n");#ifdef CONFIG_CONSOLE_PM // bushi init_timer(&console_timer); console_timer.function = blank_screen; if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); }#endif /* * kmalloc is not running yet - we use the bootmem allocator. */ for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) { vc_cons[currcons].d = (struct vc_data *) alloc_bootmem(sizeof(struct vc_data)); vt_cons[currcons] = (struct vt_struct *) alloc_bootmem(sizeof(struct vt_struct)); visual_init(currcons, 1); screenbuf = (unsigned short *) alloc_bootmem(screenbuf_size); kmalloced = 0; vc_init(currcons, video_num_lines, video_num_columns, currcons || !sw->con_save_screen); } currcons = fg_console = 0; master_display_fg = vc_cons[currcons].d; set_origin(currcons); save_screen(currcons); gotoxy(currcons,x,y); csi_J(currcons, 0); update_screen(fg_console); printk("Console: %s %s %dx%d", can_do_color ? "colour" : "mono", display_desc, video_num_columns, video_num_lines); printable = 1; printk("\n");#ifdef CONFIG_VT_CONSOLE register_console(&vt_console_driver);#endif}#ifndef VT_SINGLE_DRIVERstatic void clear_buffer_attributes(int currcons){ unsigned short *p = (unsigned short *) origin; int count = screenbuf_size/2; int mask = hi_font_mask | 0xff; for (; count > 0; count--, p++) { scr_writew((scr_readw(p)&mask) | (video_erase_char&~mask), p); }}/* * If we support more console drivers, this function is used * when a driver wants to take over some existing consoles * and become default driver for newly opened ones. */void take_over_console(const struct consw *csw, int first, int last, int deflt){ int i, j = -1; const char *desc; desc = csw->con_startup(); if (!desc) return; if (deflt) conswitchp = csw; for (i = first; i <= last; i++) { int old_was_color; int currcons = i; con_driver_map[i] = csw; if (!vc_cons[i].d || !vc_cons[i].d->vc_sw) continue; j = i; if (IS_VISIBLE) save_screen(i); old_was_color = vc_cons[i].d->vc_can_do_color; vc_cons[i].d->vc_sw->con_deinit(vc_cons[i].d); visual_init(i, 0); update_attr(i); /* If the console changed between mono <-> color, then * the attributes in the screenbuf will be wrong. The * following resets all attributes to something sane. */ if (old_was_color != vc_cons[i].d->vc_can_do_color) clear_buffer_attributes(i); if (IS_VISIBLE) update_screen(i); } printk("Console: switching "); if (!deflt) printk("consoles %d-%d ", first+1, last+1); if (j >= 0) printk("to %s %s %dx%d\n", vc_cons[j].d->vc_can_do_color ? "colour" : "mono", desc, vc_cons[j].d->vc_cols, vc_cons[j].d->vc_rows); else printk("to %s\n", desc);}void give_up_console(const struct consw *csw){ int i; for(i = 0; i < MAX_NR_CONSOLES; i++) if (con_driver_map[i] == csw) con_driver_map[i] = NULL;}#endif#ifdef CONFIG_CONSOLE_PM // bushi/* * Screen blanking */static void set_vesa_blanking(unsigned long arg){ char *argp = (char *)arg + 1
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -