?? sticon-bmode.c
字號:
/*TPG CVS users: please don't commit changes to this file directly, sendthem to prumpf@tux.org and wait for a new version instead. Otherwise,your changes will get lost when prumpf releases the next version, asthis file *will* be replaced with it. You have been warned.2000-05-30, <deller@gmx.de>*/#if 1#define DPRINTK(x) printk x#else#define DPRINTK(x)#endif/* * linux/drivers/video/sticon.c - console driver using HP's STI firmware * * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> * * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, * which were * * Created 28 Sep 1997 by Geert Uytterhoeven * Rewritten by Martin Mares <mj@ucw.cz>, July 1998 * Copyright (C) 1991, 1992 Linus Torvalds * 1995 Jay Estabrook * Copyright (C) 1995 Geert Uytterhoeven * Copyright (C) 1993 Bjoern Brauel * Roman Hodek * 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 * with work by Guenther Kelleter * Martin Schaller * Andreas Schwab * Emmanuel Marty (core@ggi-project.org) * Jakub Jelinek (jj@ultra.linux.cz) * Martin Mares <mj@ucw.cz> * * 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. *//* * TODO: * - call STI in virtual mode rather than in real mode * - support for PCI-only STI ROMs (which don't have a traditional region * list) * - safe detection (i.e. verify there is a graphics device at a given * address first, not just read a random device's io space) * - support for multiple STI devices in one machine * - support for byte-mode STI ROMs * - support for just using STI to switch to a colour fb (stifb ?) * - try to make it work on m68k hp workstations ;) */#include <linux/types.h>#include <linux/sched.h>#include <linux/fs.h>#include <linux/kernel.h>#include <linux/tty.h>#include <linux/console.h>#include <linux/string.h>#include <linux/kd.h>#include <linux/slab.h>#include <linux/vt_kern.h>#include <linux/selection.h>#include <linux/ioport.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/io.h>#include <asm/real.h>#include <linux/module.h>#include <linux/fb.h>#include <linux/smp.h>#include <asm/irq.h>#include <asm/system.h>#include <asm/uaccess.h>#include <video/fbcon.h>#include <video/font.h>#include "sti-bmode.h"/* The latency of the STI functions cannot really be reduced by setting * this to 0; STI doesn't seem to be designed to allow calling a different * function (or the same function with different arguments) after a * function exited with 1 as return value. * * As all of the functions below could be called from interrupt context, * we have to spin_lock_irqsave around the do { ret = bla(); } while(ret==1) * block. Really bad latency there. * * Probably the best solution to all this is have the generic code manage * the screen buffer and a kernel thread to call STI occasionally. * * Luckily, the frame buffer guys have the same problem so we can just wait * for them to fix it and steal their solution. prumpf * * Actually, another long-term viable solution is to completely do STI * support in userspace - that way we avoid the potential license issues * of using proprietary fonts, too. */ #define STI_WAIT 1#define STI_PTR(p) ( (typeof(p)) virt_to_phys(p))#define PTR_STI(p) ( (typeof(p)) phys_to_virt((unsigned long)p) )static struct sti_struct default_sti = { SPIN_LOCK_UNLOCKED,};static struct sti_font_flags default_font_flags = { STI_WAIT, 0, 0, NULL};/* The colour indices used by STI are * 0 - Black * 1 - White * 2 - Red * 3 - Yellow/Brown * 4 - Green * 5 - Cyan * 6 - Blue * 7 - Magenta * * So we have the same colours as VGA (basically one bit each for R, G, B), * but have to translate them, anyway. */static u8 col_trans[8] = { 0, 6, 4, 5, 2, 7, 3, 1};#define c_fg(sti, c) col_trans[((c>> 8) & 7)]#define c_bg(sti, c) col_trans[((c>>11) & 7)]#define c_index(sti, c) (c&0xff)#define sti_onscreen_x(sti) (PTR_STI(sti->glob_cfg)->onscreen_x)#define sti_onscreen_y(sti) (PTR_STI(sti->glob_cfg)->onscreen_y)#define sti_font_x(sti) (STI_U8(PTR_STI(sti->font)->width))#define sti_font_y(sti) (STI_U8(PTR_STI(sti->font)->height))static struct sti_init_flags default_init_flags = { STI_WAIT, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, NULL};static void sti_init_graph(struct sti_struct *sti) { struct sti_init_inptr_ext inptr_ext = { 0, { 0 }, 0, NULL }; struct sti_init_inptr inptr = { 3, STI_PTR(&inptr_ext) }; struct sti_init_outptr outptr = { 0 }; unsigned long flags; s32 ret; spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->init_graph, &default_init_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); sti->text_planes = outptr.text_planes;}#if 0static struct sti_conf_flags default_conf_flags = { STI_WAIT, 0, NULL};static void sti_inq_conf(struct sti_struct *sti){ struct sti_conf_inptr inptr = { NULL }; struct sti_conf_outptr_ext outptr_ext = { future_ptr: NULL }; struct sti_conf_outptr outptr = { ext_ptr: STI_PTR(&outptr_ext) }; unsigned long flags; s32 ret; do { spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->inq_conf, &default_conf_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while(ret == 1);}#endifstatic void sti_putc(struct sti_struct *sti, int c, int y, int x){ struct sti_font_inptr inptr = { (u32) sti->font, c_index(sti, c), c_fg(sti, c), c_bg(sti, c), x * sti_font_x(sti), y * sti_font_y(sti), NULL }; struct sti_font_outptr outptr = { 0, NULL }; s32 ret; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->font_unpmv, &default_font_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while(ret == 1);}static struct sti_blkmv_flags clear_blkmv_flags = { STI_WAIT, 1, 1, 0, 0, NULL};static void sti_set(struct sti_struct *sti, int src_y, int src_x, int height, int width, u8 color){ struct sti_blkmv_inptr inptr = { color, color, src_x, src_y , src_x, src_y , width, height, NULL }; struct sti_blkmv_outptr outptr = { 0, NULL }; s32 ret = 0; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->block_move, &clear_blkmv_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while(ret == 1);}static void sti_clear(struct sti_struct *sti, int src_y, int src_x, int height, int width){ struct sti_blkmv_inptr inptr = { 0, 0, src_x * sti_font_x(sti), src_y * sti_font_y(sti), src_x * sti_font_x(sti), src_y * sti_font_y(sti), width * sti_font_x(sti), height* sti_font_y(sti), NULL }; struct sti_blkmv_outptr outptr = { 0, NULL }; s32 ret = 0; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->block_move, &clear_blkmv_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while(ret == 1);}static struct sti_blkmv_flags default_blkmv_flags = { STI_WAIT, 0, 0, 0, 0, NULL};static void sti_bmove(struct sti_struct *sti, int src_y, int src_x, int dst_y, int dst_x, int height, int width){ struct sti_blkmv_inptr inptr = { 0, 0, src_x * sti_font_x(sti), src_y * sti_font_y(sti), dst_x * sti_font_x(sti), dst_y * sti_font_y(sti), width * sti_font_x(sti), height* sti_font_y(sti), NULL }; struct sti_blkmv_outptr outptr = { 0, NULL }; s32 ret = 0; unsigned long flags; do { spin_lock_irqsave(&sti->lock, flags); ret = STI_CALL(sti->block_move, &default_blkmv_flags, &inptr, &outptr, sti->glob_cfg); spin_unlock_irqrestore(&sti->lock, flags); } while(ret == 1);}/* STICON */static const char __init *sticon_startup(void){ return "STI console";}static int sticon_set_palette(struct vc_data *c, unsigned char *table){ return -EINVAL;}static int sticon_font_op(struct vc_data *c, struct console_font_op *op){ return -ENOSYS;}static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos){ sti_putc(&default_sti, c, ypos, xpos);}static void sticon_putcs(struct vc_data *conp, const unsigned short *s, int count, int ypos, int xpos){ while(count--) { sti_putc(&default_sti, scr_readw(s++), ypos, xpos++); }}static void sticon_cursor(struct vc_data *conp, int mode){}static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count){ struct sti_struct *sti = &default_sti; if(console_blanked) return 0; sticon_cursor(conp, CM_ERASE); switch(dir) { case SM_UP: sti_bmove(sti, t+count, 0, t, 0, b-t-count, conp->vc_cols); sti_clear(sti, b-count, 0, count, conp->vc_cols); break; case SM_DOWN: sti_bmove(sti, t, 0, t+count, 0, b-t-count, conp->vc_cols); sti_clear(sti, t, 0, count, conp->vc_cols); break; } return 0;} static void sticon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx, int height, int width){ sti_bmove(&default_sti, sy, sx, dy, dx, height, width);}static void sticon_init(struct vc_data *c, int init){ struct sti_struct *sti = &default_sti; int vc_cols, vc_rows; sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0); c->vc_can_do_color = 1; vc_cols = PTR_STI(sti->glob_cfg)->onscreen_x / sti_font_x(sti); vc_rows = PTR_STI(sti->glob_cfg)->onscreen_y / sti_font_y(sti); vc_resize_con(vc_rows, vc_cols, c->vc_num);}static void sticon_deinit(struct vc_data *c){}static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, int width){ sti_clear(&default_sti, sy, sx, height, width);}static int sticon_switch(struct vc_data *conp){ return 0;}static int sticon_blank(struct vc_data *conp, int blank){ return 0;}static int sticon_scrolldelta(struct vc_data *conp, int lines){ return 0;}static int sticon_set_origin(struct vc_data *conp){ return 0;}static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, u8 blink, u8 underline, u8 reverse){ u8 attr = ((color & 0x70) >> 1) | ((color & 7)); if(reverse) { color = ((color>>3)&0x7) | ((color &0x7)<<3); } return attr;}static struct consw sti_con = { con_startup: sticon_startup, con_init: sticon_init, con_deinit: sticon_deinit, con_clear: sticon_clear, con_putc: sticon_putc, con_putcs: sticon_putcs, con_cursor: sticon_cursor, con_scroll: sticon_scroll, con_bmove: sticon_bmove, con_switch: sticon_switch, con_blank: sticon_blank, con_font_op: sticon_font_op, con_set_palette: sticon_set_palette, con_scrolldelta: sticon_scrolldelta, con_set_origin: sticon_set_origin, con_build_attr: sticon_build_attr,};#include <asm/pgalloc.h> /* need cache flush routines */static void __init sti_rom_copy(unsigned long base, unsigned long offset, unsigned long count, void *dest){ void *savedest = dest; int savecount = count; while(count >= 4) { count -= 4; *(u32 *)dest = gsc_readl(base + offset);#if 0 DPRINTK(("%08x\n", *(u32 *)dest)); if(*(u32 *)dest == 0x64646464) {
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -