⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vesa.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
#include <u.h>#include <libc.h>#include <bio.h>#include </386/include/ureg.h>typedef struct Ureg Ureg;#include "pci.h"#include "vga.h"typedef struct Vbe Vbe;typedef struct Vmode Vmode;typedef struct Modelist Modelist;typedef struct Edid Edid;enum{	MemSize = 1024*1024,	PageSize = 4096,	RealModeBuf = 0x9000,};struct Vbe{	int	rmfd;	/* /dev/realmode */	int	memfd;	/* /dev/realmem */	uchar	*mem;	/* copy of memory; 1MB */	uchar	*isvalid;	/* 1byte per 4kB in mem */	uchar	*buf;	uchar	*modebuf;};struct Vmode{	char	name[32];	char	chan[32];	int	id;	int	attr;	/* flags */	int	bpl;	int	dx, dy;	int	depth;	char	*model;	int	r, g, b, x;	int	ro, go, bo, xo;	int	directcolor;	/* flags */	ulong	paddr;};struct Edid {	char		mfr[4];		/* manufacturer */	char		serialstr[16];	/* serial number as string (in extended data) */	char		name[16];		/* monitor name as string (in extended data) */	ushort	product;		/* product code, 0 = unused */	ulong	serial;		/* serial number, 0 = unused */	uchar	version;		/* major version number */	uchar	revision;		/* minor version number */	uchar	mfrweek;		/* week of manufacture, 0 = unused */	int		mfryear;		/* year of manufacture, 0 = unused */	uchar 	dxcm;		/* horizontal image size in cm. */	uchar	dycm;		/* vertical image size in cm. */	int		gamma;		/* gamma*100 */	int		rrmin;		/* minimum vertical refresh rate */	int		rrmax;		/* maximum vertical refresh rate */	int		hrmin;		/* minimum horizontal refresh rate */	int		hrmax;		/* maximum horizontal refresh rate */	ulong	pclkmax;		/* maximum pixel clock */	int		flags;	Modelist	*modelist;		/* list of supported modes */};struct Modelist{	Mode;	Modelist *next;};enum {	Fdigital = 1<<0,		/* is a digital display */	Fdpmsstandby = 1<<1,	/* supports DPMS standby mode */	Fdpmssuspend = 1<<2,	/* supports DPMS suspend mode */	Fdpmsactiveoff = 1<<3,	/* supports DPMS active off mode */	Fmonochrome = 1<<4,	/* is a monochrome display */	Fgtf = 1<<5,			/* supports VESA GTF: see /lib/vesa/gtf10.pdf */};#define WORD(p) ((p)[0] | ((p)[1]<<8))#define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24))#define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8#define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24static Vbe *vbe;static Edid edid;Vbe *mkvbe(void);int vbecheck(Vbe*);uchar *vbemodes(Vbe*);int vbemodeinfo(Vbe*, int, Vmode*);int vbegetmode(Vbe*);int vbesetmode(Vbe*, int);void vbeprintinfo(Vbe*);void vbeprintmodeinfo(Vbe*, int, char*);int vbesnarf(Vbe*, Vga*);void vesaddc(void);int vbeddcedid(Vbe *vbe, Edid *e);void printedid(Edid*);intdbvesa(Vga* vga){	vbe = mkvbe();	if(vbe == nil){		fprint(2, "mkvbe: %r\n");		return 0;	}	if(vbecheck(vbe) < 0){		fprint(2, "dbvesa: %r\n");		return 0;	}	vga->link = alloc(sizeof(Ctlr));	*vga->link = vesa;	vga->vesa = vga->link;	vga->ctlr = vga->link;	vga->link->link = alloc(sizeof(Ctlr));	*vga->link->link = softhwgc;	vga->hwgc = vga->link->link;	return 1;}Mode*dbvesamode(char *mode){	int i;	uchar *p, *ep;	Vmode vm;	Mode *m;		if(vbe == nil)		return nil;	p = vbemodes(vbe);	if(p == nil)		return nil;	for(ep=p+1024; (p[0]!=0xFF || p[1]!=0xFF) && p<ep; p+=2){		if(vbemodeinfo(vbe, WORD(p), &vm) < 0)			continue;		if(strcmp(vm.name, mode) == 0)			goto havemode;	}	if(1){		fprint(2, "warning: scanning for unoffered vesa modes\n");		for(i=0x100; i<0x200; i++){			if(vbemodeinfo(vbe, i, &vm) < 0)				continue;			if(strcmp(vm.name, mode) == 0)				goto havemode;		}	}	werrstr("no such vesa mode");	return nil;havemode:	m = alloc(sizeof(Mode));	strcpy(m->type, "vesa");	strcpy(m->size, vm.name);	strcpy(m->chan, vm.chan);	m->frequency = 100;	m->x = vm.dx;	m->y = vm.dy;	m->z = vm.depth;	m->ht = m->x;	m->shb = m->x;	m->ehb = m->x;	m->shs = m->x;	m->ehs = m->x;	m->vt = m->y;	m->vrs = m->y;	m->vre = m->y;	m->attr = alloc(sizeof(Attr));	m->attr->attr = "id";	m->attr->val = alloc(32);	sprint(m->attr->val, "0x%x", vm.id);	return m;}static voidsnarf(Vga* vga, Ctlr* ctlr){	if(!vbe)		vbe = mkvbe();	if(vbe)		vga->vesa = ctlr;	vbesnarf(vbe, vga);	vga->linear = 1;	ctlr->flag |= Hlinear|Ulinear;}static voidload(Vga* vga, Ctlr* ctlr){	if(vbe == nil)		error("no vesa bios");	if(vbesetmode(vbe, atoi(dbattr(vga->mode->attr, "id"))) < 0){		ctlr->flag |= Ferror;		fprint(2, "vbesetmode: %r\n");	}}static voiddump(Vga*, Ctlr*){	int i;	char did[0x200];	uchar *p, *ep;	if(!vbe){		Bprint(&stdout, "no vesa bios\n");		return;	}	memset(did, 0, sizeof did);	vbeprintinfo(vbe);	p = vbemodes(vbe);	if(p){		for(ep=p+1024; (p[0]!=0xFF || p[1]!=0xFF) && p<ep; p+=2){			vbeprintmodeinfo(vbe, WORD(p), "");			if(WORD(p) < nelem(did))				did[WORD(p)] = 1;		}	}	for(i=0x100; i<0x1FF; i++)		if(!did[i])			vbeprintmodeinfo(vbe, i, " (unoffered)");						if(vbeddcedid(vbe, &edid) < 0)		fprint(2, "warning: reading edid: %r\n");	else		printedid(&edid);}Ctlr vesa = {	"vesa",			/* name */	snarf,				/* snarf */	0,			/* options */	0,				/* init */	load,				/* load */	dump,				/* dump */};Ctlr softhwgc = {	"soft",};/* * VESA bios extension */typedef struct Flag Flag;struct Flag {	int bit;	char *desc;};static Flag capabilityflag[] = {	0x01, "8-bit-dac",	0x02, "not-vga",	0x04, "ramdac-needs-blank",	0x08, "stereoscopic",	0x10, "stereo-evc",	0};static Flag modeattributesflags[] = {	1<<0, "supported",	1<<2, "tty",	1<<3, "color",	1<<4, "graphics",	1<<5, "not-vga",	1<<6, "no-windowed-vga",	1<<7, "linear",	1<<8, "double-scan",	1<<9, "interlace",	1<<10, "triple-buffer",	1<<11, "stereoscopic",	1<<12, "dual-start-addr",	0};static Flag winattributesflags[] = {	1<<0, "relocatable",	1<<1, "readable",	1<<2, "writeable",	0};static Flag directcolorflags[] = {	1<<0, "programmable-color-ramp",	1<<1, "x-usable",	0};static char *modelstr[] = {	"text", "cga", "hercules", "planar", "packed", "non-chain4", "direct", "YUV"};static voidprintflags(Flag *f, int b){	int i;	for(i=0; f[i].bit; i++)		if(f[i].bit & b)			Bprint(&stdout, " %s", f[i].desc);	Bprint(&stdout, "\n");}Vbe*mkvbe(void){	Vbe *vbe;	vbe = alloc(sizeof(Vbe));	if((vbe->rmfd = open("/dev/realmode", ORDWR)) < 0)		return nil;	if((vbe->memfd = open("/dev/realmodemem", ORDWR)) < 0)		return nil;	vbe->mem = alloc(MemSize);	vbe->isvalid = alloc(MemSize/PageSize);	vbe->buf = alloc(PageSize);	vbe->modebuf = alloc(PageSize);	return vbe;}static voidloadpage(Vbe *vbe, int p){	if(p >= MemSize/PageSize || vbe->isvalid[p])		return;	if(pread(vbe->memfd, vbe->mem+p*PageSize, PageSize, p*PageSize) != PageSize)		error("read /dev/realmodemem: %r\n");	vbe->isvalid[p] = 1;}static void*unfarptr(Vbe *vbe, uchar *p){	int seg, off;	seg = WORD(p+2);	off = WORD(p);	if(seg==0 && off==0)		return nil;	off += seg<<4;	if(off >= MemSize)		return nil;	loadpage(vbe, off/PageSize);	loadpage(vbe, off/PageSize+1);	/* just in case */	return vbe->mem+off;}uchar*vbesetup(Vbe *vbe, Ureg *u, int ax){	memset(vbe->buf, 0, PageSize);	memset(u, 0, sizeof *u);	u->ax = ax;	u->es = (RealModeBuf>>4)&0xF000;	u->di = RealModeBuf&0xFFFF;	return vbe->buf;}intvbecall(Vbe *vbe, Ureg *u){	u->trap = 0x10;	if(pwrite(vbe->memfd, vbe->buf, PageSize, RealModeBuf) != PageSize)		error("write /dev/realmodemem: %r\n");	if(pwrite(vbe->rmfd, u, sizeof *u, 0) != sizeof *u)		error("write /dev/realmode: %r\n");	if(pread(vbe->rmfd, u, sizeof *u, 0) != sizeof *u)		error("read /dev/realmode: %r\n");	if(pread(vbe->memfd, vbe->buf, PageSize, RealModeBuf) != PageSize)		error("read /dev/realmodemem: %r\n");	if((u->ax&0xFFFF) != 0x004F){		werrstr("VBE error %#.4lux", u->ax&0xFFFF);		return -1;	}	memset(vbe->isvalid, 0, MemSize/PageSize);	return 0;}intvbecheck(Vbe *vbe){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F00);	strcpy((char*)p, "VBE2");	if(vbecall(vbe, &u) < 0)		return -1;	if(memcmp(p, "VESA", 4) != 0 || p[5] < 2){		werrstr("invalid vesa signature %.4H %.4H\n", p, p+4);		return -1;	}	return 0;}intvbesnarf(Vbe *vbe, Vga *vga){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F00);	strcpy((char*)p, "VBE2");	if(vbecall(vbe, &u) < 0)		return -1;	if(memcmp(p, "VESA", 4) != 0 || p[5] < 2)		return -1;	vga->apz = WORD(p+18)*0x10000UL;	return 0;}voidvbeprintinfo(Vbe *vbe){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F00);	strcpy((char*)p, "VBE2");	if(vbecall(vbe, &u) < 0)		return;	printitem("vesa", "sig");	Bprint(&stdout, "%.4s %d.%d\n", (char*)p, p[5], p[4]);	if(p[5] < 2)		return;	printitem("vesa", "oem");	Bprint(&stdout, "%s %d.%d\n", unfarptr(vbe, p+6), p[21], p[20]);	printitem("vesa", "vendor");	Bprint(&stdout, "%s\n", unfarptr(vbe, p+22));	printitem("vesa", "product");	Bprint(&stdout, "%s\n", unfarptr(vbe, p+26));	printitem("vesa", "rev");	Bprint(&stdout, "%s\n", unfarptr(vbe, p+30));	printitem("vesa", "cap");	printflags(capabilityflag, p[10]);	printitem("vesa", "mem");	Bprint(&stdout, "%lud\n", WORD(p+18)*0x10000UL);}uchar*vbemodes(Vbe *vbe){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F00);	strcpy((char*)p, "VBE2");	if(vbecall(vbe, &u) < 0)		return nil;	memmove(vbe->modebuf, unfarptr(vbe, p+14), 1024);	return vbe->modebuf;}intvbemodeinfo(Vbe *vbe, int id, Vmode *m){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F01);	u.cx = id;	if(vbecall(vbe, &u) < 0)		return -1;	m->id = id;	m->attr = WORD(p);	m->bpl = WORD(p+16);	m->dx = WORD(p+18);	m->dy = WORD(p+20);	m->depth = p[25];	m->model = p[27] < nelem(modelstr) ? modelstr[p[27]] : "unknown";	m->r = p[31];	m->g = p[33];	m->b = p[35];	m->x = p[37];	m->ro = p[32];	m->go = p[34];	m->bo = p[36];	m->xo = p[38];	m->directcolor = p[39];	m->paddr = LONG(p+40);	snprint(m->name, sizeof m->name, "%dx%dx%d",		m->dx, m->dy, m->depth);	if(m->depth <= 8)		snprint(m->chan, sizeof m->chan, "m%d", m->depth);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -