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

2000/0522/alphapc/devvga.c (diff list | history)

alphapc/devvga.c on 1999/0415
1999/0415    
/* 
2000/0407    
 * VGA controller 
1999/0415    
 */ 
#include "u.h" 
#include "../port/lib.h" 
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
#include "io.h" 
#include "../port/error.h" 
 
#define	Image	IMAGE 
#include <draw.h> 
#include <memdraw.h> 
#include <cursor.h> 
#include "screen.h" 
 
2000/0401    
extern uchar	*vgabios; 
 
1999/0415    
enum { 
	Qdir, 
	Qvgactl, 
2000/0401    
	Qvgabios, 
1999/0415    
}; 
 
static Dirtab vgadir[] = { 
	"vgactl",	{ Qvgactl, 0 },		0,	0660, 
2000/0401    
	"vgabios",	{ Qvgabios, 0 },		0x10000,	0440, 
1999/0415    
}; 
 
static void 
vgareset(void) 
{ 
2000/0401    
	/* reserve the 'standard' vga registers */ 
	if(ioalloc(0x2b0, 0x2df-0x2b0+1, 0, "vga") < 0) 
		panic("vga ports already allocated");  
	if(ioalloc(0x3c0, 0x3da-0x3c0+1, 0, "vga") < 0) 
		panic("vga ports already allocated");  
1999/0415    
	conf.monitor = 1; 
} 
 
static Chan* 
vgaattach(char* spec) 
{ 
	if(*spec && strcmp(spec, "0")) 
		error(Eio); 
	return devattach('v', spec); 
} 
 
int 
vgawalk(Chan* c, char* name) 
{ 
	return devwalk(c, name, vgadir, nelem(vgadir), devgen); 
} 
 
static void 
vgastat(Chan* c, char* dp) 
{ 
	devstat(c, dp, vgadir, nelem(vgadir), devgen); 
} 
 
static Chan* 
vgaopen(Chan* c, int omode) 
{ 
	return devopen(c, omode, vgadir, nelem(vgadir), devgen); 
} 
 
static void 
vgaclose(Chan*) 
{ 
} 
 
2000/0407    
static void 
checkport(int start, int end) 
{ 
	/* standard vga regs are OK */ 
	if(start >= 0x2b0 && end <= 0x2df+1) 
		return; 
	if(start >= 0x3c0 && end <= 0x3da+1) 
		return; 
 
	if(iounused(start, end)) 
		return; 
	error(Eperm); 
} 
 
1999/0415    
static long 
vgaread(Chan* c, void* a, long n, vlong off) 
{ 
2000/0401    
	int len; 
1999/0415    
	char *p, *s; 
	VGAscr *scr; 
	ulong offset = off; 
2000/0407    
	char chbuf[30]; 
1999/0415    
 
	switch(c->qid.path & ~CHDIR){ 
 
	case Qdir: 
		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen); 
 
	case Qvgactl: 
		scr = &vgascreen[0]; 
 
		p = malloc(READSTR); 
		if(waserror()){ 
			free(p); 
			nexterror(); 
		} 
2000/0407    
 
		len = 0; 
 
1999/0415    
		if(scr->dev) 
			s = scr->dev->name; 
		else 
			s = "cga"; 
2000/0407    
		len += snprint(p+len, READSTR-len, "type %s\n", s); 
 
		if(scr->gscreen) { 
			len += snprint(p+len, READSTR-len, "size %dx%dx%d %s\n", 
1999/0415    
				scr->gscreen->r.max.x, scr->gscreen->r.max.y, 
2000/0407    
				scr->gscreen->depth, chantostr(chbuf, scr->gscreen->chan)); 
 
			if(Dx(scr->gscreen->r) != Dx(physgscreenr)  
			|| Dy(scr->gscreen->r) != Dy(physgscreenr)) 
				len += snprint(p+len, READSTR-len, "actualsize %dx%d\n", 
					physgscreenr.max.x, physgscreenr.max.y); 
		} 
 
2000/0522    
		len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime); 
