1 /* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 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/slab.h>
16 #include <linux/delay.h>
17 #include <linux/console.h>
18 #include <linux/vt_kern.h>
19 #include <linux/selection.h>
21 #include <linux/init.h>
24 #include <asm/oplib.h>
25 #include <asm/uaccess.h>
27 static short pw
= 80 - 1, ph
= 34 - 1;
29 static unsigned long promcon_uni_pagedir
[2];
31 extern u8 promfont_unicount
[];
32 extern u16 promfont_unitable
[];
34 #define PROMCON_COLOR 0
37 #define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1)
39 #define inverted(s) (((s) & 0x0800) ? 1 : 0)
42 static __inline__
void
43 promcon_puts(char *buf
, int cnt
)
45 prom_printf("%*.*s", cnt
, cnt
, buf
);
49 promcon_start(struct vc_data
*conp
, char *b
)
51 unsigned short *s
= (unsigned short *)
52 (conp
->vc_origin
+ py
* conp
->vc_size_row
+ (px
<< 1));
57 unsigned short *t
= s
- 1;
58 u16 ct
= scr_readw(t
);
60 if (inverted(cs
) && inverted(ct
))
61 return sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m", cs
,
63 else if (inverted(cs
))
64 return sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c", cs
,
66 else if (inverted(ct
))
67 return sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m", cs
,
70 return sprintf(b
, "\b%c\b\033[@%c", cs
, ct
);
74 return sprintf(b
, "\033[7m%c\033[m\b", cs
);
76 return sprintf(b
, "%c\b", cs
);
80 promcon_end(struct vc_data
*conp
, char *b
)
82 unsigned short *s
= (unsigned short *)
83 (conp
->vc_origin
+ py
* conp
->vc_size_row
+ (px
<< 1));
87 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
91 unsigned short *t
= s
- 1;
92 u16 ct
= scr_readw(t
);
94 if (inverted(cs
) && inverted(ct
))
95 b
+= sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m", cs
, ct
);
96 else if (inverted(cs
))
97 b
+= sprintf(b
, "\b%c\b\033[@%c", cs
, ct
);
98 else if (inverted(ct
))
99 b
+= sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m", cs
, ct
);
101 b
+= sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c", cs
, ct
);
106 b
+= sprintf(b
, "%c\b", cs
);
108 b
+= sprintf(b
, "\033[7m%c\033[m\b", cs
);
112 const char __init
*promcon_startup(void)
114 const char *display_desc
= "PROM";
118 node
= prom_getchild(prom_root_node
);
119 node
= prom_searchsiblings(node
, "options");
120 if (prom_getproperty(node
, "screen-#columns", buf
, 40) != -1) {
121 pw
= simple_strtoul(buf
, NULL
, 0);
122 if (pw
< 10 || pw
> 256)
126 if (prom_getproperty(node
, "screen-#rows", buf
, 40) != -1) {
127 ph
= simple_strtoul(buf
, NULL
, 0);
128 if (ph
< 10 || ph
> 256)
132 promcon_puts("\033[H\033[J", 6);
137 promcon_init_unimap(struct vc_data
*conp
)
139 mm_segment_t old_fs
= get_fs();
140 struct unipair
*p
, *p1
;
144 p
= kmalloc(256*sizeof(struct unipair
), GFP_KERNEL
);
147 q
= promfont_unitable
;
150 for (i
= 0; i
< 256; i
++)
151 for (j
= promfont_unicount
[i
]; j
; j
--) {
158 con_clear_unimap(conp
, NULL
);
159 con_set_unimap(conp
, k
, p
);
160 con_protect_unimap(conp
, 1);
166 promcon_init(struct vc_data
*conp
, int init
)
170 conp
->vc_can_do_color
= PROMCON_COLOR
;
172 conp
->vc_cols
= pw
+ 1;
173 conp
->vc_rows
= ph
+ 1;
175 p
= *conp
->vc_uni_pagedir_loc
;
176 if (conp
->vc_uni_pagedir_loc
== &conp
->vc_uni_pagedir
||
177 !--conp
->vc_uni_pagedir_loc
[1])
178 con_free_unimap(conp
);
179 conp
->vc_uni_pagedir_loc
= promcon_uni_pagedir
;
180 promcon_uni_pagedir
[1]++;
181 if (!promcon_uni_pagedir
[0] && p
) {
182 promcon_init_unimap(conp
);
185 if (conp
->vc_cols
!= pw
+ 1 || conp
->vc_rows
!= ph
+ 1)
186 vc_resize(conp
, pw
+ 1, ph
+ 1);
191 promcon_deinit(struct vc_data
*conp
)
193 /* When closing the last console, reset video origin */
194 if (!--promcon_uni_pagedir
[1])
195 con_free_unimap(conp
);
196 conp
->vc_uni_pagedir_loc
= &conp
->vc_uni_pagedir
;
197 con_set_default_unimap(conp
);
201 promcon_switch(struct vc_data
*conp
)
206 static unsigned short *
207 promcon_repaint_line(unsigned short *s
, unsigned char *buf
, unsigned char **bp
)
211 unsigned char *b
= *bp
;
214 u16 c
= scr_readw(s
);
215 if (attr
!= inverted(c
)) {
218 strcpy (b
, "\033[7m");
221 strcpy (b
, "\033[m");
227 if (b
- buf
>= 224) {
228 promcon_puts(buf
, b
- buf
);
237 promcon_putcs(struct vc_data
*conp
, const unsigned short *s
,
238 int count
, int y
, int x
)
240 unsigned char buf
[256], *b
= buf
;
241 unsigned short attr
= scr_readw(s
);
251 b
+= promcon_start(conp
, b
);
253 if (x
+ count
>= pw
+ 1) {
256 save
= scr_readw((unsigned short *)(conp
->vc_origin
257 + y
* conp
->vc_size_row
260 if (px
!= x
|| py
!= y
) {
261 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
267 b
+= sprintf(b
, "\033[7m%c\033[m", scr_readw(s
++));
269 b
+= sprintf(b
, "%c", scr_readw(s
++));
271 strcpy(b
, "\b\033[@");
275 b
+= sprintf(b
, "\033[7m%c\033[m", save
);
277 b
+= sprintf(b
, "%c", save
);
281 b
+= promcon_end(conp
, b
);
282 promcon_puts(buf
, b
- buf
);
290 if (inverted(attr
)) {
291 strcpy(b
, "\033[7m");
295 if (px
!= x
|| py
!= y
) {
296 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
301 for (i
= 0; i
< count
; i
++) {
302 if (b
- buf
>= 224) {
303 promcon_puts(buf
, b
- buf
);
306 *b
++ = scr_readw(s
++);
312 save
= scr_readw(s
++);
313 b
+= sprintf(b
, "%c\b\033[@%c", scr_readw(s
++), save
);
317 if (inverted(attr
)) {
322 b
+= promcon_end(conp
, b
);
323 promcon_puts(buf
, b
- buf
);
327 promcon_putc(struct vc_data
*conp
, int c
, int y
, int x
)
335 promcon_putcs(conp
, &s
, 1, y
, x
);
339 promcon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
, int width
)
341 unsigned char buf
[256], *b
= buf
;
347 b
+= promcon_start(conp
, b
);
349 if (!sx
&& width
== pw
+ 1) {
351 if (!sy
&& height
== ph
+ 1) {
352 strcpy(b
, "\033[H\033[J");
354 b
+= promcon_end(conp
, b
);
355 promcon_puts(buf
, b
- buf
);
357 } else if (sy
+ height
== ph
+ 1) {
358 b
+= sprintf(b
, "\033[%dH\033[J", sy
+ 1);
359 b
+= promcon_end(conp
, b
);
360 promcon_puts(buf
, b
- buf
);
364 b
+= sprintf(b
, "\033[%dH", sy
+ 1);
365 for (i
= 1; i
< height
; i
++) {
366 strcpy(b
, "\033[K\n");
373 b
+= promcon_end(conp
, b
);
374 promcon_puts(buf
, b
- buf
);
377 } else if (sx
+ width
== pw
+ 1) {
379 b
+= sprintf(b
, "\033[%d;%dH", sy
+ 1, sx
+ 1);
380 for (i
= 1; i
< height
; i
++) {
381 strcpy(b
, "\033[K\n");
388 b
+= promcon_end(conp
, b
);
389 promcon_puts(buf
, b
- buf
);
393 for (i
= sy
+ 1; i
<= sy
+ height
; i
++) {
394 b
+= sprintf(b
, "\033[%d;%dH", i
, sx
+ 1);
395 for (j
= 0; j
< width
; j
++)
397 if (b
- buf
+ width
>= 224) {
398 promcon_puts(buf
, b
- buf
);
403 b
+= promcon_end(conp
, b
);
404 promcon_puts(buf
, b
- buf
);
408 promcon_bmove(struct vc_data
*conp
, int sy
, int sx
, int dy
, int dx
,
409 int height
, int width
)
411 char buf
[256], *b
= buf
;
416 b
+= promcon_start(conp
, b
);
417 if (sy
== dy
&& height
== 1) {
418 if (dx
> sx
&& dx
+ width
== conp
->vc_cols
)
419 b
+= sprintf(b
, "\033[%d;%dH\033[%d@\033[%d;%dH",
420 sy
+ 1, sx
+ 1, dx
- sx
, py
+ 1, px
+ 1);
421 else if (dx
< sx
&& sx
+ width
== conp
->vc_cols
)
422 b
+= sprintf(b
, "\033[%d;%dH\033[%dP\033[%d;%dH",
423 dy
+ 1, dx
+ 1, sx
- dx
, py
+ 1, px
+ 1);
425 b
+= promcon_end(conp
, b
);
426 promcon_puts(buf
, b
- buf
);
431 * FIXME: What to do here???
432 * Current console.c should not call it like that ever.
434 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
438 promcon_cursor(struct vc_data
*conp
, int mode
)
440 char buf
[32], *b
= buf
;
448 b
+= promcon_start(conp
, b
);
449 if (px
!= conp
->vc_x
|| py
!= conp
->vc_y
) {
452 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
454 promcon_puts(buf
, b
- buf
);
460 promcon_blank(struct vc_data
*conp
, int blank
, int mode_switch
)
463 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
466 /* Let console.c redraw */
472 promcon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
474 unsigned char buf
[256], *p
= buf
;
481 p
+= promcon_start(conp
, p
);
486 p
+= sprintf(p
, "\033[%dH\033[%dM", t
+ 1, count
);
489 p
+= promcon_end(conp
, p
);
490 promcon_puts(buf
, p
- buf
);
494 s
= (unsigned short *)(conp
->vc_origin
495 + (t
+ count
) * conp
->vc_size_row
);
497 p
+= sprintf(p
, "\033[%dH", t
+ 1);
499 for (i
= t
; i
< b
- count
; i
++)
500 s
= promcon_repaint_line(s
, buf
, &p
);
502 for (; i
< b
- 1; i
++) {
503 strcpy(p
, "\033[K\n");
505 if (p
- buf
>= 224) {
506 promcon_puts(buf
, p
- buf
);
514 p
+= promcon_end(conp
, p
);
515 promcon_puts(buf
, p
- buf
);
520 p
+= sprintf(p
, "\033[%dH\033[%dL", t
+ 1, count
);
523 p
+= promcon_end(conp
, p
);
524 promcon_puts(buf
, p
- buf
);
528 s
= (unsigned short *)(conp
->vc_origin
+ t
* conp
->vc_size_row
);
530 p
+= sprintf(p
, "\033[%dH", t
+ 1);
532 for (i
= t
; i
< t
+ count
; i
++) {
533 strcpy(p
, "\033[K\n");
535 if (p
- buf
>= 224) {
536 promcon_puts(buf
, p
- buf
);
542 s
= promcon_repaint_line(s
, buf
, &p
);
544 p
+= promcon_end(conp
, p
);
545 promcon_puts(buf
, p
- buf
);
553 static u8
promcon_build_attr(struct vc_data
*conp
, u8 _color
, u8 _intensity
, u8 _blink
, u8 _underline
, u8 _reverse
)
555 return (_reverse
) ? 0xf : 0x7;
560 * The console 'switch' structure for the VGA based console
563 static int promcon_dummy(void)
568 #define DUMMY (void *) promcon_dummy
570 const struct consw prom_con
= {
571 .owner
= THIS_MODULE
,
572 .con_startup
= promcon_startup
,
573 .con_init
= promcon_init
,
574 .con_deinit
= promcon_deinit
,
575 .con_clear
= promcon_clear
,
576 .con_putc
= promcon_putc
,
577 .con_putcs
= promcon_putcs
,
578 .con_cursor
= promcon_cursor
,
579 .con_scroll
= promcon_scroll
,
580 .con_bmove
= promcon_bmove
,
581 .con_switch
= promcon_switch
,
582 .con_blank
= promcon_blank
,
583 .con_set_palette
= DUMMY
,
584 .con_scrolldelta
= DUMMY
,
586 .con_build_attr
= promcon_build_attr
,
590 void __init
prom_con_init(void)
592 #ifdef CONFIG_DUMMY_CONSOLE
593 if (conswitchp
== &dummy_con
)
594 take_over_console(&prom_con
, 0, MAX_NR_CONSOLES
-1, 1);
597 if (conswitchp
== &prom_con
)
598 promcon_init_unimap(vc_cons
[fg_console
].d
);