xref: /netbsd-src/sys/arch/amiga/dev/amidisplaycc.c (revision 3b01aba77a7a698587faaae455bbfe740923c1f5)
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