vganeomagic.c 10 KB

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