📄 console.c
字号:
return __put_user(data, (char *) arg); case 7: data = mouse_reporting(); return __put_user(data, (char *) arg); case 10: set_vesa_blanking(arg); return 0; case 11: /* set kmsg redirect */ if (!suser()) return -EPERM; if (get_user(data, (char *)arg+1)) return -EFAULT; kmsg_redirect = data; return 0; case 12: /* get fg_console */ return fg_console; } return -EINVAL;}/* * /dev/ttyN handling */static int con_write(struct tty_struct * tty, int from_user, const unsigned char *buf, int count){ int retval; pm_access(pm_con); 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){ pm_access(pm_con); 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();}static void con_flush_chars(struct tty_struct *tty){ unsigned long flags; struct vt_struct *vt = (struct vt_struct *)tty->driver_data; pm_access(pm_con); spin_lock_irqsave(&console_lock, flags); set_cursor(vt->vc_num); spin_unlock_irqrestore(&console_lock, flags);}/* * 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;DECLARE_TASKLET_DISABLED(console_tasklet, console_softint, 0);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"); init_timer(&console_timer); console_timer.function = blank_screen; if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); } /* * 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 tasklet_enable(&console_tasklet); tasklet_schedule(&console_tasklet);}#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/* * Screen blanking */static void set_vesa_blanking(unsigned long arg){ char *argp = (char *)arg + 1; unsigned int mode; get_user(mode, argp); vesa_blank_mode = (mode < 4) ? mode : 0;}/* We can't register the console with devfs during con_init(), because it * is called before kmalloc() works. This function is called later to * do the registration. */void __init con_init_devfs (void){ int i; for (i = 0; i < console_driver.num; i++) tty_register_devfs (&console_driver, DEVFS_FL_AOPEN_NOTIFY, console_driver.minor_start + i);}static void vesa_powerdown(void){ struct vc_data *c = vc_cons[fg_console].d; /* * Power down if currently suspended (1 or 2), * suspend if currently blanked (0), * else do nothing (i.e. already powered down (3)). * Called only if powerdown features are allowed. */ switch (vesa_blank_mode) { case VESA_NO_BLANKING: c->vc_sw->con_blank(c, VESA_VSYNC_SUSPEND+1); break; case VESA_VSYNC_SUSPEND: case VESA_HSYNC_SUSPEND: c->vc_sw->con_blank(c, VESA_POWERDOWN+1); break; }}static void vesa_powerdown_screen(unsigned long dummy){ console_timer.function = unblank_screen_t; /* I don't have a clue why this is necessary */ vesa_powerdown();}static void timer_do_blank_screen(int entering_gfx, int from_timer_handler){ int currcons = fg_console; int i; if (console_blanked) return; /* entering graphics mode? */ if (entering_gfx) { hide_cursor(currcons); save_screen(currcons); sw->con_blank(vc_cons[currcons].d, -1); console_blanked = fg_console + 1; set_origin(currcons); return; } /* don't blank graphics */ if (vcmode != KD_TEXT) { console_blanked = fg_console + 1; return; } hide_cursor(currcons); if (!from_timer_handler) del_timer_sync(&console_timer); if (vesa_off_interval) { console_timer.function = vesa_powerdown_screen; mod_timer(&console_timer, jiffies + vesa_off_interval); } else { if (!from_timer_handler) del_timer_sync(&console_timer); console_timer.function = unblank_screen_t; } save_screen(currcons); /* In case we need to reset origin, blanking hook returns 1 */ i = sw->con_blank(vc_cons[currcons].d, 1); console_blanked = fg_console + 1; if (i) set_origin(currcons); if (console_blank_hook && console_blank_hook(1)) return; if (vesa_blank_mode) sw->con_blank(vc_cons[currcons].d, vesa_blank_mode + 1);}void do_blank_screen(int entering_gfx){ timer_do_blank_screen(entering_gfx, 0);}static void unblank_screen_t(unsigned long dummy){ unblank_screen();}void unblank_screen(void){ int currcons; if (!console_blanked) return; if (!vc_cons_allocated(fg_console)) { /* impossible */ printk("unblank_screen: tty %d not allocated ??\n", fg_console+1); return; } console_timer.function = blank_screen; if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); } currcons = fg_console; console_blanked = 0; if (console_blank_hook) console_blank_hook(0); set_palette(currcons); if (sw->con_blank(vc_cons[currcons].d, 0)) /* Low-level driver cannot restore -> do it ourselves */ update_screen(fg_console); set_cursor(fg_console);}static void blank_screen(unsigned long dummy){ timer_do_blank_screen(0, 1);}void poke_blanked_console(void){ del_timer(&console_timer); /* Can't use _sync here: called from tasklet */ if (vt_cons[fg_console]->vc_mode == KD_GRAPHICS) return; if (console_blanked) { console_timer.function = unblank_screen_t; mod_timer(&console_timer, jiffies); /* Now */ } else if (blankinterval) { mod_timer(&console_timer, jiffies + blankinterval); }}/* * Palettes */void set_palette(int currcons){ if (vcmode != KD_GRAPHICS) sw->con_set_palette(vc_cons[currcons].d, color_table);}static int set_get_cmap(unsigned char *arg, int set){ int i, j, k; for (i = 0; i < 16; i++) if (set) { get_user(default_red[i], arg++); get_user(default_grn[i], arg++); get_user(default_blu[i], arg++); } else { put_user(default_red[i], arg++); put_user(default_grn[i], arg++); put_user(default_blu[i], arg++); } if (set) { for (i = 0; i < MAX_NR_CONSOLES; i++) if (vc_cons_allocated(i)) { for (j = k = 0; j < 16; j++) { vc_cons[i].d->vc_palette[k++] = default_red[j]; vc_cons[i].d->vc_palette[k++] = default_grn[j]; vc_cons[i].d->vc_palette[k++] = default_blu[j]; } set_palette(i); } } return 0;}/* * Load palette into the DAC registers. arg points to a colour * map, 3 bytes per colour,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -