xref: /OK3568_Linux_fs/kernel/drivers/video/console/sticon.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  *  linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
3*4882a593Smuzhiyun  *
4*4882a593Smuzhiyun  *	Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
5*4882a593Smuzhiyun  *	Copyright (C) 2002-2020 Helge Deller <deller@gmx.de>
6*4882a593Smuzhiyun  *
7*4882a593Smuzhiyun  *  Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
8*4882a593Smuzhiyun  *  which were
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  *	Created 28 Sep 1997 by Geert Uytterhoeven
11*4882a593Smuzhiyun  *	Rewritten by Martin Mares <mj@ucw.cz>, July 1998
12*4882a593Smuzhiyun  *	Copyright (C) 1991, 1992  Linus Torvalds
13*4882a593Smuzhiyun  *			    1995  Jay Estabrook
14*4882a593Smuzhiyun  *	Copyright (C) 1995 Geert Uytterhoeven
15*4882a593Smuzhiyun  *	Copyright (C) 1993 Bjoern Brauel
16*4882a593Smuzhiyun  *			   Roman Hodek
17*4882a593Smuzhiyun  *	Copyright (C) 1993 Hamish Macdonald
18*4882a593Smuzhiyun  *			   Greg Harp
19*4882a593Smuzhiyun  *	Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
20*4882a593Smuzhiyun  *
21*4882a593Smuzhiyun  *	      with work by William Rucklidge (wjr@cs.cornell.edu)
22*4882a593Smuzhiyun  *			   Geert Uytterhoeven
23*4882a593Smuzhiyun  *			   Jes Sorensen (jds@kom.auc.dk)
24*4882a593Smuzhiyun  *			   Martin Apel
25*4882a593Smuzhiyun  *	      with work by Guenther Kelleter
26*4882a593Smuzhiyun  *			   Martin Schaller
27*4882a593Smuzhiyun  *			   Andreas Schwab
28*4882a593Smuzhiyun  *			   Emmanuel Marty (core@ggi-project.org)
29*4882a593Smuzhiyun  *			   Jakub Jelinek (jj@ultra.linux.cz)
30*4882a593Smuzhiyun  *			   Martin Mares <mj@ucw.cz>
31*4882a593Smuzhiyun  *
32*4882a593Smuzhiyun  *  This file is subject to the terms and conditions of the GNU General Public
33*4882a593Smuzhiyun  *  License.  See the file COPYING in the main directory of this archive for
34*4882a593Smuzhiyun  *  more details.
35*4882a593Smuzhiyun  *
36*4882a593Smuzhiyun  */
37*4882a593Smuzhiyun 
38*4882a593Smuzhiyun #include <linux/init.h>
39*4882a593Smuzhiyun #include <linux/kernel.h>
40*4882a593Smuzhiyun #include <linux/console.h>
41*4882a593Smuzhiyun #include <linux/errno.h>
42*4882a593Smuzhiyun #include <linux/vt_kern.h>
43*4882a593Smuzhiyun #include <linux/kd.h>
44*4882a593Smuzhiyun #include <linux/selection.h>
45*4882a593Smuzhiyun #include <linux/module.h>
46*4882a593Smuzhiyun #include <linux/slab.h>
47*4882a593Smuzhiyun #include <linux/font.h>
48*4882a593Smuzhiyun #include <linux/crc32.h>
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun #include <asm/io.h>
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun #include "../fbdev/sticore.h"
53*4882a593Smuzhiyun 
54*4882a593Smuzhiyun /* switching to graphics mode */
55*4882a593Smuzhiyun #define BLANK 0
56*4882a593Smuzhiyun static int vga_is_gfx;
57*4882a593Smuzhiyun 
58*4882a593Smuzhiyun #define STI_DEF_FONT	sticon_sti->font
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun /* borrowed from fbcon.c */
61*4882a593Smuzhiyun #define FNTREFCOUNT(fd)	(fd->refcount)
62*4882a593Smuzhiyun #define FNTCRC(fd)	(fd->crc)
63*4882a593Smuzhiyun static struct sti_cooked_font *font_data[MAX_NR_CONSOLES];
64*4882a593Smuzhiyun 
65*4882a593Smuzhiyun /* this is the sti_struct used for this console */
66*4882a593Smuzhiyun static struct sti_struct *sticon_sti;
67*4882a593Smuzhiyun 
sticon_startup(void)68*4882a593Smuzhiyun static const char *sticon_startup(void)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun     return "STI console";
71*4882a593Smuzhiyun }
72*4882a593Smuzhiyun 
sticon_putc(struct vc_data * conp,int c,int ypos,int xpos)73*4882a593Smuzhiyun static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos)
74*4882a593Smuzhiyun {
75*4882a593Smuzhiyun     if (vga_is_gfx || console_blanked)
76*4882a593Smuzhiyun 	    return;
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun     if (conp->vc_mode != KD_TEXT)
79*4882a593Smuzhiyun     	    return;
80*4882a593Smuzhiyun 
81*4882a593Smuzhiyun     sti_putc(sticon_sti, c, ypos, xpos, font_data[conp->vc_num]);
82*4882a593Smuzhiyun }
83*4882a593Smuzhiyun 
sticon_putcs(struct vc_data * conp,const unsigned short * s,int count,int ypos,int xpos)84*4882a593Smuzhiyun static void sticon_putcs(struct vc_data *conp, const unsigned short *s,
85*4882a593Smuzhiyun 			 int count, int ypos, int xpos)
86*4882a593Smuzhiyun {
87*4882a593Smuzhiyun     if (vga_is_gfx || console_blanked)
88*4882a593Smuzhiyun 	    return;
89*4882a593Smuzhiyun 
90*4882a593Smuzhiyun     if (conp->vc_mode != KD_TEXT)
91*4882a593Smuzhiyun     	    return;
92*4882a593Smuzhiyun 
93*4882a593Smuzhiyun     while (count--) {
94*4882a593Smuzhiyun 	sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++,
95*4882a593Smuzhiyun 		 font_data[conp->vc_num]);
96*4882a593Smuzhiyun     }
97*4882a593Smuzhiyun }
98*4882a593Smuzhiyun 
sticon_cursor(struct vc_data * conp,int mode)99*4882a593Smuzhiyun static void sticon_cursor(struct vc_data *conp, int mode)
100*4882a593Smuzhiyun {
101*4882a593Smuzhiyun     unsigned short car1;
102*4882a593Smuzhiyun 
103*4882a593Smuzhiyun     /* no cursor update if screen is blanked */
104*4882a593Smuzhiyun     if (vga_is_gfx || console_blanked)
105*4882a593Smuzhiyun 	return;
106*4882a593Smuzhiyun 
107*4882a593Smuzhiyun     car1 = conp->vc_screenbuf[conp->state.x + conp->state.y * conp->vc_cols];
108*4882a593Smuzhiyun     switch (mode) {
109*4882a593Smuzhiyun     case CM_ERASE:
110*4882a593Smuzhiyun 	sti_putc(sticon_sti, car1, conp->state.y, conp->state.x,
111*4882a593Smuzhiyun 		 font_data[conp->vc_num]);
112*4882a593Smuzhiyun 	break;
113*4882a593Smuzhiyun     case CM_MOVE:
114*4882a593Smuzhiyun     case CM_DRAW:
115*4882a593Smuzhiyun 	switch (CUR_SIZE(conp->vc_cursor_type)) {
116*4882a593Smuzhiyun 	case CUR_UNDERLINE:
117*4882a593Smuzhiyun 	case CUR_LOWER_THIRD:
118*4882a593Smuzhiyun 	case CUR_LOWER_HALF:
119*4882a593Smuzhiyun 	case CUR_TWO_THIRDS:
120*4882a593Smuzhiyun 	case CUR_BLOCK:
121*4882a593Smuzhiyun 	    sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11),
122*4882a593Smuzhiyun 		     conp->state.y, conp->state.x, font_data[conp->vc_num]);
123*4882a593Smuzhiyun 	    break;
124*4882a593Smuzhiyun 	}
125*4882a593Smuzhiyun 	break;
126*4882a593Smuzhiyun     }
127*4882a593Smuzhiyun }
128*4882a593Smuzhiyun 
sticon_scroll(struct vc_data * conp,unsigned int t,unsigned int b,enum con_scroll dir,unsigned int count)129*4882a593Smuzhiyun static bool sticon_scroll(struct vc_data *conp, unsigned int t,
130*4882a593Smuzhiyun 		unsigned int b, enum con_scroll dir, unsigned int count)
131*4882a593Smuzhiyun {
132*4882a593Smuzhiyun     struct sti_struct *sti = sticon_sti;
133*4882a593Smuzhiyun 
134*4882a593Smuzhiyun     if (vga_is_gfx)
135*4882a593Smuzhiyun         return false;
136*4882a593Smuzhiyun 
137*4882a593Smuzhiyun     sticon_cursor(conp, CM_ERASE);
138*4882a593Smuzhiyun 
139*4882a593Smuzhiyun     switch (dir) {
140*4882a593Smuzhiyun     case SM_UP:
141*4882a593Smuzhiyun 	sti_bmove(sti, t + count, 0, t, 0, b - t - count, conp->vc_cols,
142*4882a593Smuzhiyun 		  font_data[conp->vc_num]);
143*4882a593Smuzhiyun 	sti_clear(sti, b - count, 0, count, conp->vc_cols,
144*4882a593Smuzhiyun 		  conp->vc_video_erase_char, font_data[conp->vc_num]);
145*4882a593Smuzhiyun 	break;
146*4882a593Smuzhiyun 
147*4882a593Smuzhiyun     case SM_DOWN:
148*4882a593Smuzhiyun 	sti_bmove(sti, t, 0, t + count, 0, b - t - count, conp->vc_cols,
149*4882a593Smuzhiyun 		  font_data[conp->vc_num]);
150*4882a593Smuzhiyun 	sti_clear(sti, t, 0, count, conp->vc_cols,
151*4882a593Smuzhiyun 		  conp->vc_video_erase_char, font_data[conp->vc_num]);
152*4882a593Smuzhiyun 	break;
153*4882a593Smuzhiyun     }
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun     return false;
156*4882a593Smuzhiyun }
157*4882a593Smuzhiyun 
sticon_set_def_font(int unit,struct console_font * op)158*4882a593Smuzhiyun static int sticon_set_def_font(int unit, struct console_font *op)
159*4882a593Smuzhiyun {
160*4882a593Smuzhiyun 	if (font_data[unit] != STI_DEF_FONT) {
161*4882a593Smuzhiyun 		if (--FNTREFCOUNT(font_data[unit]) == 0) {
162*4882a593Smuzhiyun 			kfree(font_data[unit]->raw_ptr);
163*4882a593Smuzhiyun 			kfree(font_data[unit]);
164*4882a593Smuzhiyun 		}
165*4882a593Smuzhiyun 		font_data[unit] = STI_DEF_FONT;
166*4882a593Smuzhiyun 	}
167*4882a593Smuzhiyun 
168*4882a593Smuzhiyun 	return 0;
169*4882a593Smuzhiyun }
170*4882a593Smuzhiyun 
sticon_set_font(struct vc_data * vc,struct console_font * op)171*4882a593Smuzhiyun static int sticon_set_font(struct vc_data *vc, struct console_font *op)
172*4882a593Smuzhiyun {
173*4882a593Smuzhiyun 	struct sti_struct *sti = sticon_sti;
174*4882a593Smuzhiyun 	int vc_cols, vc_rows, vc_old_cols, vc_old_rows;
175*4882a593Smuzhiyun 	int unit = vc->vc_num;
176*4882a593Smuzhiyun 	int w = op->width;
177*4882a593Smuzhiyun 	int h = op->height;
178*4882a593Smuzhiyun 	int size, i, bpc, pitch;
179*4882a593Smuzhiyun 	struct sti_rom_font *new_font;
180*4882a593Smuzhiyun 	struct sti_cooked_font *cooked_font;
181*4882a593Smuzhiyun 	unsigned char *data = op->data, *p;
182*4882a593Smuzhiyun 
183*4882a593Smuzhiyun 	if ((w < 6) || (h < 6) || (w > 32) || (h > 32)
184*4882a593Smuzhiyun 	    || (op->charcount != 256 && op->charcount != 512))
185*4882a593Smuzhiyun 		return -EINVAL;
186*4882a593Smuzhiyun 	pitch = ALIGN(w, 8) / 8;
187*4882a593Smuzhiyun 	bpc = pitch * h;
188*4882a593Smuzhiyun 	size = bpc * op->charcount;
189*4882a593Smuzhiyun 
190*4882a593Smuzhiyun 	new_font = kmalloc(sizeof(*new_font) + size, STI_LOWMEM);
191*4882a593Smuzhiyun 	if (!new_font)
192*4882a593Smuzhiyun 		return -ENOMEM;
193*4882a593Smuzhiyun 
194*4882a593Smuzhiyun 	new_font->first_char = 0;
195*4882a593Smuzhiyun 	new_font->last_char = op->charcount - 1;
196*4882a593Smuzhiyun 	new_font->width = w;
197*4882a593Smuzhiyun 	new_font->height = h;
198*4882a593Smuzhiyun 	new_font->font_type = STI_FONT_HPROMAN8;
199*4882a593Smuzhiyun 	new_font->bytes_per_char = bpc;
200*4882a593Smuzhiyun 	new_font->underline_height = 0;
201*4882a593Smuzhiyun 	new_font->underline_pos = 0;
202*4882a593Smuzhiyun 
203*4882a593Smuzhiyun 	cooked_font = kzalloc(sizeof(*cooked_font), GFP_KERNEL);
204*4882a593Smuzhiyun 	if (!cooked_font) {
205*4882a593Smuzhiyun 		kfree(new_font);
206*4882a593Smuzhiyun 		return -ENOMEM;
207*4882a593Smuzhiyun 	}
208*4882a593Smuzhiyun 	cooked_font->raw = new_font;
209*4882a593Smuzhiyun 	cooked_font->raw_ptr = new_font;
210*4882a593Smuzhiyun 	cooked_font->width = w;
211*4882a593Smuzhiyun 	cooked_font->height = h;
212*4882a593Smuzhiyun 	FNTREFCOUNT(cooked_font) = 0;	/* usage counter */
213*4882a593Smuzhiyun 
214*4882a593Smuzhiyun 	p = (unsigned char *) new_font;
215*4882a593Smuzhiyun 	p += sizeof(*new_font);
216*4882a593Smuzhiyun 	for (i = 0; i < op->charcount; i++) {
217*4882a593Smuzhiyun 		memcpy(p, data, bpc);
218*4882a593Smuzhiyun 		data += pitch*32;
219*4882a593Smuzhiyun 		p += bpc;
220*4882a593Smuzhiyun 	}
221*4882a593Smuzhiyun 	FNTCRC(cooked_font) = crc32(0, new_font, size + sizeof(*new_font));
222*4882a593Smuzhiyun 	sti_font_convert_bytemode(sti, cooked_font);
223*4882a593Smuzhiyun 	new_font = cooked_font->raw_ptr;
224*4882a593Smuzhiyun 
225*4882a593Smuzhiyun 	/* check if font is already used by other console */
226*4882a593Smuzhiyun 	for (i = 0; i < MAX_NR_CONSOLES; i++) {
227*4882a593Smuzhiyun 		if (font_data[i] != STI_DEF_FONT
228*4882a593Smuzhiyun 		    && (FNTCRC(font_data[i]) == FNTCRC(cooked_font))) {
229*4882a593Smuzhiyun 			kfree(new_font);
230*4882a593Smuzhiyun 			kfree(cooked_font);
231*4882a593Smuzhiyun 			/* current font is the same as the new one */
232*4882a593Smuzhiyun 			if (i == unit)
233*4882a593Smuzhiyun 				return 0;
234*4882a593Smuzhiyun 			cooked_font = font_data[i];
235*4882a593Smuzhiyun 			new_font = cooked_font->raw_ptr;
236*4882a593Smuzhiyun 			break;
237*4882a593Smuzhiyun 		}
238*4882a593Smuzhiyun 	}
239*4882a593Smuzhiyun 
240*4882a593Smuzhiyun 	/* clear screen with old font: we now may have less rows */
241*4882a593Smuzhiyun 	vc_old_rows = vc->vc_rows;
242*4882a593Smuzhiyun 	vc_old_cols = vc->vc_cols;
243*4882a593Smuzhiyun 	sti_clear(sticon_sti, 0, 0, vc_old_rows, vc_old_cols,
244*4882a593Smuzhiyun 		  vc->vc_video_erase_char, font_data[vc->vc_num]);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	/* delete old font in case it is a user font */
247*4882a593Smuzhiyun 	sticon_set_def_font(unit, NULL);
248*4882a593Smuzhiyun 
249*4882a593Smuzhiyun 	FNTREFCOUNT(cooked_font)++;
250*4882a593Smuzhiyun 	font_data[unit] = cooked_font;
251*4882a593Smuzhiyun 
252*4882a593Smuzhiyun 	vc_cols = sti_onscreen_x(sti) / cooked_font->width;
253*4882a593Smuzhiyun 	vc_rows = sti_onscreen_y(sti) / cooked_font->height;
254*4882a593Smuzhiyun 	vc_resize(vc, vc_cols, vc_rows);
255*4882a593Smuzhiyun 
256*4882a593Smuzhiyun 	/* need to repaint screen if cols & rows are same as old font */
257*4882a593Smuzhiyun 	if (vc_cols == vc_old_cols && vc_rows == vc_old_rows)
258*4882a593Smuzhiyun 		update_screen(vc);
259*4882a593Smuzhiyun 
260*4882a593Smuzhiyun 	return 0;
261*4882a593Smuzhiyun }
262*4882a593Smuzhiyun 
sticon_font_default(struct vc_data * vc,struct console_font * op,char * name)263*4882a593Smuzhiyun static int sticon_font_default(struct vc_data *vc, struct console_font *op, char *name)
264*4882a593Smuzhiyun {
265*4882a593Smuzhiyun 	return sticon_set_def_font(vc->vc_num, op);
266*4882a593Smuzhiyun }
267*4882a593Smuzhiyun 
sticon_font_set(struct vc_data * vc,struct console_font * font,unsigned int flags)268*4882a593Smuzhiyun static int sticon_font_set(struct vc_data *vc, struct console_font *font,
269*4882a593Smuzhiyun 			   unsigned int flags)
270*4882a593Smuzhiyun {
271*4882a593Smuzhiyun 	return sticon_set_font(vc, font);
272*4882a593Smuzhiyun }
273*4882a593Smuzhiyun 
sticon_init(struct vc_data * c,int init)274*4882a593Smuzhiyun static void sticon_init(struct vc_data *c, int init)
275*4882a593Smuzhiyun {
276*4882a593Smuzhiyun     struct sti_struct *sti = sticon_sti;
277*4882a593Smuzhiyun     int vc_cols, vc_rows;
278*4882a593Smuzhiyun 
279*4882a593Smuzhiyun     sti_set(sti, 0, 0, sti_onscreen_y(sti), sti_onscreen_x(sti), 0);
280*4882a593Smuzhiyun     vc_cols = sti_onscreen_x(sti) / sti->font->width;
281*4882a593Smuzhiyun     vc_rows = sti_onscreen_y(sti) / sti->font->height;
282*4882a593Smuzhiyun     c->vc_can_do_color = 1;
283*4882a593Smuzhiyun 
284*4882a593Smuzhiyun     if (init) {
285*4882a593Smuzhiyun 	c->vc_cols = vc_cols;
286*4882a593Smuzhiyun 	c->vc_rows = vc_rows;
287*4882a593Smuzhiyun     } else {
288*4882a593Smuzhiyun 	vc_resize(c, vc_cols, vc_rows);
289*4882a593Smuzhiyun     }
290*4882a593Smuzhiyun }
291*4882a593Smuzhiyun 
sticon_deinit(struct vc_data * c)292*4882a593Smuzhiyun static void sticon_deinit(struct vc_data *c)
293*4882a593Smuzhiyun {
294*4882a593Smuzhiyun     int i;
295*4882a593Smuzhiyun 
296*4882a593Smuzhiyun     /* free memory used by user font */
297*4882a593Smuzhiyun     for (i = 0; i < MAX_NR_CONSOLES; i++)
298*4882a593Smuzhiyun 	sticon_set_def_font(i, NULL);
299*4882a593Smuzhiyun }
300*4882a593Smuzhiyun 
sticon_clear(struct vc_data * conp,int sy,int sx,int height,int width)301*4882a593Smuzhiyun static void sticon_clear(struct vc_data *conp, int sy, int sx, int height,
302*4882a593Smuzhiyun 			 int width)
303*4882a593Smuzhiyun {
304*4882a593Smuzhiyun     if (!height || !width)
305*4882a593Smuzhiyun 	return;
306*4882a593Smuzhiyun 
307*4882a593Smuzhiyun     sti_clear(sticon_sti, sy, sx, height, width,
308*4882a593Smuzhiyun 	      conp->vc_video_erase_char, font_data[conp->vc_num]);
309*4882a593Smuzhiyun }
310*4882a593Smuzhiyun 
sticon_switch(struct vc_data * conp)311*4882a593Smuzhiyun static int sticon_switch(struct vc_data *conp)
312*4882a593Smuzhiyun {
313*4882a593Smuzhiyun     return 1;	/* needs refreshing */
314*4882a593Smuzhiyun }
315*4882a593Smuzhiyun 
sticon_blank(struct vc_data * c,int blank,int mode_switch)316*4882a593Smuzhiyun static int sticon_blank(struct vc_data *c, int blank, int mode_switch)
317*4882a593Smuzhiyun {
318*4882a593Smuzhiyun     if (blank == 0) {
319*4882a593Smuzhiyun 	if (mode_switch)
320*4882a593Smuzhiyun 	    vga_is_gfx = 0;
321*4882a593Smuzhiyun 	return 1;
322*4882a593Smuzhiyun     }
323*4882a593Smuzhiyun     sti_clear(sticon_sti, 0, 0, c->vc_rows, c->vc_cols, BLANK,
324*4882a593Smuzhiyun 	      font_data[c->vc_num]);
325*4882a593Smuzhiyun     if (mode_switch)
326*4882a593Smuzhiyun 	vga_is_gfx = 1;
327*4882a593Smuzhiyun     return 1;
328*4882a593Smuzhiyun }
329*4882a593Smuzhiyun 
sticon_build_attr(struct vc_data * conp,u8 color,enum vc_intensity intens,bool blink,bool underline,bool reverse,bool italic)330*4882a593Smuzhiyun static u8 sticon_build_attr(struct vc_data *conp, u8 color,
331*4882a593Smuzhiyun 			    enum vc_intensity intens,
332*4882a593Smuzhiyun 			    bool blink, bool underline, bool reverse,
333*4882a593Smuzhiyun 			    bool italic)
334*4882a593Smuzhiyun {
335*4882a593Smuzhiyun 	u8 fg = color & 7;
336*4882a593Smuzhiyun 	u8 bg = (color & 0x70) >> 4;
337*4882a593Smuzhiyun 
338*4882a593Smuzhiyun 	if (reverse)
339*4882a593Smuzhiyun 		return (fg << 3) | bg;
340*4882a593Smuzhiyun 	else
341*4882a593Smuzhiyun 		return (bg << 3) | fg;
342*4882a593Smuzhiyun }
343*4882a593Smuzhiyun 
sticon_invert_region(struct vc_data * conp,u16 * p,int count)344*4882a593Smuzhiyun static void sticon_invert_region(struct vc_data *conp, u16 *p, int count)
345*4882a593Smuzhiyun {
346*4882a593Smuzhiyun     int col = 1; /* vga_can_do_color; */
347*4882a593Smuzhiyun 
348*4882a593Smuzhiyun     while (count--) {
349*4882a593Smuzhiyun 	u16 a = scr_readw(p);
350*4882a593Smuzhiyun 
351*4882a593Smuzhiyun 	if (col)
352*4882a593Smuzhiyun 		a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4);
353*4882a593Smuzhiyun 	else
354*4882a593Smuzhiyun 		a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700;
355*4882a593Smuzhiyun 
356*4882a593Smuzhiyun 	scr_writew(a, p++);
357*4882a593Smuzhiyun     }
358*4882a593Smuzhiyun }
359*4882a593Smuzhiyun 
360*4882a593Smuzhiyun static const struct consw sti_con = {
361*4882a593Smuzhiyun 	.owner			= THIS_MODULE,
362*4882a593Smuzhiyun 	.con_startup		= sticon_startup,
363*4882a593Smuzhiyun 	.con_init		= sticon_init,
364*4882a593Smuzhiyun 	.con_deinit		= sticon_deinit,
365*4882a593Smuzhiyun 	.con_clear		= sticon_clear,
366*4882a593Smuzhiyun 	.con_putc		= sticon_putc,
367*4882a593Smuzhiyun 	.con_putcs		= sticon_putcs,
368*4882a593Smuzhiyun 	.con_cursor		= sticon_cursor,
369*4882a593Smuzhiyun 	.con_scroll		= sticon_scroll,
370*4882a593Smuzhiyun 	.con_switch		= sticon_switch,
371*4882a593Smuzhiyun 	.con_blank		= sticon_blank,
372*4882a593Smuzhiyun 	.con_font_set		= sticon_font_set,
373*4882a593Smuzhiyun 	.con_font_default	= sticon_font_default,
374*4882a593Smuzhiyun 	.con_build_attr		= sticon_build_attr,
375*4882a593Smuzhiyun 	.con_invert_region	= sticon_invert_region,
376*4882a593Smuzhiyun };
377*4882a593Smuzhiyun 
378*4882a593Smuzhiyun 
379*4882a593Smuzhiyun 
sticonsole_init(void)380*4882a593Smuzhiyun static int __init sticonsole_init(void)
381*4882a593Smuzhiyun {
382*4882a593Smuzhiyun     int err, i;
383*4882a593Smuzhiyun 
384*4882a593Smuzhiyun     /* already initialized ? */
385*4882a593Smuzhiyun     if (sticon_sti)
386*4882a593Smuzhiyun 	 return 0;
387*4882a593Smuzhiyun 
388*4882a593Smuzhiyun     sticon_sti = sti_get_rom(0);
389*4882a593Smuzhiyun     if (!sticon_sti)
390*4882a593Smuzhiyun 	return -ENODEV;
391*4882a593Smuzhiyun 
392*4882a593Smuzhiyun     for (i = 0; i < MAX_NR_CONSOLES; i++)
393*4882a593Smuzhiyun 	font_data[i] = STI_DEF_FONT;
394*4882a593Smuzhiyun 
395*4882a593Smuzhiyun     pr_info("sticon: Initializing STI text console.\n");
396*4882a593Smuzhiyun     console_lock();
397*4882a593Smuzhiyun     err = do_take_over_console(&sti_con, 0, MAX_NR_CONSOLES - 1,
398*4882a593Smuzhiyun 		PAGE0->mem_cons.cl_class != CL_DUPLEX);
399*4882a593Smuzhiyun     console_unlock();
400*4882a593Smuzhiyun 
401*4882a593Smuzhiyun     return err;
402*4882a593Smuzhiyun }
403*4882a593Smuzhiyun 
404*4882a593Smuzhiyun module_init(sticonsole_init);
405*4882a593Smuzhiyun MODULE_LICENSE("GPL");
406