vganeomagic.c 10 KB

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