📄 suncons.c
字号:
/* suncons.c: Sun SparcStation console support. * * Copyright (C) 1995 Peter Zaitcev (zaitcev@lab.ipmce.su) * Copyright (C) 1995 David S. Miller (davem@caip.rutgers.edu) * Copyright (C) 1995 Miguel de Icaza (miguel@nuclecu.unam.mx) * * Added font loading Nov/21, Miguel de Icaza (miguel@nuclecu.unam.mx) * Added render_screen and faster scrolling Nov/27, miguel * Added console palette code for cg6 Dec/13/95, miguel * Added generic frame buffer support Dec/14/95, miguel * Added cgsix and bwtwo drivers Jan/96, miguel * Added 4m, and cg3 driver Feb/96, miguel * Fixed the cursor on color displays Feb/96, miguel. * * Cleaned up the detection code, generic 8bit depth display * code, Mar/96 miguel * * This file contains the frame buffer device drivers. * Each driver is kept together in case we would like to * split this file. * * Much of this driver is derived from the DEC TGA driver by * Jay Estabrook who has done a nice job with the console * driver abstraction btw. * * We try to make everything a power of two if possible to * speed up the bit blit. Doing multiplies, divides, and * remainder routines end up calling software library routines * since not all Sparcs have the hardware to do it. * * TODO: * do not use minor to index into instances of the frame buffer, * since the numbers assigned to us are not consecutive. * * do not blank the screen when frame buffer is mapped. * * Change the detection loop to use more than one video card. *//* Define this one if you are debugging something in X, it will not disable the console output *//* #define DEBUGGING_X *//* See also: sparc/keyboard.c: CODING_NEW_DRIVER */#define GRAPHDEV_MAJOR 29#define FRAME_BUFFERS 1#include <linux/sched.h>#include <linux/timer.h>#include <linux/interrupt.h>#include <linux/tty.h>#include <linux/tty_flip.h>#include <linux/kernel.h>#include <linux/string.h>#include <linux/errno.h>#include <linux/kd.h>#include <linux/malloc.h>#include <linux/major.h>#include <linux/mm.h>#include <linux/types.h>#include <asm/system.h>#include <asm/segment.h>#include <asm/page.h>#include <asm/pgtable.h>#include <asm/bitops.h>#include <asm/oplib.h>#include <asm/sbus.h>#include <asm/fbio.h>#include <asm/io.h>#include <asm/pgtsun4c.h> /* for the sun4c_nocache */#include "../../char/kbd_kern.h"#include "../../char/vt_kern.h"#include "../../char/consolemap.h"#include "../../char/selection.h"#include "../../char/console_struct.h"#define cmapsz 8192extern void register_console(void (*proc)(const char *));extern void console_print(const char *);extern unsigned char vga_font[];extern int graphics_on;extern int serial_console;/* Based upon what the PROM tells us, we can figure out where * the console is currently located. The situation can be either * of the following two scenarios: * * 1) Console i/o is done over the serial line, ttya or ttyb * 2) Console output on frame buffer (video card) and input * coming from the keyboard/mouse which each use a zilog8530 * serial channel a piece. *//* The following variables describe a Sparc console. *//* From the PROM */static char con_name[40];/* Screen dimensions and color depth. */static int con_depth, con_width, con_height, con_type;static int con_linebytes;/* Base address of first line. */static unsigned char *con_fb_base;/* Screen parameters: we compute those at startup to make the code faster */static int chars_per_line; /* number of bytes per line */static int ints_per_line; /* number of ints per line */static int skip_bytes; /* number of bytes we skip for the y margin */static int x_margin, y_margin; /* the x and y margins */static int bytes_per_row; /* bytes used by one screen line (of 16 scan lines) *//* Functions used by the SPARC dependent console code * to perform the restore_palette function. */static void (*restore_palette)(void);void set_palette (void); /* Our screen looks like at 1152 X 900: * * 0,0 * ------------------------------------------------------------------ * | ^^^^^^^^^^^ | * | 18 y-pixels | * | ^^^^^^^^^^^ | * 13 | <-64 pixels->| <-- 128 8x16 characters --> | <-64 pixels-> | * .... * 54 chars from top to bottom * .... * 888 | <-64 pixels->| <-- 128 8x16 characters --> | <-64 pixels-> | * | ^^^^^^^^^^^ | * | 18 y-pixels | * | ^^^^^^^^^^^ | * ------------------------------------------------------------------ *//* First for MONO displays. */#define SCREEN_WIDTH 1152 /* Screen width in pixels */#define SCREEN_HEIGHT 900 /* Screen height in pixels */#define CHARS_PER_LINE 144 /* Make this empirical for speed */#define NICE_Y_MARGIN 18 /* We skip 18 y-pixels at top/bottom */#define NICE_X_MARGIN 8 /* We skip 64 x-pixels at left/right */#define FBUF_TOP_SKIP 2592 /* Empirical, (CHARS_PER_LINE * NICE_Y_MARGIN) */#define CHAR_HEIGHT 16#define ONE_ROW 2304 /* CHARS_PER_LINE * CHAR_HEIGHT *//* Now we have this, to compute the base frame buffer position * for a new character to be rendered. 1 and 8 bit depth. */#define FBUF_OFFSET(cindex) \ (((FBUF_TOP_SKIP) + (((cindex)>>7) * ONE_ROW)) + \ ((NICE_X_MARGIN) + (((cindex)&127))))#define COLOR_FBUF_OFFSET(cindex) \ (((skip_bytes) + (((cindex)>>7) * bytes_per_row)) + \ ((x_margin) + (((cindex)&127) << 3)))void__set_origin(unsigned short offset){ /* * should not be called, but if so, do nothing... */}/* For the cursor, we just invert the 8x16 block at the cursor * location. Easy enough... * * Hide the cursor from view, during blanking, usually... */static int cursor_pos = -1;voidhide_cursor(void){ unsigned long flags; int j; save_flags(flags); cli(); if(cursor_pos == -1) { restore_flags (flags); return; } /* We just zero out the area for now. Certain graphics * cards like the cg6 have a hardware cursor that we could * use, but this is an optimization for some time later. */ switch (con_depth){ case 1: { unsigned char *dst; dst = (unsigned char *)((unsigned long)con_fb_base + FBUF_OFFSET(cursor_pos)); for(j = 0; j < CHAR_HEIGHT; j++, dst += CHARS_PER_LINE) *dst = ~(0); break; } case 8: { unsigned long *dst; const int ipl = ints_per_line; dst = (unsigned long *)((unsigned long)con_fb_base + COLOR_FBUF_OFFSET(cursor_pos)); for(j = 0; j < CHAR_HEIGHT; j++, dst += ipl) { *dst = ~(0UL); *(dst + 1) = ~(0UL); } break; } default: break; } restore_flags(flags);}/* The idea is the following: * we only use the colors in the range 0..15, and we only * setup the palette on that range, so we better keep the * pixel inversion using those colors, that's why we have * those constants below. */inline static voidcursor_reverse (long *dst, int height, const int ints_on_line){ int j; for (j = 0; j < height; j++){ *dst = ~(*dst) & 0x0f0f0f0f; *(dst+1) = ~(*(dst+1)) & 0x0f0f0f0f; dst += ints_on_line; }}voidset_cursor(int currcons){ int j, idx, oldpos; unsigned long flags; if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS) return; if (__real_origin != __origin) __set_origin(__real_origin); save_flags(flags); cli(); idx = (pos - video_mem_base) >> 1; oldpos = cursor_pos; cursor_pos = idx; if (!deccm) { hide_cursor (); restore_flags (flags); return; } switch (con_depth){ case 1: { unsigned char *dst, *opos; dst = (unsigned char *)((unsigned long)con_fb_base + FBUF_OFFSET(idx)); opos = (unsigned char *)((unsigned long)con_fb_base + FBUF_OFFSET(oldpos)); if(oldpos != -1) { /* Restore what was at the old position */ for(j=0; j < CHAR_HEIGHT; j++, opos += CHARS_PER_LINE) { *opos = ~*opos; } } for(j=0; j < 16; j++, dst+=CHARS_PER_LINE) { *dst = ~*dst; } break; } case 8: { unsigned long *dst, *opos; dst = (unsigned long *)((unsigned long)con_fb_base + COLOR_FBUF_OFFSET(idx)); opos = (unsigned long *)((unsigned long)con_fb_base + COLOR_FBUF_OFFSET(oldpos)); if(oldpos != -1) cursor_reverse(opos, CHAR_HEIGHT, ints_per_line); cursor_reverse (dst, CHAR_HEIGHT, ints_per_line); break; } default: } restore_flags(flags);}/* * Render the current screen * Only used at startup to avoid the caching that is being done in selection.h */static voidrender_screen(void){ int count; unsigned short *contents; count = video_num_columns * video_num_lines; contents = (unsigned short *) video_mem_base; for (;count--; contents++) sun_blitc (*contents, (unsigned long) contents);}unsigned longcon_type_init(unsigned long kmem_start, const char **display_desc){ can_do_color = (con_type != FBTYPE_SUN2BW); video_type = VIDEO_TYPE_SUN; *display_desc = "SUN"; if (!serial_console) { /* If we fall back to PROM than our output have to remain readable. */ prom_putchar('\033'); prom_putchar('['); prom_putchar('H'); /* * fake the screen memory with some CPU memory */ video_mem_base = kmem_start; kmem_start += video_screen_size; video_mem_term = kmem_start; render_screen(); } return kmem_start;}/* * NOTE: get_scrmem() and set_scrmem() are here only because * the VGA version of set_scrmem() has some direct VGA references. */voidget_scrmem(int currcons){ memcpyw((unsigned short *)vc_scrbuf[currcons], (unsigned short *)origin, video_screen_size); origin = video_mem_start = (unsigned long)vc_scrbuf[currcons]; scr_end = video_mem_end = video_mem_start + video_screen_size; pos = origin + y*video_size_row + (x<<1);}voidset_scrmem(int currcons, long offset){ if (video_mem_term - video_mem_base < offset + video_screen_size) offset = 0; memcpyw((unsigned short *)(video_mem_base + offset), (unsigned short *) origin, video_screen_size); video_mem_start = video_mem_base; video_mem_end = video_mem_term; origin = video_mem_base + offset; scr_end = origin + video_screen_size; pos = origin + y*video_size_row + (x<<1);}/* * PIO_FONT support. */intset_get_font(char * arg, int set, int ch512){ int error, i, line; if (!arg) return -EINVAL; error = verify_area (set ? VERIFY_READ : VERIFY_WRITE, (void *) arg, ch512 ? 2* cmapsz : cmapsz); if (error) return error; /* download the current font */ if (!set){ memset (arg, 0, cmapsz); for (i = 0; i < 256; i++) for (line = 0; line < CHAR_HEIGHT; line++) put_user (vga_font [i], arg+(i*32+line));
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -