]> git.karo-electronics.de Git - mv-sheeva.git/blob - drivers/video/console/promcon.c
Remove obsolete #include <linux/config.h>
[mv-sheeva.git] / drivers / video / console / promcon.c
1 /* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $
2  * Console driver utilizing PROM sun terminal emulation
3  *
4  * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
5  * Copyright (C) 1998  Jakub Jelinek  (jj@ultra.linux.cz)
6  */
7
8 #include <linux/module.h>
9 #include <linux/kernel.h>
10 #include <linux/errno.h>
11 #include <linux/string.h>
12 #include <linux/mm.h>
13 #include <linux/tty.h>
14 #include <linux/slab.h>
15 #include <linux/delay.h>
16 #include <linux/console.h>
17 #include <linux/vt_kern.h>
18 #include <linux/selection.h>
19 #include <linux/fb.h>
20 #include <linux/init.h>
21 #include <linux/kd.h>
22
23 #include <asm/oplib.h>
24 #include <asm/uaccess.h>
25
26 static short pw = 80 - 1, ph = 34 - 1;
27 static short px, py;
28 static unsigned long promcon_uni_pagedir[2];
29
30 extern u8 promfont_unicount[];
31 extern u16 promfont_unitable[];
32
33 #define PROMCON_COLOR 0
34
35 #if PROMCON_COLOR
36 #define inverted(s)     ((((s) & 0x7700) == 0x0700) ? 0 : 1)
37 #else
38 #define inverted(s)     (((s) & 0x0800) ? 1 : 0)
39 #endif
40
41 static __inline__ void
42 promcon_puts(char *buf, int cnt)
43 {
44         prom_printf("%*.*s", cnt, cnt, buf);
45 }
46
47 static int
48 promcon_start(struct vc_data *conp, char *b)
49 {
50         unsigned short *s = (unsigned short *)
51                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
52         u16 cs;
53
54         cs = scr_readw(s);
55         if (px == pw) {
56                 unsigned short *t = s - 1;
57                 u16 ct = scr_readw(t);
58
59                 if (inverted(cs) && inverted(ct))
60                         return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
61                                        ct);
62                 else if (inverted(cs))
63                         return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
64                                        ct);
65                 else if (inverted(ct))
66                         return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
67                                        ct);
68                 else
69                         return sprintf(b, "\b%c\b\033[@%c", cs, ct);
70         }
71
72         if (inverted(cs))
73                 return sprintf(b, "\033[7m%c\033[m\b", cs);
74         else
75                 return sprintf(b, "%c\b", cs);
76 }
77
78 static int
79 promcon_end(struct vc_data *conp, char *b)
80 {
81         unsigned short *s = (unsigned short *)
82                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
83         char *p = b;
84         u16 cs;
85
86         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
87
88         cs = scr_readw(s);
89         if (px == pw) {
90                 unsigned short *t = s - 1;
91                 u16 ct = scr_readw(t);
92
93                 if (inverted(cs) && inverted(ct))
94                         b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
95                 else if (inverted(cs))
96                         b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
97                 else if (inverted(ct))
98                         b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
99                 else
100                         b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
101                 return b - p;
102         }
103
104         if (inverted(cs))
105                 b += sprintf(b, "%c\b", cs);
106         else
107                 b += sprintf(b, "\033[7m%c\033[m\b", cs);
108         return b - p;
109 }
110
111 const char *promcon_startup(void)
112 {
113         const char *display_desc = "PROM";
114         int node;
115         char buf[40];
116         
117         node = prom_getchild(prom_root_node);
118         node = prom_searchsiblings(node, "options");
119         if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
120                 pw = simple_strtoul(buf, NULL, 0);
121                 if (pw < 10 || pw > 256)
122                         pw = 80;
123                 pw--;
124         }
125         if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
126                 ph = simple_strtoul(buf, NULL, 0);
127                 if (ph < 10 || ph > 256)
128                         ph = 34;
129                 ph--;
130         }
131         promcon_puts("\033[H\033[J", 6);
132         return display_desc;
133 }
134
135 static void
136 promcon_init_unimap(struct vc_data *conp)
137 {
138         mm_segment_t old_fs = get_fs();
139         struct unipair *p, *p1;
140         u16 *q;
141         int i, j, k;
142         
143         p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
144         if (!p) return;
145         
146         q = promfont_unitable;
147         p1 = p;
148         k = 0;
149         for (i = 0; i < 256; i++)
150                 for (j = promfont_unicount[i]; j; j--) {
151                         p1->unicode = *q++;
152                         p1->fontpos = i;
153                         p1++;
154                         k++;
155                 }
156         set_fs(KERNEL_DS);
157         con_clear_unimap(conp, NULL);
158         con_set_unimap(conp, k, p);
159         con_protect_unimap(conp, 1);
160         set_fs(old_fs);
161         kfree(p);
162 }
163
164 static void
165 promcon_init(struct vc_data *conp, int init)
166 {
167         unsigned long p;
168         
169         conp->vc_can_do_color = PROMCON_COLOR;
170         if (init) {
171                 conp->vc_cols = pw + 1;
172                 conp->vc_rows = ph + 1;
173         }
174         p = *conp->vc_uni_pagedir_loc;
175         if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
176             !--conp->vc_uni_pagedir_loc[1])
177                 con_free_unimap(conp);
178         conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
179         promcon_uni_pagedir[1]++;
180         if (!promcon_uni_pagedir[0] && p) {
181                 promcon_init_unimap(conp);
182         }
183         if (!init) {
184                 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
185                         vc_resize(conp, pw + 1, ph + 1);
186         }
187 }
188
189 static void
190 promcon_deinit(struct vc_data *conp)
191 {
192         /* When closing the last console, reset video origin */
193         if (!--promcon_uni_pagedir[1])
194                 con_free_unimap(conp);
195         conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
196         con_set_default_unimap(conp);
197 }
198
199 static int
200 promcon_switch(struct vc_data *conp)
201 {
202         return 1;
203 }
204
205 static unsigned short *
206 promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
207 {
208         int cnt = pw + 1;
209         int attr = -1;
210         unsigned char *b = *bp;
211
212         while (cnt--) {
213                 u16 c = scr_readw(s);
214                 if (attr != inverted(c)) {
215                         attr = inverted(c);
216                         if (attr) {
217                                 strcpy (b, "\033[7m");
218                                 b += 4;
219                         } else {
220                                 strcpy (b, "\033[m");
221                                 b += 3;
222                         }
223                 }
224                 *b++ = c;
225                 s++;
226                 if (b - buf >= 224) {
227                         promcon_puts(buf, b - buf);
228                         b = buf;
229                 }
230         }
231         *bp = b;
232         return s;
233 }
234
235 static void
236 promcon_putcs(struct vc_data *conp, const unsigned short *s,
237               int count, int y, int x)
238 {
239         unsigned char buf[256], *b = buf;
240         unsigned short attr = scr_readw(s);
241         unsigned char save;
242         int i, last = 0;
243
244         if (console_blanked)
245                 return;
246         
247         if (count <= 0)
248                 return;
249
250         b += promcon_start(conp, b);
251
252         if (x + count >= pw + 1) {
253                 if (count == 1) {
254                         x -= 1;
255                         save = scr_readw((unsigned short *)(conp->vc_origin
256                                                    + y * conp->vc_size_row
257                                                    + (x << 1)));
258
259                         if (px != x || py != y) {
260                                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
261                                 px = x;
262                                 py = y;
263                         }
264
265                         if (inverted(attr))
266                                 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
267                         else
268                                 b += sprintf(b, "%c", scr_readw(s++));
269
270                         strcpy(b, "\b\033[@");
271                         b += 4;
272
273                         if (inverted(save))
274                                 b += sprintf(b, "\033[7m%c\033[m", save);
275                         else
276                                 b += sprintf(b, "%c", save);
277
278                         px++;
279
280                         b += promcon_end(conp, b);
281                         promcon_puts(buf, b - buf);
282                         return;
283                 } else {
284                         last = 1;
285                         count = pw - x - 1;
286                 }
287         }
288
289         if (inverted(attr)) {
290                 strcpy(b, "\033[7m");
291                 b += 4;
292         }
293
294         if (px != x || py != y) {
295                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
296                 px = x;
297                 py = y;
298         }
299
300         for (i = 0; i < count; i++) {
301                 if (b - buf >= 224) {
302                         promcon_puts(buf, b - buf);
303                         b = buf;
304                 }
305                 *b++ = scr_readw(s++);
306         }
307
308         px += count;
309
310         if (last) {
311                 save = scr_readw(s++);
312                 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
313                 px++;
314         }
315
316         if (inverted(attr)) {
317                 strcpy(b, "\033[m");
318                 b += 3;
319         }
320
321         b += promcon_end(conp, b);
322         promcon_puts(buf, b - buf);
323 }
324
325 static void
326 promcon_putc(struct vc_data *conp, int c, int y, int x)
327 {
328         unsigned short s;
329
330         if (console_blanked)
331                 return;
332         
333         scr_writew(c, &s);
334         promcon_putcs(conp, &s, 1, y, x);
335 }
336
337 static void
338 promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
339 {
340         unsigned char buf[256], *b = buf;
341         int i, j;
342
343         if (console_blanked)
344                 return;
345         
346         b += promcon_start(conp, b);
347
348         if (!sx && width == pw + 1) {
349
350                 if (!sy && height == ph + 1) {
351                         strcpy(b, "\033[H\033[J");
352                         b += 6;
353                         b += promcon_end(conp, b);
354                         promcon_puts(buf, b - buf);
355                         return;
356                 } else if (sy + height == ph + 1) {
357                         b += sprintf(b, "\033[%dH\033[J", sy + 1);
358                         b += promcon_end(conp, b);
359                         promcon_puts(buf, b - buf);
360                         return;
361                 }
362
363                 b += sprintf(b, "\033[%dH", sy + 1);
364                 for (i = 1; i < height; i++) {
365                         strcpy(b, "\033[K\n");
366                         b += 4;
367                 }
368
369                 strcpy(b, "\033[K");
370                 b += 3;
371
372                 b += promcon_end(conp, b);
373                 promcon_puts(buf, b - buf);
374                 return;
375
376         } else if (sx + width == pw + 1) {
377
378                 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
379                 for (i = 1; i < height; i++) {
380                         strcpy(b, "\033[K\n");
381                         b += 4;
382                 }
383
384                 strcpy(b, "\033[K");
385                 b += 3;
386
387                 b += promcon_end(conp, b);
388                 promcon_puts(buf, b - buf);
389                 return;
390         }
391
392         for (i = sy + 1; i <= sy + height; i++) {
393                 b += sprintf(b, "\033[%d;%dH", i, sx + 1);
394                 for (j = 0; j < width; j++)
395                         *b++ = ' ';
396                 if (b - buf + width >= 224) {
397                         promcon_puts(buf, b - buf);
398                         b = buf;
399                 }
400         }
401
402         b += promcon_end(conp, b);
403         promcon_puts(buf, b - buf);
404 }
405                         
406 static void
407 promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
408               int height, int width)
409 {
410         char buf[256], *b = buf;
411
412         if (console_blanked)
413                 return;
414         
415         b += promcon_start(conp, b);
416         if (sy == dy && height == 1) {
417                 if (dx > sx && dx + width == conp->vc_cols)
418                         b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
419                                      sy + 1, sx + 1, dx - sx, py + 1, px + 1);
420                 else if (dx < sx && sx + width == conp->vc_cols)
421                         b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
422                                      dy + 1, dx + 1, sx - dx, py + 1, px + 1);
423
424                 b += promcon_end(conp, b);
425                 promcon_puts(buf, b - buf);
426                 return;
427         }
428
429         /*
430          * FIXME: What to do here???
431          * Current console.c should not call it like that ever.
432          */
433         prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
434 }
435
436 static void
437 promcon_cursor(struct vc_data *conp, int mode)
438 {
439         char buf[32], *b = buf;
440
441         switch (mode) {
442         case CM_ERASE:
443                 break;
444
445         case CM_MOVE:
446         case CM_DRAW:
447                 b += promcon_start(conp, b);
448                 if (px != conp->vc_x || py != conp->vc_y) {
449                         px = conp->vc_x;
450                         py = conp->vc_y;
451                         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
452                 }
453                 promcon_puts(buf, b - buf);
454                 break;
455         }
456 }
457
458 static int
459 promcon_blank(struct vc_data *conp, int blank, int mode_switch)
460 {
461         if (blank) {
462                 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
463                 return 0;
464         } else {
465                 /* Let console.c redraw */
466                 return 1;
467         }
468 }
469
470 static int
471 promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
472 {
473         unsigned char buf[256], *p = buf;
474         unsigned short *s;
475         int i;
476
477         if (console_blanked)
478                 return 0;
479         
480         p += promcon_start(conp, p);
481
482         switch (dir) {
483         case SM_UP:
484                 if (b == ph + 1) {
485                         p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
486                         px = 0;
487                         py = t;
488                         p += promcon_end(conp, p);
489                         promcon_puts(buf, p - buf);
490                         break;
491                 }
492
493                 s = (unsigned short *)(conp->vc_origin
494                                        + (t + count) * conp->vc_size_row);
495
496                 p += sprintf(p, "\033[%dH", t + 1);
497
498                 for (i = t; i < b - count; i++)
499                         s = promcon_repaint_line(s, buf, &p);
500
501                 for (; i < b - 1; i++) {
502                         strcpy(p, "\033[K\n");
503                         p += 4;
504                         if (p - buf >= 224) {
505                                 promcon_puts(buf, p - buf);
506                                 p = buf;
507                         }
508                 }
509
510                 strcpy(p, "\033[K");
511                 p += 3;
512
513                 p += promcon_end(conp, p);
514                 promcon_puts(buf, p - buf);
515                 break;
516
517         case SM_DOWN:
518                 if (b == ph + 1) {
519                         p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
520                         px = 0;
521                         py = t;
522                         p += promcon_end(conp, p);
523                         promcon_puts(buf, p - buf);
524                         break;
525                 }
526
527                 s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
528
529                 p += sprintf(p, "\033[%dH", t + 1);
530
531                 for (i = t; i < t + count; i++) {
532                         strcpy(p, "\033[K\n");
533                         p += 4;
534                         if (p - buf >= 224) {
535                                 promcon_puts(buf, p - buf);
536                                 p = buf;
537                         }
538                 }
539
540                 for (; i < b; i++)
541                         s = promcon_repaint_line(s, buf, &p);
542
543                 p += promcon_end(conp, p);
544                 promcon_puts(buf, p - buf);
545                 break;
546         }
547
548         return 0;
549 }
550
551 #if !(PROMCON_COLOR)
552 static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
553 {
554         return (_reverse) ? 0xf : 0x7;
555 }
556 #endif
557
558 /*
559  *  The console 'switch' structure for the VGA based console
560  */
561
562 static int promcon_dummy(void)
563 {
564         return 0;
565 }
566
567 #define DUMMY (void *) promcon_dummy
568
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,
584 #if !(PROMCON_COLOR)
585         .con_build_attr =       promcon_build_attr,
586 #endif
587 };
588
589 void __init prom_con_init(void)
590 {
591 #ifdef CONFIG_DUMMY_CONSOLE
592         if (conswitchp == &dummy_con)
593                 take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
594         else
595 #endif
596         if (conswitchp == &prom_con)
597                 promcon_init_unimap(vc_cons[fg_console].d);
598 }