vganvidia.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560
  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. /* Nvidia is good about backwards compatibility -- any did >= 0x20 is fine */
  72. static Pcidev*
  73. nvidiapci(void)
  74. {
  75. Pcidev *p;
  76. p = nil;
  77. while((p = pcimatch(p, 0x10DE, 0)) != nil){
  78. if(p->did >= 0x20 && p->ccrb == 3) /* video card */
  79. return p;
  80. }
  81. return nil;
  82. }
  83. static ulong
  84. nvidialinear(VGAscr* scr, int* size, int* align)
  85. {
  86. Pcidev *p;
  87. int oapsize, wasupamem;
  88. ulong aperture, oaperture;
  89. oaperture = scr->aperture;
  90. oapsize = scr->apsize;
  91. wasupamem = scr->isupamem;
  92. aperture = 0;
  93. if(p = nvidiapci()){
  94. aperture = p->mem[1].bar & ~0x0F;
  95. *size = p->mem[1].size;
  96. }
  97. if(wasupamem){
  98. if(oaperture == aperture)
  99. return oaperture;
  100. upafree(oaperture, oapsize);
  101. }
  102. scr->isupamem = 0;
  103. aperture = upamalloc(aperture, *size, *align);
  104. if(aperture == 0){
  105. if(wasupamem && upamalloc(oaperture, oapsize, 0)){
  106. aperture = oaperture;
  107. scr->isupamem = 1;
  108. }
  109. else
  110. scr->isupamem = 0;
  111. }
  112. else
  113. scr->isupamem = 1;
  114. return aperture;
  115. }
  116. static void
  117. nvidiaenable(VGAscr* scr)
  118. {
  119. Pcidev *p;
  120. ulong aperture, *q;
  121. int align, size, tmp;
  122. /*
  123. * Only once, can't be disabled for now.
  124. * scr->io holds the physical address of
  125. * the MMIO registers.
  126. */
  127. if(scr->io)
  128. return;
  129. p = nvidiapci();
  130. if(p == nil)
  131. return;
  132. scr->id = p->did;
  133. scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
  134. if(scr->io == 0)
  135. return;
  136. addvgaseg("nvidiammio", scr->io, p->mem[0].size);
  137. size = p->mem[1].size;
  138. align = 0;
  139. aperture = nvidialinear(scr, &size, &align);
  140. if(aperture){
  141. scr->aperture = aperture;
  142. scr->apsize = size;
  143. addvgaseg("nvidiascreen", aperture, size);
  144. }
  145. /* find video memory size */
  146. switch (scr->id & 0x0ff0) {
  147. case 0x0020:
  148. case 0x00A0:
  149. q = KADDR(scr->io + Pfb);
  150. tmp = *q;
  151. if (tmp & 0x0100) {
  152. scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
  153. } else {
  154. tmp &= 0x03;
  155. if (tmp)
  156. scr->storage = (1024*1024*2) << tmp;
  157. else
  158. scr->storage = 1024*1024*32;
  159. }
  160. break;
  161. case 0x01A0:
  162. p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
  163. tmp = pcicfgr32(p, 0x7C);
  164. scr->storage = (((tmp >> 6) & 31) + 1) * 1024 * 1024;
  165. break;
  166. case 0x01F0:
  167. p = pcimatchtbdf(MKBUS(BusPCI, 0, 0, 1));
  168. tmp = pcicfgr32(p, 0x84);
  169. scr->storage = (((tmp >> 4) & 127) + 1) * 1024 * 1024;
  170. break;
  171. default:
  172. q = KADDR(scr->io + Pfb + 0x020C);
  173. tmp = (*q >> 20) & 0xFF;
  174. if (tmp == 0)
  175. tmp = 16;
  176. scr->storage = tmp*1024*1024;
  177. break;
  178. }
  179. }
  180. static void
  181. nvidiacurdisable(VGAscr* scr)
  182. {
  183. if(scr->io == 0)
  184. return;
  185. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  186. }
  187. static void
  188. nvidiacurload(VGAscr* scr, Cursor* curs)
  189. {
  190. ulong* p;
  191. int i,j;
  192. ushort c,s;
  193. ulong tmp;
  194. if(scr->io == 0)
  195. return;
  196. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  197. switch (scr->id & 0x0ff0) {
  198. case 0x0020:
  199. case 0x00A0:
  200. p = KADDR(scr->io + Pramin + 0x1E00 * 4);
  201. break;
  202. default:
  203. p = KADDR(scr->aperture + scr->storage - 96*1024);
  204. break;
  205. }
  206. for(i=0; i<16; i++) {
  207. c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
  208. s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
  209. tmp = 0;
  210. for (j=0; j<16; j++){
  211. if(s&0x8000)
  212. tmp |= 0x80000000;
  213. else if(c&0x8000)
  214. tmp |= 0xFFFF0000;
  215. if (j&0x1){
  216. *p++ = tmp;
  217. tmp = 0;
  218. } else {
  219. tmp>>=16;
  220. }
  221. c<<=1;
  222. s<<=1;
  223. }
  224. for (j=0; j<8; j++)
  225. *p++ = 0;
  226. }
  227. for (i=0; i<256; i++)
  228. *p++ = 0;
  229. scr->offset = curs->offset;
  230. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  231. return;
  232. }
  233. static int
  234. nvidiacurmove(VGAscr* scr, Point p)
  235. {
  236. ulong* cursorpos;
  237. if(scr->io == 0)
  238. return 1;
  239. cursorpos = KADDR(scr->io + hwCurPos);
  240. *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
  241. return 0;
  242. }
  243. static void
  244. nvidiacurenable(VGAscr* scr)
  245. {
  246. nvidiaenable(scr);
  247. if(scr->io == 0)
  248. return;
  249. vgaxo(Crtx, 0x1F, 0x57);
  250. nvidiacurload(scr, &arrow);
  251. nvidiacurmove(scr, ZP);
  252. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  253. }
  254. void
  255. writeput(VGAscr *scr, int data)
  256. {
  257. uchar *p, scratch;
  258. ulong *fifo;
  259. outb(0x3D0,0);
  260. p=KADDR(scr->aperture);
  261. scratch = *p;
  262. fifo = KADDR(scr->io + Fifo);
  263. fifo[0x10] = (data << 2);
  264. USED(scratch);
  265. }
  266. ulong
  267. readget(VGAscr *scr)
  268. {
  269. ulong *fifo;
  270. fifo = KADDR(scr->io + Fifo);
  271. return (fifo[0x0011] >> 2);
  272. }
  273. void
  274. nvdmakickoff(VGAscr *scr)
  275. {
  276. if(nv.dmacurrent != nv.dmaput) {
  277. nv.dmaput = nv.dmacurrent;
  278. writeput(scr, nv.dmaput);
  279. }
  280. }
  281. static void
  282. nvdmanext(ulong data)
  283. {
  284. nv.dmabase[nv.dmacurrent++] = data;
  285. }
  286. void
  287. nvdmawait(VGAscr *scr, int size)
  288. {
  289. int dmaget;
  290. size++;
  291. while(nv.dmafree < size) {
  292. dmaget = readget(scr);
  293. if(nv.dmaput >= dmaget) {
  294. nv.dmafree = nv.dmamax - nv.dmacurrent;
  295. if(nv.dmafree < size) {
  296. nvdmanext(0x20000000);
  297. if(dmaget <= SKIPS) {
  298. if (nv.dmaput <= SKIPS) /* corner case - will be idle */
  299. writeput(scr, SKIPS + 1);
  300. do { dmaget = readget(scr); }
  301. while(dmaget <= SKIPS);
  302. }
  303. writeput(scr, SKIPS);
  304. nv.dmacurrent = nv.dmaput = SKIPS;
  305. nv.dmafree = dmaget - (SKIPS + 1);
  306. }
  307. } else
  308. nv.dmafree = dmaget - nv.dmacurrent - 1;
  309. }
  310. }
  311. static void
  312. nvdmastart(VGAscr *scr, ulong tag, int size)
  313. {
  314. if (nv.dmafree <= size)
  315. nvdmawait(scr, size);
  316. nvdmanext((size << 18) | tag);
  317. nv.dmafree -= (size + 1);
  318. }
  319. static void
  320. waitforidle(VGAscr *scr)
  321. {
  322. ulong* pgraph;
  323. int x;
  324. pgraph = KADDR(scr->io + Pgraph);
  325. x = 0;
  326. while((readget(scr) != nv.dmaput) && x++ < 1000000)
  327. ;
  328. if(x >= 1000000)
  329. iprint("idle stat %lud put %d scr %p pc %luX\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
  330. x = 0;
  331. while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
  332. ;
  333. if(x >= 1000000)
  334. iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr));
  335. }
  336. static void
  337. nvresetgraphics(VGAscr *scr)
  338. {
  339. ulong surfaceFormat, patternFormat, rectFormat, lineFormat;
  340. int pitch, i;
  341. pitch = scr->gscreen->width*BY2WD;
  342. nv.dmabase = KADDR(scr->aperture + scr->storage - 128*1024);
  343. for(i=0; i<SKIPS; i++)
  344. nv.dmabase[i] = 0x00000000;
  345. nv.dmabase[0x0 + SKIPS] = 0x00040000;
  346. nv.dmabase[0x1 + SKIPS] = 0x80000010;
  347. nv.dmabase[0x2 + SKIPS] = 0x00042000;
  348. nv.dmabase[0x3 + SKIPS] = 0x80000011;
  349. nv.dmabase[0x4 + SKIPS] = 0x00044000;
  350. nv.dmabase[0x5 + SKIPS] = 0x80000012;
  351. nv.dmabase[0x6 + SKIPS] = 0x00046000;
  352. nv.dmabase[0x7 + SKIPS] = 0x80000013;
  353. nv.dmabase[0x8 + SKIPS] = 0x00048000;
  354. nv.dmabase[0x9 + SKIPS] = 0x80000014;
  355. nv.dmabase[0xA + SKIPS] = 0x0004A000;
  356. nv.dmabase[0xB + SKIPS] = 0x80000015;
  357. nv.dmabase[0xC + SKIPS] = 0x0004C000;
  358. nv.dmabase[0xD + SKIPS] = 0x80000016;
  359. nv.dmabase[0xE + SKIPS] = 0x0004E000;
  360. nv.dmabase[0xF + SKIPS] = 0x80000017;
  361. nv.dmaput = 0;
  362. nv.dmacurrent = 16 + SKIPS;
  363. nv.dmamax = 8191;
  364. nv.dmafree = nv.dmamax - nv.dmacurrent;
  365. switch(scr->gscreen->depth) {
  366. case 32:
  367. case 24:
  368. surfaceFormat = SURFACE_FORMAT_DEPTH24;
  369. patternFormat = PATTERN_FORMAT_DEPTH24;
  370. rectFormat = RECT_FORMAT_DEPTH24;
  371. lineFormat = LINE_FORMAT_DEPTH24;
  372. break;
  373. case 16:
  374. case 15:
  375. surfaceFormat = SURFACE_FORMAT_DEPTH16;
  376. patternFormat = PATTERN_FORMAT_DEPTH16;
  377. rectFormat = RECT_FORMAT_DEPTH16;
  378. lineFormat = LINE_FORMAT_DEPTH16;
  379. break;
  380. default:
  381. surfaceFormat = SURFACE_FORMAT_DEPTH8;
  382. patternFormat = PATTERN_FORMAT_DEPTH8;
  383. rectFormat = RECT_FORMAT_DEPTH8;
  384. lineFormat = LINE_FORMAT_DEPTH8;
  385. break;
  386. }
  387. nvdmastart(scr, SURFACE_FORMAT, 4);
  388. nvdmanext(surfaceFormat);
  389. nvdmanext(pitch | (pitch << 16));
  390. nvdmanext(0);
  391. nvdmanext(0);
  392. nvdmastart(scr, PATTERN_FORMAT, 1);
  393. nvdmanext(patternFormat);
  394. nvdmastart(scr, RECT_FORMAT, 1);
  395. nvdmanext(rectFormat);
  396. nvdmastart(scr, LINE_FORMAT, 1);
  397. nvdmanext(lineFormat);
  398. nvdmastart(scr, PATTERN_COLOR_0, 4);
  399. nvdmanext(~0);
  400. nvdmanext(~0);
  401. nvdmanext(~0);
  402. nvdmanext(~0);
  403. nvdmastart(scr, ROP_SET, 1);
  404. nvdmanext(0xCC);
  405. nvdmakickoff(scr);
  406. waitforidle(scr);
  407. }
  408. static int
  409. nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
  410. {
  411. nvdmastart(scr, RECT_SOLID_COLOR, 1);
  412. nvdmanext(sval);
  413. nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
  414. nvdmanext((r.min.x << 16) | r.min.y);
  415. nvdmanext((Dx(r) << 16) | Dy(r));
  416. //if ( (Dy(r) * Dx(r)) >= 512)
  417. nvdmakickoff(scr);
  418. waitforidle(scr);
  419. return 1;
  420. }
  421. static int
  422. nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  423. {
  424. nvdmastart(scr, BLIT_POINT_SRC, 3);
  425. nvdmanext((sr.min.y << 16) | sr.min.x);
  426. nvdmanext((r.min.y << 16) | r.min.x);
  427. nvdmanext((Dy(r) << 16) | Dx(r));
  428. //if ( (Dy(r) * Dx(r)) >= 512)
  429. nvdmakickoff(scr);
  430. waitforidle(scr);
  431. return 1;
  432. }
  433. void
  434. nvidiablank(VGAscr*, int blank)
  435. {
  436. uchar seq1, crtc1A;
  437. seq1 = vgaxi(Seqx, 1) & ~0x20;
  438. crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
  439. if(blank){
  440. seq1 |= 0x20;
  441. // crtc1A |= 0xC0;
  442. crtc1A |= 0x80;
  443. }
  444. vgaxo(Seqx, 1, seq1);
  445. vgaxo(Crtx, 0x1A, crtc1A);
  446. }
  447. static void
  448. nvidiadrawinit(VGAscr *scr)
  449. {
  450. nvresetgraphics(scr);
  451. scr->blank = nvidiablank;
  452. hwblank = 1;
  453. scr->fill = nvidiahwfill;
  454. scr->scroll = nvidiahwscroll;
  455. }
  456. VGAdev vganvidiadev = {
  457. "nvidia",
  458. nvidiaenable,
  459. nil,
  460. nil,
  461. nvidialinear,
  462. nvidiadrawinit,
  463. };
  464. VGAcur vganvidiacur = {
  465. "nvidiahwgc",
  466. nvidiacurenable,
  467. nvidiacurdisable,
  468. nvidiacurload,
  469. nvidiacurmove,
  470. };