1 /* $NetBSD: bmd.c,v 1.7 2015/02/14 06:31:31 tsutsui Exp $ */ 2 3 /* 4 * Copyright (c) 1992 OMRON Corporation. 5 * 6 * This code is derived from software contributed to Berkeley by 7 * OMRON Corporation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the University of 20 * California, Berkeley and its contributors. 21 * 4. Neither the name of the University nor the names of its contributors 22 * may be used to endorse or promote products derived from this software 23 * without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 26 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 27 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 28 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 29 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 30 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 31 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 32 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 33 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 34 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 35 * SUCH DAMAGE. 36 * 37 * @(#)bmd.c 8.2 (Berkeley) 8/15/93 38 */ 39 /* 40 * Copyright (c) 1992, 1993 41 * The Regents of the University of California. All rights reserved. 42 * 43 * This code is derived from software contributed to Berkeley by 44 * OMRON Corporation. 45 * 46 * Redistribution and use in source and binary forms, with or without 47 * modification, are permitted provided that the following conditions 48 * are met: 49 * 1. Redistributions of source code must retain the above copyright 50 * notice, this list of conditions and the following disclaimer. 51 * 2. Redistributions in binary form must reproduce the above copyright 52 * notice, this list of conditions and the following disclaimer in the 53 * documentation and/or other materials provided with the distribution. 54 * 3. Neither the name of the University nor the names of its contributors 55 * may be used to endorse or promote products derived from this software 56 * without specific prior written permission. 57 * 58 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 59 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 60 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 61 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 62 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 63 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 64 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 65 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 66 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 67 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 68 * SUCH DAMAGE. 69 * 70 * @(#)bmd.c 8.2 (Berkeley) 8/15/93 71 */ 72 /* 73 74 * bmd.c --- Bitmap-Display raw-level driver routines 75 * 76 * by A.Fujita, SEP-09-1992 77 */ 78 79 80 #include <sys/param.h> 81 #include <luna68k/stand/boot/samachdep.h> 82 83 /* 84 * RFCNT register 85 */ 86 87 union bmd_rfcnt { 88 struct { 89 int16_t rfc_hcnt; 90 int16_t rfc_vcnt; 91 } p; 92 uint32_t u; 93 }; 94 95 #define isprint(c) ((c) >= 0x20 && (c) < 0x7f) 96 97 /* 98 * Width & Height 99 */ 100 101 #define PB_WIDTH 2048 /* Plane Width (Bit) */ 102 #define PB_HEIGHT 1024 /* Plane Hight (Bit) */ 103 #define PL_WIDTH 64 /* Plane Width (long) */ 104 #define PS_WIDTH 128 /* Plane Width (long) */ 105 #define P_WIDTH 256 /* Plane Width (Byte) */ 106 107 #define SB_WIDTH 1280 /* Screen Width (Bit) */ 108 #define SB_HEIGHT 1024 /* Screen Hight (Bit) */ 109 #define SL_WIDTH 40 /* Screen Width (Long) */ 110 #define S_WIDTH 160 /* Screen Width (Byte) */ 111 112 #define FB_WIDTH 12 /* Font Width (Bit) */ 113 #define FB_HEIGHT 20 /* Font Hight (Bit) */ 114 115 116 #define NEXT_LINE(addr) (addr + (PL_WIDTH * FB_HEIGHT)) 117 #define SKIP_NEXT_LINE(addr) (addr += (PL_WIDTH - SL_WIDTH)) 118 119 120 static void bmd_draw_char(uint8_t *, uint8_t *, int, int, int); 121 static void bmd_reverse_char(uint8_t *, uint8_t *, int, int); 122 static void bmd_erase_char(uint8_t *, uint8_t *, int, int); 123 static void bmd_erase_screen(volatile uint32_t *); 124 static void bmd_scroll_screen(volatile uint32_t *, volatile uint32_t *, 125 int, int, int, int); 126 127 128 struct bmd_linec { 129 struct bmd_linec *bl_next; 130 struct bmd_linec *bl_prev; 131 int bl_col; 132 int bl_end; 133 uint8_t bl_line[128]; 134 }; 135 136 struct bmd_softc { 137 int bc_stat; 138 uint8_t *bc_raddr; 139 uint8_t *bc_waddr; 140 int bc_xmin; 141 int bc_xmax; 142 int bc_ymin; 143 int bc_ymax; 144 int bc_col; 145 int bc_row; 146 struct bmd_linec *bc_bl; 147 char bc_escseq[8]; 148 char *bc_esc; 149 void (*bc_escape)(int); 150 }; 151 152 #define STAT_NORMAL 0x0000 153 #define STAT_ESCAPE 0x0001 154 #define STAT_INSERT 0x0100 155 156 static struct bmd_softc bmd_softc; 157 static struct bmd_linec bmd_linec[52]; 158 159 static void bmd_escape(int); 160 static void bmd_escape_0(int); 161 #if 0 162 static void bmd_escape_1(int); 163 #endif 164 165 166 /* 167 * Escape-Sequence 168 */ 169 170 static void 171 bmd_escape(int c) 172 { 173 struct bmd_softc *bp = &bmd_softc; 174 175 switch (c) { 176 177 case '[': 178 bp->bc_escape = bmd_escape_0; 179 break; 180 181 default: 182 bp->bc_stat &= ~STAT_ESCAPE; 183 bp->bc_esc = &bp->bc_escseq[0]; 184 bp->bc_escape = bmd_escape; 185 break; 186 } 187 } 188 189 static void 190 bmd_escape_0(int c) 191 { 192 struct bmd_softc *bp = &bmd_softc; 193 struct bmd_linec *bq = bp->bc_bl; 194 195 switch (c) { 196 197 case 'A': 198 if (bp->bc_row > bp->bc_ymin) { 199 bp->bc_row--; 200 } 201 break; 202 203 case 'C': 204 if (bq->bl_col < bp->bc_xmax - 1) { 205 bq->bl_col++; 206 } 207 break; 208 209 case 'K': 210 if (bq->bl_col < bp->bc_xmax) { 211 int col; 212 for (col = bq->bl_col; col < bp->bc_xmax; col++) 213 bmd_erase_char(bp->bc_raddr, 214 bp->bc_waddr, 215 col, bp->bc_row); 216 } 217 bq->bl_end = bq->bl_col; 218 break; 219 220 case 'H': 221 bq->bl_col = bq->bl_end = bp->bc_xmin; 222 bp->bc_row = bp->bc_ymin; 223 break; 224 225 default: 226 #if 0 227 *bp->bc_esc++ = c; 228 bp->bc_escape = bmd_escape_1; 229 return; 230 #endif 231 break; 232 } 233 234 bp->bc_stat &= ~STAT_ESCAPE; 235 bp->bc_esc = &bp->bc_escseq[0]; 236 bp->bc_escape = bmd_escape; 237 } 238 239 #if 0 240 static void 241 bmd_escape_1(int c) 242 { 243 struct bmd_softc *bp = &bmd_softc; 244 struct bmd_linec *bq = bp->bc_bl; 245 int col = 0, row = 0; 246 char *p; 247 248 switch (c) { 249 250 case 'J': 251 bp->bc_stat &= ~STAT_ESCAPE; 252 bp->bc_esc = &bp->bc_escseq[0]; 253 bp->bc_escape = bmd_escape; 254 break; 255 256 case 'H': 257 for (p = &bp->bc_escseq[0]; *p != ';'; p++) 258 row = (row * 10) + (*p - 0x30); 259 p++; 260 for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++) 261 col = (col * 10) + (*p - 0x30); 262 263 bq->bl_col = col + bp->bc_xmin; 264 bp->bc_row = row + bp->bc_ymin; 265 266 bp->bc_stat &= ~STAT_ESCAPE; 267 bp->bc_esc = &bp->bc_escseq[0]; 268 bp->bc_escape = bmd_escape; 269 break; 270 271 default: 272 *bp->bc_esc++ = c; 273 break; 274 } 275 } 276 #endif 277 278 /* 279 * Entry Routine 280 */ 281 282 void 283 bmdinit(void) 284 { 285 volatile uint32_t *bmd_rfcnt = (uint32_t *)0xB1000000; 286 volatile uint32_t *bmd_bmsel = (uint32_t *)0xB1040000; 287 struct bmd_softc *bp = &bmd_softc; 288 struct bmd_linec *bq; 289 int i; 290 union bmd_rfcnt rfcnt; 291 292 /* 293 * adjust plane position 294 */ 295 296 /* plane-0 hardware address */ 297 bp->bc_raddr = (uint8_t *)0xB10C0008; 298 /* common bitmap hardware address */ 299 bp->bc_waddr = (uint8_t *)0xB1080008; 300 301 rfcnt.p.rfc_hcnt = 7; /* shift left 16 dot */ 302 rfcnt.p.rfc_vcnt = -27; /* shift down 1 dot */ 303 *bmd_rfcnt = rfcnt.u; 304 305 bp->bc_stat = STAT_NORMAL; 306 307 bp->bc_xmin = 8; 308 bp->bc_xmax = 96; 309 bp->bc_ymin = 2; 310 bp->bc_ymax = 48; 311 312 bp->bc_row = bp->bc_ymin; 313 314 for (i = bp->bc_ymin; i < bp->bc_ymax; i++) { 315 bmd_linec[i].bl_next = &bmd_linec[i + 1]; 316 bmd_linec[i].bl_prev = &bmd_linec[i - 1]; 317 } 318 bmd_linec[bp->bc_ymax - 1].bl_next = &bmd_linec[bp->bc_ymin]; 319 bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax - 1]; 320 321 bq = bp->bc_bl = &bmd_linec[bp->bc_ymin]; 322 bq->bl_col = bq->bl_end = bp->bc_xmin; 323 324 bp->bc_col = bp->bc_xmin; 325 326 bp->bc_esc = &bp->bc_escseq[0]; 327 bp->bc_escape = bmd_escape; 328 329 *bmd_bmsel = 0xff; /* all planes */ 330 bmd_erase_screen((uint32_t *)bp->bc_waddr); /* clear screen */ 331 *bmd_bmsel = 0x01; /* 1 plane */ 332 333 /* turn on cursor */ 334 bmd_reverse_char(bp->bc_raddr, 335 bp->bc_waddr, 336 bq->bl_col, bp->bc_row); 337 } 338 339 void 340 bmdadjust(int16_t hcnt, int16_t vcnt) 341 { 342 volatile uint32_t *bmd_rfcnt = (uint32_t *)0xB1000000; 343 union bmd_rfcnt rfcnt; 344 345 printf("bmdadjust: hcnt = %d, vcnt = %d\n", hcnt, vcnt); 346 347 rfcnt.p.rfc_hcnt = hcnt; /* shift left 16 dot */ 348 rfcnt.p.rfc_vcnt = vcnt; /* shift down 1 dot */ 349 350 *bmd_rfcnt = rfcnt.u; 351 } 352 353 int 354 bmdputc(int c) 355 { 356 struct bmd_softc *bp = &bmd_softc; 357 struct bmd_linec *bq = bp->bc_bl; 358 int i; 359 360 c &= 0x7F; 361 362 /* turn off cursor */ 363 bmd_reverse_char(bp->bc_raddr, 364 bp->bc_waddr, 365 bq->bl_col, bp->bc_row); 366 367 /* do escape-sequence */ 368 if (bp->bc_stat & STAT_ESCAPE) { 369 *bp->bc_esc++ = c; 370 (*bp->bc_escape)(c); 371 goto done; 372 } 373 374 if (isprint(c)) { 375 bmd_draw_char(bp->bc_raddr, bp->bc_waddr, 376 bq->bl_col, bp->bc_row, c); 377 bq->bl_col++; 378 bq->bl_end++; 379 if (bq->bl_col >= bp->bc_xmax) { 380 bq->bl_col = bq->bl_end = bp->bc_xmin; 381 bp->bc_row++; 382 if (bp->bc_row >= bp->bc_ymax) { 383 bmd_scroll_screen((uint32_t *)bp->bc_raddr, 384 (uint32_t *)bp->bc_waddr, 385 bp->bc_xmin, bp->bc_xmax, 386 bp->bc_ymin, bp->bc_ymax); 387 388 bp->bc_row = bp->bc_ymax - 1; 389 } 390 } 391 } else { 392 switch (c) { 393 case 0x08: /* BS */ 394 if (bq->bl_col > bp->bc_xmin) { 395 bq->bl_col--; 396 } 397 break; 398 399 case 0x09: /* HT */ 400 case 0x0B: /* VT */ 401 i = ((bq->bl_col / 8) + 1) * 8; 402 if (i < bp->bc_xmax) { 403 bq->bl_col = bq->bl_end = i; 404 } 405 break; 406 407 case 0x0A: /* NL */ 408 bp->bc_row++; 409 if (bp->bc_row >= bp->bc_ymax) { 410 bmd_scroll_screen((uint32_t *)bp->bc_raddr, 411 (uint32_t *)bp->bc_waddr, 412 bp->bc_xmin, bp->bc_xmax, 413 bp->bc_ymin, bp->bc_ymax); 414 415 bp->bc_row = bp->bc_ymax - 1; 416 } 417 break; 418 419 case 0x0D: /* CR */ 420 bq->bl_col = bp->bc_xmin; 421 break; 422 423 case 0x1B: /* ESC */ 424 bp->bc_stat |= STAT_ESCAPE; 425 *bp->bc_esc++ = 0x1b; 426 break; 427 428 case 0x7F: /* DEL */ 429 if (bq->bl_col > bp->bc_xmin) { 430 bq->bl_col--; 431 bmd_erase_char(bp->bc_raddr, 432 bp->bc_waddr, 433 bq->bl_col, bp->bc_row); 434 } 435 break; 436 437 default: 438 break; 439 } 440 } 441 442 done: 443 /* turn on cursor */ 444 bmd_reverse_char(bp->bc_raddr, 445 bp->bc_waddr, 446 bq->bl_col, bp->bc_row); 447 448 return c; 449 } 450 451 void 452 bmdclear(void) 453 { 454 struct bmd_softc *bp = &bmd_softc; 455 struct bmd_linec *bq = bp->bc_bl; 456 457 /* clear screen */ 458 bmd_erase_screen((uint32_t *)bp->bc_waddr); 459 460 bq->bl_col = bq->bl_end = bp->bc_xmin; 461 bp->bc_row = bp->bc_ymin; 462 463 /* turn on cursor */ 464 bmd_reverse_char(bp->bc_raddr, 465 bp->bc_waddr, 466 bq->bl_col, bp->bc_row); 467 } 468 469 470 /* 471 * charactor operation routines 472 */ 473 474 static void 475 bmd_draw_char(uint8_t *raddr, uint8_t *waddr, int col, int row, int c) 476 { 477 volatile uint16_t *p, *q; 478 volatile uint32_t *lp, *lq; 479 const uint16_t *fp; 480 int i; 481 482 fp = &bmdfont[c][0]; 483 484 switch (col % 4) { 485 486 case 0: 487 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8) 488 + ((col / 4) * 6)); 489 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8) 490 + ((col / 4) * 6)); 491 for (i = 0; i < FB_HEIGHT; i++) { 492 *q = (*p & 0x000F) | (*fp & 0xFFF0); 493 p += 128; 494 q += 128; 495 fp++; 496 } 497 break; 498 499 case 1: 500 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8) 501 + ((col / 4) * 6)); 502 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8) 503 + ((col / 4) * 6)); 504 for (i = 0; i < FB_HEIGHT; i++) { 505 *lq = (*lp & 0xFFF000FF) | 506 ((uint32_t)(*fp & 0xFFF0) << 4); 507 lp += 64; 508 lq += 64; 509 fp++; 510 } 511 break; 512 513 case 2: 514 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8) 515 + ((col / 4) * 6) + 2); 516 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8) 517 + ((col / 4) * 6) + 2); 518 for (i = 0; i < FB_HEIGHT; i++) { 519 *lq = (*lp & 0xFF000FFF) | 520 ((uint32_t)(*fp & 0xFFF0) << 8); 521 lp += 64; 522 lq += 64; 523 fp++; 524 } 525 break; 526 527 case 3: 528 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8) 529 + ((col / 4) * 6) + 4); 530 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8) 531 + ((col / 4) * 6) + 4); 532 for (i = 0; i < FB_HEIGHT; i++) { 533 *q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4); 534 p += 128; 535 q += 128; 536 fp++; 537 } 538 break; 539 540 default: 541 break; 542 } 543 } 544 545 static void 546 bmd_reverse_char(uint8_t *raddr, uint8_t *waddr, int col, int row) 547 { 548 volatile uint16_t *p, *q; 549 volatile uint32_t *lp, *lq; 550 int i; 551 552 switch (col % 4) { 553 554 case 0: 555 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8) 556 + ((col / 4) * 6)); 557 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8) 558 + ((col / 4) * 6)); 559 for (i = 0; i < FB_HEIGHT; i++) { 560 *q = (*p & 0x000F) | (~(*p) & 0xFFF0); 561 p += 128; 562 q += 128; 563 } 564 break; 565 566 case 1: 567 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8) 568 + ((col / 4) * 6)); 569 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8) 570 + ((col / 4) * 6)); 571 for (i = 0; i < FB_HEIGHT; i++) { 572 *lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00); 573 lp += 64; 574 lq += 64; 575 } 576 break; 577 578 case 2: 579 lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8) 580 + ((col / 4) * 6) + 2); 581 lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8) 582 + ((col / 4) * 6) + 2); 583 for (i = 0; i < FB_HEIGHT; i++) { 584 *lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000); 585 lp += 64; 586 lq += 64; 587 } 588 break; 589 590 case 3: 591 p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8) 592 + ((col / 4) * 6) + 4); 593 q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8) 594 + ((col / 4) * 6) + 4); 595 for (i = 0; i < FB_HEIGHT; i++) { 596 *q = (*p & 0xF000) | (~(*p) & 0x0FFF); 597 p += 128; 598 q += 128; 599 } 600 break; 601 602 default: 603 break; 604 } 605 } 606 607 static void 608 bmd_erase_char(uint8_t *raddr, uint8_t *waddr, int col, int row) 609 { 610 611 bmd_draw_char(raddr, waddr, col, row, 0); 612 } 613 614 615 /* 616 * screen operation routines 617 */ 618 619 static void 620 bmd_erase_screen(volatile uint32_t *lp) 621 { 622 int i, j; 623 624 for (i = 0; i < SB_HEIGHT; i++) { 625 for (j = 0; j < SL_WIDTH; j++) 626 *lp++ = 0; 627 SKIP_NEXT_LINE(lp); 628 } 629 } 630 631 static void 632 bmd_scroll_screen(volatile uint32_t *lp, volatile uint32_t *lq, 633 int xmin, int xmax, int ymin, int ymax) 634 { 635 int i, j; 636 637 lp += ((PL_WIDTH * FB_HEIGHT) * (ymin + 1)); 638 lq += ((PL_WIDTH * FB_HEIGHT) * ymin); 639 640 for (i = 0; i < ((ymax - ymin -1) * FB_HEIGHT); i++) { 641 for (j = 0; j < SL_WIDTH; j++) { 642 *lq++ = *lp++; 643 } 644 lp += (PL_WIDTH - SL_WIDTH); 645 lq += (PL_WIDTH - SL_WIDTH); 646 } 647 648 for (i = 0; i < FB_HEIGHT; i++) { 649 for (j = 0; j < SL_WIDTH; j++) { 650 *lq++ = 0; 651 } 652 lq += (PL_WIDTH - SL_WIDTH); 653 } 654 } 655