vgat2r4.c 10 KB

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