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

📄 vesa.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
📖 第 1 页 / 共 2 页
字号:
	else if(m->xo)		snprint(m->chan, sizeof m->chan, "x%dr%dg%db%d", m->x, m->r, m->g, m->b);	else		snprint(m->chan, sizeof m->chan, "r%dg%db%d", m->r, m->g, m->b);	return 0;}voidvbeprintmodeinfo(Vbe *vbe, int id, char *suffix){	Vmode m;	if(vbemodeinfo(vbe, id, &m) < 0){	//	Bprint(&stdout, "vesa: cannot get mode 0x%ux: %r\n", id);		return;	}	printitem("vesa", "mode");	Bprint(&stdout, "0x%ux %s %s %s%s\n",		m.id, m.name, m.chan, m.model, suffix);}intvbegetmode(Vbe *vbe){	Ureg u;	vbesetup(vbe, &u, 0x4F03);	if(vbecall(vbe, &u) < 0)		return 0;	return u.bx;}intvbesetmode(Vbe *vbe, int id){	uchar *p;	Ureg u;	p = vbesetup(vbe, &u, 0x4F02);	if(id != 3)		id |= 3<<14;	/* graphics: use linear, do not clear */	u.bx = id;	USED(p);	/*	 * can set mode specifics (ht hss hse vt vss vse 0 clockhz refreshhz):	 *		u.bx |= 1<<11;		n = atoi(argv[2]); PWORD(p, n); p+=2;		n = atoi(argv[3]); PWORD(p, n); p+=2;		n = atoi(argv[4]); PWORD(p, n); p+=2;		n = atoi(argv[5]); PWORD(p, n); p+=2;		n = atoi(argv[6]); PWORD(p, n); p+=2;		n = atoi(argv[7]); PWORD(p, n); p+=2;		*p++ = atoi(argv[8]);		n = atoi(argv[9]); PLONG(p, n); p += 4;		n = atoi(argv[10]); PWORD(p, n); p += 2;		if(p != vbe.buf+19){			fprint(2, "prog error\n");			return;		}	 *	 */	return vbecall(vbe, &u);}voidvesatextmode(void){	if(vbe == nil){		vbe = mkvbe();		if(!vbe)			error("mkvbe: %r\n");	}	if(vbecheck(vbe) < 0)		error("vbecheck: %r\n");	if(vbesetmode(vbe, 3) < 0)		error("vbesetmode: %r\n");}static Flag edidflags[] = {	Fdigital, "digital",	Fdpmsstandby, "standby",	Fdpmssuspend, "suspend",	Fdpmsactiveoff, "activeoff",	Fmonochrome, "monochrome",	Fgtf, "gtf",	0};int parseedid128(Edid *e, void *v);intvbeddcedid(Vbe *vbe, Edid *e){	uchar *p;	Ureg u;		p = vbesetup(vbe, &u, 0x4F15);	u.bx = 0x0001;	if(vbecall(vbe, &u) < 0)		return -1;	if(parseedid128(e, p) < 0){		werrstr("parseedid128: %r");		return -1;	}	return 0;}	voidprintedid(Edid *e){	Modelist *l;		printitem("edid", "mfr");	Bprint(&stdout, "%s\n", e->mfr);	printitem("edid", "serialstr");	Bprint(&stdout, "%s\n", e->serialstr);	printitem("edid", "name");	Bprint(&stdout, "%s\n", e->name);	printitem("edid", "product");	Bprint(&stdout, "%d\n", e->product);	printitem("edid", "serial");	Bprint(&stdout, "%lud\n", e->serial);	printitem("edid", "version");	Bprint(&stdout, "%d.%d\n", e->version, e->revision);	printitem("edid", "mfrdate");	Bprint(&stdout, "%d.%d\n", e->mfryear, e->mfrweek);	printitem("edid", "size (cm)");	Bprint(&stdout, "%dx%d\n", e->dxcm, e->dycm);	printitem("edid", "gamma");	Bprint(&stdout, "%.2f\n", e->gamma/100.);	printitem("edid", "vert (Hz)");	Bprint(&stdout, "%d-%d\n", e->rrmin, e->rrmax);	printitem("edid", "horz (Hz)");	Bprint(&stdout, "%d-%d\n", e->hrmin, e->hrmax);	printitem("edid", "pclkmax");	Bprint(&stdout, "%lud\n", e->pclkmax);	printitem("edid", "flags");	printflags(edidflags, e->flags);		for(l=e->modelist; l; l=l->next){		printitem("edid", l->name);		Bprint(&stdout, "\n\t\tclock=%g\n\t\tshb=%d ehb=%d ht=%d\n\t\tvrs=%d vre=%d vt=%d\n\t\thsync=%c vsync=%c %s\n",			l->frequency/1.e6, l->shb, l->ehb, l->ht, l->vrs, l->vre, l->vt, l->hsync?l->hsync:'?', l->vsync?l->vsync:'?', l->interlace?"interlace=v" : "");	}}Modelist*addmode(Modelist *l, Mode m){	int rr;	Modelist **lp;//m.z = 8; // BUG	rr = (m.frequency+m.ht*m.vt/2)/(m.ht*m.vt);	snprint(m.name, sizeof m.name, "%dx%dx%d@%dHz", m.x, m.y, m.z, rr);	if(m.shs == 0)		m.shs = m.shb;	if(m.ehs == 0)		m.ehs = m.ehb;	if(m.vbs == 0)		m.vbs = m.vrs;	if(m.vbe == 0)		m.vbe = m.vbs+1;	for(lp=&l; *lp; lp=&(*lp)->next){		if(strcmp((*lp)->name, m.name) == 0){			(*lp)->Mode = m;			return l;		}	}	*lp = alloc(sizeof(**lp));	(*lp)->Mode = m;	return l;}/* * Parse VESA EDID information.  Based on the VESA * Extended Display Identification Data standard, Version 3, * November 13, 1997.  See /lib/vesa/edidv3.pdf. * * This only handles 128-byte EDID blocks.  Until I find * a monitor that produces 256-byte blocks, I'm not going * to try to decode them. *//* * Established timings block.  There is a bitmap * that says whether each mode is supported.  Most * of these have VESA definitions.  Those that don't are marked * as such, and we ignore them (the lookup fails). */static char *estabtime[] = {	"720x400@70Hz",	/* non-VESA: IBM, VGA */	"720x400@88Hz",	/* non-VESA: IBM, XGA2 */	"640x480@60Hz",	"640x480@67Hz",	/* non-VESA: Apple, Mac II */	"640x480@72Hz",	"640x480@75Hz",	"800x600@56Hz",	"800x600@60Hz",	"800x600@72Hz",	"800x600@75Hz",	"832x624@75Hz",	/* non-VESA: Apple, Mac II */	"1024x768i@87Hz",	/* non-VESA: IBM */	"1024x768@60Hz",	"1024x768@70Hz",	"1024x768@75Hz",	"1280x1024@75Hz",	"1152x870@75Hz",	/* non-VESA: Apple, Mac II */};/* * Decode the EDID detailed timing block.  See pp. 20-21 of the standard. */static intdecodedtb(Mode *m, uchar *p){	int ha, hb, hso, hspw, rr, va, vb, vso, vspw;	/* int dxmm, dymm, hbord, vbord; */	memset(m, 0, sizeof *m);	m->frequency = ((p[1]<<8) | p[0]) * 10000;	ha = ((p[4] & 0xF0)<<4) | p[2];		/* horizontal active */	hb = ((p[4] & 0x0F)<<8) | p[3];		/* horizontal blanking */	va = ((p[7] & 0xF0)<<4) | p[5];		/* vertical active */	vb = ((p[7] & 0x0F)<<8) | p[6];		/* vertical blanking */	hso = ((p[11] & 0xC0)<<2) | p[8];	/* horizontal sync offset */	hspw = ((p[11] & 0x30)<<4) | p[9];	/* horizontal sync pulse width */	vso = ((p[11] & 0x0C)<<2) | ((p[10] & 0xF0)>>4);	/* vertical sync offset */	vspw = ((p[11] & 0x03)<<4) | (p[10] & 0x0F);		/* vertical sync pulse width */	/* dxmm = (p[14] & 0xF0)<<4) | p[12]; 	/* horizontal image size (mm) */	/* dymm = (p[14] & 0x0F)<<8) | p[13];	/* vertical image size (mm) */	/* hbord = p[15];		/* horizontal border (pixels) */	/* vbord = p[16];		/* vertical border (pixels) */	m->x = ha;	m->y = va;	m->ht = ha+hb;	m->shs = ha;	m->shb = ha+hso;	m->ehb = ha+hso+hspw;	m->ehs = ha+hb;	m->vt = va+vb;	m->vbs = va;		m->vrs = va+vso;	m->vre = va+vso+vspw;	m->vbe = va+vb;	if(p[17] & 0x80)	/* interlaced */		m->interlace = 'v';	if(p[17] & 0x60)	/* some form of stereo monitor mode; no support */		return -1;	/*	 * Sync signal description.  I have no idea how to properly handle the 	 * first three cases, which I think are aimed at things other than	 * canonical SVGA monitors.	 */	switch((p[17] & 0x18)>>3) {	case 0:	/* analog composite sync signal*/	case 1:	/* bipolar analog composite sync signal */		/* p[17] & 0x04 means serration: hsync during vsync */		/* p[17] & 0x02 means sync pulse appears on RGB not just G */		break;	case 2:	/* digital composite sync signal */		/* p[17] & 0x04 means serration: hsync during vsync */		/* p[17] & 0x02 means hsync positive outside vsync */		break;	case 3:	/* digital separate sync signal; the norm */		m->vsync = (p[17] & 0x04) ? '+' : '-';		m->hsync = (p[17] & 0x02) ? '+' : '-';		break;	}	/* p[17] & 0x01 is another stereo bit, only referenced if p[17] & 0x60 != 0 */	rr = (m->frequency+m->ht*m->vt/2) / (m->ht*m->vt);	snprint(m->name, sizeof m->name, "%dx%d@%dHz", m->x, m->y, rr);	return 0;}extern Mode *vesamodes[];intvesalookup(Mode *m, char *name){	Mode **p;	for(p=vesamodes; *p; p++)		if(strcmp((*p)->name, name) == 0) {			*m = **p;			return 0;		}	return -1;}static intdecodesti(Mode *m, uchar *p){	int x, y, rr;	char str[20];	x = (p[0]+31)*8;	switch((p[1]>>6) & 3){	default:	case 0:		y = x;		break;	case 1:		y = (x*4)/3;		break;	case 2:		y = (x*5)/4;		break;	case 3:		y = (x*16)/9;		break;	}	rr = (p[1] & 0x1F) + 60;	sprint(str, "%dx%d@%dHz", x, y, rr);	return vesalookup(m, str);}intparseedid128(Edid *e, void *v){	static uchar magic[8] = { 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00 };	uchar *p, *q, sum;	int dpms, estab, i, m, vid;	Mode mode;	memset(e, 0, sizeof *e);	p = (uchar*)v;	if(memcmp(p, magic, 8) != 0) {		werrstr("bad edid header");		return -1;	}	sum = 0;	for(i=0; i<128; i++) 		sum += p[i];	if(sum != 0) {		werrstr("bad edid checksum");		return -1;	}	p += 8;	assert(p == (uchar*)v+8);	/* assertion offsets from pp. 12-13 of the standard */	/*	 * Manufacturer name is three 5-bit ascii letters, packed	 * into a big endian [sic] short in big endian order.  The high bit is unused.	 */	i = (p[0]<<8) | p[1];	p += 2;	e->mfr[0] = 'A'-1 + ((i>>10) & 0x1F);	e->mfr[1] = 'A'-1 + ((i>>5) & 0x1F);	e->mfr[2] = 'A'-1 + (i & 0x1F);	e->mfr[3] = '\0';	/*	 * Product code is a little endian short.	 */	e->product = (p[1]<<8) | p[0];	p += 2;	/*	 * Serial number is a little endian long, 0x01010101 = unused.	 */	e->serial = (p[3]<<24) | (p[2]<<16) | (p[1]<<8) | p[0];	p += 4;	if(e->serial == 0x01010101)		e->serial = 0;	e->mfrweek = *p++;	e->mfryear = 1990 + *p++;	assert(p == (uchar*)v+8+10);	/*	 * Structure version is next two bytes: major.minor.	 */	e->version = *p++;	e->revision = *p++;	assert(p == (uchar*)v+8+10+2);	/*	 * Basic display parameters / features.	 */	/*	 * Video input definition byte: 0x80 tells whether it is	 * an analog or digital screen; we ignore the other bits.	 * See p. 15 of the standard.	 */	vid = *p++;	if(vid & 0x80)		e->flags |= Fdigital;	e->dxcm = *p++;	e->dycm = *p++;	e->gamma = 100 + *p++;	dpms = *p++;	if(dpms & 0x80)		e->flags |= Fdpmsstandby;	if(dpms & 0x40)		e->flags |= Fdpmssuspend;	if(dpms & 0x20)		e->flags |= Fdpmsactiveoff;	if((dpms & 0x18) == 0x00)		e->flags |= Fmonochrome;	if(dpms & 0x01)		e->flags |= Fgtf;	assert(p == (uchar*)v+8+10+2+5);	/*	 * Color characteristics currently ignored.	 */	p += 10;	assert(p == (uchar*)v+8+10+2+5+10);	/*	 * Established timings: a bitmask of 19 preset timings.	 */	estab = (p[0]<<16) | (p[1]<<8) | p[2];	p += 3;		for(i=0, m=1<<23; i<nelem(estabtime); i++, m>>=1)		if(estab & m)			if(vesalookup(&mode, estabtime[i]) == 0)				e->modelist = addmode(e->modelist,  mode);	assert(p == (uchar*)v+8+10+2+5+10+3);	/*	 * Standard Timing Identifications: eight 2-byte selectors	 * of more standard timings.	 */	for(i=0; i<8; i++, p+=2)		if(decodesti(&mode, p+2*i) == 0)			e->modelist = addmode(e->modelist, mode);	assert(p == (uchar*)v+8+10+2+5+10+3+16);	/*	 * Detailed Timings	 */fprint(2, "dt\n");	for(i=0; i<4; i++, p+=18) {fprint(2, "%.8H\n", p);		if(p[0] || p[1]) {	/* detailed timing block: p[0] or p[1] != 0 */			if(decodedtb(&mode, p) == 0)				e->modelist = addmode(e->modelist, mode);		} else if(p[2]==0) {	/* monitor descriptor block */			switch(p[3]) {			case 0xFF:	/* monitor serial number (13-byte ascii, 0A terminated) */				if(q = memchr(p+5, 0x0A, 13))					*q = '\0';				memset(e->serialstr, 0, sizeof(e->serialstr));				strncpy(e->serialstr, (char*)p+5, 13);				break;			case 0xFE:	/* ascii string (13-byte ascii, 0A terminated) */				break;			case 0xFD:	/* monitor range limits */				print("fd %.18H\n", p);				e->rrmin = p[5];				e->rrmax = p[6];				e->hrmin = p[7]*1000;				e->hrmax = p[8]*1000;				if(p[9] != 0xFF)					e->pclkmax = p[9]*10*1000000;				break;			case 0xFC:	/* monitor name (13-byte ascii, 0A terminated) */				if(q = memchr(p+5, 0x0A, 13))					*q = '\0';				memset(e->name, 0, sizeof(e->name));				strncpy(e->name, (char*)p+5, 13);				break;			case 0xFB:	/* extra color point data */				break;			case 0xFA:	/* extra standard timing identifications */				for(i=0; i<6; i++)					if(decodesti(&mode, p+5+2*i) == 0)						e->modelist = addmode(e->modelist, mode);				break;			}		}	}	assert(p == (uchar*)v+8+10+2+5+10+3+16+72);	return 0;}

⌨️ 快捷键说明

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