Home | History | Annotate | Line # | Download | only in dev
ite_cc.c revision 1.12
      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