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