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

1992/1107/pc/vga.c (diff list | history)

pc/vga.c on 1991/0723
1991/0723    
#include	"u.h" 
1992/0321    
#include	"../port/lib.h" 
1991/0723    
#include	"mem.h" 
#include	"dat.h" 
#include	"fns.h" 
#include	"io.h" 
 
1991/0730    
#include	<libg.h> 
#include	<gnot.h> 
#include	"screen.h" 
1992/0528    
#include	"vga.h" 
1991/0730    
 
#define	MINX	8 
 
1992/0208    
extern	GSubfont	defont0; 
GSubfont		*defont; 
1991/0730    
 
struct{ 
	Point	pos; 
	int	bwid; 
}out; 
 
1992/1106    
int islittle = 1;		/* little endian bit ordering in bytes */ 
 
extern Cursor arrow; 
extern uchar cswizzle[256]; 
 
 
1991/0730    
/* 
 *  screen dimensions 
 */ 
1992/0502    
#define MAXX	640 
#define MAXY	480 
1991/0730    
 
1992/1106    
/* 
 *  'soft' screen bitmap 
 */ 
GBitmap	gscreen; 
GBitmap	vgascreen; 
1991/0730    
 
1991/1113    
typedef struct VGAmode	VGAmode; 
struct VGAmode 
{ 
1992/0423    
	uchar	general[2]; 
1991/1113    
	uchar	sequencer[5]; 
	uchar	crt[0x19]; 
	uchar	graphics[9]; 
	uchar	attribute[0x15]; 
}; 
 
1991/0727    
/* 
1992/1015    
 *  640x480 display, 16 bit color. 
1992/0414    
 */ 
VGAmode mode12 =  
{ 
	/* general */ 
1992/1015    
	0xe7, 0x00, 
1992/0414    
	/* sequence */ 
	0x03, 0x01, 0x0f, 0x00, 0x06, 
	/* crt */ 
1992/1015    
	0x65, 0x4f, 0x50, 0x88, 0x55, 0x9a, 0x09, 0x3e, 
1992/0414    
	0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 
1992/1015    
	0xe8, 0x8b, 0xdf, 0x28, 0x00, 0xe7, 0x04, 0xe3, 
1992/0414    
	0xff, 
	/* graphics */ 
	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x0f, 
	0xff, 
	/* attribute */ 
1992/0418    
	0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 
1992/0423    
	0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x3f, 
1992/1015    
	0x01, 0x10, 0x0f, 0x00, 0x00, 
1992/0414    
}; 
1992/0418    
 
1992/1106    
static Rectangle mbb; 
static Rectangle NULLMBB = {10000, 10000, -10000, -10000}; 
1992/0430    
 
1991/0724    
void 
1991/1113    
genout(int reg, int val) 
{ 
	if(reg == 0) 
		outb(EMISCW, val); 
	else if (reg == 1) 
		outb(EFCW, val); 
} 
void 
1991/0724    
srout(int reg, int val) 
{ 
	outb(SRX, reg); 
	outb(SR, val); 
} 
void 
grout(int reg, int val) 
{ 
	outb(GRX, reg); 
	outb(GR, val); 
} 
1991/0727    
void 
arout(int reg, int val) 
{ 
	inb(0x3DA); 
1992/0423    
	if (reg <= 0xf) { 
		outb(ARW, reg | 0x0); 
		outb(ARW, val); 
		inb(0x3DA); 
		outb(ARW, reg | 0x20); 
	} else { 
		outb(ARW, reg | 0x20); 
		outb(ARW, val); 
	} 
1991/0727    
} 
1992/0423    
 
1991/0727    
void 
crout(int reg, int val) 
{ 
	outb(CRX, reg); 
	outb(CR, val); 
} 
1991/1107    
 
1991/1113    
void 
setmode(VGAmode *v) 
1991/1112    
{ 
1991/1113    
	int i; 
1991/1112    
 
1991/1113    
	for(i = 0; i < sizeof(v->general); i++) 
		genout(i, v->general[i]); 
1991/0928    
 
1991/1113    
	for(i = 0; i < sizeof(v->sequencer); i++) 
		srout(i, v->sequencer[i]); 
1991/0928    
 
1991/1113    
	crout(Cvre, 0);	/* allow writes to CRT registers 0-7 */ 
	for(i = 0; i < sizeof(v->crt); i++) 
		crout(i, v->crt[i]); 
1991/1109    
 
1991/1113    
	for(i = 0; i < sizeof(v->graphics); i++) 
		grout(i, v->graphics[i]); 
1991/1109    
 
1991/1113    
	for(i = 0; i < sizeof(v->attribute); i++) 
		arout(i, v->attribute[i]); 
1991/0928    
} 
 
