plan 9 kernel history: overview | file list | diff list

pc/devvga.c (diff list | history)

1992/0527/sys/src/9/pc/devvga.c:7,121992/0528/sys/src/9/pc/devvga.c:7,13 (short | long)
1992/0527    
#include	"../port/error.h" 
 
#include	"devtab.h" 
1992/0528    
#include	"vga.h" 
1992/0527    
 
/* 
 *  Driver for various VGA cards 
1992/0527/sys/src/9/pc/devvga.c:25,321992/0528/sys/src/9/pc/devvga.c:26,34
1992/0527    
	Qvgamonitor=	1, 
	Qvgasize=	2, 
	Qvgatype=	3, 
	Qvgaportio=	4, 
	Nvga=		4, 
1992/0528    
	Qvgaport=	4, 
	Qvgaiport=	5, 
	Nvga=		5, 
1992/0527    
}; 
 
Dirtab vgadir[]={ 
1992/0527/sys/src/9/pc/devvga.c:33,391992/0528/sys/src/9/pc/devvga.c:35,42
1992/0527    
	"vgamonitor",	{Qvgamonitor},	0,		0666, 
	"vgatype",	{Qvgatype},	0,		0666, 
	"vgasize",	{Qvgasize},	0,		0666, 
	"vgaportio",	{Qvgaportio},	0,		0666, 
1992/0528    
	"vgaport",	{Qvgaport},	0,		0666, 
	"vgaiport",	{Qvgaiport},	0,		0666, 
1992/0527    
}; 
 
/* a routine from ../port/devcons.c */ 
1992/0527/sys/src/9/pc/devvga.c:93,991992/0528/sys/src/9/pc/devvga.c:96,102
1992/0527    
	case Qvgamonitor: 
	case Qvgatype: 
	case Qvgasize: 
	case Qvgaportio: 
1992/0528    
	case Qvgaport: 
1992/0527    
		break; 
	} 
 
1992/0527/sys/src/9/pc/devvga.c:115,1201992/0528/sys/src/9/pc/devvga.c:118,127
1992/0527    
vgaread(Chan *c, void *buf, long n, ulong offset) 
{ 
	char obuf[60]; 
1992/0528    
	int port, i; 
	uchar *cp = buf; 
	void *outfunc(int, int); 
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
		return devdirread(c, buf, n, vgadir, Nvga, devgen); 
1992/0527/sys/src/9/pc/devvga.c:125,1511992/0528/sys/src/9/pc/devvga.c:132,193
1992/0527    
	case Qvgasize: 
		sprint(obuf, "%dx%d%x%d %s", 
			screeninfo.maxx, screeninfo.maxy, 
			screeninfo.packed ? 16 : 256, 
			screeninfo.interlaced ? "interlaced" : "non-interlaced"); 
1992/0528    
			(screeninfo.packed == 0) ? 256 : 16, 
			(screeninfo.interlaced != 0) ? "interlaced" : "non-interlaced"); 
1992/0527    
		return readstr(offset, buf, n, obuf); 
	case Qvgaportio: 
		return 0; 
1992/0528    
	case Qvgaport: 
		if (offset + n >= 0x8000) 
			error(Ebadarg); 
		for (port=offset; port<offset+n; port++) 
			*cp++ = inb(port); 
		return n; 
	case Qvgaiport: 
		error(Eio); 
1992/0527    
	} 
} 
 
long 
vgawrite(Chan *c, void *va, long n, ulong offset) 
1992/0528    
vgawrite(Chan *c, void *buf, long n, ulong offset) 
1992/0527    
{ 
	if(offset != 0) 
		error(Ebadarg); 
1992/0528    
	uchar *cp = buf; 
	void (*outfunc)(int, int); 
	int port, i; 
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
		error(Eperm); 
	case Qvgamonitor: 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
		error(Eperm); 
1992/0527    
	case Qvgatype: 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
		error(Eperm); 
1992/0527    
	case Qvgasize: 
	case Qvgaportio: 
		return 0; 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
		error(Eperm); 
	case Qvgaport: 
		if (offset + n >= 0x8000) 
			error(Ebadarg); 
		for (port=offset; port<offset+n; port++) 
			outb(port, *cp++); 
		return n; 
	case Qvgaiport: 
		port = offset / 256; 
		switch (port) { 
		case EMISCW:	outfunc = genout;	break; 
		case SRX:	outfunc = srout;	break; 
		case GRX:	outfunc = grout;	break; 
		case ARW:	outfunc = arout;	break; 
		case CRX:	outfunc = crout;	break; 
		default: 
			error(Ebadarg); 
		} 
		for (i = offset%256; i < (offset%256) + n; i++) 
			outfunc(i, *cp++); 
		return n; 
1992/0527    
	} 
} 
 
1992/0528/sys/src/9/pc/devvga.c:27,341992/0529/sys/src/9/pc/devvga.c:27,33 (short | long)
1992/0527    
	Qvgasize=	2, 
	Qvgatype=	3, 
1992/0528    
	Qvgaport=	4, 
	Qvgaiport=	5, 
	Nvga=		5, 
1992/0529    
	Nvga=		4, 
1992/0527    
}; 
 
Dirtab vgadir[]={ 
1992/0528/sys/src/9/pc/devvga.c:36,421992/0529/sys/src/9/pc/devvga.c:35,40
1992/0527    
	"vgatype",	{Qvgatype},	0,		0666, 
	"vgasize",	{Qvgasize},	0,		0666, 
1992/0528    
	"vgaport",	{Qvgaport},	0,		0666, 
	"vgaiport",	{Qvgaiport},	0,		0666, 
1992/0527    
}; 
 
/* a routine from ../port/devcons.c */ 
1992/0528/sys/src/9/pc/devvga.c:141,1481992/0529/sys/src/9/pc/devvga.c:139,144
1992/0528    
		for (port=offset; port<offset+n; port++) 
			*cp++ = inb(port); 
		return n; 
	case Qvgaiport: 
		error(Eio); 
1992/0527    
	} 
} 
 
1992/0528/sys/src/9/pc/devvga.c:173,1921992/0529/sys/src/9/pc/devvga.c:169,174
1992/0528    
			error(Ebadarg); 
		for (port=offset; port<offset+n; port++) 
			outb(port, *cp++); 
		return n; 
	case Qvgaiport: 
		port = offset / 256; 
		switch (port) { 
		case EMISCW:	outfunc = genout;	break; 
		case SRX:	outfunc = srout;	break; 
		case GRX:	outfunc = grout;	break; 
		case ARW:	outfunc = arout;	break; 
		case CRX:	outfunc = crout;	break; 
		default: 
			error(Ebadarg); 
		} 
		for (i = offset%256; i < (offset%256) + n; i++) 
			outfunc(i, *cp++); 
		return n; 
1992/0527    
	} 
} 
1992/0529/sys/src/9/pc/devvga.c:6,111992/0603/sys/src/9/pc/devvga.c:6,13 (short | long)
1992/0527    
#include	"io.h" 
#include	"../port/error.h" 
 
1992/0603    
#include	<libg.h> 
#include	<gnot.h> 
1992/0527    
#include	"devtab.h" 
1992/0528    
#include	"vga.h" 
1992/0527    
 
1992/0529/sys/src/9/pc/devvga.c:128,1431992/0603/sys/src/9/pc/devvga.c:130,144
1992/0527    
	case Qvgatype: 
		return readstr(offset, buf, n, vgacard); 
	case Qvgasize: 
		sprint(obuf, "%dx%d%x%d %s", 
			screeninfo.maxx, screeninfo.maxy, 
1992/0528    
			(screeninfo.packed == 0) ? 256 : 16, 
			(screeninfo.interlaced != 0) ? "interlaced" : "non-interlaced"); 
1992/0603    
		sprint(obuf, "%d %d", 
			gscreen.r.max.x, gscreen.r.max.y); 
1992/0527    
		return readstr(offset, buf, n, obuf); 
1992/0528    
	case Qvgaport: 
		if (offset + n >= 0x8000) 
			error(Ebadarg); 
		for (port=offset; port<offset+n; port++) 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0528    
			*cp++ = inb(port); 
1992/0603    
		} 
1992/0528    
		return n; 
1992/0527    
	} 
} 
1992/0529/sys/src/9/pc/devvga.c:145,1531992/0603/sys/src/9/pc/devvga.c:146,153
1992/0527    
long 
1992/0528    
vgawrite(Chan *c, void *buf, long n, ulong offset) 
1992/0527    
{ 
1992/0528    
	uchar *cp = buf; 
	void (*outfunc)(int, int); 
	int port, i; 
1992/0603    
	char cbuf[20], *cp; 
	int port, i, maxx, maxy; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
1992/0529/sys/src/9/pc/devvga.c:163,1741992/0603/sys/src/9/pc/devvga.c:163,187
1992/0527    
	case Qvgasize: 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
		error(Eperm); 
1992/0603    
		if(n >= sizeof cbuf) 
			n = sizeof cbuf - 1; 
		memmove(cbuf, buf, n); 
		cbuf[n-1] = 0; 
		cp = cbuf; 
		maxx = strtoul(cp, &cp, 0); 
		maxy = strtoul(cp, &cp, 0); 
		if (maxx == 0 || maxy == 0 || 
		    maxx > 1280 || maxy > 1024) 
			error(Ebadarg); 
		setscreen(maxx, maxy, 1); 
		return n; 
1992/0528    
	case Qvgaport: 
1992/0603    
		cp = buf; 
1992/0528    
		if (offset + n >= 0x8000) 
			error(Ebadarg); 
		for (port=offset; port<offset+n; port++) 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0528    
			outb(port, *cp++); 
1992/0603    
		} 
1992/0528    
		return n; 
1992/0527    
	} 
} 
1992/0603/sys/src/9/pc/devvga.c:29,351992/0604/sys/src/9/pc/devvga.c:29,36 (short | long)
1992/0527    
	Qvgasize=	2, 
	Qvgatype=	3, 
1992/0528    
	Qvgaport=	4, 
1992/0529    
	Nvga=		4, 
1992/0604    
	Qvgamem=	5, 
	Nvga=		5, 
1992/0527    
}; 
 
Dirtab vgadir[]={ 
1992/0603/sys/src/9/pc/devvga.c:37,421992/0604/sys/src/9/pc/devvga.c:38,44
1992/0527    
	"vgatype",	{Qvgatype},	0,		0666, 
	"vgasize",	{Qvgasize},	0,		0666, 
1992/0528    
	"vgaport",	{Qvgaport},	0,		0666, 
1992/0604    
	"vgamem",	{Qvgamem},	0,		0666, 
1992/0527    
}; 
 
/* a routine from ../port/devcons.c */ 
1992/0603/sys/src/9/pc/devvga.c:97,1051992/0604/sys/src/9/pc/devvga.c:99,107
1992/0527    
	case Qvgatype: 
	case Qvgasize: 
1992/0528    
	case Qvgaport: 
1992/0604    
	case Qvgamem: 
1992/0527    
		break; 
	} 
                 
	return devopen(c, omode, vgadir, Nvga, devgen); 
} 
 
1992/0603/sys/src/9/pc/devvga.c:119,1241992/0604/sys/src/9/pc/devvga.c:121,127
1992/0527    
{ 
	char obuf[60]; 
1992/0528    
	int port, i; 
1992/0604    
	uchar *mem; 
1992/0528    
	uchar *cp = buf; 
	void *outfunc(int, int); 
 
1992/0603/sys/src/9/pc/devvga.c:136,1451992/0604/sys/src/9/pc/devvga.c:139,154
1992/0528    
	case Qvgaport: 
		if (offset + n >= 0x8000) 
			error(Ebadarg); 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0604    
		for (port=offset; port<offset+n; port++) 
1992/0528    
			*cp++ = inb(port); 
1992/0603    
		} 
1992/0528    
		return n; 
1992/0604    
	case Qvgamem: 
		if (offset > 0x10000) 
			return 0; 
		if (offset + n > 0x10000) 
			n = 0x10000 - offset; 
		memmove(cp, (void *)(SCREENMEM+offset), n); 
		return n; 
1992/0527    
	} 
} 
 
1992/0603/sys/src/9/pc/devvga.c:163,1721992/0604/sys/src/9/pc/devvga.c:172,181
1992/0527    
	case Qvgasize: 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
1992/0603    
		if(n >= sizeof cbuf) 
			n = sizeof cbuf - 1; 
1992/0604    
		if(n >= sizeof(cbuf)) 
			n = sizeof(cbuf) - 1; 
1992/0603    
		memmove(cbuf, buf, n); 
		cbuf[n-1] = 0; 
1992/0604    
		cbuf[n] = 0; 
1992/0603    
		cp = cbuf; 
		maxx = strtoul(cp, &cp, 0); 
		maxy = strtoul(cp, &cp, 0); 
1992/0603/sys/src/9/pc/devvga.c:182,1871992/0604/sys/src/9/pc/devvga.c:191,201
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0528    
			outb(port, *cp++); 
1992/0603    
		} 
1992/0604    
		return n; 
	case Qvgamem: 
		if (offset + n > 0x10000) 
			error(Ebadarg); 
		memmove((void *)(SCREENMEM+offset), buf, n); 
1992/0528    
		return n; 
1992/0527    
	} 
} 
1992/0604/sys/src/9/pc/devvga.c:108,1131992/0711/sys/src/9/pc/devvga.c:108,114 (short | long)
1992/0527    
void 
vgacreate(Chan *c, char *name, int omode, ulong perm) 
{ 
1992/0711    
	USED(c, name, omode, perm); 
1992/0527    
	error(Eperm); 
} 
 
1992/0604/sys/src/9/pc/devvga.c:114,1191992/0711/sys/src/9/pc/devvga.c:115,121
1992/0527    
void 
vgaclose(Chan *c) 
{ 
1992/0711    
	USED(c); 
1992/0527    
} 
 
long 
1992/0604/sys/src/9/pc/devvga.c:120,1271992/0711/sys/src/9/pc/devvga.c:122,128
1992/0527    
vgaread(Chan *c, void *buf, long n, ulong offset) 
{ 
	char obuf[60]; 
1992/0528    
	int port, i; 
1992/0604    
	uchar *mem; 
1992/0711    
	int port; 
1992/0528    
	uchar *cp = buf; 
	void *outfunc(int, int); 
 
1992/0604/sys/src/9/pc/devvga.c:156,1621992/0711/sys/src/9/pc/devvga.c:157,163
1992/0528    
vgawrite(Chan *c, void *buf, long n, ulong offset) 
1992/0527    
{ 
1992/0603    
	char cbuf[20], *cp; 
	int port, i, maxx, maxy; 
1992/0711    
	int port, maxx, maxy; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
1992/0604/sys/src/9/pc/devvga.c:203,2081992/0711/sys/src/9/pc/devvga.c:204,210
1992/0527    
void 
vgaremove(Chan *c) 
{ 
1992/0711    
	USED(c); 
1992/0527    
	error(Eperm); 
} 
 
1992/0604/sys/src/9/pc/devvga.c:209,2131992/0711/sys/src/9/pc/devvga.c:211,216
1992/0527    
void 
vgawstat(Chan *c, char *dp) 
{ 
1992/0711    
	USED(c, dp); 
1992/0527    
	error(Eperm); 
} 
1992/0711/sys/src/9/pc/devvga.c:8,641992/1119/sys/src/9/pc/devvga.c:8,158 (short | long)
1992/0527    
 
1992/0603    
#include	<libg.h> 
#include	<gnot.h> 
1992/0527    
#include	"devtab.h" 
1992/1119    
#include	"screen.h" 
1992/0528    
#include	"vga.h" 
1992/0527    
 
1992/1119    
#define	MINX	8 
 
struct{ 
	Point	pos; 
	int	bwid; 
}out; 
 
/* imported */ 
extern	GSubfont defont0; 
extern	Cursor arrow; 
extern	GBitmap cursorback; 
 
/* exported */ 
GSubfont *defont; 
int islittle = 1;		/* little endian bit ordering in bytes */ 
GBitmap	gscreen; 
 
/* local */ 
static	Lock vgalock; 
static	GBitmap	vgascreen; 
static	ulong colormap[256][3]; 
static	int cga = 1;		/* true if in cga mode */ 
 
1992/0527    
/* 
 *  Driver for various VGA cards 
1992/1119    
 *  screen dimensions 
1992/0527    
 */ 
1992/1119    
#define MAXX	640 
#define MAXY	480 
1992/0527    
 
char	monitor[NAMELEN];	/* monitor name and type */ 
char	vgacard[NAMELEN];	/* vga card type */ 
struct screeninfo { 
	int	maxx, maxy;	/* current bits per screen */ 
	int	packed;		/* 0=planar, 1=packed */ 
	int	interlaced;	/* != 0 if interlaced */ 
} screeninfo; 
1992/1119    
/* 
 *  'soft' screen bitmap 
 */ 
1992/0527    
 
enum { 
	Qdir=		0, 
	Qvgamonitor=	1, 
	Qvgasize=	2, 
	Qvgatype=	3, 
1992/0528    
	Qvgaport=	4, 
1992/0604    
	Qvgamem=	5, 
	Nvga=		5, 
1992/1119    
typedef struct VGAmode	VGAmode; 
struct VGAmode 
{ 
	uchar	general[2]; 
	uchar	sequencer[5]; 
	uchar	crt[0x19]; 
	uchar	graphics[9]; 
	uchar	attribute[0x15]; 
1992/0527    
}; 
 
1992/1119    
/* 
 *  640x480 display, 1, 2, or 4 bit color. 
 */ 
VGAmode mode12 =  
{ 
	/* general */ 
	0xe7, 0x00, 
	/* sequence */ 
	0x03, 0x01, 0x0f, 0x00, 0x06, 
	/* crt */ 
	0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e, 
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
	0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 
	0xff, 
	/* graphics */ 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 
	0xff, 
	/* attribute */ 
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
	0x01, 0x10, 0x0f, 0x00, 0x00, 
}; 
 
/* 
 *  320x200 display, 8 bit color. 
 */ 
VGAmode mode13 =  
{ 
	/* general */ 
	0x63, 0x00, 
	/* sequence */ 
	0x03, 0x01, 0x0f, 0x00, 0x0e, 
	/* crt */ 
	0x5f, 0x4f, 0x50, 0x82, 0x54, 0x80, 0xbf, 0x1f, 
	0x00, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x28, 
	0x9c, 0x8e, 0x8f, 0x28, 0x40, 0x96, 0xb9, 0xa3, 
	0xff, 
	/* graphics */ 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0f, 
	0xff, 
	/* attribute */ 
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 
	0x41, 0x10, 0x0f, 0x00, 0x00, 
}; 
 
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
static	void nopage(int), tsengpage(int);; 
 
/* 
 *  definitions of known cards 
 */ 
typedef struct Vgacard	Vgacard; 
struct Vgacard 
{ 
	char	*name; 
	void	(*setpage)(int); 
}; 
 
enum 
{ 
	Tseng,		/* tseng labs te4000 */ 
	Generic, 
}; 
 
Vgacard vgacards[] = 
{ 
[Tseng]		{ "tseng", tsengpage, }, 
[Generic]	{ "generic", nopage, }, 
		{ 0, 0, }, 
}; 
 
Vgacard	*vgacard;	/* current vga card */ 
 
/* 
 *  vga device directory 
 */ 
enum 
{ 
	Qdir=		0, 
	Qvgasize=	1, 
	Qvgatype=	2, 
	Qvgaport=	3, 
	Nvga=		4, 
}; 
1992/0527    
Dirtab vgadir[]={ 
	"vgamonitor",	{Qvgamonitor},	0,		0666, 
	"vgatype",	{Qvgatype},	0,		0666, 
	"vgasize",	{Qvgasize},	0,		0666, 
1992/1119    
	"vgatype",	{Qvgatype},	0,		0666, 
1992/0528    
	"vgaport",	{Qvgaport},	0,		0666, 
1992/0604    
	"vgamem",	{Qvgamem},	0,		0666, 
1992/0527    
}; 
 
/* a routine from ../port/devcons.c */ 
extern	int readstr(ulong, char *, ulong, char *); 
                 
void 
vgasetup(void) { 
1992/1119    
vgareset(void) 
{ 
	vgacard = &vgacards[Generic]; 
1992/0527    
} 
 
void 
vgareset(void) { 
	strcpy(monitor, "generic"); 
	strcpy(vgacard, "generic"); 
	screeninfo.maxx = 640; 
	screeninfo.maxy = 480; 
	screeninfo.packed = 0; 
	screeninfo.interlaced = 0; 
} 
                 
void 
vgainit(void) 
{ 
} 
1992/0711/sys/src/9/pc/devvga.c:84,1071992/1119/sys/src/9/pc/devvga.c:178,189
1992/0527    
void 
vgastat(Chan *c, char *dp) 
{ 
	switch(c->qid.path){ 
	default: 
		devstat(c, dp, vgadir, Nvga, devgen); 
		break; 
	} 
1992/1119    
	devstat(c, dp, vgadir, Nvga, devgen); 
1992/0527    
} 
 
Chan* 
vgaopen(Chan *c, int omode) 
{ 
	switch(c->qid.path){ 
	case Qvgamonitor: 
	case Qvgatype: 
	case Qvgasize: 
1992/0528    
	case Qvgaport: 
1992/0604    
	case Qvgamem: 
1992/0527    
		break; 
	} 
	return devopen(c, omode, vgadir, Nvga, devgen); 
} 
 
1992/0711/sys/src/9/pc/devvga.c:121,2041992/1119/sys/src/9/pc/devvga.c:203,300
1992/0527    
long 
vgaread(Chan *c, void *buf, long n, ulong offset) 
{ 
	char obuf[60]; 
1992/0711    
	int port; 
1992/0528    
	uchar *cp = buf; 
	void *outfunc(int, int); 
1992/1119    
	char cbuf[64]; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
		return devdirread(c, buf, n, vgadir, Nvga, devgen); 
	case Qvgamonitor: 
		return readstr(offset, buf, n, monitor); 
	case Qvgatype: 
		return readstr(offset, buf, n, vgacard); 
	case Qvgasize: 
1992/0603    
		sprint(obuf, "%d %d", 
			gscreen.r.max.x, gscreen.r.max.y); 
1992/0527    
		return readstr(offset, buf, n, obuf); 
1992/1119    
		sprint(cbuf, "%dx%dx%d", gscreen.r.max.x, gscreen.r.max.y, 
			1<<gscreen.ldepth); 
		return readstr(offset, buf, n, cbuf); 
	case Qvgatype: 
		return readstr(offset, buf, n, vgacard->name); 
1992/0528    
	case Qvgaport: 
		if (offset + n >= 0x8000) 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/0604    
		for (port=offset; port<offset+n; port++) 
1992/0528    
			*cp++ = inb(port); 
		return n; 
1992/0604    
	case Qvgamem: 
		if (offset > 0x10000) 
			return 0; 
		if (offset + n > 0x10000) 
			n = 0x10000 - offset; 
		memmove(cp, (void *)(SCREENMEM+offset), n); 
		return n; 
1992/0527    
	} 
1992/1119    
	error(Eperm); 
	return 0; 
1992/0527    
} 
 
long 
1992/0528    
vgawrite(Chan *c, void *buf, long n, ulong offset) 
1992/0527    
{ 
1992/0603    
	char cbuf[20], *cp; 
1992/0711    
	int port, maxx, maxy; 
1992/1119    
	char cbuf[64], *cp; 
	Vgacard *vp; 
	int port, maxx, maxy, ldepth; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
		error(Eperm); 
	case Qvgamonitor: 
1992/0528    
		if(offset != 0) 
			error(Ebadarg); 
		error(Eperm); 
1992/0527    
	case Qvgatype: 
1992/0528    
		if(offset != 0) 
1992/1119    
		if(offset != 0 || n >= sizeof(cbuf) || n < 1) 
1992/0528    
			error(Ebadarg); 
		error(Eperm); 
1992/1119    
		memmove(cbuf, buf, n); 
		cbuf[n] = 0; 
		if(cp = strchr(cbuf, '\n')) 
			*cp = 0; 
		for(vp = vgacards; vp->name; vp++) 
			if(strcmp(cbuf, vp->name) == 0){ 
				vgacard = vp; 
				return n; 
			} 
		error(Ebadarg); 
1992/0527    
	case Qvgasize: 
1992/0528    
		if(offset != 0) 
1992/1119    
		if(offset != 0 || n >= sizeof(cbuf)) 
1992/0528    
			error(Ebadarg); 
1992/0604    
		if(n >= sizeof(cbuf)) 
			n = sizeof(cbuf) - 1; 
1992/0603    
		memmove(cbuf, buf, n); 
1992/0604    
		cbuf[n] = 0; 
1992/0603    
		cp = cbuf; 
		maxx = strtoul(cp, &cp, 0); 
1992/1119    
		if(*cp!=0) 
			cp++; 
1992/0603    
		maxy = strtoul(cp, &cp, 0); 
		if (maxx == 0 || maxy == 0 || 
		    maxx > 1280 || maxy > 1024) 
1992/1119    
		if(*cp!=0) 
			cp++; 
		switch(strtoul(cp, &cp, 0)){ 
		case 1: 
			ldepth = 0; 
			break; 
		case 2: 
			ldepth = 1; 
			break; 
		case 4: 
			ldepth = 2; 
			break; 
		case 8: 
			ldepth = 3; 
			break; 
		default: 
			ldepth = -1; 
		} 
		if(maxx == 0 || maxy == 0 
		|| maxx > 1280 || maxy > 1024 
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
		setscreen(maxx, maxy, 1); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1992/0603    
		return n; 
1992/0528    
	case Qvgaport: 
1992/0603    
		cp = buf; 
1992/0528    
		if (offset + n >= 0x8000) 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0528    
			outb(port, *cp++); 
1992/0603    
		} 
1992/0604    
		return n; 
	case Qvgamem: 
		if (offset + n > 0x10000) 
			error(Ebadarg); 
		memmove((void *)(SCREENMEM+offset), buf, n); 
1992/0528    
		return n; 
1992/0527    
	} 
1992/1119    
	error(Eperm); 
	return 0; 
1992/0527    
} 
 
void 
1992/0711/sys/src/9/pc/devvga.c:214,2161992/1119/sys/src/9/pc/devvga.c:310,1009
1992/0711    
	USED(c, dp); 
1992/0527    
	error(Eperm); 
} 
1992/1119    
 
void 
genout(int reg, int val) 
{ 
	if(reg == 0) 
		outb(EMISCW, val); 
	else if (reg == 1) 
		outb(EFCW, val); 
} 
void 
srout(int reg, int val) 
{ 
	outb(SRX, reg); 
	outb(SR, val); 
} 
void 
grout(int reg, int val) 
{ 
	outb(GRX, reg); 
	outb(GR, val); 
} 
void 
arout(int reg, int val) 
{ 
	inb(0x3DA); 
	if (reg <= 0xf) { 
		outb(ARW, reg | 0x0); 
		outb(ARW, val); 
		inb(0x3DA); 
		outb(ARW, reg | 0x20); 
	} else { 
		outb(ARW, reg | 0x20); 
		outb(ARW, val); 
	} 
} 
 
void 
crout(int reg, int val) 
{ 
	outb(CRX, reg); 
	outb(CR, val); 
} 
 
void 
setmode(VGAmode *v) 
{ 
	int i; 
 
	/* turn screen off (to avoid damage) */ 
	srout(1, 0x21); 
 
	for(i = 0; i < sizeof(v->general); i++) 
		genout(i, v->general[i]); 
 
	for(i = 0; i < sizeof(v->sequencer); i++) 
		if(i == 1) 
			srout(i, v->sequencer[i]|0x20);		/* avoid enabling screen */ 
		else 
			srout(i, v->sequencer[i]); 
 
	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */ 
	for(i = 0; i < sizeof(v->crt); i++) 
		crout(i, v->crt[i]); 
 
	for(i = 0; i < sizeof(v->graphics); i++) 
		grout(i, v->graphics[i]); 
 
	for(i = 0; i < sizeof(v->attribute); i++) 
		arout(i, v->attribute[i]); 
 
	/* turn screen on */ 
	srout(1, v->sequencer[1]); 
} 
 
void 
getmode(VGAmode *v) { 
	int i; 
	v->general[0] = inb(0x3cc); 
	v->general[1] = inb(0x3ca); 
	for(i = 0; i < sizeof(v->sequencer); i++) { 
		outb(SRX, i); 
		v->sequencer[i] = inb(SR); 
	} 
	for(i = 0; i < sizeof(v->crt); i++) { 
		outb(CRX, i); 
		v->crt[i] = inb(CR); 
	} 
	for(i = 0; i < sizeof(v->graphics); i++) { 
		outb(GRX, i); 
		v->graphics[i] = inb(GR); 
	} 
	for(i = 0; i < sizeof(v->attribute); i++) { 
		inb(0x3DA); 
		outb(ARW, i | 0x20); 
		v->attribute[i] = inb(ARR); 
	} 
} 
 
void 
printmode(VGAmode *v) { 
	int i; 
	print("g %2.2x %2x\n", 
		v->general[0], v->general[1]); 
 
	print("s "); 
	for(i = 0; i < sizeof(v->sequencer); i++) { 
		print(" %2.2x", v->sequencer[i]); 
	} 
 
	print("\nc "); 
	for(i = 0; i < sizeof(v->crt); i++) { 
		print(" %2.2x", v->crt[i]); 
	} 
 
	print("\ng "); 
	for(i = 0; i < sizeof(v->graphics); i++) { 
		print(" %2.2x", v->graphics[i]); 
	} 
 
	print("\na "); 
	for(i = 0; i < sizeof(v->attribute); i++) { 
		print(" %2.2x", v->attribute[i]); 
	} 
	print("\n"); 
} 
 
/* 
 *  expand 3 and 6 bits of color to 32 
 */ 
static ulong 
x3to32(uchar x) 
{ 
	ulong y; 
 
	x = x&7; 
	x= (x<<3)|x; 
	y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30)); 
	return y; 
} 
static ulong 
x6to32(uchar x) 
{ 
	ulong y; 
 
	x = x&0x3f; 
	y = (x<<(32-6))|(x<<(32-12))|(x<<(32-18))|(x<<(32-24))|(x<<(32-30)); 
	return y; 
} 
 
