Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

at v2.6.17-rc6 599 lines 12 kB view raw
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 27static short pw = 80 - 1, ph = 34 - 1; 28static short px, py; 29static unsigned long promcon_uni_pagedir[2]; 30 31extern u8 promfont_unicount[]; 32extern 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 42static __inline__ void 43promcon_puts(char *buf, int cnt) 44{ 45 prom_printf("%*.*s", cnt, cnt, buf); 46} 47 48static int 49promcon_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 79static int 80promcon_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 112const 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 136static void __init 137promcon_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, NULL); 159 con_set_unimap(conp, k, p); 160 con_protect_unimap(conp, 1); 161 set_fs(old_fs); 162 kfree(p); 163} 164 165static void 166promcon_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); 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, pw + 1, ph + 1); 187 } 188} 189 190static void 191promcon_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); 196 conp->vc_uni_pagedir_loc = &conp->vc_uni_pagedir; 197 con_set_default_unimap(conp); 198} 199 200static int 201promcon_switch(struct vc_data *conp) 202{ 203 return 1; 204} 205 206static unsigned short * 207promcon_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 236static void 237promcon_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 326static void 327promcon_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 338static void 339promcon_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 407static void 408promcon_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 437static void 438promcon_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 459static int 460promcon_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 471static int 472promcon_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) 553static 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 563static int promcon_dummy(void) 564{ 565 return 0; 566} 567 568#define DUMMY (void *) promcon_dummy 569 570const 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 590void __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}