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