void 
setscreen(int maxx, int maxy, int ldepth) 
{ 
	int len, vgamaxy, width, i, x; 
	uchar *p; 
 
	if(ldepth == 3) 
		setmode(&mode13); 
	else 
		setmode(&mode12); 
 
	/* allocate a new soft bitmap area */ 
	width = (maxx*(1<<ldepth))/32; 
	len = width * BY2WD * maxy; 
	p = xalloc(len); 
	if(p == 0) 
		panic("can't alloc screen bitmap"); 
	mbb = NULLMBB; 
 
	/* 
	 *  zero hard screen and setup a bitmap for the new size 
	 */ 
	if(ldepth == 3) 
		vgascreen.ldepth = 3; 
	else 
		vgascreen.ldepth = 0; 
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32; 
	if(maxy > (64*1024)/(vgascreen.width*BY2WD)) 
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD); 
	else 
		vgamaxy = maxy; 
	vgascreen.base = (void*)SCREENMEM; 
	vgascreen.r.min = Pt(0, 0); 
	vgascreen.r.max = Pt(maxx, vgamaxy); 
	vgascreen.clipr = vgascreen.r; 
	memset(vgascreen.base, 0xff, vgascreen.width * BY2WD * vgamaxy); 
 
	/* 
	 *  setup new soft screen, free memory for old screen 
	 */ 
	if(gscreen.base) 
		xfree(gscreen.base); 
	gscreen.ldepth = ldepth; 
	gscreen.width = width; 
	gscreen.r.min = Pt(0, 0); 
	gscreen.r.max = Pt(maxx, maxy); 
	gscreen.clipr = gscreen.r; 
	gscreen.base = (ulong*)p; 
	memset(gscreen.base, 0xff, len); 
 
	/* 
	 *  set depth of cursor backup area 
	 */ 
	bitdepth(); 
 
	/* 
	 *  set string pointer to upper left 
	 */ 
	out.pos.x = MINX; 
	out.pos.y = 0; 
	out.bwid = defont0.info[' '].width; 
 
	/* 
	 *  default color map 
	 */ 
	switch(ldepth){ 
	case 3: 
		for(i = 0; i < 256; i++) 
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1)); 
		break; 
	case 2: 
	case 1: 
	case 0: 
		gscreen.ldepth = 3; 
		for(i = 0; i < 16; i++){ 
			x = x6to32((i*63)/15); 
			setcolor(i, x, x, x); 
		} 
		gscreen.ldepth = ldepth; 
		break; 
	} 
	cga = 0; 
} 
 
void 
screeninit(void) 
{ 
	int i; 
	ulong *l; 
 
	/* 
	 *  arrow is defined as a big endian 
	 */ 
	pixreverse(arrow.set, 2*16, 0); 
	pixreverse(arrow.clr, 2*16, 0); 
 
	/* 
	 *  swizzle the font longs.  we do both byte and bit swizzling 
	 *  since the font is initialized with big endian longs. 
	 */ 
	defont = &defont0; 
	l = defont->bits->base; 
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++) 
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24); 
	pixreverse((uchar*)defont->bits->base, 
		defont->bits->width*BY2WD*Dy(defont->bits->r), 0); 
 
	cga = 1; 
	crout(0x0a, 0xff);		/* turn off cursor */ 
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT); 
} 
 
/* 
 *  collect changes to the 'soft' screen 
 */ 
void 
mbbrect(Rectangle r) 
{ 
	if (r.min.x < mbb.min.x) 
		mbb.min.x = r.min.x; 
	if (r.min.y < mbb.min.y) 
		mbb.min.y = r.min.y; 
	if (r.max.x > mbb.max.x) 
		mbb.max.x = r.max.x; 
	if (r.max.y > mbb.max.y) 
		mbb.max.y = r.max.y; 
	if (Dy(mbb) > 32 || Dx(mbb) > 32) 
		mousescreenupdate(); 
} 
 
void 
mbbpt(Point p) 
{ 
	if (p.x < mbb.min.x) 
		mbb.min.x = p.x; 
	if (p.y < mbb.min.y) 
		mbb.min.y = p.y; 
	if (p.x >= mbb.max.x) 
		mbb.max.x = p.x+1; 
	if (p.y >= mbb.max.y) 
		mbb.max.y = p.y+1; 
} 
 
/* 
 *  paging routines for different cards 
 */ 
static void 
nopage(int page) 
{ 
	USED(page); 
} 
static void 
tsengpage(int page) 
{ 
	outb(0x3cd, (page<<4)|page); 
} 
 
/* 
 *  copy litte endian soft screen to big endian hard screen 
 */ 
static void 
vgaupdate(void) 
{ 
	uchar *sp, *hp, *edisp; 
	int y, len, incs, inch, off, page; 
	Rectangle r; 
	void* (*f)(void*, void*, long); 
 
	r = mbb; 
	mbb = NULLMBB; 
 
	if(Dy(r) < 0) 
		return; 
 
	if(r.min.x < 0) 
		r.min.x = 0; 
	if(r.min.y < 0) 
		r.min.y = 0; 
	if(r.max.x > gscreen.r.max.x) 
		r.max.x = gscreen.r.max.x; 
	if(r.max.y > gscreen.r.max.y) 
		r.max.y = gscreen.r.max.y; 
 
	incs = gscreen.width * BY2WD; 
	inch = vgascreen.width * BY2WD; 
 
	switch(gscreen.ldepth){ 
	case 0: 
		r.min.x &= ~15;		/* 16 bit allignment for l0update() */ 
		f = l0update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 16 bit allignment for l0update() */ 
		break; 
	case 1: 
		r.min.x &= ~15;		/* 16 bit allignment for l1update() */ 
		f = l1update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 16 bit allignment for l1update() */ 
		break; 
	case 2: 
		f = l2update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		break; 
	case 3: 
		f = memmove; 
		len = r.max.x - r.min.x; 
		break; 
	default: 
		return; 
	} 
	if(len < 1) 
		return; 
 
	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth)); 
	page = off>>16; 
	off &= (1<<16)-1; 
	hp = ((uchar*)vgascreen.base) + off; 
	off = r.min.y * gscreen.width * BY2WD + (r.min.x>>(3 - gscreen.ldepth)); 
	sp = ((uchar*)gscreen.base) + off; 
 
	edisp = ((uchar*)vgascreen.base) + 64*1024; 
	vgacard->setpage(page); 
	for(y = r.min.y; y < r.max.y; y++){ 
		if(hp + inch < edisp){ 
			f(hp, sp, len); 
			sp += incs; 
			hp += inch; 
		} else { 
			off = edisp - hp; 
			if(off <= len){ 
				if(off > 0) 
					f(hp, sp, off); 
				vgacard->setpage(++page); 
				if(len - off > 0) 
					f(vgascreen.base, sp+off, len - off); 
			} else { 
				f(hp, sp, len); 
				vgacard->setpage(++page); 
			} 
			sp += incs; 
			hp += inch - 64*1024; 
		} 
	} 
} 
 
void 
screenupdate(void) 
{ 
	lock(&vgalock); 
	vgaupdate(); 
	unlock(&vgalock); 
} 
 
void 
mousescreenupdate(void) 
{ 
	if(canlock(&vgalock)){ 
		vgaupdate(); 
		unlock(&vgalock); 
	} 
} 
 
static void 
cgascreenputc(int c) 
{ 
	int i; 
	static int color; 
	static int pos; 
 
	if(c == '\n'){ 
		pos = pos/CGAWIDTH; 
		pos = (pos+1)*CGAWIDTH; 
	} else if(c == '\t'){ 
		i = 8 - ((pos/2)&7); 
		while(i-->0) 
			cgascreenputc(' '); 
	} else if(c == '\b'){ 
		if(pos >= 2) 
			pos -= 2; 
		cgascreenputc(' '); 
		pos -= 2; 
	} else { 
		CGASCREEN[pos++] = c; 
		CGASCREEN[pos++] = 2;	/* green on black */ 
	} 
	if(pos >= CGAWIDTH*CGAHEIGHT){ 
		memmove(CGASCREEN, &CGASCREEN[CGAWIDTH], CGAWIDTH*(CGAHEIGHT-1)); 
		memset(&CGASCREEN[CGAWIDTH*(CGAHEIGHT-1)], 0, CGAWIDTH); 
		pos = CGAWIDTH*(CGAHEIGHT-1); 
	} 
} 
 
void 
cgascreenputs(char *s, int n) 
{ 
	while(n-- > 0) 
		cgascreenputc(*s++); 
} 
 
void 
screenputnl(void) 
{ 
	Rectangle r; 
 
	out.pos.x = MINX; 
	out.pos.y += defont0.height; 
	if(out.pos.y > gscreen.r.max.y-defont0.height){ 
		vgaupdate(); 
		out.pos.y = gscreen.r.min.y; 
	} 
	r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height); 
	gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]); 
	mbbrect(r); 
	vgaupdate(); 
} 
 
void 
screenputs(char *s, int n) 
{ 
	Rune r; 
	int i; 
	char buf[4]; 
	Rectangle rect; 
 
	if(cga) { 
		cgascreenputs(s, n); 
		return; 
	} 
 
	while(n > 0){ 
		i = chartorune(&r, s); 
		if(i == 0){ 
			s++; 
			--n; 
			continue; 
		} 
		memmove(buf, s, i); 
		buf[i] = 0; 
		n -= i; 
		s += i; 
		if(r == '\n') 
			screenputnl(); 
		else if(r == '\t'){ 
			out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; 
			if(out.pos.x >= gscreen.r.max.x) 
				screenputnl(); 
		}else if(r == '\b'){ 
			if(out.pos.x >= out.bwid+MINX){ 
				out.pos.x -= out.bwid; 
				gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]); 
			} 
			rect.min = Pt(out.pos.x, out.pos.y); 
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); 
			mbbrect(rect); 
		}else{ 
			if(out.pos.x >= gscreen.r.max.x-out.bwid) 
				screenputnl(); 
			rect.min = Pt(out.pos.x, out.pos.y); 
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); 
			out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]); 
			mbbrect(rect); 
		} 
	} 
	vgaupdate(); 
} 
 
int 
screenbits(void) 
{ 
	return 1<<gscreen.ldepth;	/* bits per pixel */ 
} 
 
void 
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) 
{ 
	p &= (1<<(1<<gscreen.ldepth))-1; 
	lock(&vgalock); 
	*pr = colormap[p][0]; 
	*pg = colormap[p][1]; 
	*pb = colormap[p][2]; 
	unlock(&vgalock); 
} 
 
int 
setcolor(ulong p, ulong r, ulong g, ulong b) 
{ 
	p &= (1<<(1<<gscreen.ldepth))-1; 
	lock(&vgalock); 
	colormap[p][0] = r; 
	colormap[p][1] = g; 
	colormap[p][2] = b; 
	outb(CMWX, p); 
	outb(CM, r>>(32-6)); 
	outb(CM, g>>(32-6)); 
	outb(CM, b>>(32-6)); 
	unlock(&vgalock); 
	return ~0; 
} 
 
int 
hwcursset(uchar *s, uchar *c, int ox, int oy) 
{ 
	USED(s, c, ox, oy); 
	return 0; 
} 
 
int 
hwcursmove(int x, int y) 
{ 
	USED(x, y); 
	return 0; 
} 
 
void 
mouseclock(void) 
{ 
	spllo();	/* so we don't cause lost chars on the uart */ 
	mouseupdate(1); 
} 
 
/* 
 *  a fatter than usual cursor for the safari 
 */ 
Cursor fatarrow = { 
	{ -1, -1 }, 
	{ 
		0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c,  
		0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,  
		0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04,  
		0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40,  
	}, 
	{ 
		0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0,  
		0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8,  
		0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8,  
		0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00,  
	}, 
}; 
 
void 
bigcursor(void) 
{ 
	memmove(&arrow, &fatarrow, sizeof(fatarrow)); 
	pixreverse(arrow.set, 2*16, 0); 
	pixreverse(arrow.clr, 2*16, 0); 
} 
 
/* 
 *  Table for separating and reversing bits in a ldepth 1 bitmap. 
 *  This aids in coverting a little endian ldepth 1 bitmap into the 
 *  2 big-endian ldepth 0 bitmaps used for the VGA bit planes. 
 * 
 *	if the bits in uchar x are labeled 
 *		76543210 
 *	then l1revsep[x] yields a ushort with bits 
 *		________1357________0246 
 *	where _ represents a bit whose value is 0. 
 * 
 *  This table is used by l1update() in l.s.  l1update is implemented 
 *  in assembler for speed. 
 * 
 */ 
ulong l1revsep[] = { 
 0x00000, 0x00008, 0x80000, 0x80008, 0x00004, 0x0000c, 0x80004, 0x8000c, 
 0x40000, 0x40008, 0xc0000, 0xc0008, 0x40004, 0x4000c, 0xc0004, 0xc000c, 
 0x00002, 0x0000a, 0x80002, 0x8000a, 0x00006, 0x0000e, 0x80006, 0x8000e, 
 0x40002, 0x4000a, 0xc0002, 0xc000a, 0x40006, 0x4000e, 0xc0006, 0xc000e, 
 0x20000, 0x20008, 0xa0000, 0xa0008, 0x20004, 0x2000c, 0xa0004, 0xa000c, 
 0x60000, 0x60008, 0xe0000, 0xe0008, 0x60004, 0x6000c, 0xe0004, 0xe000c, 
 0x20002, 0x2000a, 0xa0002, 0xa000a, 0x20006, 0x2000e, 0xa0006, 0xa000e, 
 0x60002, 0x6000a, 0xe0002, 0xe000a, 0x60006, 0x6000e, 0xe0006, 0xe000e, 
 0x00001, 0x00009, 0x80001, 0x80009, 0x00005, 0x0000d, 0x80005, 0x8000d, 
 0x40001, 0x40009, 0xc0001, 0xc0009, 0x40005, 0x4000d, 0xc0005, 0xc000d, 
 0x00003, 0x0000b, 0x80003, 0x8000b, 0x00007, 0x0000f, 0x80007, 0x8000f, 
 0x40003, 0x4000b, 0xc0003, 0xc000b, 0x40007, 0x4000f, 0xc0007, 0xc000f, 
 0x20001, 0x20009, 0xa0001, 0xa0009, 0x20005, 0x2000d, 0xa0005, 0xa000d, 
 0x60001, 0x60009, 0xe0001, 0xe0009, 0x60005, 0x6000d, 0xe0005, 0xe000d, 
 0x20003, 0x2000b, 0xa0003, 0xa000b, 0x20007, 0x2000f, 0xa0007, 0xa000f, 
 0x60003, 0x6000b, 0xe0003, 0xe000b, 0x60007, 0x6000f, 0xe0007, 0xe000f, 
 0x10000, 0x10008, 0x90000, 0x90008, 0x10004, 0x1000c, 0x90004, 0x9000c, 
 0x50000, 0x50008, 0xd0000, 0xd0008, 0x50004, 0x5000c, 0xd0004, 0xd000c, 
 0x10002, 0x1000a, 0x90002, 0x9000a, 0x10006, 0x1000e, 0x90006, 0x9000e, 
 0x50002, 0x5000a, 0xd0002, 0xd000a, 0x50006, 0x5000e, 0xd0006, 0xd000e, 
 0x30000, 0x30008, 0xb0000, 0xb0008, 0x30004, 0x3000c, 0xb0004, 0xb000c, 
 0x70000, 0x70008, 0xf0000, 0xf0008, 0x70004, 0x7000c, 0xf0004, 0xf000c, 
 0x30002, 0x3000a, 0xb0002, 0xb000a, 0x30006, 0x3000e, 0xb0006, 0xb000e, 
 0x70002, 0x7000a, 0xf0002, 0xf000a, 0x70006, 0x7000e, 0xf0006, 0xf000e, 
 0x10001, 0x10009, 0x90001, 0x90009, 0x10005, 0x1000d, 0x90005, 0x9000d, 
 0x50001, 0x50009, 0xd0001, 0xd0009, 0x50005, 0x5000d, 0xd0005, 0xd000d, 
 0x10003, 0x1000b, 0x90003, 0x9000b, 0x10007, 0x1000f, 0x90007, 0x9000f, 
 0x50003, 0x5000b, 0xd0003, 0xd000b, 0x50007, 0x5000f, 0xd0007, 0xd000f, 
 0x30001, 0x30009, 0xb0001, 0xb0009, 0x30005, 0x3000d, 0xb0005, 0xb000d, 
 0x70001, 0x70009, 0xf0001, 0xf0009, 0x70005, 0x7000d, 0xf0005, 0xf000d, 
 0x30003, 0x3000b, 0xb0003, 0xb000b, 0x30007, 0x3000f, 0xb0007, 0xb000f, 
 0x70003, 0x7000b, 0xf0003, 0xf000b, 0x70007, 0x7000f, 0xf0007, 0xf000f, 
}; 
 
