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/tty.h>
41 #include <linux/console.h>
42 #include <linux/errno.h>
43 #include <linux/vt_kern.h>
45 #include <linux/selection.h>
46 #include <linux/module.h>
50 #include "../sticore.h"
52 /* switching to graphics mode */
54 static int vga_is_gfx
;
56 /* this is the sti_struct used for this console */
57 static struct sti_struct
*sticon_sti
;
59 /* Software scrollback */
60 static unsigned long softback_buf
, softback_curr
;
61 static unsigned long softback_in
;
62 static unsigned long /* softback_top, */ softback_end
;
63 static int softback_lines
;
66 static int cursor_drawn
;
67 #define CURSOR_DRAW_DELAY (1)
68 #define DEFAULT_CURSOR_BLINK_RATE (20)
70 static int vbl_cursor_cnt
;
72 static inline void cursor_undrawn(void)
78 static const char *__init
sticon_startup(void)
83 static int sticon_set_palette(struct vc_data
*c
, unsigned char *table
)
88 static void sticon_putc(struct vc_data
*conp
, int c
, int ypos
, int xpos
)
90 int redraw_cursor
= 0;
92 if (vga_is_gfx
|| console_blanked
)
95 if (conp
->vc_mode
!= KD_TEXT
)
98 if ((p
->cursor_x
== xpos
) && (p
->cursor_y
== ypos
)) {
104 sti_putc(sticon_sti
, c
, ypos
, xpos
);
107 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
110 static void sticon_putcs(struct vc_data
*conp
, const unsigned short *s
,
111 int count
, int ypos
, int xpos
)
113 int redraw_cursor
= 0;
115 if (vga_is_gfx
|| console_blanked
)
118 if (conp
->vc_mode
!= KD_TEXT
)
122 if ((p
->cursor_y
== ypos
) && (xpos
<= p
->cursor_x
) &&
123 (p
->cursor_x
< (xpos
+ count
))) {
130 sti_putc(sticon_sti
, scr_readw(s
++), ypos
, xpos
++);
134 vbl_cursor_cnt
= CURSOR_DRAW_DELAY
;
137 static void sticon_cursor(struct vc_data
*conp
, int mode
)
141 car1
= conp
->vc_screenbuf
[conp
->vc_x
+ conp
->vc_y
* conp
->vc_cols
];
144 sti_putc(sticon_sti
, car1
, conp
->vc_y
, conp
->vc_x
);
148 switch (conp
->vc_cursor_type
& 0x0f) {
150 case CUR_LOWER_THIRD
:
154 sti_putc(sticon_sti
, (car1
& 255) + (0 << 8) + (7 << 11),
155 conp
->vc_y
, conp
->vc_x
);
162 static int sticon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
164 struct sti_struct
*sti
= sticon_sti
;
169 sticon_cursor(conp
, CM_ERASE
);
173 sti_bmove(sti
, t
+ count
, 0, t
, 0, b
- t
- count
, conp
->vc_cols
);
174 sti_clear(sti
, b
- count
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
178 sti_bmove(sti
, t
, 0, t
+ count
, 0, b
- t
- count
, conp
->vc_cols
);
179 sti_clear(sti
, t
, 0, count
, conp
->vc_cols
, conp
->vc_video_erase_char
);
186 static void sticon_bmove(struct vc_data
*conp
, int sy
, int sx
,
187 int dy
, int dx
, int height
, int width
)
189 if (!width
|| !height
)
192 if (((sy
<= p
->cursor_y
) && (p
->cursor_y
< sy
+height
) &&
193 (sx
<= p
->cursor_x
) && (p
->cursor_x
< sx
+width
)) ||
194 ((dy
<= p
->cursor_y
) && (p
->cursor_y
< dy
+height
) &&
195 (dx
<= p
->cursor_x
) && (p
->cursor_x
< dx
+width
)))
196 sticon_cursor(p
, CM_ERASE
/*|CM_SOFTBACK*/);
199 sti_bmove(sticon_sti
, sy
, sx
, dy
, dx
, height
, width
);
202 static void sticon_init(struct vc_data
*c
, int init
)
204 struct sti_struct
*sti
= sticon_sti
;
205 int vc_cols
, vc_rows
;
207 sti_set(sti
, 0, 0, sti_onscreen_y(sti
), sti_onscreen_x(sti
), 0);
208 vc_cols
= sti_onscreen_x(sti
) / sti
->font_width
;
209 vc_rows
= sti_onscreen_y(sti
) / sti
->font_height
;
210 c
->vc_can_do_color
= 1;
213 c
->vc_cols
= vc_cols
;
214 c
->vc_rows
= vc_rows
;
216 /* vc_rows = (c->vc_rows > vc_rows) ? vc_rows : c->vc_rows; */
217 /* vc_cols = (c->vc_cols > vc_cols) ? vc_cols : c->vc_cols; */
218 vc_resize(c
, vc_cols
, vc_rows
);
219 /* vc_resize_con(vc_rows, vc_cols, c->vc_num); */
223 static void sticon_deinit(struct vc_data
*c
)
227 static void sticon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
,
230 if (!height
|| !width
)
233 sti_clear(sticon_sti
, sy
, sx
, height
, width
, conp
->vc_video_erase_char
);
236 static int sticon_switch(struct vc_data
*conp
)
238 return 1; /* needs refreshing */
241 static int sticon_set_origin(struct vc_data
*conp
)
246 static int sticon_blank(struct vc_data
*c
, int blank
, int mode_switch
)
253 sticon_set_origin(c
);
254 sti_clear(sticon_sti
, 0,0, c
->vc_rows
, c
->vc_cols
, BLANK
);
260 static int sticon_scrolldelta(struct vc_data
*conp
, int lines
)
265 static u16
*sticon_screen_pos(struct vc_data
*conp
, int offset
)
270 if (conp
->vc_num
!= fg_console
|| !softback_lines
)
271 return (u16
*)(conp
->vc_origin
+ offset
);
272 line
= offset
/ conp
->vc_size_row
;
273 if (line
>= softback_lines
)
274 return (u16
*)(conp
->vc_origin
+ offset
- softback_lines
* conp
->vc_size_row
);
275 p
= softback_curr
+ offset
;
276 if (p
>= softback_end
)
277 p
+= softback_buf
- softback_end
;
281 static unsigned long sticon_getxy(struct vc_data
*conp
, unsigned long pos
,
286 if (pos
>= conp
->vc_origin
&& pos
< conp
->vc_scr_end
) {
287 unsigned long offset
= (pos
- conp
->vc_origin
) / 2;
289 x
= offset
% conp
->vc_cols
;
290 y
= offset
/ conp
->vc_cols
;
291 if (conp
->vc_num
== fg_console
)
293 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
294 } else if (conp
->vc_num
== fg_console
&& softback_lines
) {
295 unsigned long offset
= pos
- softback_curr
;
297 if (pos
< softback_curr
)
298 offset
+= softback_end
- softback_buf
;
300 x
= offset
% conp
->vc_cols
;
301 y
= offset
/ conp
->vc_cols
;
302 ret
= pos
+ (conp
->vc_cols
- x
) * 2;
303 if (ret
== softback_end
)
305 if (ret
== softback_in
)
306 ret
= conp
->vc_origin
;
308 /* Should not happen */
310 ret
= conp
->vc_origin
;
317 static u8
sticon_build_attr(struct vc_data
*conp
, u8 color
, u8 intens
,
318 u8 blink
, u8 underline
, u8 reverse
)
320 u8 attr
= ((color
& 0x70) >> 1) | ((color
& 7));
323 color
= ((color
>> 3) & 0x7) | ((color
& 0x7) << 3);
329 static void sticon_invert_region(struct vc_data
*conp
, u16
*p
, int count
)
331 int col
= 1; /* vga_can_do_color; */
334 u16 a
= scr_readw(p
);
337 a
= ((a
) & 0x88ff) | (((a
) & 0x7000) >> 4) | (((a
) & 0x0700) << 4);
339 a
= ((a
& 0x0700) == 0x0100) ? 0x7000 : 0x7700;
345 static void sticon_save_screen(struct vc_data
*conp
)
349 static struct consw sti_con
= {
350 .owner
= THIS_MODULE
,
351 .con_startup
= sticon_startup
,
352 .con_init
= sticon_init
,
353 .con_deinit
= sticon_deinit
,
354 .con_clear
= sticon_clear
,
355 .con_putc
= sticon_putc
,
356 .con_putcs
= sticon_putcs
,
357 .con_cursor
= sticon_cursor
,
358 .con_scroll
= sticon_scroll
,
359 .con_bmove
= sticon_bmove
,
360 .con_switch
= sticon_switch
,
361 .con_blank
= sticon_blank
,
362 .con_set_palette
= sticon_set_palette
,
363 .con_scrolldelta
= sticon_scrolldelta
,
364 .con_set_origin
= sticon_set_origin
,
365 .con_save_screen
= sticon_save_screen
,
366 .con_build_attr
= sticon_build_attr
,
367 .con_invert_region
= sticon_invert_region
,
368 .con_screen_pos
= sticon_screen_pos
,
369 .con_getxy
= sticon_getxy
,
374 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");
386 return take_over_console(&sti_con
, 0, MAX_NR_CONSOLES
- 1, 1);
391 module_init(sticonsole_init
);
392 MODULE_LICENSE("GPL");