patch-2.1.107 linux/drivers/char/console.c
Next file: linux/drivers/char/console_macros.h
Previous file: linux/drivers/char/Makefile
Back to the patch index
Back to the overall index
- Lines: 1849
- Date:
Wed Jun 24 15:07:54 1998
- Orig file:
v2.1.106/linux/drivers/char/console.c
- Orig date:
Tue Jun 23 10:01:22 1998
diff -u --recursive --new-file v2.1.106/linux/drivers/char/console.c linux/drivers/char/console.c
@@ -8,17 +8,18 @@
*
* This module exports the console io functions:
*
- * 'void do_keyboard_interrupt(void)'
- *
* 'int vc_allocate(unsigned int console)'
* 'int vc_cons_allocated(unsigned int console)'
* 'int vc_resize(unsigned long lines, unsigned long cols)'
+ * 'int vc_resize_con(unsigned long lines, unsigned long cols,
+ * unsigned int currcons)'
* 'void vc_disallocate(unsigned int currcons)'
*
* 'unsigned long con_init(unsigned long)'
* 'int con_open(struct tty_struct *tty, struct file * filp)'
* 'void con_write(struct tty_struct * tty)'
- * 'void vt_console_print(const char * b)'
+ * 'void vt_console_print(struct console *co, const char * b,
+ * unsigned count)'
* 'void update_screen(int new_console)'
*
* 'void do_blank_screen(int)'
@@ -61,8 +62,141 @@
* redirection by Martin Mares <mj@k332.feld.cvut.cz> 19-Nov-95
*
* APM screenblank bug fixed Takashi Manabe <manabe@roy.dsl.tutics.tut.jp>
+ *
+ * Merge with the abstract console driver by Geert Uytterhoeven
+ * <Geert.Uytterhoeven@cs.kuleuven.ac.be>, Jan 1997.
+ *
+ * Original m68k console driver modifications by
+ *
+ * - Arno Griffioen <arno@usn.nl>
+ * - David Carter <carter@cs.bris.ac.uk>
+ *
+ * Note that the abstract console driver allows all consoles to be of
+ * potentially different sizes, so the following variables depend on the
+ * current console (currcons):
+ *
+ * - video_num_columns
+ * - video_num_lines
+ * - video_size_row
+ * - video_screen_size
+ * - can_do_color
+ *
+ * The abstract console driver provides a generic interface for a text
+ * console. It supports VGA text mode, frame buffer based graphical consoles
+ * and special graphics processors that are only accessible through some
+ * registers (e.g. a TMS340x0 GSP).
+ *
+ * The interface to the hardware is specified using a special structure
+ * (struct consw) which contains function pointers to the following
+ * operations:
+ *
+ * unsigned long con_startup(unsigned long kmem_start,
+ * const char **display_desc)
+ * void con_init(struct vc_data *conp)
+ * int con_deinit(struct vc_data *conp)
+ * int con_clear(struct vc_data *conp, int sy, int sx, int height,
+ * int width)
+ * int con_putc(struct vc_data *conp, int c, int y, int x)
+ * int con_putcs(struct vc_data *conp, const char *s, int count, int y,
+ * int x)
+ * int con_cursor(struct vc_data *conp, int mode)
+ * int con_scroll(struct vc_data *conp, int t, int b, int dir, int count)
+ * int con_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
+ * int height, int width)
+ * int con_switch(struct vc_data *conp)
+ * int con_blank(int blank)
+ * int con_get_font(struct vc_data *conp, int *w, int *h, char *data)
+ * int con_set_font(struct vc_data *conp, int w, int h, char *data)
+ * int con_set_palette(struct vc_data *conp, unsigned char *table)
+ * int con_scrolldelta(struct vc_data *conp, int lines)
+ *
+ * Support for changeable cursor shape
+ * by Pavel Machek <pavel@atrey.karlin.mff.cuni.cz>, August 1997
+ *
+ * Ported to i386 and con_scrolldelta fixed
+ * by Emmanuel Marty <core@ggi-project.org>, April 1998
*/
+#include <linux/sched.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/console.h>
+#include <linux/init.h>
+#include <linux/vt_kern.h>
+#include <linux/selection.h>
+#include <linux/console_struct.h>
+#include <linux/kbd_kern.h>
+#include <linux/consolemap.h>
+#include <linux/timer.h>
+#include <linux/interrupt.h>
+#include <linux/config.h>
+#include <linux/version.h>
+#ifdef CONFIG_APM
+#include <linux/apm_bios.h>
+#endif
+
+#include <asm/io.h>
+#include <asm/system.h>
+#include <asm/uaccess.h>
+#include <asm/bitops.h>
+
+#ifndef CONFIG_ABSCON_COMPAT
+#define INCLUDE_LINUX_LOGO_DATA
+#endif
+#include <asm/linux_logo.h>
+
+#include "console_macros.h"
+
+
+struct consw *conswitchp = NULL;
+
+int (*console_show_logo)(void) __initdata = NULL;
+
+static int vesa_blank_mode = 0; /* 0:none 1:suspendV 2:suspendH 3:powerdown */
+
+static inline void hide_cursor(int currcons)
+{
+ sw->con_cursor(vc_cons[currcons].d,CM_ERASE);
+}
+
+void set_cursor(int currcons)
+{
+ if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
+ return;
+ if (deccm)
+ sw->con_cursor(vc_cons[currcons].d,CM_DRAW);
+ else
+ hide_cursor(currcons);
+}
+
+ /*
+ * Adjust the screen to fit a font of a certain height
+ *
+ * Returns < 0 for error, 0 if nothing changed, and the number
+ * of lines on the adjusted console if changed.
+ */
+
+int con_adjust_height(unsigned long fontheight)
+{
+ int currcons = fg_console;
+ /* ++Geert: Always assume that the number of lines did change? */
+ return video_num_lines;
+}
+
+/* dummy functions */
+
+void no_scroll(char *str, int *ints)
+{
+}
+
+
#define BLANK 0x0020
/* A bitmap for codes <32. A bit of 1 indicates that the code
@@ -86,45 +220,10 @@
* interrupt, as we use trap-gates. Hopefully all is well.
*/
-#include <linux/sched.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/tty.h>
-#include <linux/tty_flip.h>
-#include <linux/console.h>
-#include <linux/config.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/ioport.h>
-#include <linux/init.h>
-#ifdef CONFIG_APM
-#include <linux/apm_bios.h>
-#endif
-
-#include <asm/io.h>
-#include <asm/system.h>
-#include <asm/uaccess.h>
-#include <asm/bitops.h>
-
-#include <linux/kbd_kern.h>
-#include <linux/vt_kern.h>
-#include <linux/consolemap.h>
-#include <linux/selection.h>
-#include <linux/console_struct.h>
-
#ifndef MIN
#define MIN(a,b) ((a) < (b) ? (a) : (b))
#endif
-#ifdef __sparc__
-int serial_console;
-#endif
-
struct tty_driver console_driver;
static int console_refcount;
static struct tty_struct *console_table[MAX_NR_CONSOLES];
@@ -134,56 +233,30 @@
struct vc vc_cons [MAX_NR_CONSOLES];
static int con_open(struct tty_struct *, struct file *);
-static void con_setsize(unsigned long rows, unsigned long cols);
static void vc_init(unsigned int console, unsigned long rows,
unsigned long cols, int do_clear);
-extern void get_scrmem(int currcons);
-extern void set_scrmem(int currcons, long offset);
-static void set_origin(int currcons);
static void blank_screen(void);
static void unblank_screen(void);
extern void change_console(unsigned int);
extern void poke_blanked_console(void);
+static void update_attr(int currcons);
static void gotoxy(int currcons, int new_x, int new_y);
static void save_cur(int currcons);
-extern void set_cursor(int currcons);
-extern void hide_cursor(void);
static void reset_terminal(int currcons, int do_clear);
extern void reset_vc(unsigned int new_console);
extern void vt_init(void);
extern void set_vesa_blanking(unsigned long arg);
extern void vesa_blank(void);
-extern void vesa_unblank(void);
extern void vesa_powerdown(void);
extern void compute_shiftstate(void);
extern void reset_palette(int currcons);
extern void set_palette(void);
-extern int con_is_present(void);
-extern unsigned long con_type_init(unsigned long, const char **);
-extern void con_type_init_finish(void);
-extern int set_get_cmap(unsigned char *, int);
-extern int set_get_font(unsigned char *, int, int);
-extern void rs_cons_hook(int chip, int out, int channel);
-
-/* Description of the hardware situation */
-unsigned char video_type; /* Type of display being used */
-unsigned long video_mem_base; /* Base of video memory */
-unsigned long video_mem_term; /* End of video memory */
-unsigned short video_port_reg; /* Video register select port */
-unsigned short video_port_val; /* Video register value port */
-unsigned long video_num_columns; /* Number of text columns */
-unsigned long video_num_lines; /* Number of text lines */
-unsigned long video_size_row;
-unsigned long video_screen_size;
-int can_do_color = 0;
static int printable = 0; /* Is console ready for printing? */
int video_mode_512ch = 0; /* 512-character mode */
unsigned long video_font_height; /* Height of current screen font */
unsigned long video_scan_lines; /* Number of scan lines on screen */
-static unsigned long default_font_height; /* Height of default screen font */
-int video_font_is_default = 1;
static unsigned short console_charmask = 0x0ff;
/* used by kbd_bh - set by keyboard_interrupt */
@@ -191,7 +264,8 @@
int console_blanked = 0;
static int blankinterval = 10*60*HZ;
static int vesa_off_interval = 0;
-static long blank_origin, blank__origin, unblank_origin;
+
+static char putcs_buf[256];
/*
* fg_console is the current virtual console,
@@ -204,161 +278,58 @@
int want_console = -1;
int kmsg_redirect = 0;
-#ifdef CONFIG_SERIAL_ECHO
-
-#include <linux/serial_reg.h>
-
-extern int serial_echo_init (int base);
-extern int serial_echo_print (const char *s);
-
-/*
- * this defines the address for the port to which printk echoing is done
- * when CONFIG_SERIAL_ECHO is defined
- */
-#define SERIAL_ECHO_PORT 0x3f8 /* COM1 */
-
-static int serial_echo_port = 0;
-
-#define serial_echo_outb(v,a) outb((v),(a)+serial_echo_port)
-#define serial_echo_inb(a) inb((a)+serial_echo_port)
-
-#define BOTH_EMPTY (UART_LSR_TEMT | UART_LSR_THRE)
-
-/* Wait for transmitter & holding register to empty */
-#define WAIT_FOR_XMITR \
- do { \
- lsr = serial_echo_inb(UART_LSR); \
- } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY)
-
-/* These two functions abstract the actual communications with the
- * debug port. This is so we can change the underlying communications
- * mechanism without modifying the rest of the code.
- */
-int
-serial_echo_print(const char *s)
-{
- int lsr, ier;
- int i;
-
- if (!serial_echo_port) return (0);
-
- /*
- * First save the IER then disable the interrupts
- */
- ier = serial_echo_inb(UART_IER);
- serial_echo_outb(0x00, UART_IER);
-
- /*
- * Now, do each character
- */
- for (i = 0; *s; i++, s++) {
- WAIT_FOR_XMITR;
-
- /* Send the character out. */
- serial_echo_outb(*s, UART_TX);
-
- /* if a LF, also do CR... */
- if (*s == 10) {
- WAIT_FOR_XMITR;
- serial_echo_outb(13, UART_TX);
- }
- }
-
- /*
- * Finally, Wait for transmitter & holding register to empty
- * and restore the IER
- */
- do {
- lsr = serial_echo_inb(UART_LSR);
- } while ((lsr & BOTH_EMPTY) != BOTH_EMPTY);
- serial_echo_outb(ier, UART_IER);
-
- return (0);
-}
-
-
-int
-serial_echo_init(int base)
+int vc_cons_allocated(unsigned int i)
{
- int comstat, hi, lo;
-
- if (base != 0x2f8 && base != 0x3f8) {
- serial_echo_port = 0;
- return (0);
- } else
- serial_echo_port = base;
-
- /*
- * read the Divisor Latch
- */
- comstat = serial_echo_inb(UART_LCR);
- serial_echo_outb(comstat | UART_LCR_DLAB, UART_LCR);
- hi = serial_echo_inb(UART_DLM);
- lo = serial_echo_inb(UART_DLL);
- serial_echo_outb(comstat, UART_LCR);
-
- /*
- * now do hardwired init
- */
- serial_echo_outb(0x03, UART_LCR); /* No parity, 8 data bits, 1 stop */
- serial_echo_outb(0x83, UART_LCR); /* Access divisor latch */
- serial_echo_outb(0x00, UART_DLM); /* 9600 baud */
- serial_echo_outb(0x0c, UART_DLL);
- serial_echo_outb(0x03, UART_LCR); /* Done with divisor */
-
- /* Prior to disabling interrupts, read the LSR and RBR
- * registers
- */
- comstat = serial_echo_inb(UART_LSR); /* COM? LSR */
- comstat = serial_echo_inb(UART_RX); /* COM? RBR */
- serial_echo_outb(0x00, UART_IER); /* Disable all interrupts */
-
- return(0);
+ return (i < MAX_NR_CONSOLES && vc_cons[i].d);
}
-#endif /* CONFIG_SERIAL_ECHO */
-
-int vc_cons_allocated(unsigned int i)
+void visual_init(int currcons)
{
- return (i < MAX_NR_CONSOLES && vc_cons[i].d);
+ /* ++Geert: sw->con_init determines console size */
+ sw = conswitchp;
+ cons_num = currcons;
+ sw->con_init(vc_cons[currcons].d);
+ video_size_row = video_num_columns<<1;
+ video_screen_size = video_num_lines*video_size_row;
}
-int vc_allocate(unsigned int i) /* return 0 on success */
+int vc_allocate(unsigned int currcons) /* return 0 on success */
{
- if (i >= MAX_NR_CONSOLES)
+ if (currcons >= MAX_NR_CONSOLES)
return -ENXIO;
- if (!vc_cons[i].d) {
+ if (!vc_cons[currcons].d) {
long p, q;
/* prevent users from taking too much memory */
- if (i >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
+ if (currcons >= MAX_NR_USER_CONSOLES && !capable(CAP_SYS_RESOURCE))
return -EPERM;
/* due to the granularity of kmalloc, we waste some memory here */
/* the alloc is done in two steps, to optimize the common situation
of a 25x80 console (structsize=216, video_screen_size=4000) */
- q = (long) kmalloc(video_screen_size, GFP_KERNEL);
- if (!q)
- return -ENOMEM;
p = (long) kmalloc(structsize, GFP_KERNEL);
- if (!p) {
- kfree_s((char *) q, video_screen_size);
+ if (!p)
+ return -ENOMEM;
+ vc_cons[currcons].d = (struct vc_data *)p;
+ vt_cons[currcons] = (struct vt_struct *)(p+sizeof(struct vc_data));
+ visual_init(currcons);
+ q = (long)kmalloc(video_screen_size, GFP_KERNEL);
+ if (!q) {
+ kfree_s((char *) p, structsize);
+ vc_cons[currcons].d = NULL;
+ vt_cons[currcons] = NULL;
return -ENOMEM;
}
-
- vc_cons[i].d = (struct vc_data *) p;
- p += sizeof(struct vc_data);
- vt_cons[i] = (struct vt_struct *) p;
- vc_scrbuf[i] = (unsigned short *) q;
- vc_cons[i].d->vc_kmalloced = 1;
- vc_cons[i].d->vc_screenbuf_size = video_screen_size;
- vc_init (i, video_num_lines, video_num_columns, 1);
+ vc_scrbuf[currcons] = (unsigned short *) q;
+ vc_cons[currcons].d->vc_kmalloced = 1;
+ vc_cons[currcons].d->vc_screenbuf_size = video_screen_size;
+ vc_init(currcons, video_num_lines, video_num_columns, 1);
}
return 0;
}
/*
- * Change # of rows and columns (0 means unchanged)
+ * Change # of rows and columns (0 means unchanged/the size of fg_console)
* [this is to be used together with some user program
* like resize that changes the hardware videomode]
*/
@@ -367,7 +338,7 @@
unsigned long cc, ll, ss, sr;
unsigned long occ, oll, oss, osr;
unsigned short *p;
- unsigned int currcons, i;
+ unsigned int currcons = fg_console, i;
unsigned short *newscreens[MAX_NR_CONSOLES];
long ol, nl, rlth, rrem;
@@ -376,9 +347,6 @@
sr = cc << 1;
ss = sr * ll;
- if (ss > video_mem_term - video_mem_base)
- return -ENOMEM;
-
/*
* Some earlier version had all consoles of potentially
* different sizes, but that was really messy.
@@ -400,22 +368,20 @@
}
}
- get_scrmem(fg_console);
-
- oll = video_num_lines;
- occ = video_num_columns;
- osr = video_size_row;
- oss = video_screen_size;
-
- video_num_lines = ll;
- video_num_columns = cc;
- video_size_row = sr;
- video_screen_size = ss;
-
for (currcons = 0; currcons < MAX_NR_CONSOLES; currcons++) {
if (!vc_cons_allocated(currcons))
continue;
+ oll = video_num_lines;
+ occ = video_num_columns;
+ osr = video_size_row;
+ oss = video_screen_size;
+
+ video_num_lines = ll;
+ video_num_columns = cc;
+ video_size_row = sr;
+ video_screen_size = ss;
+
rlth = MIN(osr, sr);
rrem = sr - rlth;
ol = origin;
@@ -423,6 +389,7 @@
if (ll < oll)
ol += (oll - ll) * osr;
+ update_attr(currcons);
while (ol < scr_end) {
memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
if (rrem)
@@ -432,7 +399,7 @@
}
if (kmalloced)
- kfree_s(vc_scrbuf[currcons], screenbuf_size);
+ kfree_s(vc_scrbuf[currcons], oss);
vc_scrbuf[currcons] = newscreens[currcons];
kmalloced = 1;
screenbuf_size = ss;
@@ -450,16 +417,110 @@
save_cur(currcons);
}
- set_scrmem(fg_console, 0);
- set_origin(fg_console);
+ /* don't update in graphics mode */
+ if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
+ update_screen(fg_console);
+
set_cursor(fg_console);
return 0;
}
+/*
+ * ++Geert: Change # of rows and columns for one specific console.
+ * Of course it's not messy to have all consoles of potentially different
+ * sizes, except on PCish hardware :-)
+ */
+void vc_resize_con(unsigned long lines, unsigned long cols,
+ unsigned int currcons)
+{
+ unsigned long cc, ll, ss, sr;
+ unsigned long occ, oll, oss, osr;
+ unsigned short *newscreen;
+ long ol, nl, rlth, rrem;
+
+ if (!cols || !lines || currcons >= MAX_NR_CONSOLES)
+ return;
+
+ cc = cols;
+ ll = lines;
+ sr = cc << 1;
+ ss = sr * ll;
+
+ if (!vc_cons_allocated(currcons))
+ newscreen = 0;
+ else if (!(newscreen = (unsigned short *)kmalloc(ss, GFP_USER)))
+ return;
+
+ if (vc_cons_allocated(currcons)) {
+ oll = video_num_lines;
+ occ = video_num_columns;
+ osr = video_size_row;
+ oss = video_screen_size;
+
+ video_num_lines = ll;
+ video_num_columns = cc;
+ video_size_row = sr;
+ video_screen_size = ss;
+
+ rlth = MIN(osr, sr);
+ rrem = sr - rlth;
+ ol = origin;
+ nl = (long) newscreen;
+ if (ll < oll)
+ ol += (oll - ll) * osr;
+
+ /* ++Geert: TODO: Because the attributes have different meanings
+ for monochrome and color, they should really be converted if
+ can_do_color changes... */
+ update_attr(currcons);
+ while (ol < scr_end) {
+ memcpyw((unsigned short *) nl, (unsigned short *) ol, rlth);
+ if (rrem)
+ memsetw((void *)(nl + rlth), video_erase_char, rrem);
+ ol += osr;
+ nl += sr;
+ }
+
+ if (kmalloced)
+ kfree_s(vc_scrbuf[currcons], oss);
+ vc_scrbuf[currcons] = newscreen;
+ kmalloced = 1;
+ screenbuf_size = ss;
+
+ origin = video_mem_start = (long) vc_scrbuf[currcons];
+ scr_end = video_mem_end = video_mem_start + ss;
+
+ if (scr_end > nl)
+ memsetw((void *) nl, video_erase_char, scr_end - nl);
+
+ /* do part of a reset_terminal() */
+ top = 0;
+ bottom = video_num_lines;
+ gotoxy(currcons, x, y);
+ save_cur(currcons);
+
+ if (console_table[currcons]) {
+ struct winsize ws, *cws = &console_table[currcons]->winsize;
+ ws.ws_row = video_num_lines;
+ ws.ws_col = video_num_columns;
+ if ((ws.ws_row != cws->ws_row || ws.ws_col != cws->ws_col) &&
+ console_table[currcons]->pgrp > 0)
+ kill_pg(console_table[currcons]->pgrp, SIGWINCH, 1);
+ *cws = ws;
+ }
+ }
+
+ /* don't update in graphics mode */
+ if (currcons == fg_console && vt_cons[fg_console]->vc_mode == KD_TEXT)
+ update_screen(fg_console);
+}
+
+
void vc_disallocate(unsigned int currcons)
{
if (vc_cons_allocated(currcons)) {
+ sw->con_deinit(vc_cons[currcons].d);
if (kmalloced)
kfree_s(vc_scrbuf[currcons], screenbuf_size);
if (currcons >= MIN_NR_CONSOLES)
@@ -490,7 +551,7 @@
/* the default colour table, for VGA+ colour systems */
int default_red[] = {0x00,0xaa,0x00,0xaa,0x00,0xaa,0x00,0xaa,
0x55,0xff,0x55,0xff,0x55,0xff,0x55,0xff};
-int default_grn[] = {0x00,0x00,0xaa,0x55,0x00,0x00,0xaa,0xaa,
+int default_grn[] = {0x00,0x00,0xaa,0xaa,0x00,0x00,0xaa,0xaa,
0x55,0x55,0xff,0xff,0x55,0x55,0xff,0xff};
int default_blu[] = {0x00,0x00,0x00,0x00,0xaa,0xaa,0xaa,0xaa,
0x55,0x55,0x55,0x55,0xff,0xff,0xff,0xff};
@@ -537,58 +598,16 @@
/*
* Hardware scrollback support
*/
-extern void __set_origin(unsigned short);
-unsigned short __real_origin; /* offset of non-scrolled screen */
-unsigned short __origin; /* offset of currently displayed screen */
-unsigned char has_wrapped; /* all of videomem is data of fg_console */
-static unsigned char hardscroll_enabled;
-static unsigned char hardscroll_disabled_by_init = 0;
-
-void no_scroll(char *str, int *ints)
+static inline void scrolldelta(int lines)
{
- /*
- * Disabling scrollback is required for the Braillex ib80-piezo
- * Braille reader made by F.H. Papenmeier (Germany).
- * Use the "no-scroll" bootflag.
- */
- hardscroll_disabled_by_init = 1;
- hardscroll_enabled = 0;
-}
-
-static void scrolldelta(int lines)
-{
- int new_origin;
- int last_origin_rel = (((video_mem_term - video_mem_base)
- / video_num_columns / 2) - (video_num_lines - 1)) * video_num_columns;
-
- new_origin = __origin + lines * video_num_columns;
- if (__origin > __real_origin)
- new_origin -= last_origin_rel;
- if (new_origin < 0) {
- int s_top = __real_origin + video_num_lines*video_num_columns;
- new_origin += last_origin_rel;
- if (new_origin < s_top)
- new_origin = s_top;
- if (new_origin > last_origin_rel - video_num_columns
- || has_wrapped == 0)
- new_origin = 0;
- else {
- unsigned short * d = (unsigned short *) video_mem_base;
- unsigned short * s = d + last_origin_rel;
- int count = (video_num_lines-1)*video_num_columns;
- while (count) {
- count--;
- scr_writew(scr_readw(d++),s++);
- }
- }
- } else if (new_origin > __real_origin)
- new_origin = __real_origin;
-
- __set_origin(new_origin);
+ int currcons = fg_console;
+ sw->con_scrolldelta(vc_cons[currcons].d, lines);
}
void scrollback(int lines)
{
+ int currcons = fg_console;
+
if (!lines)
lines = video_num_lines/2;
scrolldelta(-lines);
@@ -596,80 +615,31 @@
void scrollfront(int lines)
{
+ int currcons = fg_console;
+
if (!lines)
lines = video_num_lines/2;
scrolldelta(lines);
}
-static void set_origin(int currcons)
+static void scrup(int currcons, unsigned int t, unsigned int b, int nr)
{
- if (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_VGAC
- && video_type != VIDEO_TYPE_EGAM)
- return;
- if (currcons != fg_console || console_blanked || vcmode == KD_GRAPHICS)
- return;
- __real_origin = (origin-video_mem_base) >> 1;
- __set_origin(__real_origin);
-}
-
-static void scrup(int currcons, unsigned int t, unsigned int b, unsigned int nr)
-{
- int hardscroll = hardscroll_enabled;
+ unsigned short *d, *s;
if (t+nr >= b)
nr = b - t - 1;
if (b > video_num_lines || t >= b || nr < 1)
return;
- if (t || b != video_num_lines || nr > 1)
- hardscroll = 0;
- if (hardscroll) {
- origin += video_size_row;
- pos += video_size_row;
- scr_end += video_size_row;
- if (scr_end > video_mem_end) {
- unsigned short * d = (unsigned short *) video_mem_start;
- unsigned short * s = (unsigned short *) origin;
- unsigned int count;
-
- count = (video_num_lines-1)*video_num_columns;
- while (count) {
- count--;
- scr_writew(scr_readw(s++),d++);
- }
- count = video_num_columns;
- while (count) {
- count--;
- scr_writew(video_erase_char, d++);
- }
- scr_end -= origin-video_mem_start;
- pos -= origin-video_mem_start;
- origin = video_mem_start;
- has_scrolled = 1;
- if (currcons == fg_console)
- has_wrapped = 1;
- } else {
- unsigned short * d;
- unsigned int count;
-
- d = (unsigned short *) (scr_end - video_size_row);
- count = video_num_columns;
- while (count) {
- count--;
- scr_writew(video_erase_char, d++);
- }
- }
- set_origin(currcons);
- } else {
- unsigned short * d = (unsigned short *) (origin+video_size_row*t);
- unsigned short * s = (unsigned short *) (origin+video_size_row*(t+nr));
-
- memcpyw(d, s, (b-t-nr) * video_size_row);
- memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
- }
+ d = (unsigned short *) (origin+video_size_row*t);
+ s = (unsigned short *) (origin+video_size_row*(t+nr));
+ memcpyw(d, s, (b-t-nr) * video_size_row);
+ memsetw(d + (b-t-nr) * video_num_columns, video_erase_char, video_size_row*nr);
+ if (currcons == fg_console)
+ sw->con_scroll(vc_cons[currcons].d, t, b, SM_UP, nr);
}
static void
-scrdown(int currcons, unsigned int t, unsigned int b, unsigned int nr)
+scrdown(int currcons, unsigned int t, unsigned int b, int nr)
{
unsigned short *s;
unsigned int count;
@@ -686,42 +656,14 @@
memcpyw(s + step, s, video_size_row);
s -= video_num_columns;
}
- while (nr--) {
+ count = nr;
+ while (count--) {
s += video_num_columns;
memsetw(s, video_erase_char, video_size_row);
}
has_scrolled = 1;
-}
-
-/*
- * Routine to reset the visible "screen" to the top of video memory.
- * This is necessary when exiting from the kernel back to a console
- * which expects only the top of video memory to be used for the visible
- * screen (with scrolling down by moving the memory contents).
- * The normal action of the LINUX console is to scroll using all of the
- * video memory and diddling the hardware top-of-video register as needed.
- */
-void
-scrreset(void)
-{
- int currcons = fg_console;
- unsigned short * d = (unsigned short *) video_mem_start;
- unsigned short * s = (unsigned short *) origin;
- unsigned int count;
-
- count = (video_num_lines-1)*video_num_columns;
- memcpyw(d, s, 2*count);
- memsetw(d + count, video_erase_char,
- 2*video_num_columns);
- scr_end -= origin-video_mem_start;
- pos -= origin-video_mem_start;
- origin = video_mem_start;
-
- has_scrolled = 1;
- has_wrapped = 1;
-
- set_origin(currcons);
- set_cursor(currcons);
+ if (currcons == fg_console)
+ sw->con_scroll(vc_cons[currcons].d, t, b, SM_DOWN, nr);
}
static void lf(int currcons)
@@ -730,7 +672,7 @@
* if below scrolling region
*/
if (y+1 == bottom)
- scrup(currcons,top,bottom, 1);
+ scrup(currcons,top,bottom,1);
else if (y < video_num_lines-1) {
y++;
pos += video_size_row;
@@ -781,14 +723,33 @@
case 0: /* erase from cursor to end of display */
count = (scr_end-pos)>>1;
start = (unsigned short *) pos;
+ if (currcons == fg_console) {
+ /* do in two stages */
+ sw->con_clear(vc_cons[currcons].d, y, x, 1,
+ video_num_columns-x);
+ sw->con_clear(vc_cons[currcons].d, y+1, 0,
+ video_num_lines-y-1,
+ video_num_columns);
+ }
break;
case 1: /* erase from start to cursor */
count = ((pos-origin)>>1)+1;
start = (unsigned short *) origin;
+ if (currcons == fg_console) {
+ /* do in two stages */
+ sw->con_clear(vc_cons[currcons].d, 0, 0, y,
+ video_num_columns);
+ sw->con_clear(vc_cons[currcons].d, y, 0, 1,
+ x + 1);
+ }
break;
case 2: /* erase whole display */
count = video_num_columns * video_num_lines;
start = (unsigned short *) origin;
+ if (currcons == fg_console)
+ sw->con_clear(vc_cons[currcons].d, 0, 0,
+ video_num_lines,
+ video_num_columns);
break;
default:
return;
@@ -806,14 +767,23 @@
case 0: /* erase from cursor to end of line */
count = video_num_columns-x;
start = (unsigned short *) pos;
+ if (currcons == fg_console)
+ sw->con_clear(vc_cons[currcons].d, y, x, 1,
+ video_num_columns-x);
break;
case 1: /* erase from start of line to cursor */
start = (unsigned short *) (pos - (x<<1));
count = x+1;
+ if (currcons == fg_console)
+ sw->con_clear(vc_cons[currcons].d, y, 0, 1,
+ x + 1);
break;
case 2: /* erase whole line */
start = (unsigned short *) (pos - (x<<1));
count = video_num_columns;
+ if (currcons == fg_console)
+ sw->con_clear(vc_cons[currcons].d, y, 0, 1,
+ video_num_columns);
break;
default:
return;
@@ -824,16 +794,43 @@
static void csi_X(int currcons, int vpar) /* erase the following vpar positions */
{ /* not vt100? */
+ int count;
+
if (!vpar)
vpar++;
+ count = (vpar > video_num_columns-x) ? (video_num_columns-x) : vpar;
- memsetw((unsigned short *) pos, video_erase_char,
- (vpar > video_num_columns-x) ? 2 * (video_num_columns-x) : 2 * vpar);
+ memsetw((unsigned short *) pos, video_erase_char, 2 * count);
+ if (currcons == fg_console)
+ sw->con_clear(vc_cons[currcons].d, y, x, 1, count);
need_wrap = 0;
}
static void update_attr(int currcons)
{
+/*
+ * ++roman: I completely changed the attribute format for monochrome
+ * mode (!can_do_color). The formerly used MDA (monochrome display
+ * adapter) format didn't allow the combination of certain effects.
+ * Now the attribute is just a bit vector:
+ * Bit 0..1: intensity (0..2)
+ * Bit 2 : underline
+ * Bit 3 : reverse
+ * Bit 7 : blink
+ *
+ * ++Geert: TODO: Because the attributes have different meanings
+ * for monochrome and color, they should really be converted if
+ * can_do_color changes...
+ */
+ if (!can_do_color) {
+ /* Special treatment for monochrome */
+ attr = intensity |
+ (underline ? 4 : 0) |
+ ((reverse ^ decscnm) ? 8 : 0) |
+ (blink ? 0x80 : 0);
+ video_erase_char = ' ' | ((reverse ^ decscnm) ? 0x800 : 0);
+ return;
+ }
attr = color;
if (can_do_color) {
if (underline)
@@ -847,12 +844,6 @@
attr ^= 0x80;
if (intensity == 2)
attr ^= 0x08;
- if (!can_do_color) {
- if (underline)
- attr = (attr & 0xf8) | 0x01;
- else if (intensity == 0)
- attr = (attr & 0xf0) | 0x08;
- }
if (decscnm)
video_erase_char = (reverse_video_char(color) << 8) | ' ';
else
@@ -1060,31 +1051,57 @@
static inline unsigned short *screenpos(int currcons, int offset, int viewed)
{
unsigned short *p = (unsigned short *)(origin + offset);
- if (viewed && currcons == fg_console)
- p -= (__real_origin - __origin);
return p;
}
+static inline void visual_putc_attr(int currcons, unsigned short new,
+ int yy, int xx)
+{
+ unsigned short oldattr = attr;
+ attr = new >> 8;
+ sw->con_putc(vc_cons[currcons].d, new & 0xff, yy, xx);
+ attr = oldattr;
+}
+
+static inline void visual_putc_attr_next(int currcons, unsigned short new,
+ int *yy, int *xx)
+{
+ attr = new >> 8;
+ sw->con_putc(vc_cons[currcons].d, new & 0xff, *yy, *xx);
+ if (++(*xx) == video_num_columns)
+ *xx = 0, ++(*yy);
+}
+
+
/* Note: inverting the screen twice should revert to the original state */
void invert_screen(int currcons, int offset, int count, int viewed)
{
unsigned short *p;
+ int xx = (offset >> 1) % video_num_columns;
+ int yy = (offset >> 1) / video_num_columns;
+ unsigned short oldattr = attr;
count /= 2;
p = screenpos(currcons, offset, viewed);
if (can_do_color)
while (count--) {
unsigned short old = scr_readw(p);
- scr_writew(reverse_video_short(old), p);
+ unsigned short new = reverse_video_short(old);
+ scr_writew(new, p);
p++;
+ if (currcons == fg_console)
+ visual_putc_attr_next(currcons, new, &yy, &xx);
}
else
while (count--) {
unsigned short old = scr_readw(p);
- scr_writew(old ^ (((old & 0x0700) == 0x0100)
- ? 0x7000 : 0x7700), p);
+ unsigned short new = reverse_video_short_mono(old);
+ scr_writew(new, p);
p++;
+ if (currcons == fg_console)
+ visual_putc_attr_next(currcons, new, &yy, &xx);
}
+ attr = oldattr;
}
/* used by selection: complement pointer position */
@@ -1092,15 +1109,25 @@
{
static unsigned short *p = NULL;
static unsigned short old = 0;
+ static unsigned short oldx = 0, oldy = 0;
- if (p)
+ if (p) {
scr_writew(old, p);
+ if (currcons == fg_console)
+ visual_putc_attr(currcons, old, oldy, oldx);
+ }
if (offset == -1)
p = NULL;
else {
+ unsigned short new;
p = screenpos(currcons, offset, 1);
old = scr_readw(p);
- scr_writew(old ^ 0x7700, p);
+ oldx = (offset >> 1) % video_num_columns;
+ oldy = (offset >> 1) / video_num_columns;
+ new = complement_video_short(old);
+ scr_writew(new, p);
+ if (currcons == fg_console)
+ visual_putc_attr(currcons, new, oldy, oldx);
}
}
@@ -1261,9 +1288,18 @@
p = q + video_num_columns - nr - x;
while (--p >= q)
scr_writew(scr_readw(p), p + nr);
-
memsetw(q, video_erase_char, nr*2);
need_wrap = 0;
+ if (currcons == fg_console) {
+ unsigned short oldattr = attr;
+ sw->con_bmove(vc_cons[currcons].d,y,x,y,x+nr,1,
+ video_num_columns-x-nr);
+ attr = video_erase_char >> 8;
+ while (nr--)
+ sw->con_putc(vc_cons[currcons].d,
+ (video_erase_char & 0x00ff),y,x+nr);
+ attr = oldattr;
+ }
}
static void insert_line(int currcons, unsigned int nr)
@@ -1275,7 +1311,7 @@
static void delete_char(int currcons, unsigned int nr)
{
unsigned int i = x;
- unsigned short * p = (unsigned short *) pos;
+ unsigned short *p = (unsigned short *) pos;
while (++i <= video_num_columns - nr) {
scr_writew(scr_readw(p+nr), p);
@@ -1283,6 +1319,17 @@
}
memsetw(p, video_erase_char, nr*2);
need_wrap = 0;
+ if (currcons == fg_console) {
+ unsigned short oldattr = attr;
+ sw->con_bmove(vc_cons[currcons].d, y, x+nr, y, x, 1,
+ video_num_columns-x-nr);
+ attr = video_erase_char >> 8;
+ while (nr--)
+ sw->con_putc(vc_cons[currcons].d,
+ (video_erase_char & 0x00ff), y,
+ video_num_columns-1-nr);
+ attr = oldattr;
+ }
}
static void delete_line(int currcons, unsigned int nr)
@@ -1293,8 +1340,8 @@
static void csi_at(int currcons, unsigned int nr)
{
- if (nr > video_num_columns)
- nr = video_num_columns;
+ if (nr > video_num_columns - x)
+ nr = video_num_columns - x;
else if (!nr)
nr = 1;
insert_char(currcons, nr);
@@ -1302,8 +1349,8 @@
static void csi_L(int currcons, unsigned int nr)
{
- if (nr > video_num_lines)
- nr = video_num_lines;
+ if (nr > video_num_lines - y)
+ nr = video_num_lines - y;
else if (!nr)
nr = 1;
insert_line(currcons, nr);
@@ -1311,8 +1358,8 @@
static void csi_P(int currcons, unsigned int nr)
{
- if (nr > video_num_columns)
- nr = video_num_columns;
+ if (nr > video_num_columns - x)
+ nr = video_num_columns - x;
else if (!nr)
nr = 1;
delete_char(currcons, nr);
@@ -1320,8 +1367,8 @@
static void csi_M(int currcons, unsigned int nr)
{
- if (nr > video_num_lines)
- nr = video_num_lines;
+ if (nr > video_num_lines - y)
+ nr = video_num_lines - y;
else if (!nr)
nr=1;
delete_line(currcons, nr);
@@ -1395,6 +1442,8 @@
kbd_table[currcons].ledflagstate = kbd_table[currcons].default_ledflagstate;
set_leds();
+ cursor_type = CUR_DEFAULT;
+
default_attr(currcons);
update_attr(currcons);
@@ -1455,7 +1504,7 @@
currcons = vt->vc_num;
if (vcmode != KD_GRAPHICS)
set_cursor(currcons);
-}
+}
static int do_con_write(struct tty_struct * tty, int from_user,
const unsigned char *buf, int count)
@@ -1480,6 +1529,11 @@
return 0;
}
+ /* undraw cursor first */
+ if (currcons == fg_console)
+ hide_cursor(currcons);
+
+ /* clear the selection */
if (currcons == sel_cons)
clear_selection();
@@ -1490,7 +1544,7 @@
}
disable_bh(CONSOLE_BH);
- while (!tty->stopped && count) {
+ while (count) {
enable_bh(CONSOLE_BH);
if (from_user)
__get_user(c, buf);
@@ -1577,12 +1631,93 @@
cr(currcons);
lf(currcons);
}
+
+ /* DPC: 1994-04-12
+ * Speed up overstrike mode, using new putcs.
+ *
+ * P.S. I hate 8 spaces per tab! Use Emacs!
+ */
+
+ /* Only use this for the foreground console,
+ where we really draw the chars */
+
+ if (count > 2 &&
+ !decim && !utf && currcons == fg_console) {
+ char *p = putcs_buf;
+ int putcs_count = 1;
+ ushort nextx = x + 1;
+
+ *p++ = tc;
+ scr_writew((attr << 8) + tc,
+ (unsigned short *)pos);
+ pos+=2;
+
+ if (nextx == video_num_columns) {
+ sw->con_putc(vc_cons[currcons].d,
+ *putcs_buf, y, x);
+ pos-=2;
+ need_wrap = decawm;
+ continue;
+ }
+
+ /* TAB TAB TAB - Arghh!!!! */
+
+ while (count) {
+ enable_bh(CONSOLE_BH);
+ if (from_user)
+ get_user(c, buf);
+ else
+ c = *buf;
+ disable_bh(CONSOLE_BH);
+ tc = translate[toggle_meta ? (c|0x80) : c];
+ if (!tc ||
+ !(c >= 32
+ || !(((disp_ctrl ? CTRL_ALWAYS
+ : CTRL_ACTION) >> c) & 1)))
+ break;
+ tc = conv_uni_to_pc(tc);
+ if (tc == -4)
+ tc = conv_uni_to_pc(0xfffd);
+ else if (tc == -3)
+ tc = c;
+
+ buf++; n++; count--;
+ if (tc & ~console_charmask)
+ continue; /* Conversion failed */
+
+ *p++ = tc;
+ scr_writew((attr << 8) + tc,
+ (unsigned short *)pos);
+ pos+=2;
+ ++putcs_count;
+ ++nextx;
+ if (nextx == video_num_columns ||
+ putcs_count == sizeof (putcs_buf))
+ break;
+ }
+
+ sw->con_putcs(vc_cons[currcons].d,
+ putcs_buf, putcs_count, y, x);
+ if (nextx == video_num_columns) {
+ pos-=2;
+ x = video_num_columns-1;
+ need_wrap = decawm;
+ } else
+ x += putcs_count;
+ continue;
+ }
+
+ /* DPC: End of putcs support */
+
if (decim)
insert_char(currcons, 1);
scr_writew( video_mode_512ch ?
((attr & 0xf7) << 8) + ((tc & 0x100) << 3) +
(tc & 0x0ff) : (attr << 8) + tc,
(unsigned short *) pos);
+ if (currcons == fg_console)
+ sw->con_putc(vc_cons[currcons].d, tc, y, x);
+
if (x == video_num_columns - 1)
need_wrap = decawm;
else {
@@ -1760,6 +1895,13 @@
case 'l':
set_mode(currcons,0);
continue;
+ case 'c':
+ if (par[0])
+ cursor_type = par[0] | (par[1]<<8) | (par[2]<<16);
+ else
+ cursor_type = CUR_DEFAULT;
+ set_cursor(currcons);
+ continue;
case 'n':
if (!ques) {
if (par[0] == 5)
@@ -1901,6 +2043,11 @@
/* DEC screen alignment test. kludge :-) */
video_erase_char =
(video_erase_char & 0xff00) | 'E';
+ /* Arno:
+ * Doesn't work, because csi_J(c,2)
+ * calls con_clear and doesn't print
+ * the erase char..
+ */
csi_J(currcons, 2);
video_erase_char =
(video_erase_char & 0xff00) | ' ';
@@ -1989,6 +2136,9 @@
int currcons = fg_console;
unsigned char c;
static int printing = 0;
+ const char *start = b;
+ ushort cnt = 0;
+ ushort myx = x;
#if CONFIG_AP1000
prom_printf(b);
@@ -2007,30 +2157,52 @@
return;
}
-#ifdef CONFIG_SERIAL_ECHO
- serial_echo_print(b);
-#endif /* CONFIG_SERIAL_ECHO */
-
- while (count-- > 0) {
- c = *(b++);
- if (c == 10 || c == 13 || need_wrap) {
+ /* undraw cursor first */
+ hide_cursor(currcons);
+
+ /* Contrived structure to try to emulate original need_wrap behaviour
+ * Problems caused when we have need_wrap set on '\n' character */
+ while (count--) {
+ c = *b++;
+ if (c == 10 || c == 13 || c == 8 || need_wrap) {
+ if ((cnt = b - start - 1) > 0) {
+ sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
+ x += cnt;
+ if (need_wrap)
+ x--;
+ }
+ if (c == 8) { /* backspace */
+ bs(currcons);
+ start = b;
+ myx = x;
+ continue;
+ }
if (c != 13)
lf(currcons);
cr(currcons);
- if (c == 10 || c == 13)
+ if (c == 10 || c == 13) {
+ start = b;
+ myx = x;
continue;
- }
- if (c == 8) { /* backspace */
- bs(currcons);
- continue;
+ }
+ start = b-1;
+ myx = x;
}
scr_writew((attr << 8) + c, (unsigned short *) pos);
- if (x == video_num_columns - 1) {
+ if (myx == video_num_columns - 1) {
need_wrap = 1;
continue;
}
- x++;
pos+=2;
+ myx++;
+ }
+ if ((cnt = b - start) > 0) {
+ sw->con_putcs(vc_cons[currcons].d, start, cnt, y, x);
+ x += cnt;
+ if (x == video_num_columns) {
+ x--;
+ need_wrap = 1;
+ }
}
set_cursor(currcons);
poke_blanked_console();
@@ -2101,14 +2273,6 @@
reset_terminal(currcons, do_clear);
}
-static void con_setsize(unsigned long rows, unsigned long cols)
-{
- video_num_lines = rows;
- video_num_columns = cols;
- video_size_row = 2 * cols;
- video_screen_size = video_num_lines * video_size_row;
-}
-
/*
* This is the console switching bottom half handler.
*
@@ -2150,23 +2314,17 @@
*/
__initfunc(unsigned long con_init(unsigned long kmem_start))
{
- const char *display_desc = "????";
- int currcons = 0;
- int orig_x = ORIG_X;
- int orig_y = ORIG_Y;
-
-#ifdef __sparc__
- if (serial_console) {
+ const char *display_desc = NULL;
+ unsigned int currcons = 0;
+ char q[2] = { 0, 1 };
+
+ if (conswitchp)
+ kmem_start = conswitchp->con_startup(kmem_start,
+ &display_desc);
+ if (!display_desc) {
fg_console = 0;
-
-#if CONFIG_SUN_SERIAL
- rs_cons_hook(0, 0, serial_console);
- rs_cons_hook(0, 1, serial_console);
-#endif
-
return kmem_start;
}
-#endif
memset(&console_driver, 0, sizeof(struct tty_driver));
console_driver.magic = TTY_DRIVER_MAGIC;
@@ -2201,7 +2359,6 @@
#if CONFIG_AP1000
return(kmem_start);
#endif
- con_setsize(ORIG_VIDEO_LINES, ORIG_VIDEO_COLS);
timer_table[BLANK_TIMER].fn = blank_screen;
timer_table[BLANK_TIMER].expires = 0;
@@ -2210,14 +2367,6 @@
timer_active |= 1<<BLANK_TIMER;
}
- kmem_start = con_type_init(kmem_start, &display_desc);
-
- hardscroll_enabled = (hardscroll_disabled_by_init ? 0 :
- (video_type == VIDEO_TYPE_EGAC
- || video_type == VIDEO_TYPE_VGAC
- || video_type == VIDEO_TYPE_EGAM));
- has_wrapped = 0 ;
-
/* Due to kmalloc roundup allocating statically is more efficient -
so provide MIN_NR_CONSOLES for people with very little memory */
for (currcons = 0; currcons < MIN_NR_CONSOLES; currcons++) {
@@ -2227,6 +2376,7 @@
kmem_start += sizeof(struct vc_data);
vt_cons[currcons] = (struct vt_struct *) kmem_start;
kmem_start += sizeof(struct vt_struct);
+ visual_init(currcons);
vc_scrbuf[currcons] = (unsigned short *) kmem_start;
kmem_start += video_screen_size;
kmalloced = 0;
@@ -2241,58 +2391,65 @@
currcons = fg_console = 0;
- video_mem_start = video_mem_base;
- video_mem_end = video_mem_term;
- origin = video_mem_start;
- scr_end = video_mem_start + video_num_lines * video_size_row;
- gotoxy(currcons,orig_x,orig_y);
- set_origin(currcons);
+ gotoxy(currcons,0,0);
csi_J(currcons, 0);
+ update_screen(fg_console);
- /* Figure out the size of the screen and screen font so we
- can figure out the appropriate screen size should we load
- a different font */
-
- printable = 1;
- if ( video_type == VIDEO_TYPE_VGAC || video_type == VIDEO_TYPE_EGAC
- || video_type == VIDEO_TYPE_EGAM || video_type == VIDEO_TYPE_TGAC
- || video_type == VIDEO_TYPE_SUN )
- {
- default_font_height = video_font_height = ORIG_VIDEO_POINTS;
- /* This may be suboptimal but is a safe bet - go with it */
- video_scan_lines = video_font_height * video_num_lines;
-
-#ifdef CONFIG_SERIAL_ECHO
- serial_echo_init(SERIAL_ECHO_PORT);
-#endif /* CONFIG_SERIAL_ECHO */
-
- printk("Console: %ld point font, %ld scans\n",
- video_font_height, video_scan_lines);
- }
-
- printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
+#if 0
+/* The logo is too ugly to live */
+ if (console_show_logo)
+ q[1] += console_show_logo();
+ conswitchp->con_putcs(vc_cons[fg_console].d, linux_logo_banner,
+ sizeof(linux_logo_banner)-1, q[1]-1, q[0]);
+ putconsxy(0, q);
+#endif
+ sw->con_cursor(vc_cons[currcons].d, CM_DRAW);
+ printk("Console: %s %s %ldx%ld",
can_do_color ? "colour" : "mono",
- display_desc, video_num_columns, video_num_lines,
- MIN_NR_CONSOLES, (MIN_NR_CONSOLES == 1) ? "" : "s",
- MAX_NR_CONSOLES);
-
- con_type_init_finish();
+ display_desc, video_num_columns, video_num_lines);
+ printable = 1;
+ printk("\n");
- /*
- * can't register TGA yet, because PCI bus probe has *not* taken
- * place before con_init() gets called. Trigger the real TGA hw
- * initialization and register_console() event from
- * within the bus probing code... :-(
- */
#ifdef CONFIG_VT_CONSOLE
- if (video_type != VIDEO_TYPE_TGAC && con_is_present())
- register_console(&vt_console_driver);
+ register_console(&vt_console_driver);
#endif
init_bh(CONSOLE_BH, console_bh);
return kmem_start;
}
+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;
+}
+
+void vesa_blank(void)
+{
+ vc_cons[fg_console].d->vc_sw->con_blank(vesa_blank_mode + 1);
+}
+
+void vesa_powerdown(void)
+{
+ /*
+ * 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:
+ vc_cons[fg_console].d->vc_sw->con_blank(VESA_VSYNC_SUSPEND+1);
+ break;
+ case VESA_VSYNC_SUSPEND:
+ case VESA_HSYNC_SUSPEND:
+ vc_cons[fg_console].d->vc_sw->con_blank(VESA_POWERDOWN+1);
+ break;
+ }
+}
+
void vesa_powerdown_screen(void)
{
timer_active &= ~(1<<BLANK_TIMER);
@@ -2308,6 +2465,12 @@
if (console_blanked)
return;
+ /* don't blank graphics */
+ if (vt_cons[fg_console]->vc_mode != KD_TEXT) {
+ console_blanked = fg_console + 1;
+ hide_cursor(fg_console);
+ return;
+ }
if(vesa_off_interval && !nopowersave) {
timer_table[BLANK_TIMER].fn = vesa_powerdown_screen;
timer_table[BLANK_TIMER].expires = jiffies + vesa_off_interval;
@@ -2320,14 +2483,7 @@
/* try not to lose information by blanking, and not to waste memory */
currcons = fg_console;
has_scrolled = 0;
- blank__origin = __origin;
- blank_origin = origin;
- set_origin(fg_console);
- get_scrmem(fg_console);
- unblank_origin = origin;
- memsetw((void *)blank_origin, BLANK,
- 2*video_num_lines*video_num_columns);
- hide_cursor();
+ sw->con_blank(1);
console_blanked = fg_console + 1;
if(!nopowersave)
@@ -2343,9 +2499,6 @@
void do_unblank_screen(void)
{
int currcons;
- int resetorg;
- long offset;
-
if (!console_blanked)
return;
if (!vc_cons_allocated(fg_console)) {
@@ -2360,28 +2513,11 @@
}
currcons = fg_console;
- offset = 0;
- resetorg = 0;
- if (console_blanked == fg_console + 1 && origin == unblank_origin
- && !has_scrolled) {
- /* try to restore the exact situation before blanking */
- resetorg = 1;
- offset = (blank_origin - video_mem_base)
- - (unblank_origin - video_mem_start);
- }
-
console_blanked = 0;
- set_scrmem(fg_console, offset);
- set_origin(fg_console);
+ if (sw->con_blank(0))
+ /* Low-level driver cannot restore -> do it ourselves */
+ update_screen(fg_console);
set_cursor(fg_console);
- if (resetorg)
- __set_origin(blank__origin);
-
- vesa_unblank();
-#ifdef CONFIG_APM
- if (apm_display_unblank())
- return;
-#endif
}
/*
@@ -2400,9 +2536,13 @@
void update_screen(int new_console)
{
+ int currcons = fg_console;
+ int xx, yy, startx, attr_save;
+ char *bufp;
+ unsigned short *p;
static int lock = 0;
- if (new_console == fg_console || lock)
+ if (lock)
return;
if (!vc_cons_allocated(new_console)) {
/* strange ... */
@@ -2413,15 +2553,37 @@
clear_selection();
- if (!console_blanked)
- get_scrmem(fg_console);
- else
- console_blanked = -1; /* no longer of the form console+1 */
- fg_console = new_console; /* this is the only (nonzero) assignment to fg_console */
- /* consequently, fg_console will always be allocated */
- set_scrmem(fg_console, 0);
- set_origin(fg_console);
- set_cursor(fg_console);
+ currcons = fg_console = new_console;
+ sw->con_cursor (vc_cons[currcons].d, CM_ERASE);
+ sw->con_switch (vc_cons[new_console].d);
+ /* Update the screen contents */
+ p = (unsigned short *)video_mem_start;
+ attr_save = attr;
+ for (yy = 0; yy < video_num_lines; yy++) {
+ bufp = putcs_buf;
+ for (startx = xx = 0; xx < video_num_columns; xx++) {
+ if (attr != ((scr_readw(p) >> 8) & 0xff)) {
+ if (bufp > putcs_buf)
+ sw->con_putcs (vc_cons[currcons].d, putcs_buf,
+ bufp - putcs_buf, yy, startx);
+ startx = xx;
+ bufp = putcs_buf;
+ attr = (scr_readw(p) >> 8) & 0xff;
+ }
+ *bufp++ = scr_readw(p++);
+ if (bufp == putcs_buf + sizeof (putcs_buf)) {
+ sw->con_putcs (vc_cons[currcons].d, putcs_buf,
+ bufp - putcs_buf, yy, startx);
+ startx = xx + 1;
+ bufp = putcs_buf;
+ }
+ }
+ if (bufp > putcs_buf)
+ sw->con_putcs (vc_cons[currcons].d, putcs_buf,
+ bufp - putcs_buf, yy, startx);
+ }
+ set_cursor (currcons);
+ attr = attr_save;
set_leds();
compute_shiftstate();
lock = 0;
@@ -2432,17 +2594,17 @@
*/
static int con_open(struct tty_struct *tty, struct file * filp)
{
- unsigned int idx;
+ unsigned int currcons;
int i;
- idx = MINOR(tty->device) - tty->driver.minor_start;
+ currcons = MINOR(tty->device) - tty->driver.minor_start;
- i = vc_allocate(idx);
+ i = vc_allocate(currcons);
if (i)
return i;
- vt_cons[idx]->vc_num = idx;
- tty->driver_data = vt_cons[idx];
+ 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;
@@ -2451,9 +2613,41 @@
return 0;
}
+void set_palette(void)
+{
+ if (vt_cons[fg_console]->vc_mode != KD_GRAPHICS)
+ conswitchp->con_set_palette(vc_cons[fg_console].d, color_table);
+}
+
+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();
+ }
+ return 0;
+}
/*
- * Load palette into the EGA/VGA DAC registers. arg points to a colour
+ * Load palette into the DAC registers. arg points to a colour
* map, 3 bytes per colour, 16 colours, range from 0 to 255.
*/
@@ -2476,6 +2670,58 @@
palette[k++] = default_blu[j];
}
set_palette() ;
+}
+
+/*
+ * PIO_FONT support.
+ *
+ * Currently we only support 8 pixels wide fonts, at a maximum height
+ * of 32 pixels. Userspace fontdata is stored with 32 bytes reserved
+ * for each character which is kinda wasty, but this is done in order
+ * to maintain compatibility with the EGA/VGA fonts. It is upto the
+ * actual low-level console-driver convert data into its favorite
+ * format (maybe we should add a `fontoffset' field to the `display'
+ * structure so we wont have to convert the fontdata all the time.
+ * /Jes
+ */
+
+#define cmapsz 8192
+
+int set_get_font(unsigned char * arg, int set, int ch512)
+{
+ int i, unit, size;
+ char *charmap;
+
+ if (!arg)
+ return -EINVAL;
+
+
+ size = ch512 ? 2*cmapsz : cmapsz;
+
+ charmap = (char *)kmalloc(size, GFP_USER);
+
+ if (set) {
+ if (copy_from_user(charmap, arg, size)) {
+ kfree(charmap);
+ return -EFAULT;
+ }
+
+ for (unit = 32; unit > 0; unit--)
+ for (i = 0; i < (ch512 ? 512 : 256); i++)
+ if (charmap[32*i+unit-1])
+ goto nonzero;
+ nonzero:
+ i = conswitchp->con_set_font(vc_cons[fg_console].d, 8, unit, charmap);
+ } else {
+ memset(charmap, 0, size);
+ i = conswitchp->con_get_font(vc_cons[fg_console].d, &unit, &unit,
+ charmap);
+ if (i == 0 && copy_to_user(arg, charmap, size))
+ i = -EFAULT;
+ }
+ kfree(charmap);
+
+ return i;
}
/*
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov