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 %luX\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 %.8lux scr %p pc %luX\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 }; 541