📄 sun3fb.c
字号:
/* * linux/drivers/video/sun3fb.c -- Frame buffer driver for Sun3 * * (C) 1998 Thomas Bogendoerfer * * This driver is bases on sbusfb.c, which is * * Copyright (C) 1998 Jakub Jelinek * * This driver is partly based on the Open Firmware console driver * * Copyright (C) 1997 Geert Uytterhoeven * * and SPARC console subsystem * * Copyright (C) 1995 Peter Zaitcev (zaitcev@yahoo.com) * Copyright (C) 1995-1997 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995-1996 Miguel de Icaza (miguel@nuclecu.unam.mx) * Copyright (C) 1996 Dave Redman (djhr@tadpole.co.uk) * Copyright (C) 1996-1998 Jakub Jelinek (jj@sunsite.mff.cuni.cz) * Copyright (C) 1996 Eddie C. Dost (ecd@skynet.be) * * 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/config.h>#include <linux/module.h>#include <linux/kernel.h>#include <linux/errno.h>#include <linux/string.h>#include <linux/mm.h>#include <linux/tty.h>#include <linux/slab.h>#include <linux/vmalloc.h>#include <linux/delay.h>#include <linux/interrupt.h>#include <linux/fb.h>#include <linux/selection.h>#include <linux/init.h>#include <linux/console.h>#include <linux/kd.h>#include <linux/vt_kern.h>#include <asm/uaccess.h>#include <asm/pgtable.h> /* io_remap_page_range() */#ifdef CONFIG_SUN3#include <asm/oplib.h>#endif#ifdef CONFIG_SUN3X#include <asm/sun3x.h>#endif#include <video/sbusfb.h>#define DEFAULT_CURSOR_BLINK_RATE (2*HZ/5)#define CURSOR_SHAPE 1#define CURSOR_BLINK 2 /* * Interface used by the world */int sun3fb_init(void);int sun3fb_setup(char *options);static int currcon;static char fontname[40] __initdata = { 0 };static int curblink __initdata = 1;static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info);static int sun3fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sun3fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info);static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info);static void sun3fb_cursor(struct display *p, int mode, int x, int y);static void sun3fb_clear_margin(struct display *p, int s); /* * Interface to the low level console driver */static int sun3fbcon_switch(int con, struct fb_info *info);static int sun3fbcon_updatevar(int con, struct fb_info *info);static void sun3fbcon_blank(int blank, struct fb_info *info); /* * Internal routines */static int sun3fb_getcolreg(u_int regno, u_int *red, u_int *green, u_int *blue, u_int *transp, struct fb_info *info);static int sun3fb_setcolreg(u_int regno, u_int red, u_int green, u_int blue, u_int transp, struct fb_info *info);static void do_install_cmap(int con, struct fb_info *info);static struct fb_ops sun3fb_ops = { owner: THIS_MODULE, fb_get_fix: sun3fb_get_fix, fb_get_var: sun3fb_get_var, fb_set_var: sun3fb_set_var, fb_get_cmap: sun3fb_get_cmap, fb_set_cmap: sun3fb_set_cmap,};static void sun3fb_clear_margin(struct display *p, int s){ struct fb_info_sbusfb *fb = sbusfbinfod(p); if (fb->switch_from_graph) (*fb->switch_from_graph)(fb); if (fb->fill) { unsigned short rects [16]; rects [0] = 0; rects [1] = 0; rects [2] = fb->var.xres_virtual; rects [3] = fb->y_margin; rects [4] = 0; rects [5] = fb->y_margin; rects [6] = fb->x_margin; rects [7] = fb->var.yres_virtual; rects [8] = fb->var.xres_virtual - fb->x_margin; rects [9] = fb->y_margin; rects [10] = fb->var.xres_virtual; rects [11] = fb->var.yres_virtual; rects [12] = fb->x_margin; rects [13] = fb->var.yres_virtual - fb->y_margin; rects [14] = fb->var.xres_virtual - fb->x_margin; rects [15] = fb->var.yres_virtual; (*fb->fill)(fb, p, s, 4, rects); } else { unsigned char *fb_base = p->screen_base, *q; int skip_bytes = fb->y_margin * fb->var.xres_virtual; int scr_size = fb->var.xres_virtual * fb->var.yres_virtual; int h, he, incr, size; he = fb->var.yres; if (fb->var.bits_per_pixel == 1) { fb_base -= (skip_bytes + fb->x_margin) / 8; skip_bytes /= 8; scr_size /= 8; mymemset (fb_base, skip_bytes - fb->x_margin / 8); mymemset (fb_base + scr_size - skip_bytes + fb->x_margin / 8, skip_bytes - fb->x_margin / 8); incr = fb->var.xres_virtual / 8; size = fb->x_margin / 8 * 2; for (q = fb_base + skip_bytes - fb->x_margin / 8, h = 0; h <= he; q += incr, h++) mymemset (q, size); } else { fb_base -= (skip_bytes + fb->x_margin); memset (fb_base, attr_bgcol(p,s), skip_bytes - fb->x_margin); memset (fb_base + scr_size - skip_bytes + fb->x_margin, attr_bgcol(p,s), skip_bytes - fb->x_margin); incr = fb->var.xres_virtual; size = fb->x_margin * 2; for (q = fb_base + skip_bytes - fb->x_margin, h = 0; h <= he; q += incr, h++) memset (q, attr_bgcol(p,s), size); } }}static void sun3fb_disp_setup(struct display *p){ struct fb_info_sbusfb *fb = sbusfbinfod(p); if (fb->setup) fb->setup(p); sun3fb_clear_margin(p, 0);} /* * Get the Fixed Part of the Display */static int sun3fb_get_fix(struct fb_fix_screeninfo *fix, int con, struct fb_info *info){ struct fb_info_sbusfb *fb = sbusfbinfo(info); memcpy(fix, &fb->fix, sizeof(struct fb_fix_screeninfo)); return 0;} /* * Get the User Defined Part of the Display */static int sun3fb_get_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct fb_info_sbusfb *fb = sbusfbinfo(info); memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo)); return 0;} /* * Set the User Defined Part of the Display */static int sun3fb_set_var(struct fb_var_screeninfo *var, int con, struct fb_info *info){ struct fb_info_sbusfb *fb = sbusfbinfo(info); if (var->xres > fb->var.xres || var->yres > fb->var.yres || var->xres_virtual > fb->var.xres_virtual || var->yres_virtual > fb->var.yres_virtual || var->bits_per_pixel != fb->var.bits_per_pixel || var->nonstd || (var->vmode & FB_VMODE_MASK) != FB_VMODE_NONINTERLACED) return -EINVAL; memcpy(var, &fb->var, sizeof(struct fb_var_screeninfo)); return 0;} /* * Hardware cursor */ static unsigned char hw_cursor_cmap[2] = { 0, 0xff };static voidsun3fb_cursor_timer_handler(unsigned long dev_addr){ struct fb_info_sbusfb *fb = (struct fb_info_sbusfb *)dev_addr; if (!fb->setcursor) return; if (fb->cursor.mode & CURSOR_BLINK) { fb->cursor.enable ^= 1; fb->setcursor(fb); } fb->cursor.timer.expires = jiffies + fb->cursor.blink_rate; add_timer(&fb->cursor.timer);}static void sun3fb_cursor(struct display *p, int mode, int x, int y){ struct fb_info_sbusfb *fb = sbusfbinfod(p); switch (mode) { case CM_ERASE: fb->cursor.mode &= ~CURSOR_BLINK; fb->cursor.enable = 0; (*fb->setcursor)(fb); break; case CM_MOVE: case CM_DRAW: if (fb->cursor.mode & CURSOR_SHAPE) { fb->cursor.size.fbx = fontwidth(p); fb->cursor.size.fby = fontheight(p); fb->cursor.chot.fbx = 0; fb->cursor.chot.fby = 0; fb->cursor.enable = 1; memset (fb->cursor.bits, 0, sizeof (fb->cursor.bits)); fb->cursor.bits[0][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[1][fontheight(p) - 2] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[0][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p))); fb->cursor.bits[1][fontheight(p) - 1] = (0xffffffff << (32 - fontwidth(p))); (*fb->setcursormap) (fb, hw_cursor_cmap, hw_cursor_cmap, hw_cursor_cmap); (*fb->setcurshape) (fb); } fb->cursor.mode = CURSOR_BLINK; if (fontwidthlog(p)) fb->cursor.cpos.fbx = (x << fontwidthlog(p)) + fb->x_margin; else fb->cursor.cpos.fbx = (x * fontwidth(p)) + fb->x_margin; if (fontheightlog(p)) fb->cursor.cpos.fby = (y << fontheightlog(p)) + fb->y_margin; else fb->cursor.cpos.fby = (y * fontheight(p)) + fb->y_margin; (*fb->setcursor)(fb); break; }} /* * Get the Colormap */static int sun3fb_get_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ if (con == currcon) /* current console? */ return fb_get_cmap(cmap, kspc, sun3fb_getcolreg, info); else if (fb_display[con].cmap.len) /* non default colormap? */ fb_copy_cmap(&fb_display[con].cmap, cmap, kspc ? 0 : 2); else fb_copy_cmap(fb_default_cmap(1<<fb_display[con].var.bits_per_pixel), cmap, kspc ? 0 : 2); return 0;} /* * Set the Colormap */static int sun3fb_set_cmap(struct fb_cmap *cmap, int kspc, int con, struct fb_info *info){ int err; if (!fb_display[con].cmap.len) { /* no colormap allocated? */ if ((err = fb_alloc_cmap(&fb_display[con].cmap, 1<<fb_display[con].var.bits_per_pixel, 0))) return err; } if (con == currcon) { /* current console? */ err = fb_set_cmap(cmap, kspc, sun3fb_setcolreg, info); if (!err) { struct fb_info_sbusfb *fb = sbusfbinfo(info); if (fb->loadcmap) (*fb->loadcmap)(fb, &fb_display[con], cmap->start, cmap->len); } return err; } else fb_copy_cmap(cmap, &fb_display[con].cmap, kspc ? 0 : 1); return 0;} /* * Setup: parse used options */void __init sun3fb_setup(char *options){ char *p; for (p = options;;) { if (!strncmp(p, "font=", 5)) { int i; for (i = 0; i < sizeof(fontname) - 1; i++) if (p[i+5] == ' ' || !p[i+5]) break;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -