virge.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * S3 Trio/ViRGE/Savage4
  8. * Requires work.
  9. */
  10. /* on some cards, savage4mem[1] == 8, but i don't know how to tell. -rsc */
  11. static uchar savage4mem[] = { 2, 4, 8, 12, 16, 32, 0, 32};
  12. static void
  13. snarf(Vga* vga, Ctlr* ctlr)
  14. {
  15. int i, id;
  16. char *p;
  17. /*
  18. * The Trio/ViRGE variants have some extra sequencer registers
  19. * which need to be unlocked for access.
  20. */
  21. vgaxo(Seqx, 0x08, 0x06);
  22. s3generic.snarf(vga, ctlr);
  23. for(i = 0x08; i < 0x4F; i++)
  24. vga->sequencer[i] = vgaxi(Seqx, i);
  25. vga->crt[0x2D] = vgaxi(Crtx, 0x2D);
  26. vga->crt[0x2E] = vgaxi(Crtx, 0x2E);
  27. vga->crt[0x2F] = vgaxi(Crtx, 0x2F);
  28. for(i = 0x70; i < 0x99; i++)
  29. vga->crt[i] = vgaxi(Crtx, i);
  30. id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
  31. switch(id){
  32. default:
  33. trace("Unknown ViRGE/Trio64+ - 0x%4.4uX\n",
  34. (vga->crt[0x2D]<<8)|vga->crt[0x2E]);
  35. /*FALLTHROUGH*/
  36. case 0x8811: /* Trio64+ */
  37. vga->r[1] = 3;
  38. vga->m[1] = 127;
  39. vga->n[1] = 31;
  40. vga->f[1] = 135000000;
  41. trace("Trio64+\n");
  42. break;
  43. case 0x8812: /* Aurora64V+ */
  44. vga->r[1] = 3;
  45. vga->m[1] = 127;
  46. vga->n[1] = 63;
  47. vga->f[1] = 135000000;
  48. trace("Aurora64V+\n");
  49. break;
  50. case 0x8901: /* Trio64V2 */
  51. vga->r[1] = 4;
  52. vga->m[1] = 127;
  53. vga->n[1] = 31;
  54. vga->f[1] = 170000000;
  55. trace("Trio64V2\n");
  56. break;
  57. case 0x5631: /* ViRGE */
  58. vga->r[1] = 3;
  59. vga->m[1] = 127;
  60. vga->n[1] = 31;
  61. vga->f[1] = 135000000;
  62. vga->apz = 64*1024*1024;
  63. trace("ViRGE\n");
  64. break;
  65. case 0x8A01: /* ViRGE/[DG]X */
  66. vga->r[1] = 4;
  67. vga->m[1] = 127;
  68. vga->n[1] = 31;
  69. vga->f[1] = 170000000;
  70. trace("ViRGE/[DG]X\n");
  71. break;
  72. case 0x8A10: /* ViRGE/GX2 */
  73. vga->r[1] = 4;
  74. vga->m[1] = 127;
  75. vga->n[1] = 31;
  76. vga->f[1] = 170000000;
  77. vga->apz = 64*1024*1024;
  78. trace("ViRGE/GX2\n");
  79. /*
  80. * Memory encoding on the ViRGE/GX2 is different.
  81. */
  82. switch((vga->crt[0x36]>>6) & 0x03){
  83. case 0x01:
  84. vga->vmz = 4*1024*1024;
  85. break;
  86. case 0x03:
  87. vga->vmz = 2*1024*1024;
  88. break;
  89. }
  90. break;
  91. case 0x883D: /* ViRGE/VX */
  92. vga->r[1] = 4;
  93. vga->m[1] = 127;
  94. vga->n[1] = 31;
  95. vga->f[1] = 220000000;
  96. vga->apz = 64*1024*1024;
  97. trace("ViRGE/VX\n");
  98. /*
  99. * Memory encoding on the ViRGE/VX is different.
  100. */
  101. vga->vmz = (2*(((vga->crt[0x36]>>5) & 0x03)+1)) * 1*1024*1024;
  102. break;
  103. case 0x8C10: /* Savage MX/MV */
  104. case 0x8C12: /* Savage4/IX-MV */
  105. vga->r[1] = 4;
  106. vga->m[1] = 127;
  107. vga->n[1] = 127;
  108. vga->f[1] = 135000000; /* without clock-doubling */
  109. for(i = 0x50; i < 0x70; i++)
  110. vga->sequencer[i] = vgaxi(Seqx, i);
  111. vga->apz = 128*1024*1024;
  112. vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
  113. trace("Savage4/IX-MV\n");
  114. break;
  115. case 0x8C2E: /* SuperSavage/IXC16 */
  116. /*
  117. * This is all guessed, from the Savage4/IX,
  118. * inspection of the card (apz), and web pages
  119. * talking about the chip (f[1]). It seems to
  120. * work on the IBM Thinkpad T23.
  121. *
  122. * XXX only 1024x768 works, not 1400x1050.
  123. */
  124. vga->r[1] = 4;
  125. vga->m[1] = 127;
  126. vga->n[1] = 127;
  127. vga->f[1] = 135000000; /* 300000000 after doubling? */
  128. for(i = 0x50; i < 0x70; i++)
  129. vga->sequencer[i] = vgaxi(Seqx, i);
  130. vga->apz = 64*1024*1024;
  131. vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
  132. trace("SuperSavage/IXC16\n");
  133. break;
  134. case 0x8A22: /* Savage4 */
  135. case 0x8A25: /* ProSavage PN133 */
  136. case 0x8A26: /* ProSavage KN133 */
  137. vga->r[1] = 4;
  138. vga->m[1] = 511;
  139. vga->n[1] = 127;
  140. vga->f[1] = 300000000;
  141. vga->apz = 128*1024*1024;
  142. vga->vmz = savage4mem[vga->crt[0x36]>>5] * 1024 * 1024;
  143. trace("Savage4\n");
  144. break;
  145. }
  146. /*
  147. * Work out the part speed-grade from name. Name can have,
  148. * e.g. '-135' on the end for 135MHz part.
  149. */
  150. if(p = strrchr(ctlr->name, '-'))
  151. vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
  152. ctlr->flag |= Fsnarf;
  153. }
  154. static void
  155. options(Vga *vga, Ctlr* ctlr)
  156. {
  157. int id;
  158. id = (vga->crt[0x2D]<<8)|(vga->crt[0x2E]);
  159. switch(id){
  160. case 0x8C2E: /* SuperSavage/IXC16 */
  161. case 0x8C10: /* Savage MX/MV */
  162. case 0x8C12: /* Savage4/IX-MV */
  163. case 0x8A22: /* Savage4 */
  164. case 0x8A25: /* ProSavage PN133 */
  165. case 0x8A26: /* ProSavage KN133 */
  166. /*
  167. * Round up so stride is multiple of 16.
  168. */
  169. if(vga->virtx%16)
  170. vga->virtx = (vga->virtx+15)&~15;
  171. break;
  172. }
  173. ctlr->flag |= Hlinear|Hpclk2x8|Henhanced|Foptions;
  174. }
  175. static void
  176. init(Vga* vga, Ctlr* ctlr)
  177. {
  178. char *p, *val;
  179. ulong pclk, x;
  180. int id, noclockset, width;
  181. s3generic.init(vga, ctlr);
  182. /*
  183. * Work out the part speed-grade from name. Name can have,
  184. * e.g. '-135' on the end for 135MHz part.
  185. */
  186. noclockset = 0;
  187. if(p = strrchr(ctlr->name, '-'))
  188. vga->f[1] = strtoul(p+1, 0, 0) * 1000000;
  189. pclk = vga->f[1];
  190. if(vga->mode->z > 8)
  191. width = vga->virtx*(vga->mode->z/8);
  192. else
  193. width = vga->virtx*(8/vga->mode->z);
  194. id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
  195. switch(id){
  196. case 0x8811: /* Trio64+ */
  197. /*
  198. * Part comes in -135MHz speed grade. In 8-bit mode
  199. * the maximum DCLK is 80MHz. In 2x8-bit mode the maximum
  200. * DCLK is 135MHz using the internal clock doubler.
  201. */
  202. if((ctlr->flag & Hpclk2x8) && vga->mode->z == 8){
  203. if(vga->f[0] > 80000000)
  204. ctlr->flag |= Upclk2x8;
  205. }
  206. else
  207. pclk = 80000000;
  208. vga->crt[0x67] &= ~0xF2;
  209. if(ctlr->flag & Upclk2x8){
  210. vga->sequencer[0x15] |= 0x10;
  211. vga->sequencer[0x18] |= 0x80;
  212. /*
  213. * There's a little strip of the border
  214. * appears on the left in resolutions
  215. * 1280 and above if the 0x02 bit isn't
  216. * set (when it appears on the right...).
  217. */
  218. vga->crt[0x67] |= 0x10;
  219. }
  220. /*
  221. * VLB address latch delay.
  222. */
  223. if((vga->crt[0x36] & 0x03) == 0x01)
  224. vga->crt[0x58] &= ~0x08;
  225. /*
  226. * Display memory access control.
  227. */
  228. vga->crt[0x60] = 0xFF;
  229. if(vga->mode->z > 8)
  230. error("trio64: depth %d not supported\n", vga->mode->z);
  231. break;
  232. case 0x8901: /* Trio64V2 */
  233. vga->crt[0x90] = 0;
  234. vga->crt[0x91] = 0;
  235. break;
  236. case 0x8A10: /* ViRGE/GX2 */
  237. vga->crt[0x90] = 0;
  238. vga->crt[0x31] |= 0x08;
  239. vga->crt[0x13] = (width>>3) & 0xFF;
  240. vga->crt[0x51] &= ~0x30;
  241. vga->crt[0x51] |= (width>>7) & 0x30;
  242. /*
  243. * Increase primary FIFO threshold
  244. * to reduce flicker and tearing.
  245. */
  246. vga->crt[0x85] = 0x0F;
  247. /*FALLTHROUGH*/
  248. case 0x5631: /* ViRGE */
  249. case 0x8A01: /* ViRGE/[DG]X */
  250. case 0x883D: /* ViRGE/VX */
  251. vga->crt[0x60] &= 0x0F;
  252. /*FALLTHROUGH*/
  253. case 0x8812: /* Aurora64V+ */
  254. if(id == 0x8812) /* Aurora64V+ */
  255. noclockset = 1;
  256. vga->crt[0x65] = 0;
  257. vga->crt[0x66] = 0x89;
  258. vga->crt[0x67] = 0;
  259. if(id == 0x883D){ /* ViRGE/VX */
  260. /*
  261. * Put the VRAM in 1-cycle EDO mode.
  262. * If it is not put in this mode, hardware acceleration
  263. * will leave little turds on the screen when hwfill is used.
  264. */
  265. vga->crt[0x36] &= ~0x0C;
  266. if(vga->mode->x > 800 && vga->mode->z == 8)
  267. vga->crt[0x67] = 0x10;
  268. else
  269. vga->crt[0x67] = 0;
  270. /*
  271. * Adjustments to the generic settings:
  272. * heuristic fiddling.
  273. *
  274. * We used to set crt[0x66] to 0x89, but setting it
  275. * to 0x90 seems to allow us (and more importantly the card)
  276. * to access more than 2MB of memory.
  277. */
  278. vga->crt[0x66] = 0x90;
  279. vga->crt[0x58] &= ~0x88;
  280. vga->crt[0x58] |= 0x40;
  281. if(vga->mode->x > 640 && vga->mode->z >= 8)
  282. vga->crt[0x63] |= 0x01;
  283. else
  284. vga->crt[0x63] &= ~0x01;
  285. }
  286. /*
  287. * The high nibble is the mode; or'ing in 0x02 turns
  288. * on support for gamma correction via the DACs, but I
  289. * haven't figured out how to turn on the 8-bit DACs,
  290. * so gamma correction stays off.
  291. */
  292. switch(vga->mode->z){
  293. case 1:
  294. case 2:
  295. case 4:
  296. case 8:
  297. default:
  298. vga->crt[0x67] |= 0x00;
  299. break;
  300. case 15:
  301. vga->crt[0x67] |= 0x30;
  302. break;
  303. case 16:
  304. vga->crt[0x67] |= 0x50;
  305. break;
  306. case 24:
  307. if(id == 0x8A10) /* GX2 has to be different */
  308. vga->crt[0x67] |= 0x70;
  309. else
  310. vga->crt[0x67] |= 0xD0;
  311. break;
  312. case 32:
  313. /*
  314. * The ViRGE and ViRGE/VX manuals make no mention of
  315. * 32-bit mode (which the GX/2 calls 24-bit unpacked mode).
  316. */
  317. if(id != 0x8A10)
  318. error("32-bit mode only supported on the GX/2");
  319. vga->crt[0x67] |= 0xD0;
  320. break;
  321. }
  322. /*
  323. * Set new MMIO method
  324. */
  325. vga->crt[0x53] &= ~0x18;
  326. vga->crt[0x53] |= 0x08;
  327. break;
  328. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  329. case 0x8C10: /* Savage MX/MV */
  330. case 0x8C12: /* Savage4/IX-MV */
  331. /*
  332. * Experience shows the -1 (according to the manual)
  333. * is incorrect.
  334. */
  335. x = width/8 /*-1*/;
  336. vga->crt[0x91] = x;
  337. vga->crt[0x90] &= ~0x07;
  338. vga->crt[0x90] |= (x>>8) & 0x07;
  339. /*FALLTHROUGH*/
  340. case 0x8A22: /* Savage4 */
  341. case 0x8A25: /* ProSavage PN133 */
  342. case 0x8A26: /* ProSavage KN133 */
  343. /*
  344. * The Savage 4 is frustratingly similar to the
  345. * ViRGE/GX2, but has enough slight differences
  346. * to warrant special treatment. Blog.
  347. */
  348. vga->crt[0x66] = 0x89;
  349. vga->crt[0x67] = 0;
  350. vga->crt[0x85] = 0x02;
  351. vga->crt[0x31] |= 0x08;
  352. vga->crt[0x13] = (width>>3) & 0xFF;
  353. vga->crt[0x51] &= ~0x30;
  354. vga->crt[0x51] |= (width>>7) & 0x30;
  355. /* pull screen width from GBD for graphics engine. */
  356. vga->crt[0x50] = 0xC1;
  357. /*
  358. * The high nibble is the mode; or'ing in 0x02 turns
  359. * on support for gamma correction via the DACs, but I
  360. * haven't figured out how to turn on the 8-bit DACs,
  361. * so gamma correction stays off.
  362. */
  363. switch(vga->mode->z){
  364. default:
  365. error("%d-bit mode not supported on savage 4\n", vga->mode->z);
  366. case 8:
  367. vga->crt[0x67] |= 0x00;
  368. vga->crt[0x50] |= 0<<4;
  369. break;
  370. case 15:
  371. vga->crt[0x67] |= 0x20;
  372. vga->crt[0x50] |= 1<<4;
  373. break;
  374. case 16:
  375. vga->crt[0x67] |= 0x40;
  376. vga->crt[0x50] |= 1<<4;
  377. /*
  378. * Manual says this should be accompanied by setting
  379. * the clock-doubled modes but this seems to be the
  380. * right answer.
  381. * Should check if using doubled modes tidies any of
  382. * this up.
  383. */
  384. if(id == 0x8C12 || id == 0x8C2E || id == 0x8C10)
  385. vga->crt[0x67] |= 0x10;
  386. break;
  387. case 32:
  388. vga->crt[0x67] |= 0xD0;
  389. vga->crt[0x50] |= 3<<4;
  390. break;
  391. }
  392. break;
  393. }
  394. /*
  395. * Clock bits. If the desired video clock is
  396. * one of the two standard VGA clocks it can just be
  397. * set using bits <3:2> of vga->misc, otherwise we
  398. * need to programme the DCLK PLL.
  399. */
  400. if(val = dbattr(vga->mode->attr, "noclockset")){
  401. if((noclockset = strtol(val, &p, 0)) == 0 && p == val)
  402. error("%s: invalid 'noclockset' attr\n", ctlr->name);
  403. }
  404. if(vga->f[0] == 0)
  405. vga->f[0] = vga->mode->frequency;
  406. vga->misc &= ~0x0C;
  407. if(vga->f[0] == VgaFreq0){
  408. /* nothing to do */;
  409. }
  410. else if(vga->f[0] == VgaFreq1)
  411. vga->misc |= 0x04;
  412. else if(noclockset){
  413. /*
  414. * Don't touch the clock on the Aurora64V+
  415. * and optionally on some others.
  416. */
  417. vga->misc |= 0x0C;
  418. }
  419. else{
  420. if(vga->f[0] > pclk)
  421. error("%s: invalid pclk - %lud\n",
  422. ctlr->name, vga->f[0]);
  423. trio64clock(vga, ctlr);
  424. switch(id){
  425. case 0x8A10: /* ViRGE/GX2 */
  426. vga->sequencer[0x12] = (vga->r[0]<<6)|vga->n[0];
  427. if(vga->r[0] & 0x04)
  428. vga->sequencer[0x29] |= 0x01;
  429. else
  430. vga->sequencer[0x29] &= ~0x01;
  431. break;
  432. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  433. case 0x8C10: /* Savage MX/MV */
  434. case 0x8C12: /* Savage4/IX-MV */
  435. case 0x8A22: /* Savage4 */
  436. case 0x8A25: /* ProSavage PN133 */
  437. case 0x8A26: /* ProSavage KN133 */
  438. vga->sequencer[0x12] = (vga->r[0]<<6)|(vga->n[0] & 0x3F);
  439. vga->sequencer[0x39] &= ~0x01;
  440. vga->sequencer[0x29] &= ~0x1C;
  441. if(vga->r[0] & 0x04)
  442. vga->sequencer[0x29] |= (1<<2);
  443. if(vga->m[0] & 0x100)
  444. vga->sequencer[0x29] |= (1<<3);
  445. if(vga->n[0] & 0x40)
  446. vga->sequencer[0x29] |= (1<<4);
  447. break;
  448. default:
  449. vga->sequencer[0x12] = (vga->r[0]<<5)|vga->n[0];
  450. break;
  451. }
  452. vga->sequencer[0x13] = vga->m[0];
  453. vga->misc |= 0x0C;
  454. }
  455. /*
  456. * Internal clock generator.
  457. */
  458. vga->sequencer[0x15] &= ~0x31;
  459. vga->sequencer[0x15] |= 0x02;
  460. vga->sequencer[0x18] &= ~0x80;
  461. /*
  462. * Start display FIFO fetch.
  463. */
  464. x = (vga->crt[0]+vga->crt[4]+1)/2;
  465. vga->crt[0x3B] = x;
  466. if(x & 0x100)
  467. vga->crt[0x5D] |= 0x40;
  468. /*
  469. * Display memory access control.
  470. * Calculation of the M-parameter (Crt54) is
  471. * memory-system and dot-clock dependent, the
  472. * values below are guesses from dumping
  473. * registers.
  474. * The Savage4 does not document 0x54,
  475. * but we leave this anyway.
  476. */
  477. if(vga->mode->x <= 800)
  478. vga->crt[0x54] = 0xE8;
  479. else if(vga->mode->x <= 1024 && id != 0x8C12 && id != 0x8C2E)
  480. vga->crt[0x54] = 0xA8;
  481. else
  482. vga->crt[0x54] = 0x00/*0x48*/;
  483. ctlr->flag |= Finit;
  484. }
  485. static void
  486. load(Vga* vga, Ctlr* ctlr)
  487. {
  488. int id;
  489. ushort advfunc;
  490. s3generic.load(vga, ctlr);
  491. /*
  492. * Load the PLL registers if necessary.
  493. * Not sure if the variable-delay method of setting the
  494. * PLL will work without a write here to vga->misc,
  495. * so use the immediate-load method by toggling bit 5
  496. * of Seq15 if necessary.
  497. */
  498. vgaxo(Seqx, 0x12, vga->sequencer[0x12]);
  499. vgaxo(Seqx, 0x13, vga->sequencer[0x13]);
  500. id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
  501. switch(id){
  502. case 0x883D: /* ViRGE/VX*/
  503. vgaxo(Crtx, 0x36, vga->crt[0x36]);
  504. break;
  505. case 0x8A10: /* ViRGE/GX2 */
  506. vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
  507. break;
  508. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  509. case 0x8C12: /* Savage4/IX-MV */
  510. vgaxo(Crtx, 0x90, vga->crt[0x90]);
  511. vgaxo(Crtx, 0x91, vga->crt[0x91]);
  512. /*FALLTHROUGH*/
  513. case 0x8A22: /* Savage4 */
  514. case 0x8A25: /* ProSavage PN133 */
  515. case 0x8A26: /* ProSavage KN133 */
  516. vgaxo(Seqx, 0x29, vga->sequencer[0x29]);
  517. vgaxo(Seqx, 0x39, vga->sequencer[0x39]);
  518. break;
  519. }
  520. if((vga->misc & 0x0C) == 0x0C)
  521. vgaxo(Seqx, 0x15, vga->sequencer[0x15]|0x20);
  522. vgaxo(Seqx, 0x15, vga->sequencer[0x15]);
  523. vgaxo(Seqx, 0x18, vga->sequencer[0x18]);
  524. vgaxo(Crtx, 0x60, vga->crt[0x60]);
  525. vgaxo(Crtx, 0x63, vga->crt[0x63]);
  526. vgaxo(Crtx, 0x65, vga->crt[0x65]);
  527. vgaxo(Crtx, 0x66, vga->crt[0x66]);
  528. vgaxo(Crtx, 0x67, vga->crt[0x67]);
  529. switch(id){
  530. case 0x8811: /* Trio64+ */
  531. advfunc = 0x0000;
  532. if(ctlr->flag & Uenhanced)
  533. advfunc = 0x0001;
  534. outportw(0x4AE8, advfunc);
  535. break;
  536. case 0x8901: /* Trio64V2 */
  537. vgaxo(Crtx, 0x90, vga->crt[0x90]);
  538. vgaxo(Crtx, 0x91, vga->crt[0x91]);
  539. break;
  540. case 0x8A10: /* ViRGE/GX2 */
  541. vgaxo(Crtx, 0x90, vga->crt[0x90]);
  542. vgaxo(Crtx, 0x31, vga->crt[0x31]);
  543. vgaxo(Crtx, 0x13, vga->crt[0x13]);
  544. vgaxo(Crtx, 0x51, vga->crt[0x51]);
  545. vgaxo(Crtx, 0x85, vga->crt[0x85]);
  546. break;
  547. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  548. case 0x8C12: /* Savage4/IX-MV */
  549. case 0x8A22: /* Savage4 */
  550. case 0x8A25: /* ProSavage PN133 */
  551. case 0x8A26: /* ProSavage KN133 */
  552. vgaxo(Crtx, 0x31, vga->crt[0x31]);
  553. vgaxo(Crtx, 0x13, vga->crt[0x13]);
  554. vgaxo(Crtx, 0x51, vga->crt[0x51]);
  555. vgaxo(Crtx, 0x85, vga->crt[0x85]);
  556. vgaxo(Crtx, 0x50, vga->crt[0x50]);
  557. break;
  558. }
  559. }
  560. static void
  561. dump(Vga* vga, Ctlr* ctlr)
  562. {
  563. int i, id;
  564. ulong dclk, m, n, r;
  565. s3generic.dump(vga, ctlr);
  566. printitem(ctlr->name, "Crt70");
  567. for(i = 0x70; i < 0x99; i++)
  568. printreg(vga->crt[i]);
  569. printitem(ctlr->name, "Seq08");
  570. for(i = 0x08; i < 0x10; i++)
  571. printreg(vga->sequencer[i]);
  572. printitem(ctlr->name, "Seq10");
  573. for(i = 0x10; i < 0x50; i++)
  574. printreg(vga->sequencer[i]);
  575. id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
  576. switch(id){
  577. default:
  578. break;
  579. case 0x8812: /* Aurora64V+ */
  580. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  581. case 0x8C12: /* Savage4/IX-MV */
  582. printitem(ctlr->name, "Seq50");
  583. for(i = 0x50; i < 0x70; i++)
  584. printreg(vga->sequencer[i]);
  585. break;
  586. }
  587. printitem(ctlr->name, "Crt2D");
  588. printreg(vga->crt[0x2D]);
  589. printreg(vga->crt[0x2E]);
  590. printreg(vga->crt[0x2F]);
  591. m = vga->sequencer[0x13] & vga->m[1];
  592. n = vga->sequencer[0x12] & vga->n[1];
  593. r = (vga->sequencer[0x12]>>5) & 0x03;
  594. switch(id){
  595. case 0x8812: /* Aurora64V+ */
  596. r = (vga->sequencer[0x12]>>6) & 0x03;
  597. break;
  598. case 0x8A01: /* ViRGE/[DG]X */
  599. r = (vga->sequencer[0x12]>>5) & 0x07;
  600. break;
  601. case 0x8A10: /* ViRGE/GX2 */
  602. r = (vga->sequencer[0x12]>>6) & 0x03;
  603. r |= (vga->sequencer[0x29] & 0x01)<<2;
  604. break;
  605. case 0x8C2E: /* SuperSavage/IXC16 (let's try this -rsc) */
  606. case 0x8C12: /* Savage4/IX-MV */
  607. case 0x8A22: /* Savage4 */
  608. case 0x8A25: /* ProSavage PN133 */
  609. case 0x8A26: /* ProSavage KN133 */
  610. m = vga->sequencer[0x13] & 0xFF;
  611. if(vga->sequencer[0x29] & (1<<3))
  612. m |= 0x100;
  613. if(vga->sequencer[0x29] & (1<<4))
  614. n |= 0x40;
  615. r = (vga->sequencer[0x12]>>6) & 0x03;
  616. r |= (vga->sequencer[0x29] & (1<<2));
  617. break;
  618. }
  619. dclk = (m+2)*RefFreq;
  620. dclk /= (n+2)*(1<<r);
  621. printitem(ctlr->name, "dclk m n r");
  622. Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n", dclk, m, n, r);
  623. m = vga->sequencer[0x11] & 0x7F;
  624. n = vga->sequencer[0x10] & 0x1F;
  625. r = (vga->sequencer[0x10]>>5) & 0x03; /* might be GX/2 specific */
  626. dclk = (m+2)*RefFreq;
  627. dclk /= (n+2)*(1<<r);
  628. printitem(ctlr->name, "mclk m n r");
  629. Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n", dclk, m, n, r);
  630. }
  631. Ctlr virge = {
  632. "virge", /* name */
  633. snarf, /* snarf */
  634. options, /* options */
  635. init, /* init */
  636. load, /* load */
  637. dump, /* dump */
  638. };