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

2000/0326/pc/devvga.c (diff list | history)

pc/devvga.c on 1995/0406
1995/0406    
/* 
2000/0326    
 * VGA controller 
1995/0406    
 */ 
1997/1101    
#include "u.h" 
#include "../port/lib.h" 
#include "mem.h" 
#include "dat.h" 
#include "fns.h" 
#include "../port/error.h" 
1995/0406    
 
1997/1101    
#define	Image	IMAGE 
#include <draw.h> 
#include <memdraw.h> 
1999/0119    
#include <cursor.h> 
1997/1101    
#include "screen.h" 
1995/0406    
 
1997/1101    
enum { 
	Qdir, 
	Qvgactl, 
1994/0624    
}; 
 
1997/1101    
static Dirtab vgadir[] = { 
	"vgactl",	{ Qvgactl, 0 },		0,	0660, 
1992/1119    
}; 
1992/0527    
 
1997/0327    
static void 
1992/1119    
vgareset(void) 
{ 
1999/0714    
	/* 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");  
1997/0327    
	conf.monitor = 1; 
1992/0527    
} 
 
1997/0327    
static Chan* 
1997/1101    
vgaattach(char* spec) 
1992/0527    
{ 
1997/0327    
	if(*spec && strcmp(spec, "0")) 
		error(Eio); 
	return devattach('v', spec); 
1992/0527    
} 
 
int 
1997/1101    
vgawalk(Chan* c, char* name) 
1992/0527    
{ 
1997/0327    
	return devwalk(c, name, vgadir, nelem(vgadir), devgen); 
1992/0527    
} 
 
1997/0327    
static void 
1997/1101    
vgastat(Chan* c, char* dp) 
1992/0527    
{ 
1997/0327    
	devstat(c, dp, vgadir, nelem(vgadir), devgen); 
1992/0527    
} 
 
1997/0327    
static Chan* 
1997/1101    
vgaopen(Chan* c, int omode) 
1992/0527    
{ 
1997/0327    
	return devopen(c, omode, vgadir, nelem(vgadir), devgen); 
1992/0527    
} 
 
1997/0327    
static void 
1996/0418    
vgaclose(Chan*) 
1992/0527    
{ 
} 
 
1999/0714    
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); 
} 
 
1997/0327    
static long 
1998/0319    
vgaread(Chan* c, void* a, long n, vlong off) 
1992/0527    
{ 
1999/1005    
	int len; 
1997/1101    
	char *p, *s; 
	VGAscr *scr; 
1998/0319    
	ulong offset = off; 
1992/0528    
 
1997/1101    
	switch(c->qid.path & ~CHDIR){ 
 
1992/0527    
	case Qdir: 
1997/1101    
		return devdirread(c, a, n, vgadir, nelem(vgadir), devgen); 
 
1994/0624    
	case Qvgactl: 
1997/1101    
		scr = &vgascreen[0]; 
 
		p = malloc(READSTR); 
		if(waserror()){ 
			free(p); 
			nexterror(); 
		} 
		if(scr->dev) 
			s = scr->dev->name; 
1994/0624    
		else 
1997/1101    
			s = "cga"; 
		len = snprint(p, READSTR, "type: %s\n", s); 
		if(scr->gscreen) 
			len += snprint(p+len, READSTR-len, "size: %dx%dx%d\n", 
				scr->gscreen->r.max.x, scr->gscreen->r.max.y, 
1999/1005    
				scr->gscreen->depth); 
1997/1101    
		if(scr->cur) 
			s = scr->cur->name; 
		else 
			s = "off"; 
		len += snprint(p+len, READSTR-len, "hwgc: %s\n", s); 
		snprint(p+len, READSTR-len, "addr: 0x%lux\n", scr->aperture); 
 
		n = readstr(offset, a, n, p); 
		poperror(); 
		free(p); 
 
		return n; 
 
	default: 
		error(Egreg); 
		break; 
1992/0527    
	} 
1997/1101    
 
1992/1119    
	return 0; 
1992/0527    
} 
 
1999/1009    
static char Ebusy[] = "vga already configured"; 
 
1994/0624    
static void 
1997/1101    
vgactl(char* a) 
1994/0624    
{ 
1997/1101    
	int align, i, n, size, x, y, z; 
1999/1005    
	char *chanstr, *field[6], *p; 
	ulong chan; 
1997/1101    
	VGAscr *scr; 
	extern VGAdev *vgadev[]; 
	extern VGAcur *vgacur[]; 
1999/1005    
	Rectangle r; 
1994/0624    
 
2000/0308    
	n = getfields(a, field, nelem(field), 1, " "); 
1999/1005    
	if(n < 1) 
1994/0624    
		error(Ebadarg); 
 
1997/1101    
	scr = &vgascreen[0]; 
	if(strcmp(field[0], "hwgc") == 0){ 
1995/0406    
		if(n < 2) 
			error(Ebadarg); 
1999/1005    
 
1994/0624    
		if(strcmp(field[1], "off") == 0){ 
1997/1101    
			lock(&cursor); 
			if(scr->cur){ 
				if(scr->cur->disable) 
					scr->cur->disable(scr); 
				scr->cur = nil; 
1994/0624    
			} 
1997/1101    
			unlock(&cursor); 
1994/0624    
			return; 
		} 
 
1997/1101    
		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; 
1994/0624    
		} 
	} 
	else if(strcmp(field[0], "type") == 0){ 
1995/0406    
		if(n < 2) 
			error(Ebadarg); 
1997/1101    
 
		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; 
1994/0624    
		} 
	} 
	else if(strcmp(field[0], "size") == 0){ 
1999/1005    
		if(n < 3) 
1995/0406    
			error(Ebadarg); 
1999/1009    
		if(drawhasclients()) 
			error(Ebusy); 
 
1997/1101    
		x = strtoul(field[1], &p, 0); 
1995/0206    
		if(x == 0 || x > 2048) 
1994/0624    
			error(Ebadarg); 
1997/1101    
		if(*p) 
			p++; 
1994/0624    
 
1997/1101    
		y = strtoul(p, &p, 0); 
1997/0613    
		if(y == 0 || y > 2048) 
1994/0624    
			error(Ebadarg); 
1997/1101    
		if(*p) 
			p++; 
1994/0624    
 
1999/1005    
		z = strtoul(p, &p, 0); 
1997/1101    
 
1999/1005    
		chanstr = field[2]; 
		if((chan = strtochan(chanstr)) == 0) 
			error("bad channel"); 
1994/0624    
 
1999/1005    
		if(chantodepth(chan) != z) 
			error("depth, channel do not match"); 
 
1995/0206    
		cursoroff(1); 
1999/1005    
		deletescreenimage(); 
		if(screensize(x, y, z, chan)) 
1997/1101    
			error(Egreg); 
		vgascreenwin(scr); 
1994/0624    
		cursoron(1); 
		return; 
	} 
1999/1005    
	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; 
	} 
1995/0406    
	else if(strcmp(field[0], "linear") == 0){ 
		if(n < 2) 
			error(Ebadarg); 
1997/1101    
 
1996/0418    
		size = strtoul(field[1], 0, 0); 
1995/0406    
		if(n < 3) 
1996/0418    
			align = 0; 
1995/0406    
		else 
1996/0418    
			align = strtoul(field[2], 0, 0); 
1997/1101    
		if(screenaperture(size, align)) 
1995/0406    
			error("not enough free address space"); 
		return; 
	} 
1999/1005    
/*	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){ 
		if(n < 2) 
			error(Ebadarg); 
		drawblankscreen(atoi(field[1])); 
		return; 
	} 
1999/1006    
	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/0326    
		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; 
1999/1005    
		return; 
	} 
1995/0406    
 
1994/0624    
	error(Ebadarg); 
} 
 
1997/0327    
static long 
1998/0319    
vgawrite(Chan* c, void* a, long n, vlong off) 
1992/0527    
{ 
1997/1101    
	char *p; 
1998/0319    
	ulong offset = off; 
1992/0528    
 
1997/1101    
	switch(c->qid.path & ~CHDIR){ 
 
1992/0527    
	case Qdir: 
		error(Eperm); 
1997/1101    
 
1994/0503    
	case Qvgactl: 
1997/1101    
		if(offset || n >= READSTR) 
1994/0503    
			error(Ebadarg); 
1997/1101    
		p = malloc(READSTR); 
		if(waserror()){ 
			free(p); 
			nexterror(); 
		} 
		memmove(p, a, n); 
		p[n] = 0; 
		vgactl(p); 
		poperror(); 
		free(p); 
1992/0603    
		return n; 
1997/1101    
 
	default: 
		error(Egreg); 
		break; 
1992/0527    
	} 
1997/1101    
 
1992/1119    
	return 0; 
1995/0108    
} 
 
1997/0327    
Dev vgadevtab = { 
1997/0408    
	'v', 
	"vga", 
 
1997/0327    
	vgareset, 
1997/1101    
	devinit, 
1997/0327    
	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)