1
0

vganvidia.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541
  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. if (scr->id & 0x0F00) {
  147. q = KADDR(scr->io + Pfb + 0x020C);
  148. tmp = (*q >> 20) & 0xFF;
  149. if (tmp == 0)
  150. tmp = 16;
  151. scr->storage = tmp*1024*1024;
  152. } else {
  153. q = KADDR(scr->io + Pfb);
  154. tmp = *q;
  155. if (tmp & 0x0100) {
  156. scr->storage = ((tmp >> 12) & 0x0F) * 1024 + 1024 * 2;
  157. } else {
  158. tmp &= 0x03;
  159. if (tmp)
  160. scr->storage = (1024*1024*2) << tmp;
  161. else
  162. scr->storage = 1024*1024*32;
  163. }
  164. }
  165. }
  166. static void
  167. nvidiacurdisable(VGAscr* scr)
  168. {
  169. if(scr->io == 0)
  170. return;
  171. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  172. }
  173. static void
  174. nvidiacurload(VGAscr* scr, Cursor* curs)
  175. {
  176. ulong* p;
  177. int i,j;
  178. ushort c,s;
  179. ulong tmp;
  180. if(scr->io == 0)
  181. return;
  182. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  183. if (scr->id & 0x0F00)
  184. p = KADDR(scr->aperture + scr->storage - 96*1024);
  185. else
  186. p = KADDR(scr->io + Pramin + 0x1E00 * 4);
  187. for(i=0; i<16; i++) {
  188. c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
  189. s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
  190. tmp = 0;
  191. for (j=0; j<16; j++){
  192. if(s&0x8000)
  193. tmp |= 0x80000000;
  194. else if(c&0x8000)
  195. tmp |= 0xFFFF0000;
  196. if (j&0x1){
  197. *p++ = tmp;
  198. tmp = 0;
  199. } else {
  200. tmp>>=16;
  201. }
  202. c<<=1;
  203. s<<=1;
  204. }
  205. for (j=0; j<8; j++)
  206. *p++ = 0;
  207. }
  208. for (i=0; i<256; i++)
  209. *p++ = 0;
  210. scr->offset = curs->offset;
  211. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  212. return;
  213. }
  214. static int
  215. nvidiacurmove(VGAscr* scr, Point p)
  216. {
  217. ulong* cursorpos;
  218. if(scr->io == 0)
  219. return 1;
  220. cursorpos = KADDR(scr->io + hwCurPos);
  221. *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
  222. return 0;
  223. }
  224. static void
  225. nvidiacurenable(VGAscr* scr)
  226. {
  227. nvidiaenable(scr);
  228. if(scr->io == 0)
  229. return;
  230. vgaxo(Crtx, 0x1F, 0x57);
  231. nvidiacurload(scr, &arrow);
  232. nvidiacurmove(scr, ZP);
  233. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  234. }
  235. void
  236. writeput(VGAscr *scr, int data)
  237. {
  238. uchar *p, scratch;
  239. ulong *fifo;
  240. outb(0x3D0,0);
  241. p=KADDR(scr->aperture);
  242. scratch = *p;
  243. fifo = KADDR(scr->io + Fifo);
  244. fifo[0x10] = (data << 2);
  245. USED(scratch);
  246. }
  247. ulong
  248. readget(VGAscr *scr)
  249. {
  250. ulong *fifo;
  251. fifo = KADDR(scr->io + Fifo);
  252. return (fifo[0x0011] >> 2);
  253. }
  254. void
  255. nvdmakickoff(VGAscr *scr)
  256. {
  257. if(nv.dmacurrent != nv.dmaput) {
  258. nv.dmaput = nv.dmacurrent;
  259. writeput(scr, nv.dmaput);
  260. }
  261. }
  262. static void
  263. nvdmanext(ulong data)
  264. {
  265. nv.dmabase[nv.dmacurrent++] = data;
  266. }
  267. void
  268. nvdmawait(VGAscr *scr, int size)
  269. {
  270. int dmaget;
  271. size++;
  272. while(nv.dmafree < size) {
  273. dmaget = readget(scr);
  274. if(nv.dmaput >= dmaget) {
  275. nv.dmafree = nv.dmamax - nv.dmacurrent;
  276. if(nv.dmafree < size) {
  277. nvdmanext(0x20000000);
  278. if(dmaget <= SKIPS) {
  279. if (nv.dmaput <= SKIPS) /* corner case - will be idle */
  280. writeput(scr, SKIPS + 1);
  281. do { dmaget = readget(scr); }
  282. while(dmaget <= SKIPS);
  283. }
  284. writeput(scr, SKIPS);
  285. nv.dmacurrent = nv.dmaput = SKIPS;
  286. nv.dmafree = dmaget - (SKIPS + 1);
  287. }
  288. } else
  289. nv.dmafree = dmaget - nv.dmacurrent - 1;
  290. }
  291. }
  292. static void
  293. nvdmastart(VGAscr *scr, ulong tag, int size)
  294. {
  295. if (nv.dmafree <= size)
  296. nvdmawait(scr, size);
  297. nvdmanext((size << 18) | tag);
  298. nv.dmafree -= (size + 1);
  299. }
  300. static void
  301. waitforidle(VGAscr *scr)
  302. {
  303. ulong* pgraph;
  304. int x;
  305. pgraph = KADDR(scr->io + Pgraph);
  306. x = 0;
  307. while((readget(scr) != nv.dmaput) && x++ < 1000000)
  308. ;
  309. if(x >= 1000000)
  310. iprint("idle stat %lud put %d scr %p pc %luX\n", readget(scr), nv.dmaput, scr, getcallerpc(&scr));
  311. x = 0;
  312. while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
  313. ;
  314. if(x >= 1000000)
  315. iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr));
  316. }
  317. static void
  318. nvresetgraphics(VGAscr *scr)
  319. {
  320. ulong surfaceFormat, patternFormat, rectFormat, lineFormat;
  321. int pitch, i;
  322. pitch = scr->gscreen->width*BY2WD;
  323. nv.dmabase = KADDR(scr->aperture + scr->storage - 128*1024);
  324. for(i=0; i<SKIPS; i++)
  325. nv.dmabase[i] = 0x00000000;
  326. nv.dmabase[0x0 + SKIPS] = 0x00040000;
  327. nv.dmabase[0x1 + SKIPS] = 0x80000010;
  328. nv.dmabase[0x2 + SKIPS] = 0x00042000;
  329. nv.dmabase[0x3 + SKIPS] = 0x80000011;
  330. nv.dmabase[0x4 + SKIPS] = 0x00044000;
  331. nv.dmabase[0x5 + SKIPS] = 0x80000012;
  332. nv.dmabase[0x6 + SKIPS] = 0x00046000;
  333. nv.dmabase[0x7 + SKIPS] = 0x80000013;
  334. nv.dmabase[0x8 + SKIPS] = 0x00048000;
  335. nv.dmabase[0x9 + SKIPS] = 0x80000014;
  336. nv.dmabase[0xA + SKIPS] = 0x0004A000;
  337. nv.dmabase[0xB + SKIPS] = 0x80000015;
  338. nv.dmabase[0xC + SKIPS] = 0x0004C000;
  339. nv.dmabase[0xD + SKIPS] = 0x80000016;
  340. nv.dmabase[0xE + SKIPS] = 0x0004E000;
  341. nv.dmabase[0xF + SKIPS] = 0x80000017;
  342. nv.dmaput = 0;
  343. nv.dmacurrent = 16 + SKIPS;
  344. nv.dmamax = 8191;
  345. nv.dmafree = nv.dmamax - nv.dmacurrent;
  346. switch(scr->gscreen->depth) {
  347. case 32:
  348. case 24:
  349. surfaceFormat = SURFACE_FORMAT_DEPTH24;
  350. patternFormat = PATTERN_FORMAT_DEPTH24;
  351. rectFormat = RECT_FORMAT_DEPTH24;
  352. lineFormat = LINE_FORMAT_DEPTH24;
  353. break;
  354. case 16:
  355. case 15:
  356. surfaceFormat = SURFACE_FORMAT_DEPTH16;
  357. patternFormat = PATTERN_FORMAT_DEPTH16;
  358. rectFormat = RECT_FORMAT_DEPTH16;
  359. lineFormat = LINE_FORMAT_DEPTH16;
  360. break;
  361. default:
  362. surfaceFormat = SURFACE_FORMAT_DEPTH8;
  363. patternFormat = PATTERN_FORMAT_DEPTH8;
  364. rectFormat = RECT_FORMAT_DEPTH8;
  365. lineFormat = LINE_FORMAT_DEPTH8;
  366. break;
  367. }
  368. nvdmastart(scr, SURFACE_FORMAT, 4);
  369. nvdmanext(surfaceFormat);
  370. nvdmanext(pitch | (pitch << 16));
  371. nvdmanext(0);
  372. nvdmanext(0);
  373. nvdmastart(scr, PATTERN_FORMAT, 1);
  374. nvdmanext(patternFormat);
  375. nvdmastart(scr, RECT_FORMAT, 1);
  376. nvdmanext(rectFormat);
  377. nvdmastart(scr, LINE_FORMAT, 1);
  378. nvdmanext(lineFormat);
  379. nvdmastart(scr, PATTERN_COLOR_0, 4);
  380. nvdmanext(~0);
  381. nvdmanext(~0);
  382. nvdmanext(~0);
  383. nvdmanext(~0);
  384. nvdmastart(scr, ROP_SET, 1);
  385. nvdmanext(0xCC);
  386. nvdmakickoff(scr);
  387. waitforidle(scr);
  388. }
  389. static int
  390. nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
  391. {
  392. nvdmastart(scr, RECT_SOLID_COLOR, 1);
  393. nvdmanext(sval);
  394. nvdmastart(scr, RECT_SOLID_RECTS(0), 2);
  395. nvdmanext((r.min.x << 16) | r.min.y);
  396. nvdmanext((Dx(r) << 16) | Dy(r));
  397. //if ( (Dy(r) * Dx(r)) >= 512)
  398. nvdmakickoff(scr);
  399. waitforidle(scr);
  400. return 1;
  401. }
  402. static int
  403. nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  404. {
  405. nvdmastart(scr, BLIT_POINT_SRC, 3);
  406. nvdmanext((sr.min.y << 16) | sr.min.x);
  407. nvdmanext((r.min.y << 16) | r.min.x);
  408. nvdmanext((Dy(r) << 16) | Dx(r));
  409. //if ( (Dy(r) * Dx(r)) >= 512)
  410. nvdmakickoff(scr);
  411. waitforidle(scr);
  412. return 1;
  413. }
  414. void
  415. nvidiablank(VGAscr*, int blank)
  416. {
  417. uchar seq1, crtc1A;
  418. seq1 = vgaxi(Seqx, 1) & ~0x20;
  419. crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
  420. if(blank){
  421. seq1 |= 0x20;
  422. // crtc1A |= 0xC0;
  423. crtc1A |= 0x80;
  424. }
  425. vgaxo(Seqx, 1, seq1);
  426. vgaxo(Crtx, 0x1A, crtc1A);
  427. }
  428. static void
  429. nvidiadrawinit(VGAscr *scr)
  430. {
  431. nvresetgraphics(scr);
  432. scr->blank = nvidiablank;
  433. hwblank = 1;
  434. scr->fill = nvidiahwfill;
  435. scr->scroll = nvidiahwscroll;
  436. }
  437. VGAdev vganvidiadev = {
  438. "nvidia",
  439. nvidiaenable,
  440. nil,
  441. nil,
  442. nvidialinear,
  443. nvidiadrawinit,
  444. };
  445. VGAcur vganvidiacur = {
  446. "nvidiahwgc",
  447. nvidiacurenable,
  448. nvidiacurdisable,
  449. nvidiacurload,
  450. nvidiacurmove,
  451. };