bmd.c revision 1.8
1/*	$NetBSD: bmd.c,v 1.8 2019/06/30 05:04:49 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#include <machine/board.h>
83
84/*
85 *  RFCNT register
86 */
87
88union bmd_rfcnt {
89	struct {
90		int16_t	rfc_hcnt;
91		int16_t	rfc_vcnt;
92	} p;
93	uint32_t u;
94};
95
96#define isprint(c)	((c) >= 0x20 && (c) < 0x7f)
97
98/*
99 *  Width & Height
100 */
101
102#define BMAP_OFFSET	8
103
104#define PB_WIDTH	2048			/* Plane Width   (Bit) */
105#define PB_HEIGHT	1024			/* Plane Hight   (Bit) */
106#define PL_WIDTH	64			/* Plane Width  (long) */
107#define PS_WIDTH	128			/* Plane Width  (long) */
108#define P_WIDTH		256			/* Plane Width  (Byte) */
109
110#define SB_WIDTH	1280			/* Screen Width  (Bit) */
111#define SB_HEIGHT	1024			/* Screen Hight  (Bit) */
112#define SL_WIDTH	40			/* Screen Width (Long) */
113#define S_WIDTH		160			/* Screen Width (Byte) */
114
115#define FB_WIDTH	12			/* Font Width    (Bit) */
116#define FB_HEIGHT	20			/* Font Hight    (Bit) */
117
118
119#define NEXT_LINE(addr)			(addr +  (PL_WIDTH * FB_HEIGHT))
120#define SKIP_NEXT_LINE(addr)		(addr += (PL_WIDTH - SL_WIDTH))
121
122
123static void	bmd_draw_char(uint8_t *, uint8_t *, int, int, int);
124static void	bmd_reverse_char(uint8_t *, uint8_t *, int, int);
125static void	bmd_erase_char(uint8_t *, uint8_t *, int, int);
126static void	bmd_erase_screen(volatile uint32_t *);
127static void	bmd_scroll_screen(volatile uint32_t *, volatile uint32_t *,
128		    int, int, int, int);
129
130
131struct bmd_linec {
132	struct bmd_linec *bl_next;
133	struct bmd_linec *bl_prev;
134	int	bl_col;
135	int	bl_end;
136	uint8_t	bl_line[128];
137};
138
139struct bmd_softc {
140	int	bc_stat;
141	uint8_t *bc_raddr;
142	uint8_t *bc_waddr;
143	int	bc_xmin;
144	int	bc_xmax;
145	int	bc_ymin;
146	int	bc_ymax;
147	int	bc_col;
148	int	bc_row;
149	struct bmd_linec *bc_bl;
150	char	bc_escseq[8];
151	char   *bc_esc;
152	void  (*bc_escape)(int);
153};
154
155#define STAT_NORMAL	0x0000
156#define STAT_ESCAPE	0x0001
157#define STAT_INSERT	0x0100
158
159static struct	bmd_softc bmd_softc;
160static struct	bmd_linec bmd_linec[52];
161
162static void	bmd_escape(int);
163static void	bmd_escape_0(int);
164#if 0
165static void	bmd_escape_1(int);
166#endif
167
168
169/*
170 * Escape-Sequence
171 */
172
173static void
174bmd_escape(int c)
175{
176	struct bmd_softc *bp = &bmd_softc;
177
178	switch (c) {
179
180	case '[':
181		bp->bc_escape = bmd_escape_0;
182		break;
183
184	default:
185		bp->bc_stat &= ~STAT_ESCAPE;
186		bp->bc_esc = &bp->bc_escseq[0];
187		bp->bc_escape = bmd_escape;
188		break;
189	}
190}
191
192static void
193bmd_escape_0(int c)
194{
195	struct bmd_softc *bp = &bmd_softc;
196	struct bmd_linec *bq = bp->bc_bl;
197
198	switch (c) {
199
200	case 'A':
201		if (bp->bc_row > bp->bc_ymin) {
202			bp->bc_row--;
203		}
204		break;
205
206	case 'C':
207		if (bq->bl_col < bp->bc_xmax - 1) {
208			bq->bl_col++;
209		}
210		break;
211
212	case 'K':
213		if (bq->bl_col < bp->bc_xmax) {
214			int col;
215			for (col = bq->bl_col; col < bp->bc_xmax; col++)
216				bmd_erase_char(bp->bc_raddr,
217					       bp->bc_waddr,
218					       col, bp->bc_row);
219		}
220		bq->bl_end = bq->bl_col;
221		break;
222
223	case 'H':
224		bq->bl_col = bq->bl_end = bp->bc_xmin;
225		bp->bc_row = bp->bc_ymin;
226		break;
227
228	default:
229#if 0
230		*bp->bc_esc++ = c;
231		bp->bc_escape = bmd_escape_1;
232		return;
233#endif
234		break;
235	}
236
237	bp->bc_stat &= ~STAT_ESCAPE;
238	bp->bc_esc = &bp->bc_escseq[0];
239	bp->bc_escape = bmd_escape;
240}
241
242#if 0
243static void
244bmd_escape_1(int c)
245{
246	struct bmd_softc *bp = &bmd_softc;
247	struct bmd_linec *bq = bp->bc_bl;
248	int col = 0, row = 0;
249	char *p;
250
251	switch (c) {
252
253	case 'J':
254		bp->bc_stat &= ~STAT_ESCAPE;
255		bp->bc_esc = &bp->bc_escseq[0];
256		bp->bc_escape = bmd_escape;
257		break;
258
259	case 'H':
260		for (p = &bp->bc_escseq[0]; *p != ';'; p++)
261			row = (row * 10) + (*p - 0x30);
262		p++;
263		for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++)
264			col = (col * 10) + (*p - 0x30);
265
266		bq->bl_col = col + bp->bc_xmin;
267		bp->bc_row = row + bp->bc_ymin;
268
269		bp->bc_stat &= ~STAT_ESCAPE;
270		bp->bc_esc = &bp->bc_escseq[0];
271		bp->bc_escape = bmd_escape;
272		break;
273
274	default:
275		*bp->bc_esc++ = c;
276		break;
277	}
278}
279#endif
280
281/*
282 * Entry Routine
283 */
284
285void
286bmdinit(void)
287{
288	volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
289	volatile uint32_t *bmd_bmsel = (uint32_t *)BMAP_BMSEL;
290	struct bmd_softc *bp = &bmd_softc;
291	struct bmd_linec *bq;
292	int i;
293	union bmd_rfcnt rfcnt;
294
295	/*
296	 *  adjust plane position
297	 */
298
299	/* plane-0 hardware address */
300	bp->bc_raddr = (uint8_t *)(BMAP_BMAP0 + BMAP_OFFSET);
301	/* common bitmap hardware address */
302	bp->bc_waddr = (uint8_t *)(BMAP_BMP   + BMAP_OFFSET);
303
304	rfcnt.p.rfc_hcnt = 7;			/* shift left   16 dot */
305	rfcnt.p.rfc_vcnt = -27;			/* shift down    1 dot */
306	*bmd_rfcnt = rfcnt.u;
307
308	bp->bc_stat  = STAT_NORMAL;
309
310	bp->bc_xmin  = 8;
311	bp->bc_xmax  = 96;
312	bp->bc_ymin  = 2;
313	bp->bc_ymax  = 48;
314
315	bp->bc_row = bp->bc_ymin;
316
317	for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
318		bmd_linec[i].bl_next = &bmd_linec[i + 1];
319		bmd_linec[i].bl_prev = &bmd_linec[i - 1];
320	}
321	bmd_linec[bp->bc_ymax - 1].bl_next = &bmd_linec[bp->bc_ymin];
322	bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax - 1];
323
324	bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
325	bq->bl_col = bq->bl_end = bp->bc_xmin;
326
327	bp->bc_col = bp->bc_xmin;
328
329	bp->bc_esc = &bp->bc_escseq[0];
330	bp->bc_escape = bmd_escape;
331
332	*bmd_bmsel = 0xff;				/* all planes */
333	bmd_erase_screen((uint32_t *)bp->bc_waddr);	/* clear screen */
334	*bmd_bmsel = 0x01;				/* 1 plane */
335
336	/* turn on cursor */
337	bmd_reverse_char(bp->bc_raddr,
338			 bp->bc_waddr,
339			 bq->bl_col, bp->bc_row);
340}
341
342void
343bmdadjust(int16_t hcnt, int16_t vcnt)
344{
345	volatile uint32_t *bmd_rfcnt = (uint32_t *)BMAP_RFCNT;
346	union bmd_rfcnt rfcnt;
347
348	printf("bmdadjust: hcnt = %d, vcnt = %d\n", hcnt, vcnt);
349
350	rfcnt.p.rfc_hcnt = hcnt;		/* shift left   16 dot */
351	rfcnt.p.rfc_vcnt = vcnt;		/* shift down    1 dot */
352
353	*bmd_rfcnt = rfcnt.u;
354}
355
356int
357bmdputc(int c)
358{
359	struct bmd_softc *bp = &bmd_softc;
360	struct bmd_linec *bq = bp->bc_bl;
361	int i;
362
363	c &= 0x7F;
364
365	/* turn off cursor */
366	bmd_reverse_char(bp->bc_raddr,
367			 bp->bc_waddr,
368			 bq->bl_col, bp->bc_row);
369
370	/* do escape-sequence */
371	if (bp->bc_stat & STAT_ESCAPE) {
372		*bp->bc_esc++ = c;
373		(*bp->bc_escape)(c);
374		goto done;
375	}
376
377	if (isprint(c)) {
378		bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
379			      bq->bl_col, bp->bc_row, c);
380		bq->bl_col++;
381		bq->bl_end++;
382		if (bq->bl_col >= bp->bc_xmax) {
383			bq->bl_col = bq->bl_end = bp->bc_xmin;
384			bp->bc_row++;
385			if (bp->bc_row >= bp->bc_ymax) {
386				bmd_scroll_screen((uint32_t *)bp->bc_raddr,
387						  (uint32_t *)bp->bc_waddr,
388						  bp->bc_xmin, bp->bc_xmax,
389						  bp->bc_ymin, bp->bc_ymax);
390
391				bp->bc_row = bp->bc_ymax - 1;
392			}
393		}
394	} else {
395		switch (c) {
396		case 0x08:				/* BS */
397			if (bq->bl_col > bp->bc_xmin) {
398				bq->bl_col--;
399			}
400			break;
401
402		case 0x09:				/* HT */
403		case 0x0B:				/* VT */
404			i = ((bq->bl_col / 8) + 1) * 8;
405			if (i < bp->bc_xmax) {
406				bq->bl_col = bq->bl_end = i;
407			}
408			break;
409
410		case 0x0A:				/* NL */
411			bp->bc_row++;
412			if (bp->bc_row >= bp->bc_ymax) {
413				bmd_scroll_screen((uint32_t *)bp->bc_raddr,
414						  (uint32_t *)bp->bc_waddr,
415						  bp->bc_xmin, bp->bc_xmax,
416						  bp->bc_ymin, bp->bc_ymax);
417
418				bp->bc_row = bp->bc_ymax - 1;
419			}
420			break;
421
422		case 0x0D:				/* CR */
423			bq->bl_col = bp->bc_xmin;
424			break;
425
426		case 0x1B:				/* ESC */
427			bp->bc_stat |= STAT_ESCAPE;
428			*bp->bc_esc++ = 0x1b;
429			break;
430
431		case 0x7F:				/* DEL */
432			if (bq->bl_col > bp->bc_xmin) {
433				bq->bl_col--;
434				bmd_erase_char(bp->bc_raddr,
435					       bp->bc_waddr,
436					       bq->bl_col, bp->bc_row);
437			}
438			break;
439
440		default:
441			break;
442		}
443	}
444
445 done:
446	/* turn on  cursor */
447	bmd_reverse_char(bp->bc_raddr,
448			 bp->bc_waddr,
449			 bq->bl_col, bp->bc_row);
450
451	return c;
452}
453
454void
455bmdclear(void)
456{
457	struct bmd_softc *bp = &bmd_softc;
458	struct bmd_linec *bq = bp->bc_bl;
459
460	/* clear screen */
461	bmd_erase_screen((uint32_t *)bp->bc_waddr);
462
463	bq->bl_col = bq->bl_end = bp->bc_xmin;
464	bp->bc_row = bp->bc_ymin;
465
466	/* turn on cursor */
467	bmd_reverse_char(bp->bc_raddr,
468			 bp->bc_waddr,
469			 bq->bl_col, bp->bc_row);
470}
471
472
473/*
474 *  charactor operation routines
475 */
476
477static void
478bmd_draw_char(uint8_t *raddr, uint8_t *waddr, int col, int row, int c)
479{
480	volatile uint16_t *p, *q;
481	volatile uint32_t *lp, *lq;
482	const uint16_t *fp;
483	int i;
484
485	fp = &bmdfont[c][0];
486
487	switch (col % 4) {
488
489	case 0:
490		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
491		    + ((col / 4) * 6));
492		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
493		    + ((col / 4) * 6));
494		for (i = 0; i < FB_HEIGHT; i++) {
495			*q = (*p & 0x000F) | (*fp & 0xFFF0);
496			p += 128;
497			q += 128;
498			fp++;
499		}
500		break;
501
502	case 1:
503		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
504		    + ((col / 4) * 6));
505		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
506		    + ((col / 4) * 6));
507		for (i = 0; i < FB_HEIGHT; i++) {
508			*lq = (*lp & 0xFFF000FF) |
509			    ((uint32_t)(*fp & 0xFFF0) << 4);
510			lp += 64;
511			lq += 64;
512			fp++;
513		}
514		break;
515
516	case 2:
517		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
518		    + ((col / 4) * 6) + 2);
519		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
520		    + ((col / 4) * 6) + 2);
521		for (i = 0; i < FB_HEIGHT; i++) {
522			*lq = (*lp & 0xFF000FFF) |
523			    ((uint32_t)(*fp & 0xFFF0) << 8);
524			lp += 64;
525			lq += 64;
526			fp++;
527		}
528		break;
529
530	case 3:
531		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
532		    + ((col / 4) * 6) + 4);
533		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
534		    + ((col / 4) * 6) + 4);
535		for (i = 0; i < FB_HEIGHT; i++) {
536			*q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
537			p += 128;
538			q += 128;
539			fp++;
540		}
541		break;
542
543	default:
544		break;
545	}
546}
547
548static void
549bmd_reverse_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
550{
551	volatile uint16_t *p, *q;
552	volatile uint32_t *lp, *lq;
553	int i;
554
555	switch (col % 4) {
556
557	case 0:
558		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
559		    + ((col / 4) * 6));
560		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
561		    + ((col / 4) * 6));
562		for (i = 0; i < FB_HEIGHT; i++) {
563			*q = (*p & 0x000F) | (~(*p) & 0xFFF0);
564			p += 128;
565			q += 128;
566		}
567		break;
568
569	case 1:
570		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
571		    + ((col / 4) * 6));
572		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
573		    + ((col / 4) * 6));
574		for (i = 0; i < FB_HEIGHT; i++) {
575			*lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
576			lp += 64;
577			lq += 64;
578		}
579		break;
580
581	case 2:
582		lp = (uint32_t *)(raddr + ((row * FB_HEIGHT) << 8)
583		    + ((col / 4) * 6) + 2);
584		lq = (uint32_t *)(waddr + ((row * FB_HEIGHT) << 8)
585		    + ((col / 4) * 6) + 2);
586		for (i = 0; i < FB_HEIGHT; i++) {
587			*lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
588			lp += 64;
589			lq += 64;
590		}
591		break;
592
593	case 3:
594		p = (uint16_t *)(raddr + ((row * FB_HEIGHT) << 8)
595		    + ((col / 4) * 6) + 4);
596		q = (uint16_t *)(waddr + ((row * FB_HEIGHT) << 8)
597		    + ((col / 4) * 6) + 4);
598		for (i = 0; i < FB_HEIGHT; i++) {
599			*q = (*p & 0xF000) | (~(*p) & 0x0FFF);
600			p += 128;
601			q += 128;
602		}
603		break;
604
605	default:
606		break;
607	}
608}
609
610static void
611bmd_erase_char(uint8_t *raddr, uint8_t *waddr, int col, int row)
612{
613
614	bmd_draw_char(raddr, waddr, col, row, 0);
615}
616
617
618/*
619 * screen operation routines
620 */
621
622static void
623bmd_erase_screen(volatile uint32_t *lp)
624{
625	int i, j;
626
627	for (i = 0; i < SB_HEIGHT; i++) {
628		for (j = 0; j < SL_WIDTH; j++)
629			*lp++ = 0;
630		SKIP_NEXT_LINE(lp);
631	}
632}
633
634static void
635bmd_scroll_screen(volatile uint32_t *lp, volatile uint32_t *lq,
636    int xmin, int xmax, int ymin, int ymax)
637{
638	int i, j;
639
640	lp += ((PL_WIDTH * FB_HEIGHT) * (ymin + 1));
641	lq += ((PL_WIDTH * FB_HEIGHT) *  ymin);
642
643	for (i = 0; i < ((ymax - ymin -1) * FB_HEIGHT); i++) {
644		for (j = 0; j < SL_WIDTH; j++) {
645			*lq++ = *lp++;
646		}
647		lp += (PL_WIDTH - SL_WIDTH);
648		lq += (PL_WIDTH - SL_WIDTH);
649	}
650
651	for (i = 0; i < FB_HEIGHT; i++) {
652		for (j = 0; j < SL_WIDTH; j++) {
653			*lq++ = 0;
654		}
655		lq += (PL_WIDTH - SL_WIDTH);
656	}
657}
658