vganeomagic.c 11 KB

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