et4000.c 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Tseng Labs Inc. ET4000 Video Controller.
  8. */
  9. enum {
  10. Crtcbx = 0x217A, /* Secondary CRT controller */
  11. Sprite = 0xE0,
  12. NSprite = 0x10,
  13. Ima = 0xF0,
  14. NIma = 0x08,
  15. };
  16. static void
  17. setkey(void)
  18. {
  19. outportb(0x3BF, 0x03);
  20. outportb(0x3D8, 0xA0);
  21. outportb(0x3CD, 0x00);
  22. }
  23. static void
  24. snarf(Vga* vga, Ctlr* ctlr)
  25. {
  26. int i;
  27. setkey();
  28. vga->sequencer[0x06] = vgaxi(Seqx, 0x06);
  29. vga->sequencer[0x07] = vgaxi(Seqx, 0x07);
  30. for(i = 0x30; i < 0x38; i++)
  31. vga->crt[i] = vgaxi(Crtx, i);
  32. vga->crt[0x3F] = vgaxi(Crtx, 0x3F);
  33. vga->attribute[0x16] = vgaxi(Attrx, 0x16);
  34. vga->attribute[0x17] = vgaxi(Attrx, 0x17);
  35. /*
  36. * Memory size.
  37. */
  38. switch(vga->crt[0x37] & 0x03){
  39. case 1:
  40. vga->vmz = 256*1024;
  41. break;
  42. case 2:
  43. vga->vmz = 512*1024;
  44. break;
  45. case 3:
  46. vga->vmz = 1024*1024;
  47. break;
  48. }
  49. if(strncmp(ctlr->name, "et4000-w32", 10) == 0){
  50. if(vga->crt[0x32] & 0x80)
  51. vga->vmz *= 2;
  52. }
  53. else if(vga->crt[0x37] & 0x80)
  54. vga->vmz *= 2;
  55. ctlr->flag |= Fsnarf;
  56. }
  57. static void
  58. options(Vga* vga, Ctlr* ctlr)
  59. {
  60. /*
  61. * The ET4000 does not need to have the vertical
  62. * timing values divided by 2 for interlace mode.
  63. */
  64. if(vga->mode->interlace == 'v')
  65. vga->mode->interlace = 'V';
  66. if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
  67. ctlr->flag |= Hpclk2x8;
  68. ctlr->flag |= Hclkdiv|Foptions;
  69. }
  70. static void
  71. init(Vga* vga, Ctlr* ctlr)
  72. {
  73. Mode *mode;
  74. ulong x;
  75. if(vga->mode->z > 8)
  76. error("depth %d not supported\n", vga->mode->z);
  77. if(ctlr->flag & Upclk2x8){
  78. mode = vga->mode;
  79. vga->crt[0x00] = ((mode->ht/2)>>3)-5;
  80. vga->crt[0x01] = ((mode->x/2)>>3)-1;
  81. vga->crt[0x02] = ((mode->shb/2)>>3)-1;
  82. x = (mode->ehb/2)>>3;
  83. vga->crt[0x03] = 0x80|(x & 0x1F);
  84. vga->crt[0x04] = (mode->shs/2)>>3;
  85. vga->crt[0x05] = ((mode->ehs/2)>>3) & 0x1F;
  86. if(x & 0x20)
  87. vga->crt[0x05] |= 0x80;
  88. }
  89. /*
  90. * Itth a mythtawee.
  91. */
  92. if(vga->crt[0x14] & 0x20)
  93. vga->crt[0x17] |= 0x08;
  94. vga->crt[0x17] &= ~0x20;
  95. vga->crt[0x30] = 0x00;
  96. vga->crt[0x33] = 0x00;
  97. /*
  98. * Overflow High.
  99. */
  100. vga->crt[0x35] = 0x00;
  101. if(vga->crt[0x15] & 0x400)
  102. vga->crt[0x35] |= 0x01;
  103. if(vga->crt[0x06] & 0x400)
  104. vga->crt[0x35] |= 0x02;
  105. if(vga->crt[0x12] & 0x400)
  106. vga->crt[0x35] |= 0x04;
  107. if(vga->crt[0x10] & 0x400)
  108. vga->crt[0x35] |= 0x08;
  109. if(vga->crt[0x18] & 0x400)
  110. vga->crt[0x35] |= 0x10;
  111. if(vga->mode->interlace == 'V')
  112. vga->crt[0x35] |= 0x80;
  113. /*
  114. * Horizontal Overflow.
  115. */
  116. vga->crt[0x3F] = 0x00;
  117. if(vga->crt[0x00] & 0x100)
  118. vga->crt[0x3F] |= 0x01;
  119. if(vga->crt[0x02] & 0x100)
  120. vga->crt[0x3F] |= 0x04;
  121. if(vga->crt[0x04] & 0x100)
  122. vga->crt[0x3F] |= 0x10;
  123. if(vga->crt[0x13] & 0x100)
  124. vga->crt[0x3F] |= 0x80;
  125. /*
  126. * Turn off MMU buffers, linear map
  127. * and memory-mapped registers.
  128. */
  129. vga->crt[0x36] &= ~0x38;
  130. if(strncmp(ctlr->name, "et4000-w32", 10) == 0)
  131. vga->crt[0x37] |= 0x80;
  132. vga->sequencer[0x06] = 0x00;
  133. /*
  134. * Clock select.
  135. */
  136. if(vga->f[0] > 86000000)
  137. error("%s: invalid pclk - %ld\n", ctlr->name, vga->f[0]);
  138. vga->misc &= ~0x0C;
  139. vga->misc |= (vga->i[0] & 0x03)<<2;
  140. if(vga->i[0] & 0x04)
  141. vga->crt[0x34] |= 0x02;
  142. else
  143. vga->crt[0x34] &= ~0x02;
  144. vga->crt[0x31] &= ~0xC0;
  145. vga->crt[0x31] |= (vga->i[0] & 0x18)<<3;
  146. vga->sequencer[0x07] &= ~0x41;
  147. if(vga->d[0] == 4)
  148. vga->sequencer[0x07] |= 0x01;
  149. else if(vga->d[0] == 2)
  150. vga->sequencer[0x07] |= 0x40;
  151. vga->attribute[0x10] &= ~0x40;
  152. vga->attribute[0x11] = Pblack;
  153. vga->attribute[0x16] = 0x80;
  154. if(ctlr->flag & Upclk2x8)
  155. vga->attribute[0x16] |= 0x20;
  156. ctlr->flag |= Finit;
  157. }
  158. static void
  159. load(Vga* vga, Ctlr* ctlr)
  160. {
  161. vgaxo(Crtx, 0x30, vga->crt[0x30]);
  162. vgaxo(Crtx, 0x31, vga->crt[0x31]);
  163. vgaxo(Crtx, 0x33, vga->crt[0x33]);
  164. vgaxo(Crtx, 0x34, vga->crt[0x34]);
  165. vgaxo(Crtx, 0x35, vga->crt[0x35]);
  166. vgaxo(Crtx, 0x36, vga->crt[0x36]);
  167. vgaxo(Crtx, 0x37, vga->crt[0x37]);
  168. vgaxo(Crtx, 0x3F, vga->crt[0x3F]);
  169. vgaxo(Seqx, 0x06, vga->sequencer[0x06]);
  170. vgaxo(Seqx, 0x07, vga->sequencer[0x07]);
  171. vgaxo(Attrx, 0x16, vga->attribute[0x16]);
  172. ctlr->flag |= Fload;
  173. }
  174. static void
  175. dump(Vga* vga, Ctlr* ctlr)
  176. {
  177. int i;
  178. char *name;
  179. ushort shb, vrs, x;
  180. name = ctlr->name;
  181. printitem(name, "Seq06");
  182. printreg(vga->sequencer[0x06]);
  183. printreg(vga->sequencer[0x07]);
  184. printitem(name, "Crt30");
  185. for(i = 0x30; i < 0x38; i++)
  186. printreg(vga->crt[i]);
  187. printitem(name, "Crt3F");
  188. printreg(vga->crt[0x3F]);
  189. printitem(name, "Attr16");
  190. printreg(vga->attribute[0x16]);
  191. printreg(vga->attribute[0x17]);
  192. if(strncmp(name, "et4000-w32", 10) == 0){
  193. printitem(name, "SpriteE0");
  194. for(i = Sprite; i < Sprite+NSprite; i++){
  195. outportb(Crtcbx, i);
  196. printreg(inportb(Crtcbx+1));
  197. }
  198. printitem(name, "ImaF0");
  199. for(i = Ima; i < Ima+NIma; i++){
  200. outportb(Crtcbx, i);
  201. printreg(inportb(Crtcbx+1));
  202. }
  203. }
  204. /*
  205. * Try to disassemble the snarfed values into
  206. * understandable numbers.
  207. * Only do this if we weren't called after Finit.
  208. */
  209. if(ctlr->flag & Finit)
  210. return;
  211. x = (vga->crt[0x01]+1)<<3;
  212. printitem(name, "hde");
  213. printreg(x);
  214. Bprint(&stdout, "%6ud", x);
  215. shb = ((((vga->crt[0x3F] & 0x04)<<6)|vga->crt[0x02])+1)<<3;
  216. printitem(name, "shb");
  217. printreg(shb);
  218. Bprint(&stdout, "%6ud", shb);
  219. x = (((vga->crt[0x05] & 0x80)>>2)|(vga->crt[0x03] & 0x1F))<<3;
  220. printitem(name, "ehb");
  221. printreg(x);
  222. for(i = 0; x < shb; i++)
  223. x |= 0x200<<i;
  224. Bprint(&stdout, "%6ud", x);
  225. x = ((((vga->crt[0x3F] & 0x01)<<8)|vga->crt[0x00])+5)<<3;
  226. printitem(name, "ht");
  227. printreg(x);
  228. Bprint(&stdout, "%6ud", x);
  229. x = vga->crt[0x12];
  230. if(vga->crt[0x07] & 0x02)
  231. x |= 0x100;
  232. if(vga->crt[0x07] & 0x40)
  233. x |= 0x200;
  234. if(vga->crt[0x35] & 0x04)
  235. x |= 0x400;
  236. x += 1;
  237. printitem(name, "vde");
  238. printreg(x);
  239. Bprint(&stdout, "%6ud", x);
  240. vrs = vga->crt[0x10];
  241. if(vga->crt[0x07] & 0x04)
  242. vrs |= 0x100;
  243. if(vga->crt[0x07] & 0x80)
  244. vrs |= 0x200;
  245. if(vga->crt[0x35] & 0x08)
  246. vrs |= 0x400;
  247. printitem(name, "vrs");
  248. printreg(vrs);
  249. Bprint(&stdout, "%6ud", vrs);
  250. x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
  251. printitem(name, "vre");
  252. printreg(x);
  253. Bprint(&stdout, "%6ud", x);
  254. x = vga->crt[0x06];
  255. if(vga->crt[0x07] & 0x01)
  256. x |= 0x100;
  257. if(vga->crt[0x07] & 0x20)
  258. x |= 0x200;
  259. if(vga->crt[0x35] & 0x02)
  260. x |= 0x400;
  261. x += 2;
  262. printitem(name, "vt");
  263. printreg(x);
  264. Bprint(&stdout, "%6ud", x);
  265. printitem(name, "d i");
  266. if(vga->sequencer[0x07] & 0x01)
  267. x = 4;
  268. else if(vga->sequencer[0x07] & 0x40)
  269. x = 2;
  270. else
  271. x = 0;
  272. Bprint(&stdout, "%9ud", x);
  273. x = (vga->misc & 0x0C)>>2;
  274. if(vga->crt[0x34] & 0x02)
  275. x |= 0x04;
  276. x |= (vga->crt[0x31] & 0xC0)>>3;
  277. Bprint(&stdout, "%8ud\n", x);
  278. }
  279. Ctlr et4000 = {
  280. "et4000", /* name */
  281. snarf, /* snarf */
  282. options, /* options */
  283. init, /* init */
  284. load, /* load */
  285. dump, /* dump */
  286. };