+++ /dev/null
-/* $Id: promcon.c,v 1.17 2000/07/26 23:02:52 davem Exp $
- * Console driver utilizing PROM sun terminal emulation
- *
- * Copyright (C) 1998  Eddie C. Dost  (ecd@skynet.be)
- * Copyright (C) 1998  Jakub Jelinek  (jj@ultra.linux.cz)
- */
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/errno.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/slab.h>
-#include <linux/delay.h>
-#include <linux/console.h>
-#include <linux/vt_kern.h>
-#include <linux/selection.h>
-#include <linux/fb.h>
-#include <linux/init.h>
-#include <linux/kd.h>
-
-#include <asm/oplib.h>
-#include <asm/uaccess.h>
-
-static short pw = 80 - 1, ph = 34 - 1;
-static short px, py;
-static unsigned long promcon_uni_pagedir[2];
-
-extern u8 promfont_unicount[];
-extern u16 promfont_unitable[];
-
-#define PROMCON_COLOR 0
-
-#if PROMCON_COLOR
-#define inverted(s)    ((((s) & 0x7700) == 0x0700) ? 0 : 1)
-#else
-#define inverted(s)    (((s) & 0x0800) ? 1 : 0)
-#endif
-
-static __inline__ void
-promcon_puts(char *buf, int cnt)
-{
-       prom_printf("%*.*s", cnt, cnt, buf);
-}
-
-static int
-promcon_start(struct vc_data *conp, char *b)
-{
-       unsigned short *s = (unsigned short *)
-                       (conp->vc_origin + py * conp->vc_size_row + (px << 1));
-       u16 cs;
-
-       cs = scr_readw(s);
-       if (px == pw) {
-               unsigned short *t = s - 1;
-               u16 ct = scr_readw(t);
-
-               if (inverted(cs) && inverted(ct))
-                       return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
-                                      ct);
-               else if (inverted(cs))
-                       return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
-                                      ct);
-               else if (inverted(ct))
-                       return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
-                                      ct);
-               else
-                       return sprintf(b, "\b%c\b\033[@%c", cs, ct);
-       }
-
-       if (inverted(cs))
-               return sprintf(b, "\033[7m%c\033[m\b", cs);
-       else
-               return sprintf(b, "%c\b", cs);
-}
-
-static int
-promcon_end(struct vc_data *conp, char *b)
-{
-       unsigned short *s = (unsigned short *)
-                       (conp->vc_origin + py * conp->vc_size_row + (px << 1));
-       char *p = b;
-       u16 cs;
-
-       b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
-
-       cs = scr_readw(s);
-       if (px == pw) {
-               unsigned short *t = s - 1;
-               u16 ct = scr_readw(t);
-
-               if (inverted(cs) && inverted(ct))
-                       b += sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs, ct);
-               else if (inverted(cs))
-                       b += sprintf(b, "\b%c\b\033[@%c", cs, ct);
-               else if (inverted(ct))
-                       b += sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs, ct);
-               else
-                       b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
-               return b - p;
-       }
-
-       if (inverted(cs))
-               b += sprintf(b, "%c\b", cs);
-       else
-               b += sprintf(b, "\033[7m%c\033[m\b", cs);
-       return b - p;
-}
-
-const char *promcon_startup(void)
-{
-       const char *display_desc = "PROM";
-       int node;
-       char buf[40];
-       
-       node = prom_getchild(prom_root_node);
-       node = prom_searchsiblings(node, "options");
-       if (prom_getproperty(node,  "screen-#columns", buf, 40) != -1) {
-               pw = simple_strtoul(buf, NULL, 0);
-               if (pw < 10 || pw > 256)
-                       pw = 80;
-               pw--;
-       }
-       if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
-               ph = simple_strtoul(buf, NULL, 0);
-               if (ph < 10 || ph > 256)
-                       ph = 34;
-               ph--;
-       }
-       promcon_puts("\033[H\033[J", 6);
-       return display_desc;
-}
-
-static void
-promcon_init_unimap(struct vc_data *conp)
-{
-       mm_segment_t old_fs = get_fs();
-       struct unipair *p, *p1;
-       u16 *q;
-       int i, j, k;
-       
-       p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
-       if (!p) return;
-       
-       q = promfont_unitable;
-       p1 = p;
-       k = 0;
-       for (i = 0; i < 256; i++)
-               for (j = promfont_unicount[i]; j; j--) {
-                       p1->unicode = *q++;
-                       p1->fontpos = i;
-                       p1++;
-                       k++;
-               }
-       set_fs(KERNEL_DS);
-       con_clear_unimap(conp, NULL);
-       con_set_unimap(conp, k, p);
-       con_protect_unimap(conp, 1);
-       set_fs(old_fs);
-       kfree(p);
-}
-
-static void
-promcon_init(struct vc_data *conp, int init)
-{
-       unsigned long p;
-       
-       conp->vc_can_do_color = PROMCON_COLOR;
-       if (init) {
-               conp->vc_cols = pw + 1;
-               conp->vc_rows = ph + 1;
-       }
-       p = *conp->vc_uni_pagedir_loc;
-       if (conp->vc_uni_pagedir_loc == &conp->vc_uni_pagedir ||
-           !--conp->vc_uni_pagedir_loc[1])
-               con_free_unimap(conp);
-       conp->vc_uni_pagedir_loc = promcon_uni_pagedir;
-       promcon_uni_pagedir[1]++;
-       if (!promcon_uni_pagedir[0] && p) {
-               promcon_init_unimap(conp);
-       }
-       if (!init) {
-               if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
-                       vc_resize(conp, pw + 1, ph + 1);
-       }
-}
-
-static void
-promcon_deinit(struct vc_data *conp)
-{
-       /* When closing the last console, reset video origin */
-       if (!--promcon_uni_pagedir[1])
-               con_free_unimap(conp);
-       conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
-       con_set_default_unimap(conp);
-}
-
-static int
-promcon_switch(struct vc_data *conp)
-{
-       return 1;
-}
-
-static unsigned short *
-promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
-{
-       int cnt = pw + 1;
-       int attr = -1;
-       unsigned char *b = *bp;
-
-       while (cnt--) {
-               u16 c = scr_readw(s);
-               if (attr != inverted(c)) {
-                       attr = inverted(c);
-                       if (attr) {
-                               strcpy (b, "\033[7m");
-                               b += 4;
-                       } else {
-                               strcpy (b, "\033[m");
-                               b += 3;
-                       }
-               }
-               *b++ = c;
-               s++;
-               if (b - buf >= 224) {
-                       promcon_puts(buf, b - buf);
-                       b = buf;
-               }
-       }
-       *bp = b;
-       return s;
-}
-
-static void
-promcon_putcs(struct vc_data *conp, const unsigned short *s,
-             int count, int y, int x)
-{
-       unsigned char buf[256], *b = buf;
-       unsigned short attr = scr_readw(s);
-       unsigned char save;
-       int i, last = 0;
-
-       if (console_blanked)
-               return;
-       
-       if (count <= 0)
-               return;
-
-       b += promcon_start(conp, b);
-
-       if (x + count >= pw + 1) {
-               if (count == 1) {
-                       x -= 1;
-                       save = scr_readw((unsigned short *)(conp->vc_origin
-                                                  + y * conp->vc_size_row
-                                                  + (x << 1)));
-
-                       if (px != x || py != y) {
-                               b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
-                               px = x;
-                               py = y;
-                       }
-
-                       if (inverted(attr))
-                               b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
-                       else
-                               b += sprintf(b, "%c", scr_readw(s++));
-
-                       strcpy(b, "\b\033[@");
-                       b += 4;
-
-                       if (inverted(save))
-                               b += sprintf(b, "\033[7m%c\033[m", save);
-                       else
-                               b += sprintf(b, "%c", save);
-
-                       px++;
-
-                       b += promcon_end(conp, b);
-                       promcon_puts(buf, b - buf);
-                       return;
-               } else {
-                       last = 1;
-                       count = pw - x - 1;
-               }
-       }
-
-       if (inverted(attr)) {
-               strcpy(b, "\033[7m");
-               b += 4;
-       }
-
-       if (px != x || py != y) {
-               b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
-               px = x;
-               py = y;
-       }
-
-       for (i = 0; i < count; i++) {
-               if (b - buf >= 224) {
-                       promcon_puts(buf, b - buf);
-                       b = buf;
-               }
-               *b++ = scr_readw(s++);
-       }
-
-       px += count;
-
-       if (last) {
-               save = scr_readw(s++);
-               b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
-               px++;
-       }
-
-       if (inverted(attr)) {
-               strcpy(b, "\033[m");
-               b += 3;
-       }
-
-       b += promcon_end(conp, b);
-       promcon_puts(buf, b - buf);
-}
-
-static void
-promcon_putc(struct vc_data *conp, int c, int y, int x)
-{
-       unsigned short s;
-
-       if (console_blanked)
-               return;
-       
-       scr_writew(c, &s);
-       promcon_putcs(conp, &s, 1, y, x);
-}
-
-static void
-promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
-{
-       unsigned char buf[256], *b = buf;
-       int i, j;
-
-       if (console_blanked)
-               return;
-       
-       b += promcon_start(conp, b);
-
-       if (!sx && width == pw + 1) {
-
-               if (!sy && height == ph + 1) {
-                       strcpy(b, "\033[H\033[J");
-                       b += 6;
-                       b += promcon_end(conp, b);
-                       promcon_puts(buf, b - buf);
-                       return;
-               } else if (sy + height == ph + 1) {
-                       b += sprintf(b, "\033[%dH\033[J", sy + 1);
-                       b += promcon_end(conp, b);
-                       promcon_puts(buf, b - buf);
-                       return;
-               }
-
-               b += sprintf(b, "\033[%dH", sy + 1);
-               for (i = 1; i < height; i++) {
-                       strcpy(b, "\033[K\n");
-                       b += 4;
-               }
-
-               strcpy(b, "\033[K");
-               b += 3;
-
-               b += promcon_end(conp, b);
-               promcon_puts(buf, b - buf);
-               return;
-
-       } else if (sx + width == pw + 1) {
-
-               b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
-               for (i = 1; i < height; i++) {
-                       strcpy(b, "\033[K\n");
-                       b += 4;
-               }
-
-               strcpy(b, "\033[K");
-               b += 3;
-
-               b += promcon_end(conp, b);
-               promcon_puts(buf, b - buf);
-               return;
-       }
-
-       for (i = sy + 1; i <= sy + height; i++) {
-               b += sprintf(b, "\033[%d;%dH", i, sx + 1);
-               for (j = 0; j < width; j++)
-                       *b++ = ' ';
-               if (b - buf + width >= 224) {
-                       promcon_puts(buf, b - buf);
-                       b = buf;
-               }
-       }
-
-       b += promcon_end(conp, b);
-       promcon_puts(buf, b - buf);
-}
-                        
-static void
-promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
-             int height, int width)
-{
-       char buf[256], *b = buf;
-
-       if (console_blanked)
-               return;
-       
-       b += promcon_start(conp, b);
-       if (sy == dy && height == 1) {
-               if (dx > sx && dx + width == conp->vc_cols)
-                       b += sprintf(b, "\033[%d;%dH\033[%d@\033[%d;%dH",
-                                    sy + 1, sx + 1, dx - sx, py + 1, px + 1);
-               else if (dx < sx && sx + width == conp->vc_cols)
-                       b += sprintf(b, "\033[%d;%dH\033[%dP\033[%d;%dH",
-                                    dy + 1, dx + 1, sx - dx, py + 1, px + 1);
-
-               b += promcon_end(conp, b);
-               promcon_puts(buf, b - buf);
-               return;
-       }
-
-       /*
-        * FIXME: What to do here???
-        * Current console.c should not call it like that ever.
-        */
-       prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
-}
-
-static void
-promcon_cursor(struct vc_data *conp, int mode)
-{
-       char buf[32], *b = buf;
-
-       switch (mode) {
-       case CM_ERASE:
-               break;
-
-       case CM_MOVE:
-       case CM_DRAW:
-               b += promcon_start(conp, b);
-               if (px != conp->vc_x || py != conp->vc_y) {
-                       px = conp->vc_x;
-                       py = conp->vc_y;
-                       b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
-               }
-               promcon_puts(buf, b - buf);
-               break;
-       }
-}
-
-static int
-promcon_blank(struct vc_data *conp, int blank, int mode_switch)
-{
-       if (blank) {
-               promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
-               return 0;
-       } else {
-               /* Let console.c redraw */
-               return 1;
-       }
-}
-
-static int
-promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
-{
-       unsigned char buf[256], *p = buf;
-       unsigned short *s;
-       int i;
-
-       if (console_blanked)
-               return 0;
-       
-       p += promcon_start(conp, p);
-
-       switch (dir) {
-       case SM_UP:
-               if (b == ph + 1) {
-                       p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
-                       px = 0;
-                       py = t;
-                       p += promcon_end(conp, p);
-                       promcon_puts(buf, p - buf);
-                       break;
-               }
-
-               s = (unsigned short *)(conp->vc_origin
-                                      + (t + count) * conp->vc_size_row);
-
-               p += sprintf(p, "\033[%dH", t + 1);
-
-               for (i = t; i < b - count; i++)
-                       s = promcon_repaint_line(s, buf, &p);
-
-               for (; i < b - 1; i++) {
-                       strcpy(p, "\033[K\n");
-                       p += 4;
-                       if (p - buf >= 224) {
-                               promcon_puts(buf, p - buf);
-                               p = buf;
-                       }
-               }
-
-               strcpy(p, "\033[K");
-               p += 3;
-
-               p += promcon_end(conp, p);
-               promcon_puts(buf, p - buf);
-               break;
-
-       case SM_DOWN:
-               if (b == ph + 1) {
-                       p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
-                       px = 0;
-                       py = t;
-                       p += promcon_end(conp, p);
-                       promcon_puts(buf, p - buf);
-                       break;
-               }
-
-               s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
-
-               p += sprintf(p, "\033[%dH", t + 1);
-
-               for (i = t; i < t + count; i++) {
-                       strcpy(p, "\033[K\n");
-                       p += 4;
-                       if (p - buf >= 224) {
-                               promcon_puts(buf, p - buf);
-                               p = buf;
-                       }
-               }
-
-               for (; i < b; i++)
-                       s = promcon_repaint_line(s, buf, &p);
-
-               p += promcon_end(conp, p);
-               promcon_puts(buf, p - buf);
-               break;
-       }
-
-       return 0;
-}
-
-#if !(PROMCON_COLOR)
-static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity,
-    u8 _blink, u8 _underline, u8 _reverse, u8 _italic)
-{
-       return (_reverse) ? 0xf : 0x7;
-}
-#endif
-
-/*
- *  The console 'switch' structure for the VGA based console
- */
-
-static int promcon_dummy(void)
-{
-        return 0;
-}
-
-#define DUMMY (void *) promcon_dummy
-
-const struct consw prom_con = {
-       .owner =                THIS_MODULE,
-       .con_startup =          promcon_startup,
-       .con_init =             promcon_init,
-       .con_deinit =           promcon_deinit,
-       .con_clear =            promcon_clear,
-       .con_putc =             promcon_putc,
-       .con_putcs =            promcon_putcs,
-       .con_cursor =           promcon_cursor,
-       .con_scroll =           promcon_scroll,
-       .con_bmove =            promcon_bmove,
-       .con_switch =           promcon_switch,
-       .con_blank =            promcon_blank,
-       .con_set_palette =      DUMMY,
-       .con_scrolldelta =      DUMMY,
-#if !(PROMCON_COLOR)
-       .con_build_attr =       promcon_build_attr,
-#endif
-};
-
-void __init prom_con_init(void)
-{
-#ifdef CONFIG_DUMMY_CONSOLE
-       if (conswitchp == &dummy_con)
-               take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
-       else
-#endif
-       if (conswitchp == &prom_con)
-               promcon_init_unimap(vc_cons[fg_console].d);
-}