/* * linux/drivers/video/fbcon.c -- Low level frame buffer based console driver * * Copyright (C) 1995 Geert Uytterhoeven * * * This file is based on the original Amiga console driver (amicon.c): * * Copyright (C) 1993 Hamish Macdonald * Greg Harp * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] * * with work by William Rucklidge (wjr@cs.cornell.edu) * Geert Uytterhoeven * Jes Sorensen (jds@kom.auc.dk) * Martin Apel * * and on the original Atari console driver (atacon.c): * * Copyright (C) 1993 Bjoern Brauel * Roman Hodek * * with work by Guenther Kelleter * Martin Schaller * Andreas Schwab * * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) * Smart redraw scrolling, arbitrary font width support, 512char font support * and software scrollback added by * Jakub Jelinek (jj@ultra.linux.cz) * * Random hacking by Martin Mares <mj@ucw.cz> * * 2001 - Documented with DocBook * - Brad Douglas <brad@neruo.com> * * The low level operations for the various display memory organizations are * now in separate source files. * * Currently the following organizations are supported: * * o afb Amiga bitplanes * o cfb{2,4,8,16,24,32} Packed pixels * o ilbm Amiga interleaved bitplanes * o iplan2p[248] Atari interleaved bitplanes * o mfb Monochrome * o vga VGA characters/attributes * * To do: * * - Implement 16 plane mode (iplan2p16) * * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. */ #include <linux/export.h>#include <linux/module.h>#include <linux/types.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/delay.h> /* MSch: for IRQ probe */#include <linux/console.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/panic.h>#include <linux/pci.h>#include <linux/printk.h>#include <linux/slab.h>#include <linux/fb.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/font.h>#include <linux/smp.h>#include <linux/init.h>#include <linux/interrupt.h>#include <linux/crc32.h> /* For counting font checksums */#include <linux/uaccess.h>#include <linux/vga_switcheroo.h>#include <asm/irq.h> #include "fbcon.h"#include "fbcon_rotate.h"#include "fb_internal.h" /* * FIXME: Locking * * - fbcon state itself is protected by the console_lock, and the code does a * pretty good job at making sure that lock is held everywhere it's needed. * * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it * means concurrent access to the same fbdev from both fbcon and userspace * will blow up. To fix this all fbcon calls from fbmem.c need to be moved out * of fb_lock/unlock protected sections, since otherwise we'll recurse and * deadlock eventually. Aside: Due to these deadlock issues the fbdev code in * fbmem.c cannot use locking asserts, and there's lots of callers which get * the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too. */ enum { FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */}; static struct fbcon_display fb_display[MAX_NR_CONSOLES]; static struct fb_info *fbcon_registered_fb[FB_MAX];static int fbcon_num_registered_fb; #define fbcon_for_each_registered_fb(i) \ for (i = 0; WARN_CONSOLE_UNLOCKED(), i < FB_MAX; i++) \ if (!fbcon_registered_fb[i]) {} else static signed char con2fb_map[MAX_NR_CONSOLES];static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static struct fb_info *fbcon_info_from_console(int console){ signed char fb; WARN_CONSOLE_UNLOCKED(); fb = con2fb_map[console]; if (fb < 0 || fb >= ARRAY_SIZE(fbcon_registered_fb)) return NULL; return fbcon_registered_fb[fb];} static int logo_lines;/* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO enums. */static int logo_shown = FBCON_LOGO_CANSHOW;/* console mappings */static unsigned int first_fb_vc;static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1;static bool fbcon_is_default = true;static int primary_device = -1;static bool fbcon_has_console_bind; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARYstatic int map_override; static inline void fbcon_map_override(void){ map_override = 1;}#elsestatic inline void fbcon_map_override(void){}#endif /* CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY */ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVERstatic bool deferred_takeover = true;#else#define deferred_takeover false#endif /* font data */static char fontname[40]; /* current fb_info */static int info_idx = -1; /* console rotation */static int initial_rotation = -1;static int margin_color; static const struct consw fb_con; #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) static bool fbcon_cursor_blink = true; #define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) /* * Interface used by the world */ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only);static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); /* * Internal routines */static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, int unit);static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, int line, int count, int dy);static void fbcon_modechanged(struct fb_info *info);static void fbcon_set_all_vcs(struct fb_info *info); static struct device *fbcon_device; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATIONstatic inline void fbcon_set_rotation(struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; if (!(info->flags & FBINFO_MISC_TILEBLITTING) && par->p->con_rotate < 4) par->rotate = par->p->con_rotate; else par->rotate = 0;} static void fbcon_rotate(struct fb_info *info, u32 rotate){ struct fbcon_par *par = info->fbcon_par; struct fb_info *fb_info; if (!par || par->currcon == -1) return; fb_info = fbcon_info_from_console(par->currcon); if (info == fb_info) { struct fbcon_display *p = &fb_display[par->currcon]; if (rotate < 4) p->con_rotate = rotate; else p->con_rotate = 0; fbcon_modechanged(info); }} static void fbcon_rotate_all(struct fb_info *info, u32 rotate){ struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; struct fbcon_display *p; int i; if (!par || par->currcon < 0 || rotate > 3) return; for (i = first_fb_vc; i <= last_fb_vc; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || fbcon_info_from_console(i) != info) continue; p = &fb_display[vc->vc_num]; p->con_rotate = rotate; } fbcon_set_all_vcs(info);}#elsestatic inline void fbcon_set_rotation(struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; par->rotate = FB_ROTATE_UR;} static void fbcon_rotate(struct fb_info *info, u32 rotate){ return;} static void fbcon_rotate_all(struct fb_info *info, u32 rotate){ return;}#endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ static void fbcon_set_bitops(struct fbcon_par *par){ switch (par->rotate) { default: fallthrough; case FB_ROTATE_UR: fbcon_set_bitops_ur(par); break; case FB_ROTATE_CW: fbcon_set_bitops_cw(par); break; case FB_ROTATE_UD: fbcon_set_bitops_ud(par); break; case FB_ROTATE_CCW: fbcon_set_bitops_ccw(par); break; }} static int fbcon_get_rotate(struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; return (par) ? par->rotate : 0;} static bool fbcon_skip_panic(struct fb_info *info){ return (info->skip_panic && unlikely(panic_in_progress()));} static inline bool fbcon_is_active(struct vc_data *vc, struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; return info->state == FBINFO_STATE_RUNNING && vc->vc_mode == KD_TEXT && !par->graphics && !fbcon_skip_panic(info);} static int get_color(struct vc_data *vc, struct fb_info *info, u16 c, bool is_fg){ int depth = fb_get_color_depth(&info->var, &info->fix); int color = 0; if (console_blanked) { unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; c = vc->vc_video_erase_char & charmask; } if (depth != 1) color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c) : attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c); switch (depth) { case 1: { int col = mono_col(info); /* 0 or 1 */ int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; if (console_blanked) fg = bg; color = (is_fg) ? fg : bg; break; } case 2: /* * Scale down 16-colors to 4 colors. Default 4-color palette * is grayscale. However, simply dividing the values by 4 * will not work, as colors 1, 2 and 3 will be scaled-down * to zero rendering them invisible. So empirically convert * colors to a sane 4-level grayscale. */ switch (color) { case 0: color = 0; /* black */ break; case 1 ... 6: color = 2; /* white */ break; case 7 ... 8: color = 1; /* gray */ break; default: color = 3; /* intense white */ break; } break; case 3: /* * Last 8 entries of default 16-color palette is a more intense * version of the first 8 (i.e., same chrominance, different * luminance). */ color &= 7; break; } return color;} static int get_fg_color(struct vc_data *vc, struct fb_info *info, u16 c){ return get_color(vc, info, c, true);} static int get_bg_color(struct vc_data *vc, struct fb_info *info, u16 c){ return get_color(vc, info, c, false);} static void fb_flashcursor(struct work_struct *work){ struct fbcon_par *par = container_of(work, struct fbcon_par, cursor_work.work); struct fb_info *info; struct vc_data *vc = NULL; int c; bool enable; int ret; /* FIXME: we should sort out the unbind locking instead */ /* instead we just fail to flash the cursor if we can't get * the lock instead of blocking fbcon deinit */ ret = console_trylock(); if (ret == 0) return; /* protected by console_lock */ info = par->info; if (par->currcon != -1) vc = vc_cons[par->currcon].d; if (!vc || !con_is_visible(vc) || fbcon_info_from_console(vc->vc_num) != info || vc->vc_deccm != 1) { console_unlock(); return; } c = scr_readw((u16 *) vc->vc_pos); enable = par->cursor_flash && !par->cursor_state.enable; par->bitops->cursor(vc, info, enable, get_fg_color(vc, info, c), get_bg_color(vc, info, c)); console_unlock(); queue_delayed_work(system_power_efficient_wq, &par->cursor_work, par->cur_blink_jiffies);} static void fbcon_add_cursor_work(struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; if (fbcon_cursor_blink) queue_delayed_work(system_power_efficient_wq, &par->cursor_work, par->cur_blink_jiffies);} static void fbcon_del_cursor_work(struct fb_info *info){ struct fbcon_par *par = info->fbcon_par; cancel_delayed_work_sync(&par->cursor_work);} void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask){ static const unsigned int pattern = 0xffffffff; unsigned int pitch = vc_font_pitch(&vc->vc_font); unsigned int cur_height, size; switch (CUR_SIZE(vc->vc_cursor_type)) { case CUR_NONE: cur_height = 0; break; case CUR_UNDERLINE: if (vc->vc_font.height < 10) cur_height = 1; else cur_height = 2; break; case CUR_LOWER_THIRD: cur_height = vc->vc_font.height / 3; break; case CUR_LOWER_HALF: cur_height = vc->vc_font.height / 2; break; case CUR_TWO_THIRDS: cur_height = (vc->vc_font.height * 2) / 3; break; case CUR_BLOCK: default: cur_height = vc->vc_font.height; break; } size = (vc->vc_font.height - cur_height) * pitch; while (size--) *mask++ = (unsigned char)~pattern; size = cur_height * pitch; while (size--) *mask++ = (unsigned char)pattern;} #ifndef MODULEstatic int __init fb_console_setup(char *this_opt){ char *options; int i, j; if (!this_opt || !*this_opt) return 1; while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) { strscpy(fontname, options + 5, sizeof(fontname)); continue;Lines 1–500 of 3409. Load more
/* * linux/drivers/video/fbcon.c -- Low level frame buffer based console driver * * Copyright (C) 1995 Geert Uytterhoeven * * * This file is based on the original Amiga console driver (amicon.c): * * Copyright (C) 1993 Hamish Macdonald * Greg Harp * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] * * with work by William Rucklidge (wjr@cs.cornell.edu) * Geert Uytterhoeven * Jes Sorensen (jds@kom.auc.dk) * Martin Apel * * and on the original Atari console driver (atacon.c): * * Copyright (C) 1993 Bjoern Brauel * Roman Hodek * * with work by Guenther Kelleter * Martin Schaller * Andreas Schwab * * Hardware cursor support added by Emmanuel Marty (core@ggi-project.org) * Smart redraw scrolling, arbitrary font width support, 512char font support * and software scrollback added by * Jakub Jelinek (jj@ultra.linux.cz) * * Random hacking by Martin Mares <mj@ucw.cz> * * 2001 - Documented with DocBook * - Brad Douglas <brad@neruo.com> * * The low level operations for the various display memory organizations are * now in separate source files. * * Currently the following organizations are supported: * * o afb Amiga bitplanes * o cfb{2,4,8,16,24,32} Packed pixels * o ilbm Amiga interleaved bitplanes * o iplan2p[248] Atari interleaved bitplanes * o mfb Monochrome * o vga VGA characters/attributes * * To do: * * - Implement 16 plane mode (iplan2p16) * * * This file is subject to the terms and conditions of the GNU General Public * License. See the file COPYING in the main directory of this archive for * more details. */ #include <linux/export.h> #include <linux/module.h> #include <linux/types.h> #include <linux/fs.h> #include <linux/kernel.h> #include <linux/delay.h> /* MSch: for IRQ probe */ #include <linux/console.h> #include <linux/string.h> #include <linux/kd.h> #include <linux/panic.h> #include <linux/pci.h> #include <linux/printk.h> #include <linux/slab.h> #include <linux/fb.h> #include <linux/vt_kern.h> #include <linux/selection.h> #include <linux/font.h> #include <linux/smp.h> #include <linux/init.h> #include <linux/interrupt.h> #include <linux/crc32.h> /* For counting font checksums */ #include <linux/uaccess.h> #include <linux/vga_switcheroo.h> #include <asm/irq.h> #include "fbcon.h" #include "fbcon_rotate.h" #include "fb_internal.h" /* * FIXME: Locking * * - fbcon state itself is protected by the console_lock, and the code does a * pretty good job at making sure that lock is held everywhere it's needed. * * - fbcon doesn't bother with fb_lock/unlock at all. This is buggy, since it * means concurrent access to the same fbdev from both fbcon and userspace * will blow up. To fix this all fbcon calls from fbmem.c need to be moved out * of fb_lock/unlock protected sections, since otherwise we'll recurse and * deadlock eventually. Aside: Due to these deadlock issues the fbdev code in * fbmem.c cannot use locking asserts, and there's lots of callers which get * the rules wrong, e.g. fbsysfs.c entirely missed fb_lock/unlock calls too. */ enum { FBCON_LOGO_CANSHOW = -1, /* the logo can be shown */ FBCON_LOGO_DRAW = -2, /* draw the logo to a console */ FBCON_LOGO_DONTSHOW = -3 /* do not show the logo */ }; static struct fbcon_display fb_display[MAX_NR_CONSOLES]; static struct fb_info *fbcon_registered_fb[FB_MAX]; static int fbcon_num_registered_fb; #define fbcon_for_each_registered_fb(i) \ for (i = 0; WARN_CONSOLE_UNLOCKED(), i < FB_MAX; i++) \ if (!fbcon_registered_fb[i]) {} else static signed char con2fb_map[MAX_NR_CONSOLES]; static signed char con2fb_map_boot[MAX_NR_CONSOLES]; static struct fb_info *fbcon_info_from_console(int console) { signed char fb; WARN_CONSOLE_UNLOCKED(); fb = con2fb_map[console]; if (fb < 0 || fb >= ARRAY_SIZE(fbcon_registered_fb)) return NULL; return fbcon_registered_fb[fb]; } static int logo_lines; /* logo_shown is an index to vc_cons when >= 0; otherwise follows FBCON_LOGO enums. */ static int logo_shown = FBCON_LOGO_CANSHOW; /* console mappings */ static unsigned int first_fb_vc; static unsigned int last_fb_vc = MAX_NR_CONSOLES - 1; static bool fbcon_is_default = true; static int primary_device = -1; static bool fbcon_has_console_bind; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY static int map_override; static inline void fbcon_map_override(void) { map_override = 1; } #else static inline void fbcon_map_override(void) { } #endif /* CONFIG_FRAMEBUFFER_CONSOLE_DETECT_PRIMARY */ #ifdef CONFIG_FRAMEBUFFER_CONSOLE_DEFERRED_TAKEOVER static bool deferred_takeover = true; #else #define deferred_takeover false #endif /* font data */ static char fontname[40]; /* current fb_info */ static int info_idx = -1; /* console rotation */ static int initial_rotation = -1; static int margin_color; static const struct consw fb_con; #define advance_row(p, delta) (unsigned short *)((unsigned long)(p) + (delta) * vc->vc_size_row) static bool fbcon_cursor_blink = true; #define divides(a, b) ((!(a) || (b)%(a)) ? 0 : 1) /* * Interface used by the world */ static void fbcon_clear_margins(struct vc_data *vc, int bottom_only); static void fbcon_set_palette(struct vc_data *vc, const unsigned char *table); /* * Internal routines */ static void fbcon_set_disp(struct fb_info *info, struct fb_var_screeninfo *var, int unit); static void fbcon_redraw_move(struct vc_data *vc, struct fbcon_display *p, int line, int count, int dy); static void fbcon_modechanged(struct fb_info *info); static void fbcon_set_all_vcs(struct fb_info *info); static struct device *fbcon_device; #ifdef CONFIG_FRAMEBUFFER_CONSOLE_ROTATION static inline void fbcon_set_rotation(struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; if (!(info->flags & FBINFO_MISC_TILEBLITTING) && par->p->con_rotate < 4) par->rotate = par->p->con_rotate; else par->rotate = 0; } static void fbcon_rotate(struct fb_info *info, u32 rotate) { struct fbcon_par *par = info->fbcon_par; struct fb_info *fb_info; if (!par || par->currcon == -1) return; fb_info = fbcon_info_from_console(par->currcon); if (info == fb_info) { struct fbcon_display *p = &fb_display[par->currcon]; if (rotate < 4) p->con_rotate = rotate; else p->con_rotate = 0; fbcon_modechanged(info); } } static void fbcon_rotate_all(struct fb_info *info, u32 rotate) { struct fbcon_par *par = info->fbcon_par; struct vc_data *vc; struct fbcon_display *p; int i; if (!par || par->currcon < 0 || rotate > 3) return; for (i = first_fb_vc; i <= last_fb_vc; i++) { vc = vc_cons[i].d; if (!vc || vc->vc_mode != KD_TEXT || fbcon_info_from_console(i) != info) continue; p = &fb_display[vc->vc_num]; p->con_rotate = rotate; } fbcon_set_all_vcs(info); } #else static inline void fbcon_set_rotation(struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; par->rotate = FB_ROTATE_UR; } static void fbcon_rotate(struct fb_info *info, u32 rotate) { return; } static void fbcon_rotate_all(struct fb_info *info, u32 rotate) { return; } #endif /* CONFIG_FRAMEBUFFER_CONSOLE_ROTATION */ static void fbcon_set_bitops(struct fbcon_par *par) { switch (par->rotate) { default: fallthrough; case FB_ROTATE_UR: fbcon_set_bitops_ur(par); break; case FB_ROTATE_CW: fbcon_set_bitops_cw(par); break; case FB_ROTATE_UD: fbcon_set_bitops_ud(par); break; case FB_ROTATE_CCW: fbcon_set_bitops_ccw(par); break; } } static int fbcon_get_rotate(struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; return (par) ? par->rotate : 0; } static bool fbcon_skip_panic(struct fb_info *info) { return (info->skip_panic && unlikely(panic_in_progress())); } static inline bool fbcon_is_active(struct vc_data *vc, struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; return info->state == FBINFO_STATE_RUNNING && vc->vc_mode == KD_TEXT && !par->graphics && !fbcon_skip_panic(info); } static int get_color(struct vc_data *vc, struct fb_info *info, u16 c, bool is_fg) { int depth = fb_get_color_depth(&info->var, &info->fix); int color = 0; if (console_blanked) { unsigned short charmask = vc->vc_hi_font_mask ? 0x1ff : 0xff; c = vc->vc_video_erase_char & charmask; } if (depth != 1) color = (is_fg) ? attr_fgcol((vc->vc_hi_font_mask) ? 9 : 8, c) : attr_bgcol((vc->vc_hi_font_mask) ? 13 : 12, c); switch (depth) { case 1: { int col = mono_col(info); /* 0 or 1 */ int fg = (info->fix.visual != FB_VISUAL_MONO01) ? col : 0; int bg = (info->fix.visual != FB_VISUAL_MONO01) ? 0 : col; if (console_blanked) fg = bg; color = (is_fg) ? fg : bg; break; } case 2: /* * Scale down 16-colors to 4 colors. Default 4-color palette * is grayscale. However, simply dividing the values by 4 * will not work, as colors 1, 2 and 3 will be scaled-down * to zero rendering them invisible. So empirically convert * colors to a sane 4-level grayscale. */ switch (color) { case 0: color = 0; /* black */ break; case 1 ... 6: color = 2; /* white */ break; case 7 ... 8: color = 1; /* gray */ break; default: color = 3; /* intense white */ break; } break; case 3: /* * Last 8 entries of default 16-color palette is a more intense * version of the first 8 (i.e., same chrominance, different * luminance). */ color &= 7; break; } return color; } static int get_fg_color(struct vc_data *vc, struct fb_info *info, u16 c) { return get_color(vc, info, c, true); } static int get_bg_color(struct vc_data *vc, struct fb_info *info, u16 c) { return get_color(vc, info, c, false); } static void fb_flashcursor(struct work_struct *work) { struct fbcon_par *par = container_of(work, struct fbcon_par, cursor_work.work); struct fb_info *info; struct vc_data *vc = NULL; int c; bool enable; int ret; /* FIXME: we should sort out the unbind locking instead */ /* instead we just fail to flash the cursor if we can't get * the lock instead of blocking fbcon deinit */ ret = console_trylock(); if (ret == 0) return; /* protected by console_lock */ info = par->info; if (par->currcon != -1) vc = vc_cons[par->currcon].d; if (!vc || !con_is_visible(vc) || fbcon_info_from_console(vc->vc_num) != info || vc->vc_deccm != 1) { console_unlock(); return; } c = scr_readw((u16 *) vc->vc_pos); enable = par->cursor_flash && !par->cursor_state.enable; par->bitops->cursor(vc, info, enable, get_fg_color(vc, info, c), get_bg_color(vc, info, c)); console_unlock(); queue_delayed_work(system_power_efficient_wq, &par->cursor_work, par->cur_blink_jiffies); } static void fbcon_add_cursor_work(struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; if (fbcon_cursor_blink) queue_delayed_work(system_power_efficient_wq, &par->cursor_work, par->cur_blink_jiffies); } static void fbcon_del_cursor_work(struct fb_info *info) { struct fbcon_par *par = info->fbcon_par; cancel_delayed_work_sync(&par->cursor_work); } void fbcon_fill_cursor_mask(struct fbcon_par *par, struct vc_data *vc, unsigned char *mask) { static const unsigned int pattern = 0xffffffff; unsigned int pitch = vc_font_pitch(&vc->vc_font); unsigned int cur_height, size; switch (CUR_SIZE(vc->vc_cursor_type)) { case CUR_NONE: cur_height = 0; break; case CUR_UNDERLINE: if (vc->vc_font.height < 10) cur_height = 1; else cur_height = 2; break; case CUR_LOWER_THIRD: cur_height = vc->vc_font.height / 3; break; case CUR_LOWER_HALF: cur_height = vc->vc_font.height / 2; break; case CUR_TWO_THIRDS: cur_height = (vc->vc_font.height * 2) / 3; break; case CUR_BLOCK: default: cur_height = vc->vc_font.height; break; } size = (vc->vc_font.height - cur_height) * pitch; while (size--) *mask++ = (unsigned char)~pattern; size = cur_height * pitch; while (size--) *mask++ = (unsigned char)pattern; } #ifndef MODULE static int __init fb_console_setup(char *this_opt) { char *options; int i, j; if (!this_opt || !*this_opt) return 1; while ((options = strsep(&this_opt, ",")) != NULL) { if (!strncmp(options, "font:", 5)) { strscpy(fontname, options + 5, sizeof(fontname)); continue;