1 /* $Id: promcon.c,v 1.16 1999/08/10 15:56:22 davem 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/malloc.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));
56 unsigned short *t
= s
- 1;
58 if (inverted(*s
) && inverted(*t
))
59 return sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m",
61 else if (inverted(*s
))
62 return sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c",
64 else if (inverted(*t
))
65 return sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m",
68 return sprintf(b
, "\b%c\b\033[@%c", *s
, *t
);
72 return sprintf(b
, "\033[7m%c\033[m\b", *s
);
74 return sprintf(b
, "%c\b", *s
);
78 promcon_end(struct vc_data
*conp
, char *b
)
80 unsigned short *s
= (unsigned short *)
81 (conp
->vc_origin
+ py
* conp
->vc_size_row
+ (px
<< 1));
84 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
87 unsigned short *t
= s
- 1;
89 if (inverted(*s
) && inverted(*t
))
90 b
+= sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m", *s
, *t
);
91 else if (inverted(*s
))
92 b
+= sprintf(b
, "\b%c\b\033[@%c", *s
, *t
);
93 else if (inverted(*t
))
94 b
+= sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m", *s
, *t
);
96 b
+= sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c", *s
, *t
);
101 b
+= sprintf(b
, "%c\b", *s
);
103 b
+= sprintf(b
, "\033[7m%c\033[m\b", *s
);
107 const char __init
*promcon_startup(void)
109 const char *display_desc
= "PROM";
113 node
= prom_getchild(prom_root_node
);
114 node
= prom_searchsiblings(node
, "options");
115 if (prom_getproperty(node
, "screen-#columns", buf
, 40) != -1) {
116 pw
= simple_strtoul(buf
, NULL
, 0);
117 if (pw
< 10 || pw
> 256)
121 if (prom_getproperty(node
, "screen-#rows", buf
, 40) != -1) {
122 ph
= simple_strtoul(buf
, NULL
, 0);
123 if (ph
< 10 || ph
> 256)
127 promcon_puts("\033[H\033[J", 6);
132 promcon_init_unimap(struct vc_data
*conp
)
134 mm_segment_t old_fs
= get_fs();
135 struct unipair
*p
, *p1
;
139 p
= kmalloc(256*sizeof(struct unipair
), GFP_KERNEL
);
142 q
= promfont_unitable
;
145 for (i
= 0; i
< 256; i
++)
146 for (j
= promfont_unicount
[i
]; j
; j
--) {
153 con_clear_unimap(conp
->vc_num
, NULL
);
154 con_set_unimap(conp
->vc_num
, k
, p
);
155 con_protect_unimap(conp
->vc_num
, 1);
161 promcon_init(struct vc_data
*conp
, int init
)
165 conp
->vc_can_do_color
= PROMCON_COLOR
;
167 conp
->vc_cols
= pw
+ 1;
168 conp
->vc_rows
= ph
+ 1;
170 p
= *conp
->vc_uni_pagedir_loc
;
171 if (conp
->vc_uni_pagedir_loc
== &conp
->vc_uni_pagedir
||
172 !--conp
->vc_uni_pagedir_loc
[1])
173 con_free_unimap(conp
->vc_num
);
174 conp
->vc_uni_pagedir_loc
= promcon_uni_pagedir
;
175 promcon_uni_pagedir
[1]++;
176 if (!promcon_uni_pagedir
[0] && p
) {
177 promcon_init_unimap(conp
);
180 if (conp
->vc_cols
!= pw
+ 1 || conp
->vc_rows
!= ph
+ 1)
181 vc_resize_con(ph
+ 1, pw
+ 1, conp
->vc_num
);
186 promcon_deinit(struct vc_data
*conp
)
188 /* When closing the last console, reset video origin */
189 if (!--promcon_uni_pagedir
[1])
190 con_free_unimap(conp
->vc_num
);
191 conp
->vc_uni_pagedir_loc
= &conp
->vc_uni_pagedir
;
192 con_set_default_unimap(conp
->vc_num
);
196 promcon_switch(struct vc_data
*conp
)
201 static unsigned short *
202 promcon_repaint_line(unsigned short *s
, unsigned char *buf
, unsigned char **bp
)
206 unsigned char *b
= *bp
;
209 if (attr
!= inverted(*s
)) {
212 strcpy (b
, "\033[7m");
215 strcpy (b
, "\033[m");
220 if (b
- buf
>= 224) {
221 promcon_puts(buf
, b
- buf
);
230 promcon_putcs(struct vc_data
*conp
, const unsigned short *s
,
231 int count
, int y
, int x
)
233 unsigned char buf
[256], *b
= buf
;
234 unsigned short attr
= scr_readw(s
);
244 b
+= promcon_start(conp
, b
);
246 if (x
+ count
>= pw
+ 1) {
249 save
= *(unsigned short *)(conp
->vc_origin
250 + y
* conp
->vc_size_row
253 if (px
!= x
|| py
!= y
) {
254 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
260 b
+= sprintf(b
, "\033[7m%c\033[m", scr_readw(s
++));
262 b
+= sprintf(b
, "%c", scr_readw(s
++));
264 strcpy(b
, "\b\033[@");
268 b
+= sprintf(b
, "\033[7m%c\033[m", save
);
270 b
+= sprintf(b
, "%c", save
);
274 b
+= promcon_end(conp
, b
);
275 promcon_puts(buf
, b
- buf
);
283 if (inverted(attr
)) {
284 strcpy(b
, "\033[7m");
288 if (px
!= x
|| py
!= y
) {
289 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
294 for (i
= 0; i
< count
; i
++) {
295 if (b
- buf
>= 224) {
296 promcon_puts(buf
, b
- buf
);
299 *b
++ = scr_readw(s
++);
305 save
= scr_readw(s
++);
306 b
+= sprintf(b
, "%c\b\033[@%c", scr_readw(s
++), save
);
310 if (inverted(attr
)) {
315 b
+= promcon_end(conp
, b
);
316 promcon_puts(buf
, b
- buf
);
320 promcon_putc(struct vc_data
*conp
, int c
, int y
, int x
)
328 promcon_putcs(conp
, &s
, 1, y
, x
);
332 promcon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
, int width
)
334 unsigned char buf
[256], *b
= buf
;
340 b
+= promcon_start(conp
, b
);
342 if (!sx
&& width
== pw
+ 1) {
344 if (!sy
&& height
== ph
+ 1) {
345 strcpy(b
, "\033[H\033[J");
347 b
+= promcon_end(conp
, b
);
348 promcon_puts(buf
, b
- buf
);
350 } else if (sy
+ height
== ph
+ 1) {
351 b
+= sprintf(b
, "\033[%dH\033[J", sy
+ 1);
352 b
+= promcon_end(conp
, b
);
353 promcon_puts(buf
, b
- buf
);
357 b
+= sprintf(b
, "\033[%dH", sy
+ 1);
358 for (i
= 1; i
< height
; i
++) {
359 strcpy(b
, "\033[K\n");
366 b
+= promcon_end(conp
, b
);
367 promcon_puts(buf
, b
- buf
);
370 } else if (sx
+ width
== pw
+ 1) {
372 b
+= sprintf(b
, "\033[%d;%dH", sy
+ 1, sx
+ 1);
373 for (i
= 1; i
< height
; i
++) {
374 strcpy(b
, "\033[K\n");
381 b
+= promcon_end(conp
, b
);
382 promcon_puts(buf
, b
- buf
);
386 for (i
= sy
+ 1; i
<= sy
+ height
; i
++) {
387 b
+= sprintf(b
, "\033[%d;%dH", i
, sx
+ 1);
388 for (j
= 0; j
< width
; j
++)
390 if (b
- buf
+ width
>= 224) {
391 promcon_puts(buf
, b
- buf
);
396 b
+= promcon_end(conp
, b
);
397 promcon_puts(buf
, b
- buf
);
401 promcon_bmove(struct vc_data
*conp
, int sy
, int sx
, int dy
, int dx
,
402 int height
, int width
)
404 char buf
[256], *b
= buf
;
409 b
+= promcon_start(conp
, b
);
410 if (sy
== dy
&& height
== 1) {
411 if (dx
> sx
&& dx
+ width
== conp
->vc_cols
)
412 b
+= sprintf(b
, "\033[%d;%dH\033[%d@\033[%d;%dH",
413 sy
+ 1, sx
+ 1, dx
- sx
, py
+ 1, px
+ 1);
414 else if (dx
< sx
&& sx
+ width
== conp
->vc_cols
)
415 b
+= sprintf(b
, "\033[%d;%dH\033[%dP\033[%d;%dH",
416 dy
+ 1, dx
+ 1, sx
- dx
, py
+ 1, px
+ 1);
418 b
+= promcon_end(conp
, b
);
419 promcon_puts(buf
, b
- buf
);
424 * FIXME: What to do here???
425 * Current console.c should not call it like that ever.
427 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
431 promcon_cursor(struct vc_data
*conp
, int mode
)
433 char buf
[32], *b
= buf
;
441 b
+= promcon_start(conp
, b
);
442 if (px
!= conp
->vc_x
|| py
!= conp
->vc_y
) {
445 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
447 promcon_puts(buf
, b
- buf
);
453 promcon_font_op(struct vc_data
*conp
, struct console_font_op
*op
)
459 promcon_blank(struct vc_data
*conp
, int blank
)
462 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
465 /* Let console.c redraw */
471 promcon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
473 unsigned char buf
[256], *p
= buf
;
480 p
+= promcon_start(conp
, p
);
485 p
+= sprintf(p
, "\033[%dH\033[%dM", t
+ 1, count
);
488 p
+= promcon_end(conp
, p
);
489 promcon_puts(buf
, p
- buf
);
493 s
= (unsigned short *)(conp
->vc_origin
494 + (t
+ count
) * conp
->vc_size_row
);
496 p
+= sprintf(p
, "\033[%dH", t
+ 1);
498 for (i
= t
; i
< b
- count
; i
++)
499 s
= promcon_repaint_line(s
, buf
, &p
);
501 for (; i
< b
- 1; i
++) {
502 strcpy(p
, "\033[K\n");
504 if (p
- buf
>= 224) {
505 promcon_puts(buf
, p
- buf
);
513 p
+= promcon_end(conp
, p
);
514 promcon_puts(buf
, p
- buf
);
519 p
+= sprintf(p
, "\033[%dH\033[%dL", t
+ 1, count
);
522 p
+= promcon_end(conp
, p
);
523 promcon_puts(buf
, p
- buf
);
527 s
= (unsigned short *)(conp
->vc_origin
+ t
* conp
->vc_size_row
);
529 p
+= sprintf(p
, "\033[%dH", t
+ 1);
531 for (i
= t
; i
< t
+ count
; i
++) {
532 strcpy(p
, "\033[K\n");
534 if (p
- buf
>= 224) {
535 promcon_puts(buf
, p
- buf
);
541 s
= promcon_repaint_line(s
, buf
, &p
);
543 p
+= promcon_end(conp
, p
);
544 promcon_puts(buf
, p
- buf
);
552 static u8
promcon_build_attr(struct vc_data
*conp
, u8 _color
, u8 _intensity
, u8 _blink
, u8 _underline
, u8 _reverse
)
554 return (_reverse
) ? 0xf : 0x7;
559 * The console 'switch' structure for the VGA based console
562 static int promcon_dummy(void)
567 #define DUMMY (void *) promcon_dummy
569 struct consw prom_con
= {
570 con_startup
: promcon_startup
,
571 con_init
: promcon_init
,
572 con_deinit
: promcon_deinit
,
573 con_clear
: promcon_clear
,
574 con_putc
: promcon_putc
,
575 con_putcs
: promcon_putcs
,
576 con_cursor
: promcon_cursor
,
577 con_scroll
: promcon_scroll
,
578 con_bmove
: promcon_bmove
,
579 con_switch
: promcon_switch
,
580 con_blank
: promcon_blank
,
581 con_font_op
: promcon_font_op
,
582 con_set_palette
: DUMMY
,
583 con_scrolldelta
: DUMMY
,
584 con_set_origin
: NULL
,
585 con_save_screen
: NULL
,
587 con_build_attr
: NULL
,
589 con_build_attr
: promcon_build_attr
,
591 con_invert_region
: NULL
,
594 void __init
prom_con_init(void)
596 #ifdef CONFIG_DUMMY_CONSOLE
597 if (conswitchp
== &dummy_con
)
598 take_over_console(&prom_con
, 0, MAX_NR_CONSOLES
-1, 1);
601 if (conswitchp
== &prom_con
)
602 promcon_init_unimap(vc_cons
[fg_console
].d
);