vgat2r4.c 9.1 KB

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