1991/0727    
void 
1992/0502    
getmode(VGAmode *v) { 
1992/0423    
	int i; 
1992/0502    
	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); 
	} 
} 
1992/0423    
 
1992/0502    
void 
printmode(VGAmode *v) { 
	int i; 
1992/0519    
	print("g %2.2x %2x\n", 
1992/0502    
		v->general[0], v->general[1]); 
 
1992/0519    
	print("s "); 
1992/0502    
	for(i = 0; i < sizeof(v->sequencer); i++) { 
1992/0519    
		print(" %2.2x", v->sequencer[i]); 
1992/0502    
	} 
 
1992/0519    
	print("\nc "); 
1992/0502    
	for(i = 0; i < sizeof(v->crt); i++) { 
1992/0519    
		print(" %2.2x", v->crt[i]); 
1992/0502    
	} 
 
1992/0519    
	print("\ng "); 
1992/0502    
	for(i = 0; i < sizeof(v->graphics); i++) { 
1992/0519    
		print(" %2.2x", v->graphics[i]); 
1992/0502    
	} 
 
1992/0519    
	print("\na "); 
1992/0502    
	for(i = 0; i < sizeof(v->attribute); i++) { 
1992/0519    
		print(" %2.2x", v->attribute[i]); 
1992/0502    
	} 
	print("\n"); 
} 
 
void 
dumpmodes(void) { 
	VGAmode *v; 
	int i; 
 
1992/0423    
	print("general registers: %02x %02x %02x %02x\n", 
		inb(0x3cc), inb(0x3ca), inb(0x3c2), inb(0x3da)); 
 
	print("sequence registers: "); 
	for(i = 0; i < sizeof(v->sequencer); i++) { 
		outb(SRX, i); 
		print(" %02x", inb(SR)); 
	} 
 
	print("\nCRT registers: "); 
	for(i = 0; i < sizeof(v->crt); i++) { 
		outb(CRX, i); 
		print(" %02x", inb(CR)); 
	} 
 
	print("\nGraphics registers: "); 
	for(i = 0; i < sizeof(v->graphics); i++) { 
		outb(GRX, i); 
		print(" %02x", inb(GR)); 
	} 
 
	print("\nAttribute registers: "); 
	for(i = 0; i < sizeof(v->attribute); i++) { 
		inb(0x3DA); 
		outb(ARW, i | 0x20); 
		print(" %02x", inb(ARR)); 
	} 
} 
#endif 
 
void 
1992/1106    
setscreen(int maxx, int maxy, int ldepth) 
1992/0711    
{ 
1992/1106    
	int len; 
 
	mbb = NULLMBB; 
 
	/* 
	 *  zero hard screen 
	 */ 
	memset((void*)SCREENMEM, 0xff, 64*1024); 
	vgascreen.ldepth = 0; 
	vgascreen.base = (void*)SCREENMEM; 
	vgascreen.width = (maxx*(1<<ldepth))/32; 
	vgascreen.r.max = Pt(maxx, maxy); 
	vgascreen.clipr.max = vgascreen.r.max; 
 
	/* 
	 *  setup new soft screen 
	 */ 
	gscreen.ldepth = ldepth; 
	gscreen.width = (maxx*(1<<ldepth))/32; 
1992/0603    
	gscreen.r.max = Pt(maxx, maxy); 
1992/0604    
	gscreen.clipr.max = gscreen.r.max; 
1992/1106    
	len = gscreen.width * 4 * maxy; 
1992/1107    
	gscreen.base = ((ulong*)malloc(len+2*1024))+256; 
	memset((char*)gscreen.base, 0xff, len); 
1992/1106    
 
	/* 
	 *  set string pointer to upper left 
	 */ 
1992/0603    
	out.pos.x = MINX; 
	out.pos.y = 0; 
	out.bwid = defont0.info[' '].width; 
} 
 
void 
1991/0730    
screeninit(void) 
1991/0723    
{ 
1992/0711    
	int i; 
1991/0730    
	ulong *l; 
1991/0723    
 
1992/0527    
	setmode(&mode12); 
1991/0929    
 
1991/0727    
	/* 
1992/1106    
	 *  arrow is defined as a big endian 
1991/0801    
	 */ 
1992/1106    
	bitreverse(arrow.set, 2*16); 
	bitreverse(arrow.clr, 2*16); 
 
	/* 
	 *  swizzle the font longs.  we do both byte and bit swizzling 
	 *  since the font is initialized with big endian longs. 
	 */ 
1991/0801    
	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); 
1992/1106    
	bitreverse((uchar*)defont->bits->base, 
		defont->bits->width*BY2WD*Dy(defont->bits->r)); 
 
	/* 
	 *  set up 'soft' and hard screens 
	 */ 
	if(conf.maxx == 0) 
		conf.maxx = MAXX; 
	if(conf.maxy == 0) 
		conf.maxy = MAXY; 
 
	setscreen(conf.maxx, conf.maxy, conf.ldepth); 
