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