bmd.c revision 1.7 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