The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/pc/vganvidia.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 
    2 /* Portions of this file derived from work with the following copyright */
    3 
    4  /***************************************************************************\
    5 |*                                                                           *|
    6 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
    7 |*                                                                           *|
    8 |*     NOTICE TO USER:   The source code  is copyrighted under  U.S. and     *|
    9 |*     international laws.  Users and possessors of this source code are     *|
   10 |*     hereby granted a nonexclusive,  royalty-free copyright license to     *|
   11 |*     use this code in individual and commercial software.                  *|
   12 |*                                                                           *|
   13 |*     Any use of this source code must include,  in the user documenta-     *|
   14 |*     tion and  internal comments to the code,  notices to the end user     *|
   15 |*     as follows:                                                           *|
   16 |*                                                                           *|
   17 |*       Copyright 2003 NVIDIA, Corporation.  All rights reserved.           *|
   18 |*                                                                           *|
   19 |*     NVIDIA, CORPORATION MAKES NO REPRESENTATION ABOUT THE SUITABILITY     *|
   20 |*     OF  THIS SOURCE  CODE  FOR ANY PURPOSE.  IT IS  PROVIDED  "AS IS"     *|
   21 |*     WITHOUT EXPRESS OR IMPLIED WARRANTY OF ANY KIND.  NVIDIA, CORPOR-     *|
   22 |*     ATION DISCLAIMS ALL WARRANTIES  WITH REGARD  TO THIS SOURCE CODE,     *|
   23 |*     INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGE-     *|
   24 |*     MENT,  AND FITNESS  FOR A PARTICULAR PURPOSE.   IN NO EVENT SHALL     *|
   25 |*     NVIDIA, CORPORATION  BE LIABLE FOR ANY SPECIAL,  INDIRECT,  INCI-     *|
   26 |*     DENTAL, OR CONSEQUENTIAL DAMAGES,  OR ANY DAMAGES  WHATSOEVER RE-     *|
   27 |*     SULTING FROM LOSS OF USE,  DATA OR PROFITS,  WHETHER IN AN ACTION     *|
   28 |*     OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,  ARISING OUT OF     *|
   29 |*     OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOURCE CODE.     *|
   30 |*                                                                           *|
   31 |*     U.S. Government  End  Users.   This source code  is a "commercial     *|
   32 |*     item,"  as that  term is  defined at  48 C.F.R. 2.101 (OCT 1995),     *|
   33 |*     consisting  of "commercial  computer  software"  and  "commercial     *|
   34 |*     computer  software  documentation,"  as such  terms  are  used in     *|
   35 |*     48 C.F.R. 12.212 (SEPT 1995)  and is provided to the U.S. Govern-     *|
   36 |*     ment only as  a commercial end item.   Consistent with  48 C.F.R.     *|
   37 |*     12.212 and  48 C.F.R. 227.7202-1 through  227.7202-4 (JUNE 1995),     *|
   38 |*     all U.S. Government End Users  acquire the source code  with only     *|
   39 |*     those rights set forth herein.                                        *|
   40 |*                                                                           *|
   41  \***************************************************************************/
   42 
   43 #include "u.h"
   44 #include "../port/lib.h"
   45 #include "mem.h"
   46 #include "dat.h"
   47 #include "fns.h"
   48 #include "io.h"
   49 #include "../port/error.h"
   50 
   51 #define Image   IMAGE
   52 #include <draw.h>
   53 #include <memdraw.h>
   54 #include <cursor.h>
   55 #include "screen.h"
   56 #include "nv_dma.h"
   57 
   58 enum {
   59         Pramin = 0x00710000,
   60         Pramdac = 0x00680000,
   61         Fifo = 0x00800000,
   62         Pgraph = 0x00400000,
   63         Pfb = 0x00100000
   64 };
   65 
   66 enum {
   67         hwCurPos = Pramdac + 0x0300,
   68 };
   69 
   70 #define SKIPS 8
   71 
   72 struct {
   73         ulong   *dmabase;
   74         int             dmacurrent;
   75         int             dmaput;
   76         int             dmafree;
   77         int             dmamax;
   78 } nv;
   79 
   80 static Pcidev*
   81 nvidiapci(void)
   82 {
   83         Pcidev *p;
   84 
   85         p = nil;
   86         while((p = pcimatch(p, 0x10DE, 0)) != nil){
   87                 if(p->did >= 0x20 && p->ccrb == 3)      /* video card */
   88                         return p;
   89         }
   90         return nil;
   91 }
   92 
   93 static void
   94 nvidialinear(VGAscr*, int, int)
   95 {
   96 }
   97 
   98 static void
   99 nvidiaenable(VGAscr* scr)
  100 {
  101         Pcidev *p;
  102         ulong *q;
  103         int tmp;
  104 
  105         if(scr->mmio)
  106                 return;
  107         p = nvidiapci();
  108         if(p == nil)
  109                 return;
  110         scr->id = p->did;
  111         scr->pci = p;
  112 
  113         scr->mmio = vmap(p->mem[0].bar & ~0x0F, p->mem[0].size);
  114         if(scr->mmio == nil)
  115                 return;
  116         addvgaseg("nvidiammio", p->mem[0].bar&~0x0F, p->mem[0].size);
  117 
  118         vgalinearpci(scr);
  119         if(scr->apsize)
  120                 addvgaseg("nvidiascreen", scr->paddr, scr->apsize);
  121 
  122         /* find video memory size */
  123         switch (scr->id & 0x0ff0) {
  124         case 0x0020:
  125         case 0x00A0:
  126                 q = (void*)((uchar*)scr->mmio + Pfb);
  127                 tmp = *q;
  128                 if (tmp & 0x0100) {
  129                         scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
  130                 } else {
  131                         tmp &= 0x03;
  132                         if (tmp)
  133                                 scr->storage = (1024*1024*2) << tmp;
  134                         else
  135                                 scr->storage = 1024*1024*32;
  136                 }
  137                 break;
  138         case 0x01A0:
  139                 p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
  140                 tmp = pcicfgr32(p, 0x7C);
  141                 scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
  142                 break;
  143         case 0x01F0:
  144                 p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
  145                 tmp = pcicfgr32(p, 0x84);
  146                 scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
  147                 break;
  148         default:
  149                 q = (void*)((uchar*)scr->mmio + Pfb + 0x020C);
  150                 tmp = (*q >> 20) & 0xFFF;
  151                 if (tmp == 0)
  152                         tmp = 16;
  153                 scr->storage = tmp*1024*1024;
  154                 break;
  155         }
  156 }
  157 
  158 static void
  159 nvidiacurdisable(VGAscr* scr)
  160 {
  161         if(scr->mmio == 0)
  162                 return;
  163 
  164         vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  165 }
  166 
  167 
  168 static void
  169 nvidiacurload(VGAscr* scr, Cursor* curs)
  170 {
  171         ulong*  p;
  172         int     i,j;
  173         ushort  c,s;
  174         ulong   tmp;
  175 
  176         if(scr->mmio == 0)
  177                 return;
  178 
  179         vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  180 
  181         switch (scr->id & 0x0ff0) {
  182         case 0x0020:
  183         case 0x00A0:
  184                 p = (void*)((uchar*)scr->mmio + Pramin + 0x1E00 * 4);
  185                 break;
  186         default:
  187                 /*
  188                  * Reset the cursor location, since the kernel may
  189                  * have allocated less storage than aux/vga
  190                  * expected.
  191                  */
  192                 tmp = scr->apsize - 96*1024;
  193                 p = (void*)((uchar*)scr->vaddr + tmp);
  194                 vgaxo(Crtx, 0x30, 0x80|(tmp>>17));
  195                 vgaxo(Crtx, 0x31, (tmp>>11)<<2);
  196                 vgaxo(Crtx, 0x2F, tmp>>24);
  197                 break;
  198         }
  199 
  200         for(i=0; i<16; i++) {
  201                 c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
  202                 s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
  203                 tmp = 0;
  204                 for (j=0; j<16; j++){
  205                         if(s&0x8000)
  206                                 tmp |= 0x80000000;
  207                         else if(c&0x8000)
  208                                 tmp |= 0xFFFF0000;
  209                         if (j&0x1){
  210                                 *p++ = tmp;
  211                                 tmp = 0;
  212                         } else {
  213                                 tmp>>=16;
  214                         }
  215                         c<<=1;
  216                         s<<=1;
  217                 }
  218                 for (j=0; j<8; j++)
  219                         *p++ = 0;
  220         }
  221         for (i=0; i<256; i++)
  222                 *p++ = 0;
  223 
  224         scr->offset = curs->offset;
  225         vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  226 
  227         return;
  228 }
  229 
  230 static int
  231 nvidiacurmove(VGAscr* scr, Point p)
  232 {
  233         ulong*  cursorpos;
  234 
  235         if(scr->mmio == 0)
  236                 return 1;
  237 
  238         cursorpos = (void*)((uchar*)scr->mmio + hwCurPos);
  239         *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
  240 
  241         return 0;
  242 }
  243 
  244 static void
  245 nvidiacurenable(VGAscr* scr)
  246 {
  247         nvidiaenable(scr);
  248         if(scr->mmio == 0)
  249                 return;
  250 
  251         vgaxo(Crtx, 0x1F, 0x57);
  252 
  253         nvidiacurload(scr, &arrow);
  254         nvidiacurmove(scr, ZP);
  255 
  256         vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  257 }
  258 
  259 void
  260 writeput(VGAscr *scr, int data)
  261 {
  262         uchar   *p, scratch;
  263         ulong   *fifo;
  264 
  265         outb(0x3D0,0);
  266         p = scr->vaddr;
  267         scratch = *p;
  268         fifo = (void*)((uchar*)scr->mmio + Fifo);
  269         fifo[0x10] = (data << 2);
  270         USED(scratch);
  271 }
  272 
  273 ulong
  274 readget(VGAscr *scr)
  275 {
  276         ulong   *fifo;
  277 
  278         fifo = (void*)((uchar*)scr->mmio + Fifo);
  279         return (fifo[0x0011] >> 2);
  280 }
  281 
  282 void
  283 nvdmakickoff(VGAscr *scr)
  284 {
  285         if(nv.dmacurrent != nv.dmaput) {
  286                 nv.dmaput = nv.dmacurrent;
  287                 writeput(scr, nv.dmaput);
  288         }
  289 }
  290 
  291 static void
  292 nvdmanext(ulong data)
  293 {
  294         nv.dmabase[nv.dmacurrent++] = data;
  295 }
  296 
  297 void
  298 nvdmawait(VGAscr *scr, int size)
  299 {
  300         int dmaget;
  301 
  302         size++;
  303 
  304         while(nv.dmafree < size) {
  305                 dmaget = readget(scr);
  306 
  307                 if(nv.dmaput >= dmaget) {
  308                         nv.dmafree = nv.dmamax - nv.dmacurrent;
  309                         if(nv.dmafree < size) {
  310                                 nvdmanext(0x20000000);
  311                                 if(dmaget <= SKIPS) {
  312                                         if (nv.dmaput <= SKIPS) /* corner case - will be idle */
  313                                                 writeput(scr, SKIPS + 1);
  314                                         do { dmaget = readget(scr); }
  315                                         while(dmaget <= SKIPS);
  316                                 }
  317                                 writeput(scr, SKIPS);
  318                                 nv.dmacurrent = nv.dmaput = SKIPS;
  319                                 nv.dmafree = dmaget - (SKIPS + 1);
  320                         }
  321                 } else
  322                         nv.dmafree = dmaget - nv.dmacurrent - 1;
  323         }
  324 }
  325 
  326 
  327 static void
  328 nvdmastart(VGAscr *scr, ulong tag, int size)
  329 {
  330         if (nv.dmafree <= size)
  331                 nvdmawait(scr, size);
  332         nvdmanext((size << 18) | tag);
  333         nv.dmafree -= (size + 1);
  334 }
  335 
  336 static void
  337 waitforidle(VGAscr *scr)
  338 {
  339         ulong*  pgraph;
  340         int x;
  341 
  342         pgraph = (void*)((uchar*)scr->mmio + Pgraph);
  343 
  344         x = 0;
  345         while((readget(scr) != nv.dmaput) && x++ < 1000000)
  346                 ;
  347         if(x >= 1000000)
  348                 iprint("idle stat %lud put %d scr %#p pc %#p\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
  349 
  350         x = 0;
  351         while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
  352                 ;
  353 
  354         if(x >= 1000000)
  355                 iprint("idle stat %lud scrio %#p scr %#p pc %#p\n", *pgraph, scr->mmio, scr, getcallerpc(&scr));
  356 }
  357 
  358 static void
  359 nvresetgraphics(VGAscr *scr)
  360 {
  361         ulong   surfaceFormat, patternFormat, rectFormat, lineFormat;
  362         int             pitch, i;
  363 
  364         pitch = scr->gscreen->width*BY2WD;
  365 
  366         /*
  367          * DMA is at the end of the virtual window,
  368          * but we might have cut it short when mapping it.
  369          */
  370         if(nv.dmabase == nil){
  371                 if(scr->storage <= scr->apsize)
  372                         nv.dmabase = (ulong*)((uchar*)scr->vaddr + scr->storage - 128*1024);
  373                 else{
  374                         nv.dmabase = (void*)vmap(scr->paddr + scr->storage - 128*1024, 128*1024);
  375                         if(nv.dmabase == 0){
  376                                 hwaccel = 0;
  377                                 hwblank = 0;
  378                                 print("vmap nvidia dma failed\n");
  379                                 return;
  380                         }
  381                 }
  382         }
  383 
  384         for(i=0; i<SKIPS; i++)
  385                 nv.dmabase[i] = 0x00000000;
  386 
  387         nv.dmabase[0x0 + SKIPS] = 0x00040000;
  388         nv.dmabase[0x1 + SKIPS] = 0x80000010;
  389         nv.dmabase[0x2 + SKIPS] = 0x00042000;
  390         nv.dmabase[0x3 + SKIPS] = 0x80000011;
  391         nv.dmabase[0x4 + SKIPS] = 0x00044000;
  392         nv.dmabase[0x5 + SKIPS] = 0x80000012;
  393         nv.dmabase[0x6 + SKIPS] = 0x00046000;
  394         nv.dmabase[0x7 + SKIPS] = 0x80000013;
  395         nv.dmabase[0x8 + SKIPS] = 0x00048000;
  396         nv.dmabase[0x9 + SKIPS] = 0x80000014;
  397         nv.dmabase[0xA + SKIPS] = 0x0004A000;
  398         nv.dmabase[0xB + SKIPS] = 0x80000015;
  399         nv.dmabase[0xC + SKIPS] = 0x0004C000;
  400         nv.dmabase[0xD + SKIPS] = 0x80000016;
  401         nv.dmabase[0xE + SKIPS] = 0x0004E000;
  402         nv.dmabase[0xF + SKIPS] = 0x80000017;
  403 
  404         nv.dmaput = 0;
  405         nv.dmacurrent = 16 + SKIPS;
  406         nv.dmamax = 8191;
  407         nv.dmafree = nv.dmamax - nv.dmacurrent;
  408 
  409         switch(scr->gscreen->depth) {
  410         case 32:
  411         case 24:
  412                 surfaceFormat = SURFACE_FORMAT_DEPTH24;
  413                 patternFormat = PATTERN_FORMAT_DEPTH24;
  414                 rectFormat = RECT_FORMAT_DEPTH24;
  415                 lineFormat = LINE_FORMAT_DEPTH24;
  416                 break;
  417         case 16:
  418         case 15:
  419                 surfaceFormat = SURFACE_FORMAT_DEPTH16;
  420                 patternFormat = PATTERN_FORMAT_DEPTH16;
  421                 rectFormat = RECT_FORMAT_DEPTH16;
  422                 lineFormat = LINE_FORMAT_DEPTH16;
  423                 break;
  424         default:
  425                 surfaceFormat = SURFACE_FORMAT_DEPTH8;
  426                 patternFormat = PATTERN_FORMAT_DEPTH8;
  427                 rectFormat = RECT_FORMAT_DEPTH8;
  428                 lineFormat = LINE_FORMAT_DEPTH8;
  429                 break;
  430         }
  431 
  432         nvdmastart(scr, SURFACE_FORMAT, 4);
  433         nvdmanext(surfaceFormat);
  434         nvdmanext(pitch | (pitch << 16));
  435         nvdmanext(0);
  436         nvdmanext(0);
  437 
  438         nvdmastart(scr, PATTERN_FORMAT, 1);
  439         nvdmanext(patternFormat);
  440 
  441         nvdmastart(scr, RECT_FORMAT, 1);
  442         nvdmanext(rectFormat);
  443 
  444         nvdmastart(scr, LINE_FORMAT, 1);
  445         nvdmanext(lineFormat);
  446 
  447         nvdmastart(scr, PATTERN_COLOR_0, 4);
  448         nvdmanext(~0);
  449         nvdmanext(~0);
  450         nvdmanext(~0);
  451         nvdmanext(~0);
  452 
  453         nvdmastart(scr, ROP_SET, 1);
  454         nvdmanext(0xCC);
  455 
  456         nvdmakickoff(scr);
  457         waitforidle(scr);
  458 }
  459 
  460 
  461 static int
  462 nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
  463 {
  464         nvdmastart(scr, RECT_SOLID_COLOR, 1);
  465         nvdmanext(sval);
  466 
  467         nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
  468         nvdmanext((r.min.x << 16) | r.min.y);
  469         nvdmanext((Dx(r) << 16) | Dy(r));
  470 
  471         //if ( (Dy(r) * Dx(r)) >= 512)
  472                 nvdmakickoff(scr);
  473 
  474         waitforidle(scr);
  475 
  476         return 1;
  477 }
  478 
  479 static int
  480 nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  481 {
  482         nvdmastart(scr, BLIT_POINT_SRC, 3);
  483         nvdmanext((sr.min.y << 16) | sr.min.x);
  484         nvdmanext((r.min.y << 16) | r.min.x);
  485         nvdmanext((Dy(r) << 16) | Dx(r));
  486 
  487         //if ( (Dy(r) * Dx(r)) >= 512)
  488                 nvdmakickoff(scr);
  489 
  490         waitforidle(scr);
  491 
  492         return 1;
  493 }
  494 
  495 void
  496 nvidiablank(VGAscr*, int blank)
  497 {
  498         uchar seq1, crtc1A;
  499 
  500         seq1 = vgaxi(Seqx, 1) & ~0x20;
  501         crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
  502 
  503         if(blank){
  504                 seq1 |= 0x20;
  505 //              crtc1A |= 0xC0;
  506                 crtc1A |= 0x80;
  507         }
  508 
  509         vgaxo(Seqx, 1, seq1);
  510         vgaxo(Crtx, 0x1A, crtc1A);
  511 }
  512 
  513 static void
  514 nvidiadrawinit(VGAscr *scr)
  515 {
  516         nvresetgraphics(scr);
  517         scr->blank = nvidiablank;
  518         hwblank = 1;
  519         scr->fill = nvidiahwfill;
  520         scr->scroll = nvidiahwscroll;
  521 }
  522 
  523 VGAdev vganvidiadev = {
  524         "nvidia",
  525 
  526         nvidiaenable,
  527         nil,
  528         nil,
  529         nvidialinear,
  530         nvidiadrawinit,
  531 };
  532 
  533 VGAcur vganvidiacur = {
  534         "nvidiahwgc",
  535 
  536         nvidiacurenable,
  537         nvidiacurdisable,
  538         nvidiacurload,
  539         nvidiacurmove,
  540 };

Cache object: 79c06e56ac2659de26002015018c3376


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.