Linux kernel & device driver programming

Cross-Referenced Linux and Device Driver Code

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