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 "../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 int sticon_set_palette(struct vc_data
*c
, unsigned char *table
)
87 static void sticon_putc(struct vc_data
*conp
, int c
, int ypos
, int xpos
)
89 int redraw_cursor
= 0;
91 if (vga_is_gfx
|| console_blanked
)
94 if (conp
->vc_mode
!= KD_TEXT
)
97 if ((p
->cursor_x
== xpos
) && (p
->cursor_y
== ypos
)) {
103 sti_putc(sticon_sti
, c
, ypos
, xpos
);
106 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
109 static void sticon_putcs(struct vc_data
*conp
, const unsigned short *s
,
110 int count
, int ypos
, int xpos
)
112 int redraw_cursor
= 0;
114 if (vga_is_gfx
|| console_blanked
)
117 if (conp
->vc_mode
!= KD_TEXT
)
121 if ((p
->cursor_y
== ypos
) && (xpos
<= p
->cursor_x
) &&
122 (p
->cursor_x
< (xpos
+ count
))) {
129 sti_putc(sticon_sti
, scr_readw(s
++), ypos
, xpos
++);
133 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
136 static void sticon_cursor(struct vc_data
*conp
, int mode
)
140 car1
= conp
->vc_screenbuf
[conp
->vc_x
+ conp
->vc_y
* conp
->vc_cols
];
143 sti_putc(sticon_sti
, car1
, conp
->vc_y
, conp
->vc_x
);
147 switch (conp
->vc_cursor_type
& 0x0f) {
149 case CUR_LOWER_THIRD
:
153 sti_putc(sticon_sti
, (car1
& 255) + (0 << 8) + (7 << 11),
154 conp
->vc_y
, conp
->vc_x
);
161 static int sticon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
163 struct sti_struct
*sti
= sticon_sti
;
168 sticon_cursor(conp
, CM_ERASE
);
172 sti_bmove(sti
, t
+ count
, 0, t
, 0, b
- t
- count
, conp
->vc_cols
);
173 sti_clear(sti
, b
- count
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
177 sti_bmove(sti
, t
, 0, t
+ count
, 0, b
- t
- count
, conp
->vc_cols
);
178 sti_clear(sti
, t
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
185 static void sticon_bmove(struct vc_data
*conp
, int sy
, int sx
,
186 int dy
, int dx
, int height
, int width
)
188 if (!width
|| !height
)
191 if (((sy
<= p
->cursor_y
) && (p
->cursor_y
< sy
+height
) &&
192 (sx
<= p
->cursor_x
) && (p
->cursor_x
< sx
+width
)) ||
193 ((dy
<= p
->cursor_y
) && (p
->cursor_y
< dy
+height
) &&
194 (dx
<= p
->cursor_x
) && (p
->cursor_x
< dx
+width
)))
195 sticon_cursor(p
, CM_ERASE
/*|CM_SOFTBACK*/);
198 sti_bmove(sticon_sti
, sy
, sx
, dy
, dx
, height
, width
);
201 static void sticon_init(struct vc_data
*c
, int init
)
203 struct sti_struct
*sti
= sticon_sti
;
204 int vc_cols
, vc_rows
;
206 sti_set(sti
, 0, 0, sti_onscreen_y(sti
), sti_onscreen_x(sti
), 0);
207 vc_cols
= sti_onscreen_x(sti
) / sti
->font_width
;
208 vc_rows
= sti_onscreen_y(sti
) / sti
->font_height
;
209 c
->vc_can_do_color
= 1;
212 c
->vc_cols
= vc_cols
;
213 c
->vc_rows
= vc_rows
;
215 /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
216 /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
217 vc_resize(c
, vc_cols
, vc_rows
);
218 /* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
222 static void sticon_deinit(struct vc_data
*c
)
226 static void sticon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
,
229 if (!height
|| !width
)
232 sti_clear(sticon_sti
, sy
, sx
, height
, width
, conp
->vc_video_erase_char
);
235 static int sticon_switch(struct vc_data
*conp
)
237 return 1; /* needs refreshing */
240 static int sticon_set_origin(struct vc_data
*conp
)
245 static int sticon_blank(struct vc_data
*c
, int blank
, int mode_switch
)
252 sticon_set_origin(c
);
253 sti_clear(sticon_sti
, 0,0, c
->vc_rows
, c
->vc_cols
, BLANK
);
259 static int sticon_scrolldelta(struct vc_data
*conp
, int lines
)
264 static u16
*sticon_screen_pos(struct vc_data
*conp
, int offset
)
269 if (conp
->vc_num
!= fg_console
|| !softback_lines
)
270 return (u16
*)(conp
->vc_origin
+ offset
);
271 line
= offset
/ conp
->vc_size_row
;
272 if (line
>= softback_lines
)
273 return (u16
*)(conp
->vc_origin
+ offset
- softback_lines
* conp
->vc_size_row
);
274 p
= softback_curr
+ offset
;
275 if (p
>= softback_end
)
276 p
+= softback_buf
- softback_end
;
280 static unsigned long sticon_getxy(struct vc_data
*conp
, unsigned long pos
,
285 if (pos
>= conp
->vc_origin
&& pos
< conp
->vc_scr_end
) {
286 unsigned long offset
= (pos
- conp
->vc_origin
) / 2;
288 x
= offset
% conp
->vc_cols
;
289 y
= offset
/ conp
->vc_cols
;
290 if (conp
->vc_num
== fg_console
)
292 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
293 } else if (conp
->vc_num
== fg_console
&& softback_lines
) {
294 unsigned long offset
= pos
- softback_curr
;
296 if (pos
< softback_curr
)
297 offset
+= softback_end
- softback_buf
;
299 x
= offset
% conp
->vc_cols
;
300 y
= offset
/ conp
->vc_cols
;
301 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
302 if (ret
== softback_end
)
304 if (ret
== softback_in
)
305 ret
= conp
->vc_origin
;
307 /* Should not happen */
309 ret
= conp
->vc_origin
;
316 static u8
sticon_build_attr(struct vc_data
*conp
, u8 color
, u8 intens
,
317 u8 blink
, u8 underline
, u8 reverse
, u8 italic
)
319 u8 attr
= ((color
& 0x70) >> 1) | ((color
& 7));
322 color
= ((color
>> 3) & 0x7) | ((color
& 0x7) << 3);
328 static void sticon_invert_region(struct vc_data
*conp
, u16
*p
, int count
)
330 int col
= 1; /* vga_can_do_color; */
333 u16 a
= scr_readw(p
);
336 a
= ((a
) & 0x88ff) | (((a
) & 0x7000) >> 4) | (((a
) & 0x0700) << 4);
338 a
= ((a
& 0x0700) == 0x0100) ? 0x7000 : 0x7700;
344 static void sticon_save_screen(struct vc_data
*conp
)
348 static const struct consw sti_con
= {
349 .owner
= THIS_MODULE
,
350 .con_startup
= sticon_startup
,
351 .con_init
= sticon_init
,
352 .con_deinit
= sticon_deinit
,
353 .con_clear
= sticon_clear
,
354 .con_putc
= sticon_putc
,
355 .con_putcs
= sticon_putcs
,
356 .con_cursor
= sticon_cursor
,
357 .con_scroll
= sticon_scroll
,
358 .con_bmove
= sticon_bmove
,
359 .con_switch
= sticon_switch
,
360 .con_blank
= sticon_blank
,
361 .con_set_palette
= sticon_set_palette
,
362 .con_scrolldelta
= sticon_scrolldelta
,
363 .con_set_origin
= sticon_set_origin
,
364 .con_save_screen
= sticon_save_screen
,
365 .con_build_attr
= sticon_build_attr
,
366 .con_invert_region
= sticon_invert_region
,
367 .con_screen_pos
= sticon_screen_pos
,
368 .con_getxy
= sticon_getxy
,
373 static int __init
sticonsole_init(void)
376 /* already initialized ? */
380 sticon_sti
= sti_get_rom(0);
384 if (conswitchp
== &dummy_con
) {
385 printk(KERN_INFO
"sticon: Initializing STI text console.\n");
387 err
= do_take_over_console(&sti_con
, 0, MAX_NR_CONSOLES
- 1, 1);
394 module_init(sticonsole_init
);
395 MODULE_LICENSE("GPL");