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