vganeomagic.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509
  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. typedef struct CursorNM CursorNM;
  14. struct CursorNM {
  15. int enable;
  16. int x;
  17. int y;
  18. int colour1;
  19. int colour2;
  20. int addr;
  21. };
  22. static void
  23. neomagicenable(VGAscr* scr)
  24. {
  25. Pcidev *p;
  26. int curoff, vmsize;
  27. ulong ioaddr;
  28. ulong iosize;
  29. /*
  30. * scr->mmio holds the virtual address of the cursor registers
  31. * in the MMIO space. This may need to change for older chips
  32. * which have the MMIO space offset in the framebuffer region.
  33. *
  34. * scr->io holds the offset into mmio of the CursorNM struct.
  35. */
  36. if(scr->mmio)
  37. return;
  38. if(p = pcimatch(nil, 0x10C8, 0)){
  39. switch(p->did){
  40. case 0x0003: /* MagicGraph 128ZV */
  41. curoff = 0x100;
  42. vmsize = 1152*1024;
  43. ioaddr = (p->mem[0].bar & ~0x0F) + 0x200000;
  44. iosize = 0x200000;
  45. break;
  46. case 0x0083: /* MagicGraph 128ZV+ */
  47. curoff = 0x100;
  48. vmsize = 1152*1024;
  49. ioaddr = p->mem[1].bar & ~0x0F;
  50. iosize = p->mem[1].size;
  51. break;
  52. case 0x0004: /* MagicGraph 128XD */
  53. curoff = 0x100;
  54. vmsize = 2048*1024;
  55. ioaddr = p->mem[1].bar & ~0x0F;
  56. iosize = p->mem[1].size;
  57. break;
  58. case 0x0005: /* MagicMedia 256AV */
  59. curoff = 0x1000;
  60. vmsize = 2560*1024;
  61. ioaddr = p->mem[1].bar & ~0x0F;
  62. iosize = p->mem[1].size;
  63. break;
  64. case 0x0006: /* MagicMedia 256ZX */
  65. curoff = 0x1000;
  66. vmsize = 4096*1024;
  67. ioaddr = p->mem[1].bar & ~0x0F;
  68. iosize = p->mem[1].size;
  69. break;
  70. default:
  71. return;
  72. }
  73. }
  74. else
  75. return;
  76. scr->pci = p;
  77. scr->mmio = vmap(ioaddr, iosize);
  78. if(scr->mmio == nil)
  79. return;
  80. addvgaseg("neomagicmmio", ioaddr, iosize);
  81. /*
  82. * Find a place for the cursor data in display memory.
  83. * 2 cursor images might be needed, 1KB each so use the
  84. * last 2KB of the framebuffer.
  85. */
  86. scr->storage = vmsize-2*1024;
  87. scr->io = curoff;
  88. vgalinearpci(scr);
  89. if(scr->paddr)
  90. addvgaseg("neomagicscreen", scr->paddr, scr->apsize);
  91. }
  92. static void
  93. neomagiccurdisable(VGAscr* scr)
  94. {
  95. CursorNM *cursornm;
  96. if(scr->mmio == 0)
  97. return;
  98. cursornm = (void*)((char*)scr->mmio + scr->io);
  99. cursornm->enable = 0;
  100. }
  101. static void
  102. neomagicinitcursor(VGAscr* scr, int xo, int yo, int index)
  103. {
  104. uchar *p;
  105. uint p0, p1;
  106. int x, y;
  107. p = (uchar*)scr->vaddr;
  108. p += scr->storage + index*1024;
  109. for(y = yo; y < 16; y++){
  110. p0 = scr->set[2*y];
  111. p1 = scr->set[2*y+1];
  112. if(xo){
  113. p0 = (p0<<xo)|(p1>>(8-xo));
  114. p1 <<= xo;
  115. }
  116. *p++ = p0;
  117. *p++ = p1;
  118. for(x = 16; x < 64; x += 8)
  119. *p++ = 0x00;
  120. p0 = scr->clr[2*y]|scr->set[2*y];
  121. p1 = scr->clr[2*y+1]|scr->set[2*y+1];
  122. if(xo){
  123. p0 = (p0<<xo)|(p1>>(8-xo));
  124. p1 <<= xo;
  125. }
  126. *p++ = p0;
  127. *p++ = p1;
  128. for(x = 16; x < 64; x += 8)
  129. *p++ = 0x00;
  130. }
  131. while(y < 64+yo){
  132. for(x = 0; x < 64; x += 8){
  133. *p++ = 0x00;
  134. *p++ = 0x00;
  135. }
  136. y++;
  137. }
  138. }
  139. static void
  140. neomagiccurload(VGAscr* scr, Cursor* curs)
  141. {
  142. CursorNM *cursornm;
  143. if(scr->mmio == 0)
  144. return;
  145. cursornm = (void*)((char*)scr->mmio + scr->io);
  146. cursornm->enable = 0;
  147. memmove(&scr->Cursor, curs, sizeof(Cursor));
  148. neomagicinitcursor(scr, 0, 0, 0);
  149. cursornm->enable = 1;
  150. }
  151. static int
  152. neomagiccurmove(VGAscr* scr, Point p)
  153. {
  154. CursorNM *cursornm;
  155. int addr, index, x, xo, y, yo;
  156. if(scr->mmio == 0)
  157. return 1;
  158. cursornm = (void*)((char*)scr->mmio + scr->io);
  159. index = 0;
  160. if((x = p.x+scr->offset.x) < 0){
  161. xo = -x;
  162. x = 0;
  163. }
  164. else
  165. xo = 0;
  166. if((y = p.y+scr->offset.y) < 0){
  167. yo = -y;
  168. y = 0;
  169. }
  170. else
  171. yo = 0;
  172. if(xo || yo){
  173. index = 1;
  174. neomagicinitcursor(scr, xo, yo, index);
  175. }
  176. addr = ((scr->storage+(1024*index))>>10) & 0xFFF;
  177. addr = ((addr & 0x00F)<<8)|((addr>>4) & 0xFF);
  178. if(cursornm->addr != addr)
  179. cursornm->addr = addr;
  180. cursornm->x = x;
  181. cursornm->y = y;
  182. return 0;
  183. }
  184. static void
  185. neomagiccurenable(VGAscr* scr)
  186. {
  187. CursorNM *cursornm;
  188. neomagicenable(scr);
  189. if(scr->mmio == 0)
  190. return;
  191. cursornm = (void*)((char*)scr->mmio + scr->io);
  192. cursornm->enable = 0;
  193. /*
  194. * Cursor colours.
  195. */
  196. cursornm->colour1 = (Pblack<<16)|(Pblack<<8)|Pblack;
  197. cursornm->colour2 = (Pwhite<<16)|(Pwhite<<8)|Pwhite;
  198. /*
  199. * Load, locate and enable the 64x64 cursor.
  200. */
  201. neomagiccurload(scr, &arrow);
  202. neomagiccurmove(scr, ZP);
  203. cursornm->enable = 1;
  204. }
  205. static int neomagicbltflags;
  206. /* registers */
  207. enum {
  208. BltStat = 0,
  209. BltCntl = 1,
  210. XPColor = 2,
  211. FGColor = 3,
  212. BGColor = 4,
  213. Pitch = 5,
  214. ClipLT = 6,
  215. ClipRB = 7,
  216. SrcBitOff = 8,
  217. SrcStartOff = 9,
  218. DstStartOff = 11,
  219. XYExt = 12,
  220. PageCntl = 20,
  221. PageBase,
  222. PostBase,
  223. PostPtr,
  224. DataPtr,
  225. };
  226. /* flags */
  227. enum {
  228. NEO_BS0_BLT_BUSY = 0x00000001,
  229. NEO_BS0_FIFO_AVAIL = 0x00000002,
  230. NEO_BS0_FIFO_PEND = 0x00000004,
  231. NEO_BC0_DST_Y_DEC = 0x00000001,
  232. NEO_BC0_X_DEC = 0x00000002,
  233. NEO_BC0_SRC_TRANS = 0x00000004,
  234. NEO_BC0_SRC_IS_FG = 0x00000008,
  235. NEO_BC0_SRC_Y_DEC = 0x00000010,
  236. NEO_BC0_FILL_PAT = 0x00000020,
  237. NEO_BC0_SRC_MONO = 0x00000040,
  238. NEO_BC0_SYS_TO_VID = 0x00000080,
  239. NEO_BC1_DEPTH8 = 0x00000100,
  240. NEO_BC1_DEPTH16 = 0x00000200,
  241. NEO_BC1_DEPTH24 = 0x00000300,
  242. NEO_BC1_X_320 = 0x00000400,
  243. NEO_BC1_X_640 = 0x00000800,
  244. NEO_BC1_X_800 = 0x00000c00,
  245. NEO_BC1_X_1024 = 0x00001000,
  246. NEO_BC1_X_1152 = 0x00001400,
  247. NEO_BC1_X_1280 = 0x00001800,
  248. NEO_BC1_X_1600 = 0x00001c00,
  249. NEO_BC1_DST_TRANS = 0x00002000,
  250. NEO_BC1_MSTR_BLT = 0x00004000,
  251. NEO_BC1_FILTER_Z = 0x00008000,
  252. NEO_BC2_WR_TR_DST = 0x00800000,
  253. NEO_BC3_SRC_XY_ADDR = 0x01000000,
  254. NEO_BC3_DST_XY_ADDR = 0x02000000,
  255. NEO_BC3_CLIP_ON = 0x04000000,
  256. NEO_BC3_FIFO_EN = 0x08000000,
  257. NEO_BC3_BLT_ON_ADDR = 0x10000000,
  258. NEO_BC3_SKIP_MAPPING = 0x80000000,
  259. NEO_MODE1_DEPTH8 = 0x0100,
  260. NEO_MODE1_DEPTH16 = 0x0200,
  261. NEO_MODE1_DEPTH24 = 0x0300,
  262. NEO_MODE1_X_320 = 0x0400,
  263. NEO_MODE1_X_640 = 0x0800,
  264. NEO_MODE1_X_800 = 0x0c00,
  265. NEO_MODE1_X_1024 = 0x1000,
  266. NEO_MODE1_X_1152 = 0x1400,
  267. NEO_MODE1_X_1280 = 0x1800,
  268. NEO_MODE1_X_1600 = 0x1c00,
  269. NEO_MODE1_BLT_ON_ADDR = 0x2000,
  270. };
  271. /* Raster Operations */
  272. enum {
  273. GXclear = 0x000000, /* 0x0000 */
  274. GXand = 0x080000, /* 0x1000 */
  275. GXandReverse = 0x040000, /* 0x0100 */
  276. GXcopy = 0x0c0000, /* 0x1100 */
  277. GXandInvert = 0x020000, /* 0x0010 */
  278. GXnoop = 0x0a0000, /* 0x1010 */
  279. GXxor = 0x060000, /* 0x0110 */
  280. GXor = 0x0e0000, /* 0x1110 */
  281. GXnor = 0x010000, /* 0x0001 */
  282. GXequiv = 0x090000, /* 0x1001 */
  283. GXinvert = 0x050000, /* 0x0101 */
  284. GXorReverse = 0x0d0000, /* 0x1101 */
  285. GXcopyInvert = 0x030000, /* 0x0011 */
  286. GXorInverted = 0x0b0000, /* 0x1011 */
  287. GXnand = 0x070000, /* 0x0111 */
  288. GXset = 0x0f0000, /* 0x1111 */
  289. };
  290. static void
  291. waitforidle(VGAscr *scr)
  292. {
  293. ulong *mmio;
  294. long x;
  295. mmio = scr->mmio;
  296. x = 0;
  297. while((mmio[BltStat] & NEO_BS0_BLT_BUSY) && x++ < 1000000)
  298. ;
  299. //if(x >= 1000000)
  300. // iprint("idle stat %lud scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat], scr->mmio, scr, getcallerpc(&scr));
  301. }
  302. static void
  303. waitforfifo(VGAscr *scr, int entries)
  304. {
  305. ulong *mmio;
  306. long x;
  307. mmio = scr->mmio;
  308. x = 0;
  309. while(((mmio[BltStat]>>8) < entries) && x++ < 1000000)
  310. ;
  311. //if(x >= 1000000)
  312. // iprint("fifo stat %d scrmmio %.8lux scr %p pc %luX\n", mmio[BltStat]>>8, scr->mmio, scr, getcallerpc(&scr));
  313. /* DirectFB says the above doesn't work. if so... */
  314. /* waitforidle(scr); */
  315. }
  316. static int
  317. neomagichwfill(VGAscr *scr, Rectangle r, ulong sval)
  318. {
  319. ulong *mmio;
  320. mmio = scr->mmio;
  321. waitforfifo(scr, 1);
  322. mmio[FGColor] = sval;
  323. waitforfifo(scr, 3);
  324. mmio[BltCntl] = neomagicbltflags
  325. | NEO_BC3_FIFO_EN
  326. | NEO_BC0_SRC_IS_FG
  327. | NEO_BC3_SKIP_MAPPING
  328. | GXcopy;
  329. mmio[DstStartOff] = scr->paddr
  330. + r.min.y*scr->gscreen->width*BY2WD
  331. + r.min.x*scr->gscreen->depth/BI2BY;
  332. mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
  333. waitforidle(scr);
  334. return 1;
  335. }
  336. static int
  337. neomagichwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  338. {
  339. ulong *mmio;
  340. int pitch, pixel;
  341. mmio = scr->mmio;
  342. pitch = scr->gscreen->width*BY2WD;
  343. pixel = scr->gscreen->depth/BI2BY;
  344. waitforfifo(scr, 4);
  345. if (r.min.y < sr.min.y || (r.min.y == sr.min.y && r.min.x < sr.min.x)) {
  346. /* start from upper-left */
  347. mmio[BltCntl] = neomagicbltflags
  348. | NEO_BC3_FIFO_EN
  349. | NEO_BC3_SKIP_MAPPING
  350. | GXcopy;
  351. mmio[SrcStartOff] = scr->paddr
  352. + sr.min.y*pitch + sr.min.x*pixel;
  353. mmio[DstStartOff] = scr->paddr
  354. + r.min.y*pitch + r.min.x*pixel;
  355. } else {
  356. /* start from lower-right */
  357. mmio[BltCntl] = neomagicbltflags
  358. | NEO_BC0_X_DEC
  359. | NEO_BC0_DST_Y_DEC
  360. | NEO_BC0_SRC_Y_DEC
  361. | NEO_BC3_FIFO_EN
  362. | NEO_BC3_SKIP_MAPPING
  363. | GXcopy;
  364. mmio[SrcStartOff] = scr->paddr
  365. + (sr.max.y-1)*pitch + (sr.max.x-1)*pixel;
  366. mmio[DstStartOff] = scr->paddr
  367. + (r.max.y-1)*pitch + (r.max.x-1)*pixel;
  368. }
  369. mmio[XYExt] = (Dy(r) << 16) | (Dx(r) & 0xffff);
  370. waitforidle(scr);
  371. return 1;
  372. }
  373. static void
  374. neomagicdrawinit(VGAscr *scr)
  375. {
  376. ulong *mmio;
  377. uint bltmode, pitch;
  378. mmio = scr->mmio;
  379. pitch = scr->gscreen->width*BY2WD;
  380. neomagicbltflags = bltmode = 0;
  381. switch(scr->gscreen->depth) {
  382. case 8:
  383. bltmode |= NEO_MODE1_DEPTH8;
  384. neomagicbltflags |= NEO_BC1_DEPTH8;
  385. break;
  386. case 16:
  387. bltmode |= NEO_MODE1_DEPTH16;
  388. neomagicbltflags |= NEO_BC1_DEPTH16;
  389. break;
  390. case 24: /* I can't get it to work, and XFree86 doesn't either. */
  391. default: /* give up */
  392. return;
  393. }
  394. switch(Dx(scr->gscreen->r)) {
  395. case 320:
  396. bltmode |= NEO_MODE1_X_320;
  397. neomagicbltflags |= NEO_BC1_X_320;
  398. break;
  399. case 640:
  400. bltmode |= NEO_MODE1_X_640;
  401. neomagicbltflags |= NEO_BC1_X_640;
  402. break;
  403. case 800:
  404. bltmode |= NEO_MODE1_X_800;
  405. neomagicbltflags |= NEO_BC1_X_800;
  406. break;
  407. case 1024:
  408. bltmode |= NEO_MODE1_X_1024;
  409. neomagicbltflags |= NEO_BC1_X_1024;
  410. break;
  411. case 1152:
  412. bltmode |= NEO_MODE1_X_1152;
  413. neomagicbltflags |= NEO_BC1_X_1152;
  414. break;
  415. case 1280:
  416. bltmode |= NEO_MODE1_X_1280;
  417. neomagicbltflags |= NEO_BC1_X_1280;
  418. break;
  419. case 1600:
  420. bltmode |= NEO_MODE1_X_1600;
  421. neomagicbltflags |= NEO_BC1_X_1600;
  422. break;
  423. default:
  424. /* don't worry about it */
  425. break;
  426. }
  427. waitforidle(scr);
  428. mmio[BltStat] = bltmode << 16;
  429. mmio[Pitch] = (pitch << 16) | (pitch & 0xffff);
  430. scr->fill = neomagichwfill;
  431. scr->scroll = neomagichwscroll;
  432. }
  433. VGAdev vganeomagicdev = {
  434. "neomagic",
  435. neomagicenable,
  436. nil,
  437. nil,
  438. nil,
  439. neomagicdrawinit,
  440. };
  441. VGAcur vganeomagiccur = {
  442. "neomagichwgc",
  443. neomagiccurenable,
  444. neomagiccurdisable,
  445. neomagiccurload,
  446. neomagiccurmove,
  447. };