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

📄 vganvidia.c

📁 这是一个同样来自贝尔实验室的和UNIX有着渊源的操作系统, 其简洁的设计和实现易于我们学习和理解
💻 C
字号:
/* Portions of this file derived from work with the following copyright */ /***************************************************************************\|*                                                                           *||*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *||*                                                                           *||*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *||*     international laws.  Users and possessors of this source code are     *||*     hereby granted a nonexclusive,  royalty-free copyright license to     *||*     use this code in individual and commercial software.                  *||*                                                                           *||*     Any use of this source code must include,  in the user documenta-     *||*     tion and  internal comments to the code,  notices to the end user     *||*     as follows:                                                           *||*                                                                           *||*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *||*                                                                           *||*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *||*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *||*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *||*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *||*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *||*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *||*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *||*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *||*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *||*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *||*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *||*                                                                           *||*     U.S. Government  End  Users.   This source code  is a "commercial     *||*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *||*     consisting  of "commercial  computer  software"  and  "commercial     *||*     computer  software  documentation,"  as such  terms  are  used in     *||*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *||*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *||*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *||*     all U.S. Government End Users  acquire the source code  with only     *||*     those rights set forth herein.                                        *||*                                                                           *| \***************************************************************************/#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"#include "nv_dma.h"enum {	Pramin = 0x00710000,	Pramdac = 0x00680000,	Fifo = 0x00800000,	Pgraph = 0x00400000,	Pfb = 0x00100000};enum {	hwCurPos = Pramdac + 0x0300,};#define SKIPS 8struct {	ulong	*dmabase;	int		dmacurrent;	int		dmaput;	int		dmafree;	int		dmamax;} nv;static Pcidev*nvidiapci(void){	Pcidev *p;	p = nil;	while((p = pcimatch(p, 0x10DE, 0)) != nil){		if(p->did >= 0x20 && p->ccrb == 3)	/* video card */			return p;	}	return nil;}static voidnvidialinear(VGAscr*, int, int){}static voidnvidiaenable(VGAscr* scr){	Pcidev *p;	ulong *q;	int tmp;	if(scr->mmio)		return;	p = nvidiapci();	if(p == nil)		return;	scr->id = p->did;	scr->pci = p;	scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);	if(scr->mmio == nil)		return;	addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);	vgalinearpci(scr);	if(scr->apsize)		addvgaseg("nvidiascreen", scr->paddr, scr->apsize);	/* find video memory size */	switch (scr->id & 0x0ff0) {	case 0x0020:	case 0x00A0:		q = (void*)((uchar*)scr->mmio + Pfb);		tmp = *q;		if (tmp & 0x0100) {			scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;		} else {			tmp &= 0x03;			if (tmp)				scr->storage = (1024*1024*2) << tmp;			else				scr->storage = 1024*1024*32;		}		break;	case 0x01A0:		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));		tmp = pcicfgr32(p, 0x7C);		scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;		break;	case 0x01F0:		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));		tmp = pcicfgr32(p, 0x84);		scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;		break;	default:		q = (void*)((uchar*)scr->mmio + Pfb + 0x020C);		tmp = (*q >> 20) & 0xFFF;		if (tmp == 0)			tmp = 16;		scr->storage = tmp*1024*1024;		break;	}}static voidnvidiacurdisable(VGAscr* scr){	if(scr->mmio == 0)		return;	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);}static voidnvidiacurload(VGAscr* scr, Cursor* curs){	ulong*	p;	int	i,j;	ushort	c,s;	ulong	tmp;	if(scr->mmio == 0)		return;	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);	switch (scr->id & 0x0ff0) {	case 0x0020:	case 0x00A0:		p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);		break;	default:		/*		 * Reset the cursor location, since the kernel may		 * have allocated less storage than aux/vga		 * expected.		 */		tmp = scr->apsize - 96*1024;		p = (void*)((uchar*)scr->vaddr + tmp);		vgaxo(Crtx, 0x30, 0x80|(tmp>>17));		vgaxo(Crtx, 0x31, (tmp>>11)<<2);		vgaxo(Crtx, 0x2F, tmp>>24);		break;	}	for(i=0; i<16; i++) {		c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];		s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];		tmp = 0;		for (j=0; j<16; j++){			if(s&0x8000)				tmp |= 0x80000000;			else if(c&0x8000)				tmp |= 0xFFFF0000;			if (j&0x1){				*p++ = tmp;				tmp = 0;			} else {				tmp>>=16;			}			c<<=1;			s<<=1;		}		for (j=0; j<8; j++)			*p++ = 0;	}	for (i=0; i<256; i++)		*p++ = 0;	scr->offset = curs->offset;	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);	return;}static intnvidiacurmove(VGAscr* scr, Point p){	ulong*	cursorpos;	if(scr->mmio == 0)		return 1;	cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);	*cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);	return 0;}static voidnvidiacurenable(VGAscr* scr){	nvidiaenable(scr);	if(scr->mmio == 0)		return;	vgaxo(Crtx, 0x1F, 0x57);	nvidiacurload(scr, &arrow);	nvidiacurmove(scr, ZP);	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);}voidwriteput(VGAscr *scr, int data){	uchar	*p, scratch;	ulong	*fifo;	outb(0x3D0,0);	p = scr->vaddr;	scratch = *p;	fifo = (void*)((uchar*)scr->mmio + Fifo);	fifo[0x10] = (data << 2);	USED(scratch);}ulongreadget(VGAscr *scr){	ulong	*fifo;	fifo = (void*)((uchar*)scr->mmio + Fifo);	return (fifo[0x0011] >> 2);}voidnvdmakickoff(VGAscr *scr){	if(nv.dmacurrent != nv.dmaput) {		nv.dmaput = nv.dmacurrent;		writeput(scr, nv.dmaput);	}}static voidnvdmanext(ulong data){	nv.dmabase[nv.dmacurrent++] = data;}voidnvdmawait(VGAscr *scr, int size){	int dmaget;	size++;	while(nv.dmafree < size) {		dmaget = readget(scr);		if(nv.dmaput >= dmaget) {			nv.dmafree = nv.dmamax - nv.dmacurrent;			if(nv.dmafree < size) {				nvdmanext(0x20000000);				if(dmaget <= SKIPS) {					if (nv.dmaput <= SKIPS) /* corner case - will be idle */						writeput(scr, SKIPS + 1);					do { dmaget = readget(scr); }					while(dmaget <= SKIPS);				}				writeput(scr, SKIPS);				nv.dmacurrent = nv.dmaput = SKIPS;				nv.dmafree = dmaget - (SKIPS + 1);			}		} else			nv.dmafree = dmaget - nv.dmacurrent - 1;	}}static voidnvdmastart(VGAscr *scr, ulong tag, int size){	if (nv.dmafree <= size)		nvdmawait(scr, size);	nvdmanext((size << 18) | tag);	nv.dmafree -= (size + 1);}static voidwaitforidle(VGAscr *scr){	ulong*	pgraph;	int x;	pgraph = (void*)((uchar*)scr->mmio + Pgraph);	x = 0;	while((readget(scr) != nv.dmaput) && x++ < 1000000)		;	if(x >= 1000000)		iprint("idle stat %lud put %d scr %p pc %luX\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));	x = 0;	while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)		;	if(x >= 1000000)		iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));}static voidnvresetgraphics(VGAscr *scr){	ulong	surfaceFormat, patternFormat, rectFormat, lineFormat;	int		pitch, i;	pitch = scr->gscreen->width*BY2WD;	/*	 * DMA is at the end of the virtual window,	 * but we might have cut it short when mapping it.	 */	if(nv.dmabase == nil){		if(scr->storage <= scr->apsize)			nv.dmabase = (ulong*)((uchar*)scr->vaddr + scr->storage - 128*1024);		else{			nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);			if(nv.dmabase == 0){				hwaccel = 0;				hwblank = 0;				print("vmap nvidia dma failed\n");				return;			}		}	}	for(i=0; i<SKIPS; i++)		nv.dmabase[i] = 0x00000000;	nv.dmabase[0x0 + SKIPS] = 0x00040000;	nv.dmabase[0x1 + SKIPS] = 0x80000010;	nv.dmabase[0x2 + SKIPS] = 0x00042000;	nv.dmabase[0x3 + SKIPS] = 0x80000011;	nv.dmabase[0x4 + SKIPS] = 0x00044000;	nv.dmabase[0x5 + SKIPS] = 0x80000012;	nv.dmabase[0x6 + SKIPS] = 0x00046000;	nv.dmabase[0x7 + SKIPS] = 0x80000013;	nv.dmabase[0x8 + SKIPS] = 0x00048000;	nv.dmabase[0x9 + SKIPS] = 0x80000014;	nv.dmabase[0xA + SKIPS] = 0x0004A000;	nv.dmabase[0xB + SKIPS] = 0x80000015;	nv.dmabase[0xC + SKIPS] = 0x0004C000;	nv.dmabase[0xD + SKIPS] = 0x80000016;	nv.dmabase[0xE + SKIPS] = 0x0004E000;	nv.dmabase[0xF + SKIPS] = 0x80000017;	nv.dmaput = 0;	nv.dmacurrent = 16 + SKIPS;	nv.dmamax = 8191;	nv.dmafree = nv.dmamax - nv.dmacurrent;	switch(scr->gscreen->depth) {	case 32:	case 24:		surfaceFormat = SURFACE_FORMAT_DEPTH24;		patternFormat = PATTERN_FORMAT_DEPTH24;		rectFormat = RECT_FORMAT_DEPTH24;		lineFormat = LINE_FORMAT_DEPTH24;		break;	case 16:	case 15:		surfaceFormat = SURFACE_FORMAT_DEPTH16;		patternFormat = PATTERN_FORMAT_DEPTH16;		rectFormat = RECT_FORMAT_DEPTH16;		lineFormat = LINE_FORMAT_DEPTH16;		break;	default:		surfaceFormat = SURFACE_FORMAT_DEPTH8;		patternFormat = PATTERN_FORMAT_DEPTH8;		rectFormat = RECT_FORMAT_DEPTH8;		lineFormat = LINE_FORMAT_DEPTH8;		break;	}	nvdmastart(scr, SURFACE_FORMAT, 4);	nvdmanext(surfaceFormat);	nvdmanext(pitch | (pitch << 16));	nvdmanext(0);	nvdmanext(0);	nvdmastart(scr, PATTERN_FORMAT, 1);	nvdmanext(patternFormat);	nvdmastart(scr, RECT_FORMAT, 1);	nvdmanext(rectFormat);	nvdmastart(scr, LINE_FORMAT, 1);	nvdmanext(lineFormat);	nvdmastart(scr, PATTERN_COLOR_0, 4);	nvdmanext(~0);	nvdmanext(~0);	nvdmanext(~0);	nvdmanext(~0);	nvdmastart(scr, ROP_SET, 1);	nvdmanext(0xCC);	nvdmakickoff(scr);	waitforidle(scr);}static intnvidiahwfill(VGAscr *scr, Rectangle r, ulong sval){	nvdmastart(scr, RECT_SOLID_COLOR, 1);	nvdmanext(sval);	nvdmastart(scr, RECT_SOLID_RECTS(0), 2);	nvdmanext((r.min.x << 16) | r.min.y);	nvdmanext((Dx(r) << 16) | Dy(r));	//if ( (Dy(r) * Dx(r)) >= 512)		nvdmakickoff(scr);	waitforidle(scr);	return 1;}static intnvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr){	nvdmastart(scr, BLIT_POINT_SRC, 3);	nvdmanext((sr.min.y << 16) | sr.min.x);	nvdmanext((r.min.y << 16) | r.min.x);	nvdmanext((Dy(r) << 16) | Dx(r));	//if ( (Dy(r) * Dx(r)) >= 512)		nvdmakickoff(scr);	waitforidle(scr);	return 1;}voidnvidiablank(VGAscr*, int blank){	uchar seq1, crtc1A;	seq1 = vgaxi(Seqx, 1) & ~0x20;	crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;	if(blank){		seq1 |= 0x20;//		crtc1A |= 0xC0;		crtc1A |= 0x80;	}	vgaxo(Seqx, 1, seq1);	vgaxo(Crtx, 0x1A, crtc1A);}static voidnvidiadrawinit(VGAscr *scr){	nvresetgraphics(scr);	scr->blank = nvidiablank;	hwblank = 1;	scr->fill = nvidiahwfill;	scr->scroll = nvidiahwscroll;}VGAdev vganvidiadev = {	"nvidia",	nvidiaenable,	nil,	nil,	nvidialinear,	nvidiadrawinit,};VGAcur vganvidiacur = {	"nvidiahwgc",	nvidiacurenable,	nvidiacurdisable,	nvidiacurload,	nvidiacurmove,};

⌨️ 快捷键说明

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