11da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*
21da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
31da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
41da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
51da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 2002 Helge Deller <deller@gmx.de>
61da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
71da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
81da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  which were
91da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Created 28 Sep 1997 by Geert Uytterhoeven
111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Rewritten by Martin Mares <mj@ucw.cz>, July 1998
121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 1991, 1992  Linus Torvalds
131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			    1995  Jay Estabrook
141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 1995 Geert Uytterhoeven
151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 1993 Bjoern Brauel
161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Roman Hodek
171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 1993 Hamish Macdonald
181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Greg Harp
191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      with work by William Rucklidge (wjr@cs.cornell.edu)
221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Geert Uytterhoeven
231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Jes Sorensen (jds@kom.auc.dk)
241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Martin Apel
251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *	      with work by Guenther Kelleter
261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Martin Schaller
271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Andreas Schwab
281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Emmanuel Marty (core@ggi-project.org)
291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Jakub Jelinek (jj@ultra.linux.cz)
301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *			   Martin Mares <mj@ucw.cz>
311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  This file is subject to the terms and conditions of the GNU General Public
331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  License.  See the file COPYING in the main directory of this archive for
341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *  more details.
351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds *
361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds */
371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/init.h>
391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kernel.h>
401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/console.h>
411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/errno.h>
421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/vt_kern.h>
431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/kd.h>
441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/selection.h>
451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <linux/module.h>
461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include <asm/io.h>
481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#include "../sticore.h"
501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* switching to graphics mode */
521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define BLANK 0
531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int vga_is_gfx;
541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* this is the sti_struct used for this console */
561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic struct sti_struct *sticon_sti;
571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* Software scrollback */
591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long softback_buf, softback_curr;
601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long softback_in;
611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long /* softback_top, */ softback_end;
621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int softback_lines;
631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/* software cursor */
651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int cursor_drawn;
661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define CURSOR_DRAW_DELAY		(1)
671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#define DEFAULT_CURSOR_BLINK_RATE	(20)
681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int vbl_cursor_cnt;
701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic inline void cursor_undrawn(void)
721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    vbl_cursor_cnt = 0;
741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    cursor_drawn = 0;
751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
77b877a96409a3a99f2ce27b3c6473c9b28298ac7cAntonino A. Daplasstatic const char *sticon_startup(void)
781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return "STI console";
801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_set_palette(struct vc_data *c, unsigned char *table)
831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return -EINVAL;
851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int redraw_cursor = 0;
901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (vga_is_gfx || console_blanked)
921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    return;
931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (conp->vc_mode != KD_TEXT)
951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	    return;
961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) {
981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    cursor_undrawn();
991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    redraw_cursor = 1;
1001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sti_putc(sticon_sti, c, ypos, xpos);
1041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (redraw_cursor)
1061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    vbl_cursor_cnt = CURSOR_DRAW_DELAY;
1071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_putcs(struct vc_data *conp, const unsigned short *s,
1101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int count, int ypos, int xpos)
1111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int redraw_cursor = 0;
1131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (vga_is_gfx || console_blanked)
1151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    return;
1161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (conp->vc_mode != KD_TEXT)
1181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	    return;
1191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
1211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) &&
1221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(p->cursor_x < (xpos + count))) {
1231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    cursor_undrawn();
1241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    redraw_cursor = 1;
1251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    while (count--) {
1291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++);
1301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (redraw_cursor)
1331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    vbl_cursor_cnt = CURSOR_DRAW_DELAY;
1341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_cursor(struct vc_data *conp, int mode)
1371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    unsigned short car1;
1391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols];
1411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    switch (mode) {
1421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case CM_ERASE:
1431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x);
1441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	break;
1451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case CM_MOVE:
1461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case CM_DRAW:
1471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	switch (conp->vc_cursor_type & 0x0f) {
1481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CUR_UNDERLINE:
1491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CUR_LOWER_THIRD:
1501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CUR_LOWER_HALF:
1511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CUR_TWO_THIRDS:
1521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	case CUR_BLOCK:
1531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
1541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		     conp->vc_y, conp->vc_x);
1551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    break;
1561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	}
1571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	break;
1581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
1621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    struct sti_struct *sti = sticon_sti;
1641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (vga_is_gfx)
1661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds        return 0;
1671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sticon_cursor(conp, CM_ERASE);
1691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    switch (dir) {
1711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case SM_UP:
1721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols);
17393f78da405685a756beeaeae4b5e41fcec39eab3Linus Torvalds	sti_clear(sti, b - count, 0, count, conp->vc_cols, conp->vc_video_erase_char);
1741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	break;
1751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    case SM_DOWN:
1771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols);
17893f78da405685a756beeaeae4b5e41fcec39eab3Linus Torvalds	sti_clear(sti, t, 0, count, conp->vc_cols, conp->vc_video_erase_char);
1791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	break;
1801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
1811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
1831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
1841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_bmove(struct vc_data *conp, int sy, int sx,
1861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	int dy, int dx, int height, int width)
1871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
1881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (!width || !height)
1891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    return;
1901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#if 0
1911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (((sy <= p->cursor_y) && (p->cursor_y < sy+height) &&
1921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(sx <= p->cursor_x) && (p->cursor_x < sx+width)) ||
1931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	((dy <= p->cursor_y) && (p->cursor_y < dy+height) &&
1941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	(dx <= p->cursor_x) && (p->cursor_x < dx+width)))
1951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		sticon_cursor(p, CM_ERASE /*|CM_SOFTBACK*/);
1961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds#endif
1971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
1981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sti_bmove(sticon_sti, sy, sx, dy, dx, height, width);
1991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_init(struct vc_data *c, int init)
2021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    struct sti_struct *sti = sticon_sti;
2041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int vc_cols, vc_rows;
2051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
2071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    vc_cols = sti_onscreen_x(sti) / sti->font_width;
2081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    vc_rows = sti_onscreen_y(sti) / sti->font_height;
2091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    c->vc_can_do_color = 1;
2101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (init) {
2121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	c->vc_cols = vc_cols;
2131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	c->vc_rows = vc_rows;
2141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    } else {
2151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
2161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	/* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
2171da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vc_resize(c, vc_cols, vc_rows);
2181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds/*	vc_resize_con(vc_rows, vc_cols, c->vc_num); */
2191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
2201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_deinit(struct vc_data *c)
2231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
2271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds			 int width)
2281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (!height || !width)
2301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return;
2311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char);
2331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_switch(struct vc_data *conp)
2361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 1;	/* needs refreshing */
2381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_set_origin(struct vc_data *conp)
2411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
2431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_blank(struct vc_data *c, int blank, int mode_switch)
2461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (blank == 0) {
2481da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (mode_switch)
2491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    vga_is_gfx = 0;
2501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return 1;
2511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
2521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sticon_set_origin(c);
2531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK);
2541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (mode_switch)
2551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	vga_is_gfx = 1;
2561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 1;
2571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic int sticon_scrolldelta(struct vc_data *conp, int lines)
2601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
2621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u16 *sticon_screen_pos(struct vc_data *conp, int offset)
2651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int line;
2671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    unsigned long p;
2681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (conp->vc_num != fg_console || !softback_lines)
2701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	return (u16 *)(conp->vc_origin + offset);
2711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    line = offset / conp->vc_size_row;
2721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (line >= softback_lines)
2731da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	return (u16 *)(conp->vc_origin + offset - softback_lines * conp->vc_size_row);
2741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    p = softback_curr + offset;
2751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (p >= softback_end)
2761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	p += softback_buf - softback_end;
2771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return (u16 *)p;
2781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
2791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos,
2811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds				  int *px, int *py)
2821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
2831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int x, y;
2841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    unsigned long ret;
2851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (pos >= conp->vc_origin && pos < conp->vc_scr_end) {
2861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	unsigned long offset = (pos - conp->vc_origin) / 2;
2871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	x = offset % conp->vc_cols;
2891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	y = offset / conp->vc_cols;
2901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	if (conp->vc_num == fg_console)
2911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	    y += softback_lines;
2921da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	ret = pos + (conp->vc_cols - x) * 2;
2931da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    } else if (conp->vc_num == fg_console && softback_lines) {
2941da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	unsigned long offset = pos - softback_curr;
2951da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
2961da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	if (pos < softback_curr)
2971da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	    offset += softback_end - softback_buf;
2981da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	offset /= 2;
2991da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	x = offset % conp->vc_cols;
3001da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	y = offset / conp->vc_cols;
3011da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	ret = pos + (conp->vc_cols - x) * 2;
3021da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret == softback_end)
3031da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ret = softback_buf;
3041da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (ret == softback_in)
3051da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	    ret = conp->vc_origin;
3061da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    } else {
3071da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	/* Should not happen */
3081da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	x = y = 0;
3091da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    	ret = conp->vc_origin;
3101da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3111da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (px) *px = x;
3121da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (py) *py = y;
3131da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return ret;
3141da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3151da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3161da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens,
317fa6ce9ab5fbcb4c276c48861584b70d387e787b3Jan Engelhardt			    u8 blink, u8 underline, u8 reverse, u8 italic)
3181da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3191da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    u8 attr = ((color & 0x70) >> 1) | ((color & 7));
3201da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3211da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (reverse) {
3221da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	color = ((color >> 3) & 0x7) | ((color & 0x7) << 3);
3231da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3241da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3251da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return attr;
3261da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3271da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3281da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_invert_region(struct vc_data *conp, u16 *p, int count)
3291da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3301da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    int col = 1; /* vga_can_do_color; */
3311da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3321da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    while (count--) {
3331da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	u16 a = scr_readw(p);
3341da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3351da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	if (col)
3361da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
3371da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	else
3381da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds		a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
3391da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3401da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	scr_writew(a, p++);
3411da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3421da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3431da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3441da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsstatic void sticon_save_screen(struct vc_data *conp)
3451da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3461da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3471da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
348d95159cf1b12e8e4b169094b35cbd93b887cb939Helge Dellerstatic const struct consw sti_con = {
3491da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.owner			= THIS_MODULE,
3501da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_startup		= sticon_startup,
3511da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_init		= sticon_init,
3521da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_deinit		= sticon_deinit,
3531da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_clear		= sticon_clear,
3541da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_putc		= sticon_putc,
3551da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_putcs		= sticon_putcs,
3561da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_cursor		= sticon_cursor,
3571da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_scroll		= sticon_scroll,
3581da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_bmove		= sticon_bmove,
3591da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_switch		= sticon_switch,
3601da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_blank		= sticon_blank,
3611da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_set_palette	= sticon_set_palette,
3621da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_scrolldelta	= sticon_scrolldelta,
3631da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_set_origin		= sticon_set_origin,
3641da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_save_screen	= sticon_save_screen,
3651da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_build_attr		= sticon_build_attr,
3661da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_invert_region	= sticon_invert_region,
3671da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_screen_pos		= sticon_screen_pos,
3681da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	.con_getxy		= sticon_getxy,
3691da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds};
3701da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3711da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3721da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3733d1e412ac5570a669e1b1fc5fd0f6859250c3d76Adrian Bunkstatic int __init sticonsole_init(void)
3741da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds{
3751da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    /* already initialized ? */
3761da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (sticon_sti)
3771da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	 return 0;
3781da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3791da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    sticon_sti = sti_get_rom(0);
3801da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (!sticon_sti)
3811da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return -ENODEV;
3821da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3831da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    if (conswitchp == &dummy_con) {
3841da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	printk(KERN_INFO "sticon: Initializing STI text console.\n");
3851da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds	return take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1, 1);
3861da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    }
3871da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds    return 0;
3881da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds}
3891da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvalds
3901da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus Torvaldsmodule_init(sticonsole_init);
3911da177e4c3f41524e886b7f1b8a0c1fc7321cacLinus TorvaldsMODULE_LICENSE("GPL");
392