Plan 9 from Bell Labs’s /usr/web/sources/extra/9hist/alphapc/devvga.c

Copyright © 2021 Plan 9 Foundation.
Distributed under the MIT License.
Download the Plan 9 distribution.


## diffname alphapc/devvga.c 1999/0415
## diff -e /dev/null /n/emeliedump/1999/0415/sys/src/brazil/alphapc/devvga.c
0a
/*
 */
#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"

enum {
	Qdir,
	Qvgaiob,
	Qvgaiow,
	Qvgaiol,
	Qvgactl,
};

static Dirtab vgadir[] = {
	"vgaiob",	{ Qvgaiob, 0 },		0,	0660,
	"vgaiow",	{ Qvgaiow, 0 },		0,	0660,
	"vgaiol",	{ Qvgaiol, 0 },		0,	0660,
	"vgactl",	{ Qvgactl, 0 },		0,	0660,
};

static void
vgareset(void)
{
	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*)
{
}

static long
vgaread(Chan* c, void* a, long n, vlong off)
{
	int len, port;
	char *p, *s;
	ushort *sp;
	ulong *lp;
	VGAscr *scr;
	ulong offset = off;

	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();
		}
		if(scr->dev)
			s = scr->dev->name;
		else
			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,
				1<<scr->gscreen->ldepth);
		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;

	case Qvgaiob:
		port = offset;
		for(p = a; port < offset+n; port++)
			*p++ = inb(port);
		return n;

	case Qvgaiow:
		if((n & 0x01) || (offset & 0x01))
			error(Ebadarg);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			*sp++ = ins(port);
		return n*2;

	case Qvgaiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			*lp++ = inl(port);
		return n*4;

	default:
		error(Egreg);
		break;
	}

	return 0;
}

static void
vgactl(char* a)
{
	int align, i, n, size, x, y, z;
	char *field[4], *p;
	VGAscr *scr;
	extern VGAdev *vgadev[];
	extern VGAcur *vgacur[];

	n = parsefields(a, field, 4, " ");
	if(n < 2)
		error(Ebadarg);

	scr = &vgascreen[0];
	if(strcmp(field[0], "hwgc") == 0){
		if(n < 2)
			error(Ebadarg);
		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){
		if(n < 2)
			error(Ebadarg);
		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++;

		switch(strtoul(p, &p, 0)){
		case 8:
			z = 3;
			break;

		default:
			z = 0;
			error(Ebadarg);
		}

		cursoroff(1);
		if(screensize(x, y, z))
			error(Egreg);
		vgascreenwin(scr);
		cursoron(1);
		return;
	}
	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;
	}

	error(Ebadarg);
}

static long
vgawrite(Chan* c, void* a, long n, vlong off)
{
	int port;
	char *p;
	ushort *sp;
	ulong *lp;
	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;

	case Qvgaiob:
		p = a;
		for(port = offset; port < offset+n; port++)
			outb(port, *p++);
		return n;

	case Qvgaiow:
		if((n & 01) || (offset & 01))
			error(Ebadarg);
		n /= 2;
		sp = a;
		for(port = offset; port < offset+n; port += 2)
			outs(port, *sp++);
		return n*2;

	case Qvgaiol:
		if((n & 0x03) || (offset & 0x03))
			error(Ebadarg);
		n /= 4;
		lp = a;
		for(port = offset; port < offset+n; port += 4)
			outl(port, *lp++);
		return n*4;

	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,
};
.
## diffname alphapc/devvga.c 1999/0512
## diff -e /n/emeliedump/1999/0415/sys/src/brazil/alphapc/devvga.c /n/emeliedump/1999/0512/sys/src/brazil/alphapc/devvga.c
106c
		if(scr->pciaddr)
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
				scr->pciaddr);
		else
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
				scr->aperture);
.
## diffname alphapc/devvga.c 2000/0308
## diff -e /n/emeliedump/1999/0512/sys/src/brazil/alphapc/devvga.c /n/emeliedump/2000/0308/sys/src/9/alphapc/devvga.c
160c
	n = getfields(a, field, 4, 1, " ");
.
## diffname alphapc/devvga.c 2000/0330
## diff -e /n/emeliedump/2000/0308/sys/src/9/alphapc/devvga.c /n/emeliedump/2000/0330/sys/src/9/alphapc/devvga.c
110c
			snprint(p+len, READSTR-len, "addr 0x%lux\n",
.
107c
			snprint(p+len, READSTR-len, "addr 0x%lux\n",
.
105c
		len += snprint(p+len, READSTR-len, "hwgc %s\n", s);
.
98c
			len += snprint(p+len, READSTR-len, "size %dx%dx%d\n",
.
96c
		len = snprint(p, READSTR, "type %s\n", s);
.
## diffname alphapc/devvga.c 2000/0401
## diff -e /n/emeliedump/2000/0330/sys/src/9/alphapc/devvga.c /n/emeliedump/2000/0401/sys/src/9/alphapc/devvga.c
284,307d
261,262d
259d
251a
/*	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;
	}
	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;
		return;
	}
.
238a
	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){
		/*
		 * This is a separate message, but first we need to make
		 * aux/vga send it; once everyone has the new vga, we
		 * can take the drawinit stuff out of hwgc.
		 */

		/*
		if(scr && scr->dev && scr->dev->drawinit)
			scr->dev->drawinit(scr);
		*/

		return;
	}
.
233c
		deletescreenimage();
		if(screensize(x, y, z, chan))
.
231a
		if(chantodepth(chan) != z)
			error("depth, channel do not match");

.
227,230c
		chanstr = field[2];
		if((chan = strtochan(chanstr)) == 0)
			error("bad channel");
.
222,225c
		z = strtoul(p, &p, 0);
.
209a
		if(drawhasclients())
			error(Ebusy);

.
208c
		if(n < 3)
.
167a

		/* BUG: drawinit should become a different message rather than piggybacking */
		if(scr && scr->dev && scr->dev->drawinit)
			scr->dev->drawinit(scr);

.
160,161c
	n = getfields(a, field, nelem(field), 1, " ");
	if(n < 1)
.
158a
	Rectangle r;
.
155c
	char *chanstr, *field[6], *p;
	ulong chan;
.
150a
static char Ebusy[] = "vga already configured";

.
125,142d
119,122c
	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);
.
110c
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
.
107c
			snprint(p+len, READSTR-len, "addr: 0x%lux\n",
.
105c
		len += snprint(p+len, READSTR-len, "hwgc: %s\n", s);
.
100c
				scr->gscreen->depth);
.
98c
			len += snprint(p+len, READSTR-len, "size: %dx%dx%d\n",
.
96c
		len = snprint(p, READSTR, "type: %s\n", s);
.
74,75d
72c
	int len;
.
34a
	/* 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"); 
.
29a
	"vgabios",	{ Qvgabios, 0 },		0x10000,	0440,
.
26,28d
22a
	Qvgabios,
.
19,21d
16a
extern uchar	*vgabios;

.
## diffname alphapc/devvga.c 2000/0407
## diff -e /n/emeliedump/2000/0401/sys/src/9/alphapc/devvga.c /n/emeliedump/2000/0407/sys/src/9/alphapc/devvga.c
325a
		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;
.
316c
		drawblankscreen(1);
.
314c
		if(n < 1)
.
289,290d
280,286d
162,165d
111,113c
			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->aperture);
.
108,109c
			snprint(p+len, READSTR-len, "addr 0x%lux\n", scr->pciaddr);
.
101,106c
				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);
		}

		len += snprint(p+len, READSTR-len, "hwaccel %s\n", hwaccel ? "on" : "off");
		len += snprint(p+len, READSTR-len, "hwblank %s\n", hwblank ? "on" : "off");
.
97,99c
		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",
.
92a

		len = 0;

.
78a
	char chbuf[30];
.
71a
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);
}

.
1a
 * VGA controller
.
## diffname alphapc/devvga.c 2000/0522
## diff -e /n/emeliedump/2000/0407/sys/src/9/alphapc/devvga.c /n/emeliedump/2000/0522/sys/src/9/alphapc/devvga.c
325a
	}
	else if(strcmp(field[0], "blanktime") == 0){
		if(n < 2)
			error(Ebadarg);
		blanktime = strtoul(field[1], 0, 0);
.
128a
		len += snprint(p+len, READSTR-len, "blanktime %lud\n", blanktime);
.
## diffname alphapc/devvga.c 2000/0530
## diff -e /n/emeliedump/2000/0522/sys/src/9/alphapc/devvga.c /n/emeliedump/2000/0530/sys/src/9/alphapc/devvga.c
331a
		return;
.
## diffname alphapc/devvga.c 2001/0727
## diff -e /n/emeliedump/2000/0530/sys/src/9/alphapc/devvga.c /n/emeliedump/2001/0727/sys/src/9/alphapc/devvga.c
397d
362c
	switch((ulong)c->qid.path){
.
96c
	switch((ulong)c->qid.path){
.
59c
	return devstat(c, dp, n, vgadir, nelem(vgadir), devgen);
.
56,57c
static int
vgastat(Chan* c, uchar* dp, int n)
.
53c
	return devwalk(c, nc, name, nname, vgadir, nelem(vgadir), devgen);
.
50,51c
Walkqid*
vgawalk(Chan* c, Chan *nc, char** name, int nname)
.
26a
	".",	{ Qdir, 0, QTDIR },		0,	0550,
.
## diffname alphapc/devvga.c 2001/1117
## diff -e /n/emeliedump/2001/0727/sys/src/9/alphapc/devvga.c /n/emeliedump/2001/1117/sys/src/9/alphapc/devvga.c
176c
	n = tokenize(a, field, nelem(field));
.
## diffname alphapc/devvga.c 2002/0109
## diff -e /n/emeliedump/2001/1117/sys/src/9/alphapc/devvga.c /n/emeliedump/2002/0109/sys/src/9/alphapc/devvga.c
396c
	devinit,	
	devshutdown,
.

Bell Labs OSI certified Powered by Plan 9

(Return to Plan 9 Home Page)

Copyright © 2021 Plan 9 Foundation. All Rights Reserved.
Comments to [email protected].