~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Linux Cross Reference
Linux/drivers/video/promcon.c

Version: ~ [ 2.4.0 ] ~
Architecture: ~ [ i386 ] ~ [ alpha ] ~ [ m68k ] ~ [ mips ] ~ [ ppc ] ~ [ sparc ] ~ [ sparc64 ] ~

  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/config.h>
  9 #include <linux/module.h>
 10 #include <linux/kernel.h>
 11 #include <linux/errno.h>
 12 #include <linux/string.h>
 13 #include <linux/mm.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>
 21 #include <linux/fb.h>
 22 #include <linux/init.h>
 23 #include <linux/kd.h>
 24 
 25 #include <asm/oplib.h>
 26 #include <asm/uaccess.h>
 27 
 28 static short pw = 80 - 1, ph = 34 - 1;
 29 static short px, py;
 30 static unsigned long promcon_uni_pagedir[2];
 31 
 32 extern u8 promfont_unicount[];
 33 extern u16 promfont_unitable[];
 34 
 35 #define PROMCON_COLOR 0
 36 
 37 #if PROMCON_COLOR
 38 #define inverted(s)     ((((s) & 0x7700) == 0x0700) ? 0 : 1)
 39 #else
 40 #define inverted(s)     (((s) & 0x0800) ? 1 : 0)
 41 #endif
 42 
 43 static __inline__ void
 44 promcon_puts(char *buf, int cnt)
 45 {
 46         prom_printf("%*.*s", cnt, cnt, buf);
 47 }
 48 
 49 static int
 50 promcon_start(struct vc_data *conp, char *b)
 51 {
 52         unsigned short *s = (unsigned short *)
 53                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 54 
 55         if (px == pw) {
 56                 unsigned short *t = s - 1;
 57 
 58                 if (inverted(*s) && inverted(*t))
 59                         return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m",
 60                                        *s, *t);
 61                 else if (inverted(*s))
 62                         return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c",
 63                                        *s, *t);
 64                 else if (inverted(*t))
 65                         return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m",
 66                                        *s, *t);
 67                 else
 68                         return sprintf(b, "\b%c\b\033[@%c", *s, *t);
 69         }
 70 
 71         if (inverted(*s))
 72                 return sprintf(b, "\033[7m%c\033[m\b", *s);
 73         else
 74                 return sprintf(b, "%c\b", *s);
 75 }
 76 
 77 static int
 78 promcon_end(struct vc_data *conp, char *b)
 79 {
 80         unsigned short *s = (unsigned short *)
 81                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 82         char *p = b;
 83 
 84         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
 85 
 86         if (px == pw) {
 87                 unsigned short *t = s - 1;
 88 
 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);
 95                 else
 96                         b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", *s, *t);
 97                 return b - p;
 98         }
 99 
