1 /* 2 * Copyright (c) 1992 OMRON Corporation. 3 * Copyright (c) 1992, 1993 4 * The Regents of the University of California. All rights reserved. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * %sccs.include.redist.c% 10 * 11 * @(#)bmd.c 8.1 (Berkeley) 06/10/93 12 */ 13 14 /* 15 16 * bmd.c --- Bitmap-Display raw-level driver routines 17 * 18 * by A.Fujita, SEP-09-1992 19 */ 20 21 #undef BMD_PRINTF 22 23 #include <sys/param.h> 24 #include <sys/systm.h> 25 26 extern u_short bmdfont[][20]; 27 28 #define isprint(c) ( c < 0x20 ? 0 : 1) 29 30 /* 31 * Width & Hight 32 */ 33 34 #define PB_WIDTH 2048 /* Plane Width (Bit) */ 35 #define PB_HIGHT 1024 /* Plane Hight (Bit) */ 36 #define PL_WIDTH 64 /* Plane Width (long) */ 37 #define PS_WIDTH 128 /* Plane Width (long) */ 38 #define P_WIDTH 256 /* Plane Width (Byte) */ 39 40 #define SB_WIDTH 1280 /* Screen Width (Bit) */ 41 #define SB_HIGHT 1024 /* Screen Hight (Bit) */ 42 #define SL_WIDTH 40 /* Screen Width (Long) */ 43 #define S_WIDTH 160 /* Screen Width (Byte) */ 44 45 #define FB_WIDTH 12 /* Font Width (Bit) */ 46 #define FB_HIGHT 20 /* Font Hight (Bit) */ 47 48 49 #define NEXT_LINE(addr) ( addr + (PL_WIDTH * FB_HIGHT) ) 50 #define SKIP_NEXT_LINE(addr) ( addr += (PL_WIDTH - SL_WIDTH) ) 51 52 53 void bmd_add_new_line(); 54 55 void bmd_draw_char(); 56 void bmd_reverse_char(); 57 void bmd_erase_char(); 58 void bmd_erase_screen(); 59 void bmd_scroll_screen(); 60 61 void bmd_escape(); 62 63 64 struct bmd_linec { 65 struct bmd_linec *bl_next; 66 struct bmd_linec *bl_prev; 67 int bl_col; 68 int bl_end; 69 u_char bl_line[128]; 70 }; 71 72 struct bmd_softc { 73 int bc_stat; 74 char *bc_raddr; 75 char *bc_waddr; 76 int bc_xmin; 77 int bc_xmax; 78 int bc_ymin; 79 int bc_ymax; 80 int bc_col; 81 int bc_row; 82 struct bmd_linec *bc_bl; 83 char bc_escseq[8]; 84 char *bc_esc; 85 void (*bc_escape)(); 86 }; 87 88 #define STAT_NORMAL 0x0000 89 #define STAT_ESCAPE 0x0001 90 #define STAT_STOP 0x0002 91 92 struct bmd_softc bmd_softc; 93 struct bmd_linec bmd_linec[52]; 94 95 int bmd_initflag = 0; 96 97 /* 98 * Escape-Sequence 99 */ 100 101 #define push_ESC(p, c) *(p)->bc_esc++ = c; *(p)->bc_esc = '\0' 102 103 void 104 bmd_escape(c) 105 int c; 106 { 107 register struct bmd_softc *bp = &bmd_softc; 108 109 bp->bc_stat &= ~STAT_ESCAPE; 110 bp->bc_esc = &bp->bc_escseq[0]; 111 /* bp->bc_escape = bmd_escape; */ 112 } 113 114 /* 115 * Entry Routine 116 */ 117 118 bmdinit() 119 { 120 register struct bmd_softc *bp = &bmd_softc; 121 register struct bmd_linec *bq; 122 register int i; 123 124 bp->bc_raddr = (char *) 0xB10C0008; /* plane-0 hardware address */ 125 bp->bc_waddr = (char *) 0xB1080008; /* common bitmap hardware address */ 126 127 /* 128 * adjust plane position 129 */ 130 131 fb_adjust(7, -27); 132 133 bp->bc_stat = STAT_NORMAL; 134 135 bp->bc_xmin = 8; 136 bp->bc_xmax = 96; 137 bp->bc_ymin = 2; 138 bp->bc_ymax = 48; 139 140 bp->bc_row = bp->bc_ymin; 141 142 for (i = bp->bc_ymin; i < bp->bc_ymax; i++) { 143 bmd_linec[i].bl_next = &bmd_linec[i+1]; 144 bmd_linec[i].bl_prev = &bmd_linec[i-1]; 145 } 146 bmd_linec[bp->bc_ymax-1].bl_next = &bmd_linec[bp->bc_ymin]; 147 bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax-1]; 148 149 bq = bp->bc_bl = &bmd_linec[bp->bc_ymin]; 150 bq->bl_col = bq->bl_end = bp->bc_xmin; 151 152 bp->bc_col = bp->bc_xmin; 153 154 bp->bc_esc = &bp->bc_escseq[0]; 155 bp->bc_escape = bmd_escape; 156 157 bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */ 158 159 /* turn on cursole */ 160 bmd_reverse_char(bp->bc_raddr, 161 bp->bc_waddr, 162 bq->bl_col, bp->bc_row); 163 164 bmd_initflag = 1; 165 } 166 167 bmdputc(c) 168 register int c; 169 { 170 register struct bmd_softc *bp; 171 register struct bmd_linec *bq; 172 register int i; 173 174 if (!bmd_initflag) 175 bmdinit(); 176 177 bp = &bmd_softc; 178 bq = bp->bc_bl; 179 180 /* skip out, if STAT_STOP */ 181 if (bp->bc_stat & STAT_STOP) 182 return(c); 183 184 c &= 0x7F; 185 /* turn off cursole */ 186 bmd_reverse_char(bp->bc_raddr, 187 bp->bc_waddr, 188 bq->bl_col, bp->bc_row); 189 /* do escape-sequence */ 190 191 if (bp->bc_stat & STAT_ESCAPE) { 192 *bp->bc_esc++ = c; 193 (*bp->bc_escape)(c); 194 goto done; 195 } 196 197 if (isprint(c)) { 198 bmd_draw_char(bp->bc_raddr, bp->bc_waddr, 199 bq->bl_col, bp->bc_row, c); 200 bq->bl_col++; 201 bq->bl_end++; 202 if (bq->bl_col >= bp->bc_xmax) { 203 bq->bl_col = bq->bl_end = bp->bc_xmin; 204 bp->bc_row++; 205 if (bp->bc_row >= bp->bc_ymax) { 206 bmd_scroll_screen((u_long *) bp->bc_raddr, 207 (u_long *) bp->bc_waddr, 208 bp->bc_xmin, bp->bc_xmax, 209 bp->bc_ymin, bp->bc_ymax); 210 211 bp->bc_row = bp->bc_ymax - 1; 212 } 213 } 214 } else { 215 switch (c) { 216 case 0x08: /* BS */ 217 if (bq->bl_col > bp->bc_xmin) { 218 bq->bl_col--; 219 } 220 break; 221 222 case 0x09: /* HT */ 223 case 0x0B: /* VT */ 224 i = ((bq->bl_col / 8) + 1) * 8; 225 if (i < bp->bc_xmax) { 226 bq->bl_col = bq->bl_end = i; 227 } 228 break; 229 230 case 0x0A: /* NL */ 231 bp->bc_row++; 232 if (bp->bc_row >= bp->bc_ymax) { 233 bmd_scroll_screen((u_long *) bp->bc_raddr, 234 (u_long *) bp->bc_waddr, 235 bp->bc_xmin, bp->bc_xmax, 236 bp->bc_ymin, bp->bc_ymax); 237 238 bp->bc_row = bp->bc_ymax - 1; 239 } 240 break; 241 242 case 0x0D: /* CR */ 243 bq->bl_col = bp->bc_xmin; 244 break; 245 246 case 0x1b: /* ESC */ 247 bmdputc('<'); 248 bmdputc('E'); 249 bmdputc('S'); 250 bmdputc('C'); 251 bmdputc('>'); 252 /* 253 bp->bc_stat |= STAT_ESCAPE; 254 *bp->bc_esc++ = 0x1b; 255 */ 256 break; 257 258 case 0x7F: /* DEL */ 259 if (bq->bl_col > bp->bc_xmin) { 260 bq->bl_col--; 261 bmd_erase_char(bp->bc_raddr, 262 bp->bc_waddr, 263 bq->bl_col, bp->bc_row); 264 } 265 break; 266 267 default: 268 break; 269 } 270 } 271 272 done: 273 /* turn on cursole */ 274 bmd_reverse_char(bp->bc_raddr, 275 bp->bc_waddr, 276 bq->bl_col, bp->bc_row); 277 278 return(c); 279 } 280 281 /* 282 * 283 */ 284 285 bmd_on() 286 { 287 bmdinit(); 288 } 289 290 bmd_off() 291 { 292 register struct bmd_softc *bp = &bmd_softc; 293 294 bp->bc_stat |= STAT_STOP; 295 bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */ 296 } 297 298 bmd_clear() 299 { 300 register struct bmd_softc *bp = &bmd_softc; 301 register struct bmd_linec *bq = bp->bc_bl; 302 303 bmd_erase_screen((u_long *) bp->bc_waddr); /* clear screen */ 304 305 bmd_reverse_char(bp->bc_raddr, 306 bp->bc_waddr, 307 bq->bl_col, bp->bc_row); /* turn on cursole */ 308 } 309 310 bmd_home() 311 { 312 register struct bmd_softc *bp = &bmd_softc; 313 register struct bmd_linec *bq = bp->bc_bl; 314 315 bmd_reverse_char(bp->bc_raddr, 316 bp->bc_waddr, 317 bq->bl_col, bp->bc_row); /* turn off cursole */ 318 319 bq->bl_col = bq->bl_end = bp->bc_xmin; 320 bp->bc_row = bp->bc_ymin; 321 322 bmd_reverse_char(bp->bc_raddr, 323 bp->bc_waddr, 324 bq->bl_col, bp->bc_row); /* turn on cursole */ 325 } 326 327 /* 328 * charactor operation routines 329 */ 330 331 void 332 bmd_draw_char(raddr, waddr, col, row, c) 333 char *raddr; 334 char *waddr; 335 int col; 336 int row; 337 int c; 338 { 339 volatile register u_short *p, *q, *fp; 340 volatile register u_long *lp, *lq; 341 register int i; 342 343 fp = &bmdfont[c][0]; 344 345 switch (col % 4) { 346 347 case 0: 348 p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 349 q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 350 for (i = 0; i < FB_HIGHT; i++) { 351 *q = (*p & 0x000F) | (*fp & 0xFFF0); 352 p += 128; 353 q += 128; 354 fp++; 355 } 356 break; 357 358 case 1: 359 lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 360 lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 361 for (i = 0; i < FB_HIGHT; i++) { 362 *lq = (*lp & 0xFFF000FF) | ((u_long)(*fp & 0xFFF0) << 4); 363 lp += 64; 364 lq += 64; 365 fp++; 366 } 367 break; 368 369 case 2: 370 lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 ); 371 lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 ); 372 for (i = 0; i < FB_HIGHT; i++) { 373 *lq = (*lp & 0xFF000FFF) | ((u_long)(*fp & 0xFFF0) << 8); 374 lp += 64; 375 lq += 64; 376 fp++; 377 } 378 break; 379 380 case 3: 381 p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 ); 382 q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 ); 383 for (i = 0; i < FB_HIGHT; i++) { 384 *q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4); 385 p += 128; 386 q += 128; 387 fp++; 388 } 389 break; 390 391 default: 392 break; 393 } 394 } 395 396 void 397 bmd_reverse_char(raddr, waddr, col, row) 398 char *raddr; 399 char *waddr; 400 int col; 401 int row; 402 { 403 volatile register u_short *p, *q, us; 404 volatile register u_long *lp, *lq, ul; 405 register int i; 406 407 switch (col%4) { 408 409 case 0: 410 p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 411 q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 412 for (i = 0; i < FB_HIGHT; i++) { 413 *q = (*p & 0x000F) | (~(*p) & 0xFFF0); 414 p += 128; 415 q += 128; 416 } 417 break; 418 419 case 1: 420 lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 421 lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 )); 422 for (i = 0; i < FB_HIGHT; i++) { 423 *lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00); 424 lp += 64; 425 lq += 64; 426 } 427 break; 428 429 case 2: 430 lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 ); 431 lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 ); 432 for (i = 0; i < FB_HIGHT; i++) { 433 *lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000); 434 lp += 64; 435 lq += 64; 436 } 437 break; 438 439 case 3: 440 p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 ); 441 q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 ); 442 for (i = 0; i < FB_HIGHT; i++) { 443 *q = (*p & 0xF000) | (~(*p) & 0x0FFF); 444 p += 128; 445 q += 128; 446 } 447 break; 448 449 default: 450 break; 451 } 452 } 453 454 void 455 bmd_erase_char(raddr, waddr, col, row) 456 char *raddr; 457 char *waddr; 458 int col; 459 int row; 460 { 461 bmd_draw_char(raddr, waddr, col, row, 0); 462 463 return; 464 } 465 466 467 /* 468 * screen operation routines 469 */ 470 471 void 472 bmd_erase_screen(lp) 473 volatile register u_long *lp; 474 { 475 register int i, j; 476 477 for (i = 0; i < SB_HIGHT; i++) { 478 for (j = 0; j < SL_WIDTH; j++) 479 *lp++ = 0; 480 SKIP_NEXT_LINE(lp); 481 } 482 483 return; 484 } 485 486 void 487 bmd_scroll_screen(lp, lq, xmin, xmax, ymin, ymax) 488 volatile register u_long *lp; 489 volatile register u_long *lq; 490 int xmin, xmax, ymin, ymax; 491 { 492 register int i, j; 493 494 lp += ((PL_WIDTH * FB_HIGHT) * (ymin + 1)); 495 lq += ((PL_WIDTH * FB_HIGHT) * ymin); 496 497 for (i = 0; i < ((ymax - ymin -1) * FB_HIGHT); i++) { 498 for (j = 0; j < SL_WIDTH; j++) { 499 *lq++ = *lp++; 500 } 501 lp += (PL_WIDTH - SL_WIDTH); 502 lq += (PL_WIDTH - SL_WIDTH); 503 } 504 505 for (i = 0; i < FB_HIGHT; i++) { 506 for (j = 0; j < SL_WIDTH; j++) { 507 *lq++ = 0; 508 } 509 lq += (PL_WIDTH - SL_WIDTH); 510 } 511 512 } 513 514 515 #ifdef BMD_PRINTF 516 517 #include <machine/stdarg.h> 518 519 void bmd_kprintf(); 520 static char * bmd_sprintn(); 521 522 void 523 #ifdef __STDC__ 524 bmd_printf(const char *fmt, ...) 525 #else 526 bmd_printf(fmt, va_alist) 527 char *fmt; 528 #endif 529 { 530 va_list ap; 531 532 va_start(ap, fmt); 533 bmd_kprintf(fmt, ap); 534 va_end(ap); 535 } 536 537 /* 538 * Scaled down version of printf(3). 539 * 540 * Two additional formats: 541 * 542 * The format %b is supported to decode error registers. 543 * Its usage is: 544 * 545 * printf("reg=%b\n", regval, "<base><arg>*"); 546 * 547 * where <base> is the output base expressed as a control character, e.g. 548 * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, 549 * the first of which gives the bit number to be inspected (origin 1), and 550 * the next characters (up to a control character, i.e. a character <= 32), 551 * give the name of the register. Thus: 552 * 553 * kprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); 554 * 555 * would produce output: 556 * 557 * reg=3<BITTWO,BITONE> 558 * 559 * The format %r passes an additional format string and argument list 560 * recursively. Its usage is: 561 * 562 * fn(char *fmt, ...) 563 * { 564 * va_list ap; 565 * va_start(ap, fmt); 566 * printf("prefix: %r: suffix\n", fmt, ap); 567 * va_end(ap); 568 * } 569 * 570 * Space or zero padding and a field width are supported for the numeric 571 * formats only. 572 */ 573 void 574 bmd_kprintf(fmt, ap) 575 register const char *fmt; 576 va_list ap; 577 { 578 register char *p, *q; 579 register int ch, n; 580 u_long ul; 581 int base, lflag, tmp, width; 582 char padc; 583 584 for (;;) { 585 padc = ' '; 586 width = 0; 587 while ((ch = *(u_char *)fmt++) != '%') { 588 if (ch == '\0') 589 return; 590 if (ch == '\n') 591 bmdputc('\r'); 592 bmdputc(ch); 593 } 594 lflag = 0; 595 reswitch: switch (ch = *(u_char *)fmt++) { 596 case '0': 597 padc = '0'; 598 goto reswitch; 599 case '1': case '2': case '3': case '4': 600 case '5': case '6': case '7': case '8': case '9': 601 for (width = 0;; ++fmt) { 602 width = width * 10 + ch - '0'; 603 ch = *fmt; 604 if (ch < '0' || ch > '9') 605 break; 606 } 607 goto reswitch; 608 case 'l': 609 lflag = 1; 610 goto reswitch; 611 case 'b': 612 ul = va_arg(ap, int); 613 p = va_arg(ap, char *); 614 for (q = bmd_sprintn(ul, *p++, NULL); ch = *q--;) 615 bmdputc(ch); 616 617 if (!ul) 618 break; 619 620 for (tmp = 0; n = *p++;) { 621 if (ul & (1 << (n - 1))) { 622 bmdputc(tmp ? ',' : '<'); 623 for (; (n = *p) > ' '; ++p) 624 bmdputc(n); 625 tmp = 1; 626 } else 627 for (; *p > ' '; ++p) 628 continue; 629 } 630 if (tmp) 631 bmdputc('>'); 632 break; 633 case 'c': 634 bmdputc(va_arg(ap, int)); 635 break; 636 case 'r': 637 p = va_arg(ap, char *); 638 bmd_kprintf(p, va_arg(ap, va_list)); 639 break; 640 case 's': 641 p = va_arg(ap, char *); 642 while (ch = *p++) 643 bmdputc(ch); 644 break; 645 case 'd': 646 ul = lflag ? va_arg(ap, long) : va_arg(ap, int); 647 if ((long)ul < 0) { 648 bmdputc('-'); 649 ul = -(long)ul; 650 } 651 base = 10; 652 goto number; 653 case 'o': 654 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 655 base = 8; 656 goto number; 657 case 'u': 658 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 659 base = 10; 660 goto number; 661 case 'x': 662 ul = lflag ? va_arg(ap, u_long) : va_arg(ap, u_int); 663 base = 16; 664 number: p = bmd_sprintn(ul, base, &tmp); 665 if (width && (width -= tmp) > 0) 666 while (width--) 667 bmdputc(padc); 668 while (ch = *p--) 669 bmdputc(ch); 670 break; 671 default: 672 bmdputc('%'); 673 if (lflag) 674 bmdputc('l'); 675 /* FALLTHROUGH */ 676 case '%': 677 bmdputc(ch); 678 } 679 } 680 } 681 682 /* 683 * Put a number (base <= 16) in a buffer in reverse order; return an 684 * optional length and a pointer to the NULL terminated (preceded?) 685 * buffer. 686 */ 687 static char * 688 bmd_sprintn(ul, base, lenp) 689 register u_long ul; 690 register int base, *lenp; 691 { /* A long in base 8, plus NULL. */ 692 static char buf[sizeof(long) * NBBY / 3 + 2]; 693 register char *p; 694 695 p = buf; 696 do { 697 *++p = "0123456789abcdef"[ul % base]; 698 } while (ul /= base); 699 if (lenp) 700 *lenp = p - buf; 701 return (p); 702 } 703 #endif 704