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