📄 nvidia.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 <libc.h>#include <bio.h>#include "pci.h"#include "vga.h"typedef struct Nvidia Nvidia;struct Nvidia { Pcidev* pci; int did; /* not always == pci->did */ int arch; int crystalfreq; ulong* mmio; ulong* pfb; /* mmio pointers */ ulong* pramdac; ulong* pextdev; ulong* pmc; ulong* ptimer; ulong* pfifo; ulong* pramin; ulong* pgraph; ulong* fifo; ulong* pcrtc; ushort repaint0; ushort repaint1; ushort screen; ushort pixel; ushort horiz; ushort cursor0; ushort cursor1; ushort cursor2; ushort interlace; ushort extra; ushort crtcowner; ushort timingH; ushort timingV; ulong vpll; ulong vpllB; ulong vpll2; ulong vpll2B; ulong pllsel; ulong general; ulong scale; ulong config; ulong head; ulong head2; ulong cursorconfig; ulong dither; ulong crtcsync; ulong displayV; int islcd; int fpwidth; int fpheight; int twoheads; int twostagepll; int crtcnumber;};static voidgetpcixdid(Nvidia* nv){ ulong pcicmd, pciid; ushort vid, did; pcicmd = pcicfgr32(nv->pci, PciPCR); pcicfgw32(nv->pci, PciPCR, pcicmd | 0x02); pciid = nv->mmio[0x1800/4]; pcicfgw32(nv->pci, PciPCR, pcicmd); vid = pciid >> 16; did = (pciid & 0xFFFF); if (did == 0x10DE) did = vid; else if (vid == 0xDE10) did = ((pciid << 8) & 0xFF00) | ((pciid >> 8) & 0x00FF); nv->did = did;}static voidsnarf(Vga* vga, Ctlr* ctlr){ Nvidia *nv; Pcidev *p; ulong *mmio, tmp; int implementation; if(vga->private == nil){ vga->private = alloc(sizeof(Nvidia)); nv = vga->private; p = nil; while((p = pcimatch(p, 0x10DE, 0)) != nil){ if((p->ccru>>8) == 3) break; } if(p == nil) error("%s: not found\n", ctlr->name); vgactlw("type", ctlr->name); mmio = segattach(0, "nvidiammio", 0, p->mem[0].size); if(mmio == (void*)-1) error("%s: segattach nvidiammio, size %d: %r\n", ctlr->name, p->mem[0].size); nv->pci = p; nv->mmio = mmio; nv->pfb = mmio+0x00100000/4; nv->pramdac = mmio+0x00680000/4; nv->pextdev = mmio+0x00101000/4; nv->pmc = mmio+0x00000000/4; nv->ptimer = mmio+0x00009000/4; nv->pfifo = mmio+0x00002000/4; nv->pramin = mmio+0x00710000/4; nv->pgraph = mmio+0x00400000/4; nv->fifo = mmio+0x00800000/4; nv->pcrtc= mmio+0x00600000/4; nv->did = p->did; if ((nv->did & 0xfff0) == 0x00f0) getpcixdid(nv); switch (nv->did & 0x0ff0) { case 0x0020: case 0x00A0: nv->arch = 4; break; case 0x0100: /* GeForce 256 */ case 0x0110: /* GeForce2 MX */ case 0x0150: /* GeForce2 */ case 0x0170: /* GeForce4 MX */ case 0x0180: /* GeForce4 MX (8x AGP) */ case 0x01A0: /* nForce */ case 0x01F0: /* nForce2 */ nv->arch = 10; break; case 0x0200: /* GeForce3 */ case 0x0250: /* GeForce4 Ti */ case 0x0280: /* GeForce4 Ti (8x AGP) */ nv->arch = 20; break; case 0x0300: /* GeForceFX 5800 */ case 0x0310: /* GeForceFX 5600 */ case 0x0320: /* GeForceFX 5200 */ case 0x0330: /* GeForceFX 5900 */ case 0x0340: /* GeForceFX 5700 */ nv->arch = 30; break; case 0x0040: case 0x00C0: case 0x0120: case 0x0130: case 0x0140: /* GeForce 6600 */ case 0x0160: case 0x01D0: case 0x0090: case 0x0210: nv->arch = 40; break; default: error("%s: DID %4.4uX unsupported\n", ctlr->name, nv->did); break; } } nv = vga->private; implementation = nv->did & 0x0ff0; /* * Unlock */ vgaxo(Crtx, 0x1F, 0x57); if (nv->pextdev[0x00000000] & 0x00000040) nv->crystalfreq = RefFreq; else nv->crystalfreq = 13500000; if ((implementation == 0x0170) || (implementation == 0x0180) || (implementation == 0x01F0) || (implementation >= 0x0250)) if(nv->pextdev[0x00000000] & (1 << 22)) nv->crystalfreq = 27000000; nv->twoheads = (nv->arch >= 10) && (implementation != 0x0100) && (implementation != 0x0150) && (implementation != 0x01A0) && (implementation != 0x0200); nv->twostagepll = (implementation == 0x0310) || (implementation == 0x0340) || (nv->arch >= 40); if (nv->twoheads && (implementation != 0x0110)) if(nv->pextdev[0x00000000] & (1 << 22)) nv->crystalfreq = 27000000; /* laptop chips */ switch (nv->did & 0xffff) { case 0x0112: case 0x0174: case 0x0175: case 0x0176: case 0x0177: case 0x0179: case 0x017C: case 0x017D: case 0x0186: case 0x0187: case 0x0189: /* 0x0189 not in nwaples's driver */ case 0x018D: case 0x0286: case 0x028C: case 0x0316: case 0x0317: case 0x031A: case 0x031B: case 0x031C: case 0x031D: case 0x031E: case 0x031F: case 0x0324: case 0x0325: case 0x0328: case 0x0329: case 0x032C: case 0x032D: case 0x0347: case 0x0348: case 0x0349: case 0x034B: case 0x034C: case 0x0160: case 0x0166: case 0x00C8: case 0x00CC: case 0x0144: case 0x0146: case 0x0148: nv->islcd = 1; break; default: break; } if (nv->arch == 4) { tmp = nv->pfb[0x00000000]; if (tmp & 0x0100) { vga->vmz = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2; } else { tmp &= 0x03; if (tmp) vga->vmz = (1024*1024*2) << tmp; else vga->vmz = 1024*1024*32; } } else if (implementation == 0x01a0) { p = nil; tmp = MKBUS(BusPCI, 0, 0, 1); while((p = pcimatch(p, 0x10DE, 0)) != nil){ if(p->tbdf == tmp) break; } tmp = pcicfgr32(p, 0x7C); vga->vmz = (((tmp >> 6) & 31) + 1) * 1024 * 1024; } else if (implementation == 0x01f0) { p = nil; tmp = MKBUS(BusPCI, 0, 0, 1); while((p = pcimatch(p, 0x10DE, 0)) != nil){ if(p->tbdf == tmp) break; } tmp = pcicfgr32(p, 0x84); vga->vmz = (((tmp >> 4) & 127) + 1) * 1024 * 1024; } else { tmp = (nv->pfb[0x0000020C/4] >> 20) & 0xFFF; if (tmp == 0) tmp = 16; vga->vmz = 1024*1024*tmp; } nv->repaint0 = vgaxi(Crtx, 0x19); nv->repaint1 = vgaxi(Crtx, 0x1A); nv->screen = vgaxi(Crtx, 0x25); nv->pixel = vgaxi(Crtx, 0x28); nv->horiz = vgaxi(Crtx, 0x2D); nv->cursor0 = vgaxi(Crtx, 0x30); nv->cursor1 = vgaxi(Crtx, 0x31); nv->cursor2 = vgaxi(Crtx, 0x2F); nv->interlace = vgaxi(Crtx, 0x39); nv->vpll = nv->pramdac[0x00000508/4]; if (nv->twoheads) nv->vpll2 = nv->pramdac[0x00000520/4]; if (nv->twostagepll) { nv->vpllB = nv->pramdac[0x00000578/4]; nv->vpll2B = nv->pramdac[0x0000057C/4]; } nv->pllsel = nv->pramdac[0x0000050C/4]; nv->general = nv->pramdac[0x00000600/4]; nv->scale = nv->pramdac[0x00000848/4]; nv->config = nv->pfb[0x00000200/4]; if (nv->pixel & 0x80){ nv->islcd = 1; } if (nv->arch >= 10) { if (nv->twoheads) { nv->head = nv->pcrtc[0x0860/4]; nv->head2 = nv->pcrtc[0x2860/4]; nv->crtcowner = vgaxi(Crtx, 0x44); } nv->extra = vgaxi(Crtx, 0x41); nv->cursorconfig = nv->pcrtc[0x0810/4]; if (implementation == 0x0110) nv->dither = nv->pramdac[0x0528/4]; else if (nv->twoheads) nv->dither = nv->pramdac[0x083C/4]; } /* * DFP. */ if (nv->islcd) { nv->fpwidth = nv->pramdac[0x0820/4] + 1; nv->fpheight = nv->pramdac[0x0800/4] + 1; nv->crtcsync = nv->pramdac[0x0828/4]; } nv->crtcnumber = 0; ctlr->flag |= Fsnarf;}static voidoptions(Vga*, Ctlr* ctlr){ ctlr->flag |= Hlinear|Foptions;}static voidclock(Vga* vga, Ctlr* ctlr){ int m, n, p, f, d; Nvidia *nv; double trouble; int fmin, mmin, nmin, crystalfreq; nv = vga->private; if(vga->f[0] == 0) vga->f[0] = vga->mode->frequency; vga->d[0] = vga->f[0]+1; vga->n[1] = 255; if (nv->twostagepll) { vga->p[1] = 6; vga->m[1] = 13; vga->f[1] = 400000000 << 2; crystalfreq = nv->crystalfreq << 2; fmin = 100000000 << 2; mmin = 1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -