1099 lines
22 KiB
C
1099 lines
22 KiB
C
/*-
|
|
* Copyright (c) 2000 Jukka Andberg.
|
|
* All rights reserved.
|
|
*
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions
|
|
* are met:
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
* documentation and/or other materials provided with the distribution.
|
|
* 3. The name of the author may not be used to endorse or promote products
|
|
* derived from this software without specific prior written permission
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
|
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
|
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
|
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
|
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
|
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
|
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
|
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
/*
|
|
* wscons interface to amiga custom chips. Contains the necessary functions
|
|
* to render text on bitmapped screens. Uses the functions defined in
|
|
* grfabs_reg.h for display creation/destruction and low level setup.
|
|
*/
|
|
|
|
#include "amidisplaycc.h"
|
|
#include "grfcc.h"
|
|
#include "view.h"
|
|
|
|
#if NAMIDISPLAYCC>0
|
|
|
|
#include <sys/param.h>
|
|
#include <sys/types.h>
|
|
#include <sys/device.h>
|
|
#include <sys/malloc.h>
|
|
#include <sys/systm.h>
|
|
|
|
#include <sys/conf.h>
|
|
|
|
#include <amiga/dev/grfabs_reg.h>
|
|
#include <amiga/dev/viewioctl.h>
|
|
#include <amiga/amiga/device.h>
|
|
#include <dev/wscons/wsconsio.h>
|
|
#include <dev/rcons/raster.h>
|
|
#include <dev/wscons/wscons_raster.h>
|
|
#include <dev/wscons/wsdisplayvar.h>
|
|
#include <dev/cons.h>
|
|
|
|
struct amidisplaycc_softc
|
|
{
|
|
struct device dev;
|
|
};
|
|
|
|
|
|
/*
|
|
* Configuration stuff.
|
|
*/
|
|
|
|
static int amidisplaycc_match __P((struct device *,
|
|
struct cfdata *,
|
|
void *));
|
|
static void amidisplaycc_attach __P((struct device *,
|
|
struct device *,
|
|
void *));
|
|
|
|
struct cfattach amidisplaycc_ca = {
|
|
sizeof(struct amidisplaycc_softc),
|
|
amidisplaycc_match,
|
|
amidisplaycc_attach
|
|
};
|
|
|
|
cons_decl(amidisplaycc_);
|
|
|
|
/* end of configuration stuff */
|
|
|
|
/* These can be lowered if you are sure you dont need that much colors. */
|
|
#define MAXDEPTH 8
|
|
#define MAXCOLORS (1<<MAXDEPTH)
|
|
#define MAXROWS 128
|
|
|
|
/* Perform validity checking on parameters on some functions? */
|
|
#define PARANOIA
|
|
|
|
#define ADJUSTCOLORS
|
|
|
|
/* emulops for wscons */
|
|
void amidisplaycc_cursor __P(( void *, int, int, int ));
|
|
int amidisplaycc_mapchar __P(( void *, int, unsigned int * ));
|
|
void amidisplaycc_putchar __P(( void *, int, int, u_int, long ));
|
|
void amidisplaycc_copycols __P(( void *, int, int, int, int ));
|
|
void amidisplaycc_erasecols __P(( void *, int, int, int, long ));
|
|
void amidisplaycc_copyrows __P(( void *, int, int, int ));
|
|
void amidisplaycc_eraserows __P(( void *, int, int, long ));
|
|
int amidisplaycc_alloc_attr __P(( void *, int, int, int, long * ));
|
|
/* end of emulops for wscons */
|
|
|
|
/* accessops for wscons */
|
|
int amidisplaycc_ioctl __P(( void *, u_long, caddr_t,
|
|
int, struct proc * ));
|
|
paddr_t amidisplaycc_mmap __P(( void *, off_t, int ));
|
|
int amidisplaycc_alloc_screen __P(( void *,
|
|
const struct wsscreen_descr *,
|
|
void **, int *, int *, long * ));
|
|
|
|
void amidisplaycc_free_screen __P(( void *, void * ));
|
|
int amidisplaycc_show_screen __P(( void *, void *, int,
|
|
void (*) (void *, int, int),
|
|
void * ));
|
|
int amidisplaycc_load_font __P(( void *, void *,
|
|
struct wsdisplay_font * ));
|
|
/* end of accessops for wscons */
|
|
|
|
/*
|
|
* These structures are passed to wscons, and they contain the
|
|
* display-specific callback functions.
|
|
*/
|
|
|
|
const struct wsdisplay_accessops amidisplaycc_accessops = {
|
|
amidisplaycc_ioctl,
|
|
amidisplaycc_mmap,
|
|
amidisplaycc_alloc_screen,
|
|
amidisplaycc_free_screen,
|
|
amidisplaycc_show_screen,
|
|
amidisplaycc_load_font
|
|
};
|
|
|
|
const struct wsdisplay_emulops amidisplaycc_emulops = {
|
|
amidisplaycc_cursor,
|
|
amidisplaycc_mapchar,
|
|
amidisplaycc_putchar,
|
|
amidisplaycc_copycols,
|
|
amidisplaycc_erasecols,
|
|
amidisplaycc_copyrows,
|
|
amidisplaycc_eraserows,
|
|
amidisplaycc_alloc_attr
|
|
};
|
|
|
|
/* add some of our own data to the wsscreen_descr */
|
|
struct amidisplaycc_screen_descr {
|
|
struct wsscreen_descr wsdescr;
|
|
int depth;
|
|
};
|
|
|
|
/*
|
|
* List of supported screenmodes. Almost anything can be given here.
|
|
*/
|
|
|
|
#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 }
|
|
|
|
struct amidisplaycc_screen_descr amidisplaycc_screentab[] = {
|
|
ADCC_SCREEN(640,400,1),
|
|
ADCC_SCREEN(640,400,2),
|
|
ADCC_SCREEN(640,400,3),
|
|
ADCC_SCREEN(640,400,4),
|
|
|
|
ADCC_SCREEN(640,200,1),
|
|
ADCC_SCREEN(640,200,2),
|
|
ADCC_SCREEN(640,200,3),
|
|
ADCC_SCREEN(640,200,4),
|
|
|
|
ADCC_SCREEN(640,480,1),
|
|
ADCC_SCREEN(640,480,2),
|
|
ADCC_SCREEN(640,480,3),
|
|
ADCC_SCREEN(640,480,4),
|
|
};
|
|
|
|
#define ADCC_SCREENPTR(index) &amidisplaycc_screentab[index].wsdescr
|
|
const struct wsscreen_descr *amidisplaycc_screens[] = {
|
|
ADCC_SCREENPTR(0),
|
|
ADCC_SCREENPTR(1),
|
|
ADCC_SCREENPTR(2),
|
|
ADCC_SCREENPTR(3),
|
|
ADCC_SCREENPTR(4),
|
|
ADCC_SCREENPTR(5),
|
|
ADCC_SCREENPTR(6),
|
|
ADCC_SCREENPTR(7),
|
|
ADCC_SCREENPTR(8),
|
|
ADCC_SCREENPTR(9),
|
|
ADCC_SCREENPTR(10),
|
|
ADCC_SCREENPTR(11)
|
|
};
|
|
|
|
/*
|
|
* This structure also is passed to wscons. It contains pointers
|
|
* to the available display modes.
|
|
*/
|
|
|
|
const struct wsscreen_list amidisplaycc_screenlist = {
|
|
sizeof(amidisplaycc_screens)/sizeof(amidisplaycc_screens[0]),
|
|
amidisplaycc_screens
|
|
};
|
|
|
|
/*
|
|
* Our own screen structure. One will be created for each screen.
|
|
*/
|
|
|
|
struct amidisplaycc_screen
|
|
{
|
|
int isconsole;
|
|
int isvisible;
|
|
view_t *view;
|
|
|
|
int ncols;
|
|
int nrows;
|
|
|
|
/*
|
|
* For each row store which bitplanes contain
|
|
* data (just optimisation)
|
|
*/
|
|
int rowmasks[MAXROWS];
|
|
|
|
/* Mapping of colors to screen colors. Currently mostly unused. */
|
|
int colormap[MAXCOLORS];
|
|
|
|
int fontheight;
|
|
};
|
|
|
|
typedef struct amidisplaycc_screen adccscr_t;
|
|
|
|
/*
|
|
* Need one statically allocated screen for early init.
|
|
* The rest are mallocated when needed.
|
|
*/
|
|
adccscr_t amidisplaycc_consolescreen;
|
|
|
|
|
|
/*
|
|
* This gets called at console init to determine the priority of
|
|
* this console device.
|
|
*
|
|
* Of course pointers to this and other functions must present
|
|
* in constab[] in conf.c for this to work.
|
|
*/
|
|
void
|
|
amidisplaycc_cnprobe(cd)
|
|
struct consdev *cd;
|
|
{
|
|
cd->cn_pri = CN_INTERNAL;
|
|
|
|
/*
|
|
* Yeah, real nice. But if we win the console then the wscons system
|
|
* does the proper initialization.
|
|
*/
|
|
cd->cn_dev = NODEV;
|
|
}
|
|
|
|
/*
|
|
* This gets called if this device is used as the console.
|
|
*/
|
|
void
|
|
amidisplaycc_cninit(cd)
|
|
struct consdev *cd;
|
|
{
|
|
int x,y;
|
|
void *cookie;
|
|
long attr;
|
|
|
|
/* Yeah, we got the console! */
|
|
|
|
/*
|
|
* This will do the basic stuff we also need.
|
|
*/
|
|
config_console();
|
|
|
|
/*
|
|
* Call the init function in grfabs.c if we have
|
|
* no grfcc to do it.
|
|
* If grfcc is present it will call grfcc_probe()
|
|
* during config_console() above.
|
|
*/
|
|
#if NGRFCC==0
|
|
grfcc_probe();
|
|
#endif
|
|
|
|
#if NVIEW>0
|
|
viewprobe();
|
|
#endif
|
|
|
|
/*
|
|
* Set up wscons to handle the details.
|
|
* It will then call us back when it needs something
|
|
* display-specific. It will also set up cn_tab properly,
|
|
* something which we failed to do at amidisplaycc_cnprobe().
|
|
*/
|
|
|
|
amidisplaycc_alloc_screen(NULL, &amidisplaycc_screentab[0].wsdescr,
|
|
&cookie, &x, &y, &attr);
|
|
wsdisplay_cnattach(&amidisplaycc_screentab[0].wsdescr,
|
|
cookie, x, y, attr);
|
|
}
|
|
|
|
int
|
|
amidisplaycc_match(pdp,cfp,auxp)
|
|
struct device *pdp;
|
|
struct cfdata *cfp;
|
|
void *auxp;
|
|
{
|
|
char *name = auxp;
|
|
|
|
if (matchname("amidisplaycc",name)==0)
|
|
return (0);
|
|
|
|
/* Allow only one of us now. Not sure about that. */
|
|
if (cfp->cf_unit != 0)
|
|
return (0);
|
|
|
|
return 1;
|
|
}
|
|
|
|
void
|
|
amidisplaycc_attach(pdp,dp,auxp)
|
|
struct device *pdp;
|
|
struct device *dp;
|
|
void *auxp;
|
|
{
|
|
struct wsemuldisplaydev_attach_args waa;
|
|
|
|
/*
|
|
* Attach only at real configuration time. Console init is done at
|
|
* the amidisplaycc_cninit function above.
|
|
*/
|
|
if (dp) {
|
|
printf("\n");
|
|
|
|
waa.console = 1;
|
|
waa.scrdata = &amidisplaycc_screenlist;
|
|
waa.accessops = &amidisplaycc_accessops;
|
|
waa.accesscookie = NULL;
|
|
config_found(dp,&waa,wsemuldisplaydevprint);
|
|
}
|
|
}
|
|
|
|
|
|
/*
|
|
* Color, bgcolor and style are packed into one long attribute.
|
|
* These macros are used to create/split the attribute
|
|
*/
|
|
|
|
#define MAKEATTR(fg, bg, mode) (((fg)<<16) | ((bg)<<8) | (mode))
|
|
#define ATTRFG(attr) (((attr)>>16) & 255)
|
|
#define ATTRBG(attr) (((attr)>>8) & 255)
|
|
#define ATTRMO(attr) ((attr) & 255)
|
|
|
|
/*
|
|
* Called by wscons to draw/clear the cursor.
|
|
* We do this by xorring the block to the screen.
|
|
*
|
|
* This simple implementation will break if the screen is modified
|
|
* under the cursor before clearing it.
|
|
*/
|
|
void
|
|
amidisplaycc_cursor(screen, on, row, col)
|
|
void *screen;
|
|
int on;
|
|
int row;
|
|
int col;
|
|
{
|
|
adccscr_t *scr;
|
|
u_char *plane;
|
|
int y;
|
|
int miny;
|
|
int maxy;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (row < 0 || col < 0 || row >= scr->nrows || col >= scr->ncols)
|
|
return;
|
|
#endif
|
|
|
|
miny = row * scr->fontheight;
|
|
maxy = miny + scr->fontheight;
|
|
|
|
for (y = miny ; y < maxy ; y++) {
|
|
plane = col + VDISPLAY_LINE(scr->view, 0, y);
|
|
*plane ^= 255;
|
|
}
|
|
|
|
}
|
|
|
|
/*
|
|
* This obviously does something important, don't ask me what.
|
|
*/
|
|
int
|
|
amidisplaycc_mapchar(screen, ch, chp)
|
|
void *screen;
|
|
int ch;
|
|
unsigned int *chp;
|
|
{
|
|
if (ch > 0 && ch < 256) {
|
|
*chp = ch;
|
|
return (5);
|
|
}
|
|
*chp = ' ';
|
|
return (0);
|
|
}
|
|
|
|
extern unsigned char kernel_font_8x8[];
|
|
|
|
/* Write a character to screen with color / bgcolor / hilite(bold) /
|
|
* underline / inverse.
|
|
* Surely could be made faster but I'm not sure if its worth the
|
|
* effort as scrolling is at least a magnitude slower.
|
|
*/
|
|
void
|
|
amidisplaycc_putchar(screen, row, col, ch, attr)
|
|
void *screen;
|
|
int row;
|
|
int col;
|
|
u_int ch;
|
|
long attr;
|
|
{
|
|
bmap_t *bitmap;
|
|
u_char *dst;
|
|
adccscr_t *scr;
|
|
u_char *font;
|
|
u_char f;
|
|
int j;
|
|
int fgcolor;
|
|
int bgcolor;
|
|
int plane;
|
|
int depth;
|
|
int rowsize;
|
|
int fontoffset;
|
|
int bmapoffset;
|
|
int mode;
|
|
int bold;
|
|
int underline;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (row < 0 || col < 0 || row >= scr->nrows || col >= scr->ncols)
|
|
return;
|
|
#endif
|
|
|
|
bitmap = scr->view->bitmap;
|
|
depth = bitmap->depth;
|
|
rowsize = bitmap->bytes_per_row + bitmap->row_mod;
|
|
|
|
/* Extract the colors from the attribute */
|
|
fgcolor = ATTRFG(attr);
|
|
bgcolor = ATTRBG(attr);
|
|
mode = ATTRMO(attr);
|
|
|
|
/* Translate to screen colors */
|
|
fgcolor = scr->colormap[fgcolor];
|
|
bgcolor = scr->colormap[bgcolor];
|
|
|
|
if(mode & WSATTR_REVERSE) {
|
|
j = fgcolor;
|
|
fgcolor = bgcolor;
|
|
bgcolor = j;
|
|
}
|
|
|
|
if (mode & WSATTR_HILIT)
|
|
bold = 1;
|
|
else
|
|
bold = 0;
|
|
|
|
|
|
if (mode & WSATTR_UNDERLINE)
|
|
underline = 1;
|
|
else
|
|
underline = 0;
|
|
|
|
|
|
if (ch < 32)
|
|
ch = 32;
|
|
if (ch > 255)
|
|
ch = 255;
|
|
|
|
|
|
fontoffset = scr->fontheight * (ch - 32);
|
|
bmapoffset = row * scr->fontheight * rowsize + col;
|
|
|
|
scr->rowmasks[row] |= fgcolor | bgcolor;
|
|
|
|
for (plane = 0 ; plane < depth ; plane++) {
|
|
dst = bitmap->plane[plane] + bmapoffset;
|
|
|
|
if (fgcolor & 1) {
|
|
if (bgcolor & 1) {
|
|
/* fg=on bg=on (fill) */
|
|
|
|
for (j = 0 ; j < scr->fontheight ; j++)
|
|
{
|
|
*dst = 255;
|
|
dst += rowsize;
|
|
}
|
|
} else {
|
|
/* fg=on bg=off (normal) */
|
|
|
|
font = &kernel_font_8x8[fontoffset];
|
|
for (j = 0 ; j < scr->fontheight ; j++)
|
|
{
|
|
f = *(font++);
|
|
f |= f>>bold;
|
|
*dst = f;
|
|
dst += rowsize;
|
|
}
|
|
|
|
/* XXX underline does not recognise baseline */
|
|
if (underline)
|
|
*(dst-rowsize) = 255;
|
|
}
|
|
} else {
|
|
if (bgcolor & 1) {
|
|
/* fg=off bg=on (inverted) */
|
|
|
|
font = &kernel_font_8x8[fontoffset];
|
|
for (j = 0 ; j < scr->fontheight ; j++) {
|
|
f = *(font++);
|
|
f |= f>>bold;
|
|
*dst = ~f;
|
|
dst += rowsize;
|
|
}
|
|
|
|
/* XXX underline does not recognise baseline */
|
|
if (underline)
|
|
*(dst-rowsize) = 0;
|
|
} else {
|
|
/* fg=off bg=off (clear) */
|
|
|
|
for (j = 0 ; j < scr->fontheight ; j++) {
|
|
*dst = 0;
|
|
dst += rowsize;
|
|
}
|
|
}
|
|
}
|
|
fgcolor >>= 1;
|
|
bgcolor >>= 1;
|
|
}
|
|
}
|
|
|
|
|
|
void
|
|
amidisplaycc_copycols(screen, row, srccol, dstcol, ncols)
|
|
void *screen;
|
|
int row;
|
|
int srccol;
|
|
int dstcol;
|
|
int ncols;
|
|
{
|
|
bmap_t *bitmap;
|
|
adccscr_t *scr;
|
|
int depth;
|
|
int i;
|
|
int j;
|
|
int plane;
|
|
int rowsize;
|
|
u_char *buf;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (srccol < 0 || srccol + ncols > scr->ncols ||
|
|
dstcol < 0 || dstcol + ncols > scr->ncols ||
|
|
row < 0 || row >= scr->nrows)
|
|
return;
|
|
#endif
|
|
|
|
bitmap = scr->view->bitmap;
|
|
depth = bitmap->depth;
|
|
rowsize = bitmap->bytes_per_row + bitmap->row_mod;
|
|
|
|
for (plane = 0 ; plane < depth ; plane++) {
|
|
buf = bitmap->plane[plane] + row*scr->fontheight*rowsize;
|
|
|
|
for (j = 0 ; j < scr->fontheight ; j++) {
|
|
|
|
if (srccol < dstcol) {
|
|
|
|
for (i = ncols - 1 ; i >= 0 ; i--)
|
|
buf[dstcol + i] = buf[srccol + i];
|
|
|
|
} else {
|
|
|
|
for (i = 0 ; i < ncols ; i++)
|
|
buf[dstcol + i] = buf[srccol + i];
|
|
|
|
}
|
|
buf += rowsize;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
amidisplaycc_erasecols(screen, row, startcol, ncols, attr)
|
|
void *screen;
|
|
int row;
|
|
int startcol;
|
|
int ncols;
|
|
long attr;
|
|
{
|
|
bmap_t *bitmap;
|
|
adccscr_t *scr;
|
|
u_char *buf;
|
|
int depth;
|
|
int j;
|
|
int plane;
|
|
int rowsize;
|
|
int fill;
|
|
int bgcolor;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (row < 0 || row >= scr->nrows ||
|
|
startcol < 0 || startcol + ncols > scr->ncols)
|
|
return;
|
|
#endif
|
|
|
|
bitmap = scr->view->bitmap;
|
|
depth = bitmap->depth;
|
|
rowsize = bitmap->bytes_per_row + bitmap->row_mod;
|
|
|
|
bgcolor = ATTRBG(attr);
|
|
bgcolor = scr->colormap[bgcolor];
|
|
|
|
for(plane = 0 ; plane < depth ; plane++) {
|
|
|
|
fill = (bgcolor & 1) ? 255 : 0;
|
|
|
|
buf = bitmap->plane[plane];
|
|
buf += row * scr->fontheight * rowsize;
|
|
buf += startcol;
|
|
|
|
for (j = 0 ; j < scr->fontheight ; j++)
|
|
{
|
|
memset(buf, fill, ncols);
|
|
buf += rowsize;
|
|
}
|
|
}
|
|
}
|
|
|
|
void
|
|
amidisplaycc_copyrows(screen, srcrow, dstrow, nrows)
|
|
void *screen;
|
|
int srcrow;
|
|
int dstrow;
|
|
int nrows;
|
|
{
|
|
bmap_t *bitmap;
|
|
adccscr_t *scr;
|
|
u_char *src;
|
|
u_char *dst;
|
|
|
|
int depth;
|
|
int plane;
|
|
int i;
|
|
int j;
|
|
int rowmod;
|
|
int bytesperrow;
|
|
int rowsize;
|
|
int srcmask;
|
|
int dstmask;
|
|
int srcbmapoffset;
|
|
int dstbmapoffset;
|
|
int copysize;
|
|
int bmdelta;
|
|
int rowdelta;
|
|
int bmwidth;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (srcrow < 0 || srcrow + nrows > scr->nrows ||
|
|
dstrow < 0 || dstrow + nrows > scr->nrows)
|
|
return;
|
|
#endif
|
|
|
|
bitmap = scr->view->bitmap;
|
|
depth = bitmap->depth;
|
|
rowmod = bitmap->row_mod;
|
|
bytesperrow = bitmap->bytes_per_row;
|
|
bmwidth = bytesperrow+rowmod;
|
|
rowsize = bmwidth*scr->fontheight;
|
|
|
|
srcbmapoffset = rowsize*srcrow;
|
|
dstbmapoffset = rowsize*dstrow;
|
|
|
|
if (srcrow < dstrow) {
|
|
/* Move data downwards, need to copy from down to up */
|
|
bmdelta = -rowsize;
|
|
rowdelta = -1;
|
|
|
|
srcbmapoffset += rowsize * (nrows - 1);
|
|
srcrow += nrows - 1;
|
|
|
|
dstbmapoffset += rowsize * (nrows - 1);
|
|
dstrow += nrows - 1;
|
|
} else {
|
|
/* Move data upwards, copy up to down */
|
|
bmdelta = rowsize;
|
|
rowdelta = 1;
|
|
}
|
|
|
|
if (rowmod == 0)
|
|
copysize = rowsize;
|
|
else
|
|
copysize = 0;
|
|
|
|
for (j = 0 ; j < nrows ; j++) {
|
|
/* Need to copy only planes that have data on src or dst */
|
|
srcmask = scr->rowmasks[srcrow];
|
|
dstmask = scr->rowmasks[dstrow];
|
|
scr->rowmasks[dstrow] = srcmask;
|
|
|
|
for (plane = 0 ; plane < depth ; plane++) {
|
|
|
|
if (srcmask & 1) {
|
|
/*
|
|
* Source row has data on this
|
|
* plane, copy it
|
|
*/
|
|
|
|
src = bitmap->plane[plane] + srcbmapoffset;
|
|
dst = bitmap->plane[plane] + dstbmapoffset;
|
|
|
|
if (copysize > 0) {
|
|
|
|
/* Do it all */
|
|
memcpy(dst,src,copysize);
|
|
|
|
} else {
|
|
|
|
/*
|
|
* Data not continuous,
|
|
* must do in pieces
|
|
*/
|
|
for (i=0 ; i < scr->fontheight ; i++) {
|
|
memcpy(dst, src, bytesperrow);
|
|
|
|
src += bmwidth;
|
|
dst += bmwidth;
|
|
}
|
|
}
|
|
} else if (dstmask & 1) {
|
|
/*
|
|
* Source plane is empty, but dest is not.
|
|
* so all we need to is clear it.
|
|
*/
|
|
|
|
dst = bitmap->plane[plane] + dstbmapoffset;
|
|
|
|
if (copysize > 0) {
|
|
/* Do it all */
|
|
bzero(dst, copysize);
|
|
} else {
|
|
for (i = 0 ;
|
|
i < scr->fontheight ; i++) {
|
|
bzero(dst, bytesperrow);
|
|
dst += bmwidth;
|
|
}
|
|
}
|
|
}
|
|
|
|
srcmask >>= 1;
|
|
dstmask >>= 1;
|
|
}
|
|
srcbmapoffset += bmdelta;
|
|
dstbmapoffset += bmdelta;
|
|
|
|
srcrow += rowdelta;
|
|
dstrow += rowdelta;
|
|
}
|
|
}
|
|
|
|
void
|
|
amidisplaycc_eraserows(screen, row, nrows, attr)
|
|
void *screen;
|
|
int row;
|
|
int nrows;
|
|
long attr;
|
|
{
|
|
bmap_t *bitmap;
|
|
adccscr_t *scr;
|
|
int depth;
|
|
int plane;
|
|
int j;
|
|
int bytesperrow;
|
|
int rowmod;
|
|
int rowsize;
|
|
int bmwidth;
|
|
int bgcolor;
|
|
int fill;
|
|
int bmapoffset;
|
|
int fillsize;
|
|
u_char *dst;
|
|
|
|
scr = screen;
|
|
|
|
#ifdef PARANOIA
|
|
if (row < 0 || row + nrows > scr->nrows)
|
|
return;
|
|
#endif
|
|
|
|
bitmap = scr->view->bitmap;
|
|
depth = bitmap->depth;
|
|
bytesperrow = bitmap->bytes_per_row;
|
|
rowmod = bitmap->row_mod;
|
|
bmwidth = bytesperrow + rowmod;
|
|
rowsize = bmwidth * scr->fontheight;
|
|
bmapoffset = row * rowsize;
|
|
|
|
if (rowmod == 0)
|
|
fillsize = rowsize * nrows;
|
|
else
|
|
fillsize = 0;
|
|
|
|
bgcolor = ATTRBG(attr);
|
|
bgcolor = scr->colormap[bgcolor];
|
|
|
|
for (j = 0 ; j < nrows ; j++)
|
|
scr->rowmasks[row+j] = bgcolor;
|
|
|
|
for (plane = 0 ; plane < depth ; plane++) {
|
|
dst = bitmap->plane[plane] + bmapoffset;
|
|
fill = (bgcolor & 1) ? 255 : 0;
|
|
|
|
if (fillsize > 0) {
|
|
/* If the rows are continuous, write them all. */
|
|
memset(dst, fill, fillsize);
|
|
} else {
|
|
for (j = 0 ; j < scr->fontheight * nrows ; j++) {
|
|
memset(dst, fill, bytesperrow);
|
|
dst += bmwidth;
|
|
}
|
|
}
|
|
bgcolor >>= 1;
|
|
}
|
|
}
|
|
|
|
int
|
|
amidisplaycc_alloc_attr(screen, fg, bg, flags, attrp)
|
|
void *screen;
|
|
int fg;
|
|
int bg;
|
|
int flags;
|
|
long *attrp;
|
|
{
|
|
adccscr_t *scr;
|
|
int maxcolor;
|
|
int newfg;
|
|
int newbg;
|
|
|
|
scr = screen;
|
|
maxcolor = (1 << scr->view->bitmap->depth) - 1;
|
|
|
|
/* Ensure the colors are displayable. */
|
|
newfg = fg & maxcolor;
|
|
newbg = bg & maxcolor;
|
|
|
|
#ifdef ADJUSTCOLORS
|
|
/*
|
|
* Hack for low-color screens, if background color is nonzero
|
|
* but would be displayed as one, adjust it.
|
|
*/
|
|
if (bg > 0 && newbg == 0)
|
|
newbg = maxcolor;
|
|
|
|
/*
|
|
* If foreground and background colors are different but would
|
|
* display the same fix them by modifying the foreground.
|
|
*/
|
|
if (fg != bg && newfg == newbg) {
|
|
if (newbg > 0)
|
|
newfg = 0;
|
|
else
|
|
newfg = maxcolor;
|
|
}
|
|
#endif
|
|
*attrp = MAKEATTR(newfg, newbg, flags);
|
|
|
|
return (0);
|
|
}
|
|
|
|
int
|
|
amidisplaycc_ioctl(dp, cmd, data, flag, p)
|
|
void *dp;
|
|
u_long cmd;
|
|
caddr_t data;
|
|
int flag;
|
|
struct proc *p;
|
|
{
|
|
switch (cmd)
|
|
{
|
|
case WSDISPLAYIO_GTYPE:
|
|
*(u_int*)data = WSDISPLAY_TYPE_EGA; /* XXX */
|
|
return (0);
|
|
}
|
|
|
|
printf("amidisplaycc_ioctl %lx (grp:'%c' num:%d)\n",
|
|
(long)cmd,
|
|
(char)((cmd&0xff00)>>8),
|
|
(int)(cmd&0xff));
|
|
|
|
/* Yes, think should return -1 if didnt understand. */
|
|
return (-1);
|
|
}
|
|
|
|
paddr_t
|
|
amidisplaycc_mmap(dp, off, prot)
|
|
void *dp;
|
|
off_t off;
|
|
int prot;
|
|
{
|
|
return (-1);
|
|
}
|
|
|
|
int
|
|
amidisplaycc_alloc_screen(dp, screenp, cookiep, curxp, curyp, defattrp)
|
|
void *dp;
|
|
const struct wsscreen_descr *screenp;
|
|
void **cookiep;
|
|
int *curxp;
|
|
int *curyp;
|
|
long *defattrp;
|
|
{
|
|
dimen_t dimension;
|
|
adccscr_t *scr;
|
|
view_t *view;
|
|
struct amidisplaycc_screen_descr *adccscreenp;
|
|
int depth;
|
|
int maxcolor;
|
|
int i;
|
|
int j;
|
|
|
|
adccscreenp = (struct amidisplaycc_screen_descr*)screenp;
|
|
depth = adccscreenp->depth;
|
|
|
|
maxcolor = (1 << depth) - 1;
|
|
|
|
/* Sanity checks because of fixed buffers */
|
|
if (depth > MAXDEPTH || maxcolor >= MAXCOLORS)
|
|
return (ENOMEM);
|
|
if (screenp->nrows > MAXROWS)
|
|
return (ENOMEM);
|
|
|
|
dimension.width = screenp->ncols * 8;
|
|
dimension.height = screenp->nrows * 8;
|
|
|
|
view = grf_alloc_view(NULL, &dimension, depth);
|
|
if (view == NULL)
|
|
return (ENOMEM);
|
|
|
|
/*
|
|
* First screen gets the statically allocated console screen.
|
|
* Others are allocated dynamically.
|
|
*/
|
|
if (amidisplaycc_consolescreen.isconsole == 0) {
|
|
scr = &amidisplaycc_consolescreen;
|
|
scr->isconsole = 1;
|
|
} else {
|
|
scr = malloc(sizeof(adccscr_t), M_DEVBUF, M_WAITOK);
|
|
bzero(scr, sizeof(adccscr_t));
|
|
}
|
|
|
|
scr->view = view;
|
|
scr->fontheight = 8;
|
|
|
|
scr->ncols = screenp->ncols;
|
|
scr->nrows = screenp->nrows;
|
|
|
|
for (i = 0 ; i < MAXROWS ; i++)
|
|
scr->rowmasks[i] = 0;
|
|
|
|
/* Simple one-to-one mapping for most colors */
|
|
for (i = 0 ; i < MAXCOLORS ; i++)
|
|
scr->colormap[i] = i;
|
|
|
|
/*
|
|
* Arrange the most used pens to quickest colors.
|
|
* The default color for given depth is (1<<depth)-1.
|
|
* It is assumed it is used most and it is mapped to
|
|
* color that can be drawn by writing data to one bitplane
|
|
* only.
|
|
* So map colors 3->2, 7->4, 15->8 and so on.
|
|
* This of course should be reflected on the palette
|
|
* but currently we don't do any palette management.
|
|
*/
|
|
for (i = 2 ; i < MAXCOLORS ; i *= 2) {
|
|
j = i * 2 - 1;
|
|
|
|
if (j < MAXCOLORS) {
|
|
scr->colormap[i] = j;
|
|
scr->colormap[j] = i;
|
|
}
|
|
}
|
|
|
|
*cookiep = scr;
|
|
|
|
*curxp = 0;
|
|
*curyp = 0;
|
|
amidisplaycc_cursor(scr, 1, *curxp, *curyp);
|
|
|
|
*defattrp = MAKEATTR(maxcolor, 0, 0);
|
|
|
|
/* Show the console automatically */
|
|
if (scr->isconsole)
|
|
grf_display_view(scr->view);
|
|
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
amidisplaycc_free_screen(dp, screen)
|
|
void *dp;
|
|
void *screen;
|
|
{
|
|
adccscr_t *scr;
|
|
|
|
scr = screen;
|
|
|
|
if (scr == NULL)
|
|
return;
|
|
|
|
if (scr->view)
|
|
grf_free_view(scr->view);
|
|
scr->view = NULL;
|
|
|
|
/* Take care not to free the statically allocated console screen */
|
|
if (scr != &amidisplaycc_consolescreen) {
|
|
free(scr, M_DEVBUF);
|
|
}
|
|
}
|
|
|
|
int
|
|
amidisplaycc_show_screen(dp, screen, waitok, cb, cbarg)
|
|
void *dp;
|
|
void *screen;
|
|
int waitok;
|
|
void (*cb) (void *, int, int);
|
|
void *cbarg;
|
|
{
|
|
adccscr_t *scr;
|
|
|
|
scr = screen;
|
|
grf_display_view(scr->view);
|
|
|
|
return (0);
|
|
}
|
|
|
|
/*
|
|
* Load a font. Not supported yet.
|
|
*/
|
|
int
|
|
amidisplaycc_load_font(dp, cookie, fontp)
|
|
void *dp;
|
|
void *cookie;
|
|
struct wsdisplay_font *fontp;
|
|
{
|
|
return (-1);
|
|
}
|
|
|
|
/*
|
|
* These dummy functions are here just so that we can compete of
|
|
* the console at init.
|
|
* If we win the console then the wscons system will provide the
|
|
* real ones which in turn will call the apropriate wskbd device.
|
|
* These should never be called.
|
|
*/
|
|
|
|
void
|
|
amidisplaycc_cnputc(cd,ch)
|
|
dev_t cd;
|
|
int ch;
|
|
{
|
|
}
|
|
|
|
int
|
|
amidisplaycc_cngetc(cd)
|
|
dev_t cd;
|
|
{
|
|
return (0);
|
|
}
|
|
|
|
void
|
|
amidisplaycc_cnpollc(cd,on)
|
|
dev_t cd;
|
|
int on;
|
|
{
|
|
}
|
|
|
|
#endif /* AMIDISPLAYCC */
|
|
|
|
|
|
|
|
|