patch-1.3.1 linux/drivers/char/console.c
Next file: linux/drivers/char/consolemap.c
Previous file: linux/drivers/char/conmakehash.c
Back to the patch index
Back to the overall index
- Lines: 441
- Date:
Tue Jun 13 10:47:47 1995
- Orig file:
v1.3.0/linux/drivers/char/console.c
- Orig date:
Sat Jun 10 19:13:12 1995
diff -u --recursive --new-file v1.3.0/linux/drivers/char/console.c linux/drivers/char/console.c
@@ -33,8 +33,9 @@
* 'void scrollback(int lines)'
* 'void scrollfront(int lines)'
*
- * 'int con_get_font(char *)'
- * 'int con_set_font(char *)'
+ * 'int con_get_font(char *data)'
+ * 'int con_set_font(char *data, int ch512)'
+ * 'int con_adjust_height(int fontheight)'
*
* 'void mouse_report(struct tty_struct * tty, int butt, int mrx, int mry)'
* 'int mouse_reporting(void)'
@@ -64,6 +65,8 @@
* Code for xterm like mouse click reporting by Peter Orbaek 20-Jul-94
* <poe@daimi.aau.dk>
*
+ * Improved loadable font/UTF-8 support by H. Peter Anvin, Feb 1995
+ *
*/
#define BLANK 0x0020
@@ -74,7 +77,8 @@
* (such as cursor movement) and should not be displayed as a
* glyph unless the disp_ctrl mode is explicitly enabled.
*/
-#define CTRL_ACTION 0xd00ff80
+#define CTRL_ACTION 0x0d00ff81
+#define CTRL_ALWAYS 0x0800f501 /* Cannot be overridden by disp_ctrl */
/*
* NOTE!!! We sometimes disable and enable interrupts for a short while
@@ -122,8 +126,8 @@
#define NPAR 16
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);
+static void vc_init(unsigned int console, unsigned long rows,
+ unsigned long cols, int do_clear);
static void get_scrmem(int currcons);
static void set_scrmem(int currcons, long offset);
static void set_origin(int currcons);
@@ -140,7 +144,7 @@
extern void vesa_blank(void);
extern void vesa_unblank(void);
extern void compute_shiftstate(void);
-extern int conv_uni_to_pc(unsigned long ucs);
+extern int conv_uni_to_pc(long ucs);
/* Description of the hardware situation */
static unsigned char video_type; /* Type of display being used */
@@ -157,6 +161,11 @@
static unsigned long video_screen_size;
static int can_do_color = 0;
static int printable = 0; /* Is console ready for printing? */
+ /* these two also used in in vt.c */
+ int video_mode_512ch = 0; /* 512-character mode */
+ unsigned long video_font_height; /* Height of current screen font */
+static unsigned long video_scan_lines; /* Number of scan lines on screen */
+static unsigned short console_charmask = 0x0ff;
static unsigned short *vc_scrbuf[MAX_NR_CONSOLES];
@@ -164,6 +173,7 @@
static int blankinterval = 10*60*HZ;
static long blank_origin, blank__origin, unblank_origin;
+
struct vc_data {
unsigned long vc_screenbuf_size;
unsigned short vc_video_erase_char; /* Background erase character */
@@ -212,9 +222,9 @@
unsigned long vc_report_mouse : 2;
unsigned char vc_utf : 1; /* Unicode UTF-8 encoding */
unsigned char vc_utf_count;
- unsigned long vc_utf_char;
+ long vc_utf_char;
unsigned long vc_tab_stop[5]; /* Tab stops. 160 columns. */
- unsigned char * vc_translate;
+ unsigned short * vc_translate;
unsigned char vc_G0_charset;
unsigned char vc_G1_charset;
unsigned char vc_saved_G0;
@@ -879,7 +889,7 @@
* Select first alternate font, let's
* chars < 32 be displayed as ROM chars.
*/
- translate = set_translate(NULL_MAP);
+ translate = set_translate(IBMPC_MAP);
disp_ctrl = 1;
toggle_meta = 0;
break;
@@ -887,7 +897,7 @@
* Select second alternate font, toggle
* high bit before displaying as ROM char.
*/
- translate = set_translate(NULL_MAP);
+ translate = set_translate(IBMPC_MAP);
disp_ctrl = 1;
toggle_meta = 1;
break;
@@ -1264,8 +1274,8 @@
bottom = video_num_lines;
vc_state = ESnormal;
ques = 0;
- translate = set_translate(NORM_MAP);
- G0_charset = NORM_MAP;
+ translate = set_translate(LAT1_MAP);
+ G0_charset = LAT1_MAP;
G1_charset = GRAF_MAP;
charset = 0;
need_wrap = 0;
@@ -1370,7 +1380,7 @@
utf_char = (utf_char << 6) | (c & 0x3f);
utf_count--;
if (utf_count == 0)
- c = utf_char;
+ tc = c = utf_char;
else continue;
} else {
if ((c & 0xe0) == 0xc0) {
@@ -1379,26 +1389,25 @@
} else if ((c & 0xf0) == 0xe0) {
utf_count = 2;
utf_char = (c & 0x0f);
+ } else if ((c & 0xf8) == 0xf0) {
+ utf_count = 3;
+ utf_char = (c & 0x07);
+ } else if ((c & 0xfc) == 0xf8) {
+ utf_count = 4;
+ utf_char = (c & 0x03);
+ } else if ((c & 0xfe) == 0xfc) {
+ utf_count = 5;
+ utf_char = (c & 0x01);
} else
utf_count = 0;
continue;
- }
- } else
- utf_count = 0;
-
- /* Now try to find out how to display it */
- tc = conv_uni_to_pc(c);
- if (tc == -1 || tc == -2)
- continue;
- if (tc == -3 || tc == -4) { /* hashtable not valid */
- /* or symbol not found */
- tc = (c <= 0xff) ? translate[c] : 040;
- ok = 0;
- } else
- ok = 1;
+ }
+ } else {
+ tc = c;
+ utf_count = 0;
+ }
} else { /* no utf */
- tc = translate[toggle_meta ? (c|0x80) : c];
- ok = 0;
+ tc = translate[toggle_meta ? (c|0x80) : c];
}
/* If the original code was < 32 we only allow a
@@ -1407,19 +1416,39 @@
* disp_ctrl mode has been explicitly enabled.
* Note: ESC is *never* allowed to be displayed as
* that would disable all escape sequences!
+ * To display font position 0x1B, go into UTF mode
+ * and display character U+F01B, or change the mapping.
*/
- if (!ok && tc && (c >= 32 || (disp_ctrl && c != 0x1b)
- || !((CTRL_ACTION >> c) & 1)))
- ok = 1;
-
+ ok = (tc && (c >= 32 || (!utf && !(((disp_ctrl ? CTRL_ALWAYS
+ : CTRL_ACTION) >> c) & 1))));
+
if (vc_state == ESnormal && ok) {
+ /* Now try to find out how to display it */
+ tc = conv_uni_to_pc(tc);
+ if ( tc == -4 )
+ {
+ /* If we got -4 (not found) then see if we have
+ defined a replacement character (U+FFFD) */
+ tc = conv_uni_to_pc(0xfffd);
+ }
+ else if ( tc == -3 )
+ {
+ /* Bad hash table -- hope for the best */
+ tc = c;
+ }
+ if (tc & ~console_charmask)
+ continue; /* Conversion failed */
+
if (need_wrap) {
cr(currcons);
lf(currcons);
}
if (decim)
insert_char(currcons);
- scr_writew((attr << 8) + tc, (unsigned short *) pos);
+ scr_writew( video_mode_512ch ?
+ ((attr & 0xf7) << 8) + ((tc & 0x100) << 3) +
+ (tc & 0x0ff) : (attr << 8) + tc,
+ (unsigned short *) pos);
if (x == video_num_columns - 1)
need_wrap = decawm;
else {
@@ -1710,9 +1739,9 @@
if (c == '0')
G0_charset = GRAF_MAP;
else if (c == 'B')
- G0_charset = NORM_MAP;
+ G0_charset = LAT1_MAP;
else if (c == 'U')
- G0_charset = NULL_MAP;
+ G0_charset = IBMPC_MAP;
else if (c == 'K')
G0_charset = USER_MAP;
if (charset == 0)
@@ -1723,9 +1752,9 @@
if (c == '0')
G1_charset = GRAF_MAP;
else if (c == 'B')
- G1_charset = NORM_MAP;
+ G1_charset = LAT1_MAP;
else if (c == 'U')
- G1_charset = NULL_MAP;
+ G1_charset = IBMPC_MAP;
else if (c == 'K')
G1_charset = USER_MAP;
if (charset == 1)
@@ -1973,6 +2002,21 @@
gotoxy(currcons,orig_x,orig_y);
set_origin(currcons);
csi_J(currcons, 0);
+
+
+ /* 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 */
+
+ if ( video_type == VIDEO_TYPE_EGAC || video_type == VIDEO_TYPE_EGAM )
+ {
+ 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;
+ printk("Console: %ld point font, %ld scans\n",
+ video_font_height, video_scan_lines);
+ }
+
printable = 1;
printk("Console: %s %s %ldx%ld, %d virtual console%s (max %d)\n",
can_do_color ? "colour" : "mono",
@@ -2187,17 +2231,19 @@
should use 0xA0000 for the bwmap as well.. */
#define blackwmap ((char *)0xa0000)
#define cmapsz 8192
+#define attrib_port (0x3c0)
#define seq_port_reg (0x3c4)
#define seq_port_val (0x3c5)
#define gr_port_reg (0x3ce)
#define gr_port_val (0x3cf)
-static int set_get_font(char * arg, int set)
+static int set_get_font(char * arg, int set, int ch512)
{
#ifdef CAN_LOAD_EGA_FONTS
int i;
char *charmap;
int beg;
+ unsigned short video_port_status = video_port_reg + 6;
/* no use to "load" CGA... */
@@ -2210,7 +2256,8 @@
} else
return -EINVAL;
- i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg, cmapsz);
+ i = verify_area(set ? VERIFY_READ : VERIFY_WRITE, (void *)arg,
+ ch512 ? 2*cmapsz : cmapsz);
if (i)
return i;
@@ -2239,6 +2286,23 @@
for (i=0; i<cmapsz ; i++)
put_user(scr_readb(charmap + i), arg + i);
+ /*
+ * In 512-character mode, the character map is not contiguous if
+ * we want to remain EGA compatible -- which we do
+ */
+
+ if (ch512)
+ {
+ charmap += 2*cmapsz;
+ arg += cmapsz;
+ if (set)
+ for (i=0; i<cmapsz ; i++)
+ *(charmap+i) = get_fs_byte(arg+i);
+ else
+ for (i=0; i<cmapsz ; i++)
+ put_fs_byte(*(charmap+i), arg+i);
+ };
+
cli();
outb_p( 0x00, seq_port_reg ); /* First, the sequencer */
outb_p( 0x01, seq_port_val ); /* Synchronous reset */
@@ -2246,6 +2310,11 @@
outb_p( 0x03, seq_port_val ); /* CPU writes to maps 0 and 1 */
outb_p( 0x04, seq_port_reg );
outb_p( 0x03, seq_port_val ); /* odd-even addressing */
+ if (set)
+ {
+ outb_p( 0x03, seq_port_reg ); /* Character Map Select */
+ outb_p( ch512 ? 0x04 : 0x00, seq_port_val );
+ }
outb_p( 0x00, seq_port_reg );
outb_p( 0x03, seq_port_val ); /* clear synchronous reset */
@@ -2255,6 +2324,18 @@
outb_p( 0x10, gr_port_val ); /* enable even-odd addressing */
outb_p( 0x06, gr_port_reg );
outb_p( beg, gr_port_val ); /* map starts at b800:0 or b000:0 */
+ if (set) /* attribute controller */
+ {
+ /* 256-char: enable intensity bit
+ 512-char: disable intensity bit */
+ inb_p( video_port_status ); /* clear address flip-flop */
+ outb_p ( 0x12, attrib_port ); /* color plane enable register */
+ outb_p ( ch512 ? 0x07 : 0x0f, attrib_port );
+ /* Wilton (1987) mentions the following; I don't know what
+ it means, but it works, and it appears necessary */
+ inb_p( video_port_status );
+ outb_p ( 0x20, attrib_port );
+ }
sti();
return 0;
@@ -2269,13 +2350,96 @@
* 8xH fonts (0 < H <= 32).
*/
-int con_set_font (char *arg)
+int con_set_font (char *arg, int ch512)
{
- hashtable_contents_valid = 0;
- return set_get_font (arg,1);
+ int i;
+
+ i = set_get_font (arg,1,ch512);
+ if ( !i ) {
+ hashtable_contents_valid = 0;
+ video_mode_512ch = ch512;
+ console_charmask = ch512 ? 0x1ff : 0x0ff;
+ }
+ return i;
}
int con_get_font (char *arg)
{
- return set_get_font (arg,0);
+ return set_get_font (arg,0,video_mode_512ch);
+}
+
+/*
+ * 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 rows, maxscan;
+ unsigned char ovr, vde, fsr, curs, cure;
+
+ if (fontheight > 32 ||
+ (video_type != VIDEO_TYPE_EGAC && video_type != VIDEO_TYPE_EGAM))
+ return -EINVAL;
+
+ if ( fontheight == video_font_height || fontheight == 0 )
+ return 0;
+
+ video_font_height = fontheight;
+
+ rows = video_scan_lines/fontheight; /* Number of video rows we end up with */
+ maxscan = rows*fontheight - 1; /* Scan lines to actually display-1 */
+
+ /* Reprogram the CRTC for the new font size
+ Note: the attempt to read the overflow register will fail
+ on an EGA, but using 0xff for the previous value appears to
+ be OK for EGA text modes in the range 257-512 scan lines, so I
+ guess we don't need to worry about it.
+
+ The same applies for the spill bits in the font size and cursor
+ registers; they are write-only on EGA, but it appears that they
+ are all don't care bits on EGA, so I guess it doesn't matter. */
+
+ cli();
+ outb_p( 0x07, video_port_reg ); /* CRTC overflow register */
+ ovr = inb_p(video_port_val);
+ outb_p( 0x09, video_port_reg ); /* Font size register */
+ fsr = inb_p(video_port_val);
+ outb_p( 0x0a, video_port_reg ); /* Cursor start */
+ curs = inb_p(video_port_val);
+ outb_p( 0x0b, video_port_reg ); /* Cursor end */
+ cure = inb_p(video_port_val);
+ sti();
+
+ vde = maxscan & 0xff; /* Vertical display end reg */
+ ovr = (ovr & 0xbd) + /* Overflow register */
+ ((maxscan & 0x100) >> 7) +
+ ((maxscan & 0x200) >> 3);
+ fsr = (fsr & 0xe0) + (fontheight-1); /* Font size register */
+ curs = (curs & 0xc0) + fontheight - (fontheight < 10 ? 2 : 3);
+ cure = (cure & 0xe0) + fontheight - (fontheight < 10 ? 1 : 2);
+
+ cli();
+ outb_p( 0x07, video_port_reg ); /* CRTC overflow register */
+ outb_p( ovr, video_port_val );
+ outb_p( 0x09, video_port_reg ); /* Font size */
+ outb_p( fsr, video_port_val );
+ outb_p( 0x0a, video_port_reg ); /* Cursor start */
+ outb_p( curs, video_port_val );
+ outb_p( 0x0b, video_port_reg ); /* Cursor end */
+ outb_p( cure, video_port_val );
+ outb_p( 0x12, video_port_reg ); /* Vertical display limit */
+ outb_p( vde, video_port_val );
+ sti();
+
+ if ( rows == video_num_lines ) {
+ /* Change didn't affect number of lines -- no need to scare
+ the rest of the world */
+ return 0;
+ }
+
+ vc_resize(rows, 0); /* Adjust console size */
+
+ return rows;
}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen, slshen@lbl.gov
with Sam's (original) version of this