1 /* $Id: promcon.c,v 1.1.1.1 2005/04/11 02:50:42 jack Exp $
2 * Console driver utilizing PROM sun terminal emulation
4 * Copyright (C) 1998 Eddie C. Dost (ecd@skynet.be)
5 * Copyright (C) 1998 Jakub Jelinek (jj@ultra.linux.cz)
8 #include <linux/config.h>
9 #include <linux/module.h>
10 #include <linux/kernel.h>
11 #include <linux/errno.h>
12 #include <linux/string.h>
14 #include <linux/tty.h>
15 #include <linux/slab.h>
16 #include <linux/delay.h>
17 #include <linux/console.h>
18 #include <linux/console_struct.h>
19 #include <linux/vt_kern.h>
20 #include <linux/selection.h>
22 #include <linux/init.h>
25 #include <asm/oplib.h>
26 #include <asm/uaccess.h>
28 static short pw = 80 - 1, ph = 34 - 1;
30 static unsigned long promcon_uni_pagedir[2];
32 extern u8 promfont_unicount[];
33 extern u16 promfont_unitable[];
35 #define PROMCON_COLOR 0
38 #define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1)
40 #define inverted(s) (((s) & 0x0800) ? 1 : 0)
43 static __inline__ void
44 promcon_puts(char *buf, int cnt)
46 prom_printf("%*.*s", cnt, cnt, buf);
50 promcon_start(struct vc_data *conp, char *b)
52 unsigned short *s = (unsigned short *)
53 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
58 unsigned short *t = s - 1;
59 u16 ct = scr_readw(t);
61 if (inverted(cs) && inverted(ct))
62 return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
64 else if (inverted(cs))
65 return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
67 else if (inverted(ct))
68 return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
71 return sprintf(b, "\b%c\b\033[@%c", cs, ct);
75 return sprintf(b, "\033[7m%c\033[m\b", cs);
77 return sprintf(b, "%c\b", cs);
81 promcon_end(struct vc_data *conp, char *b)
83 unsigned short *s = (unsigned short *)
84 (conp->vc_origin + py * conp->vc_size_row + (px << 1));
88 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
92 unsigned short *t = s - 1;
93 u16 ct = scr_readw(t);
95 if (inverted(cs) && inverted(ct))
96 b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
97 else if (inverted(cs))
98 b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
99 else if (inverted(ct))
100 b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
102 b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
107 b += sprintf(b, "%c\b", cs);
109 b += sprintf(b, "\033[7m%c\033[m\b", cs);
113 const char __init *promcon_startup(void)
115 const char *display_desc = "PROM";
119 node = prom_getchild(prom_root_node);
120 node = prom_searchsiblings(node, "options");
121 if (prom_getproperty(node, "screen-#columns", buf, 40) != -1) {
122 pw = simple_strtoul(buf, NULL, 0);
123 if (pw < 10 || pw > 256)
127 if (prom_getproperty(node, "screen-#rows", buf, 40) != -1) {
128 ph = simple_strtoul(buf, NULL, 0);
129 if (ph < 10 || ph > 256)
133 promcon_puts("\033[H\033[J", 6);
138 promcon_init_unimap(struct vc_data *conp)
140 mm_segment_t old_fs = get_fs();
141 struct unipair *p, *p1;
145 p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
148 q = promfont_unitable;
151 for (i = 0; i < 256; i++)
152 for (j = promfont_unicount[i]; j; j--) {
159 con_clear_unimap(conp->vc_num, NULL);
160 con_set_unimap(conp->vc_num, k, p);
161 con_protect_unimap(conp->vc_num, 1);
167 promcon_init(struct vc_data *conp, int init)
171 conp->vc_can_do_color = PROMCON_COLOR;
173 conp->vc_cols = pw + 1;
174 conp->vc_rows = ph + 1;
176 p = *conp->vc_uni_pagedir_loc;
177 if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
178 !--conp->vc_uni_pagedir_loc[1])
179 con_free_unimap(conp->vc_num);
180 conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
181 promcon_uni_pagedir[1]++;
182 if (!promcon_uni_pagedir[0] && p) {
183 promcon_init_unimap(conp);
186 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
187 vc_resize_con(ph + 1, pw + 1, conp->vc_num);
192 promcon_deinit(struct vc_data *conp)
194 /* When closing the last console, reset video origin */
195 if (!--promcon_uni_pagedir[1])
196 con_free_unimap(conp->vc_num);
197 conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
198 con_set_default_unimap(conp->vc_num);
202 promcon_switch(struct vc_data *conp)
207 static unsigned short *
208 promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
212 unsigned char *b = *bp;
215 u16 c = scr_readw(s);
216 if (attr != inverted(c)) {
219 strcpy (b, "\033[7m");
222 strcpy (b, "\033[m");
228 if (b - buf >= 224) {
229 promcon_puts(buf, b - buf);
238 promcon_putcs(struct vc_data *conp, const unsigned short *s,
239 int count, int y, int x)
241 unsigned char buf[256], *b = buf;
242 unsigned short attr = scr_readw(s);
252 b += promcon_start(conp, b);
254 if (x + count >= pw + 1) {
257 save = scr_readw((unsigned short *)(conp->vc_origin
258 + y * conp->vc_size_row
261 if (px != x || py != y) {
262 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
268 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
270 b += sprintf(b, "%c", scr_readw(s++));
272 strcpy(b, "\b\033[@");
276 b += sprintf(b, "\033[7m%c\033[m", save);
278 b += sprintf(b, "%c", save);
282 b += promcon_end(conp, b);
283 promcon_puts(buf, b - buf);
291 if (inverted(attr)) {
292 strcpy(b, "\033[7m");
296 if (px != x || py != y) {
297 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
302 for (i = 0; i < count; i++) {
303 if (b - buf >= 224) {
304 promcon_puts(buf, b - buf);
307 *b++ = scr_readw(s++);
313 save = scr_readw(s++);
314 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
318 if (inverted(attr)) {
323 b += promcon_end(conp, b);
324 promcon_puts(buf, b - buf);
328 promcon_putc(struct vc_data *conp, int c, int y, int x)
336 promcon_putcs(conp, &s, 1, y, x);
340 promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
342 unsigned char buf[256], *b = buf;
348 b += promcon_start(conp, b);
350 if (!sx && width == pw + 1) {
352 if (!sy && height == ph + 1) {
353 strcpy(b, "\033[H\033[J");
355 b += promcon_end(conp, b);
356 promcon_puts(buf, b - buf);
358 } else if (sy + height == ph + 1) {
359 b += sprintf(b, "\033[%dH\033[J", sy + 1);
360 b += promcon_end(conp, b);
361 promcon_puts(buf, b - buf);
365 b += sprintf(b, "\033[%dH", sy + 1);
366 for (i = 1; i < height; i++) {
367 strcpy(b, "\033[K\n");
374 b += promcon_end(conp, b);
375 promcon_puts(buf, b - buf);
378 } else if (sx + width == pw + 1) {
380 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
381 for (i = 1; i < height; i++) {
382 strcpy(b, "\033[K\n");
389 b += promcon_end(conp, b);
390 promcon_puts(buf, b - buf);
394 for (i = sy + 1; i <= sy + height; i++) {
395 b += sprintf(b, "\033[%d;%dH", i, sx + 1);
396 for (j = 0; j < width; j++)
398 if (b - buf + width >= 224) {
399 promcon_puts(buf, b - buf);
404 b += promcon_end(conp, b);
405 promcon_puts(buf, b - buf);
409 promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
410 int height, int width)
412 char buf[256], *b = buf;
417 b += promcon_start(conp, b);
418 if (sy == dy && height == 1) {
419 if (dx > sx && dx + width == conp->vc_cols)
420 b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
421 sy + 1, sx + 1, dx - sx, py + 1, px + 1);
422 else if (dx < sx && sx + width == conp->vc_cols)
423 b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
424 dy + 1, dx + 1, sx - dx, py + 1, px + 1);
426 b += promcon_end(conp, b);
427 promcon_puts(buf, b - buf);
432 * FIXME: What to do here???
433 * Current console.c should not call it like that ever.
435 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
439 promcon_cursor(struct vc_data *conp, int mode)
441 char buf[32], *b = buf;
449 b += promcon_start(conp, b);
450 if (px != conp->vc_x || py != conp->vc_y) {
453 b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
455 promcon_puts(buf, b - buf);
461 promcon_font_op(struct vc_data *conp, struct console_font_op *op)
467 promcon_blank(struct vc_data *conp, int blank)
470 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
473 /* Let console.c redraw */
479 promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
481 unsigned char buf[256], *p = buf;
488 p += promcon_start(conp, p);
493 p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
496 p += promcon_end(conp, p);
497 promcon_puts(buf, p - buf);
501 s = (unsigned short *)(conp->vc_origin
502 + (t + count) * conp->vc_size_row);
504 p += sprintf(p, "\033[%dH", t + 1);
506 for (i = t; i < b - count; i++)
507 s = promcon_repaint_line(s, buf, &p);
509 for (; i < b - 1; i++) {
510 strcpy(p, "\033[K\n");
512 if (p - buf >= 224) {
513 promcon_puts(buf, p - buf);
521 p += promcon_end(conp, p);
522 promcon_puts(buf, p - buf);
527 p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
530 p += promcon_end(conp, p);
531 promcon_puts(buf, p - buf);
535 s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
537 p += sprintf(p, "\033[%dH", t + 1);
539 for (i = t; i < t + count; i++) {
540 strcpy(p, "\033[K\n");
542 if (p - buf >= 224) {
543 promcon_puts(buf, p - buf);
549 s = promcon_repaint_line(s, buf, &p);
551 p += promcon_end(conp, p);
552 promcon_puts(buf, p - buf);
560 static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
562 return (_reverse) ? 0xf : 0x7;
567 * The console 'switch' structure for the VGA based console
570 static int promcon_dummy(void)
575 #define DUMMY (void *) promcon_dummy
577 const struct consw prom_con = {
578 con_startup: promcon_startup,
579 con_init: promcon_init,
580 con_deinit: promcon_deinit,
581 con_clear: promcon_clear,
582 con_putc: promcon_putc,
583 con_putcs: promcon_putcs,
584 con_cursor: promcon_cursor,
585 con_scroll: promcon_scroll,
586 con_bmove: promcon_bmove,
587 con_switch: promcon_switch,
588 con_blank: promcon_blank,
589 con_font_op: promcon_font_op,
590 con_set_palette: DUMMY,
591 con_scrolldelta: DUMMY,
593 con_build_attr: promcon_build_attr,
597 void __init prom_con_init(void)
599 #ifdef CONFIG_DUMMY_CONSOLE
600 if (conswitchp == &dummy_con)
601 take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
604 if (conswitchp == &prom_con)
605 promcon_init_unimap(vc_cons[fg_console].d);