2000/0407    
		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off"); 
		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off"); 
1999/0512    
		if(scr->pciaddr) 
2000/0407    
			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->pciaddr); 
1999/0512    
		else 
2000/0407    
			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture); 
1999/0415    
		n = readstr(offset, a, n, p); 
		poperror(); 
		free(p); 
 
		return n; 
 
2000/0401    
	case Qvgabios: 
		if(vgabios == nil) 
			error(Egreg); 
		if(offset&0x80000000) 
			offset &= ~0x800E0000; 
		if(offset+n > 0x10000) 
			n = 0x10000-offset; 
		if(n < 0) 
			return 0; 
		memmove(a, vgabios+offset, n); 
1999/0415    
		return n; 
 
	default: 
		error(Egreg); 
		break; 
	} 
 
	return 0; 
} 
 
2000/0401    
static char Ebusy[] = "vga already configured"; 
 
1999/0415    
static void 
vgactl(char* a) 
{ 
	int align, i, n, size, x, y, z; 
2000/0401    
	char *chanstr, *field[6], *p; 
	ulong chan; 
1999/0415    
	VGAscr *scr; 
	extern VGAdev *vgadev[]; 
	extern VGAcur *vgacur[]; 
2000/0401    
	Rectangle r; 
1999/0415    
 
2000/0401    
	n = getfields(a, field, nelem(field), 1, " "); 
	if(n < 1) 
1999/0415    
		error(Ebadarg); 
 
	scr = &vgascreen[0]; 
	if(strcmp(field[0], "hwgc") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
2000/0401    
 
1999/0415    
		if(strcmp(field[1], "off") == 0){ 
			lock(&cursor); 
			if(scr->cur){ 
				if(scr->cur->disable) 
					scr->cur->disable(scr); 
				scr->cur = nil; 
			} 
			unlock(&cursor); 
			return; 
		} 
 
		for(i = 0; vgacur[i]; i++){ 
			if(strcmp(field[1], vgacur[i]->name)) 
				continue; 
			lock(&cursor); 
			if(scr->cur && scr->cur->disable) 
				scr->cur->disable(scr); 
			scr->cur = vgacur[i]; 
			if(scr->cur->enable) 
				scr->cur->enable(scr); 
			unlock(&cursor); 
			return; 
		} 
	} 
	else if(strcmp(field[0], "type") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
 
		for(i = 0; vgadev[i]; i++){ 
			if(strcmp(field[1], vgadev[i]->name)) 
				continue; 
			if(scr->dev && scr->dev->disable) 
				scr->dev->disable(scr); 
			scr->dev = vgadev[i]; 
			if(scr->dev->enable) 
				scr->dev->enable(scr); 
			return; 
		} 
	} 
	else if(strcmp(field[0], "size") == 0){ 
2000/0401    
		if(n < 3) 
1999/0415    
			error(Ebadarg); 
2000/0401    
		if(drawhasclients()) 
			error(Ebusy); 
 
1999/0415    
		x = strtoul(field[1], &p, 0); 
		if(x == 0 || x > 2048) 
			error(Ebadarg); 
		if(*p) 
			p++; 
 
		y = strtoul(p, &p, 0); 
		if(y == 0 || y > 2048) 
			error(Ebadarg); 
		if(*p) 
			p++; 
 
2000/0401    
		z = strtoul(p, &p, 0); 
1999/0415    
 
2000/0401    
		chanstr = field[2]; 
		if((chan = strtochan(chanstr)) == 0) 
			error("bad channel"); 
1999/0415    
 
2000/0401    
		if(chantodepth(chan) != z) 
			error("depth, channel do not match"); 
 
1999/0415    
		cursoroff(1); 
2000/0401    
		deletescreenimage(); 
		if(screensize(x, y, z, chan)) 
1999/0415    
			error(Egreg); 
		vgascreenwin(scr); 
		cursoron(1); 
		return; 
	} 
2000/0401    
	else if(strcmp(field[0], "actualsize") == 0){ 
		if(scr->gscreen == nil) 
			error("set the screen size first"); 
 
		if(n < 2) 
			error(Ebadarg); 
		x = strtoul(field[1], &p, 0); 
		if(x == 0 || x > 2048) 
			error(Ebadarg); 
		if(*p) 
			p++; 
 
		y = strtoul(p, nil, 0); 
		if(y == 0 || y > 2048) 
			error(Ebadarg); 
 
		if(x > scr->gscreen->r.max.x || y > scr->gscreen->r.max.y) 
			error("physical screen bigger than virtual"); 
 
		r = Rect(0,0,x,y); 
		if(!eqrect(r, scr->gscreen->r)){ 
			if(scr->cur == nil || scr->cur->doespanning == 0) 
				error("virtual screen not supported"); 
		} 
 
		physgscreenr = r; 
		return; 
	} 
	else if(strcmp(field[0], "palettedepth") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
 
		x = strtoul(field[1], &p, 0); 
		if(x != 8 && x != 6) 
			error(Ebadarg); 
 
		scr->palettedepth = x; 
		return; 
	} 
	else if(strcmp(field[0], "drawinit") == 0){ 
		if(scr && scr->dev && scr->dev->drawinit) 
			scr->dev->drawinit(scr); 
		return; 
	} 
1999/0415    
	else if(strcmp(field[0], "linear") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
 
		size = strtoul(field[1], 0, 0); 
		if(n < 3) 
			align = 0; 
		else 
			align = strtoul(field[2], 0, 0); 
		if(screenaperture(size, align)) 
			error("not enough free address space"); 
		return; 
	} 
2000/0401    
/*	else if(strcmp(field[0], "memset") == 0){ 
		if(n < 4) 
			error(Ebadarg); 
		memset((void*)strtoul(field[1], 0, 0), atoi(field[2]), atoi(field[3])); 
		return; 
	} 
*/ 
	else if(strcmp(field[0], "blank") == 0){ 
2000/0407    
		if(n < 1) 
2000/0401    
			error(Ebadarg); 
2000/0407    
		drawblankscreen(1); 
2000/0401    
		return; 
2000/0522    
	} 
	else if(strcmp(field[0], "blanktime") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
		blanktime = strtoul(field[1], 0, 0); 
2000/0401    
	} 
	else if(strcmp(field[0], "hwaccel") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
		if(strcmp(field[1], "on") == 0) 
			hwaccel = 1; 
		else if(strcmp(field[1], "off") == 0) 
			hwaccel = 0; 
2000/0407    
		return; 
	} 
	else if(strcmp(field[0], "hwblank") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
		if(strcmp(field[1], "on") == 0) 
			hwblank = 1; 
		else if(strcmp(field[1], "off") == 0) 
			hwblank = 0; 
2000/0401    
		return; 
	} 
1999/0415    
 
	error(Ebadarg); 
} 
 
static long 
vgawrite(Chan* c, void* a, long n, vlong off) 
{ 
	char *p; 
	ulong offset = off; 
 
	switch(c->qid.path & ~CHDIR){ 
 
	case Qdir: 
		error(Eperm); 
 
	case Qvgactl: 
		if(offset || n >= READSTR) 
			error(Ebadarg); 
		p = malloc(READSTR); 
		if(waserror()){ 
			free(p); 
			nexterror(); 
		} 
		memmove(p, a, n); 
		p[n] = 0; 
		vgactl(p); 
		poperror(); 
		free(p); 
		return n; 
 
	default: 
		error(Egreg); 
		break; 
	} 
 
	return 0; 
} 
 
Dev vgadevtab = { 
	'v', 
	"vga", 
 
	vgareset, 
	devinit, 
	vgaattach, 
	devclone, 
	vgawalk, 
	vgastat, 
	vgaopen, 
	devcreate, 
	vgaclose, 
	vgaread, 
	devbread, 
	vgawrite, 
	devbwrite, 
	devremove, 
	devwstat, 
}; 


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