100         if (inverted(*s))
101                 b += sprintf(b, "%c\b", *s);
102         else
103                 b += sprintf(b, "\033[7m%c\033[m\b", *s);
104         return b - p;
105 }
106 
107 const char __init *promcon_startup(void)
108 {
109         const char *display_desc = "PROM";
110         int node;
111         char buf[40];
112         
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)
118                         pw = 80;
119                 pw--;
120         }
121         if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
122                 ph = simple_strtoul(buf, NULL, 0);
123                 if (ph < 10 || ph > 256)
124                         ph = 34;
125                 ph--;
126         }
127         promcon_puts("\033[H\033[J", 6);
128         return display_desc;
129 }
130 
131 static void __init 
132 promcon_init_unimap(struct vc_data *conp)
133 {
134         mm_segment_t old_fs = get_fs();
135         struct unipair *p, *p1;
136         u16 *q;
137         int i, j, k;
138         
139         p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
140         if (!p) return;
141         
142         q = promfont_unitable;
143         p1 = p;
144         k = 0;
145         for (i = 0; i < 256; i++)
146                 for (j = promfont_unicount[i]; j; j--) {
147                         p1->unicode = *q++;
148                         p1->fontpos = i;
149                         p1++;
150                         k++;
151                 }
152         set_fs(KERNEL_DS);
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);
156         set_fs(old_fs);
157         kfree(p);
158 }
159 
160 static void
161 promcon_init(struct vc_data *conp, int init)
162 {
163         unsigned long p;
164         
165         conp->vc_can_do_color = PROMCON_COLOR;
166         if (init) {
167                 conp->vc_cols = pw + 1;
168                 conp->vc_rows = ph + 1;
169         }
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);
178         }
179         if (!init) {
180                 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
181                         vc_resize_con(ph + 1, pw + 1, conp->vc_num);
182         }
183 }
184 
185 static void
186 promcon_deinit(struct vc_data *conp)
187 {
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);
193 }
194 
195 static int
196 promcon_switch(struct vc_data *conp)
197 {
198         return 1;
199 }
200 
201 static unsigned short *
202 promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
203 {
204         int cnt = pw + 1;
205         int attr = -1;
206         unsigned char *b = *bp;
207 
208         while (cnt--) {
209                 if (attr != inverted(*s)) {
210                         attr = inverted(*s);
211                         if (attr) {
212                                 strcpy (b, "\033[7m");
213                                 b += 4;
214                         } else {
215                                 strcpy (b, "\033[m");
216                                 b += 3;
217                         }
218                 }
219                 *b++ = *s++;
220                 if (b - buf >= 224) {
221                         promcon_puts(buf, b - buf);
222                         b = buf;
223                 }
224         }
225         *bp = b;
226         return s;
227 }
228 
229 static void
230 promcon_putcs(struct vc_data *conp, const unsigned short *s,
231               int count, int y, int x)
232 {
233         unsigned char buf[256], *b = buf;
234         unsigned short attr = scr_readw(s);
235         unsigned char save;
236         int i, last = 0;
237 
238         if (console_blanked)
239                 return;
240         
241         if (count <= 0)
242                 return;
243 
244         b += promcon_start(conp, b);
245 
246         if (x + count >= pw + 1) {
247                 if (count == 1) {
248                         x -= 1;
249                         save = *(unsigned short *)(conp->vc_origin
250                                                    + y * conp->vc_size_row
251                                                    + (x << 1));
252 
253                         if (px != x || py != y) {
254                                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
255                                 px = x;
256                                 py = y;
257                         }
258 
259                         if (inverted(attr))
260                                 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
261                         else
262                                 b += sprintf(b, "%c", scr_readw(s++));
263 
264                         strcpy(b, "\b\033[@");
265                         b += 4;
266 
267                         if (inverted(save))
268                                 b += sprintf(b, "\033[7m%c\033[m", save);
269                         else
270                                 b += sprintf(b, "%c", save);
271 
272                         px++;
273 
274                         b += promcon_end(conp, b);
275                         promcon_puts(buf, b - buf);
276                         return;
277                 } else {
278                         last = 1;
279                         count = pw - x - 1;
280                 }
281         }
282 
283         if (inverted(attr)) {
284                 strcpy(b, "\033[7m");
285                 b += 4;
286         }
287 
288         if (px != x || py != y) {
289                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
290                 px = x;
291                 py = y;
292         }
293 
294         for (i = 0; i < count; i++) {
295                 if (b - buf >= 224) {
296                         promcon_puts(buf, b - buf);
297                         b = buf;
298                 }
299                 *b++ = scr_readw(s++);
300         }
301 
302         px += count;
303 
304         if (last) {
305                 save = scr_readw(s++);
306                 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
307                 px++;
308         }
309 
310         if (inverted(attr)) {
311                 strcpy(b, "\033[m");
312                 b += 3;
313         }
314 
315         b += promcon_end(conp, b);
316         promcon_puts(buf, b - buf);
317 }
318 
319 static void
320 promcon_putc(struct vc_data *conp, int c, int y, int x)
321 {
322         unsigned short s;
323 
324         if (console_blanked)
325                 return;
326         
327         scr_writew(c, &s);
328         promcon_putcs(conp, &s, 1, y, x);
329 }
330 
331 static void
332 promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
333 {
334         unsigned char buf[256], *b = buf;
335         int i, j;
336 
337         if (console_blanked)
338                 return;
339         
340         b += promcon_start(conp, b);
341 
342         if (!sx && width == pw + 1) {
343 
344                 if (!sy && height == ph + 1) {
345                         strcpy(b, "\033[H\033[J");
346                         b += 6;
347                         b += promcon_end(conp, b);
348                         promcon_puts(buf, b - buf);
349                         return;
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);
354                         return;
355                 }
356 
357                 b += sprintf(b, "\033[%dH", sy + 1);
358                 for (i = 1; i < height; i++) {
359                         strcpy(b, "\033[K\n");
360                         b += 4;
361                 }
362 
363                 strcpy(b, "\033[K");
364                 b += 3;
365 
366                 b += promcon_end(conp, b);
367                 promcon_puts(buf, b - buf);
368                 return;
369 
370         } else if (sx + width == pw + 1) {
371 
372                 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
373                 for (i = 1; i < height; i++) {
374                         strcpy(b, "\033[K\n");
375                         b += 4;
376                 }
377 
378                 strcpy(b, "\033[K");
379                 b += 3;
380 
381                 b += promcon_end(conp, b);
382                 promcon_puts(buf, b - buf);
383                 return;
384         }
385 
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++)
389                         *b++ = ' ';
390                 if (b - buf + width >= 224) {
391                         promcon_puts(buf, b - buf);
392                         b = buf;
393                 }
394         }
395 
396         b += promcon_end(conp, b);
397         promcon_puts(buf, b - buf);
398 }
399                         
400 static void
401 promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
402               int height, int width)
403 {
404         char buf[256], *b = buf;
405 
406         if (console_blanked)
407                 return;
408         
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);
417 
418                 b += promcon_end(conp, b);
419                 promcon_puts(buf, b - buf);
420                 return;
421         }
422 
423         /*
424          * FIXME: What to do here???
425          * Current console.c should not call it like that ever.
426          */
427         prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
428 }
429 
430 static void
431 promcon_cursor(struct vc_data *conp, int mode)
432 {
433         char buf[32], *b = buf;
434 
435         switch (mode) {
436         case CM_ERASE:
437                 break;
438 
439         case CM_MOVE:
440         case CM_DRAW:
441                 b += promcon_start(conp, b);
442                 if (px != conp->vc_x || py != conp->vc_y) {
443                         px = conp->vc_x;
444                         py = conp->vc_y;
445                         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
446                 }
447                 promcon_puts(buf, b - buf);
448                 break;
449         }
450 }
451 
452 static int
453 promcon_font_op(struct vc_data *conp, struct console_font_op *op)
454 {
455         return -ENOSYS;
456 }
457         
458 static int
459 promcon_blank(struct vc_data *conp, int blank)
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         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 #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 }
599 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.