xref: /netbsd-src/sys/arch/amiga/dev/ite_cc.c (revision ae1bfcddc410612bc8c58b807e1830becb69a24c)
1 /*
2  *	$Id: ite_cc.c,v 1.16 1994/05/08 05:53:19 chopps Exp $
3  */
4 
5 #include <sys/param.h>
6 #include <sys/conf.h>
7 #include <sys/proc.h>
8 #include <sys/device.h>
9 #include <sys/ioctl.h>
10 #include <sys/tty.h>
11 #include <sys/systm.h>
12 #include <sys/queue.h>
13 #include <sys/termios.h>
14 #include <dev/cons.h>
15 #include <machine/cpu.h>
16 #include <amiga/dev/itevar.h>
17 #include <amiga/dev/iteioctl.h>
18 #include <amiga/amiga/cc.h>
19 #include <amiga/amiga/device.h>
20 #include <amiga/dev/grfabs_reg.h>
21 #include <amiga/dev/grfioctl.h>
22 #include <amiga/dev/grfvar.h>
23 #include <amiga/dev/grf_ccreg.h>
24 #include <amiga/dev/viewioctl.h>
25 #include <amiga/dev/viewvar.h>
26 
27 #ifndef KFONT_CUSTOM
28 #ifdef KFONT_8X11
29 #define kernel_font_width       kernel_font_width_8x11
30 #define kernel_font_height      kernel_font_height_8x11
31 #define kernel_font_baseline    kernel_font_baseline_8x11
32 #define kernel_font_boldsmear   kernel_font_boldsmear_8x11
33 #define kernel_font_lo  kernel_font_lo_8x11
34 #define kernel_font_hi  kernel_font_hi_8x11
35 #define kernel_font     kernel_font_8x11
36 #define kernel_cursor   kernel_cursor_8x11
37 #else
38 #define kernel_font_width       kernel_font_width_8x8
39 #define kernel_font_height      kernel_font_height_8x8
40 #define kernel_font_baseline    kernel_font_baseline_8x8
41 #define kernel_font_boldsmear   kernel_font_boldsmear_8x8
42 #define kernel_font_lo  kernel_font_lo_8x8
43 #define kernel_font_hi  kernel_font_hi_8x8
44 #define kernel_font     kernel_font_8x8
45 #define kernel_cursor   kernel_cursor_8x8
46 #endif
47 #endif
48 
49 extern u_char kernel_font_width, kernel_font_height, kernel_font_baseline;
50 extern short  kernel_font_boldsmear;
51 extern u_char kernel_font_lo, kernel_font_hi;
52 extern u_char kernel_font[], kernel_cursor[];
53 
54 /*
55  * This is what ip->priv points to;
56  * it contains local variables for custom-chip ites.
57  */
58 struct ite_priv {
59 	view_t *view;		/* the view for this ite. */
60 	u_char **row_ptr;	/* array of pointers into the bitmap  */
61 	u_long row_bytes;
62 	u_long cursor_opt;
63 	u_int  *column_offset;	/* array of offsets for columns */
64 	u_int  row_offset;	/* the row offset */
65 	u_short width;		/* the bitmap width */
66 	u_short underline;	/* where the underline goes */
67 	u_short ft_x;		/* the font width */
68 	u_short ft_y;		/* the font height */
69 	u_char *font_cell[256];	/* the font pointer */
70 };
71 typedef struct ite_priv ipriv_t;
72 
73 void view_deinit __P((struct ite_softc *));
74 void view_init __P((struct ite_softc *));
75 
76 static void putc8 __P((struct ite_softc *, int, int, int, int));
77 static void clear8 __P((struct ite_softc *, int, int, int, int));
78 static void scroll8 __P((struct ite_softc *, int, int, int, int));
79 static void cursor32 __P((struct ite_softc *, int));
80 static void scrollbmap __P((bmap_t *, u_short, u_short, u_short, u_short,
81     short, short, u_char));
82 
83 /* patchable */
84 int ite_default_x = 0;		/* def leftedge offset */
85 int ite_default_y = 0;		/* def topedge offset */
86 int ite_default_width = 640;	/* def width */
87 int ite_default_depth = 2;	/* def depth */
88 #if defined (GRF_NTSC)
89 int ite_default_height = 400;	/* def NTSC height */
90 #elif defined (GRF_PAL)
91 int ite_default_height = 512;	/* def PAL height */
92 #else
93 int ite_default_height = 400;	/* def NON-PAL/NTSC height (?) */
94 #endif
95 
96 /* audio bell stuff */
97 u_int bvolume = 10;
98 u_int bpitch = 660;
99 u_int bmsec = 75;
100 
101 static char *bsamplep;
102 static char sample[20] = {
103 	0,39,75,103,121,127,121,103,75,39,0,
104 	-39,-75,-103,-121,-127,-121,-103,-75,-39
105 };
106 
107 /*
108  * called from grf_cc to return console priority
109  */
110 int
111 grfcc_cnprobe()
112 {
113 	return(CN_INTERNAL);
114 }
115 
116 /*
117  * called form grf_cc to init ite portion of
118  * grf_softc struct
119  */
120 void
121 grfcc_iteinit(gp)
122 	struct grf_softc *gp;
123 {
124 	gp->g_itecursor = cursor32;
125 	gp->g_iteputc = putc8;
126 	gp->g_iteclear = clear8;
127 	gp->g_itescroll = scroll8;
128 	gp->g_iteinit = view_init;
129 	gp->g_itedeinit = view_deinit;
130 }
131 
132 void
133 init_bell()
134 {
135 	short i;
136 
137 	if (bsamplep != NULL)
138 		return;
139 	bsamplep = alloc_chipmem(20);
140 	if (bsamplep == NULL)
141 		panic("no chipmem for ccbell");
142 
143 	bcopy(sample, bsamplep, 20);
144 }
145 
146 void
147 cc_bell()
148 {
149 	u_int clock;
150 	u_int period;
151 	u_int count;
152 
153 	clock = 3579545; 	/* PAL 3546895 */
154 
155 	/*
156 	 * the number of clock ticks per sample byte must be > 124
157 	 * ergo bpitch must be < clock / 124*20
158 	 * i.e. ~1443, 1300 to be safe (PAL etc.). also not zero obviously
159 	 */
160 	period = clock / (bpitch * 20);
161 	count = bmsec * bpitch / 1000;
162 
163 	play_sample(10, PREP_DMA_MEM(bsamplep), period, bvolume, 0x3, count);
164 }
165 
166 
167 int
168 ite_newsize(ip, winsz)
169 	struct ite_softc *ip;
170 	struct itewinsize *winsz;
171 {
172 	extern struct view_softc views[];
173 	struct view_size vs;
174 	ipriv_t *cci = ip->priv;
175 	u_long fbp, i;
176 	int error;
177 
178 	vs.x = winsz->x;
179 	vs.y = winsz->y;
180 	vs.width = winsz->width;
181 	vs.height = winsz->height;
182 	vs.depth = winsz->depth;
183 	error = viewioctl(0, VIOCSSIZE, &vs, 0, -1);
184 
185 	/*
186 	 * Reinitialize our structs
187 	 */
188 	cci->view = views[0].view;
189 
190 	/* -1 for bold. */
191 	ip->cols = (cci->view->display.width - 1) / ip->ftwidth;
192 	ip->rows = cci->view->display.height / ip->ftheight;
193 
194 	/*
195 	 * save new values so that future opens use them
196 	 * this may not be correct when we implement Virtual Consoles
197 	 */
198 	ite_default_height = cci->view->display.height;
199 	ite_default_width = cci->view->display.width;
200 	ite_default_x = cci->view->display.x;
201 	ite_default_y = cci->view->display.y;
202 	ite_default_depth = cci->view->bitmap->depth;
203 
204 	if (cci->row_ptr)
205 		free_chipmem(cci->row_ptr);
206 	if (cci->column_offset)
207 		free_chipmem(cci->column_offset);
208 
209 	cci->row_ptr = alloc_chipmem(sizeof(u_char *) * ip->rows);
210 	cci->column_offset = alloc_chipmem(sizeof(u_int) * ip->cols);
211 
212 	if (cci->row_ptr == NULL || cci->column_offset == NULL)
213 		panic("no chipmem for itecc data");
214 
215 
216 	cci->width = cci->view->bitmap->bytes_per_row << 3;
217 	cci->underline = ip->ftbaseline + 1;
218 	cci->row_offset = cci->view->bitmap->bytes_per_row
219 	    + cci->view->bitmap->row_mod;
220 	cci->ft_x = ip->ftwidth;
221 	cci->ft_y = ip->ftheight;
222 
223 	cci->row_bytes = cci->row_offset * ip->ftheight;
224 
225 	cci->row_ptr[0] = VDISPLAY_LINE (cci->view, 0, 0);
226 	for (i = 1; i < ip->rows; i++)
227 		cci->row_ptr[i] = cci->row_ptr[i-1] + cci->row_bytes;
228 
229 	/* initialize the column offsets */
230 	cci->column_offset[0] = 0;
231 	for (i = 1; i < ip->cols; i++)
232 		cci->column_offset[i] = cci->column_offset[i - 1] + cci->ft_x;
233 
234 	/* initialize the font cell pointers */
235 	cci->font_cell[ip->font_lo] = ip->font;
236 	for (i=ip->font_lo+1; i<=ip->font_hi; i++)
237 		cci->font_cell[i] = cci->font_cell[i-1] + ip->ftheight;
238 
239 	return (error);
240 }
241 
242 void
243 view_init(ip)
244 	register struct ite_softc *ip;
245 {
246 	struct itewinsize wsz;
247 	ipriv_t *cci;
248 
249 	cci = ip->priv;
250 
251 	if (cci)
252 		return;
253 
254 	init_bell();
255 
256 	ip->font     = kernel_font;
257 	ip->font_lo  = kernel_font_lo;
258 	ip->font_hi  = kernel_font_hi;
259 	ip->ftwidth  = kernel_font_width;
260 	ip->ftheight = kernel_font_height;
261 	ip->ftbaseline = kernel_font_baseline;
262 	ip->ftboldsmear = kernel_font_boldsmear;
263 
264 	/* Find the correct set of rendering routines for this font.  */
265 	if (ip->ftwidth > 8)
266 		panic("kernel font size not supported");
267 	cci = alloc_chipmem(sizeof (*cci));
268 	if (cci == NULL)
269 		panic("no memory for console device.");
270 
271 	ip->priv = cci;
272 	cci->cursor_opt = 0;
273 	cci->view = NULL;
274 	cci->row_ptr = NULL;
275 	cci->column_offset = NULL;
276 
277 	wsz.x = ite_default_x;
278 	wsz.y = ite_default_y;
279 	wsz.width = ite_default_width;
280 	wsz.height = ite_default_height;
281 	wsz.depth = ite_default_depth;
282 
283 	ite_newsize (ip, &wsz);
284 	cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
285 }
286 
287 int
288 ite_grf_ioctl (ip, cmd, addr, flag, p)
289 	struct ite_softc *ip;
290 	caddr_t addr;
291 	struct proc *p;
292 {
293 	struct winsize ws;
294 	struct itewinsize *is;
295 	struct itebell *ib;
296 	ipriv_t *cci;
297 	int error;
298 
299 	cci = ip->priv;
300 	error = 0;
301 
302 	switch (cmd) {
303 	case ITEIOCGWINSZ:
304 		is = (struct itewinsize *)addr;
305 		is->x = cci->view->display.x;
306 		is->y = cci->view->display.y;
307 		is->width = cci->view->display.width;
308 		is->height = cci->view->display.height;
309 		is->depth = cci->view->bitmap->depth;
310 		break;
311 	case ITEIOCSWINSZ:
312 		is = (struct itewinsize *)addr;
313 
314 		if (ite_newsize(ip, is))
315 			error = ENOMEM;
316 		else {
317 			ws.ws_row = ip->rows;
318 			ws.ws_col = ip->cols;
319 			ws.ws_xpixel = cci->view->display.width;
320 			ws.ws_ypixel = cci->view->display.height;
321 			ite_reset (ip);
322 			/*
323 			 * XXX tell tty about the change
324 			 * XXX this is messy, but works
325 			 */
326 			iteioctl(0, TIOCSWINSZ, (caddr_t)&ws, 0, p);
327 		}
328 		break;
329 	case ITEIOCDSPWIN:
330 		cc_mode(ip->grf, GM_GRFON, NULL, 0, 0);
331 		break;
332 	case ITEIOCREMWIN:
333 		cc_mode(ip->grf, GM_GRFOFF, NULL, 0, 0);
334 		break;
335 	case ITEIOCGBELL:
336 		ib = (struct itebell *)addr;
337 		ib->volume = bvolume;
338 		ib->pitch = bpitch;
339 		ib->msec = bmsec;
340 		break;
341 	case ITEIOCSBELL:
342 		ib = (struct itebell *)addr;
343 		/* bounds check */
344 		if (ib->pitch > MAXBPITCH || ib->pitch < MINBPITCH ||
345 		    ib->volume > MAXBVOLUME || ib->msec > MAXBTIME)
346 			error = EINVAL;
347 		else {
348 			bvolume = ib->volume;
349 			bpitch = ib->pitch;
350 			bmsec = ib->msec;
351 		}
352 		break;
353 	case VIOCSCMAP:
354 	case VIOCGCMAP:
355 		/*
356 		 * XXX needs to be fixed when multiple console implemented
357 		 * XXX watchout for that -1 its not really the kernel talking
358 		 * XXX these two commands don't use the proc pointer though
359 		 */
360 		error = viewioctl(0, cmd, addr, flag, -1);
361 		break;
362 	default:
363 		error = -1;
364 		break;
365 	}
366 	return (error);
367 }
368 
369 void
370 view_deinit(ip)
371 	struct ite_softc *ip;
372 {
373 	ip->flags &= ~ITE_INITED;
374 }
375 
376 /*** (M<8)-by-N routines ***/
377 
378 static void
379 cursor32(struct ite_softc *ip, int flag)
380 {
381 	int cend, ofs, h, cstart, dr_plane;
382 	u_char *pl, opclr, opset;
383 	ipriv_t *cci;
384 	bmap_t *bm;
385 	view_t *v;
386 
387 	cci = ip->priv;
388 	v = cci->view;
389    	bm = v->bitmap;
390 	dr_plane = (bm->depth > 1 ? bm->depth-1 : 0);
391 
392 	if (flag == END_CURSOROPT)
393 		cci->cursor_opt--;
394 	else if (flag == START_CURSOROPT) {
395 		if (!cci->cursor_opt)
396 			cursor32 (ip, ERASE_CURSOR);
397 		cci->cursor_opt++;
398 		return;		  /* if we are already opted. */
399 	}
400 
401 	if (cci->cursor_opt)
402 		return;		  /* if we are still nested. */
403 				  /* else we draw the cursor. */
404 	cstart = 0;
405 	cend = ip->ftheight-1;
406 	pl = VDISPLAY_LINE(v, dr_plane, (ip->cursory * ip->ftheight + cstart));
407 	ofs = (ip->cursorx * ip->ftwidth);
408 
409 	if (flag != DRAW_CURSOR && flag != END_CURSOROPT) {
410 		/*
411 		 * erase the cursor
412 		 */
413 		int h;
414 
415 		if (dr_plane) {
416 			for (h = cend; h >= 0; h--) {
417 				asm("bfclr %0@{%1:%2}" : : "a" (pl),
418 				    "d" (ofs), "d" (ip->ftwidth));
419 				pl += cci->row_offset;
420 			}
421 		} else {
422 			for (h = cend; h >= 0; h--) {
423 				asm("bfchg %0@{%1:%2}" : : "a" (pl),
424 				    "d" (ofs), "d" (ip->ftwidth));
425 				pl += cci->row_offset;
426 			}
427 		}
428 	}
429 
430 	if (flag != DRAW_CURSOR && flag != MOVE_CURSOR &&
431 	    flag != END_CURSOROPT)
432 		return;
433 
434 	/*
435 	 * draw the cursor
436 	 */
437 
438 	ip->cursorx = MIN(ip->curx, ip->cols-1);
439 	ip->cursory = ip->cury;
440 	cstart = 0;
441 	cend = ip->ftheight-1;
442 	pl = VDISPLAY_LINE(v, dr_plane, ip->cursory * ip->ftheight + cstart);
443 	ofs = ip->cursorx * ip->ftwidth;
444 
445 	if (dr_plane) {
446 		for (h = cend; h >= 0; h--) {
447 			asm("bfset %0@{%1:%2}" : : "a" (pl),
448 			    "d" (ofs), "d" (ip->ftwidth));
449 			pl += cci->row_offset;
450 		}
451 	} else {
452 		for (h = cend; h >= 0; h--) {
453 			asm("bfchg %0@{%1:%2}" : : "a" (pl),
454 			    "d" (ofs), "d" (ip->ftwidth));
455 			pl += cci->row_offset;
456 		}
457 	}
458 }
459 
460 
461 static inline
462 int expbits (int data)
463 {
464 	int i, nd = 0;
465 
466 	if (data & 1)
467 		nd |= 0x02;
468 	for (i=1; i < 32; i++) {
469 		if (data & (1 << i))
470 			nd |= 0x5 << (i-1);
471 	}
472 	nd &= ~data;
473 	return(~nd);
474 }
475 
476 
477 /* Notes: optimizations given the kernel_font_(width|height) #define'd.
478  *        the dbra loops could be elminated and unrolled using height,
479  *        the :width in the bfxxx instruction could be made immediate instead
480  *        of a data register as it now is.
481  *        the underline could be added when the loop is unrolled
482  *
483  *        It would look like hell but be very fast.*/
484 
485 static void
486 putc_nm (cci,p,f,co,ro,fw,fh)
487     register ipriv_t *cci;
488     register u_char  *p;
489     register u_char  *f;
490     register u_int    co;
491     register u_int    ro;
492     register u_int    fw;
493     register u_int    fh;
494 {
495     while (fh--) {
496 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
497 	     "d" (*f++), "a" (p), "d" (co), "d" (fw));
498 	p += ro;
499     }
500 }
501 
502 static void
503 putc_in (cci,p,f,co,ro,fw,fh)
504     register ipriv_t *cci;
505     register u_char  *p;
506     register u_char  *f;
507     register u_int    co;
508     register u_int    ro;
509     register u_int    fw;
510     register u_int    fh;
511 {
512     while (fh--) {
513 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
514 	     "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
515 	p += ro;
516     }
517 }
518 
519 
520 static void
521 putc_ul (cci,p,f,co,ro,fw,fh)
522     register ipriv_t *cci;
523     register u_char  *p;
524     register u_char  *f;
525     register u_int    co;
526     register u_int    ro;
527     register u_int    fw;
528     register u_int    fh;
529 {
530     int underline = cci->underline;
531     while (underline--) {
532 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
533 	     "d" (*f++), "a" (p), "d" (co), "d" (fw));
534 	p += ro;
535     }
536 
537     asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
538 	 "d" (expbits(*f++)), "a" (p), "d" (co), "d" (fw));
539     p += ro;
540 
541     underline = fh - cci->underline - 1;
542     while (underline--) {
543 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
544 	     "d" (*f++), "a" (p), "d" (co), "d" (fw));
545 	p += ro;
546     }
547 }
548 
549 
550 static void
551 putc_ul_in (cci,p,f,co,ro,fw,fh)
552     register ipriv_t *cci;
553     register u_char  *p;
554     register u_char  *f;
555     register u_int    co;
556     register u_int    ro;
557     register u_int    fw;
558     register u_int    fh;
559 {
560     int underline = cci->underline;
561     while (underline--) {
562 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
563 	     "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
564 	p += ro;
565     }
566 
567     asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
568 	 "d" (~expbits(*f++)), "a" (p), "d" (co), "d" (fw));
569     p += ro;
570 
571     underline = fh - cci->underline - 1;
572     while (underline--) {
573 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
574 	     "d" (~(*f++)), "a" (p), "d" (co), "d" (fw));
575 	p += ro;
576     }
577 }
578 
579 /* bold */
580 static void
581 putc_bd (cci,p,f,co,ro,fw,fh)
582     register ipriv_t *cci;
583     register u_char  *p;
584     register u_char  *f;
585     register u_int    co;
586     register u_int    ro;
587     register u_int    fw;
588     register u_int    fh;
589 {
590     u_short ch;
591 
592     while (fh--) {
593 	ch = *f++;
594 	ch |= ch << 1;
595 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
596 	     "d" (ch), "a" (p), "d" (co), "d" (fw+1));
597 	p += ro;
598     }
599 }
600 
601 static void
602 putc_bd_in (cci,p,f,co,ro,fw,fh)
603     register ipriv_t *cci;
604     register u_char  *p;
605     register u_char  *f;
606     register u_int    co;
607     register u_int    ro;
608     register u_int    fw;
609     register u_int    fh;
610 {
611     u_short ch;
612 
613     while (fh--) {
614 	ch = *f++;
615 	ch |= ch << 1;
616 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
617 	     "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
618 	p += ro;
619     }
620 }
621 
622 
623 static void
624 putc_bd_ul (cci,p,f,co,ro,fw,fh)
625     register ipriv_t *cci;
626     register u_char  *p;
627     register u_char  *f;
628     register u_int    co;
629     register u_int    ro;
630     register u_int    fw;
631     register u_int    fh;
632 {
633     int underline = cci->underline;
634     u_short ch;
635 
636     while (underline--) {
637 	ch = *f++;
638 	ch |= ch << 1;
639 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
640 	     "d" (ch), "a" (p), "d" (co), "d" (fw+1));
641 	p += ro;
642     }
643 
644     ch = *f++;
645     ch |= ch << 1;
646     asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
647 	 "d" (expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
648     p += ro;
649 
650     underline = fh - cci->underline - 1;
651     while (underline--) {
652 	ch = *f++;
653 	ch |= ch << 1;
654 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
655 	     "d" (ch), "a" (p), "d" (co), "d" (fw+1));
656 	p += ro;
657     }
658 }
659 
660 
661 static void
662 putc_bd_ul_in (cci,p,f,co,ro,fw,fh)
663     register ipriv_t *cci;
664     register u_char  *p;
665     register u_char  *f;
666     register u_int    co;
667     register u_int    ro;
668     register u_int    fw;
669     register u_int    fh;
670 {
671     int underline = cci->underline;
672     u_short ch;
673 
674     while (underline--) {
675 	ch = *f++;
676 	ch |= ch << 1;
677 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
678 	     "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
679 	p += ro;
680     }
681 
682     ch = *f++;
683     ch |= ch << 1;
684     asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
685 	 "d" (~expbits(ch)), "a" (p), "d" (co), "d" (fw+1));
686     p += ro;
687 
688     underline = fh - cci->underline - 1;
689     while (underline--) {
690 	ch = *f++;
691 	ch |= ch << 1;
692 	asm ("bfins %0,%1@{%2:%3}" : /* no output */ :
693 	     "d" (~(ch)), "a" (p), "d" (co), "d" (fw+1));
694 	p += ro;
695     }
696 }
697 
698 
699 typedef void cc_putc_func ();
700 
701 cc_putc_func *put_func[ATTR_ALL+1] = {
702     putc_nm,
703     putc_in,
704     putc_ul,
705     putc_ul_in,
706     putc_bd,
707     putc_bd_in,
708     putc_bd_ul,
709     putc_bd_ul_in,
710 /* no support for blink */
711     putc_nm,
712     putc_in,
713     putc_ul,
714     putc_ul_in,
715     putc_bd,
716     putc_bd_in,
717     putc_bd_ul,
718     putc_bd_ul_in
719 };
720 
721 
722 /* FIX: shouldn't this advance the cursor even if the character to
723         be output is not available in the font? -ch */
724 
725 static void
726 putc8(struct ite_softc *ip, int c, int dy, int dx, int mode)
727 {
728     register ipriv_t *cci = (ipriv_t *) ip->priv;
729     if (c < ip->font_lo || c > ip->font_hi)
730 	return;
731 
732     put_func[mode](cci,
733 		   cci->row_ptr[dy],
734 		   cci->font_cell[c],
735 		   cci->column_offset[dx],
736 		   cci->row_offset,
737 		   cci->ft_x,
738 		   cci->ft_y);
739 }
740 
741 static void
742 clear8(struct ite_softc *ip, int sy, int sx, int h, int w)
743 {
744   ipriv_t *cci = (ipriv_t *) ip->priv;
745   view_t *v = cci->view;
746   bmap_t *bm = cci->view->bitmap;
747 
748   if ((sx == 0) && (w == ip->cols))
749     {
750       /* common case: clearing whole lines */
751       while (h--)
752 	{
753 	  int i;
754 	  u_char *ptr = cci->row_ptr[sy];
755 	  for (i=0; i < ip->ftheight; i++) {
756             bzero(ptr, bm->bytes_per_row);
757             ptr += bm->bytes_per_row + bm->row_mod;			/* don't get any smart
758                                                    ideas, becuase this is for
759                                                    interleaved bitmaps */
760           }
761 	  sy++;
762 	}
763     }
764   else
765     {
766       /* clearing only part of a line */
767       /* XXX could be optimized MUCH better, but is it worth the trouble? */
768       while (h--)
769 	{
770 	  u_char *pl = cci->row_ptr[sy];
771           int ofs = sx * ip->ftwidth;
772 	  int i, j;
773 	  for (i = w-1; i >= 0; i--)
774 	    {
775 	      u_char *ppl = pl;
776               for (j = ip->ftheight-1; j >= 0; j--)
777 	        {
778 	          asm("bfclr %0@{%1:%2}"
779 	              : : "a" (ppl), "d" (ofs), "d" (ip->ftwidth));
780 	          ppl += bm->row_mod + bm->bytes_per_row;
781 	        }
782 	      ofs += ip->ftwidth;
783 	    }
784 	  sy++;
785 	}
786     }
787 }
788 
789 /* Note: sx is only relevant for SCROLL_LEFT or SCROLL_RIGHT.  */
790 static void
791 scroll8(ip, sy, sx, count, dir)
792         register struct ite_softc *ip;
793         register int sy;
794         int dir, sx, count;
795 {
796   bmap_t *bm = ((ipriv_t *)ip->priv)->view->bitmap;
797   u_char *pl = ((ipriv_t *)ip->priv)->row_ptr[sy];
798 
799   if (dir == SCROLL_UP)
800     {
801       int dy = sy - count;
802       int height = ip->bottom_margin - sy + 1;
803       int i;
804 
805       /*FIX: add scroll bitmap call */
806         cursor32(ip, ERASE_CURSOR);
807 	scrollbmap (bm, 0, dy*ip->ftheight,
808 		       bm->bytes_per_row >> 3, (ip->bottom_margin-dy+1)*ip->ftheight,
809 		       0, -(count*ip->ftheight), 0x1);
810 /*	if (ip->cursory <= bot || ip->cursory >= dy) {
811 	    ip->cursory -= count;
812 	} */
813     }
814   else if (dir == SCROLL_DOWN)
815     {
816       int dy = sy + count;
817       int height = ip->bottom_margin - dy + 1;
818       int i;
819 
820       /* FIX: add scroll bitmap call */
821         cursor32(ip, ERASE_CURSOR);
822 	scrollbmap (bm, 0, sy*ip->ftheight,
823 		       bm->bytes_per_row >> 3, (ip->bottom_margin-sy+1)*ip->ftheight,
824 		       0, count*ip->ftheight, 0x1);
825 /*	if (ip->cursory <= bot || ip->cursory >= sy) {
826 	    ip->cursory += count;
827 	} */
828     }
829   else if (dir == SCROLL_RIGHT)
830     {
831       int sofs = (ip->cols - count) * ip->ftwidth;
832       int dofs = (ip->cols) * ip->ftwidth;
833       int i, j;
834 
835       cursor32(ip, ERASE_CURSOR);
836       for (j = ip->ftheight-1; j >= 0; j--)
837 	{
838 	  int sofs2 = sofs, dofs2 = dofs;
839 	  for (i = (ip->cols - (sx + count))-1; i >= 0; i--)
840 	    {
841 	      int t;
842 	      sofs2 -= ip->ftwidth;
843 	      dofs2 -= ip->ftwidth;
844 	      asm("bfextu %1@{%2:%3},%0"
845 	          : "=d" (t)
846 		  : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
847 	      asm("bfins %3,%0@{%1:%2}"
848 	          : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
849 	    }
850 	  pl += bm->row_mod + bm->bytes_per_row;
851 	}
852     }
853   else /* SCROLL_LEFT */
854     {
855       int sofs = (sx) * ip->ftwidth;
856       int dofs = (sx - count) * ip->ftwidth;
857       int i, j;
858 
859       cursor32(ip, ERASE_CURSOR);
860       for (j = ip->ftheight-1; j >= 0; j--)
861 	{
862 	  int sofs2 = sofs, dofs2 = dofs;
863 	  for (i = (ip->cols - sx)-1; i >= 0; i--)
864 	    {
865 	      int t;
866 	      asm("bfextu %1@{%2:%3},%0"
867 	          : "=d" (t)
868 		  : "a" (pl), "d" (sofs2), "d" (ip->ftwidth));
869 	      asm("bfins %3,%0@{%1:%2}"
870 	          : : "a" (pl), "d" (dofs2), "d" (ip->ftwidth), "d" (t));
871 	      sofs2 += ip->ftwidth;
872 	      dofs2 += ip->ftwidth;
873 	    }
874 	  pl += bm->row_mod + bm->bytes_per_row;
875 	}
876     }
877 }
878 
879 void
880 scrollbmap (bmap_t *bm, u_short x, u_short y, u_short width, u_short height, short dx, short dy, u_char mask)
881 {
882     u_short depth = bm->depth;
883     u_short lwpr = bm->bytes_per_row >> 2;
884     if (dx) {
885     	/* FIX: */ panic ("delta x not supported in scroll bitmap yet.");
886     }
887     if (bm->flags & BMF_INTERLEAVED) {
888 	height *= depth;
889 	depth = 1;
890     }
891     if (dy == 0) {
892         return;
893     }
894     if (dy > 0) {
895     	int i;
896     	for (i=0; i < depth && mask; i++, mask >>= 1) {
897     	    if (0x1 & mask) {
898 	    	u_long *pl = (u_long *)bm->plane[i];
899 		u_long *src_y = pl + (lwpr*y);
900 		u_long *dest_y = pl + (lwpr*(y+dy));
901 		u_long count = lwpr*(height-dy);
902 		u_long *clr_y = src_y;
903 		u_long clr_count = dest_y - src_y;
904 		u_long bc, cbc;
905 
906 		src_y += count - 1;
907 		dest_y += count - 1;
908 
909 		bc = count >> 4;
910 		count &= 0xf;
911 
912 		while (bc--) {
913 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
914 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
915 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
916 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
917 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
918 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
919 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
920 		    *dest_y-- = *src_y--; *dest_y-- = *src_y--;
921 		}
922 		while (count--) {
923 		    *dest_y-- = *src_y--;
924 		}
925 
926 		cbc = clr_count >> 4;
927 		clr_count &= 0xf;
928 
929 		while (cbc--) {
930 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
931 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
932 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
933 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
934 		}
935 		while (clr_count--) {
936 		    *clr_y++ = 0;
937 		}
938     	    }
939 	}
940     } else if (dy < 0) {
941     	int i;
942     	for (i=0; i < depth && mask; i++, mask >>= 1) {
943     	    if (0x1 & mask) {
944     		u_long *pl = (u_long *)bm->plane[i];
945     		u_long *src_y = pl + (lwpr*(y-dy));
946     		u_long *dest_y = pl + (lwpr*y);
947 		long count = lwpr*(height + dy);
948 		u_long *clr_y = dest_y + count;
949 		u_long clr_count = src_y - dest_y;
950 		u_long bc, cbc;
951 
952 		bc = count >> 4;
953 		count &= 0xf;
954 
955 		while (bc--) {
956 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
957 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
958 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
959 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
960 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
961 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
962 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
963 		    *dest_y++ = *src_y++; *dest_y++ = *src_y++;
964 		}
965 		while (count--) {
966 		    *dest_y++ = *src_y++;
967 		}
968 
969 		cbc = clr_count >> 4;
970 		clr_count &= 0xf;
971 
972 		while (cbc--) {
973 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
974 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
975 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
976 		    *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0; *clr_y++ = 0;
977 		}
978 		while (clr_count--) {
979 		    *clr_y++ = 0;
980 		}
981 	    }
982 	}
983     }
984 }
985