2 * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware
4 * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org>
5 * Copyright (C) 2002 Helge Deller <deller@gmx.de>
7 * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c,
10 * Created 28 Sep 1997 by Geert Uytterhoeven
11 * Rewritten by Martin Mares <mj@ucw.cz>, July 1998
12 * Copyright (C) 1991, 1992 Linus Torvalds
14 * Copyright (C) 1995 Geert Uytterhoeven
15 * Copyright (C) 1993 Bjoern Brauel
17 * Copyright (C) 1993 Hamish Macdonald
19 * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk]
21 * with work by William Rucklidge (wjr@cs.cornell.edu)
23 * Jes Sorensen (jds@kom.auc.dk)
25 * with work by Guenther Kelleter
28 * Emmanuel Marty (core@ggi-project.org)
29 * Jakub Jelinek (jj@ultra.linux.cz)
30 * Martin Mares <mj@ucw.cz>
32 * This file is subject to the terms and conditions of the GNU General Public
33 * License. See the file COPYING in the main directory of this archive for
38 #include <linux/init.h>
39 #include <linux/kernel.h>
40 #include <linux/console.h>
41 #include <linux/errno.h>
42 #include <linux/vt_kern.h>
44 #include <linux/selection.h>
45 #include <linux/module.h>
49 #include "../fbdev/sticore.h"
51 /* switching to graphics mode */
53 static int vga_is_gfx
;
55 /* this is the sti_struct used for this console */
56 static struct sti_struct
*sticon_sti
;
58 /* Software scrollback */
59 static unsigned long softback_buf
, softback_curr
;
60 static unsigned long softback_in
;
61 static unsigned long /* softback_top, */ softback_end
;
62 static int softback_lines
;
65 static int cursor_drawn
;
66 #define CURSOR_DRAW_DELAY (1)
67 #define DEFAULT_CURSOR_BLINK_RATE (20)
69 static int vbl_cursor_cnt
;
71 static inline void cursor_undrawn(void)
77 static const char *sticon_startup(void)
82 static void sticon_putc(struct vc_data
*conp
, int c
, int ypos
, int xpos
)
84 int redraw_cursor
= 0;
86 if (vga_is_gfx
|| console_blanked
)
89 if (conp
->vc_mode
!= KD_TEXT
)
92 if ((p
->cursor_x
== xpos
) && (p
->cursor_y
== ypos
)) {
98 sti_putc(sticon_sti
, c
, ypos
, xpos
);
101 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
104 static void sticon_putcs(struct vc_data
*conp
, const unsigned short *s
,
105 int count
, int ypos
, int xpos
)
107 int redraw_cursor
= 0;
109 if (vga_is_gfx
|| console_blanked
)
112 if (conp
->vc_mode
!= KD_TEXT
)
116 if ((p
->cursor_y
== ypos
) && (xpos
<= p
->cursor_x
) &&
117 (p
->cursor_x
< (xpos
+ count
))) {
124 sti_putc(sticon_sti
, scr_readw(s
++), ypos
, xpos
++);
128 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
131 static void sticon_cursor(struct vc_data
*conp
, int mode
)
135 car1
= conp
->vc_screenbuf
[conp
->vc_x
+ conp
->vc_y
* conp
->vc_cols
];
138 sti_putc(sticon_sti
, car1
, conp
->vc_y
, conp
->vc_x
);
142 switch (conp
->vc_cursor_type
& 0x0f) {
144 case CUR_LOWER_THIRD
:
148 sti_putc(sticon_sti
, (car1
& 255) + (0 << 8) + (7 << 11),
149 conp
->vc_y
, conp
->vc_x
);
156 static bool sticon_scroll(struct vc_data
*conp
, unsigned int t
,
157 unsigned int b
, enum con_scroll dir
, unsigned int count
)
159 struct sti_struct
*sti
= sticon_sti
;
164 sticon_cursor(conp
, CM_ERASE
);
168 sti_bmove(sti
, t
+ count
, 0, t
, 0, b
- t
- count
, conp
->vc_cols
);
169 sti_clear(sti
, b
- count
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
173 sti_bmove(sti
, t
, 0, t
+ count
, 0, b
- t
- count
, conp
->vc_cols
);
174 sti_clear(sti
, t
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
181 static void sticon_init(struct vc_data
*c
, int init
)
183 struct sti_struct
*sti
= sticon_sti
;
184 int vc_cols
, vc_rows
;
186 sti_set(sti
, 0, 0, sti_onscreen_y(sti
), sti_onscreen_x(sti
), 0);
187 vc_cols
= sti_onscreen_x(sti
) / sti
->font_width
;
188 vc_rows
= sti_onscreen_y(sti
) / sti
->font_height
;
189 c
->vc_can_do_color
= 1;
192 c
->vc_cols
= vc_cols
;
193 c
->vc_rows
= vc_rows
;
195 /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
196 /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
197 vc_resize(c
, vc_cols
, vc_rows
);
198 /* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
202 static void sticon_deinit(struct vc_data
*c
)
206 static void sticon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
,
209 if (!height
|| !width
)
212 sti_clear(sticon_sti
, sy
, sx
, height
, width
, conp
->vc_video_erase_char
);
215 static int sticon_switch(struct vc_data
*conp
)
217 return 1; /* needs refreshing */
220 static int sticon_set_origin(struct vc_data
*conp
)
225 static int sticon_blank(struct vc_data
*c
, int blank
, int mode_switch
)
232 sticon_set_origin(c
);
233 sti_clear(sticon_sti
, 0,0, c
->vc_rows
, c
->vc_cols
, BLANK
);
239 static u16
*sticon_screen_pos(struct vc_data
*conp
, int offset
)
244 if (conp
->vc_num
!= fg_console
|| !softback_lines
)
245 return (u16
*)(conp
->vc_origin
+ offset
);
246 line
= offset
/ conp
->vc_size_row
;
247 if (line
>= softback_lines
)
248 return (u16
*)(conp
->vc_origin
+ offset
- softback_lines
* conp
->vc_size_row
);
249 p
= softback_curr
+ offset
;
250 if (p
>= softback_end
)
251 p
+= softback_buf
- softback_end
;
255 static unsigned long sticon_getxy(struct vc_data
*conp
, unsigned long pos
,
260 if (pos
>= conp
->vc_origin
&& pos
< conp
->vc_scr_end
) {
261 unsigned long offset
= (pos
- conp
->vc_origin
) / 2;
263 x
= offset
% conp
->vc_cols
;
264 y
= offset
/ conp
->vc_cols
;
265 if (conp
->vc_num
== fg_console
)
267 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
268 } else if (conp
->vc_num
== fg_console
&& softback_lines
) {
269 unsigned long offset
= pos
- softback_curr
;
271 if (pos
< softback_curr
)
272 offset
+= softback_end
- softback_buf
;
274 x
= offset
% conp
->vc_cols
;
275 y
= offset
/ conp
->vc_cols
;
276 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
277 if (ret
== softback_end
)
279 if (ret
== softback_in
)
280 ret
= conp
->vc_origin
;
282 /* Should not happen */
284 ret
= conp
->vc_origin
;
291 static u8
sticon_build_attr(struct vc_data
*conp
, u8 color
, u8 intens
,
292 u8 blink
, u8 underline
, u8 reverse
, u8 italic
)
294 u8 attr
= ((color
& 0x70) >> 1) | ((color
& 7));
297 color
= ((color
>> 3) & 0x7) | ((color
& 0x7) << 3);
303 static void sticon_invert_region(struct vc_data
*conp
, u16
*p
, int count
)
305 int col
= 1; /* vga_can_do_color; */
308 u16 a
= scr_readw(p
);
311 a
= ((a
) & 0x88ff) | (((a
) & 0x7000) >> 4) | (((a
) & 0x0700) << 4);
313 a
= ((a
& 0x0700) == 0x0100) ? 0x7000 : 0x7700;
319 static void sticon_save_screen(struct vc_data
*conp
)
323 static const struct consw sti_con
= {
324 .owner
= THIS_MODULE
,
325 .con_startup
= sticon_startup
,
326 .con_init
= sticon_init
,
327 .con_deinit
= sticon_deinit
,
328 .con_clear
= sticon_clear
,
329 .con_putc
= sticon_putc
,
330 .con_putcs
= sticon_putcs
,
331 .con_cursor
= sticon_cursor
,
332 .con_scroll
= sticon_scroll
,
333 .con_switch
= sticon_switch
,
334 .con_blank
= sticon_blank
,
335 .con_set_origin
= sticon_set_origin
,
336 .con_save_screen
= sticon_save_screen
,
337 .con_build_attr
= sticon_build_attr
,
338 .con_invert_region
= sticon_invert_region
,
339 .con_screen_pos
= sticon_screen_pos
,
340 .con_getxy
= sticon_getxy
,
345 static int __init
sticonsole_init(void)
348 /* already initialized ? */
352 sticon_sti
= sti_get_rom(0);
356 if (conswitchp
== &dummy_con
) {
357 printk(KERN_INFO
"sticon: Initializing STI text console.\n");
359 err
= do_take_over_console(&sti_con
, 0, MAX_NR_CONSOLES
- 1, 1);
366 module_init(sticonsole_init
);
367 MODULE_LICENSE("GPL");