vganvidia.c 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #define Image IMAGE
  9. #include <draw.h>
  10. #include <memdraw.h>
  11. #include <cursor.h>
  12. #include "screen.h"
  13. enum {
  14. Pramin = 0x00710000,
  15. Pramdac = 0x00680000,
  16. Fifo = 0x00800000,
  17. Pgraph = 0x00400000
  18. };
  19. enum {
  20. hwCurPos = Pramdac + 0x0300,
  21. hwCurImage = Pramin + (0x00010000 - 0x0800),
  22. };
  23. /* Nvidia is good about backwards compatibility -- any did >= 0x20 is fine */
  24. static Pcidev*
  25. nvidiapci(void)
  26. {
  27. Pcidev *p;
  28. p = nil;
  29. while((p = pcimatch(p, 0x10DE, 0)) != nil){
  30. if(p->did >= 0x20 && p->ccrb == 3) /* video card */
  31. return p;
  32. }
  33. return nil;
  34. }
  35. static ulong
  36. nvidialinear(VGAscr* scr, int* size, int* align)
  37. {
  38. Pcidev *p;
  39. int oapsize, wasupamem;
  40. ulong aperture, oaperture;
  41. oaperture = scr->aperture;
  42. oapsize = scr->apsize;
  43. wasupamem = scr->isupamem;
  44. aperture = 0;
  45. if(p = nvidiapci()){
  46. aperture = p->mem[1].bar & ~0x0F;
  47. *size = p->mem[1].size;
  48. }
  49. if(wasupamem){
  50. if(oaperture == aperture)
  51. return oaperture;
  52. upafree(oaperture, oapsize);
  53. }
  54. scr->isupamem = 0;
  55. aperture = upamalloc(aperture, *size, *align);
  56. if(aperture == 0){
  57. if(wasupamem && upamalloc(oaperture, oapsize, 0)){
  58. aperture = oaperture;
  59. scr->isupamem = 1;
  60. }
  61. else
  62. scr->isupamem = 0;
  63. }
  64. else
  65. scr->isupamem = 1;
  66. return aperture;
  67. }
  68. static void
  69. nvidiaenable(VGAscr* scr)
  70. {
  71. Pcidev *p;
  72. ulong aperture;
  73. int align, size;
  74. /*
  75. * Only once, can't be disabled for now.
  76. * scr->io holds the physical address of
  77. * the MMIO registers.
  78. */
  79. if(scr->io)
  80. return;
  81. p = nvidiapci();
  82. if(p == nil)
  83. return;
  84. scr->id = p->did;
  85. scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
  86. if(scr->io == 0)
  87. return;
  88. addvgaseg("nvidiammio", scr->io, p->mem[0].size);
  89. size = p->mem[1].size;
  90. align = 0;
  91. aperture = nvidialinear(scr, &size, &align);
  92. if(aperture){
  93. scr->aperture = aperture;
  94. scr->apsize = size;
  95. addvgaseg("nvidiascreen", aperture, size);
  96. }
  97. }
  98. static void
  99. nvidiacurdisable(VGAscr* scr)
  100. {
  101. if(scr->io == 0)
  102. return;
  103. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  104. }
  105. static void
  106. nvidiacurload(VGAscr* scr, Cursor* curs)
  107. {
  108. ulong* p;
  109. int i,j;
  110. ushort c,s;
  111. ulong tmp;
  112. if(scr->io == 0)
  113. return;
  114. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) & ~0x01);
  115. p = KADDR(scr->io + hwCurImage);
  116. for(i=0; i<16; i++) {
  117. switch(scr->id){
  118. default:
  119. c = (curs->clr[2 * i] << 8) | curs->clr[2 * i+1];
  120. s = (curs->set[2 * i] << 8) | curs->set[2 * i+1];
  121. break;
  122. case 0x171: /* for Geforece4 MX bug, K.Okamoto */
  123. case 0x181:
  124. c = (curs->clr[2 * i+1] << 8) | curs->clr[2 * i];
  125. s = (curs->set[2 * i+1] << 8) | curs->set[2 * i];
  126. break;
  127. }
  128. tmp = 0;
  129. for (j=0; j<16; j++){
  130. if(s&0x8000)
  131. tmp |= 0x80000000;
  132. else if(c&0x8000)
  133. tmp |= 0xFFFF0000;
  134. if (j&0x1){
  135. *p++ = tmp;
  136. tmp = 0;
  137. } else {
  138. tmp>>=16;
  139. }
  140. c<<=1;
  141. s<<=1;
  142. }
  143. for (j=0; j<8; j++)
  144. *p++ = 0;
  145. }
  146. for (i=0; i<256; i++)
  147. *p++ = 0;
  148. scr->offset = curs->offset;
  149. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  150. return;
  151. }
  152. static int
  153. nvidiacurmove(VGAscr* scr, Point p)
  154. {
  155. ulong* cursorpos;
  156. if(scr->io == 0)
  157. return 1;
  158. cursorpos = KADDR(scr->io + hwCurPos);
  159. *cursorpos = ((p.y+scr->offset.y)<<16)|((p.x+scr->offset.x) & 0xFFFF);
  160. return 0;
  161. }
  162. static void
  163. nvidiacurenable(VGAscr* scr)
  164. {
  165. nvidiaenable(scr);
  166. if(scr->io == 0)
  167. return;
  168. vgaxo(Crtx, 0x1F, 0x57);
  169. nvidiacurload(scr, &arrow);
  170. nvidiacurmove(scr, ZP);
  171. vgaxo(Crtx, 0x31, vgaxi(Crtx, 0x31) | 0x01);
  172. }
  173. enum {
  174. RopFifo = 0x00000000,
  175. ClipFifo = 0x00002000,
  176. PattFifo = 0x00004000,
  177. BltFifo = 0x00008000,
  178. BitmapFifo = 0x0000A000,
  179. };
  180. enum {
  181. RopRop3 = RopFifo + 0x300,
  182. ClipTopLeft = ClipFifo + 0x300,
  183. ClipWidthHeight = ClipFifo + 0x304,
  184. PattShape = PattFifo + 0x0308,
  185. PattColor0 = PattFifo + 0x0310,
  186. PattColor1 = PattFifo + 0x0314,
  187. PattMonochrome0 = PattFifo + 0x0318,
  188. PattMonochrome1 = PattFifo + 0x031C,
  189. BltTopLeftSrc = BltFifo + 0x0300,
  190. BltTopLeftDst = BltFifo + 0x0304,
  191. BltWidthHeight = BltFifo + 0x0308,
  192. BitmapColor1A = BitmapFifo + 0x03FC,
  193. BitmapURect0TopLeft = BitmapFifo + 0x0400,
  194. BitmapURect0WidthHeight = BitmapFifo + 0x0404,
  195. };
  196. static void
  197. waitforidle(VGAscr *scr)
  198. {
  199. ulong* pgraph;
  200. int x;
  201. pgraph = KADDR(scr->io + Pgraph);
  202. x = 0;
  203. while(pgraph[0x00000700/4] & 0x01 && x++ < 1000000)
  204. ;
  205. if(x >= 1000000)
  206. iprint("idle stat %lud scrio %.8lux scr %p pc %luX\n", *pgraph, scr->io, scr, getcallerpc(&scr));
  207. }
  208. static void
  209. waitforfifo(VGAscr *scr, int fifo, int entries)
  210. {
  211. ushort* fifofree;
  212. int x;
  213. x = 0;
  214. fifofree = KADDR(scr->io + Fifo + fifo + 0x10);
  215. while(((*fifofree >> 2) < entries) && x++ < 1000000)
  216. ;
  217. if(x >= 1000000)
  218. iprint("fifo stat %d scrio %.8lux scr %p pc %luX\n", *fifofree, scr->io, scr, getcallerpc(&scr));
  219. }
  220. static int
  221. nvidiahwfill(VGAscr *scr, Rectangle r, ulong sval)
  222. {
  223. ulong* fifo;
  224. fifo = KADDR(scr->io + Fifo);
  225. waitforfifo(scr, BitmapFifo, 1);
  226. fifo[BitmapColor1A/4] = sval;
  227. waitforfifo(scr, BitmapFifo, 2);
  228. fifo[BitmapURect0TopLeft/4] = (r.min.x << 16) | r.min.y;
  229. fifo[BitmapURect0WidthHeight/4] = (Dx(r) << 16) | Dy(r);
  230. waitforidle(scr);
  231. return 1;
  232. }
  233. static int
  234. nvidiahwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  235. {
  236. ulong* fifo;
  237. fifo = KADDR(scr->io + Fifo);
  238. waitforfifo(scr, BltFifo, 3);
  239. fifo[BltTopLeftSrc/4] = (sr.min.y << 16) | sr.min.x;
  240. fifo[BltTopLeftDst/4] = (r.min.y << 16) | r.min.x;
  241. fifo[BltWidthHeight/4] = (Dy(r) << 16) | Dx(r);
  242. waitforidle(scr);
  243. return 1;
  244. }
  245. void
  246. nvidiablank(VGAscr*, int blank)
  247. {
  248. uchar seq1, crtc1A;
  249. seq1 = vgaxi(Seqx, 1) & ~0x20;
  250. crtc1A = vgaxi(Crtx, 0x1A) & ~0xC0;
  251. if(blank){
  252. seq1 |= 0x20;
  253. // crtc1A |= 0xC0;
  254. crtc1A |= 0x80;
  255. }
  256. vgaxo(Seqx, 1, seq1);
  257. vgaxo(Crtx, 0x1A, crtc1A);
  258. }
  259. static void
  260. nvidiadrawinit(VGAscr *scr)
  261. {
  262. ulong* fifo;
  263. fifo = KADDR(scr->io + Fifo);
  264. waitforfifo(scr, ClipFifo, 2);
  265. fifo[ClipTopLeft/4] = 0x0;
  266. fifo[ClipWidthHeight/4] = 0x80008000;
  267. waitforfifo(scr, PattFifo, 5);
  268. fifo[PattShape/4] = 0;
  269. fifo[PattColor0/4] = 0xffffffff;
  270. fifo[PattColor1/4] = 0xffffffff;
  271. fifo[PattMonochrome0/4] = 0xffffffff;
  272. fifo[PattMonochrome1/4] = 0xffffffff;
  273. waitforfifo(scr, RopFifo, 1);
  274. fifo[RopRop3/4] = 0xCC;
  275. waitforidle(scr);
  276. scr->blank = nvidiablank;
  277. hwblank = 1;
  278. scr->fill = nvidiahwfill;
  279. scr->scroll = nvidiahwscroll;
  280. }
  281. VGAdev vganvidiadev = {
  282. "nvidia",
  283. nvidiaenable,
  284. nil,
  285. nil,
  286. nvidialinear,
  287. nvidiadrawinit,
  288. };
  289. VGAcur vganvidiacur = {
  290. "nvidiahwgc",
  291. nvidiacurenable,
  292. nvidiacurdisable,
  293. nvidiacurload,
  294. nvidiacurmove,
  295. };