/* 
 *  Table for separating and reversing bits in a ldepth 2 bitmap. 
 *  This aids in coverting a little endian ldepth 1 bitmap into the 
 *  4 big-endian ldepth 0 bitmaps used for the VGA bit planes. 
 * 
 *	if the bits in uchar x are labeled 
 *		76543210 
 *	then l1revsep[x] yields a ushort with bits 
 *		______37______26______15______04 
 *	where _ represents a bit whose value is 0. 
 * 
 *  This table is used by l2update() in l.s.  l2update is implemented 
 *  in assembler for speed. 
 * 
 */ 
ulong l2revsep[] = { 
 0x0000000, 0x0000002, 0x0000200, 0x0000202, 0x0020000, 0x0020002, 0x0020200, 0x0020202, 
 0x2000000, 0x2000002, 0x2000200, 0x2000202, 0x2020000, 0x2020002, 0x2020200, 0x2020202, 
 0x0000001, 0x0000003, 0x0000201, 0x0000203, 0x0020001, 0x0020003, 0x0020201, 0x0020203, 
 0x2000001, 0x2000003, 0x2000201, 0x2000203, 0x2020001, 0x2020003, 0x2020201, 0x2020203, 
 0x0000100, 0x0000102, 0x0000300, 0x0000302, 0x0020100, 0x0020102, 0x0020300, 0x0020302, 
 0x2000100, 0x2000102, 0x2000300, 0x2000302, 0x2020100, 0x2020102, 0x2020300, 0x2020302, 
 0x0000101, 0x0000103, 0x0000301, 0x0000303, 0x0020101, 0x0020103, 0x0020301, 0x0020303, 
 0x2000101, 0x2000103, 0x2000301, 0x2000303, 0x2020101, 0x2020103, 0x2020301, 0x2020303, 
 0x0010000, 0x0010002, 0x0010200, 0x0010202, 0x0030000, 0x0030002, 0x0030200, 0x0030202, 
 0x2010000, 0x2010002, 0x2010200, 0x2010202, 0x2030000, 0x2030002, 0x2030200, 0x2030202, 
 0x0010001, 0x0010003, 0x0010201, 0x0010203, 0x0030001, 0x0030003, 0x0030201, 0x0030203, 
 0x2010001, 0x2010003, 0x2010201, 0x2010203, 0x2030001, 0x2030003, 0x2030201, 0x2030203, 
 0x0010100, 0x0010102, 0x0010300, 0x0010302, 0x0030100, 0x0030102, 0x0030300, 0x0030302, 
 0x2010100, 0x2010102, 0x2010300, 0x2010302, 0x2030100, 0x2030102, 0x2030300, 0x2030302, 
 0x0010101, 0x0010103, 0x0010301, 0x0010303, 0x0030101, 0x0030103, 0x0030301, 0x0030303, 
 0x2010101, 0x2010103, 0x2010301, 0x2010303, 0x2030101, 0x2030103, 0x2030301, 0x2030303, 
 0x1000000, 0x1000002, 0x1000200, 0x1000202, 0x1020000, 0x1020002, 0x1020200, 0x1020202, 
 0x3000000, 0x3000002, 0x3000200, 0x3000202, 0x3020000, 0x3020002, 0x3020200, 0x3020202, 
 0x1000001, 0x1000003, 0x1000201, 0x1000203, 0x1020001, 0x1020003, 0x1020201, 0x1020203, 
 0x3000001, 0x3000003, 0x3000201, 0x3000203, 0x3020001, 0x3020003, 0x3020201, 0x3020203, 
 0x1000100, 0x1000102, 0x1000300, 0x1000302, 0x1020100, 0x1020102, 0x1020300, 0x1020302, 
 0x3000100, 0x3000102, 0x3000300, 0x3000302, 0x3020100, 0x3020102, 0x3020300, 0x3020302, 
 0x1000101, 0x1000103, 0x1000301, 0x1000303, 0x1020101, 0x1020103, 0x1020301, 0x1020303, 
 0x3000101, 0x3000103, 0x3000301, 0x3000303, 0x3020101, 0x3020103, 0x3020301, 0x3020303, 
 0x1010000, 0x1010002, 0x1010200, 0x1010202, 0x1030000, 0x1030002, 0x1030200, 0x1030202, 
 0x3010000, 0x3010002, 0x3010200, 0x3010202, 0x3030000, 0x3030002, 0x3030200, 0x3030202, 
 0x1010001, 0x1010003, 0x1010201, 0x1010203, 0x1030001, 0x1030003, 0x1030201, 0x1030203, 
 0x3010001, 0x3010003, 0x3010201, 0x3010203, 0x3030001, 0x3030003, 0x3030201, 0x3030203, 
 0x1010100, 0x1010102, 0x1010300, 0x1010302, 0x1030100, 0x1030102, 0x1030300, 0x1030302, 
 0x3010100, 0x3010102, 0x3010300, 0x3010302, 0x3030100, 0x3030102, 0x3030300, 0x3030302, 
 0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303, 
 0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303, 
}; 
1992/1119/sys/src/9/pc/devvga.c:647,6531992/1121/sys/src/9/pc/devvga.c:647,653 (short | long)
1992/1119    
 
	switch(gscreen.ldepth){ 
	case 0: 
		r.min.x &= ~15;		/* 16 bit allignment for l0update() */ 
1992/1121    
		r.min.x &= ~15;		/* 16 pixel allignment for l0update() */ 
1992/1119    
		f = l0update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
1992/1119/sys/src/9/pc/devvga.c:654,6661992/1121/sys/src/9/pc/devvga.c:654,667
1992/1119    
			len++;		/* 16 bit allignment for l0update() */ 
		break; 
	case 1: 
		r.min.x &= ~15;		/* 16 bit allignment for l1update() */ 
1992/1121    
		r.min.x &= ~15;		/* 8 pixel allignment for l1update() */ 
1992/1119    
		f = l1update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 16 bit allignment for l1update() */ 
1992/1121    
			len++;		/* 8 pixel allignment for l1update() */ 
1992/1119    
		break; 
	case 2: 
1992/1121    
		r.min.x &= ~7;		/* 8 pixel allignment for l2update() */ 
1992/1119    
		f = l2update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		break; 
1992/1119/sys/src/9/pc/devvga.c:678,6841992/1121/sys/src/9/pc/devvga.c:679,686
1992/1119    
	page = off>>16; 
	off &= (1<<16)-1; 
	hp = ((uchar*)vgascreen.base) + off; 
	off = r.min.y * gscreen.width * BY2WD + (r.min.x>>(3 - gscreen.ldepth)); 
1992/1121    
	off = r.min.y * gscreen.width * BY2WD 
		+ (r.min.x>>(3 - gscreen.ldepth)); 
1992/1119    
	sp = ((uchar*)gscreen.base) + off; 
 
	edisp = ((uchar*)vgascreen.base) + 64*1024; 
1992/1121/sys/src/9/pc/devvga.c:102,1081992/1124/sys/src/9/pc/devvga.c:102,108 (short | long)
1992/1119    
 
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
static	void nopage(int), tsengpage(int);; 
1992/1124    
static	void nopage(int), tsengpage(int), parapage(int); 
1992/1119    
 
/* 
 *  definitions of known cards 
1992/1121/sys/src/9/pc/devvga.c:117,1271992/1124/sys/src/9/pc/devvga.c:117,129
1992/1119    
enum 
{ 
	Tseng,		/* tseng labs te4000 */ 
1992/1124    
	Pvga1a,		/* paradise */ 
1992/1119    
	Generic, 
}; 
 
Vgacard vgacards[] = 
{ 
1992/1124    
[Pvga1a]	{ "pvga1a", parapage, }, 
1992/1119    
[Tseng]		{ "tseng", tsengpage, }, 
[Generic]	{ "generic", nopage, }, 
		{ 0, 0, }, 
1992/1121/sys/src/9/pc/devvga.c:614,6191992/1124/sys/src/9/pc/devvga.c:616,626
1992/1119    
tsengpage(int page) 
{ 
	outb(0x3cd, (page<<4)|page); 
1992/1124    
} 
static void 
parapage(int page) 
{ 
	grout(9, page<<4); 
1992/1119    
} 
 
/* 
1992/1124/sys/src/9/pc/devvga.c:587,5941992/1209/sys/src/9/pc/devvga.c:587,593 (short | long)
1992/1119    
		mbb.max.x = r.max.x; 
	if (r.max.y > mbb.max.y) 
		mbb.max.y = r.max.y; 
	if (Dy(mbb) > 32 || Dx(mbb) > 32) 
		mousescreenupdate(); 
1992/1209    
	mousescreenupdate(); 
1992/1119    
} 
 
void 
1992/1209/sys/src/9/pc/devvga.c:118,1231992/1215/sys/src/9/pc/devvga.c:118,124 (short | long)
1992/1119    
{ 
	Tseng,		/* tseng labs te4000 */ 
1992/1124    
	Pvga1a,		/* paradise */ 
1992/1215    
	Ati, 
1992/1119    
	Generic, 
}; 
 
1992/1209/sys/src/9/pc/devvga.c:125,1301992/1215/sys/src/9/pc/devvga.c:126,132
1992/1119    
{ 
1992/1124    
[Pvga1a]	{ "pvga1a", parapage, }, 
1992/1119    
[Tseng]		{ "tseng", tsengpage, }, 
1992/1215    
[Ati]		{ "ati", nopage, }, 
1992/1119    
[Generic]	{ "generic", nopage, }, 
		{ 0, 0, }, 
}; 
1992/1215/sys/src/9/pc/devvga.c:102,1081992/1216/sys/src/9/pc/devvga.c:102,109 (short | long)
1992/1119    
 
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/1124    
static	void nopage(int), tsengpage(int), parapage(int); 
1992/1216    
static	void nopage(int), tsengpage(int), tridentpage(int), parapage(int); 
static	void vgaupdate(void); 
1992/1119    
 
/* 
 *  definitions of known cards 
1992/1215/sys/src/9/pc/devvga.c:116,1321992/1216/sys/src/9/pc/devvga.c:117,135
1992/1119    
 
enum 
{ 
	Tseng,		/* tseng labs te4000 */ 
1992/1216    
	Ati,		/* ATI */ 
1992/1124    
	Pvga1a,		/* paradise */ 
1992/1215    
	Ati, 
1992/1216    
	Trident,	/* Trident 8900 */ 
	Tseng,		/* tseng labs te4000 */ 
1992/1119    
	Generic, 
}; 
 
Vgacard vgacards[] = 
{ 
1992/1216    
[Ati]		{ "ati", nopage, }, 
1992/1124    
[Pvga1a]	{ "pvga1a", parapage, }, 
1992/1216    
[Trident]	{ "trident", tridentpage, }, 
1992/1119    
[Tseng]		{ "tseng", tsengpage, }, 
1992/1215    
[Ati]		{ "ati", nopage, }, 
1992/1119    
[Generic]	{ "generic", nopage, }, 
		{ 0, 0, }, 
}; 
1992/1215/sys/src/9/pc/devvga.c:221,2281992/1216/sys/src/9/pc/devvga.c:224,233
1992/1119    
	case Qvgatype: 
		return readstr(offset, buf, n, vgacard->name); 
1992/0528    
	case Qvgaport: 
1992/1216    
		/* at the moment, I need freedom for the ATI card - ches 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/1216    
		*/ 
1992/0604    
		for (port=offset; port<offset+n; port++) 
1992/0528    
			*cp++ = inb(port); 
		return n; 
1992/1215/sys/src/9/pc/devvga.c:286,2921992/1216/sys/src/9/pc/devvga.c:291,299
1992/1119    
		|| maxx > 1280 || maxy > 1024 
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
1992/1216    
		cursoroff(1); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1992/1216    
		cursoron(1); 
1992/0603    
		return n; 
1992/0528    
	case Qvgaport: 
1992/0603    
		cp = buf; 
1992/1215/sys/src/9/pc/devvga.c:498,5041992/1216/sys/src/9/pc/devvga.c:505,510
1992/1119    
	vgascreen.r.min = Pt(0, 0); 
	vgascreen.r.max = Pt(maxx, vgamaxy); 
	vgascreen.clipr = vgascreen.r; 
	memset(vgascreen.base, 0xff, vgascreen.width * BY2WD * vgamaxy); 
 
	/* 
	 *  setup new soft screen, free memory for old screen 
1992/1215/sys/src/9/pc/devvga.c:545,5501992/1216/sys/src/9/pc/devvga.c:551,562
1992/1119    
		break; 
	} 
	cga = 0; 
1992/1216    
 
	/* 
	 * clear screen 
	 */ 
	mbb = gscreen.r; 
	vgaupdate(); 
1992/1119    
} 
 
void 
1992/1215/sys/src/9/pc/devvga.c:612,6171992/1216/sys/src/9/pc/devvga.c:624,634
1992/1119    
nopage(int page) 
{ 
	USED(page); 
1992/1216    
} 
static void 
tridentpage(int page) 
{ 
	srout(0x0e, page^0x02);	/* yes, the page bit needs to be toggled! */ 
1992/1119    
} 
static void 
tsengpage(int page) 
1992/1216/sys/src/9/pc/devvga.c:297,3041992/1217/sys/src/9/pc/devvga.c:297,306 (short | long)
1992/0603    
		return n; 
1992/0528    
	case Qvgaport: 
1992/0603    
		cp = buf; 
1992/1217    
		/* 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/1217    
		*/ 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1992/0528    
			outb(port, *cp++); 
1992/0603    
		} 
