xref: /csrg-svn/sys/luna68k/dev/bmd.c (revision 57218)
1 /*
2  * Copyright (c) 1992 OMRON Corporation.
3  * Copyright (c) 1992 The Regents of the University of California.
4  * 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	7.3 (Berkeley) 12/19/92
12  */
13 /*
14 
15  * bmd.c --- Bitmap-Display raw-level driver routines
16  *
17  *	by A.Fujita, SEP-09-1992
18  */
19 
20 
21 #include <sys/param.h>
22 #include <sys/systm.h>
23 
24 extern u_short bmdfont[][20];
25 
26 #define isprint(c)	( c < 0x20 ? 0 : 1)
27 
28 /*
29  *  Width & Hight
30  */
31 
32 #define	PB_WIDTH	2048				/* Plane Width   (Bit) */
33 #define	PB_HIGHT	1024				/* Plane Hight   (Bit) */
34 #define PL_WIDTH	64				/* Plane Width  (long) */
35 #define PS_WIDTH	128				/* Plane Width  (long) */
36 #define P_WIDTH		256				/* Plane Width  (Byte) */
37 
38 #define SB_WIDTH	1280				/* Screen Width  (Bit) */
39 #define	SB_HIGHT	1024				/* Screen Hight  (Bit) */
40 #define SL_WIDTH	40				/* Screen Width (Long) */
41 #define S_WIDTH		160				/* Screen Width (Byte) */
42 
43 #define FB_WIDTH	12				/* Font Width    (Bit) */
44 #define FB_HIGHT	20				/* Font Hight    (Bit) */
45 
46 
47 #define NEXT_LINE(addr)				( addr +  (PL_WIDTH * FB_HIGHT) )
48 #define SKIP_NEXT_LINE(addr)			( addr += (PL_WIDTH - SL_WIDTH) )
49 
50 
51 void	bmd_add_new_line();
52 
53 void	bmd_draw_char();
54 void	bmd_reverse_char();
55 void	bmd_erase_char();
56 void	bmd_erase_screen();
57 void	bmd_scroll_screen();
58 
59 
60 struct bmd_linec {
61 	struct bmd_linec *bl_next;
62 	struct bmd_linec *bl_prev;
63 	int	bl_col;
64 	int	bl_end;
65 	u_char	bl_line[128];
66 };
67 
68 struct bmd_softc {
69 	int	bc_stat;
70 	char   *bc_raddr;
71 	char   *bc_waddr;
72 	int	bc_xmin;
73 	int	bc_xmax;
74 	int	bc_ymin;
75 	int	bc_ymax;
76 	int	bc_col;
77 	int	bc_row;
78 	struct bmd_linec *bc_bl;
79 	char	bc_escseq[8];
80 	char   *bc_esc;
81 	void  (*bc_escape)();
82 };
83 
84 #define	STAT_NORMAL	0x0000
85 #define	STAT_ESCAPE	0x0001
86 #define	STAT_INSERT	0x0100
87 
88 struct	bmd_softc bmd_softc;
89 struct	bmd_linec bmd_linec[52];
90 
91 void	bmd_escape();
92 void	bmd_escape_0();
93 void	bmd_escape_1();
94 
95 
96 /*
97  * Escape-Sequence
98  */
99 
100 void
101 bmd_escape(c)
102 	int c;
103 {
104 	register struct bmd_softc *bp = &bmd_softc;
105 
106 	switch (c) {
107 
108 	case '[':
109 		bp->bc_escape = bmd_escape_0;
110 		break;
111 
112 	default:
113 		bp->bc_stat &= ~STAT_ESCAPE;
114 		bp->bc_esc = &bp->bc_escseq[0];
115 		bp->bc_escape = bmd_escape;
116 		break;
117 	}
118 }
119 
120 void
121 bmd_escape_0(c)
122 	int c;
123 {
124 	register struct bmd_softc *bp = &bmd_softc;
125 	register struct	bmd_linec *bq = bp->bc_bl;
126 
127 	switch (c) {
128 
129 	case 'A':
130 		if (bp->bc_row > bp->bc_ymin) {
131 			bp->bc_row--;
132 		}
133 		break;
134 
135 	case 'C':
136 		if (bq->bl_col < bp->bc_xmax - 1) {
137 			bq->bl_col++;
138 		}
139 		break;
140 
141 	case 'K':
142 		if (bq->bl_col < bp->bc_xmax) {
143 			register int col;
144 			for (col = bq->bl_col; col < bp->bc_xmax; col++)
145 				bmd_erase_char(bp->bc_raddr,
146 					       bp->bc_waddr,
147 					       col, bp->bc_row);
148 		}
149 		bq->bl_end = bq->bl_col;
150 		break;
151 
152 	case 'H':
153 		bq->bl_col = bq->bl_end = bp->bc_xmin;
154 		bp->bc_row = bp->bc_ymin;
155 		break;
156 
157 	default:
158 /*
159 		*bp->bc_esc++ = c;
160 		bp->bc_escape = bmd_escape_1;
161 		return;
162  */
163 		break;
164 	}
165 
166 	bp->bc_stat &= ~STAT_ESCAPE;
167 	bp->bc_esc = &bp->bc_escseq[0];
168 	bp->bc_escape = bmd_escape;
169 }
170 
171 void
172 bmd_escape_1(c)
173 	int c;
174 {
175 	register struct bmd_softc *bp = &bmd_softc;
176 	register struct	bmd_linec *bq = bp->bc_bl;
177 	register int col = 0, row = 0;
178 	register char *p;
179 
180 	switch (c) {
181 
182 	case 'J':
183 		bp->bc_stat &= ~STAT_ESCAPE;
184 		bp->bc_esc = &bp->bc_escseq[0];
185 		bp->bc_escape = bmd_escape;
186 		break;
187 
188 	case 'H':
189 		for (p = &bp->bc_escseq[0]; *p != ';'; p++)
190 			row = (row * 10) + (*p - 0x30);
191 		p++;
192 		for (p = &bp->bc_escseq[0]; p != bp->bc_esc; p++)
193 			col = (col * 10) + (*p - 0x30);
194 
195 		bq->bl_col = col + bp->bc_xmin;
196 		bp->bc_row = row + bp->bc_ymin;
197 
198 		bp->bc_stat &= ~STAT_ESCAPE;
199 		bp->bc_esc = &bp->bc_escseq[0];
200 		bp->bc_escape = bmd_escape;
201 		break;
202 
203 	default:
204 		*bp->bc_esc++ = c;
205 		break;
206 	}
207 }
208 
209 
210 /*
211  * Entry Routine
212  */
213 
214 bmdinit()
215 {
216 	register struct bmd_softc *bp = &bmd_softc;
217 	register struct bmd_linec *bq;
218 	register int i;
219 
220 	bp->bc_raddr = (char *) 0xB10C0008;		/* plane-0 hardware address */
221 	bp->bc_waddr = (char *) 0xB1080008;		/* common bitmap hardware address */
222 
223 	/*
224 	 *  adjust plane position
225 	 */
226 
227 	fb_adjust(7, -27);
228 
229 	bp->bc_stat  = STAT_NORMAL;
230 
231 	bp->bc_xmin  = 8;
232 	bp->bc_xmax  = 96;
233 	bp->bc_ymin  = 2;
234 	bp->bc_ymax  = 48;
235 
236 	bp->bc_row = bp->bc_ymin;
237 
238 	for (i = bp->bc_ymin; i < bp->bc_ymax; i++) {
239 		bmd_linec[i].bl_next = &bmd_linec[i+1];
240 		bmd_linec[i].bl_prev = &bmd_linec[i-1];
241 	}
242 	bmd_linec[bp->bc_ymax-1].bl_next = &bmd_linec[bp->bc_ymin];
243 	bmd_linec[bp->bc_ymin].bl_prev = &bmd_linec[bp->bc_ymax-1];
244 
245 	bq = bp->bc_bl = &bmd_linec[bp->bc_ymin];
246 	bq->bl_col = bq->bl_end = bp->bc_xmin;
247 
248 	bp->bc_col = bp->bc_xmin;
249 
250 	bp->bc_esc = &bp->bc_escseq[0];
251 	bp->bc_escape = bmd_escape;
252 
253 	bmd_erase_screen((u_long *) bp->bc_waddr);	/* clear screen */
254 
255 							/* turn on  cursole */
256 	bmd_reverse_char(bp->bc_raddr,
257 			 bp->bc_waddr,
258 			 bq->bl_col, bp->bc_row);
259 }
260 
261 bmdputc(c)
262 	register int c;
263 {
264 	register struct bmd_softc *bp = &bmd_softc;
265 	register struct bmd_linec *bq = bp->bc_bl;
266 	register int i;
267 
268 	c &= 0x7F;
269 							/* turn off cursole */
270 	bmd_reverse_char(bp->bc_raddr,
271 			 bp->bc_waddr,
272 			 bq->bl_col, bp->bc_row);
273 							/* do escape-sequence */
274 	if (bp->bc_stat & STAT_ESCAPE) {
275 		*bp->bc_esc++ = c;
276 		(*bp->bc_escape)(c);
277 		goto done;
278 	}
279 
280 	if (isprint(c)) {
281 		bmd_draw_char(bp->bc_raddr, bp->bc_waddr,
282 			      bq->bl_col, bp->bc_row, c);
283 		bq->bl_col++;
284 		bq->bl_end++;
285 		if (bq->bl_col >= bp->bc_xmax) {
286 			bq->bl_col = bq->bl_end = bp->bc_xmin;
287 			bp->bc_row++;
288 			if (bp->bc_row >= bp->bc_ymax) {
289 				bmd_scroll_screen((u_long *) bp->bc_raddr,
290 						  (u_long *) bp->bc_waddr,
291 						  bp->bc_xmin, bp->bc_xmax,
292 						  bp->bc_ymin, bp->bc_ymax);
293 
294 				bp->bc_row = bp->bc_ymax - 1;
295 			}
296 		}
297 	} else {
298 		switch (c) {
299 		case 0x08:				/* BS */
300 			if (bq->bl_col > bp->bc_xmin) {
301 				bq->bl_col--;
302 			}
303 			break;
304 
305 		case 0x09:				/* HT */
306 		case 0x0B:				/* VT */
307 			i = ((bq->bl_col / 8) + 1) * 8;
308 			if (i < bp->bc_xmax) {
309 				bq->bl_col = bq->bl_end = i;
310 			}
311 			break;
312 
313 		case 0x0A:				/* NL */
314 			bp->bc_row++;
315 			if (bp->bc_row >= bp->bc_ymax) {
316 				bmd_scroll_screen((u_long *) bp->bc_raddr,
317 						  (u_long *) bp->bc_waddr,
318 						  bp->bc_xmin, bp->bc_xmax,
319 						  bp->bc_ymin, bp->bc_ymax);
320 
321 				bp->bc_row = bp->bc_ymax - 1;
322 			}
323 			break;
324 
325 		case 0x0D:				/* CR */
326 			bq->bl_col = bp->bc_xmin;
327 			break;
328 
329 		case 0x1b:				/* ESC */
330 			bp->bc_stat |= STAT_ESCAPE;
331 			*bp->bc_esc++ = 0x1b;
332 			break;
333 
334 		case 0x7F:				/* DEL */
335 			if (bq->bl_col > bp->bc_xmin) {
336 				bq->bl_col--;
337 				bmd_erase_char(bp->bc_raddr,
338 					       bp->bc_waddr,
339 					       bq->bl_col, bp->bc_row);
340 			}
341 			break;
342 
343 		default:
344 			break;
345 		}
346 	}
347 
348  done:
349 							/* turn on  cursole */
350 	bmd_reverse_char(bp->bc_raddr,
351 			 bp->bc_waddr,
352 			 bq->bl_col, bp->bc_row);
353 
354 	return(c);
355 }
356 
357 bmdclear()
358 {
359 	register struct bmd_softc *bp = &bmd_softc;
360 	register struct bmd_linec *bq = bp->bc_bl;
361 
362 	bmd_erase_screen((u_long *) bp->bc_waddr);	/* clear screen */
363 
364 	bq->bl_col = bq->bl_end = bp->bc_xmin;
365 	bp->bc_row = bp->bc_ymin;
366 
367 	bmd_reverse_char(bp->bc_raddr,
368 			 bp->bc_waddr,
369 			 bq->bl_col, bp->bc_row);	/* turn on  cursole */
370 }
371 
372 
373 /*
374  *
375  */
376 
377 void
378 bmd_add_new_line()
379 {
380 }
381 
382 
383 /*
384  *  charactor operation routines
385  */
386 
387 void
388 bmd_draw_char(raddr, waddr, col, row, c)
389 	char *raddr;
390 	char *waddr;
391 	int col;
392 	int row;
393 	int c;
394 {
395 	volatile register u_short  *p,  *q, *fp;
396 	volatile register u_long  *lp, *lq;
397 	register int i;
398 
399 	fp = &bmdfont[c][0];
400 
401 	switch (col % 4) {
402 
403 	case 0:
404 		p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
405 		q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
406 		for (i = 0; i < FB_HIGHT; i++) {
407 			*q = (*p & 0x000F) | (*fp & 0xFFF0);
408 			p += 128;
409 			q += 128;
410 			fp++;
411 		}
412 		break;
413 
414 	case 1:
415 		lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
416 		lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
417 		for (i = 0; i < FB_HIGHT; i++) {
418 			*lq = (*lp & 0xFFF000FF) | ((u_long)(*fp & 0xFFF0) << 4);
419 			lp += 64;
420 			lq += 64;
421 			fp++;
422 		}
423 		break;
424 
425 	case 2:
426 		lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
427 		lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
428 		for (i = 0; i < FB_HIGHT; i++) {
429 			*lq = (*lp & 0xFF000FFF) | ((u_long)(*fp & 0xFFF0) << 8);
430 			lp += 64;
431 			lq += 64;
432 			fp++;
433 		}
434 		break;
435 
436 	case 3:
437 		p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
438 		q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
439 		for (i = 0; i < FB_HIGHT; i++) {
440 			*q = (*p & 0xF000) | ((*fp & 0xFFF0) >> 4);
441 			p += 128;
442 			q += 128;
443 			fp++;
444 		}
445 		break;
446 
447 	default:
448 		break;
449 	}
450 }
451 
452 void
453 bmd_reverse_char(raddr, waddr, col, row)
454 	char *raddr;
455 	char *waddr;
456 	int col;
457 	int row;
458 {
459 	volatile register u_short  *p,  *q,  us;
460 	volatile register u_long  *lp, *lq,  ul;
461 	register int i;
462 
463 	switch (col%4) {
464 
465 	case 0:
466 		p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
467 		q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
468 		for (i = 0; i < FB_HIGHT; i++) {
469 			*q = (*p & 0x000F) | (~(*p) & 0xFFF0);
470 			p += 128;
471 			q += 128;
472 		}
473 		break;
474 
475 	case 1:
476 		lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
477 		lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ));
478 		for (i = 0; i < FB_HIGHT; i++) {
479 			*lq = (*lp & 0xFFF000FF) | (~(*lp) & 0x000FFF00);
480 			lp += 64;
481 			lq += 64;
482 		}
483 		break;
484 
485 	case 2:
486 		lp = (u_long *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
487 		lq = (u_long *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 2 );
488 		for (i = 0; i < FB_HIGHT; i++) {
489 			*lq = (*lp & 0xFF000FFF) | (~(*lp) & 0x00FFF000);
490 			lp += 64;
491 			lq += 64;
492 		}
493 		break;
494 
495 	case 3:
496 		p = (u_short *) ( raddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
497 		q = (u_short *) ( waddr + (( row * FB_HIGHT ) << 8 ) + (( col / 4 ) * 6 ) + 4 );
498 		for (i = 0; i < FB_HIGHT; i++) {
499 			*q = (*p & 0xF000) | (~(*p) & 0x0FFF);
500 			p += 128;
501 			q += 128;
502 		}
503 		break;
504 
505 	default:
506 		break;
507 	}
508 }
509 
510 void
511 bmd_erase_char(raddr, waddr, col, row)
512 	char *raddr;
513 	char *waddr;
514 	int col;
515 	int row;
516 {
517 	bmd_draw_char(raddr, waddr, col, row, 0);
518 
519 	return;
520 }
521 
522 
523 /*
524  * screen operation routines
525  */
526 
527 void
528 bmd_erase_screen(lp)
529 	volatile register u_long *lp;
530 {
531 	register int i, j;
532 
533 	for (i = 0; i < SB_HIGHT; i++) {
534 		for (j = 0; j < SL_WIDTH; j++)
535 			*lp++ = 0;
536 		SKIP_NEXT_LINE(lp);
537 	}
538 
539 	return;
540 }
541 
542 void
543 bmd_scroll_screen(lp, lq, xmin, xmax, ymin, ymax)
544 	volatile register u_long *lp;
545 	volatile register u_long *lq;
546 	int xmin, xmax, ymin, ymax;
547 {
548 	register int i, j;
549 
550 	lp += ((PL_WIDTH * FB_HIGHT) * (ymin + 1));
551 	lq += ((PL_WIDTH * FB_HIGHT) *  ymin);
552 
553 	for (i = 0; i < ((ymax - ymin -1) * FB_HIGHT); i++) {
554 		for (j = 0; j < SL_WIDTH; j++) {
555 			*lq++ = *lp++;
556 		}
557 		lp += (PL_WIDTH - SL_WIDTH);
558 		lq += (PL_WIDTH - SL_WIDTH);
559 	}
560 
561 	for (i = 0; i < FB_HIGHT; i++) {
562 		for (j = 0; j < SL_WIDTH; j++) {
563 			*lq++ = 0;
564 		}
565 		lq += (PL_WIDTH - SL_WIDTH);
566 	}
567 
568 }
569