vgat2r4.c 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533
  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. /*
  14. * #9 Ticket to Ride IV.
  15. */
  16. enum {
  17. IndexLo = 0x10/4,
  18. IndexHi = 0x14/4,
  19. Data = 0x18/4,
  20. IndexCtl = 0x1C/4,
  21. Zoom = 0x54/4,
  22. };
  23. enum { /* index registers */
  24. CursorSyncCtl = 0x03,
  25. HsyncHi = 0x01,
  26. HsyncLo = 0x02,
  27. VsyncHi = 0x04,
  28. VsyncLo = 0x08,
  29. CursorCtl = 0x30,
  30. CursorXLo = 0x31,
  31. CursorXHi = 0x32,
  32. CursorYLo = 0x33,
  33. CursorYHi = 0x34,
  34. CursorHotX = 0x35,
  35. CursorHotY = 0x36,
  36. CursorR1 = 0x40,
  37. CursorG1 = 0x41,
  38. CursorB1 = 0x42,
  39. CursorR2 = 0x43,
  40. CursorG2 = 0x44,
  41. CursorB2 = 0x45,
  42. CursorR3 = 0x46,
  43. CursorG3 = 0x47,
  44. CursorB3 = 0x48,
  45. CursorArray = 0x100,
  46. CursorMode32x32 = 0x23,
  47. CursorMode64x64 = 0x27,
  48. CursorMode = CursorMode32x32,
  49. };
  50. static void
  51. t2r4enable(VGAscr* scr)
  52. {
  53. Pcidev *p;
  54. void *mmio;
  55. if(scr->mmio)
  56. return;
  57. if(p = pcimatch(nil, 0x105D, 0)){
  58. switch(p->did){
  59. case 0x5348:
  60. break;
  61. default:
  62. return;
  63. }
  64. }
  65. else
  66. return;
  67. scr->pci = p;
  68. mmio = vmap(p->mem[4].bar & ~0x0F, p->mem[4].size);
  69. if(mmio == nil)
  70. return;
  71. addvgaseg("t2r4mmio", p->mem[4].bar & ~0x0F, p->mem[4].size);
  72. scr->mmio = mmio;
  73. vgalinearpci(scr);
  74. if(scr->paddr) {
  75. addvgaseg("t2r4screen", scr->paddr, scr->apsize);
  76. mtrr(scr->paddr, scr->apsize, "wc");
  77. }
  78. }
  79. static uchar
  80. t2r4xi(VGAscr* scr, int index)
  81. {
  82. ulong *mmio;
  83. mmio = scr->mmio;
  84. mmio[IndexLo] = index & 0xFF;
  85. mmio[IndexHi] = (index>>8) & 0xFF;
  86. return mmio[Data];
  87. }
  88. static void
  89. t2r4xo(VGAscr* scr, int index, uchar data)
  90. {
  91. ulong *mmio;
  92. mmio = scr->mmio;
  93. mmio[IndexLo] = index & 0xFF;
  94. mmio[IndexHi] = (index>>8) & 0xFF;
  95. mmio[Data] = data;
  96. }
  97. static void
  98. t2r4curdisable(VGAscr* scr)
  99. {
  100. if(scr->mmio == 0)
  101. return;
  102. t2r4xo(scr, CursorCtl, 0x00);
  103. }
  104. static void
  105. t2r4curload(VGAscr* scr, Cursor* curs)
  106. {
  107. uchar *data;
  108. int size, x, y, zoom;
  109. ulong clr, *mmio, pixels, set;
  110. mmio = scr->mmio;
  111. if(mmio == 0)
  112. return;
  113. /*
  114. * Make sure cursor is off by initialising the cursor
  115. * control to defaults.
  116. */
  117. t2r4xo(scr, CursorCtl, 0x00);
  118. /*
  119. * Set auto-increment mode for index-register addressing
  120. * and initialise the cursor array index.
  121. */
  122. mmio[IndexCtl] = 0x01;
  123. mmio[IndexLo] = CursorArray & 0xFF;
  124. mmio[IndexHi] = (CursorArray>>8) & 0xFF;
  125. /*
  126. * Initialise the cursor RAM array. There are 2 planes,
  127. * p0 and p1. Data is written 4 pixels per byte, with p1 the
  128. * MS bit of each pixel.
  129. * The cursor is set in X-Windows mode which gives the following
  130. * truth table:
  131. * p1 p0 colour
  132. * 0 0 underlying pixel colour
  133. * 0 1 underlying pixel colour
  134. * 1 0 cursor colour 1
  135. * 1 1 cursor colour 2
  136. * Put the cursor into the top-left of the array.
  137. *
  138. * Although this looks a lot like the IBM RGB524 cursor, the
  139. * scanlines appear to be twice as long as they should be and
  140. * some of the other features are missing.
  141. */
  142. if(mmio[Zoom] & 0x0F)
  143. zoom = 32;
  144. else
  145. zoom = 16;
  146. data = (uchar*)&mmio[Data];
  147. for(y = 0; y < zoom; y++){
  148. clr = (curs->clr[2*y]<<8)|curs->clr[y*2 + 1];
  149. set = (curs->set[2*y]<<8)|curs->set[y*2 + 1];
  150. pixels = 0;
  151. for(x = 0; x < 16; x++){
  152. if(set & (1<<x))
  153. pixels |= 0x03<<(x*2);
  154. else if(clr & (1<<x))
  155. pixels |= 0x02<<(x*2);
  156. }
  157. *data = pixels>>24;
  158. *data = pixels>>16;
  159. *data = pixels>>8;
  160. *data = pixels;
  161. *data = 0x00;
  162. *data = 0x00;
  163. *data = 0x00;
  164. *data = 0x00;
  165. if(CursorMode == CursorMode32x32 && zoom == 16)
  166. continue;
  167. *data = pixels>>24;
  168. *data = pixels>>16;
  169. *data = pixels>>8;
  170. *data = pixels;
  171. *data = 0x00;
  172. *data = 0x00;
  173. *data = 0x00;
  174. *data = 0x00;
  175. }
  176. if(CursorMode == CursorMode32x32)
  177. size = 32;
  178. else
  179. size = 64;
  180. while(y < size){
  181. for(x = 0; x < size/8; x++){
  182. *data = 0x00;
  183. *data = 0x00;
  184. }
  185. y++;
  186. }
  187. mmio[IndexCtl] = 0x00;
  188. /*
  189. * Initialise the hotpoint and enable the cursor.
  190. */
  191. t2r4xo(scr, CursorHotX, -curs->offset.x);
  192. zoom = (scr->mmio[Zoom] & 0x0F)+1;
  193. t2r4xo(scr, CursorHotY, -curs->offset.y*zoom);
  194. t2r4xo(scr, CursorCtl, CursorMode);
  195. }
  196. static int
  197. t2r4curmove(VGAscr* scr, Point p)
  198. {
  199. int y, zoom;
  200. if(scr->mmio == 0)
  201. return 1;
  202. t2r4xo(scr, CursorXLo, p.x & 0xFF);
  203. t2r4xo(scr, CursorXHi, (p.x>>8) & 0x0F);
  204. zoom = (scr->mmio[Zoom] & 0x0F)+1;
  205. y = p.y*zoom;
  206. t2r4xo(scr, CursorYLo, y & 0xFF);
  207. t2r4xo(scr, CursorYHi, (y>>8) & 0x0F);
  208. return 0;
  209. }
  210. static void
  211. t2r4curenable(VGAscr* scr)
  212. {
  213. t2r4enable(scr);
  214. if(scr->mmio == 0)
  215. return;
  216. /*
  217. * Make sure cursor is off by initialising the cursor
  218. * control to defaults.
  219. */
  220. t2r4xo(scr, CursorCtl, 0x00);
  221. /*
  222. * Cursor colour 1 (white),
  223. * cursor colour 2 (black).
  224. */
  225. t2r4xo(scr, CursorR1, Pwhite);
  226. t2r4xo(scr, CursorG1, Pwhite);
  227. t2r4xo(scr, CursorB1, Pwhite);
  228. t2r4xo(scr, CursorR2, Pblack);
  229. t2r4xo(scr, CursorG2, Pblack);
  230. t2r4xo(scr, CursorB2, Pblack);
  231. /*
  232. * Load, locate and enable the cursor, 64x64, mode 2.
  233. */
  234. t2r4curload(scr, &arrow);
  235. t2r4curmove(scr, ZP);
  236. t2r4xo(scr, CursorCtl, CursorMode);
  237. }
  238. enum {
  239. Flow = 0x08/4,
  240. Busy = 0x0C/4,
  241. BufCtl = 0x20/4,
  242. DeSorg = 0x28/4,
  243. DeDorg = 0x2C/4,
  244. DeSptch = 0x40/4,
  245. DeDptch = 0x44/4,
  246. CmdOpc = 0x50/4,
  247. CmdRop = 0x54/4,
  248. CmdStyle = 0x58/4,
  249. CmdPatrn = 0x5C/4,
  250. CmdClp = 0x60/4,
  251. CmdPf = 0x64/4,
  252. Fore = 0x68/4,
  253. Back = 0x6C/4,
  254. Mask = 0x70/4,
  255. DeKey = 0x74/4,
  256. Lpat = 0x78/4,
  257. Pctrl = 0x7C/4,
  258. Clptl = 0x80/4,
  259. Clpbr = 0x84/4,
  260. XY0 = 0x88/4,
  261. XY1 = 0x8C/4,
  262. XY2 = 0x90/4,
  263. XY3 = 0x94/4,
  264. XY4 = 0x98/4,
  265. Alpha = 0x128/4,
  266. ACtl = 0x16C/4,
  267. RBaseD = 0x4000/4,
  268. };
  269. /* wait until pipeline ready for new command */
  270. static void
  271. waitforfifo(VGAscr *scr)
  272. {
  273. int x;
  274. ulong *d;
  275. x = 0;
  276. d = scr->mmio + RBaseD;
  277. while((d[Busy]&1) && x++ < 1000000)
  278. ;
  279. if(x >= 1000000) /* shouldn't happen */
  280. iprint("busy %8lux\n", d[Busy]);
  281. }
  282. /* wait until command has finished executing */
  283. static void
  284. waitforcmd(VGAscr *scr)
  285. {
  286. int x;
  287. ulong *d;
  288. x = 0;
  289. d = scr->mmio + RBaseD;
  290. while((d[Flow]&0x1B) && x++ < 1000000)
  291. ;
  292. if(x >= 1000000) /* shouldn't happen */
  293. iprint("flow %8lux\n", d[Flow]);
  294. }
  295. /* wait until memory controller not busy (i.e. wait for writes to flush) */
  296. static void
  297. waitformem(VGAscr *scr)
  298. {
  299. int x;
  300. ulong *d;
  301. x = 0;
  302. d = scr->mmio + RBaseD;
  303. while((d[Flow]&2)&& x++ < 1000000)
  304. ;
  305. if(x >= 1000000) /* shouldn't happen */
  306. iprint("mem %8lux\n", d[Busy]);
  307. }
  308. static int
  309. t2r4hwscroll(VGAscr *scr, Rectangle r, Rectangle sr)
  310. {
  311. int ctl;
  312. Point dp, sp;
  313. ulong *d;
  314. int depth;
  315. if(r.min.y == sr.min.y){ /* a purely horizontal scroll */
  316. depth = scr->gscreen->depth;
  317. switch(depth){
  318. case 32:
  319. /*
  320. * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
  321. * 32-bit scrolls don't work perfectly on rectangles of width <= 24.
  322. * we bail on a bigger bound for padding.
  323. */
  324. if(Dx(r) < 32)
  325. return 0;
  326. break;
  327. case 16:
  328. /*
  329. * Using the SGI flat panels with the Ticket-to-Ride IV, horizontal
  330. * 16-bit scrolls don't work perfectly on rectangles of width <= 96.
  331. * we bail on a bigger bound for padding.
  332. */
  333. if(Dx(r) < 104)
  334. return 0;
  335. break;
  336. }
  337. }
  338. waitformem(scr);
  339. waitforfifo(scr);
  340. d = scr->mmio + RBaseD;
  341. ctl = 0;
  342. if(r.min.x <= sr.min.x){
  343. dp.x = r.min.x;
  344. sp.x = sr.min.x;
  345. }else{
  346. ctl |= 2;
  347. dp.x = r.max.x-1;
  348. sp.x = sr.max.x-1;
  349. }
  350. if(r.min.y < sr.min.y){
  351. dp.y = r.min.y;
  352. sp.y = sr.min.y;
  353. }else{
  354. ctl |= 1;
  355. dp.y = r.max.y-1;
  356. sp.y = sr.max.y-1;
  357. }
  358. d[CmdOpc] = 0x1; /* bitblt */
  359. d[CmdRop] = 0xC; /* copy source */
  360. d[CmdStyle] = 0;
  361. d[CmdPatrn] = 0;
  362. d[Fore] = 0;
  363. d[Back] = 0;
  364. /* writing XY1 executes cmd */
  365. d[XY3] = ctl;
  366. d[XY0] = (sp.x<<16)|sp.y;
  367. d[XY2] = (Dx(r)<<16)|Dy(r);
  368. d[XY4] = 0;
  369. d[XY1] = (dp.x<<16)|dp.y;
  370. waitforcmd(scr);
  371. return 1;
  372. }
  373. static int
  374. t2r4hwfill(VGAscr *scr, Rectangle r, ulong sval)
  375. {
  376. ulong *d;
  377. d = scr->mmio + RBaseD;
  378. waitformem(scr);
  379. waitforfifo(scr);
  380. d[CmdOpc] = 0x1; /* bitblt */
  381. d[CmdRop] = 0xC; /* copy source */
  382. d[CmdStyle] = 1; /* use source from Fore register */
  383. d[CmdPatrn] = 0; /* no stipple */
  384. d[Fore] = sval;
  385. d[Back] = sval;
  386. /* writing XY1 executes cmd */
  387. d[XY3] = 0;
  388. d[XY0] = (r.min.x<<16)|r.min.y;
  389. d[XY2] = (Dx(r)<<16)|Dy(r);
  390. d[XY4] = 0;
  391. d[XY1] = (r.min.x<<16)|r.min.y;
  392. waitforcmd(scr);
  393. return 1;
  394. }
  395. static void
  396. t2r4blank(VGAscr *scr, int blank)
  397. {
  398. uchar x;
  399. x = t2r4xi(scr, CursorSyncCtl);
  400. x &= ~0x0F;
  401. if(blank)
  402. x |= HsyncLo | VsyncLo;
  403. t2r4xo(scr, CursorSyncCtl, x);
  404. }
  405. static void
  406. t2r4drawinit(VGAscr *scr)
  407. {
  408. ulong pitch;
  409. int depth;
  410. int fmt;
  411. ulong *d;
  412. pitch = Dx(scr->gscreen->r);
  413. depth = scr->gscreen->depth;
  414. switch(scr->gscreen->chan){
  415. case RGB16:
  416. fmt = 3;
  417. break;
  418. case XRGB32:
  419. fmt = 2;
  420. break;
  421. case RGB15:
  422. fmt = 1;
  423. break;
  424. default:
  425. scr->fill = nil;
  426. scr->scroll = nil;
  427. return;
  428. }
  429. d = scr->mmio + RBaseD;
  430. d[BufCtl] = fmt<<24;
  431. d[DeSorg] = 0;
  432. d[DeDorg] = 0;
  433. d[DeSptch] = (pitch*depth)/8;
  434. d[DeDptch] = (pitch*depth)/8;
  435. d[CmdClp] = 0; /* 2 = inside rectangle */
  436. d[Mask] = ~0;
  437. d[DeKey] = 0;
  438. d[Clptl] = 0;
  439. d[Clpbr] = 0xFFF0FFF0;
  440. d[Alpha] = 0;
  441. d[ACtl] = 0;
  442. scr->fill = t2r4hwfill;
  443. scr->scroll = t2r4hwscroll;
  444. scr->blank = t2r4blank;
  445. hwblank = 1;
  446. }
  447. VGAdev vgat2r4dev = {
  448. "t2r4",
  449. t2r4enable,
  450. nil,
  451. nil,
  452. nil,
  453. t2r4drawinit,
  454. };
  455. VGAcur vgat2r4cur = {
  456. "t2r4hwgc",
  457. t2r4curenable,
  458. t2r4curdisable,
  459. t2r4curload,
  460. t2r4curmove,
  461. };