Home | History | Annotate | Line # | Download | only in dev
amidisplaycc.c revision 1.1
      1 /*-
      2  * Copyright (c) 2000 Jukka Andberg.
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. The name of the author may not be used to endorse or promote products
     14  *    derived from this software without specific prior written permission
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  */
     27 
     28 /*
     29  * wscons interface to amiga custom chips. Contains the necessary functions
     30  * to render text on bitmapped screens. Uses the functions defined in
     31  * grfabs_reg.h for display creation/destruction and low level setup.
     32  */
     33 
     34 #include "amidisplaycc.h"
     35 #include "grfcc.h"
     36 #include "view.h"
     37 
     38 #if NAMIDISPLAYCC>0
     39 
     40 #include <sys/param.h>
     41 #include <sys/types.h>
     42 #include <sys/device.h>
     43 #include <sys/malloc.h>
     44 #include <sys/systm.h>
     45 
     46 #include <sys/conf.h>
     47 
     48 #include <amiga/dev/grfabs_reg.h>
     49 #include <amiga/dev/viewioctl.h>
     50 #include <amiga/amiga/device.h>
     51 #include <dev/wscons/wsconsio.h>
     52 #include <dev/rcons/raster.h>
     53 #include <dev/wscons/wscons_raster.h>
     54 #include <dev/wscons/wsdisplayvar.h>
     55 #include <dev/cons.h>
     56 
     57 struct amidisplaycc_softc
     58 {
     59 	struct device dev;
     60 };
     61 
     62 
     63 /*
     64  * Configuration stuff.
     65  */
     66 
     67 static int  amidisplaycc_match  __P((struct device *,
     68 				     struct cfdata *,
     69 				     void *));
     70 static void amidisplaycc_attach __P((struct device *,
     71 				     struct device *,
     72 				     void *));
     73 
     74 struct cfattach amidisplaycc_ca = {
     75 	sizeof(struct amidisplaycc_softc),
     76 	amidisplaycc_match,
     77 	amidisplaycc_attach
     78 };
     79 
     80 cons_decl(amidisplaycc_);
     81 
     82 /* end of configuration stuff */
     83 
     84 /* These can be lowered if you are sure you dont need that much colors. */
     85 #define MAXDEPTH 8
     86 #define MAXCOLORS (1<<MAXDEPTH)
     87 #define MAXROWS 128
     88 
     89 /* Perform validity checking on parameters on some functions? */
     90 #define PARANOIA
     91 
     92 #define ADJUSTCOLORS
     93 
     94 /* emulops for wscons */
     95 void amidisplaycc_cursor       __P(( void *, int, int, int         ));
     96 int  amidisplaycc_mapchar      __P(( void *, int, unsigned int *   ));
     97 void amidisplaycc_putchar      __P(( void *, int, int, u_int, long ));
     98 void amidisplaycc_copycols     __P(( void *, int, int, int, int    ));
     99 void amidisplaycc_erasecols    __P(( void *, int, int, int, long   ));
    100 void amidisplaycc_copyrows     __P(( void *, int, int, int         ));
    101 void amidisplaycc_eraserows    __P(( void *, int, int, long        ));
    102 int  amidisplaycc_alloc_attr   __P(( void *, int, int, int, long * ));
    103 /* end of emulops for wscons */
    104 
    105 /* accessops for wscons */
    106 int      amidisplaycc_ioctl        __P(( void *, u_long, caddr_t,
    107 					 int, struct proc *              ));
    108 paddr_t  amidisplaycc_mmap         __P(( void *, off_t, int              ));
    109 int      amidisplaycc_alloc_screen __P(( void *,
    110 					 const struct wsscreen_descr *,
    111 					 void **, int *, int *, long *   ));
    112 
    113 void     amidisplaycc_free_screen  __P(( void *, void *                  ));
    114 int      amidisplaycc_show_screen  __P(( void *, void *, int,
    115 					 void (*) (void *, int, int),
    116 					 void *                          ));
    117 int      amidisplaycc_load_font    __P(( void *, void *,
    118 					 struct wsdisplay_font *         ));
    119 /* end of accessops for wscons */
    120 
    121 /*
    122  * These structures are passed to wscons, and they contain the
    123  * display-specific callback functions.
    124  */
    125 
    126 const struct wsdisplay_accessops amidisplaycc_accessops = {
    127 	amidisplaycc_ioctl,
    128 	amidisplaycc_mmap,
    129 	amidisplaycc_alloc_screen,
    130 	amidisplaycc_free_screen,
    131 	amidisplaycc_show_screen,
    132 	amidisplaycc_load_font
    133 };
    134 
    135 const struct wsdisplay_emulops amidisplaycc_emulops = {
    136 	amidisplaycc_cursor,
    137 	amidisplaycc_mapchar,
    138 	amidisplaycc_putchar,
    139 	amidisplaycc_copycols,
    140 	amidisplaycc_erasecols,
    141 	amidisplaycc_copyrows,
    142 	amidisplaycc_eraserows,
    143 	amidisplaycc_alloc_attr
    144 };
    145 
    146 /* add some of our own data to the wsscreen_descr */
    147 struct amidisplaycc_screen_descr {
    148 	struct wsscreen_descr wsdescr;
    149 	int depth;
    150 };
    151 
    152 /*
    153  * List of supported screenmodes. Almost anything can be given here.
    154  */
    155 
    156 #define ADCC_SCREEN(width,height,depth) { {#width "x" #height "x" #depth, width/8, height/8, &amidisplaycc_emulops, 8, 8, WSSCREEN_WSCOLORS|WSSCREEN_REVERSE|WSSCREEN_HILIT|WSSCREEN_UNDERLINE},depth }
    157 
    158 struct amidisplaycc_screen_descr amidisplaycc_screentab[] = {
    159 	ADCC_SCREEN(640,400,1),
    160 	ADCC_SCREEN(640,400,2),
    161 	ADCC_SCREEN(640,400,3),
    162 	ADCC_SCREEN(640,400,4),
    163 
    164 	ADCC_SCREEN(640,200,1),
    165 	ADCC_SCREEN(640,200,2),
    166 	ADCC_SCREEN(640,200,3),
    167 	ADCC_SCREEN(640,200,4),
    168 
    169 	ADCC_SCREEN(640,480,1),
    170 	ADCC_SCREEN(640,480,2),
    171 	ADCC_SCREEN(640,480,3),
    172 	ADCC_SCREEN(640,480,4),
    173 };
    174 
    175 #define ADCC_SCREENPTR(index) &amidisplaycc_screentab[index].wsdescr
    176 const struct wsscreen_descr *amidisplaycc_screens[] = {
    177 	ADCC_SCREENPTR(0),
    178 	ADCC_SCREENPTR(1),
    179 	ADCC_SCREENPTR(2),
    180 	ADCC_SCREENPTR(3),
    181 	ADCC_SCREENPTR(4),
    182 	ADCC_SCREENPTR(5),
    183 	ADCC_SCREENPTR(6),
    184 	ADCC_SCREENPTR(7),
    185 	ADCC_SCREENPTR(8),
    186 	ADCC_SCREENPTR(9),
    187 	ADCC_SCREENPTR(10),
    188 	ADCC_SCREENPTR(11)
    189 };
    190 
    191 /*
    192  * This structure also is passed to wscons. It contains pointers
    193  * to the available display modes.
    194  */
    195 
    196 const struct wsscreen_list amidisplaycc_screenlist = {
    197 	sizeof(amidisplaycc_screens)/sizeof(amidisplaycc_screens[0]),
    198 	amidisplaycc_screens
    199 };
    200 
    201 /*
    202  * Our own screen structure. One will be created for each screen.
    203  */
    204 
    205 struct amidisplaycc_screen
    206 {
    207 	int isconsole;
    208 	int isvisible;
    209 	view_t *view;
    210 
    211 	int ncols;
    212 	int nrows;
    213 
    214 	/*
    215 	 * For each row store which bitplanes contain
    216 	 * data (just optimisation)
    217 	 */
    218 	int rowmasks[MAXROWS];
    219 
    220 	/* Mapping of colors to screen colors. Currently mostly unused. */
    221 	int colormap[MAXCOLORS];
    222 
    223 	int fontheight;
    224 };
    225 
    226 typedef struct amidisplaycc_screen adccscr_t;
    227 
    228 /*
    229  * Need one statically allocated screen for early init.
    230  * The rest are mallocated when needed.
    231  */
    232 adccscr_t amidisplaycc_consolescreen;
    233 
    234 
    235 /*
    236  * This gets called at console init to determine the priority of
    237  * this console device.
    238  *
    239  * Of course pointers to this and other functions must present
    240  * in constab[] in conf.c for this to work.
    241  */
    242 void
    243 amidisplaycc_cnprobe(cd)
    244 	struct consdev *cd;
    245 {
    246 	cd->cn_pri = CN_INTERNAL;
    247 
    248 	/*
    249 	 * Yeah, real nice. But if we win the console then the wscons system
    250 	 * does the proper initialization.
    251 	 */
    252 	cd->cn_dev = NODEV;
    253 }
    254 
    255 /*
    256  * This gets called if this device is used as the console.
    257  */
    258 void
    259 amidisplaycc_cninit(cd)
    260 	struct consdev *cd;
    261 {
    262 	int x,y;
    263 	void *cookie;
    264 	long attr;
    265 
    266 	/* Yeah, we got the console! */
    267 
    268 	/*
    269 	 * This will do the basic stuff we also need.
    270 	 */
    271 	config_console();
    272 
    273 	/*
    274 	 * Call the init function in grfabs.c if we have
    275 	 * no grfcc to do it.
    276 	 * If grfcc is present it will call grfcc_probe()
    277 	 * during config_console() above.
    278 	 */
    279 #if NGRFCC==0
    280 	grfcc_probe();
    281 #endif
    282 
    283 #if NVIEW>0
    284 	viewprobe();
    285 #endif
    286 
    287 	/*
    288 	 * Set up wscons to handle the details.
    289 	 * It will then call us back when it needs something
    290 	 * display-specific. It will also set up cn_tab properly,
    291 	 * something which we failed to do at amidisplaycc_cnprobe().
    292 	 */
    293 
    294 	amidisplaycc_alloc_screen(NULL, &amidisplaycc_screentab[0].wsdescr,
    295 				  &cookie, &x, &y, &attr);
    296 	wsdisplay_cnattach(&amidisplaycc_screentab[0].wsdescr,
    297 			   cookie, x, y, attr);
    298 }
    299 
    300 int
    301 amidisplaycc_match(pdp,cfp,auxp)
    302 	struct device *pdp;
    303 	struct cfdata *cfp;
    304 	void *auxp;
    305 {
    306 	char *name = auxp;
    307 
    308 	if (matchname("amidisplaycc",name)==0)
    309 		return (0);
    310 
    311 	/* Allow only one of us now. Not sure about that. */
    312 	if (cfp->cf_unit != 0)
    313 		return (0);
    314 
    315 	return 1;
    316 }
    317 
    318 void
    319 amidisplaycc_attach(pdp,dp,auxp)
    320 	struct device *pdp;
    321 	struct device *dp;
    322 	void *auxp;
    323 {
    324 	struct wsemuldisplaydev_attach_args waa;
    325 
    326 	/*
    327 	 * Attach only at real configuration time. Console init is done at
    328 	 * the amidisplaycc_cninit function above.
    329 	 */
    330 	if (dp) {
    331 		printf("\n");
    332 
    333 		waa.console = 1;
    334 		waa.scrdata = &amidisplaycc_screenlist;
    335 		waa.accessops = &amidisplaycc_accessops;
    336 		waa.accesscookie = NULL;
    337 		config_found(dp,&waa,wsemuldisplaydevprint);
    338 	}
    339 }
    340 
    341 
    342 /*
    343  * Color, bgcolor and style are packed into one long attribute.
    344  * These macros are used to create/split the attribute
    345  */
    346 
    347 #define MAKEATTR(fg, bg, mode) (((fg)<<16) | ((bg)<<8) | (mode))
    348 #define ATTRFG(attr) (((attr)>>16) & 255)
    349 #define ATTRBG(attr) (((attr)>>8) & 255)
    350 #define ATTRMO(attr) ((attr) & 255)
    351 
    352 /*
    353  * Called by wscons to draw/clear the cursor.
    354  * We do this by xorring the block to the screen.
    355  *
    356  * This simple implementation will break if the screen is modified
    357  * under the cursor before clearing it.
    358  */
    359 void
    360 amidisplaycc_cursor(screen, on, row, col)
    361 	void  *screen;
    362 	int    on;
    363 	int    row;
    364 	int    col;
    365 {
    366 	adccscr_t *scr;
    367 	u_char *plane;
    368 	int y;
    369 	int miny;
    370 	int maxy;
    371 
    372 	scr = screen;
    373 
    374 #ifdef PARANOIA
    375 	if (row < 0 || col < 0 || row >= scr->nrows || col >= scr->ncols)
    376 		return;
    377 #endif
    378 
    379 	miny = row * scr->fontheight;
    380 	maxy = miny + scr->fontheight;
    381 
    382 	for (y = miny ; y < maxy ; y++) {
    383 		plane = col + VDISPLAY_LINE(scr->view, 0, y);
    384 		*plane ^= 255;
    385 	}
    386 
    387 }
    388 
    389 /*
    390  * This obviously does something important, don't ask me what.
    391  */
    392 int
    393 amidisplaycc_mapchar(screen, ch, chp)
    394 	void  *screen;
    395 	int    ch;
    396 	unsigned int *chp;
    397 {
    398 	if (ch > 0 && ch < 256) {
    399 		*chp = ch;
    400 		return (5);
    401 	}
    402 	*chp = ' ';
    403 	return (0);
    404 }
    405 
    406 extern unsigned char kernel_font_8x8[];
    407 
    408 /* Write a character to screen with color / bgcolor / hilite(bold) /
    409  * underline / inverse.
    410  * Surely could be made faster but I'm not sure if its worth the
    411  * effort as scrolling is at least a magnitude slower.
    412  */
    413 void
    414 amidisplaycc_putchar(screen, row, col, ch, attr)
    415 	void  *screen;
    416 	int    row;
    417 	int    col;
    418 	u_int  ch;
    419 	long   attr;
    420 {
    421 	bmap_t *bitmap;
    422 	u_char *dst;
    423 	adccscr_t *scr;
    424 	u_char *font;
    425 	u_char f;
    426 	int j;
    427 	int fgcolor;
    428 	int bgcolor;
    429 	int plane;
    430 	int depth;
    431 	int rowsize;
    432 	int fontoffset;
    433 	int bmapoffset;
    434 	int mode;
    435 	int bold;
    436 	int underline;
    437 
    438 	scr = screen;
    439 
    440 #ifdef PARANOIA
    441 	if (row < 0 || col < 0 || row >= scr->nrows || col >= scr->ncols)
    442 		return;
    443 #endif
    444 
    445 	bitmap = scr->view->bitmap;
    446 	depth = bitmap->depth;
    447 	rowsize = bitmap->bytes_per_row + bitmap->row_mod;
    448 
    449 	/* Extract the colors from the attribute */
    450 	fgcolor = ATTRFG(attr);
    451 	bgcolor = ATTRBG(attr);
    452 	mode = ATTRMO(attr);
    453 
    454 	/* Translate to screen colors */
    455 	fgcolor = scr->colormap[fgcolor];
    456 	bgcolor = scr->colormap[bgcolor];
    457 
    458 	if(mode & WSATTR_REVERSE) {
    459 		j = fgcolor;
    460 		fgcolor = bgcolor;
    461 		bgcolor = j;
    462 	}
    463 
    464 	if (mode & WSATTR_HILIT)
    465 		bold = 1;
    466 	else
    467 		bold = 0;
    468 
    469 
    470 	if (mode & WSATTR_UNDERLINE)
    471 		underline = 1;
    472 	else
    473 		underline = 0;
    474 
    475 
    476 	if (ch < 32)
    477 		ch = 32;
    478 	if (ch > 255)
    479 		ch = 255;
    480 
    481 
    482 	fontoffset = scr->fontheight * (ch - 32);
    483 	bmapoffset = row * scr->fontheight * rowsize + col;
    484 
    485 	scr->rowmasks[row] |= fgcolor | bgcolor;
    486 
    487 	for (plane = 0 ; plane < depth ; plane++) {
    488 		dst = bitmap->plane[plane] + bmapoffset;
    489 
    490 		if (fgcolor & 1) {
    491 			if (bgcolor & 1) {
    492 				/* fg=on bg=on (fill) */
    493 
    494 				for (j = 0 ; j < scr->fontheight ; j++)
    495 				{
    496 					*dst = 255;
    497 					dst += rowsize;
    498 				}
    499 			} else {
    500 				/* fg=on bg=off (normal) */
    501 
    502 				font = &kernel_font_8x8[fontoffset];
    503 				for (j = 0 ; j < scr->fontheight ; j++)
    504 				{
    505 					f = *(font++);
    506 					f |= f>>bold;
    507 					*dst = f;
    508 					dst += rowsize;
    509 				}
    510 
    511 				/* XXX underline does not recognise baseline */
    512 				if (underline)
    513 					*(dst-rowsize) = 255;
    514 			}
    515 		} else {
    516 			if (bgcolor & 1) {
    517 				/* fg=off bg=on (inverted) */
    518 
    519 				font = &kernel_font_8x8[fontoffset];
    520 				for (j = 0 ; j < scr->fontheight ; j++) {
    521 					f = *(font++);
    522 					f |= f>>bold;
    523 					*dst = ~f;
    524 					dst += rowsize;
    525 				}
    526 
    527 				/* XXX underline does not recognise baseline */
    528 				if (underline)
    529 					*(dst-rowsize) = 0;
    530 			} else {
    531 				/* fg=off bg=off (clear) */
    532 
    533 				for (j = 0 ; j < scr->fontheight ; j++) {
    534 					*dst = 0;
    535 					dst += rowsize;
    536 				}
    537 			}
    538 		}
    539 		fgcolor >>= 1;
    540 		bgcolor >>= 1;
    541 	}
    542 }
    543 
    544 
    545 void
    546 amidisplaycc_copycols(screen, row, srccol, dstcol, ncols)
    547 	void  *screen;
    548 	int    row;
    549 	int    srccol;
    550 	int    dstcol;
    551 	int    ncols;
    552 {
    553 	bmap_t *bitmap;
    554 	adccscr_t *scr;
    555 	int depth;
    556 	int i;
    557 	int j;
    558 	int plane;
    559 	int rowsize;
    560 	u_char *buf;
    561 
    562 	scr = screen;
    563 
    564 #ifdef PARANOIA
    565 	if (srccol < 0 || srccol + ncols > scr->ncols ||
    566 	    dstcol < 0 || dstcol + ncols > scr->ncols ||
    567 	    row < 0 || row >= scr->nrows)
    568 		return;
    569 #endif
    570 
    571 	bitmap = scr->view->bitmap;
    572 	depth = bitmap->depth;
    573 	rowsize = bitmap->bytes_per_row + bitmap->row_mod;
    574 
    575 	for (plane = 0 ; plane < depth ; plane++) {
    576 		buf = bitmap->plane[plane] + row*scr->fontheight*rowsize;
    577 
    578 		for (j = 0 ; j < scr->fontheight ; j++) {
    579 
    580 			if (srccol < dstcol) {
    581 
    582 				for (i = ncols - 1 ; i >= 0 ; i--)
    583 					buf[dstcol + i] = buf[srccol + i];
    584 
    585 			} else {
    586 
    587 				for (i = 0 ; i < ncols ; i++)
    588 					buf[dstcol + i] = buf[srccol + i];
    589 
    590 			}
    591 			buf += rowsize;
    592 		}
    593 	}
    594 }
    595 
    596 void
    597 amidisplaycc_erasecols(screen, row, startcol, ncols, attr)
    598 	void  *screen;
    599 	int    row;
    600 	int    startcol;
    601 	int    ncols;
    602 	long   attr;
    603 {
    604 	bmap_t *bitmap;
    605 	adccscr_t *scr;
    606 	u_char *buf;
    607 	int depth;
    608 	int j;
    609 	int plane;
    610 	int rowsize;
    611 	int fill;
    612 	int bgcolor;
    613 
    614 	scr = screen;
    615 
    616 #ifdef PARANOIA
    617 	if (row < 0 || row >= scr->nrows ||
    618 	    startcol < 0 || startcol + ncols > scr->ncols)
    619 		return;
    620 #endif
    621 
    622 	bitmap = scr->view->bitmap;
    623 	depth = bitmap->depth;
    624 	rowsize = bitmap->bytes_per_row + bitmap->row_mod;
    625 
    626 	bgcolor = ATTRBG(attr);
    627 	bgcolor = scr->colormap[bgcolor];
    628 
    629 	for(plane = 0 ; plane < depth ; plane++) {
    630 
    631 		fill = (bgcolor & 1) ? 255 : 0;
    632 
    633 		buf = bitmap->plane[plane];
    634 		buf += row * scr->fontheight * rowsize;
    635 		buf += startcol;
    636 
    637 		for (j = 0 ; j < scr->fontheight ; j++)
    638 		{
    639 			memset(buf, fill, ncols);
    640 			buf += rowsize;
    641 		}
    642 	}
    643 }
    644 
    645 void
    646 amidisplaycc_copyrows(screen, srcrow, dstrow, nrows)
    647 	void  *screen;
    648 	int    srcrow;
    649 	int    dstrow;
    650 	int    nrows;
    651 {
    652 	bmap_t *bitmap;
    653 	adccscr_t *scr;
    654 	u_char *src;
    655 	u_char *dst;
    656 
    657 	int depth;
    658 	int plane;
    659 	int i;
    660 	int j;
    661 	int rowmod;
    662 	int bytesperrow;
    663 	int rowsize;
    664 	int srcmask;
    665 	int dstmask;
    666 	int srcbmapoffset;
    667 	int dstbmapoffset;
    668 	int copysize;
    669 	int bmdelta;
    670 	int rowdelta;
    671 	int bmwidth;
    672 
    673 	scr = screen;
    674 
    675 #ifdef PARANOIA
    676 	if (srcrow < 0 || srcrow + nrows > scr->nrows ||
    677 	    dstrow < 0 || dstrow + nrows > scr->nrows)
    678 		return;
    679 #endif
    680 
    681 	bitmap = scr->view->bitmap;
    682 	depth = bitmap->depth;
    683 	rowmod = bitmap->row_mod;
    684 	bytesperrow = bitmap->bytes_per_row;
    685 	bmwidth = bytesperrow+rowmod;
    686 	rowsize = bmwidth*scr->fontheight;
    687 
    688 	srcbmapoffset = rowsize*srcrow;
    689 	dstbmapoffset = rowsize*dstrow;
    690 
    691 	if (srcrow < dstrow) {
    692 		/* Move data downwards, need to copy from down to up */
    693 		bmdelta = -rowsize;
    694 		rowdelta = -1;
    695 
    696 		srcbmapoffset += rowsize * (nrows - 1);
    697 		srcrow += nrows - 1;
    698 
    699 		dstbmapoffset += rowsize * (nrows - 1);
    700 		dstrow += nrows - 1;
    701 	} else {
    702 		/* Move data upwards, copy up to down */
    703 		bmdelta = rowsize;
    704 		rowdelta = 1;
    705 	}
    706 
    707 	if (rowmod == 0)
    708 		copysize = rowsize;
    709 	else
    710 		copysize = 0;
    711 
    712 	for (j = 0 ; j < nrows ; j++)    {
    713 		/* Need to copy only planes that have data on src or dst */
    714 		srcmask = scr->rowmasks[srcrow];
    715 		dstmask = scr->rowmasks[dstrow];
    716 		scr->rowmasks[dstrow] = srcmask;
    717 
    718 		for (plane = 0 ; plane < depth ; plane++) {
    719 
    720 			if (srcmask & 1) {
    721 				/*
    722 				 * Source row has data on this
    723 				 * plane, copy it
    724 				 */
    725 
    726 				src = bitmap->plane[plane] + srcbmapoffset;
    727 				dst = bitmap->plane[plane] + dstbmapoffset;
    728 
    729 				if (copysize > 0) {
    730 
    731 					/* Do it all */
    732 					memcpy(dst,src,copysize);
    733 
    734 				} else {
    735 
    736 					/*
    737 					 * Data not continuous,
    738 					 * must do in pieces
    739 					 */
    740 					for (i=0 ; i < scr->fontheight ; i++) {
    741 						memcpy(dst, src, bytesperrow);
    742 
    743 						src += bmwidth;
    744 						dst += bmwidth;
    745 					}
    746 				}
    747 			} else if (dstmask & 1) {
    748 				/*
    749 				 * Source plane is empty, but dest is not.
    750 				 * so all we need to is clear it.
    751 				 */
    752 
    753 				dst = bitmap->plane[plane] + dstbmapoffset;
    754 
    755 				if (copysize > 0) {
    756 					/* Do it all */
    757 					bzero(dst, copysize);
    758 				} else {
    759 					for (i = 0 ;
    760 					     i < scr->fontheight ; i++) {
    761 						bzero(dst, bytesperrow);
    762 						dst += bmwidth;
    763 					}
    764 				}
    765 			}
    766 
    767 			srcmask >>= 1;
    768 			dstmask >>= 1;
    769 		}
    770 		srcbmapoffset += bmdelta;
    771 		dstbmapoffset += bmdelta;
    772 
    773 		srcrow += rowdelta;
    774 		dstrow += rowdelta;
    775 	}
    776 }
    777 
    778 void
    779 amidisplaycc_eraserows(screen, row, nrows, attr)
    780 	void  *screen;
    781 	int    row;
    782 	int    nrows;
    783 	long   attr;
    784 {
    785 	bmap_t *bitmap;
    786 	adccscr_t *scr;
    787 	int depth;
    788 	int plane;
    789 	int j;
    790 	int bytesperrow;
    791 	int rowmod;
    792 	int rowsize;
    793 	int bmwidth;
    794 	int bgcolor;
    795 	int fill;
    796 	int bmapoffset;
    797 	int fillsize;
    798 	u_char *dst;
    799 
    800 	scr = screen;
    801 
    802 #ifdef PARANOIA
    803 	if (row < 0 || row + nrows > scr->nrows)
    804 		return;
    805 #endif
    806 
    807 	bitmap = scr->view->bitmap;
    808 	depth = bitmap->depth;
    809 	bytesperrow = bitmap->bytes_per_row;
    810 	rowmod = bitmap->row_mod;
    811 	bmwidth = bytesperrow + rowmod;
    812 	rowsize = bmwidth * scr->fontheight;
    813 	bmapoffset = row * rowsize;
    814 
    815 	if (rowmod == 0)
    816 		fillsize = rowsize * nrows;
    817 	else
    818 		fillsize = 0;
    819 
    820 	bgcolor = ATTRBG(attr);
    821 	bgcolor = scr->colormap[bgcolor];
    822 
    823 	for (j = 0 ; j < nrows ; j++)
    824 		scr->rowmasks[row+j] = bgcolor;
    825 
    826 	for (plane = 0 ; plane < depth ; plane++) {
    827 		dst = bitmap->plane[plane] + bmapoffset;
    828 		fill = (bgcolor & 1) ? 255 : 0;
    829 
    830 		if (fillsize > 0) {
    831 			/* If the rows are continuous, write them all. */
    832 			memset(dst, fill, fillsize);
    833 		} else {
    834 			for (j = 0 ; j < scr->fontheight * nrows ; j++) {
    835 				memset(dst, fill, bytesperrow);
    836 				dst += bmwidth;
    837 			}
    838 		}
    839 		bgcolor >>= 1;
    840 	}
    841 }
    842 
    843 int
    844 amidisplaycc_alloc_attr(screen, fg, bg, flags, attrp)
    845 	void  *screen;
    846 	int    fg;
    847 	int    bg;
    848 	int    flags;
    849 	long  *attrp;
    850 {
    851 	adccscr_t *scr;
    852 	int maxcolor;
    853 	int newfg;
    854 	int newbg;
    855 
    856 	scr = screen;
    857 	maxcolor = (1 << scr->view->bitmap->depth) - 1;
    858 
    859 	/* Ensure the colors are displayable. */
    860 	newfg = fg & maxcolor;
    861 	newbg = bg & maxcolor;
    862 
    863 #ifdef ADJUSTCOLORS
    864 	/*
    865 	 * Hack for low-color screens, if background color is nonzero
    866 	 * but would be displayed as one, adjust it.
    867 	 */
    868 	if (bg > 0 && newbg == 0)
    869 		newbg = maxcolor;
    870 
    871 	/*
    872 	 * If foreground and background colors are different but would
    873 	 * display the same fix them by modifying the foreground.
    874 	 */
    875 	if (fg != bg && newfg == newbg) {
    876 		if (newbg > 0)
    877 			newfg = 0;
    878 		else
    879 			newfg = maxcolor;
    880 	}
    881 #endif
    882 	*attrp = MAKEATTR(newfg, newbg, flags);
    883 
    884 	return (0);
    885 }
    886 
    887 int
    888 amidisplaycc_ioctl(dp, cmd, data, flag, p)
    889 	void         *dp;
    890 	u_long        cmd;
    891 	caddr_t       data;
    892 	int           flag;
    893 	struct proc  *p;
    894 {
    895 	switch (cmd)
    896 	{
    897 	case WSDISPLAYIO_GTYPE:
    898 		*(u_int*)data = WSDISPLAY_TYPE_EGA; /* XXX */
    899 		return (0);
    900 	}
    901 
    902 	printf("amidisplaycc_ioctl %lx (grp:'%c' num:%d)\n",
    903 	       (long)cmd,
    904 	       (char)((cmd&0xff00)>>8),
    905 	       (int)(cmd&0xff));
    906 
    907 	/* Yes, think should return -1 if didnt understand. */
    908 	return (-1);
    909 }
    910 
    911 paddr_t
    912 amidisplaycc_mmap(dp, off, prot)
    913 	void   *dp;
    914 	off_t   off;
    915 	int     prot;
    916 {
    917 	return (-1);
    918 }
    919 
    920 int
    921 amidisplaycc_alloc_screen(dp, screenp, cookiep, curxp, curyp, defattrp)
    922 	void   *dp;
    923 	const struct wsscreen_descr *screenp;
    924 	void  **cookiep;
    925 	int    *curxp;
    926 	int    *curyp;
    927 	long   *defattrp;
    928 {
    929 	dimen_t dimension;
    930 	adccscr_t *scr;
    931 	view_t *view;
    932 	struct amidisplaycc_screen_descr *adccscreenp;
    933 	int depth;
    934 	int maxcolor;
    935 	int i;
    936 	int j;
    937 
    938 	adccscreenp = (struct amidisplaycc_screen_descr*)screenp;
    939 	depth = adccscreenp->depth;
    940 
    941 	maxcolor = (1 << depth) - 1;
    942 
    943 	/* Sanity checks because of fixed buffers */
    944 	if (depth > MAXDEPTH || maxcolor >= MAXCOLORS)
    945 		return (ENOMEM);
    946 	if (screenp->nrows > MAXROWS)
    947 		return (ENOMEM);
    948 
    949 	dimension.width = screenp->ncols * 8;
    950 	dimension.height = screenp->nrows * 8;
    951 
    952 	view = grf_alloc_view(NULL, &dimension, depth);
    953 	if (view == NULL)
    954 		return (ENOMEM);
    955 
    956 	/*
    957 	 * First screen gets the statically allocated console screen.
    958 	 * Others are allocated dynamically.
    959 	 */
    960 	if (amidisplaycc_consolescreen.isconsole == 0) {
    961 		scr = &amidisplaycc_consolescreen;
    962 		scr->isconsole = 1;
    963 	} else {
    964 		scr = malloc(sizeof(adccscr_t), M_DEVBUF, M_WAITOK);
    965 		bzero(scr, sizeof(adccscr_t));
    966 	}
    967 
    968 	scr->view = view;
    969 	scr->fontheight = 8;
    970 
    971 	scr->ncols = screenp->ncols;
    972 	scr->nrows = screenp->nrows;
    973 
    974 	for (i = 0 ; i < MAXROWS ; i++)
    975 		scr->rowmasks[i] = 0;
    976 
    977 	/* Simple one-to-one mapping for most colors */
    978 	for (i = 0 ; i < MAXCOLORS ; i++)
    979 		scr->colormap[i] = i;
    980 
    981 	/*
    982 	 * Arrange the most used pens to quickest colors.
    983 	 * The default color for given depth is (1<<depth)-1.
    984 	 * It is assumed it is used most and it is mapped to
    985 	 * color that can be drawn by writing data to one bitplane
    986 	 * only.
    987 	 * So map colors 3->2, 7->4, 15->8 and so on.
    988 	 * This of course should be reflected on the palette
    989 	 * but currently we don't do any palette management.
    990 	 */
    991 	for (i = 2 ; i < MAXCOLORS ; i *= 2) {
    992 		j = i * 2 - 1;
    993 
    994 		if (j < MAXCOLORS) {
    995 			scr->colormap[i] = j;
    996 			scr->colormap[j] = i;
    997 		}
    998 	}
    999 
   1000 	*cookiep = scr;
   1001 
   1002 	*curxp = 0;
   1003 	*curyp = 0;
   1004 	amidisplaycc_cursor(scr, 1, *curxp, *curyp);
   1005 
   1006 	*defattrp = MAKEATTR(maxcolor, 0, 0);
   1007 
   1008 	/* Show the console automatically */
   1009 	if (scr->isconsole)
   1010 		grf_display_view(scr->view);
   1011 
   1012 	return (0);
   1013 }
   1014 
   1015 void
   1016 amidisplaycc_free_screen(dp, screen)
   1017 	void  *dp;
   1018 	void  *screen;
   1019 {
   1020 	adccscr_t *scr;
   1021 
   1022 	scr = screen;
   1023 
   1024 	if (scr == NULL)
   1025 		return;
   1026 
   1027 	if (scr->view)
   1028 		grf_free_view(scr->view);
   1029 	scr->view = NULL;
   1030 
   1031 	/* Take care not to free the statically allocated console screen */
   1032 	if (scr != &amidisplaycc_consolescreen) {
   1033 		free(scr, M_DEVBUF);
   1034 	}
   1035 }
   1036 
   1037 int
   1038 amidisplaycc_show_screen(dp, screen, waitok, cb, cbarg)
   1039 	void  *dp;
   1040 	void  *screen;
   1041 	int    waitok;
   1042 	void (*cb) (void *, int, int);
   1043 	void  *cbarg;
   1044 {
   1045 	adccscr_t *scr;
   1046 
   1047 	scr = screen;
   1048 	grf_display_view(scr->view);
   1049 
   1050 	return (0);
   1051 }
   1052 
   1053 /*
   1054  * Load a font. Not supported yet.
   1055  */
   1056 int
   1057 amidisplaycc_load_font(dp, cookie, fontp)
   1058 	void  *dp;
   1059 	void  *cookie;
   1060 	struct wsdisplay_font  *fontp;
   1061 {
   1062 	return (-1);
   1063 }
   1064 
   1065 /*
   1066  * These dummy functions are here just so that we can compete of
   1067  * the console at init.
   1068  * If we win the console then the wscons system will provide the
   1069  * real ones which in turn will call the apropriate wskbd device.
   1070  * These should never be called.
   1071  */
   1072 
   1073 void
   1074 amidisplaycc_cnputc(cd,ch)
   1075 	dev_t cd;
   1076 	int ch;
   1077 {
   1078 }
   1079 
   1080 int
   1081 amidisplaycc_cngetc(cd)
   1082 	dev_t cd;
   1083 {
   1084 	return (0);
   1085 }
   1086 
   1087 void
   1088 amidisplaycc_cnpollc(cd,on)
   1089 	dev_t cd;
   1090 	int on;
   1091 {
   1092 }
   1093 
   1094 #endif /* AMIDISPLAYCC */
   1095 
   1096 
   1097 
   1098 
   1099