1991/0723    
} 
1991/0727    
 
1992/1106    
/* 
 *  collect changes to the 'soft' screen 
 */ 
1991/0730    
void 
1992/1106    
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; 
	screenupdate(); 
} 
 
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; 
} 
 
void 
1991/1228    
screenputnl(void) 
1991/0730    
{ 
1992/1106    
	Rectangle r; 
 
1991/1228    
	out.pos.x = MINX; 
	out.pos.y += defont0.height; 
	if(out.pos.y > gscreen.r.max.y-defont0.height) 
		out.pos.y = gscreen.r.min.y; 
1992/1106    
	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); 
	screenupdate(); 
1991/0730    
} 
 
1992/0402    
Lock screenlock; 
 
1991/0730    
void 
screenputs(char *s, int n) 
{ 
1991/1228    
	Rune r; 
	int i; 
1992/1106    
	Rectangle rs; 
1991/1228    
	char buf[4]; 
 
1992/1106    
	rs.min = Pt(0, out.pos.y); 
1991/1228    
	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; 
1992/0208    
				gsubfstring(&gscreen, out.pos, defont, " ", flipD[S]); 
1991/1228    
			} 
		}else{ 
			if(out.pos.x >= gscreen.r.max.x-out.bwid) 
				screenputnl(); 
1992/0208    
			out.pos = gsubfstring(&gscreen, out.pos, defont, buf, flipD[S]); 
1991/1228    
		} 
	} 
1992/1106    
	rs.max = Pt(gscreen.r.max.x, out.pos.y+defont0.height); 
	unlock(&screenlock); 
	mbbrect(rs); 
	screenupdate(); 
1991/0730    
} 
 
int 
screenbits(void) 
{ 
	return 1;	/* bits per pixel */ 
} 
 
1992/1106    
 
/* 
 *  copy litte endian soft screen to big endian hard screen 
 */ 
1991/0730    
void 
1992/1106    
screenupdate(void) 
{ 
	uchar *sp, *hp, *se; 
	int y, len, inc; 
1992/1107    
	Rectangle r; 
1992/1106    
 
1992/1107    
	r = mbb; 
	mbb = NULLMBB; 
 
1992/1106    
	if(Dy(r) < 0) 
		return; 
 
1992/1107    
	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; 
 
1992/1106    
	sp = (uchar*)gaddr(&gscreen, r.min); 
	hp = (uchar*)gaddr(&vgascreen, r.min); 
 
	len = (r.max.x * (1<<gscreen.ldepth) + 31)/32 
		- (r.min.x * (1<<gscreen.ldepth))/32; 
	len *= BY2WD; 
1992/1107    
	if(len <= 0) 
		return; 
1992/1106    
 
	inc = gscreen.width * BY2WD - len; 
 
	for (y = r.min.y; y < r.max.y; y++){ 
1992/1107    
		l0update(sp, hp, len); 
		sp += inc+len; 
		hp += inc+len; 
1992/1106    
	} 
} 
 
void 
mousescreenupdate(void) 
{ 
	screenupdate(); 
} 
 
void 
1991/0730    
getcolor(ulong p, ulong *pr, ulong *pg, ulong *pb) 
{ 
	ulong ans; 
 
	/* 
1991/0731    
	 * The safari monochrome says 0 is black (zero intensity) 
1991/0730    
	 */ 
	if(p == 0) 
		ans = 0; 
	else 
		ans = ~0; 
	*pr = *pg = *pb = ans; 
} 
 
 
int 
setcolor(ulong p, ulong r, ulong g, ulong b) 
{ 
1992/0711    
	USED(p, r, g, b); 
1991/0730    
	return 0;	/* can't change mono screen colormap */ 
} 
 
int 
hwcursset(uchar *s, uchar *c, int ox, int oy) 
{ 
1992/0711    
	USED(s, c, ox, oy); 
1991/0730    
	return 0; 
} 
 
int 
hwcursmove(int x, int y) 
{ 
1992/0711    
	USED(x, y); 
1991/0730    
	return 0; 
} 
 
void 
1991/0904    
mouseclock(void) 
1991/0730    
{ 
	mouseupdate(1); 
1991/0927    
} 
1991/1113    
 
/* 
 *  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,  
	}, 
}; 
1992/1106    
 
1991/1113    
void 
bigcursor(void) 
{ 
	memmove(&arrow, &fatarrow, sizeof(fatarrow)); 
1992/1106    
	bitreverse(arrow.set, 2*16); 
	bitreverse(arrow.clr, 2*16); 
1991/0730    
} 


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