vganvidia.c 12 KB

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