virge.c 18 KB

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