vganeomagic.c 11 KB

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