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