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/config.h>
 
   9 #include <linux/module.h>
 
  10 #include <linux/kernel.h>
 
  11 #include <linux/errno.h>
 
  12 #include <linux/string.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>
 
  21 #include <linux/init.h>
 
  24 #include <asm/oplib.h>
 
  25 #include <asm/uaccess.h>
 
  27 static short pw = 80 - 1, ph = 34 - 1;
 
  29 static unsigned long promcon_uni_pagedir[2];
 
  31 extern u8 promfont_unicount[];
 
  32 extern u16 promfont_unitable[];
 
  34 #define PROMCON_COLOR 0
 
  37 #define inverted(s)     ((((s) & 0x7700) == 0x0700) ? 0 : 1)
 
  39 #define inverted(s)     (((s) & 0x0800) ? 1 : 0)
 
  42 static __inline__ void
 
  43 promcon_puts(char *buf, int cnt)
 
  45         prom_printf("%*.*s", cnt, cnt, buf);
 
  49 promcon_start(struct vc_data *conp, char *b)
 
  51         unsigned short *s = (unsigned short *)
 
  52                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 
  57                 unsigned short *t = s - 1;
 
  58                 u16 ct = scr_readw(t);
 
  60                 if (inverted(cs) && inverted(ct))
 
  61                         return sprintf(b, "\b\033[7m%c\b\033[@%c\033[m", cs,
 
  63                 else if (inverted(cs))
 
  64                         return sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs,
 
  66                 else if (inverted(ct))
 
  67                         return sprintf(b, "\b%c\b\033[@\033[7m%c\033[m", cs,
 
  70                         return sprintf(b, "\b%c\b\033[@%c", cs, ct);
 
  74                 return sprintf(b, "\033[7m%c\033[m\b", cs);
 
  76                 return sprintf(b, "%c\b", cs);
 
  80 promcon_end(struct vc_data *conp, char *b)
 
  82         unsigned short *s = (unsigned short *)
 
  83                         (conp->vc_origin + py * conp->vc_size_row + (px << 1));
 
  87         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
 
  91                 unsigned short *t = s - 1;
 
  92                 u16 ct = scr_readw(t);
 
  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);
 
 101                         b += sprintf(b, "\b\033[7m%c\033[m\b\033[@%c", cs, ct);
 
 106                 b += sprintf(b, "%c\b", cs);
 
 108                 b += sprintf(b, "\033[7m%c\033[m\b", cs);
 
 112 const char __init *promcon_startup(void)
 
 114         const char *display_desc = "PROM";
 
 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)
 
 126         if (prom_getproperty(node,  "screen-#rows", buf, 40) != -1) {
 
 127                 ph = simple_strtoul(buf, NULL, 0);
 
 128                 if (ph < 10 || ph > 256)
 
 132         promcon_puts("\033[H\033[J", 6);
 
 137 promcon_init_unimap(struct vc_data *conp)
 
 139         mm_segment_t old_fs = get_fs();
 
 140         struct unipair *p, *p1;
 
 144         p = kmalloc(256*sizeof(struct unipair), GFP_KERNEL);
 
 147         q = promfont_unitable;
 
 150         for (i = 0; i < 256; i++)
 
 151                 for (j = promfont_unicount[i]; j; j--) {
 
 158         con_clear_unimap(conp, NULL);
 
 159         con_set_unimap(conp, k, p);
 
 160         con_protect_unimap(conp, 1);
 
 166 promcon_init(struct vc_data *conp, int init)
 
 170         conp->vc_can_do_color = PROMCON_COLOR;
 
 172                 conp->vc_cols = pw + 1;
 
 173                 conp->vc_rows = ph + 1;
 
 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);
 
 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);
 
 185                 if (conp->vc_cols != pw + 1 || conp->vc_rows != ph + 1)
 
 186                         vc_resize(conp, pw + 1, ph + 1);
 
 191 promcon_deinit(struct vc_data *conp)
 
 193         /* When closing the last console, reset video origin */
 
 194         if (!--promcon_uni_pagedir[1])
 
 195                 con_free_unimap(conp);
 
 196         conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir;
 
 197         con_set_default_unimap(conp);
 
 201 promcon_switch(struct vc_data *conp)
 
 206 static unsigned short *
 
 207 promcon_repaint_line(unsigned short *s, unsigned char *buf, unsigned char **bp)
 
 211         unsigned char *b = *bp;
 
 214                 u16 c = scr_readw(s);
 
 215                 if (attr != inverted(c)) {
 
 218                                 strcpy (b, "\033[7m");
 
 221                                 strcpy (b, "\033[m");
 
 227                 if (b - buf >= 224) {
 
 228                         promcon_puts(buf, b - buf);
 
 237 promcon_putcs(struct vc_data *conp, const unsigned short *s,
 
 238               int count, int y, int x)
 
 240         unsigned char buf[256], *b = buf;
 
 241         unsigned short attr = scr_readw(s);
 
 251         b += promcon_start(conp, b);
 
 253         if (x + count >= pw + 1) {
 
 256                         save = scr_readw((unsigned short *)(conp->vc_origin
 
 257                                                    + y * conp->vc_size_row
 
 260                         if (px != x || py != y) {
 
 261                                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
 
 267                                 b += sprintf(b, "\033[7m%c\033[m", scr_readw(s++));
 
 269                                 b += sprintf(b, "%c", scr_readw(s++));
 
 271                         strcpy(b, "\b\033[@");
 
 275                                 b += sprintf(b, "\033[7m%c\033[m", save);
 
 277                                 b += sprintf(b, "%c", save);
 
 281                         b += promcon_end(conp, b);
 
 282                         promcon_puts(buf, b - buf);
 
 290         if (inverted(attr)) {
 
 291                 strcpy(b, "\033[7m");
 
 295         if (px != x || py != y) {
 
 296                 b += sprintf(b, "\033[%d;%dH", y + 1, x + 1);
 
 301         for (i = 0; i < count; i++) {
 
 302                 if (b - buf >= 224) {
 
 303                         promcon_puts(buf, b - buf);
 
 306                 *b++ = scr_readw(s++);
 
 312                 save = scr_readw(s++);
 
 313                 b += sprintf(b, "%c\b\033[@%c", scr_readw(s++), save);
 
 317         if (inverted(attr)) {
 
 322         b += promcon_end(conp, b);
 
 323         promcon_puts(buf, b - buf);
 
 327 promcon_putc(struct vc_data *conp, int c, int y, int x)
 
 335         promcon_putcs(conp, &s, 1, y, x);
 
 339 promcon_clear(struct vc_data *conp, int sy, int sx, int height, int width)
 
 341         unsigned char buf[256], *b = buf;
 
 347         b += promcon_start(conp, b);
 
 349         if (!sx && width == pw + 1) {
 
 351                 if (!sy && height == ph + 1) {
 
 352                         strcpy(b, "\033[H\033[J");
 
 354                         b += promcon_end(conp, b);
 
 355                         promcon_puts(buf, b - buf);
 
 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);
 
 364                 b += sprintf(b, "\033[%dH", sy + 1);
 
 365                 for (i = 1; i < height; i++) {
 
 366                         strcpy(b, "\033[K\n");
 
 373                 b += promcon_end(conp, b);
 
 374                 promcon_puts(buf, b - buf);
 
 377         } else if (sx + width == pw + 1) {
 
 379                 b += sprintf(b, "\033[%d;%dH", sy + 1, sx + 1);
 
 380                 for (i = 1; i < height; i++) {
 
 381                         strcpy(b, "\033[K\n");
 
 388                 b += promcon_end(conp, b);
 
 389                 promcon_puts(buf, b - buf);
 
 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++)
 
 397                 if (b - buf + width >= 224) {
 
 398                         promcon_puts(buf, b - buf);
 
 403         b += promcon_end(conp, b);
 
 404         promcon_puts(buf, b - buf);
 
 408 promcon_bmove(struct vc_data *conp, int sy, int sx, int dy, int dx,
 
 409               int height, int width)
 
 411         char buf[256], *b = buf;
 
 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);
 
 425                 b += promcon_end(conp, b);
 
 426                 promcon_puts(buf, b - buf);
 
 431          * FIXME: What to do here???
 
 432          * Current console.c should not call it like that ever.
 
 434         prom_printf("\033[7mFIXME: bmove not handled\033[m\n");
 
 438 promcon_cursor(struct vc_data *conp, int mode)
 
 440         char buf[32], *b = buf;
 
 448                 b += promcon_start(conp, b);
 
 449                 if (px != conp->vc_x || py != conp->vc_y) {
 
 452                         b += sprintf(b, "\033[%d;%dH", py + 1, px + 1);
 
 454                 promcon_puts(buf, b - buf);
 
 460 promcon_blank(struct vc_data *conp, int blank, int mode_switch)
 
 463                 promcon_puts("\033[H\033[J\033[7m \033[m\b", 15);
 
 466                 /* Let console.c redraw */
 
 472 promcon_scroll(struct vc_data *conp, int t, int b, int dir, int count)
 
 474         unsigned char buf[256], *p = buf;
 
 481         p += promcon_start(conp, p);
 
 486                         p += sprintf(p, "\033[%dH\033[%dM", t + 1, count);
 
 489                         p += promcon_end(conp, p);
 
 490                         promcon_puts(buf, p - buf);
 
 494                 s = (unsigned short *)(conp->vc_origin
 
 495                                        + (t + count) * conp->vc_size_row);
 
 497                 p += sprintf(p, "\033[%dH", t + 1);
 
 499                 for (i = t; i < b - count; i++)
 
 500                         s = promcon_repaint_line(s, buf, &p);
 
 502                 for (; i < b - 1; i++) {
 
 503                         strcpy(p, "\033[K\n");
 
 505                         if (p - buf >= 224) {
 
 506                                 promcon_puts(buf, p - buf);
 
 514                 p += promcon_end(conp, p);
 
 515                 promcon_puts(buf, p - buf);
 
 520                         p += sprintf(p, "\033[%dH\033[%dL", t + 1, count);
 
 523                         p += promcon_end(conp, p);
 
 524                         promcon_puts(buf, p - buf);
 
 528                 s = (unsigned short *)(conp->vc_origin + t * conp->vc_size_row);
 
 530                 p += sprintf(p, "\033[%dH", t + 1);
 
 532                 for (i = t; i < t + count; i++) {
 
 533                         strcpy(p, "\033[K\n");
 
 535                         if (p - buf >= 224) {
 
 536                                 promcon_puts(buf, p - buf);
 
 542                         s = promcon_repaint_line(s, buf, &p);
 
 544                 p += promcon_end(conp, p);
 
 545                 promcon_puts(buf, p - buf);
 
 553 static u8 promcon_build_attr(struct vc_data *conp, u8 _color, u8 _intensity, u8 _blink, u8 _underline, u8 _reverse)
 
 555         return (_reverse) ? 0xf : 0x7;
 
 560  *  The console 'switch' structure for the VGA based console
 
 563 static int promcon_dummy(void)
 
 568 #define DUMMY (void *) promcon_dummy
 
 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,
 
 586         .con_build_attr =       promcon_build_attr,
 
 590 void __init prom_con_init(void)
 
 592 #ifdef CONFIG_DUMMY_CONSOLE
 
 593         if (conswitchp == &dummy_con)
 
 594                 take_over_console(&prom_con, 0, MAX_NR_CONSOLES-1, 1);
 
 597         if (conswitchp == &prom_con)
 
 598                 promcon_init_unimap(vc_cons[fg_console].d);