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 int sticon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
158 struct sti_struct
*sti
= sticon_sti
;
163 sticon_cursor(conp
, CM_ERASE
);
167 sti_bmove(sti
, t
+ count
, 0, t
, 0, b
- t
- count
, conp
->vc_cols
);
168 sti_clear(sti
, b
- count
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
172 sti_bmove(sti
, t
, 0, t
+ count
, 0, b
- t
- count
, conp
->vc_cols
);
173 sti_clear(sti
, t
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
180 static void sticon_init(struct vc_data
*c
, int init
)
182 struct sti_struct
*sti
= sticon_sti
;
183 int vc_cols
, vc_rows
;
185 sti_set(sti
, 0, 0, sti_onscreen_y(sti
), sti_onscreen_x(sti
), 0);
186 vc_cols
= sti_onscreen_x(sti
) / sti
->font_width
;
187 vc_rows
= sti_onscreen_y(sti
) / sti
->font_height
;
188 c
->vc_can_do_color
= 1;
191 c
->vc_cols
= vc_cols
;
192 c
->vc_rows
= vc_rows
;
194 /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
195 /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
196 vc_resize(c
, vc_cols
, vc_rows
);
197 /* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
201 static void sticon_deinit(struct vc_data
*c
)
205 static void sticon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
,
208 if (!height
|| !width
)
211 sti_clear(sticon_sti
, sy
, sx
, height
, width
, conp
->vc_video_erase_char
);
214 static int sticon_switch(struct vc_data
*conp
)
216 return 1; /* needs refreshing */
219 static int sticon_set_origin(struct vc_data
*conp
)
224 static int sticon_blank(struct vc_data
*c
, int blank
, int mode_switch
)
231 sticon_set_origin(c
);
232 sti_clear(sticon_sti
, 0,0, c
->vc_rows
, c
->vc_cols
, BLANK
);
238 static u16
*sticon_screen_pos(struct vc_data
*conp
, int offset
)
243 if (conp
->vc_num
!= fg_console
|| !softback_lines
)
244 return (u16
*)(conp
->vc_origin
+ offset
);
245 line
= offset
/ conp
->vc_size_row
;
246 if (line
>= softback_lines
)
247 return (u16
*)(conp
->vc_origin
+ offset
- softback_lines
* conp
->vc_size_row
);
248 p
= softback_curr
+ offset
;
249 if (p
>= softback_end
)
250 p
+= softback_buf
- softback_end
;
254 static unsigned long sticon_getxy(struct vc_data
*conp
, unsigned long pos
,
259 if (pos
>= conp
->vc_origin
&& pos
< conp
->vc_scr_end
) {
260 unsigned long offset
= (pos
- conp
->vc_origin
) / 2;
262 x
= offset
% conp
->vc_cols
;
263 y
= offset
/ conp
->vc_cols
;
264 if (conp
->vc_num
== fg_console
)
266 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
267 } else if (conp
->vc_num
== fg_console
&& softback_lines
) {
268 unsigned long offset
= pos
- softback_curr
;
270 if (pos
< softback_curr
)
271 offset
+= softback_end
- softback_buf
;
273 x
= offset
% conp
->vc_cols
;
274 y
= offset
/ conp
->vc_cols
;
275 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
276 if (ret
== softback_end
)
278 if (ret
== softback_in
)
279 ret
= conp
->vc_origin
;
281 /* Should not happen */
283 ret
= conp
->vc_origin
;
290 static u8
sticon_build_attr(struct vc_data
*conp
, u8 color
, u8 intens
,
291 u8 blink
, u8 underline
, u8 reverse
, u8 italic
)
293 u8 attr
= ((color
& 0x70) >> 1) | ((color
& 7));
296 color
= ((color
>> 3) & 0x7) | ((color
& 0x7) << 3);
302 static void sticon_invert_region(struct vc_data
*conp
, u16
*p
, int count
)
304 int col
= 1; /* vga_can_do_color; */
307 u16 a
= scr_readw(p
);
310 a
= ((a
) & 0x88ff) | (((a
) & 0x7000) >> 4) | (((a
) & 0x0700) << 4);
312 a
= ((a
& 0x0700) == 0x0100) ? 0x7000 : 0x7700;
318 static void sticon_save_screen(struct vc_data
*conp
)
322 static const struct consw sti_con
= {
323 .owner
= THIS_MODULE
,
324 .con_startup
= sticon_startup
,
325 .con_init
= sticon_init
,
326 .con_deinit
= sticon_deinit
,
327 .con_clear
= sticon_clear
,
328 .con_putc
= sticon_putc
,
329 .con_putcs
= sticon_putcs
,
330 .con_cursor
= sticon_cursor
,
331 .con_scroll
= sticon_scroll
,
332 .con_switch
= sticon_switch
,
333 .con_blank
= sticon_blank
,
334 .con_set_origin
= sticon_set_origin
,
335 .con_save_screen
= sticon_save_screen
,
336 .con_build_attr
= sticon_build_attr
,
337 .con_invert_region
= sticon_invert_region
,
338 .con_screen_pos
= sticon_screen_pos
,
339 .con_getxy
= sticon_getxy
,
344 static int __init
sticonsole_init(void)
347 /* already initialized ? */
351 sticon_sti
= sti_get_rom(0);
355 if (conswitchp
== &dummy_con
) {
356 printk(KERN_INFO
"sticon: Initializing STI text console.\n");
358 err
= do_take_over_console(&sti_con
, 0, MAX_NR_CONSOLES
- 1, 1);
365 module_init(sticonsole_init
);
366 MODULE_LICENSE("GPL");