xref: /plan9-contrib/sys/src/9/pc/vganvidia.c (revision cb8c047aa49e908a428eac8b13623e1b242fa11e)
1bb0aa005SDavid du Colombier 
2bb0aa005SDavid du Colombier /* Portions of this file derived from work with the following copyright */
3bb0aa005SDavid du Colombier 
4bb0aa005SDavid du Colombier  /***************************************************************************\
5bb0aa005SDavid du Colombier |*                                                                           *|
6bb0aa005SDavid du Colombier |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
7bb0aa005SDavid du Colombier |*                                                                           *|
8bb0aa005SDavid du Colombier |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
9bb0aa005SDavid du Colombier |*     international laws.  Users and possessors of this source code are     *|
10bb0aa005SDavid du Colombier |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
11bb0aa005SDavid du Colombier |*     use this code in individual and commercial software.                  *|
12bb0aa005SDavid du Colombier |*                                                                           *|
13bb0aa005SDavid du Colombier |*     Any use of this source code must include,  in the user documenta-     *|
14bb0aa005SDavid du Colombier |*     tion and  internal comments to the code,  notices to the end user     *|
15bb0aa005SDavid du Colombier |*     as follows:                                                           *|
16bb0aa005SDavid du Colombier |*                                                                           *|
17bb0aa005SDavid du Colombier |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
18bb0aa005SDavid du Colombier |*                                                                           *|
19bb0aa005SDavid du Colombier |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
20bb0aa005SDavid du Colombier |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
21bb0aa005SDavid du Colombier |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
22bb0aa005SDavid du Colombier |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
23bb0aa005SDavid du Colombier |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
24bb0aa005SDavid du Colombier |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
25bb0aa005SDavid du Colombier |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
26bb0aa005SDavid du Colombier |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
27bb0aa005SDavid du Colombier |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
28bb0aa005SDavid du Colombier |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
29bb0aa005SDavid du Colombier |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
30bb0aa005SDavid du Colombier |*                                                                           *|
31bb0aa005SDavid du Colombier |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
32bb0aa005SDavid du Colombier |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
33bb0aa005SDavid du Colombier |*     consisting  of "commercial  computer  software"  and  "commercial     *|
34bb0aa005SDavid du Colombier |*     computer  software  documentation,"  as such  terms  are  used in     *|
35bb0aa005SDavid du Colombier |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
36bb0aa005SDavid du Colombier |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
37bb0aa005SDavid du Colombier |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
38bb0aa005SDavid du Colombier |*     all U.S. Government End Users  acquire the source code  with only     *|
39bb0aa005SDavid du Colombier |*     those rights set forth herein.                                        *|
40bb0aa005SDavid du Colombier |*                                                                           *|
41bb0aa005SDavid du Colombier  \***************************************************************************/
42bb0aa005SDavid du Colombier 
439a747e4fSDavid du Colombier #include "u.h"
449a747e4fSDavid du Colombier #include "../port/lib.h"
459a747e4fSDavid du Colombier #include "mem.h"
469a747e4fSDavid du Colombier #include "dat.h"
479a747e4fSDavid du Colombier #include "fns.h"
489a747e4fSDavid du Colombier #include "io.h"
499a747e4fSDavid du Colombier #include "../port/error.h"
509a747e4fSDavid du Colombier 
519a747e4fSDavid du Colombier #define	Image	IMAGE
529a747e4fSDavid du Colombier #include <draw.h>
539a747e4fSDavid du Colombier #include <memdraw.h>
549a747e4fSDavid du Colombier #include <cursor.h>
559a747e4fSDavid du Colombier #include "screen.h"
56bb0aa005SDavid du Colombier #include "nv_dma.h"
579a747e4fSDavid du Colombier 
589a747e4fSDavid du Colombier enum {
599a747e4fSDavid du Colombier 	Pramin = 0x00710000,
609a747e4fSDavid du Colombier 	Pramdac = 0x00680000,
619a747e4fSDavid du Colombier 	Fifo = 0x00800000,
62bb0aa005SDavid du Colombier 	Pgraph = 0x00400000,
63bb0aa005SDavid du Colombier 	Pfb = 0x00100000
649a747e4fSDavid du Colombier };
659a747e4fSDavid du Colombier 
669a747e4fSDavid du Colombier enum {
679a747e4fSDavid du Colombier 	hwCurPos = Pramdac + 0x0300,
689a747e4fSDavid du Colombier };
699a747e4fSDavid du Colombier 
70bb0aa005SDavid du Colombier #define SKIPS 8
71bb0aa005SDavid du Colombier 
72bb0aa005SDavid du Colombier struct {
73bb0aa005SDavid du Colombier 	ulong	*dmabase;
74bb0aa005SDavid du Colombier 	int		dmacurrent;
75bb0aa005SDavid du Colombier 	int		dmaput;
76bb0aa005SDavid du Colombier 	int		dmafree;
77bb0aa005SDavid du Colombier 	int		dmamax;
78bb0aa005SDavid du Colombier } nv;
79bb0aa005SDavid du Colombier 
809a747e4fSDavid du Colombier static Pcidev*
nvidiapci(void)819a747e4fSDavid du Colombier nvidiapci(void)
829a747e4fSDavid du Colombier {
839a747e4fSDavid du Colombier 	Pcidev *p;
849a747e4fSDavid du Colombier 
85fb7f0c93SDavid du Colombier 	p = nil;
867abd426fSDavid du Colombier 	while((p = pcimatch(p, 0x10DE, 0)) != nil){
87aa46331bSDavid du Colombier 		if(p->did >= 0x20 && p->ccrb == 3)	/* video card */
889a747e4fSDavid du Colombier 			return p;
897abd426fSDavid du Colombier 	}
909a747e4fSDavid du Colombier 	return nil;
919a747e4fSDavid du Colombier }
929a747e4fSDavid du Colombier 
934de34a7eSDavid du Colombier static void
nvidialinear(VGAscr *,int,int)944de34a7eSDavid du Colombier nvidialinear(VGAscr*, int, int)
959a747e4fSDavid du Colombier {
969a747e4fSDavid du Colombier }
979a747e4fSDavid du Colombier 
989a747e4fSDavid du Colombier static void
nvidiaenable(VGAscr * scr)999a747e4fSDavid du Colombier nvidiaenable(VGAscr* scr)
1009a747e4fSDavid du Colombier {
1019a747e4fSDavid du Colombier 	Pcidev *p;
1024de34a7eSDavid du Colombier 	ulong *q;
1034de34a7eSDavid du Colombier 	int tmp;
1049a747e4fSDavid du Colombier 
1054de34a7eSDavid du Colombier 	if(scr->mmio)
1069a747e4fSDavid du Colombier 		return;
1079a747e4fSDavid du Colombier 	p = nvidiapci();
1089a747e4fSDavid du Colombier 	if(p == nil)
1099a747e4fSDavid du Colombier 		return;
1106a081dcdSDavid du Colombier 	scr->id = p->did;
1114de34a7eSDavid du Colombier 	scr->pci = p;
1129a747e4fSDavid du Colombier 
1134de34a7eSDavid du Colombier 	scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
1144de34a7eSDavid du Colombier 	if(scr->mmio == nil)
1159a747e4fSDavid du Colombier 		return;
1164de34a7eSDavid du Colombier 	addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);
1179a747e4fSDavid du Colombier 
1184de34a7eSDavid du Colombier 	vgalinearpci(scr);
119*cb8c047aSDavid du Colombier 	if(scr->apsize)
1204de34a7eSDavid du Colombier 		addvgaseg("nvidiascreen", scr->paddr, scr->apsize);
121bb0aa005SDavid du Colombier 
122bb0aa005SDavid du Colombier 	/* find video memory size */
12342bd533dSDavid du Colombier 	switch (scr->id & 0x0ff0) {
12442bd533dSDavid du Colombier 	case 0x0020:
12542bd533dSDavid du Colombier 	case 0x00A0:
1264de34a7eSDavid du Colombier 		q = (void*)((uchar*)scr->mmio + Pfb);
127bb0aa005SDavid du Colombier 		tmp = *q;
128bb0aa005SDavid du Colombier 		if (tmp & 0x0100) {
129bb0aa005SDavid du Colombier 			scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
130bb0aa005SDavid du Colombier 		} else {
131bb0aa005SDavid du Colombier 			tmp &= 0x03;
132bb0aa005SDavid du Colombier 			if (tmp)
133bb0aa005SDavid du Colombier 				scr->storage = (1024*1024*2) << tmp;
134bb0aa005SDavid du Colombier 			else
135bb0aa005SDavid du Colombier 				scr->storage = 1024*1024*32;
136bb0aa005SDavid du Colombier 		}
13742bd533dSDavid du Colombier 		break;
13842bd533dSDavid du Colombier 	case 0x01A0:
13942bd533dSDavid du Colombier 		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
14042bd533dSDavid du Colombier 		tmp = pcicfgr32(p, 0x7C);
14142bd533dSDavid du Colombier 		scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
14242bd533dSDavid du Colombier 		break;
14342bd533dSDavid du Colombier 	case 0x01F0:
14442bd533dSDavid du Colombier 		p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
14542bd533dSDavid du Colombier 		tmp = pcicfgr32(p, 0x84);
14642bd533dSDavid du Colombier 		scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
14742bd533dSDavid du Colombier 		break;
14842bd533dSDavid du Colombier 	default:
1494de34a7eSDavid du Colombier 		q = (void*)((uchar*)scr->mmio + Pfb + 0x020C);
150a49e8198SDavid du Colombier 		tmp = (*q >> 20) & 0xFFF;
15142bd533dSDavid du Colombier 		if (tmp == 0)
15242bd533dSDavid du Colombier 			tmp = 16;
15342bd533dSDavid du Colombier 		scr->storage = tmp*1024*1024;
15442bd533dSDavid du Colombier 		break;
155bb0aa005SDavid du Colombier 	}
1569a747e4fSDavid du Colombier }
1579a747e4fSDavid du Colombier 
1589a747e4fSDavid du Colombier static void
nvidiacurdisable(VGAscr * scr)1599a747e4fSDavid du Colombier nvidiacurdisable(VGAscr* scr)
1609a747e4fSDavid du Colombier {
1614de34a7eSDavid du Colombier 	if(scr->mmio == 0)
1629a747e4fSDavid du Colombier 		return;
1639a747e4fSDavid du Colombier 
1649a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
1659a747e4fSDavid du Colombier }
1669a747e4fSDavid du Colombier 
167bb0aa005SDavid du Colombier 
1689a747e4fSDavid du Colombier static void
nvidiacurload(VGAscr * scr,Cursor * curs)1699a747e4fSDavid du Colombier nvidiacurload(VGAscr* scr, Cursor* curs)
1709a747e4fSDavid du Colombier {
1719a747e4fSDavid du Colombier 	ulong*	p;
1729a747e4fSDavid du Colombier 	int	i,j;
1739a747e4fSDavid du Colombier 	ushort	c,s;
1749a747e4fSDavid du Colombier 	ulong	tmp;
1759a747e4fSDavid du Colombier 
1764de34a7eSDavid du Colombier 	if(scr->mmio == 0)
1779a747e4fSDavid du Colombier 		return;
1789a747e4fSDavid du Colombier 
1799a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
1809a747e4fSDavid du Colombier 
18142bd533dSDavid du Colombier 	switch (scr->id & 0x0ff0) {
18242bd533dSDavid du Colombier 	case 0x0020:
18342bd533dSDavid du Colombier 	case 0x00A0:
1844de34a7eSDavid du Colombier 		p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);
18542bd533dSDavid du Colombier 		break;
18642bd533dSDavid du Colombier 	default:
187a7529a1dSDavid du Colombier 		/*
188a7529a1dSDavid du Colombier 		 * Reset the cursor location, since the kernel may
189a7529a1dSDavid du Colombier 		 * have allocated less storage than aux/vga
190a7529a1dSDavid du Colombier 		 * expected.
191a7529a1dSDavid du Colombier 		 */
192be6ef7ccSDavid du Colombier 		tmp = scr->apsize - 96*1024;
193a7529a1dSDavid du Colombier 		p = (void*)((uchar*)scr->vaddr + tmp);
194a7529a1dSDavid du Colombier 		vgaxo(Crtx, 0x30, 0x80|(tmp>>17));
195a7529a1dSDavid du Colombier 		vgaxo(Crtx, 0x31, (tmp>>11)<<2);
196a7529a1dSDavid du Colombier 		vgaxo(Crtx, 0x2F, tmp>>24);
19742bd533dSDavid du Colombier 		break;
19842bd533dSDavid du Colombier 	}
1999a747e4fSDavid du Colombier 
2009a747e4fSDavid du Colombier 	for(i=0; i<16; i++) {
2019a747e4fSDavid du Colombier 		c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
2029a747e4fSDavid du Colombier 		s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
2039a747e4fSDavid du Colombier 		tmp = 0;
2049a747e4fSDavid du Colombier 		for (j=0; j<16; j++){
2059a747e4fSDavid du Colombier 			if(s&0x8000)
2069a747e4fSDavid du Colombier 				tmp |= 0x80000000;
2079a747e4fSDavid du Colombier 			else if(c&0x8000)
2089a747e4fSDavid du Colombier 				tmp |= 0xFFFF0000;
2099a747e4fSDavid du Colombier 			if (j&0x1){
2109a747e4fSDavid du Colombier 				*p++ = tmp;
2119a747e4fSDavid du Colombier 				tmp = 0;
2129a747e4fSDavid du Colombier 			} else {
2139a747e4fSDavid du Colombier 				tmp>>=16;
2149a747e4fSDavid du Colombier 			}
2159a747e4fSDavid du Colombier 			c<<=1;
2169a747e4fSDavid du Colombier 			s<<=1;
2179a747e4fSDavid du Colombier 		}
2189a747e4fSDavid du Colombier 		for (j=0; j<8; j++)
2199a747e4fSDavid du Colombier 			*p++ = 0;
2209a747e4fSDavid du Colombier 	}
2219a747e4fSDavid du Colombier 	for (i=0; i<256; i++)
2229a747e4fSDavid du Colombier 		*p++ = 0;
2239a747e4fSDavid du Colombier 
2249a747e4fSDavid du Colombier 	scr->offset = curs->offset;
2259a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
2269a747e4fSDavid du Colombier 
2279a747e4fSDavid du Colombier 	return;
2289a747e4fSDavid du Colombier }
2299a747e4fSDavid du Colombier 
2309a747e4fSDavid du Colombier static int
nvidiacurmove(VGAscr * scr,Point p)2319a747e4fSDavid du Colombier nvidiacurmove(VGAscr* scr, Point p)
2329a747e4fSDavid du Colombier {
2339a747e4fSDavid du Colombier 	ulong*	cursorpos;
2349a747e4fSDavid du Colombier 
2354de34a7eSDavid du Colombier 	if(scr->mmio == 0)
2369a747e4fSDavid du Colombier 		return 1;
2379a747e4fSDavid du Colombier 
2384de34a7eSDavid du Colombier 	cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);
2399a747e4fSDavid du Colombier 	*cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
2409a747e4fSDavid du Colombier 
2419a747e4fSDavid du Colombier 	return 0;
2429a747e4fSDavid du Colombier }
2439a747e4fSDavid du Colombier 
2449a747e4fSDavid du Colombier static void
nvidiacurenable(VGAscr * scr)2459a747e4fSDavid du Colombier nvidiacurenable(VGAscr* scr)
2469a747e4fSDavid du Colombier {
2479a747e4fSDavid du Colombier 	nvidiaenable(scr);
2484de34a7eSDavid du Colombier 	if(scr->mmio == 0)
2499a747e4fSDavid du Colombier 		return;
2509a747e4fSDavid du Colombier 
2519a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x1F, 0x57);
2529a747e4fSDavid du Colombier 
2539a747e4fSDavid du Colombier 	nvidiacurload(scr, &arrow);
2549a747e4fSDavid du Colombier 	nvidiacurmove(scr, ZP);
2559a747e4fSDavid du Colombier 
2569a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
2579a747e4fSDavid du Colombier }
2589a747e4fSDavid du Colombier 
259bb0aa005SDavid du Colombier void
writeput(VGAscr * scr,int data)260bb0aa005SDavid du Colombier writeput(VGAscr *scr, int data)
261bb0aa005SDavid du Colombier {
262bb0aa005SDavid du Colombier 	uchar	*p, scratch;
263bb0aa005SDavid du Colombier 	ulong	*fifo;
2649a747e4fSDavid du Colombier 
265bb0aa005SDavid du Colombier 	outb(0x3D0,0);
2664de34a7eSDavid du Colombier 	p = scr->vaddr;
267bb0aa005SDavid du Colombier 	scratch = *p;
2684de34a7eSDavid du Colombier 	fifo = (void*)((uchar*)scr->mmio + Fifo);
269bb0aa005SDavid du Colombier 	fifo[0x10] = (data << 2);
270bb0aa005SDavid du Colombier 	USED(scratch);
271bb0aa005SDavid du Colombier }
2729a747e4fSDavid du Colombier 
273bb0aa005SDavid du Colombier ulong
readget(VGAscr * scr)274bb0aa005SDavid du Colombier readget(VGAscr *scr)
275bb0aa005SDavid du Colombier {
276bb0aa005SDavid du Colombier 	ulong	*fifo;
2779a747e4fSDavid du Colombier 
2784de34a7eSDavid du Colombier 	fifo = (void*)((uchar*)scr->mmio + Fifo);
279bb0aa005SDavid du Colombier 	return (fifo[0x0011] >> 2);
280bb0aa005SDavid du Colombier }
2819a747e4fSDavid du Colombier 
282bb0aa005SDavid du Colombier void
nvdmakickoff(VGAscr * scr)283bb0aa005SDavid du Colombier nvdmakickoff(VGAscr *scr)
284bb0aa005SDavid du Colombier {
285bb0aa005SDavid du Colombier 	if(nv.dmacurrent != nv.dmaput) {
286bb0aa005SDavid du Colombier 		nv.dmaput = nv.dmacurrent;
287bb0aa005SDavid du Colombier 		writeput(scr, nv.dmaput);
288bb0aa005SDavid du Colombier 	}
289bb0aa005SDavid du Colombier }
2909a747e4fSDavid du Colombier 
291bb0aa005SDavid du Colombier static void
nvdmanext(ulong data)292bb0aa005SDavid du Colombier nvdmanext(ulong data)
293bb0aa005SDavid du Colombier {
294bb0aa005SDavid du Colombier 	nv.dmabase[nv.dmacurrent++] = data;
295bb0aa005SDavid du Colombier }
296bb0aa005SDavid du Colombier 
297bb0aa005SDavid du Colombier void
nvdmawait(VGAscr * scr,int size)298bb0aa005SDavid du Colombier nvdmawait(VGAscr *scr, int size)
299bb0aa005SDavid du Colombier {
300bb0aa005SDavid du Colombier 	int dmaget;
301bb0aa005SDavid du Colombier 
302bb0aa005SDavid du Colombier 	size++;
303bb0aa005SDavid du Colombier 
304bb0aa005SDavid du Colombier 	while(nv.dmafree < size) {
305bb0aa005SDavid du Colombier 		dmaget = readget(scr);
306bb0aa005SDavid du Colombier 
307bb0aa005SDavid du Colombier 		if(nv.dmaput >= dmaget) {
308bb0aa005SDavid du Colombier 			nv.dmafree = nv.dmamax - nv.dmacurrent;
309bb0aa005SDavid du Colombier 			if(nv.dmafree < size) {
310bb0aa005SDavid du Colombier 				nvdmanext(0x20000000);
311bb0aa005SDavid du Colombier 				if(dmaget <= SKIPS) {
312bb0aa005SDavid du Colombier 					if (nv.dmaput <= SKIPS) /* corner case - will be idle */
313bb0aa005SDavid du Colombier 						writeput(scr, SKIPS + 1);
314bb0aa005SDavid du Colombier 					do { dmaget = readget(scr); }
315bb0aa005SDavid du Colombier 					while(dmaget <= SKIPS);
316bb0aa005SDavid du Colombier 				}
317bb0aa005SDavid du Colombier 				writeput(scr, SKIPS);
318bb0aa005SDavid du Colombier 				nv.dmacurrent = nv.dmaput = SKIPS;
319bb0aa005SDavid du Colombier 				nv.dmafree = dmaget - (SKIPS + 1);
320bb0aa005SDavid du Colombier 			}
321bb0aa005SDavid du Colombier 		} else
322bb0aa005SDavid du Colombier 			nv.dmafree = dmaget - nv.dmacurrent - 1;
323bb0aa005SDavid du Colombier 	}
324bb0aa005SDavid du Colombier }
325bb0aa005SDavid du Colombier 
326bb0aa005SDavid du Colombier 
327bb0aa005SDavid du Colombier static void
nvdmastart(VGAscr * scr,ulong tag,int size)328bb0aa005SDavid du Colombier nvdmastart(VGAscr *scr, ulong tag, int size)
329bb0aa005SDavid du Colombier {
330bb0aa005SDavid du Colombier 	if (nv.dmafree <= size)
331bb0aa005SDavid du Colombier 		nvdmawait(scr, size);
332bb0aa005SDavid du Colombier 	nvdmanext((size << 18) | tag);
333bb0aa005SDavid du Colombier 	nv.dmafree -= (size + 1);
334bb0aa005SDavid du Colombier }
3359a747e4fSDavid du Colombier 
3369a747e4fSDavid du Colombier static void
waitforidle(VGAscr * scr)3379a747e4fSDavid du Colombier waitforidle(VGAscr *scr)
3389a747e4fSDavid du Colombier {
3399a747e4fSDavid du Colombier 	ulong*	pgraph;
3409a747e4fSDavid du Colombier 	int x;
3419a747e4fSDavid du Colombier 
3424de34a7eSDavid du Colombier 	pgraph = (void*)((uchar*)scr->mmio + Pgraph);
3439a747e4fSDavid du Colombier 
3449a747e4fSDavid du Colombier 	x = 0;
345bb0aa005SDavid du Colombier 	while((readget(scr) != nv.dmaput) && x++ < 1000000)
346bb0aa005SDavid du Colombier 		;
347bb0aa005SDavid du Colombier 	if(x >= 1000000)
348567483c8SDavid du Colombier 		iprint("idle stat %lud put %d scr %#p pc %#p\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
349bb0aa005SDavid du Colombier 
350bb0aa005SDavid du Colombier 	x = 0;
3519a747e4fSDavid du Colombier 	while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
3529a747e4fSDavid du Colombier 		;
3539a747e4fSDavid du Colombier 
3549a747e4fSDavid du Colombier 	if(x >= 1000000)
355567483c8SDavid du Colombier 		iprint("idle stat %lud scrio %#p scr %#p pc %#p\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
3569a747e4fSDavid du Colombier }
3579a747e4fSDavid du Colombier 
3589a747e4fSDavid du Colombier static void
nvresetgraphics(VGAscr * scr)359bb0aa005SDavid du Colombier nvresetgraphics(VGAscr *scr)
3609a747e4fSDavid du Colombier {
361bb0aa005SDavid du Colombier 	ulong	surfaceFormat, patternFormat, rectFormat, lineFormat;
362bb0aa005SDavid du Colombier 	int		pitch, i;
3639a747e4fSDavid du Colombier 
364bb0aa005SDavid du Colombier 	pitch = scr->gscreen->width*BY2WD;
3659a747e4fSDavid du Colombier 
366be6ef7ccSDavid du Colombier 	/*
367be6ef7ccSDavid du Colombier 	 * DMA is at the end of the virtual window,
368be6ef7ccSDavid du Colombier 	 * but we might have cut it short when mapping it.
369be6ef7ccSDavid du Colombier 	 */
370be6ef7ccSDavid du Colombier 	if(nv.dmabase == nil){
371be6ef7ccSDavid du Colombier 		if(scr->storage <= scr->apsize)
372be6ef7ccSDavid du Colombier 			nv.dmabase = (ulong*)((uchar*)scr->vaddr + scr->storage - 128*1024);
373be6ef7ccSDavid du Colombier 		else{
374be6ef7ccSDavid du Colombier 			nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);
375be6ef7ccSDavid du Colombier 			if(nv.dmabase == 0){
376be6ef7ccSDavid du Colombier 				hwaccel = 0;
377be6ef7ccSDavid du Colombier 				hwblank = 0;
378be6ef7ccSDavid du Colombier 				print("vmap nvidia dma failed\n");
379be6ef7ccSDavid du Colombier 				return;
380be6ef7ccSDavid du Colombier 			}
381be6ef7ccSDavid du Colombier 		}
382be6ef7ccSDavid du Colombier 	}
3839a747e4fSDavid du Colombier 
384bb0aa005SDavid du Colombier 	for(i=0; i<SKIPS; i++)
385bb0aa005SDavid du Colombier 		nv.dmabase[i] = 0x00000000;
386bb0aa005SDavid du Colombier 
387bb0aa005SDavid du Colombier 	nv.dmabase[0x0 + SKIPS] = 0x00040000;
388bb0aa005SDavid du Colombier 	nv.dmabase[0x1 + SKIPS] = 0x80000010;
389bb0aa005SDavid du Colombier 	nv.dmabase[0x2 + SKIPS] = 0x00042000;
390bb0aa005SDavid du Colombier 	nv.dmabase[0x3 + SKIPS] = 0x80000011;
391bb0aa005SDavid du Colombier 	nv.dmabase[0x4 + SKIPS] = 0x00044000;
392bb0aa005SDavid du Colombier 	nv.dmabase[0x5 + SKIPS] = 0x80000012;
393bb0aa005SDavid du Colombier 	nv.dmabase[0x6 + SKIPS] = 0x00046000;
394bb0aa005SDavid du Colombier 	nv.dmabase[0x7 + SKIPS] = 0x80000013;
395bb0aa005SDavid du Colombier 	nv.dmabase[0x8 + SKIPS] = 0x00048000;
396bb0aa005SDavid du Colombier 	nv.dmabase[0x9 + SKIPS] = 0x80000014;
397bb0aa005SDavid du Colombier 	nv.dmabase[0xA + SKIPS] = 0x0004A000;
398bb0aa005SDavid du Colombier 	nv.dmabase[0xB + SKIPS] = 0x80000015;
399bb0aa005SDavid du Colombier 	nv.dmabase[0xC + SKIPS] = 0x0004C000;
400bb0aa005SDavid du Colombier 	nv.dmabase[0xD + SKIPS] = 0x80000016;
401bb0aa005SDavid du Colombier 	nv.dmabase[0xE + SKIPS] = 0x0004E000;
402bb0aa005SDavid du Colombier 	nv.dmabase[0xF + SKIPS] = 0x80000017;
403bb0aa005SDavid du Colombier 
404bb0aa005SDavid du Colombier 	nv.dmaput = 0;
405bb0aa005SDavid du Colombier 	nv.dmacurrent = 16 + SKIPS;
406bb0aa005SDavid du Colombier 	nv.dmamax = 8191;
407bb0aa005SDavid du Colombier 	nv.dmafree = nv.dmamax - nv.dmacurrent;
408bb0aa005SDavid du Colombier 
409bb0aa005SDavid du Colombier 	switch(scr->gscreen->depth) {
410bb0aa005SDavid du Colombier 	case 32:
411bb0aa005SDavid du Colombier 	case 24:
412bb0aa005SDavid du Colombier 		surfaceFormat = SURFACE_FORMAT_DEPTH24;
413bb0aa005SDavid du Colombier 		patternFormat = PATTERN_FORMAT_DEPTH24;
414bb0aa005SDavid du Colombier 		rectFormat = RECT_FORMAT_DEPTH24;
415bb0aa005SDavid du Colombier 		lineFormat = LINE_FORMAT_DEPTH24;
416bb0aa005SDavid du Colombier 		break;
417bb0aa005SDavid du Colombier 	case 16:
418bb0aa005SDavid du Colombier 	case 15:
419bb0aa005SDavid du Colombier 		surfaceFormat = SURFACE_FORMAT_DEPTH16;
420bb0aa005SDavid du Colombier 		patternFormat = PATTERN_FORMAT_DEPTH16;
421bb0aa005SDavid du Colombier 		rectFormat = RECT_FORMAT_DEPTH16;
422bb0aa005SDavid du Colombier 		lineFormat = LINE_FORMAT_DEPTH16;
423bb0aa005SDavid du Colombier 		break;
424bb0aa005SDavid du Colombier 	default:
425bb0aa005SDavid du Colombier 		surfaceFormat = SURFACE_FORMAT_DEPTH8;
426bb0aa005SDavid du Colombier 		patternFormat = PATTERN_FORMAT_DEPTH8;
427bb0aa005SDavid du Colombier 		rectFormat = RECT_FORMAT_DEPTH8;
428bb0aa005SDavid du Colombier 		lineFormat = LINE_FORMAT_DEPTH8;
429bb0aa005SDavid du Colombier 		break;
4309a747e4fSDavid du Colombier 	}
4319a747e4fSDavid du Colombier 
432bb0aa005SDavid du Colombier 	nvdmastart(scr, SURFACE_FORMAT, 4);
433bb0aa005SDavid du Colombier 	nvdmanext(surfaceFormat);
434bb0aa005SDavid du Colombier 	nvdmanext(pitch | (pitch << 16));
435bb0aa005SDavid du Colombier 	nvdmanext(0);
436bb0aa005SDavid du Colombier 	nvdmanext(0);
437bb0aa005SDavid du Colombier 
438bb0aa005SDavid du Colombier 	nvdmastart(scr, PATTERN_FORMAT, 1);
439bb0aa005SDavid du Colombier 	nvdmanext(patternFormat);
440bb0aa005SDavid du Colombier 
441bb0aa005SDavid du Colombier 	nvdmastart(scr, RECT_FORMAT, 1);
442bb0aa005SDavid du Colombier 	nvdmanext(rectFormat);
443bb0aa005SDavid du Colombier 
444bb0aa005SDavid du Colombier 	nvdmastart(scr, LINE_FORMAT, 1);
445bb0aa005SDavid du Colombier 	nvdmanext(lineFormat);
446bb0aa005SDavid du Colombier 
447bb0aa005SDavid du Colombier 	nvdmastart(scr, PATTERN_COLOR_0, 4);
448bb0aa005SDavid du Colombier 	nvdmanext(~0);
449bb0aa005SDavid du Colombier 	nvdmanext(~0);
450bb0aa005SDavid du Colombier 	nvdmanext(~0);
451bb0aa005SDavid du Colombier 	nvdmanext(~0);
452bb0aa005SDavid du Colombier 
453bb0aa005SDavid du Colombier 	nvdmastart(scr, ROP_SET, 1);
454bb0aa005SDavid du Colombier 	nvdmanext(0xCC);
455bb0aa005SDavid du Colombier 
456bb0aa005SDavid du Colombier 	nvdmakickoff(scr);
457bb0aa005SDavid du Colombier 	waitforidle(scr);
458bb0aa005SDavid du Colombier }
459bb0aa005SDavid du Colombier 
460bb0aa005SDavid du Colombier 
4619a747e4fSDavid du Colombier static int
nvidiahwfill(VGAscr * scr,Rectangle r,ulong sval)4629a747e4fSDavid du Colombier nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
4639a747e4fSDavid du Colombier {
464bb0aa005SDavid du Colombier 	nvdmastart(scr, RECT_SOLID_COLOR, 1);
465bb0aa005SDavid du Colombier 	nvdmanext(sval);
4669a747e4fSDavid du Colombier 
467bb0aa005SDavid du Colombier 	nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
468bb0aa005SDavid du Colombier 	nvdmanext((r.min.x << 16) | r.min.y);
469bb0aa005SDavid du Colombier 	nvdmanext((Dx(r) << 16) | Dy(r));
4709a747e4fSDavid du Colombier 
471bb0aa005SDavid du Colombier 	//if ( (Dy(r) * Dx(r)) >= 512)
472bb0aa005SDavid du Colombier 		nvdmakickoff(scr);
4739a747e4fSDavid du Colombier 
4749a747e4fSDavid du Colombier 	waitforidle(scr);
4759a747e4fSDavid du Colombier 
4769a747e4fSDavid du Colombier 	return 1;
4779a747e4fSDavid du Colombier }
4789a747e4fSDavid du Colombier 
4799a747e4fSDavid du Colombier static int
nvidiahwscroll(VGAscr * scr,Rectangle r,Rectangle sr)4809a747e4fSDavid du Colombier nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
4819a747e4fSDavid du Colombier {
482bb0aa005SDavid du Colombier 	nvdmastart(scr, BLIT_POINT_SRC, 3);
483bb0aa005SDavid du Colombier 	nvdmanext((sr.min.y << 16) | sr.min.x);
484bb0aa005SDavid du Colombier 	nvdmanext((r.min.y << 16) | r.min.x);
485bb0aa005SDavid du Colombier 	nvdmanext((Dy(r) << 16) | Dx(r));
4869a747e4fSDavid du Colombier 
487bb0aa005SDavid du Colombier 	//if ( (Dy(r) * Dx(r)) >= 512)
488bb0aa005SDavid du Colombier 		nvdmakickoff(scr);
4899a747e4fSDavid du Colombier 
4909a747e4fSDavid du Colombier 	waitforidle(scr);
4919a747e4fSDavid du Colombier 
4929a747e4fSDavid du Colombier 	return 1;
4939a747e4fSDavid du Colombier }
4949a747e4fSDavid du Colombier 
4959a747e4fSDavid du Colombier void
nvidiablank(VGAscr *,int blank)4969a747e4fSDavid du Colombier nvidiablank(VGAscr*, int blank)
4979a747e4fSDavid du Colombier {
4989a747e4fSDavid du Colombier 	uchar seq1, crtc1A;
4999a747e4fSDavid du Colombier 
5009a747e4fSDavid du Colombier 	seq1 = vgaxi(Seqx, 1) & ~0x20;
5019a747e4fSDavid du Colombier 	crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
5029a747e4fSDavid du Colombier 
5039a747e4fSDavid du Colombier 	if(blank){
5049a747e4fSDavid du Colombier 		seq1 |= 0x20;
5059a747e4fSDavid du Colombier //		crtc1A |= 0xC0;
5069a747e4fSDavid du Colombier 		crtc1A |= 0x80;
5079a747e4fSDavid du Colombier 	}
5089a747e4fSDavid du Colombier 
5099a747e4fSDavid du Colombier 	vgaxo(Seqx, 1, seq1);
5109a747e4fSDavid du Colombier 	vgaxo(Crtx, 0x1A, crtc1A);
5119a747e4fSDavid du Colombier }
5129a747e4fSDavid du Colombier 
5139a747e4fSDavid du Colombier static void
nvidiadrawinit(VGAscr * scr)5149a747e4fSDavid du Colombier nvidiadrawinit(VGAscr *scr)
5159a747e4fSDavid du Colombier {
516bb0aa005SDavid du Colombier 	nvresetgraphics(scr);
5179a747e4fSDavid du Colombier 	scr->blank = nvidiablank;
5189a747e4fSDavid du Colombier 	hwblank = 1;
5199a747e4fSDavid du Colombier 	scr->fill = nvidiahwfill;
5209a747e4fSDavid du Colombier 	scr->scroll = nvidiahwscroll;
5219a747e4fSDavid du Colombier }
5229a747e4fSDavid du Colombier 
5239a747e4fSDavid du Colombier VGAdev vganvidiadev = {
5249a747e4fSDavid du Colombier 	"nvidia",
5259a747e4fSDavid du Colombier 
5269a747e4fSDavid du Colombier 	nvidiaenable,
5279a747e4fSDavid du Colombier 	nil,
5289a747e4fSDavid du Colombier 	nil,
5299a747e4fSDavid du Colombier 	nvidialinear,
5309a747e4fSDavid du Colombier 	nvidiadrawinit,
5319a747e4fSDavid du Colombier };
5329a747e4fSDavid du Colombier 
5339a747e4fSDavid du Colombier VGAcur vganvidiacur = {
5349a747e4fSDavid du Colombier 	"nvidiahwgc",
5359a747e4fSDavid du Colombier 
5369a747e4fSDavid du Colombier 	nvidiacurenable,
5379a747e4fSDavid du Colombier 	nvidiacurdisable,
5389a747e4fSDavid du Colombier 	nvidiacurload,
5399a747e4fSDavid du Colombier 	nvidiacurmove,
5409a747e4fSDavid du Colombier };
541