1992/1217/sys/src/9/pc/devvga.c:475,4821993/0102/sys/src/9/pc/devvga.c:475,482 (short | long)
1992/1119    
void 
setscreen(int maxx, int maxy, int ldepth) 
{ 
	int len, vgamaxy, width, i, x; 
	uchar *p; 
1993/0102    
	int len, vgamaxy, width, i, x, s; 
	uchar *p, *oldp; 
1992/1119    
 
	if(ldepth == 3) 
		setmode(&mode13); 
1992/1217/sys/src/9/pc/devvga.c:488,4941993/0102/sys/src/9/pc/devvga.c:488,494
1992/1119    
	len = width * BY2WD * maxy; 
	p = xalloc(len); 
	if(p == 0) 
		panic("can't alloc screen bitmap"); 
1993/0102    
		error(Enobitstore); 
1992/1119    
	mbb = NULLMBB; 
 
	/* 
1992/1217/sys/src/9/pc/devvga.c:511,5181993/0102/sys/src/9/pc/devvga.c:511,518
1992/1119    
	/* 
	 *  setup new soft screen, free memory for old screen 
	 */ 
	if(gscreen.base) 
		xfree(gscreen.base); 
1993/0102    
	oldp = gscreen.base; 
	s = splhi(); 
1992/1119    
	gscreen.ldepth = ldepth; 
	gscreen.width = width; 
	gscreen.r.min = Pt(0, 0); 
1992/1217/sys/src/9/pc/devvga.c:519,5251993/0102/sys/src/9/pc/devvga.c:519,527
1992/1119    
	gscreen.r.max = Pt(maxx, maxy); 
	gscreen.clipr = gscreen.r; 
	gscreen.base = (ulong*)p; 
	memset(gscreen.base, 0xff, len); 
1993/0102    
	splx(s); 
	if(oldp) 
		xfree(oldp); 
1992/1119    
 
	/* 
	 *  set depth of cursor backup area 
1993/0102/sys/src/9/pc/devvga.c:476,4821993/0103/sys/src/9/pc/devvga.c:476,482 (short | long)
1992/1119    
setscreen(int maxx, int maxy, int ldepth) 
{ 
1993/0102    
	int len, vgamaxy, width, i, x, s; 
	uchar *p, *oldp; 
1993/0103    
	ulong *p, *oldp; 
1992/1119    
 
	if(ldepth == 3) 
		setmode(&mode13); 
1993/0102/sys/src/9/pc/devvga.c:518,5241993/0103/sys/src/9/pc/devvga.c:518,524
1992/1119    
	gscreen.r.min = Pt(0, 0); 
	gscreen.r.max = Pt(maxx, maxy); 
	gscreen.clipr = gscreen.r; 
	gscreen.base = (ulong*)p; 
1993/0103    
	gscreen.base = p; 
1993/0102    
	splx(s); 
	if(oldp) 
		xfree(oldp); 
1993/0103/sys/src/9/pc/devvga.c:103,1081993/0106/sys/src/9/pc/devvga.c:103,109 (short | long)
1992/1119    
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/1216    
static	void nopage(int), tsengpage(int), tridentpage(int), parapage(int); 
1993/0106    
static	void atipage(int); 
1992/1216    
static	void vgaupdate(void); 
1992/1119    
 
/* 
1993/0103/sys/src/9/pc/devvga.c:124,1321993/0106/sys/src/9/pc/devvga.c:125,133
1992/1119    
	Generic, 
}; 
 
Vgacard vgacards[] = 
1993/0106    
Vgacard vgachips[] = 
1992/1119    
{ 
1992/1216    
[Ati]		{ "ati", nopage, }, 
1993/0106    
[Ati]		{ "ati", atipage, }, 
1992/1124    
[Pvga1a]	{ "pvga1a", parapage, }, 
1992/1216    
[Trident]	{ "trident", tridentpage, }, 
1992/1119    
[Tseng]		{ "tseng", tsengpage, }, 
1993/0103/sys/src/9/pc/devvga.c:145,1511993/0106/sys/src/9/pc/devvga.c:146,152
1992/1119    
	Qvgasize=	1, 
	Qvgatype=	2, 
	Qvgaport=	3, 
	Nvga=		4, 
1993/0106    
	Nvga=		3, 
1992/1119    
}; 
1992/0527    
Dirtab vgadir[]={ 
	"vgasize",	{Qvgasize},	0,		0666, 
1993/0103/sys/src/9/pc/devvga.c:156,1621993/0106/sys/src/9/pc/devvga.c:157,163
1992/0527    
void 
1992/1119    
vgareset(void) 
{ 
	vgacard = &vgacards[Generic]; 
1993/0106    
	vgacard = &vgachips[Generic]; 
1992/0527    
} 
 
void 
1993/0103/sys/src/9/pc/devvga.c:253,2591993/0106/sys/src/9/pc/devvga.c:254,260
1992/1119    
		cbuf[n] = 0; 
		if(cp = strchr(cbuf, '\n')) 
			*cp = 0; 
		for(vp = vgacards; vp->name; vp++) 
1993/0106    
		for(vp = vgachips; vp->name; vp++) 
1992/1119    
			if(strcmp(cbuf, vp->name) == 0){ 
				vgacard = vp; 
				return n; 
1993/0103/sys/src/9/pc/devvga.c:629,6381993/0106/sys/src/9/pc/devvga.c:630,655
1992/1119    
{ 
	USED(page); 
1992/1216    
} 
1993/0106    
/* 
 * The following code is unproven: we haven't got the 
 * ATI stuff to work yet. 
 */ 
1992/1216    
static void 
1993/0106    
atipage(int page) 
{ 
	/* the ext register is in the ATI ROM at a fixed address */ 
	ushort extreg = *((ushort *)0x800C0010); 
	uchar v; 
 
	outb(extreg, 0xb2); 
	v = (inb(extreg+1) & 0xe1) | (page<<1); 
	outb(extreg, 0xb2); 
	outb(extreg+1, v); 
} 
static void 
1992/1216    
tridentpage(int page) 
{ 
	srout(0x0e, page^0x02);	/* yes, the page bit needs to be toggled! */ 
1993/0106    
	srout(0x0e, page^0x02); 
1992/1119    
} 
static void 
tsengpage(int page) 
1993/0106/sys/src/9/pc/devvga.c:325,3301993/0108/sys/src/9/pc/devvga.c:325,335 (short | long)
1992/0527    
	error(Eperm); 
} 
1992/1119    
 
1993/0108    
uchar 
srin(int i) { 
	outb(SRX, i); 
	return inb(SR); 
} 
1992/1119    
void 
genout(int reg, int val) 
{ 
1993/0106/sys/src/9/pc/devvga.c:649,6551993/0108/sys/src/9/pc/devvga.c:654,660
1993/0106    
static void 
1992/1216    
tridentpage(int page) 
{ 
1993/0106    
	srout(0x0e, page^0x02); 
1993/0108    
	srout(0x0e, (srin(0xe)&0xf0) | page^0x02); 
1992/1119    
} 
static void 
tsengpage(int page) 
1993/0108/sys/src/9/pc/devvga.c:495,5001993/0115/sys/src/9/pc/devvga.c:495,501 (short | long)
1992/1119    
	p = xalloc(len); 
	if(p == 0) 
1993/0102    
		error(Enobitstore); 
1993/0115    
	memset(p, 0xff, len); 
1992/1119    
	mbb = NULLMBB; 
 
	/* 
1993/0115/sys/src/9/pc/devvga.c:652,6611993/0206/sys/src/9/pc/devvga.c:652,664 (short | long)
1993/0106    
	outb(extreg, 0xb2); 
	outb(extreg+1, v); 
} 
1993/0206    
/* 
 * The following assumes that the new mode registers have been selected. 
 */ 
1993/0106    
static void 
1992/1216    
tridentpage(int page) 
{ 
1993/0108    
	srout(0x0e, (srin(0xe)&0xf0) | page^0x02); 
1993/0206    
	srout(0x0e, (srin(0x0e)&0xf0) | page^0x02); 
1992/1119    
} 
static void 
tsengpage(int page) 
1993/0206/sys/src/9/pc/devvga.c:931,9431993/0226/sys/src/9/pc/devvga.c:931,936 (short | long)
1992/1119    
	return 0; 
} 
 
void 
mouseclock(void) 
{ 
	spllo();	/* so we don't cause lost chars on the uart */ 
	mouseupdate(1); 
} 
                 
/* 
 *  a fatter than usual cursor for the safari 
 */ 
1993/0226/sys/src/9/pc/devvga.c:293,2981993/0402/sys/src/9/pc/devvga.c:293,299 (short | long)
1992/1119    
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
1992/1216    
		cursoroff(1); 
1993/0402    
		bbinit(); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1992/1216    
		cursoron(1); 
1992/0603    
		return n; 
1993/0402/sys/src/9/pc/devvga.c:293,2991993/0409/sys/src/9/pc/devvga.c:293,298 (short | long)
1992/1119    
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
1992/1216    
		cursoroff(1); 
1993/0402    
		bbinit(); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1992/1216    
		cursoron(1); 
1992/0603    
		return n; 
1993/0402/sys/src/9/pc/devvga.c:562,5671993/0409/sys/src/9/pc/devvga.c:561,567
1992/1119    
		gscreen.ldepth = ldepth; 
		break; 
	} 
1993/0409    
	bbinit(); 
1992/1119    
	cga = 0; 
1992/1216    
 
	/* 
1993/0409/sys/src/9/pc/devvga.c:103,1091993/0915/sys/src/9/pc/devvga.c:103,109 (short | long)
1992/1119    
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/1216    
static	void nopage(int), tsengpage(int), tridentpage(int), parapage(int); 
1993/0106    
static	void atipage(int); 
1993/0915    
static	void atipage(int), cirruspage(int); 
1992/1216    
static	void vgaupdate(void); 
1992/1119    
 
/* 
1993/0409/sys/src/9/pc/devvga.c:122,1271993/0915/sys/src/9/pc/devvga.c:122,128
1992/1124    
	Pvga1a,		/* paradise */ 
1992/1216    
	Trident,	/* Trident 8900 */ 
	Tseng,		/* tseng labs te4000 */ 
1993/0915    
	Cirrus,		/* Cirrus CLGD542X */ 
1992/1119    
	Generic, 
}; 
 
1993/0409/sys/src/9/pc/devvga.c:131,1361993/0915/sys/src/9/pc/devvga.c:132,138
1992/1124    
[Pvga1a]	{ "pvga1a", parapage, }, 
1992/1216    
[Trident]	{ "trident", tridentpage, }, 
1992/1119    
[Tseng]		{ "tseng", tsengpage, }, 
1993/0915    
[Cirrus]	{ "cirrus", cirruspage, }, 
1992/1119    
[Generic]	{ "generic", nopage, }, 
		{ 0, 0, }, 
}; 
1993/0409/sys/src/9/pc/devvga.c:659,6651993/0915/sys/src/9/pc/devvga.c:661,667
1993/0106    
static void 
1992/1216    
tridentpage(int page) 
{ 
1993/0206    
	srout(0x0e, (srin(0x0e)&0xf0) | page^0x02); 
1993/0915    
	srout(0xe, (srin(0xe)&0xf0) | page^0x2); 
1992/1119    
} 
static void 
tsengpage(int page) 
1993/0409/sys/src/9/pc/devvga.c:667,6751993/0915/sys/src/9/pc/devvga.c:669,682
1992/1119    
	outb(0x3cd, (page<<4)|page); 
1992/1124    
} 
static void 
1993/0915    
cirruspage(int page) 
{ 
	grout(0x9, page<<4); 
} 
static void 
1992/1124    
parapage(int page) 
{ 
	grout(9, page<<4); 
1993/0915    
	grout(0x9, page<<4); 
1992/1119    
} 
 
/* 
1993/0409/sys/src/9/pc/devvga.c:918,9351993/0915/sys/src/9/pc/devvga.c:925,940
1992/1119    
	return ~0; 
} 
 
int 
hwcursset(uchar *s, uchar *c, int ox, int oy) 
1993/0915    
void 
hwcursset(ulong *s, ulong *c, int ox, int oy) 
1992/1119    
{ 
	USED(s, c, ox, oy); 
	return 0; 
} 
 
int 
1993/0915    
void 
1992/1119    
hwcursmove(int x, int y) 
{ 
	USED(x, y); 
	return 0; 
} 
 
/* 
1993/0915/sys/src/9/pc/devvga.c:8,491993/1116/sys/src/9/pc/devvga.c:8,77 (short | long)
1992/0527    
 
1992/0603    
#include	<libg.h> 
#include	<gnot.h> 
1992/1119    
#include	"screen.h" 
1992/0528    
#include	"vga.h" 
1992/0527    
 
1992/1119    
#define	MINX	8 
1993/1116    
enum 
{ 
	EMISCR=		0x3CC,		/* control sync polarity */ 
	EMISCW=		0x3C2, 
	EFCW=		0x3DA,		/* feature control */ 
	EFCR=		0x3CA, 
	GRX=		0x3CE,		/* index to graphics registers */ 
	GR=		0x3CF,		/* graphics registers */ 
	 Grms=		 0x04,		/*  read map select register */ 
	SRX=		0x3C4,		/* index to sequence registers */ 
	SR=		0x3C5,		/* sequence registers */ 
	 Smmask=	 0x02,		/*  map mask */ 
	CRX=		0x3D4,		/* index to crt registers */ 
	CR=		0x3D5,		/* crt registers */ 
	 Cvre=		 0x11,		/*  vertical retrace end */ 
	ARW=		0x3C0,		/* attribute registers (writing) */ 
	ARR=		0x3C1,		/* attribute registers (reading) */ 
	CMRX=		0x3C7,		/* color map read index */ 
	CMWX=		0x3C8,		/* color map write index */ 
	CM=		0x3C9,		/* color map data reg */ 
}; 
1992/1119    
 
struct{ 
	Point	pos; 
	int	bwid; 
}out; 
                 
/* imported */ 
extern	GSubfont defont0; 
extern	Cursor arrow; 
extern	GBitmap cursorback; 
 
/* exported */ 
GSubfont *defont; 
int islittle = 1;		/* little endian bit ordering in bytes */ 
GBitmap	gscreen; 
 
/* local */ 
static	Lock vgalock; 
1993/1116    
/* vga screen */ 
static	Lock	screenlock; 
1992/1119    
static	GBitmap	vgascreen; 
static	ulong colormap[256][3]; 
static	int cga = 1;		/* true if in cga mode */ 
1993/1116    
static	ulong	colormap[256][3]; 
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/1119    
 
1993/1116    
/* cga screen */ 
static	int	cga = 1;		/* true if in cga mode */ 
 
/* system window */ 
static	int	isscroll; 
static	Rectangle window; 
static	int	h, w; 
static	Point	cursor; 
 
1992/0527    
/* 
1992/1119    
 *  screen dimensions 
1992/0527    
 */ 
1993/1116    
#define	MINX	8 
1992/1119    
#define MAXX	640 
#define MAXY	480 
1993/1116    
#define	CGAWIDTH	160 
#define	CGAHEIGHT	24 
1992/0527    
 
1992/1119    
/* 
 *  'soft' screen bitmap 
1993/1116    
 *  screen memory addresses 
1992/1119    
 */ 
1993/1116    
#define SCREENMEM	(0xA0000 | KZERO) 
#define CGASCREEN	((uchar*)(0xB8000 | KZERO)) 
1992/0527    
 
1993/1116    
/* 
 *  VGA modes 
 */ 
1992/1119    
typedef struct VGAmode	VGAmode; 
struct VGAmode 
{ 
1993/0915/sys/src/9/pc/devvga.c:100,1111993/1116/sys/src/9/pc/devvga.c:128,133
1992/1119    
	0x41, 0x10, 0x0f, 0x00, 0x00, 
}; 
 
static	Rectangle mbb; 
static	Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/1216    
static	void nopage(int), tsengpage(int), tridentpage(int), parapage(int); 
1993/0915    
static	void atipage(int), cirruspage(int); 
1992/1216    
static	void vgaupdate(void); 
1992/1119    
                 
/* 
 *  definitions of known cards 
 */ 
1993/0915/sys/src/9/pc/devvga.c:113,1191993/1116/sys/src/9/pc/devvga.c:135,141
1992/1119    
struct Vgacard 
{ 
	char	*name; 
	void	(*setpage)(int); 
1993/1116    
	void	(*setpage)(int);	/* routine to page though display memory */ 
1992/1119    
}; 
 
enum 
1993/0915/sys/src/9/pc/devvga.c:126,1311993/1116/sys/src/9/pc/devvga.c:148,156
1992/1119    
	Generic, 
}; 
 
1993/1116    
static void	nopage(int), tsengpage(int), tridentpage(int), parapage(int); 
static void	atipage(int), cirruspage(int); 
 
1993/0106    
Vgacard vgachips[] = 
1992/1119    
{ 
1993/0106    
[Ati]		{ "ati", atipage, }, 
1993/0915/sys/src/9/pc/devvga.c:139,1461993/1116/sys/src/9/pc/devvga.c:164,192
1992/1119    
 
Vgacard	*vgacard;	/* current vga card */ 
 
1993/1116    
/* predefined for the stupid compiler */ 
static void	setscreen(int, int, int); 
static uchar	srin(int); 
static void	genout(int, int); 
static void	srout(int, int); 
static void	grout(int, int); 
static void	arout(int, int); 
static void	crout(int, int); 
static void	setmode(VGAmode*); 
static void	getmode(VGAmode*); 
static void	printmode(VGAmode*); 
static void	cgascreenputc(int); 
static void	cgascreenputs(char*, int); 
static void	screenputc(char*); 
static void	scroll(void); 
static ulong	x3to32(uchar); 
static ulong	x6to32(uchar); 
void	screenupdate(void); 
void	pixreverse(uchar*, int, int); 
void	mbbrect(Rectangle); 
 
1992/1119    
/* 
 *  vga device directory 
1993/1116    
 *  vga device 
1992/1119    
 */ 
enum 
{ 
1993/0915/sys/src/9/pc/devvga.c:148,1591993/1116/sys/src/9/pc/devvga.c:194,207
1992/1119    
	Qvgasize=	1, 
	Qvgatype=	2, 
	Qvgaport=	3, 
1993/0106    
	Nvga=		3, 
1993/1116    
	Qvgaportw=	4, 
	Nvga=		4, 
1992/1119    
}; 
1992/0527    
Dirtab vgadir[]={ 
	"vgasize",	{Qvgasize},	0,		0666, 
1992/1119    
	"vgatype",	{Qvgatype},	0,		0666, 
1992/0528    
	"vgaport",	{Qvgaport},	0,		0666, 
1993/1116    
	"vgaportw",	{Qvgaportw},	0,		0666, 
1992/0527    
}; 
 
void 
1993/0915/sys/src/9/pc/devvga.c:214,2211993/1116/sys/src/9/pc/devvga.c:262,270
1992/0527    
vgaread(Chan *c, void *buf, long n, ulong offset) 
{ 
1992/0711    
	int port; 
1992/0528    
	uchar *cp = buf; 
1993/1116    
	uchar *cp; 
1992/1119    
	char cbuf[64]; 
1993/1116    
	ushort *sp; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
1993/0915/sys/src/9/pc/devvga.c:227,2391993/1116/sys/src/9/pc/devvga.c:276,291
1992/1119    
	case Qvgatype: 
		return readstr(offset, buf, n, vgacard->name); 
1992/0528    
	case Qvgaport: 
1992/1216    
		/* at the moment, I need freedom for the ATI card - ches 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/1216    
		*/ 
1992/0604    
		for (port=offset; port<offset+n; port++) 
1993/1116    
		for (cp = buf, port=offset; port<offset+n; port++) 
1992/0528    
			*cp++ = inb(port); 
		return n; 
1993/1116    
	case Qvgaportw: 
		if((n & 01) || (offset & 01)) 
			error(Ebadarg); 
		n /= 2; 
		for (sp = buf, port=offset; port<offset+n; port+=2) 
			*sp++ = ins(port); 
		return n*2; 
1992/0527    
	} 
1992/1119    
	error(Eperm); 
	return 0; 
1993/0915/sys/src/9/pc/devvga.c:245,2501993/1116/sys/src/9/pc/devvga.c:297,303
1992/1119    
	char cbuf[64], *cp; 
	Vgacard *vp; 
	int port, maxx, maxy, ldepth; 
1993/1116    
	ushort *sp; 
1992/0528    
 
1992/0527    
	switch(c->qid.path&~CHDIR){ 
	case Qdir: 
1993/0915/sys/src/9/pc/devvga.c:294,3131993/1116/sys/src/9/pc/devvga.c:347,365
1992/1119    
		|| maxx > 1280 || maxy > 1024 
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
1992/1216    
		cursoroff(1); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1992/1216    
		cursoron(1); 
1992/0603    
		return n; 
1992/0528    
	case Qvgaport: 
1992/0603    
		cp = buf; 
1992/1217    
		/* 
1992/1119    
		if (offset + n >= 0x8000 || offset < 0x300) 
1992/0528    
			error(Ebadarg); 
1992/1217    
		*/ 
1992/0603    
		for (port=offset; port<offset+n; port++) { 
1993/1116    
		for (cp = buf, port=offset; port<offset+n; port++) 
1992/0528    
			outb(port, *cp++); 
1992/0603    
		} 
1992/0604    
		return n; 
1993/1116    
	case Qvgaportw: 
		if((n & 01) || (offset & 01)) 
			error(Ebadarg); 
		n /= 2; 
		for (sp = buf, port=offset; port<offset+n; port+=2) 
			outs(port, *sp++); 
		return n*2; 
1992/0527    
	} 
1992/1119    
	error(Eperm); 
	return 0; 
1993/0915/sys/src/9/pc/devvga.c:327,3381993/1116/sys/src/9/pc/devvga.c:379,725
1992/0527    
	error(Eperm); 
} 
1992/1119    
 
1993/0108    
uchar 
1993/1116    
/* 
 *  start the screen in CGA mode.  Create the fonts for VGA. 
 */ 
void 
screeninit(void) 
{ 
	int i; 
	ulong *l; 
 
	/* 
	 *  swizzle the font longs.  we do both byte and bit swizzling 
	 *  since the font is initialized with big endian longs. 
	 */ 
	defont = &defont0; 
	l = defont->bits->base; 
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++) 
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24); 
	pixreverse((uchar*)defont->bits->base, 
		defont->bits->width*BY2WD*Dy(defont->bits->r), 0); 
 
	/* 
	 *  start in CGA mode 
	 */ 
	cga = 1; 
	crout(0x0a, 0xff);		/* turn off cursor */ 
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT); 
} 
 
/* 
 *  reconfigure screen shape 
 */ 
static void 
setscreen(int maxx, int maxy, int ldepth) 
{ 
	int len, vgamaxy, width, i, x, s; 
	ulong *p, *oldp; 
 
	if(ldepth == 3) 
		setmode(&mode13); 
	else 
		setmode(&mode12); 
 
	/* allocate a new soft bitmap area */ 
	width = (maxx*(1<<ldepth))/32; 
	len = width * BY2WD * maxy; 
	p = xalloc(len); 
	if(p == 0) 
		error(Enobitstore); 
	memset(p, 0xff, len); 
	mbb = NULLMBB; 
 
	/* 
	 *  zero hard screen and setup a bitmap for the new size 
	 */ 
	if(ldepth == 3) 
		vgascreen.ldepth = 3; 
	else 
		vgascreen.ldepth = 0; 
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32; 
	if(maxy > (64*1024)/(vgascreen.width*BY2WD)) 
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD); 
	else 
		vgamaxy = maxy; 
	vgascreen.base = (void*)SCREENMEM; 
	vgascreen.r.min = Pt(0, 0); 
	vgascreen.r.max = Pt(maxx, vgamaxy); 
	vgascreen.clipr = vgascreen.r; 
 
	/* 
	 *  setup new soft screen, free memory for old screen 
	 */ 
	oldp = gscreen.base; 
	s = splhi(); 
	gscreen.ldepth = ldepth; 
	gscreen.width = width; 
	gscreen.r.min = Pt(0, 0); 
	gscreen.r.max = Pt(maxx, maxy); 
	gscreen.clipr = gscreen.r; 
	gscreen.base = p; 
	splx(s); 
	if(oldp) 
		xfree(oldp); 
 
	/* 
	 *  default color map 
	 */ 
	switch(ldepth){ 
	case 3: 
		for(i = 0; i < 256; i++) 
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1)); 
		break; 
	case 2: 
	case 1: 
	case 0: 
		gscreen.ldepth = 3; 
		for(i = 0; i < 16; i++){ 
			x = x6to32((i*63)/15); 
			setcolor(i, x, x, x); 
		} 
		gscreen.ldepth = ldepth; 
		break; 
	} 
	cga = 0; 
 
	/* 
	 * display white window 
	 */ 
	mbb = gscreen.r; 
	screenupdate(); 
 
	/* 
	 *  set up inset system window 
	 */ 
	h = defont0.height; 
	w = defont0.info[' '].width; 
 
	window.min = Pt(50, 50); 
	window.max = add(window.min, Pt(10+w*64, 10+h*24)); 
 
	gbitblt(&gscreen, window.min, &gscreen, window, Zero); 
	window = inset(window, 5); 
	cursor = window.min; 
	window.max.y = window.min.y+((window.max.y-window.min.y)/h)*h; 
	hwcurs = 0; 
 
	mbb = gscreen.r; 
	screenupdate(); 
} 
 
/* 
 * paste tile into soft screen. 
 * tile is at location r, first pixel in *data.  tl is length of scan line to insert, 
 * l is amount to advance data after each scan line. 
 */ 
void 
screenload(Rectangle r, uchar *data, int tl, int l) 
{ 
	int y, lpart, rpart, mx, m, mr; 
	uchar *q; 
	extern void cursorlock(Rectangle); 
	extern void cursorunlock(void); 
 
	if(!rectclip(&r, gscreen.r) || tl<=0) 
		return; 
	lock(&screenlock); 
	cursorlock(r); 
	screenupdate(); 
	q = gbaddr(&gscreen, r.min); 
	mx = 7>>gscreen.ldepth; 
	lpart = (r.min.x & mx) << gscreen.ldepth; 
	rpart = (r.max.x & mx) << gscreen.ldepth; 
	m = 0xFF >> lpart; 
	mr = 0xFF ^ (0xFF >> rpart); 
	/* may need to do bit insertion on edges */ 
	if(l == 1){	/* all in one byte */ 
		if(rpart) 
			m ^= 0xFF >> rpart; 
		for(y=r.min.y; y<r.max.y; y++){ 
			*q ^= (*data^*q) & m; 
			q += gscreen.width*sizeof(ulong); 
			data += l; 
		} 
	}else if(lpart==0 && rpart==0){	/* easy case */ 
		for(y=r.min.y; y<r.max.y; y++){ 
			memmove(q, data, tl); 
			q += gscreen.width*sizeof(ulong); 
			data += l; 
		} 
	}else if(rpart==0){ 
		for(y=r.min.y; y<r.max.y; y++){ 
			*q ^= (*data^*q) & m; 
			if(tl > 1) 
				memmove(q+1, data+1, tl-1); 
			q += gscreen.width*sizeof(ulong); 
			data += l; 
		} 
	}else if(lpart == 0){ 
		for(y=r.min.y; y<r.max.y; y++){ 
			if(tl > 1) 
				memmove(q, data, tl-1); 
			q[tl-1] ^= (data[tl-1]^q[tl-1]) & mr; 
			q += gscreen.width*sizeof(ulong); 
			data += l; 
		} 
	}else for(y=r.min.y; y<r.max.y; y++){ 
			*q ^= (*data^*q) & m; 
			if(l > 2) 
				memmove(q+1, data+1, tl-2); 
			q[tl-1] ^= (data[tl-1]^q[l-1]) & mr; 
			q += gscreen.width*sizeof(ulong); 
			data += l; 
		} 
	mbbrect(r); 
	screenupdate(); 
	cursorunlock(); 
	screenupdate(); 
	unlock(&screenlock); 
} 
 
/* 
 *  copy litte endian soft screen to big endian hard screen 
 */ 
void 
screenupdate(void) 
{ 
	uchar *sp, *hp, *edisp; 
	int y, len, incs, inch, off, page; 
	Rectangle r; 
	void* (*f)(void*, void*, long); 
 
	r = mbb; 
	mbb = NULLMBB; 
 
	if(Dy(r) < 0) 
		return; 
 
	if(r.min.x < 0) 
		r.min.x = 0; 
	if(r.min.y < 0) 
		r.min.y = 0; 
	if(r.max.x > gscreen.r.max.x) 
		r.max.x = gscreen.r.max.x; 
	if(r.max.y > gscreen.r.max.y) 
		r.max.y = gscreen.r.max.y; 
 
	incs = gscreen.width * BY2WD; 
	inch = vgascreen.width * BY2WD; 
 
	switch(gscreen.ldepth){ 
	case 0: 
		r.min.x &= ~15;		/* 16 pixel allignment for l0update() */ 
		f = l0update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 16 bit allignment for l0update() */ 
		break; 
	case 1: 
		r.min.x &= ~15;		/* 8 pixel allignment for l1update() */ 
		f = l1update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 8 pixel allignment for l1update() */ 
		break; 
	case 2: 
		r.min.x &= ~7;		/* 8 pixel allignment for l2update() */ 
		f = l2update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		break; 
	case 3: 
		f = memmove; 
		len = r.max.x - r.min.x; 
		break; 
	default: 
		return; 
	} 
	if(len < 1) 
		return; 
 
	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth)); 
	page = off>>16; 
	off &= (1<<16)-1; 
	hp = ((uchar*)vgascreen.base) + off; 
	off = r.min.y * gscreen.width * BY2WD 
		+ (r.min.x>>(3 - gscreen.ldepth)); 
	sp = ((uchar*)gscreen.base) + off; 
 
	edisp = ((uchar*)vgascreen.base) + 64*1024; 
	vgacard->setpage(page); 
	for(y = r.min.y; y < r.max.y; y++){ 
		if(hp + inch < edisp){ 
			f(hp, sp, len); 
			sp += incs; 
			hp += inch; 
		} else { 
			off = edisp - hp; 
			if(off <= len){ 
				if(off > 0) 
					f(hp, sp, off); 
				vgacard->setpage(++page); 
				if(len - off > 0) 
					f(vgascreen.base, sp+off, len - off); 
			} else { 
				f(hp, sp, len); 
				vgacard->setpage(++page); 
			} 
			sp += incs; 
			hp += inch - 64*1024; 
		} 
	} 
} 
 
void 
screenputs(char *s, int n) 
{ 
	int i; 
	Rune r; 
	char buf[4]; 
 
	if(cga) { 
		cgascreenputs(s, n); 
		return; 
	} 
 
	if((getstatus() & IFLAG) == 0) { 
		/* don't deadlock trying to print in interrupt */ 
		if(!canlock(&screenlock)) 
			return;	 
	} else 
		lock(&screenlock); 
 
	while(n > 0) { 
		i = chartorune(&r, s); 
		if(i == 0){ 
			s++; 
			--n; 
			continue; 
		} 
		memmove(buf, s, i); 
		buf[i] = 0; 
		n -= i; 
		s += i; 
		screenputc(buf); 
	} 
	if(isscroll) { 
		mbb = window; 
		isscroll = 0; 
	} 
 
	screenupdate(); 
	unlock(&screenlock); 
} 
 
/* 
 *  accessing registers 
 */ 
static uchar 
1993/0108    
srin(int i) { 
	outb(SRX, i); 
	return inb(SR); 
} 
1992/1119    
void 
1993/1116    
static void 
1992/1119    
genout(int reg, int val) 
{ 
	if(reg == 0) 
1993/0915/sys/src/9/pc/devvga.c:340,3581993/1116/sys/src/9/pc/devvga.c:727,745
1992/1119    
	else if (reg == 1) 
		outb(EFCW, val); 
} 
void 
1993/1116    
static void 
1992/1119    
srout(int reg, int val) 
{ 
	outb(SRX, reg); 
	outb(SR, val); 
} 
void 
1993/1116    
static void 
1992/1119    
grout(int reg, int val) 
{ 
	outb(GRX, reg); 
	outb(GR, val); 
} 
void 
1993/1116    
static void 
1992/1119    
arout(int reg, int val) 
{ 
	inb(0x3DA); 
1993/0915/sys/src/9/pc/devvga.c:366,3731993/1116/sys/src/9/pc/devvga.c:753,759
1992/1119    
		outb(ARW, val); 
	} 
} 
                 
void 
1993/1116    
static void 
1992/1119    
crout(int reg, int val) 
{ 
	outb(CRX, reg); 
1993/0915/sys/src/9/pc/devvga.c:374,3801993/1116/sys/src/9/pc/devvga.c:760,766
1992/1119    
	outb(CR, val); 
} 
 
void 
1993/1116    
static void 
1992/1119    
setmode(VGAmode *v) 
{ 
	int i; 
1993/0915/sys/src/9/pc/devvga.c:405,4121993/1116/sys/src/9/pc/devvga.c:791,799
1992/1119    
	srout(1, v->sequencer[1]); 
} 
 
void 
getmode(VGAmode *v) { 
1993/1116    
static void 
getmode(VGAmode *v) 
{ 
1992/1119    
	int i; 
	v->general[0] = inb(0x3cc); 
	v->general[1] = inb(0x3ca); 
1993/0915/sys/src/9/pc/devvga.c:429,4361993/1116/sys/src/9/pc/devvga.c:816,824
1992/1119    
	} 
} 
 
void 
printmode(VGAmode *v) { 
1993/1116    
static void 
printmode(VGAmode *v) 
{ 
1992/1119    
	int i; 
	print("g %2.2x %2x\n", 
		v->general[0], v->general[1]); 
1993/0915/sys/src/9/pc/devvga.c:480,6041993/1116/sys/src/9/pc/devvga.c:868,886
1992/1119    
	return y; 
} 
 
1993/1116    
/* 
 *  just in case we have one 
 */ 
1992/1119    
void 
setscreen(int maxx, int maxy, int ldepth) 
1993/1116    
hwcursset(ulong *s, ulong *c, int ox, int oy) 
1992/1119    
{ 
1993/0102    
	int len, vgamaxy, width, i, x, s; 
1993/0103    
	ulong *p, *oldp; 
1992/1119    
                 
	if(ldepth == 3) 
		setmode(&mode13); 
	else 
		setmode(&mode12); 
                 
	/* allocate a new soft bitmap area */ 
	width = (maxx*(1<<ldepth))/32; 
	len = width * BY2WD * maxy; 
	p = xalloc(len); 
	if(p == 0) 
1993/0102    
		error(Enobitstore); 
1993/0115    
	memset(p, 0xff, len); 
1992/1119    
	mbb = NULLMBB; 
                 
	/* 
	 *  zero hard screen and setup a bitmap for the new size 
	 */ 
	if(ldepth == 3) 
		vgascreen.ldepth = 3; 
	else 
		vgascreen.ldepth = 0; 
	vgascreen.width = (maxx*(1<<vgascreen.ldepth))/32; 
	if(maxy > (64*1024)/(vgascreen.width*BY2WD)) 
		vgamaxy = (64*1024)/(vgascreen.width*BY2WD); 
	else 
		vgamaxy = maxy; 
	vgascreen.base = (void*)SCREENMEM; 
	vgascreen.r.min = Pt(0, 0); 
	vgascreen.r.max = Pt(maxx, vgamaxy); 
	vgascreen.clipr = vgascreen.r; 
                 
	/* 
	 *  setup new soft screen, free memory for old screen 
	 */ 
1993/0102    
	oldp = gscreen.base; 
	s = splhi(); 
1992/1119    
	gscreen.ldepth = ldepth; 
	gscreen.width = width; 
	gscreen.r.min = Pt(0, 0); 
	gscreen.r.max = Pt(maxx, maxy); 
	gscreen.clipr = gscreen.r; 
1993/0103    
	gscreen.base = p; 
1993/0102    
	splx(s); 
	if(oldp) 
		xfree(oldp); 
1992/1119    
                 
	/* 
	 *  set depth of cursor backup area 
	 */ 
	bitdepth(); 
                 
	/* 
	 *  set string pointer to upper left 
	 */ 
	out.pos.x = MINX; 
	out.pos.y = 0; 
	out.bwid = defont0.info[' '].width; 
                 
	/* 
	 *  default color map 
	 */ 
	switch(ldepth){ 
	case 3: 
		for(i = 0; i < 256; i++) 
			setcolor(i, x3to32(i>>5), x3to32(i>>2), x3to32(i<<1)); 
		break; 
	case 2: 
	case 1: 
	case 0: 
		gscreen.ldepth = 3; 
		for(i = 0; i < 16; i++){ 
			x = x6to32((i*63)/15); 
			setcolor(i, x, x, x); 
		} 
		gscreen.ldepth = ldepth; 
		break; 
	} 
1993/0409    
	bbinit(); 
1992/1119    
	cga = 0; 
1992/1216    
                 
	/* 
	 * clear screen 
	 */ 
	mbb = gscreen.r; 
	vgaupdate(); 
1993/1116    
	USED(s, c, ox, oy); 
1992/1119    
} 
 
void 
screeninit(void) 
1993/1116    
hwcursmove(int x, int y) 
1992/1119    
{ 
	int i; 
	ulong *l; 
                 
	/* 
	 *  arrow is defined as a big endian 
	 */ 
	pixreverse(arrow.set, 2*16, 0); 
	pixreverse(arrow.clr, 2*16, 0); 
                 
	/* 
	 *  swizzle the font longs.  we do both byte and bit swizzling 
	 *  since the font is initialized with big endian longs. 
	 */ 
	defont = &defont0; 
	l = defont->bits->base; 
	for(i = defont->bits->width*Dy(defont->bits->r); i > 0; i--, l++) 
		*l = (*l<<24) | ((*l>>8)&0x0000ff00) | ((*l<<8)&0x00ff0000) | (*l>>24); 
	pixreverse((uchar*)defont->bits->base, 
		defont->bits->width*BY2WD*Dy(defont->bits->r), 0); 
                 
	cga = 1; 
	crout(0x0a, 0xff);		/* turn off cursor */ 
	memset(CGASCREEN, 0, CGAWIDTH*CGAHEIGHT); 
1993/1116    
	USED(x, y); 
1992/1119    
} 
 
/* 
1993/0915/sys/src/9/pc/devvga.c:615,6211993/1116/sys/src/9/pc/devvga.c:897,902
1992/1119    
		mbb.max.x = r.max.x; 
	if (r.max.y > mbb.max.y) 
		mbb.max.y = r.max.y; 
1992/1209    
	mousescreenupdate(); 
1992/1119    
} 
 
void 
1993/0915/sys/src/9/pc/devvga.c:639,6471993/1116/sys/src/9/pc/devvga.c:920,932
1992/1119    
{ 
	USED(page); 
1992/1216    
} 
1993/1116    
 
1993/0106    
/* 
 * The following code is unproven: we haven't got the 
 * ATI stuff to work yet. 
1993/1116    
 * Extended registers can be read with inb(), but must be 
 * written with outs(). The index must be written each time 
 * before the register is accessed. 
 * The page bits are spread across registers 0xAE and 0xB2. 
 * This can go away when we use the memory aperture. 
1993/0106    
 */ 
1992/1216    
static void 
1993/0106    
atipage(int page) 
1993/0915/sys/src/9/pc/devvga.c:650,6601993/1116/sys/src/9/pc/devvga.c:935,949
1993/0106    
	ushort extreg = *((ushort *)0x800C0010); 
	uchar v; 
 
	outb(extreg, 0xb2); 
	v = (inb(extreg+1) & 0xe1) | (page<<1); 
	outb(extreg, 0xb2); 
	outb(extreg+1, v); 
1993/1116    
	outb(extreg, 0xAE); 
	v = (inb(extreg+1) & 0xFC)|((page>>4) & 0x03); 
	outs(extreg, (v<<8)|0xAE); 
 
	outb(extreg, 0xB2); 
	v = (inb(extreg+1) & 0xE1)|((page & 0x0F)<<1); 
	outs(extreg, (v<<8)|0xB2); 
1993/0106    
} 
1993/1116    
 
1993/0206    
/* 
 * The following assumes that the new mode registers have been selected. 
 */ 
1993/0915/sys/src/9/pc/devvga.c:679,7931993/1116/sys/src/9/pc/devvga.c:968,983
1993/0915    
	grout(0x9, page<<4); 
1992/1119    
} 
 
/* 
 *  copy litte endian soft screen to big endian hard screen 
 */ 
static void 
vgaupdate(void) 
1993/1116    
void 
mousescreenupdate(void) 
1992/1119    
{ 
	uchar *sp, *hp, *edisp; 
	int y, len, incs, inch, off, page; 
	Rectangle r; 
	void* (*f)(void*, void*, long); 
                 
	r = mbb; 
	mbb = NULLMBB; 
                 
	if(Dy(r) < 0) 
1993/1116    
	if(canlock(&screenlock) == 0) 
1992/1119    
		return; 
 
	if(r.min.x < 0) 
		r.min.x = 0; 
	if(r.min.y < 0) 
		r.min.y = 0; 
	if(r.max.x > gscreen.r.max.x) 
		r.max.x = gscreen.r.max.x; 
	if(r.max.y > gscreen.r.max.y) 
		r.max.y = gscreen.r.max.y; 
                 
	incs = gscreen.width * BY2WD; 
	inch = vgascreen.width * BY2WD; 
                 
	switch(gscreen.ldepth){ 
	case 0: 
1992/1121    
		r.min.x &= ~15;		/* 16 pixel allignment for l0update() */ 
1992/1119    
		f = l0update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
			len++;		/* 16 bit allignment for l0update() */ 
		break; 
	case 1: 
1992/1121    
		r.min.x &= ~15;		/* 8 pixel allignment for l1update() */ 
1992/1119    
		f = l1update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		if(len & 1) 
1992/1121    
			len++;		/* 8 pixel allignment for l1update() */ 
1992/1119    
		break; 
	case 2: 
1992/1121    
		r.min.x &= ~7;		/* 8 pixel allignment for l2update() */ 
1992/1119    
		f = l2update; 
		len = (r.max.x + 7)/8 - r.min.x/8; 
		break; 
	case 3: 
		f = memmove; 
		len = r.max.x - r.min.x; 
		break; 
	default: 
		return; 
	} 
	if(len < 1) 
		return; 
                 
	off = r.min.y * vgascreen.width * BY2WD + (r.min.x>>(3 - vgascreen.ldepth)); 
	page = off>>16; 
	off &= (1<<16)-1; 
	hp = ((uchar*)vgascreen.base) + off; 
1992/1121    
	off = r.min.y * gscreen.width * BY2WD 
		+ (r.min.x>>(3 - gscreen.ldepth)); 
1992/1119    
	sp = ((uchar*)gscreen.base) + off; 
                 
	edisp = ((uchar*)vgascreen.base) + 64*1024; 
	vgacard->setpage(page); 
	for(y = r.min.y; y < r.max.y; y++){ 
		if(hp + inch < edisp){ 
			f(hp, sp, len); 
			sp += incs; 
			hp += inch; 
		} else { 
			off = edisp - hp; 
			if(off <= len){ 
				if(off > 0) 
					f(hp, sp, off); 
				vgacard->setpage(++page); 
				if(len - off > 0) 
					f(vgascreen.base, sp+off, len - off); 
			} else { 
				f(hp, sp, len); 
				vgacard->setpage(++page); 
			} 
			sp += incs; 
			hp += inch - 64*1024; 
		} 
	} 
1993/1116    
	screenupdate(); 
	unlock(&screenlock); 
1992/1119    
} 
 
void 
screenupdate(void) 
{ 
	lock(&vgalock); 
	vgaupdate(); 
	unlock(&vgalock); 
} 
                 
void 
mousescreenupdate(void) 
{ 
	if(canlock(&vgalock)){ 
		vgaupdate(); 
		unlock(&vgalock); 
	} 
} 
                 
static void 
cgascreenputc(int c) 
{ 
1993/0915/sys/src/9/pc/devvga.c:818,8241993/1116/sys/src/9/pc/devvga.c:1008,1014
1992/1119    
	} 
} 
 
void 
1993/1116    
static void 
1992/1119    
cgascreenputs(char *s, int n) 
{ 
	while(n-- > 0) 
1993/0915/sys/src/9/pc/devvga.c:825,8951993/1116/sys/src/9/pc/devvga.c:1015,1067
1992/1119    
		cgascreenputc(*s++); 
} 
 
void 
screenputnl(void) 
1993/1116    
static void 
scroll(void) 
1992/1119    
{ 
1993/1116    
	int o; 
1992/1119    
	Rectangle r; 
 
	out.pos.x = MINX; 
	out.pos.y += defont0.height; 
	if(out.pos.y > gscreen.r.max.y-defont0.height){ 
		vgaupdate(); 
		out.pos.y = gscreen.r.min.y; 
	} 
	r = Rect(0, out.pos.y, gscreen.r.max.x, out.pos.y+2*defont0.height); 
	gbitblt(&gscreen, r.min, &gscreen, r, flipD[0]); 
	mbbrect(r); 
	vgaupdate(); 
1993/1116    
	o = 5*h; 
	r = Rpt(Pt(window.min.x, window.min.y+o), window.max); 
	gbitblt(&gscreen, window.min, &gscreen, r, S); 
	r = Rpt(Pt(window.min.x, window.max.y-o), window.max); 
	gbitblt(&gscreen, r.min, &gscreen, r, Zero); 
	cursor.y -= o; 
	isscroll = 1; 
1992/1119    
} 
 
void 
screenputs(char *s, int n) 
1993/1116    
static void 
screenputc(char *buf) 
1992/1119    
{ 
	Rune r; 
	int i; 
	char buf[4]; 
	Rectangle rect; 
1993/1116    
	int pos; 
1992/1119    
 
	if(cga) { 
		cgascreenputs(s, n); 
		return; 
	} 
1993/1116    
	mbbpt(cursor); 
	switch(buf[0]) { 
	case '\n': 
		if(cursor.y+h >= window.max.y) 
			scroll(); 
		cursor.y += h; 
		screenputc("\r"); 
		break; 
	case '\r': 
		cursor.x = window.min.x; 
		break; 
	case '\t': 
		pos = (cursor.x-window.min.x)/w; 
		pos = 8-(pos%8); 
		cursor.x += pos*w; 
		break; 
	case '\b': 
		if(cursor.x-w >= window.min.x) 
			cursor.x -= w; 
		break; 
	default: 
		if(cursor.x >= window.max.x-w) 
			screenputc("\n"); 
1992/1119    
 
	while(n > 0){ 
		i = chartorune(&r, s); 
		if(i == 0){ 
			s++; 
			--n; 
			continue; 
		} 
		memmove(buf, s, i); 
		buf[i] = 0; 
		n -= i; 
		s += i; 
		if(r == '\n') 
			screenputnl(); 
		else if(r == '\t'){ 
			out.pos.x += (8-((out.pos.x-MINX)/out.bwid&7))*out.bwid; 
			if(out.pos.x >= gscreen.r.max.x) 
				screenputnl(); 
		}else if(r == '\b'){ 
			if(out.pos.x >= out.bwid+MINX){ 
				out.pos.x -= out.bwid; 
				gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]); 
			} 
			rect.min = Pt(out.pos.x, out.pos.y); 
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); 
			mbbrect(rect); 
		}else{ 
			if(out.pos.x >= gscreen.r.max.x-out.bwid) 
				screenputnl(); 
			rect.min = Pt(out.pos.x, out.pos.y); 
			rect.max = Pt(out.pos.x+out.bwid, out.pos.y+defont0.height); 
			out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]); 
			mbbrect(rect); 
		} 
1993/1116    
		cursor = gsubfstring(&gscreen, cursor, &defont0, buf, S); 
1992/1119    
	} 
	vgaupdate(); 
1993/1116    
	mbbpt(Pt(cursor.x, cursor.y+h)); 
1992/1119    
} 
 
