vgamga4xx.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525
  1. /*
  2. * Matrox G200, G400 and G450.
  3. * Written by Philippe Anel <xigh@free.fr>
  4. *
  5. * 2006-08-07 : Minor fix to allow the G200 cards to work fine. YDSTORG is now initialized.
  6. * : Also support for 16 and 24 bit modes is added.
  7. * : by Leonardo Valencia <leoval@anixcorp.com>
  8. */
  9. #include "u.h"
  10. #include "../port/lib.h"
  11. #include "mem.h"
  12. #include "dat.h"
  13. #include "fns.h"
  14. #include "io.h"
  15. #include "../port/error.h"
  16. #define Image IMAGE
  17. #include <draw.h>
  18. #include <memdraw.h>
  19. #include <cursor.h>
  20. #include "screen.h"
  21. enum {
  22. MATROX = 0x102B,
  23. MGA550 = 0x2527,
  24. MGA4xx = 0x0525,
  25. MGA200 = 0x0521,
  26. FCOL = 0x1c24,
  27. FXRIGHT = 0x1cac,
  28. FXLEFT = 0x1ca8,
  29. YDST = 0x1c90,
  30. YLEN = 0x1c5c,
  31. DWGCTL = 0x1c00,
  32. DWG_TRAP = 0x04,
  33. DWG_BITBLT = 0x08,
  34. DWG_ILOAD = 0x09,
  35. DWG_LINEAR = 0x0080,
  36. DWG_SOLID = 0x0800,
  37. DWG_ARZERO = 0x1000,
  38. DWG_SGNZERO = 0x2000,
  39. DWG_SHIFTZERO = 0x4000,
  40. DWG_REPLACE = 0x000C0000,
  41. DWG_BFCOL = 0x04000000,
  42. SRCORG = 0x2cb4,
  43. PITCH = 0x1c8c,
  44. DSTORG = 0x2cb8,
  45. YDSTORG = 0x1c94,
  46. PLNWRT = 0x1c1c,
  47. ZORG = 0x1c0c,
  48. MACCESS = 0x1c04,
  49. STATUS = 0x1e14,
  50. FXBNDRY = 0x1C84,
  51. CXBNDRY = 0x1C80,
  52. YTOP = 0x1C98,
  53. YBOT = 0x1C9C,
  54. YDSTLEN = 0x1C88,
  55. AR0 = 0x1C60,
  56. AR1 = 0x1C64,
  57. AR2 = 0x1C68,
  58. AR3 = 0x1C6C,
  59. AR4 = 0x1C70,
  60. AR5 = 0x1C74,
  61. SGN = 0x1C58,
  62. SGN_LEFT = 1,
  63. SGN_UP = 4,
  64. GO = 0x0100,
  65. FIFOSTATUS = 0x1E10,
  66. CACHEFLUSH = 0x1FFF,
  67. CRTCEXTIDX = 0x1FDE, /* CRTC Extension Index */
  68. CRTCEXTDATA = 0x1FDF, /* CRTC Extension Data */
  69. FILL_OPERAND = 0x800c7804,
  70. };
  71. static Pcidev *
  72. mgapcimatch(void)
  73. {
  74. Pcidev *p;
  75. p = pcimatch(nil, MATROX, MGA4xx);
  76. if(p == nil)
  77. p = pcimatch(nil, MATROX, MGA550);
  78. if(p == nil)
  79. p = pcimatch(nil, MATROX, MGA200);
  80. return p;
  81. }
  82. static void
  83. mgawrite8(VGAscr *scr, int index, uchar val)
  84. {
  85. ((uchar*)scr->mmio)[index] = val;
  86. }
  87. static uchar
  88. mgaread8(VGAscr *scr, int index)
  89. {
  90. return ((uchar*)scr->mmio)[index];
  91. }
  92. static uchar
  93. crtcextset(VGAscr *scr, int index, uchar set, uchar clr)
  94. {
  95. uchar tmp;
  96. mgawrite8(scr, CRTCEXTIDX, index);
  97. tmp = mgaread8(scr, CRTCEXTDATA);
  98. mgawrite8(scr, CRTCEXTIDX, index);
  99. mgawrite8(scr, CRTCEXTDATA, (tmp & ~clr) | set);
  100. return tmp;
  101. }
  102. static void
  103. mga4xxenable(VGAscr* scr)
  104. {
  105. Pcidev *pci;
  106. int size;
  107. int i, n, k;
  108. uchar *p;
  109. uchar x[16];
  110. uchar crtcext3;
  111. if(scr->mmio)
  112. return;
  113. pci = mgapcimatch();
  114. if(pci == nil)
  115. return;
  116. scr->mmio = vmap(pci->mem[1].bar&~0x0F, 16*1024);
  117. if(scr->mmio == nil)
  118. return;
  119. addvgaseg("mga4xxmmio", pci->mem[1].bar&~0x0F, pci->mem[1].size);
  120. /* need to map frame buffer here too, so vga can find memory size */
  121. if(pci->did == MGA4xx || pci->did == MGA550)
  122. size = 32*MB;
  123. else
  124. size = 8*MB;
  125. vgalinearaddr(scr, pci->mem[0].bar&~0x0F, size);
  126. if(scr->paddr){
  127. /* Find out how much memory is here, some multiple of 2 MB */
  128. /* First Set MGA Mode ... */
  129. crtcext3 = crtcextset(scr, 3, 0x80, 0x00);
  130. p = scr->vaddr;
  131. n = (size / MB) / 2;
  132. for(i = 0; i < n; i++){
  133. k = (2*i+1)*MB;
  134. p[k] = 0;
  135. p[k] = i+1;
  136. *((uchar*)scr->mmio + CACHEFLUSH) = 0;
  137. x[i] = p[k];
  138. }
  139. for(i = 1; i < n; i++)
  140. if(x[i] != i+1)
  141. break;
  142. scr->apsize = 2*i*MB; /* sketchy */
  143. addvgaseg("mga4xxscreen", scr->paddr, scr->apsize);
  144. crtcextset(scr, 3, crtcext3, 0xff);
  145. }
  146. }
  147. enum{
  148. Index = 0x00, /* Index */
  149. Data = 0x0A, /* Data */
  150. Cxlsb = 0x0C, /* Cursor X LSB */
  151. Cxmsb = 0x0D, /* Cursor X MSB */
  152. Cylsb = 0x0E, /* Cursor Y LSB */
  153. Cymsb = 0x0F, /* Cursor Y MSB */
  154. Icuradrl = 0x04, /* Cursor Base Address Low */
  155. Icuradrh = 0x05, /* Cursor Base Address High */
  156. Icctl = 0x06, /* Indirect Cursor Control */
  157. };
  158. static void
  159. dac4xxdisable(VGAscr *scr)
  160. {
  161. uchar *dac4xx;
  162. if(scr->mmio == 0)
  163. return;
  164. dac4xx = (uchar*)scr->mmio+0x3C00;
  165. *(dac4xx+Index) = Icctl;
  166. *(dac4xx+Data) = 0x00;
  167. }
  168. static void
  169. dac4xxload(VGAscr *scr, Cursor *curs)
  170. {
  171. int y;
  172. uchar *p;
  173. uchar *dac4xx;
  174. if(scr->mmio == 0)
  175. return;
  176. dac4xx = (uchar*)scr->mmio+0x3C00;
  177. dac4xxdisable(scr);
  178. p = (uchar*)scr->storage;
  179. for(y = 0; y < 64; y++){
  180. *p++ = 0; *p++ = 0; *p++ = 0;
  181. *p++ = 0; *p++ = 0; *p++ = 0;
  182. if(y < 16){
  183. *p++ = curs->set[1+y*2];
  184. *p++ = curs->set[y*2];
  185. } else{
  186. *p++ = 0; *p++ = 0;
  187. }
  188. *p++ = 0; *p++ = 0; *p++ = 0;
  189. *p++ = 0; *p++ = 0; *p++ = 0;
  190. if(y < 16){
  191. *p++ = curs->set[1+y*2]|curs->clr[1+2*y];
  192. *p++ = curs->set[y*2]|curs->clr[2*y];
  193. } else{
  194. *p++ = 0; *p++ = 0;
  195. }
  196. }
  197. scr->offset.x = 64 + curs->offset.x;
  198. scr->offset.y = 64 + curs->offset.y;
  199. *(dac4xx+Index) = Icctl;
  200. *(dac4xx+Data) = 0x03;
  201. }
  202. static int
  203. dac4xxmove(VGAscr *scr, Point p)
  204. {
  205. int x, y;
  206. uchar *dac4xx;
  207. if(scr->mmio == 0)
  208. return 1;
  209. dac4xx = (uchar*)scr->mmio + 0x3C00;
  210. x = p.x + scr->offset.x;
  211. y = p.y + scr->offset.y;
  212. *(dac4xx+Cxlsb) = x & 0xFF;
  213. *(dac4xx+Cxmsb) = (x>>8) & 0x0F;
  214. *(dac4xx+Cylsb) = y & 0xFF;
  215. *(dac4xx+Cymsb) = (y>>8) & 0x0F;
  216. return 0;
  217. }
  218. static void
  219. dac4xxenable(VGAscr *scr)
  220. {
  221. uchar *dac4xx;
  222. ulong storage;
  223. if(scr->mmio == 0)
  224. return;
  225. dac4xx = (uchar*)scr->mmio+0x3C00;
  226. dac4xxdisable(scr);
  227. storage = (scr->apsize-4096)&~0x3ff;
  228. *(dac4xx+Index) = Icuradrl;
  229. *(dac4xx+Data) = 0xff & (storage >> 10);
  230. *(dac4xx+Index) = Icuradrh;
  231. *(dac4xx+Data) = 0xff & (storage >> 18);
  232. scr->storage = (ulong)scr->vaddr + storage;
  233. /* Show X11-Like Cursor */
  234. *(dac4xx+Index) = Icctl;
  235. *(dac4xx+Data) = 0x03;
  236. /* Cursor Color 0 : White */
  237. *(dac4xx+Index) = 0x08;
  238. *(dac4xx+Data) = 0xff;
  239. *(dac4xx+Index) = 0x09;
  240. *(dac4xx+Data) = 0xff;
  241. *(dac4xx+Index) = 0x0a;
  242. *(dac4xx+Data) = 0xff;
  243. /* Cursor Color 1 : Black */
  244. *(dac4xx+Index) = 0x0c;
  245. *(dac4xx+Data) = 0x00;
  246. *(dac4xx+Index) = 0x0d;
  247. *(dac4xx+Data) = 0x00;
  248. *(dac4xx+Index) = 0x0e;
  249. *(dac4xx+Data) = 0x00;
  250. /* Cursor Color 2 : Red */
  251. *(dac4xx+Index) = 0x10;
  252. *(dac4xx+Data) = 0xff;
  253. *(dac4xx+Index) = 0x11;
  254. *(dac4xx+Data) = 0x00;
  255. *(dac4xx+Index) = 0x12;
  256. *(dac4xx+Data) = 0x00;
  257. /*
  258. * Load, locate and enable the
  259. * 64x64 cursor in X11 mode.
  260. */
  261. dac4xxload(scr, &arrow);
  262. dac4xxmove(scr, ZP);
  263. }
  264. static void
  265. mga4xxblank(VGAscr *scr, int blank)
  266. {
  267. char *cp;
  268. uchar *mga;
  269. uchar seq1, crtcext1;
  270. /* blank = 0 -> turn screen on */
  271. /* blank = 1 -> turn screen off */
  272. if(scr->mmio == 0)
  273. return;
  274. mga = (uchar*)scr->mmio;
  275. if(blank == 0){
  276. seq1 = 0x00;
  277. crtcext1 = 0x00;
  278. } else {
  279. seq1 = 0x20;
  280. crtcext1 = 0x10; /* Default value ... : standby */
  281. cp = getconf("*dpms");
  282. if(cp){
  283. if(cistrcmp(cp, "standby") == 0)
  284. crtcext1 = 0x10;
  285. else if(cistrcmp(cp, "suspend") == 0)
  286. crtcext1 = 0x20;
  287. else if(cistrcmp(cp, "off") == 0)
  288. crtcext1 = 0x30;
  289. }
  290. }
  291. *(mga + 0x1fc4) = 1;
  292. seq1 |= *(mga + 0x1fc5) & ~0x20;
  293. *(mga + 0x1fc5) = seq1;
  294. *(mga + 0x1fde) = 1;
  295. crtcext1 |= *(mga + 0x1fdf) & ~0x30;
  296. *(mga + 0x1fdf) = crtcext1;
  297. }
  298. static void
  299. mgawrite32(uchar *mga, ulong reg, ulong val)
  300. {
  301. *((ulong*)(&mga[reg])) = val;
  302. }
  303. static ulong
  304. mgaread32(uchar *mga, ulong reg)
  305. {
  306. return *((ulong*)(&mga[reg]));
  307. }
  308. static void
  309. mga_fifo(uchar *mga, uchar n)
  310. {
  311. ulong t;
  312. #define Timeout 100
  313. for (t = 0; t < Timeout; t++)
  314. if ((mgaread32(mga, FIFOSTATUS) & 0xff) >= n)
  315. break;
  316. if (t >= Timeout)
  317. print("mga4xx: fifo timeout");
  318. }
  319. static int
  320. mga4xxfill(VGAscr *scr, Rectangle r, ulong color)
  321. {
  322. uchar *mga;
  323. if(scr->mmio == 0)
  324. return 0;
  325. mga = (uchar*)scr->mmio;
  326. mga_fifo(mga, 7);
  327. mgawrite32(mga, DWGCTL, 0);
  328. mgawrite32(mga, FCOL, color);
  329. mgawrite32(mga, FXLEFT, r.min.x);
  330. mgawrite32(mga, FXRIGHT, r.max.x);
  331. mgawrite32(mga, YDST, r.min.y);
  332. mgawrite32(mga, YLEN, Dy(r));
  333. mgawrite32(mga, DWGCTL + GO, FILL_OPERAND);
  334. while(mgaread32(mga, STATUS) & 0x00010000)
  335. ;
  336. return 1;
  337. }
  338. static int
  339. mga4xxscroll(VGAscr *scr, Rectangle dr, Rectangle sr)
  340. {
  341. uchar * mga;
  342. int pitch;
  343. int width, height;
  344. ulong start, end, sgn;
  345. Point sp, dp;
  346. if(scr->mmio == 0)
  347. return 0;
  348. mga = (uchar*)scr->mmio;
  349. assert(Dx(sr) == Dx(dr) && Dy(sr) == Dy(dr));
  350. sp = sr.min;
  351. dp = dr.min;
  352. if(eqpt(sp, dp))
  353. return 1;
  354. pitch = Dx(scr->gscreen->r);
  355. width = Dx(sr);
  356. height = Dy(sr);
  357. sgn = 0;
  358. if(dp.y > sp.y && dp.y < sp.y + height){
  359. sp.y += height - 1;
  360. dp.y += height - 1;
  361. sgn |= SGN_UP;
  362. }
  363. width--;
  364. start = end = sp.x + (sp.y * pitch);
  365. if(dp.x > sp.x && dp.x < sp.x + width){
  366. start += width;
  367. sgn |= SGN_LEFT;
  368. }
  369. else
  370. end += width;
  371. mga_fifo(mga, 8);
  372. mgawrite32(mga, DWGCTL, 0);
  373. mgawrite32(mga, SGN, sgn);
  374. mgawrite32(mga, AR5, sgn & SGN_UP ? -pitch : pitch);
  375. mgawrite32(mga, AR0, end);
  376. mgawrite32(mga, AR3, start);
  377. mgawrite32(mga, FXBNDRY, ((dp.x + width) << 16) | dp.x);
  378. mgawrite32(mga, YDSTLEN, (dp.y << 16) | height);
  379. mgawrite32(mga, DWGCTL + GO, DWG_BITBLT | DWG_SHIFTZERO | DWG_BFCOL | DWG_REPLACE);
  380. while(mgaread32(mga, STATUS) & 0x00010000)
  381. ;
  382. return 1;
  383. }
  384. static void
  385. mga4xxdrawinit(VGAscr *scr)
  386. {
  387. uchar *mga;
  388. if(scr->mmio == 0)
  389. return;
  390. mga = (uchar*)scr->mmio;
  391. mgawrite32(mga, SRCORG, 0);
  392. mgawrite32(mga, DSTORG, 0);
  393. mgawrite32(mga, YDSTORG, 0);
  394. mgawrite32(mga, ZORG, 0);
  395. mgawrite32(mga, PLNWRT, ~0);
  396. mgawrite32(mga, FCOL, 0xffff0000);
  397. mgawrite32(mga, CXBNDRY, 0xFFFF0000);
  398. mgawrite32(mga, YTOP, 0);
  399. mgawrite32(mga, YBOT, 0x01FFFFFF);
  400. mgawrite32(mga, PITCH, Dx(scr->gscreen->r) & ((1 << 13) - 1));
  401. switch(scr->gscreen->depth){
  402. case 8:
  403. mgawrite32(mga, MACCESS, 0);
  404. break;
  405. case 16:
  406. mgawrite32(mga, MACCESS, 1);
  407. break;
  408. case 24:
  409. mgawrite32(mga, MACCESS, 3);
  410. break;
  411. case 32:
  412. mgawrite32(mga, MACCESS, 2);
  413. break;
  414. default:
  415. return; /* depth not supported ! */
  416. }
  417. scr->fill = mga4xxfill;
  418. scr->scroll = mga4xxscroll;
  419. scr->blank = mga4xxblank;
  420. }
  421. VGAdev vgamga4xxdev = {
  422. "mga4xx",
  423. mga4xxenable, /* enable */
  424. 0, /* disable */
  425. 0, /* page */
  426. 0, /* linear */
  427. mga4xxdrawinit,
  428. };
  429. VGAcur vgamga4xxcur = {
  430. "mga4xxhwgc",
  431. dac4xxenable,
  432. dac4xxdisable,
  433. dac4xxload,
  434. dac4xxmove,
  435. };