diff options
Diffstat (limited to 'drivers/video/console/sticon.c')
-rw-r--r-- | drivers/video/console/sticon.c | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/drivers/video/console/sticon.c b/drivers/video/console/sticon.c new file mode 100644 index 000000000000..fd5940f41271 --- /dev/null +++ b/drivers/video/console/sticon.c | |||
@@ -0,0 +1,392 @@ | |||
1 | /* | ||
2 | * linux/drivers/video/console/sticon.c - console driver using HP's STI firmware | ||
3 | * | ||
4 | * Copyright (C) 2000 Philipp Rumpf <prumpf@tux.org> | ||
5 | * Copyright (C) 2002 Helge Deller <deller@gmx.de> | ||
6 | * | ||
7 | * Based on linux/drivers/video/vgacon.c and linux/drivers/video/fbcon.c, | ||
8 | * which were | ||
9 | * | ||
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 | ||
13 | * 1995 Jay Estabrook | ||
14 | * Copyright (C) 1995 Geert Uytterhoeven | ||
15 | * Copyright (C) 1993 Bjoern Brauel | ||
16 | * Roman Hodek | ||
17 | * Copyright (C) 1993 Hamish Macdonald | ||
18 | * Greg Harp | ||
19 | * Copyright (C) 1994 David Carter [carter@compsci.bristol.ac.uk] | ||
20 | * | ||
21 | * with work by William Rucklidge (wjr@cs.cornell.edu) | ||
22 | * Geert Uytterhoeven | ||
23 | * Jes Sorensen (jds@kom.auc.dk) | ||
24 | * Martin Apel | ||
25 | * with work by Guenther Kelleter | ||
26 | * Martin Schaller | ||
27 | * Andreas Schwab | ||
28 | * Emmanuel Marty (core@ggi-project.org) | ||
29 | * Jakub Jelinek (jj@ultra.linux.cz) | ||
30 | * Martin Mares <mj@ucw.cz> | ||
31 | * | ||
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 | ||
34 | * more details. | ||
35 | * | ||
36 | */ | ||
37 | |||
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> | ||
44 | #include <linux/kd.h> | ||
45 | #include <linux/selection.h> | ||
46 | #include <linux/module.h> | ||
47 | |||
48 | #include <asm/io.h> | ||
49 | |||
50 | #include "../sticore.h" | ||
51 | |||
52 | /* switching to graphics mode */ | ||
53 | #define BLANK 0 | ||
54 | static int vga_is_gfx; | ||
55 | |||
56 | /* this is the sti_struct used for this console */ | ||
57 | static struct sti_struct *sticon_sti; | ||
58 | |||
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; | ||
64 | |||
65 | /* software cursor */ | ||
66 | static int cursor_drawn; | ||
67 | #define CURSOR_DRAW_DELAY (1) | ||
68 | #define DEFAULT_CURSOR_BLINK_RATE (20) | ||
69 | |||
70 | static int vbl_cursor_cnt; | ||
71 | |||
72 | static inline void cursor_undrawn(void) | ||
73 | { | ||
74 | vbl_cursor_cnt = 0; | ||
75 | cursor_drawn = 0; | ||
76 | } | ||
77 | |||
78 | static const char *__init sticon_startup(void) | ||
79 | { | ||
80 | return "STI console"; | ||
81 | } | ||
82 | |||
83 | static int sticon_set_palette(struct vc_data *c, unsigned char *table) | ||
84 | { | ||
85 | return -EINVAL; | ||
86 | } | ||
87 | |||
88 | static void sticon_putc(struct vc_data *conp, int c, int ypos, int xpos) | ||
89 | { | ||
90 | int redraw_cursor = 0; | ||
91 | |||
92 | if (vga_is_gfx || console_blanked) | ||
93 | return; | ||
94 | |||
95 | if (conp->vc_mode != KD_TEXT) | ||
96 | return; | ||
97 | #if 0 | ||
98 | if ((p->cursor_x == xpos) && (p->cursor_y == ypos)) { | ||
99 | cursor_undrawn(); | ||
100 | redraw_cursor = 1; | ||
101 | } | ||
102 | #endif | ||
103 | |||
104 | sti_putc(sticon_sti, c, ypos, xpos); | ||
105 | |||
106 | if (redraw_cursor) | ||
107 | vbl_cursor_cnt = CURSOR_DRAW_DELAY; | ||
108 | } | ||
109 | |||
110 | static void sticon_putcs(struct vc_data *conp, const unsigned short *s, | ||
111 | int count, int ypos, int xpos) | ||
112 | { | ||
113 | int redraw_cursor = 0; | ||
114 | |||
115 | if (vga_is_gfx || console_blanked) | ||
116 | return; | ||
117 | |||
118 | if (conp->vc_mode != KD_TEXT) | ||
119 | return; | ||
120 | |||
121 | #if 0 | ||
122 | if ((p->cursor_y == ypos) && (xpos <= p->cursor_x) && | ||
123 | (p->cursor_x < (xpos + count))) { | ||
124 | cursor_undrawn(); | ||
125 | redraw_cursor = 1; | ||
126 | } | ||
127 | #endif | ||
128 | |||
129 | while (count--) { | ||
130 | sti_putc(sticon_sti, scr_readw(s++), ypos, xpos++); | ||
131 | } | ||
132 | |||
133 | if (redraw_cursor) | ||
134 | vbl_cursor_cnt = CURSOR_DRAW_DELAY; | ||
135 | } | ||
136 | |||
137 | static void sticon_cursor(struct vc_data *conp, int mode) | ||
138 | { | ||
139 | unsigned short car1; | ||
140 | |||
141 | car1 = conp->vc_screenbuf[conp->vc_x + conp->vc_y * conp->vc_cols]; | ||
142 | switch (mode) { | ||
143 | case CM_ERASE: | ||
144 | sti_putc(sticon_sti, car1, conp->vc_y, conp->vc_x); | ||
145 | break; | ||
146 | case CM_MOVE: | ||
147 | case CM_DRAW: | ||
148 | switch (conp->vc_cursor_type & 0x0f) { | ||
149 | case CUR_UNDERLINE: | ||
150 | case CUR_LOWER_THIRD: | ||
151 | case CUR_LOWER_HALF: | ||
152 | case CUR_TWO_THIRDS: | ||
153 | case CUR_BLOCK: | ||
154 | sti_putc(sticon_sti, (car1 & 255) + (0 << 8) + (7 << 11), | ||
155 | conp->vc_y, conp->vc_x); | ||
156 | break; | ||
157 | } | ||
158 | break; | ||
159 | } | ||
160 | } | ||
161 | |||
162 | static int sticon_scroll(struct vc_data *conp, int t, int b, int dir, int count) | ||
163 | { | ||
164 | struct sti_struct *sti = sticon_sti; | ||
165 | |||
166 | if (vga_is_gfx) | ||
167 | return 0; | ||
168 | |||
169 | sticon_cursor(conp, CM_ERASE); | ||
170 | |||
171 | switch (dir) { | ||
172 | case SM_UP: | ||
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); | ||
175 | break; | ||
176 | |||
177 | case SM_DOWN: | ||
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); | ||
180 | break; | ||
181 | } | ||
182 | |||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | static void sticon_bmove(struct vc_data *conp, int sy, int sx, | ||
187 | int dy, int dx, int height, int width) | ||
188 | { | ||
189 | if (!width || !height) | ||
190 | return; | ||
191 | #if 0 | ||
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*/); | ||
197 | #endif | ||
198 | |||
199 | sti_bmove(sticon_sti, sy, sx, dy, dx, height, width); | ||
200 | } | ||
201 | |||
202 | static void sticon_init(struct vc_data *c, int init) | ||
203 | { | ||
204 | struct sti_struct *sti = sticon_sti; | ||
205 | int vc_cols, vc_rows; | ||
206 | |||
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; | ||
211 | |||
212 | if (init) { | ||
213 | c->vc_cols = vc_cols; | ||
214 | c->vc_rows = vc_rows; | ||
215 | } else { | ||
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); */ | ||
220 | } | ||
221 | } | ||
222 | |||
223 | static void sticon_deinit(struct vc_data *c) | ||
224 | { | ||
225 | } | ||
226 | |||
227 | static void sticon_clear(struct vc_data *conp, int sy, int sx, int height, | ||
228 | int width) | ||
229 | { | ||
230 | if (!height || !width) | ||
231 | return; | ||
232 | |||
233 | sti_clear(sticon_sti, sy, sx, height, width, conp->vc_video_erase_char); | ||
234 | } | ||
235 | |||
236 | static int sticon_switch(struct vc_data *conp) | ||
237 | { | ||
238 | return 1; /* needs refreshing */ | ||
239 | } | ||
240 | |||
241 | static int sticon_set_origin(struct vc_data *conp) | ||
242 | { | ||
243 | return 0; | ||
244 | } | ||
245 | |||
246 | static int sticon_blank(struct vc_data *c, int blank, int mode_switch) | ||
247 | { | ||
248 | if (blank == 0) { | ||
249 | if (mode_switch) | ||
250 | vga_is_gfx = 0; | ||
251 | return 1; | ||
252 | } | ||
253 | sticon_set_origin(c); | ||
254 | sti_clear(sticon_sti, 0,0, c->vc_rows, c->vc_cols, BLANK); | ||
255 | if (mode_switch) | ||
256 | vga_is_gfx = 1; | ||
257 | return 1; | ||
258 | } | ||
259 | |||
260 | static int sticon_scrolldelta(struct vc_data *conp, int lines) | ||
261 | { | ||
262 | return 0; | ||
263 | } | ||
264 | |||
265 | static u16 *sticon_screen_pos(struct vc_data *conp, int offset) | ||
266 | { | ||
267 | int line; | ||
268 | unsigned long p; | ||
269 | |||
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; | ||
278 | return (u16 *)p; | ||
279 | } | ||
280 | |||
281 | static unsigned long sticon_getxy(struct vc_data *conp, unsigned long pos, | ||
282 | int *px, int *py) | ||
283 | { | ||
284 | int x, y; | ||
285 | unsigned long ret; | ||
286 | if (pos >= conp->vc_origin && pos < conp->vc_scr_end) { | ||
287 | unsigned long offset = (pos - conp->vc_origin) / 2; | ||
288 | |||
289 | x = offset % conp->vc_cols; | ||
290 | y = offset / conp->vc_cols; | ||
291 | if (conp->vc_num == fg_console) | ||
292 | y += softback_lines; | ||
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; | ||
296 | |||
297 | if (pos < softback_curr) | ||
298 | offset += softback_end - softback_buf; | ||
299 | offset /= 2; | ||
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) | ||
304 | ret = softback_buf; | ||
305 | if (ret == softback_in) | ||
306 | ret = conp->vc_origin; | ||
307 | } else { | ||
308 | /* Should not happen */ | ||
309 | x = y = 0; | ||
310 | ret = conp->vc_origin; | ||
311 | } | ||
312 | if (px) *px = x; | ||
313 | if (py) *py = y; | ||
314 | return ret; | ||
315 | } | ||
316 | |||
317 | static u8 sticon_build_attr(struct vc_data *conp, u8 color, u8 intens, | ||
318 | u8 blink, u8 underline, u8 reverse) | ||
319 | { | ||
320 | u8 attr = ((color & 0x70) >> 1) | ((color & 7)); | ||
321 | |||
322 | if (reverse) { | ||
323 | color = ((color >> 3) & 0x7) | ((color & 0x7) << 3); | ||
324 | } | ||
325 | |||
326 | return attr; | ||
327 | } | ||
328 | |||
329 | static void sticon_invert_region(struct vc_data *conp, u16 *p, int count) | ||
330 | { | ||
331 | int col = 1; /* vga_can_do_color; */ | ||
332 | |||
333 | while (count--) { | ||
334 | u16 a = scr_readw(p); | ||
335 | |||
336 | if (col) | ||
337 | a = ((a) & 0x88ff) | (((a) & 0x7000) >> 4) | (((a) & 0x0700) << 4); | ||
338 | else | ||
339 | a = ((a & 0x0700) == 0x0100) ? 0x7000 : 0x7700; | ||
340 | |||
341 | scr_writew(a, p++); | ||
342 | } | ||
343 | } | ||
344 | |||
345 | static void sticon_save_screen(struct vc_data *conp) | ||
346 | { | ||
347 | } | ||
348 | |||
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, | ||
370 | }; | ||
371 | |||
372 | |||
373 | |||
374 | int __init sticonsole_init(void) | ||
375 | { | ||
376 | /* already initialized ? */ | ||
377 | if (sticon_sti) | ||
378 | return 0; | ||
379 | |||
380 | sticon_sti = sti_get_rom(0); | ||
381 | if (!sticon_sti) | ||
382 | return -ENODEV; | ||
383 | |||
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); | ||
387 | } | ||
388 | return 0; | ||
389 | } | ||
390 | |||
391 | module_init(sticonsole_init); | ||
392 | MODULE_LICENSE("GPL"); | ||