int 
1993/0915/sys/src/9/pc/devvga.c:902,9121993/1116/sys/src/9/pc/devvga.c:1074,1084
1992/1119    
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) 
{ 
	p &= (1<<(1<<gscreen.ldepth))-1; 
	lock(&vgalock); 
1993/1116    
	lock(&screenlock); 
1992/1119    
	*pr = colormap[p][0]; 
	*pg = colormap[p][1]; 
	*pb = colormap[p][2]; 
	unlock(&vgalock); 
1993/1116    
	unlock(&screenlock); 
1992/1119    
} 
 
int 
1993/0915/sys/src/9/pc/devvga.c:913,9191993/1116/sys/src/9/pc/devvga.c:1085,1091
1992/1119    
setcolor(ulong p, ulong r, ulong g, ulong b) 
{ 
	p &= (1<<(1<<gscreen.ldepth))-1; 
	lock(&vgalock); 
1993/1116    
	lock(&screenlock); 
1992/1119    
	colormap[p][0] = r; 
	colormap[p][1] = g; 
	colormap[p][2] = b; 
1993/0915/sys/src/9/pc/devvga.c:921,9701993/1116/sys/src/9/pc/devvga.c:1093,1103
1992/1119    
	outb(CM, r>>(32-6)); 
	outb(CM, g>>(32-6)); 
	outb(CM, b>>(32-6)); 
	unlock(&vgalock); 
1993/1116    
	unlock(&screenlock); 
1992/1119    
	return ~0; 
} 
 
1993/0915    
void 
hwcursset(ulong *s, ulong *c, int ox, int oy) 
1992/1119    
{ 
	USED(s, c, ox, oy); 
} 
                 
1993/0915    
void 
1992/1119    
hwcursmove(int x, int y) 
{ 
	USED(x, y); 
} 
                 
/* 
 *  a fatter than usual cursor for the safari 
 */ 
Cursor fatarrow = { 
	{ -1, -1 }, 
	{ 
		0xff, 0xff, 0x80, 0x01, 0x80, 0x02, 0x80, 0x0c,  
		0x80, 0x10, 0x80, 0x10, 0x80, 0x08, 0x80, 0x04,  
		0x80, 0x02, 0x80, 0x01, 0x80, 0x02, 0x8c, 0x04,  
		0x92, 0x08, 0x91, 0x10, 0xa0, 0xa0, 0xc0, 0x40,  
	}, 
	{ 
		0x00, 0x00, 0x7f, 0xfe, 0x7f, 0xfc, 0x7f, 0xf0,  
		0x7f, 0xe0, 0x7f, 0xe0, 0x7f, 0xf0, 0x7f, 0xf8,  
		0x7f, 0xfc, 0x7f, 0xfe, 0x7f, 0xfc, 0x73, 0xf8,  
		0x61, 0xf0, 0x60, 0xe0, 0x40, 0x40, 0x00, 0x00,  
	}, 
}; 
                 
void 
bigcursor(void) 
{ 
	memmove(&arrow, &fatarrow, sizeof(fatarrow)); 
	pixreverse(arrow.set, 2*16, 0); 
	pixreverse(arrow.clr, 2*16, 0); 
} 
                 
/* 
 *  Table for separating and reversing bits in a ldepth 1 bitmap. 
 *  This aids in coverting a little endian ldepth 1 bitmap into the 
 *  2 big-endian ldepth 0 bitmaps used for the VGA bit planes. 
1993/0915/sys/src/9/pc/devvga.c:1063,10651993/1116/sys/src/9/pc/devvga.c:1196,1328
1992/1119    
 0x1010101, 0x1010103, 0x1010301, 0x1010303, 0x1030101, 0x1030103, 0x1030301, 0x1030303, 
 0x3010101, 0x3010103, 0x3010301, 0x3010303, 0x3030101, 0x3030103, 0x3030301, 0x3030303, 
}; 
1993/1116    
 
/* 
 *  reverse pixels into little endian order 
 */ 
uchar revtab0[] = { 
 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 
 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 
 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 
 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 
 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 
 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 
 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 
 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 
 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 
 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 
 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 
 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 
 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 
 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 
 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 
 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 
 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 
 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 
 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 
 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 
 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 
 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 
 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 
 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 
 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 
 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 
 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 
 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 
 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 
 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 
 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 
 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff, 
}; 
uchar revtab1[] = { 
 0x00, 0x40, 0x80, 0xc0, 0x10, 0x50, 0x90, 0xd0, 
 0x20, 0x60, 0xa0, 0xe0, 0x30, 0x70, 0xb0, 0xf0, 
 0x04, 0x44, 0x84, 0xc4, 0x14, 0x54, 0x94, 0xd4, 
 0x24, 0x64, 0xa4, 0xe4, 0x34, 0x74, 0xb4, 0xf4, 
 0x08, 0x48, 0x88, 0xc8, 0x18, 0x58, 0x98, 0xd8, 
 0x28, 0x68, 0xa8, 0xe8, 0x38, 0x78, 0xb8, 0xf8, 
 0x0c, 0x4c, 0x8c, 0xcc, 0x1c, 0x5c, 0x9c, 0xdc, 
 0x2c, 0x6c, 0xac, 0xec, 0x3c, 0x7c, 0xbc, 0xfc, 
 0x01, 0x41, 0x81, 0xc1, 0x11, 0x51, 0x91, 0xd1, 
 0x21, 0x61, 0xa1, 0xe1, 0x31, 0x71, 0xb1, 0xf1, 
 0x05, 0x45, 0x85, 0xc5, 0x15, 0x55, 0x95, 0xd5, 
 0x25, 0x65, 0xa5, 0xe5, 0x35, 0x75, 0xb5, 0xf5, 
 0x09, 0x49, 0x89, 0xc9, 0x19, 0x59, 0x99, 0xd9, 
 0x29, 0x69, 0xa9, 0xe9, 0x39, 0x79, 0xb9, 0xf9, 
 0x0d, 0x4d, 0x8d, 0xcd, 0x1d, 0x5d, 0x9d, 0xdd, 
 0x2d, 0x6d, 0xad, 0xed, 0x3d, 0x7d, 0xbd, 0xfd, 
 0x02, 0x42, 0x82, 0xc2, 0x12, 0x52, 0x92, 0xd2, 
 0x22, 0x62, 0xa2, 0xe2, 0x32, 0x72, 0xb2, 0xf2, 
 0x06, 0x46, 0x86, 0xc6, 0x16, 0x56, 0x96, 0xd6, 
 0x26, 0x66, 0xa6, 0xe6, 0x36, 0x76, 0xb6, 0xf6, 
 0x0a, 0x4a, 0x8a, 0xca, 0x1a, 0x5a, 0x9a, 0xda, 
 0x2a, 0x6a, 0xaa, 0xea, 0x3a, 0x7a, 0xba, 0xfa, 
 0x0e, 0x4e, 0x8e, 0xce, 0x1e, 0x5e, 0x9e, 0xde, 
 0x2e, 0x6e, 0xae, 0xee, 0x3e, 0x7e, 0xbe, 0xfe, 
 0x03, 0x43, 0x83, 0xc3, 0x13, 0x53, 0x93, 0xd3, 
 0x23, 0x63, 0xa3, 0xe3, 0x33, 0x73, 0xb3, 0xf3, 
 0x07, 0x47, 0x87, 0xc7, 0x17, 0x57, 0x97, 0xd7, 
 0x27, 0x67, 0xa7, 0xe7, 0x37, 0x77, 0xb7, 0xf7, 
 0x0b, 0x4b, 0x8b, 0xcb, 0x1b, 0x5b, 0x9b, 0xdb, 
 0x2b, 0x6b, 0xab, 0xeb, 0x3b, 0x7b, 0xbb, 0xfb, 
 0x0f, 0x4f, 0x8f, 0xcf, 0x1f, 0x5f, 0x9f, 0xdf, 
 0x2f, 0x6f, 0xaf, 0xef, 0x3f, 0x7f, 0xbf, 0xff, 
}; 
uchar revtab2[] = { 
 0x00, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 
 0x80, 0x90, 0xa0, 0xb0, 0xc0, 0xd0, 0xe0, 0xf0, 
 0x01, 0x11, 0x21, 0x31, 0x41, 0x51, 0x61, 0x71, 
 0x81, 0x91, 0xa1, 0xb1, 0xc1, 0xd1, 0xe1, 0xf1, 
 0x02, 0x12, 0x22, 0x32, 0x42, 0x52, 0x62, 0x72, 
 0x82, 0x92, 0xa2, 0xb2, 0xc2, 0xd2, 0xe2, 0xf2, 
 0x03, 0x13, 0x23, 0x33, 0x43, 0x53, 0x63, 0x73, 
 0x83, 0x93, 0xa3, 0xb3, 0xc3, 0xd3, 0xe3, 0xf3, 
 0x04, 0x14, 0x24, 0x34, 0x44, 0x54, 0x64, 0x74, 
 0x84, 0x94, 0xa4, 0xb4, 0xc4, 0xd4, 0xe4, 0xf4, 
 0x05, 0x15, 0x25, 0x35, 0x45, 0x55, 0x65, 0x75, 
 0x85, 0x95, 0xa5, 0xb5, 0xc5, 0xd5, 0xe5, 0xf5, 
 0x06, 0x16, 0x26, 0x36, 0x46, 0x56, 0x66, 0x76, 
 0x86, 0x96, 0xa6, 0xb6, 0xc6, 0xd6, 0xe6, 0xf6, 
 0x07, 0x17, 0x27, 0x37, 0x47, 0x57, 0x67, 0x77, 
 0x87, 0x97, 0xa7, 0xb7, 0xc7, 0xd7, 0xe7, 0xf7, 
 0x08, 0x18, 0x28, 0x38, 0x48, 0x58, 0x68, 0x78, 
 0x88, 0x98, 0xa8, 0xb8, 0xc8, 0xd8, 0xe8, 0xf8, 
 0x09, 0x19, 0x29, 0x39, 0x49, 0x59, 0x69, 0x79, 
 0x89, 0x99, 0xa9, 0xb9, 0xc9, 0xd9, 0xe9, 0xf9, 
 0x0a, 0x1a, 0x2a, 0x3a, 0x4a, 0x5a, 0x6a, 0x7a, 
 0x8a, 0x9a, 0xaa, 0xba, 0xca, 0xda, 0xea, 0xfa, 
 0x0b, 0x1b, 0x2b, 0x3b, 0x4b, 0x5b, 0x6b, 0x7b, 
 0x8b, 0x9b, 0xab, 0xbb, 0xcb, 0xdb, 0xeb, 0xfb, 
 0x0c, 0x1c, 0x2c, 0x3c, 0x4c, 0x5c, 0x6c, 0x7c, 
 0x8c, 0x9c, 0xac, 0xbc, 0xcc, 0xdc, 0xec, 0xfc, 
 0x0d, 0x1d, 0x2d, 0x3d, 0x4d, 0x5d, 0x6d, 0x7d, 
 0x8d, 0x9d, 0xad, 0xbd, 0xcd, 0xdd, 0xed, 0xfd, 
 0x0e, 0x1e, 0x2e, 0x3e, 0x4e, 0x5e, 0x6e, 0x7e, 
 0x8e, 0x9e, 0xae, 0xbe, 0xce, 0xde, 0xee, 0xfe, 
 0x0f, 0x1f, 0x2f, 0x3f, 0x4f, 0x5f, 0x6f, 0x7f, 
 0x8f, 0x9f, 0xaf, 0xbf, 0xcf, 0xdf, 0xef, 0xff, 
}; 
 
void 
pixreverse(uchar *p, int len, int ldepth) 
{ 
	uchar *e; 
	uchar *tab; 
 
	switch(ldepth){ 
	case 0: 
		tab = revtab0; 
		break; 
	case 1: 
		tab = revtab1; 
		break; 
	case 2: 
		tab = revtab2; 
		break; 
	default: 
		return; 
	} 
 
	for(e = p + len; p < e; p++) 
		*p = tab[*p]; 
} 
1993/1116/sys/src/9/pc/devvga.c:33,381993/1117/sys/src/9/pc/devvga.c:33,39 (short | long)
1992/1119    
 
/* imported */ 
extern	GSubfont defont0; 
1993/1117    
extern Cursor arrow; 
1992/1119    
 
/* exported */ 
GSubfont *defont; 
1993/1116/sys/src/9/pc/devvga.c:347,3531993/1117/sys/src/9/pc/devvga.c:348,356
1992/1119    
		|| maxx > 1280 || maxy > 1024 
		|| ldepth > 3 || ldepth < 0) 
1992/0603    
			error(Ebadarg); 
1993/1117    
		cursoroff(1); 
1992/1119    
		setscreen(maxx, maxy, ldepth); 
1993/1117    
		cursoron(1); 
1992/0603    
		return n; 
1992/0528    
	case Qvgaport: 
1993/1116    
		for (cp = buf, port=offset; port<offset+n; port++) 
1993/1116/sys/src/9/pc/devvga.c:389,3941993/1117/sys/src/9/pc/devvga.c:392,403
1993/1116    
	ulong *l; 
 
	/* 
1993/1117    
	 *  arrow is defined as a big endian 
	 */ 
	pixreverse(arrow.set, 2*16, 0); 
	pixreverse(arrow.clr, 2*16, 0); 
 
	/* 
1993/1116    
	 *  swizzle the font longs.  we do both byte and bit swizzling 
	 *  since the font is initialized with big endian longs. 
	 */ 
1993/1116/sys/src/9/pc/devvga.c:1104,11101993/1117/sys/src/9/pc/devvga.c:1113,1119
1992/1119    
 * 
 *	if the bits in uchar x are labeled 
 *		76543210 
 *	then l1revsep[x] yields a ushort with bits 
1993/1117    
 *	then l1revsep[x] yields a ulong with bits 
1992/1119    
 *		________1357________0246 
 *	where _ represents a bit whose value is 0. 
 * 
1993/1116/sys/src/9/pc/devvga.c:1154,11601993/1117/sys/src/9/pc/devvga.c:1163,1169
1992/1119    
 * 
 *	if the bits in uchar x are labeled 
 *		76543210 
 *	then l1revsep[x] yields a ushort with bits 
1993/1117    
 *	then l1revsep[x] yields a ulongt with bits 
1992/1119    
 *		______37______26______15______04 
 *	where _ represents a bit whose value is 0. 
 * 
1993/1116/sys/src/9/pc/devvga.c:1198,12041993/1117/sys/src/9/pc/devvga.c:1207,1213
1992/1119    
}; 
1993/1116    
 
/* 
 *  reverse pixels into little endian order 
1993/1117    
 *  reverse pixels into little endian order (also used by l0update) 
1993/1116    
 */ 
uchar revtab0[] = { 
 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 
1993/1117/sys/src/9/pc/devvga.c:518,5261993/1217/sys/src/9/pc/devvga.c:518,526 (short | long)
1993/1116    
} 
 
/* 
 * paste tile into soft screen. 
 * tile is at location r, first pixel in *data.  tl is length of scan line to insert, 
 * l is amount to advance data after each scan line. 
1993/1217    
 *   paste tile into soft screen. 
 *   tile is at location r, first pixel in *data.  tl is length of scan line to insert, 
 *   l is amount to advance data after each scan line. 
1993/1116    
 */ 
void 
screenload(Rectangle r, uchar *data, int tl, int l) 
1993/1117/sys/src/9/pc/devvga.c:588,5941993/1217/sys/src/9/pc/devvga.c:588,594
1993/1116    
} 
 
/* 
 *  copy litte endian soft screen to big endian hard screen 
1993/1217    
 *  copy little endian soft screen to big endian hard screen 
1993/1116    
 */ 
void 
screenupdate(void) 
Too many diffs (26 > 25). Stopping.


source code copyright © 1990-2005 Lucent Technologies; see license
Plan 9 distribution
comments to russ cox (rsc@swtch.com)