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/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
13 #include <linux/slab.h>
14 #include <linux/delay.h>
15 #include <linux/console.h>
16 #include <linux/vt_kern.h>
17 #include <linux/selection.h>
19 #include <linux/init.h>
22 #include <asm/oplib.h>
23 #include <asm/uaccess.h>
25 static short pw
= 80 - 1, ph
= 34 - 1;
27 static unsigned long promcon_uni_pagedir
[2];
29 extern u8 promfont_unicount
[];
30 extern u16 promfont_unitable
[];
32 #define PROMCON_COLOR 0
35 #define inverted(s) ((((s) & 0x7700) == 0x0700) ? 0 : 1)
37 #define inverted(s) (((s) & 0x0800) ? 1 : 0)
40 static __inline__
void
41 promcon_puts(char *buf
, int cnt
)
43 prom_printf("%*.*s", cnt
, cnt
, buf
);
47 promcon_start(struct vc_data
*conp
, char *b
)
49 unsigned short *s
= (unsigned short *)
50 (conp
->vc_origin
+ py
* conp
->vc_size_row
+ (px
<< 1));
55 unsigned short *t
= s
- 1;
56 u16 ct
= scr_readw(t
);
58 if (inverted(cs
) && inverted(ct
))
59 return sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m", cs
,
61 else if (inverted(cs
))
62 return sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c", cs
,
64 else if (inverted(ct
))
65 return sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m", cs
,
68 return sprintf(b
, "\b%c\b\033[@%c", cs
, ct
);
72 return sprintf(b
, "\033[7m%c\033[m\b", cs
);
74 return sprintf(b
, "%c\b", cs
);
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));
85 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
89 unsigned short *t
= s
- 1;
90 u16 ct
= scr_readw(t
);
92 if (inverted(cs
) && inverted(ct
))
93 b
+= sprintf(b
, "\b%c\b\033[@\033[7m%c\033[m", cs
, ct
);
94 else if (inverted(cs
))
95 b
+= sprintf(b
, "\b%c\b\033[@%c", cs
, ct
);
96 else if (inverted(ct
))
97 b
+= sprintf(b
, "\b\033[7m%c\b\033[@%c\033[m", cs
, ct
);
99 b
+= sprintf(b
, "\b\033[7m%c\033[m\b\033[@%c", cs
, ct
);
104 b
+= sprintf(b
, "%c\b", cs
);
106 b
+= sprintf(b
, "\033[7m%c\033[m\b", cs
);
110 const char *promcon_startup(void)
112 const char *display_desc
= "PROM";
116 node
= prom_getchild(prom_root_node
);
117 node
= prom_searchsiblings(node
, "options");
118 if (prom_getproperty(node
, "screen-#columns", buf
, 40) != -1) {
119 pw
= simple_strtoul(buf
, NULL
, 0);
120 if (pw
< 10 || pw
> 256)
124 if (prom_getproperty(node
, "screen-#rows", buf
, 40) != -1) {
125 ph
= simple_strtoul(buf
, NULL
, 0);
126 if (ph
< 10 || ph
> 256)
130 promcon_puts("\033[H\033[J", 6);
135 promcon_init_unimap(struct vc_data
*conp
)
137 mm_segment_t old_fs
= get_fs();
138 struct unipair
*p
, *p1
;
142 p
= kmalloc(256*sizeof(struct unipair
), GFP_KERNEL
);
145 q
= promfont_unitable
;
148 for (i
= 0; i
< 256; i
++)
149 for (j
= promfont_unicount
[i
]; j
; j
--) {
156 con_clear_unimap(conp
, NULL
);
157 con_set_unimap(conp
, k
, p
);
158 con_protect_unimap(conp
, 1);
164 promcon_init(struct vc_data
*conp
, int init
)
168 conp
->vc_can_do_color
= PROMCON_COLOR
;
170 conp
->vc_cols
= pw
+ 1;
171 conp
->vc_rows
= ph
+ 1;
173 p
= *conp
->vc_uni_pagedir_loc
;
174 if (conp
->vc_uni_pagedir_loc
== &conp
->vc_uni_pagedir
||
175 !--conp
->vc_uni_pagedir_loc
[1])
176 con_free_unimap(conp
);
177 conp
->vc_uni_pagedir_loc
= promcon_uni_pagedir
;
178 promcon_uni_pagedir
[1]++;
179 if (!promcon_uni_pagedir
[0] && p
) {
180 promcon_init_unimap(conp
);
183 if (conp
->vc_cols
!= pw
+ 1 || conp
->vc_rows
!= ph
+ 1)
184 vc_resize(conp
, pw
+ 1, ph
+ 1);
189 promcon_deinit(struct vc_data
*conp
)
191 /* When closing the last console, reset video origin */
192 if (!--promcon_uni_pagedir
[1])
193 con_free_unimap(conp
);
194 conp
->vc_uni_pagedir_loc
= &conp
->vc_uni_pagedir
;
195 con_set_default_unimap(conp
);
199 promcon_switch(struct vc_data
*conp
)
204 static unsigned short *
205 promcon_repaint_line(unsigned short *s
, unsigned char *buf
, unsigned char **bp
)
209 unsigned char *b
= *bp
;
212 u16 c
= scr_readw(s
);
213 if (attr
!= inverted(c
)) {
216 strcpy (b
, "\033[7m");
219 strcpy (b
, "\033[m");
225 if (b
- buf
>= 224) {
226 promcon_puts(buf
, b
- buf
);
235 promcon_putcs(struct vc_data
*conp
, const unsigned short *s
,
236 int count
, int y
, int x
)
238 unsigned char buf
[256], *b
= buf
;
239 unsigned short attr
= scr_readw(s
);
249 b
+= promcon_start(conp
, b
);
251 if (x
+ count
>= pw
+ 1) {
254 save
= scr_readw((unsigned short *)(conp
->vc_origin
255 + y
* conp
->vc_size_row
258 if (px
!= x
|| py
!= y
) {
259 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
265 b
+= sprintf(b
, "\033[7m%c\033[m", scr_readw(s
++));
267 b
+= sprintf(b
, "%c", scr_readw(s
++));
269 strcpy(b
, "\b\033[@");
273 b
+= sprintf(b
, "\033[7m%c\033[m", save
);
275 b
+= sprintf(b
, "%c", save
);
279 b
+= promcon_end(conp
, b
);
280 promcon_puts(buf
, b
- buf
);
288 if (inverted(attr
)) {
289 strcpy(b
, "\033[7m");
293 if (px
!= x
|| py
!= y
) {
294 b
+= sprintf(b
, "\033[%d;%dH", y
+ 1, x
+ 1);
299 for (i
= 0; i
< count
; i
++) {
300 if (b
- buf
>= 224) {
301 promcon_puts(buf
, b
- buf
);
304 *b
++ = scr_readw(s
++);
310 save
= scr_readw(s
++);
311 b
+= sprintf(b
, "%c\b\033[@%c", scr_readw(s
++), save
);
315 if (inverted(attr
)) {
320 b
+= promcon_end(conp
, b
);
321 promcon_puts(buf
, b
- buf
);
325 promcon_putc(struct vc_data
*conp
, int c
, int y
, int x
)
333 promcon_putcs(conp
, &s
, 1, y
, x
);
337 promcon_clear(struct vc_data
*conp
, int sy
, int sx
, int height
, int width
)
339 unsigned char buf
[256], *b
= buf
;
345 b
+= promcon_start(conp
, b
);
347 if (!sx
&& width
== pw
+ 1) {
349 if (!sy
&& height
== ph
+ 1) {
350 strcpy(b
, "\033[H\033[J");
352 b
+= promcon_end(conp
, b
);
353 promcon_puts(buf
, b
- buf
);
355 } else if (sy
+ height
== ph
+ 1) {
356 b
+= sprintf(b
, "\033[%dH\033[J", sy
+ 1);
357 b
+= promcon_end(conp
, b
);
358 promcon_puts(buf
, b
- buf
);
362 b
+= sprintf(b
, "\033[%dH", sy
+ 1);
363 for (i
= 1; i
< height
; i
++) {
364 strcpy(b
, "\033[K\n");
371 b
+= promcon_end(conp
, b
);
372 promcon_puts(buf
, b
- buf
);
375 } else if (sx
+ width
== pw
+ 1) {
377 b
+= sprintf(b
, "\033[%d;%dH", sy
+ 1, sx
+ 1);
378 for (i
= 1; i
< height
; i
++) {
379 strcpy(b
, "\033[K\n");
386 b
+= promcon_end(conp
, b
);
387 promcon_puts(buf
, b
- buf
);
391 for (i
= sy
+ 1; i
<= sy
+ height
; i
++) {
392 b
+= sprintf(b
, "\033[%d;%dH", i
, sx
+ 1);
393 for (j
= 0; j
< width
; j
++)
395 if (b
- buf
+ width
>= 224) {
396 promcon_puts(buf
, b
- buf
);
401 b
+= promcon_end(conp
, b
);
402 promcon_puts(buf
, b
- buf
);
406 promcon_bmove(struct vc_data
*conp
, int sy
, int sx
, int dy
, int dx
,
407 int height
, int width
)
409 char buf
[256], *b
= buf
;
414 b
+= promcon_start(conp
, b
);
415 if (sy
== dy
&& height
== 1) {
416 if (dx
> sx
&& dx
+ width
== conp
->vc_cols
)
417 b
+= sprintf(b
, "\033[%d;%dH\033[%d@\033[%d;%dH",
418 sy
+ 1, sx
+ 1, dx
- sx
, py
+ 1, px
+ 1);
419 else if (dx
< sx
&& sx
+ width
== conp
->vc_cols
)
420 b
+= sprintf(b
, "\033[%d;%dH\033[%dP\033[%d;%dH",
421 dy
+ 1, dx
+ 1, sx
- dx
, py
+ 1, px
+ 1);
423 b
+= promcon_end(conp
, b
);
424 promcon_puts(buf
, b
- buf
);
429 * FIXME: What to do here???
430 * Current console.c should not call it like that ever.
432 prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
436 promcon_cursor(struct vc_data
*conp
, int mode
)
438 char buf
[32], *b
= buf
;
446 b
+= promcon_start(conp
, b
);
447 if (px
!= conp
->vc_x
|| py
!= conp
->vc_y
) {
450 b
+= sprintf(b
, "\033[%d;%dH", py
+ 1, px
+ 1);
452 promcon_puts(buf
, b
- buf
);
458 promcon_blank(struct vc_data
*conp
, int blank
, int mode_switch
)
461 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
464 /* Let console.c redraw */
470 promcon_scroll(struct vc_data
*conp
, int t
, int b
, int dir
, int count
)
472 unsigned char buf
[256], *p
= buf
;
479 p
+= promcon_start(conp
, p
);
484 p
+= sprintf(p
, "\033[%dH\033[%dM", t
+ 1, count
);
487 p
+= promcon_end(conp
, p
);
488 promcon_puts(buf
, p
- buf
);
492 s
= (unsigned short *)(conp
->vc_origin
493 + (t
+ count
) * conp
->vc_size_row
);
495 p
+= sprintf(p
, "\033[%dH", t
+ 1);
497 for (i
= t
; i
< b
- count
; i
++)
498 s
= promcon_repaint_line(s
, buf
, &p
);
500 for (; i
< b
- 1; i
++) {
501 strcpy(p
, "\033[K\n");
503 if (p
- buf
>= 224) {
504 promcon_puts(buf
, p
- buf
);
512 p
+= promcon_end(conp
, p
);
513 promcon_puts(buf
, p
- buf
);
518 p
+= sprintf(p
, "\033[%dH\033[%dL", t
+ 1, count
);
521 p
+= promcon_end(conp
, p
);
522 promcon_puts(buf
, p
- buf
);
526 s
= (unsigned short *)(conp
->vc_origin
+ t
* conp
->vc_size_row
);
528 p
+= sprintf(p
, "\033[%dH", t
+ 1);
530 for (i
= t
; i
< t
+ count
; i
++) {
531 strcpy(p
, "\033[K\n");
533 if (p
- buf
>= 224) {
534 promcon_puts(buf
, p
- buf
);
540 s
= promcon_repaint_line(s
, buf
, &p
);
542 p
+= promcon_end(conp
, p
);
543 promcon_puts(buf
, p
- buf
);
551 static u8
promcon_build_attr(struct vc_data
*conp
, u8 _color
, u8 _intensity
,
552 u8 _blink
, u8 _underline
, u8 _reverse
, u8 _italic
)
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 const struct consw prom_con
= {
570 .owner
= THIS_MODULE
,
571 .con_startup
= promcon_startup
,
572 .con_init
= promcon_init
,
573 .con_deinit
= promcon_deinit
,
574 .con_clear
= promcon_clear
,
575 .con_putc
= promcon_putc
,
576 .con_putcs
= promcon_putcs
,
577 .con_cursor
= promcon_cursor
,
578 .con_scroll
= promcon_scroll
,
579 .con_bmove
= promcon_bmove
,
580 .con_switch
= promcon_switch
,
581 .con_blank
= promcon_blank
,
582 .con_set_palette
= DUMMY
,
583 .con_scrolldelta
= DUMMY
,
585 .con_build_attr
= promcon_build_attr
,
589 void __init
prom_con_init(void)
591 #ifdef CONFIG_DUMMY_CONSOLE
592 if (conswitchp
== &dummy_con
)
593 take_over_console(&prom_con
, 0, MAX_NR_CONSOLES
-1, 1);
596 if (conswitchp
== &prom_con
)
597 promcon_init_unimap(vc_cons
[fg_console
].d
);