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