s3generic.c 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Generic S3 GUI Accelerator.
  8. */
  9. static void
  10. snarf(Vga* vga, Ctlr* ctlr)
  11. {
  12. int i;
  13. trace("%s->snarf->s3generic\n", ctlr->name);
  14. /*
  15. * Unlock extended registers.
  16. * 0xA5 ensures Crt36 and Crt37 are also unlocked
  17. * (0xA0 unlocks everything else).
  18. */
  19. vgaxo(Crtx, 0x38, 0x48);
  20. vgaxo(Crtx, 0x39, 0xA5);
  21. /*
  22. * Not all registers exist on all chips.
  23. * Crt3[EF] don't exist on any.
  24. */
  25. for(i = 0x30; i < 0x70; i++)
  26. vga->crt[i] = vgaxi(Crtx, i);
  27. /*
  28. * Memory size.
  29. */
  30. switch((vga->crt[0x36]>>5) & 0x07){
  31. case 0x00:
  32. vga->vmz = 4*1024*1024;
  33. break;
  34. case 0x02:
  35. vga->vmz = 3*1024*1024;
  36. break;
  37. case 0x04:
  38. vga->vmz = 2*1024*1024;
  39. break;
  40. case 0x06:
  41. vga->vmz = 1*1024*1024;
  42. break;
  43. case 0x07:
  44. vga->vmz = 512*1024;
  45. break;
  46. }
  47. ctlr->flag |= Fsnarf;
  48. }
  49. static void
  50. init(Vga* vga, Ctlr* ctlr)
  51. {
  52. Mode *mode;
  53. ulong x;
  54. trace("%s->init->s3generic\n", ctlr->name);
  55. mode = vga->mode;
  56. /*
  57. * Is enhanced mode is necessary?
  58. */
  59. if((ctlr->flag & (Uenhanced|Henhanced)) == Henhanced){
  60. if(mode->z >= 8)
  61. resyncinit(vga, ctlr, Uenhanced, 0);
  62. else
  63. resyncinit(vga, ctlr, 0, Uenhanced|Henhanced);
  64. }
  65. if((ctlr->flag & Uenhanced) == 0 && mode->x > 1024)
  66. error("%s: no support for 1-bit mode > 1024x768x1\n", ctlr->name);
  67. vga->crt[0x31] = 0x85;
  68. vga->crt[0x6A] &= 0xC0;
  69. vga->crt[0x32] &= ~0x40;
  70. vga->crt[0x31] |= 0x08;
  71. vga->crt[0x32] |= 0x40;
  72. vga->crt[0x33] |= 0x20;
  73. if(mode->z >= 8)
  74. vga->crt[0x3A] |= 0x10;
  75. else
  76. vga->crt[0x3A] &= ~0x10;
  77. vga->crt[0x34] = 0x10;
  78. vga->crt[0x35] = 0x00;
  79. if(mode->interlace){
  80. vga->crt[0x3C] = vga->crt[0]/2;
  81. vga->crt[0x42] |= 0x20;
  82. }
  83. else{
  84. vga->crt[0x3C] = 0x00;
  85. vga->crt[0x42] &= ~0x20;
  86. }
  87. vga->crt[0x40] = (vga->crt[0x40] & 0xF2);
  88. vga->crt[0x43] = 0x00;
  89. vga->crt[0x45] = 0x00;
  90. vga->crt[0x50] &= 0x3E;
  91. if(mode->x <= 640)
  92. x = 0x40;
  93. else if(mode->x <= 800)
  94. x = 0x80;
  95. else if(mode->x <= 1024)
  96. x = 0x00;
  97. else if(mode->x <= 1152)
  98. x = 0x01;
  99. else if(mode->x <= 1280)
  100. x = 0xC0;
  101. else
  102. x = 0x81;
  103. vga->crt[0x50] |= x;
  104. vga->crt[0x51] = (vga->crt[0x51] & 0xC3)|((vga->crt[0x13]>>4) & 0x30);
  105. vga->crt[0x53] &= ~0x10;
  106. /*
  107. * Set up linear aperture. For the moment it's 64K at 0xA0000.
  108. * The real base address will be assigned before load is called.
  109. */
  110. vga->crt[0x58] = 0x88;
  111. if(ctlr->flag & Uenhanced){
  112. vga->crt[0x58] |= 0x10;
  113. if(vga->linear && (ctlr->flag & Hlinear))
  114. ctlr->flag |= Ulinear;
  115. if(vga->vmz <= 1024*1024)
  116. vga->vma = 1024*1024;
  117. else if(vga->vmz <= 2*1024*1024)
  118. vga->vma = 2*1024*1024;
  119. else
  120. vga->vma = 8*1024*1024;
  121. }
  122. vga->crt[0x59] = 0x00;
  123. vga->crt[0x5A] = 0x0A;
  124. vga->crt[0x5D] &= 0x80;
  125. if(vga->crt[0x00] & 0x100)
  126. vga->crt[0x5D] |= 0x01;
  127. if(vga->crt[0x01] & 0x100)
  128. vga->crt[0x5D] |= 0x02;
  129. if(vga->crt[0x02] & 0x100)
  130. vga->crt[0x5D] |= 0x04;
  131. if(vga->crt[0x04] & 0x100)
  132. vga->crt[0x5D] |= 0x10;
  133. if(vga->crt[0x3B] & 0x100)
  134. vga->crt[0x5D] |= 0x40;
  135. vga->crt[0x5E] = 0x40;
  136. if(vga->crt[0x06] & 0x400)
  137. vga->crt[0x5E] |= 0x01;
  138. if(vga->crt[0x12] & 0x400)
  139. vga->crt[0x5E] |= 0x02;
  140. if(vga->crt[0x15] & 0x400)
  141. vga->crt[0x5E] |= 0x04;
  142. if(vga->crt[0x10] & 0x400)
  143. vga->crt[0x5E] |= 0x10;
  144. ctlr->type = s3generic.name;
  145. ctlr->flag |= Finit;
  146. }
  147. static void
  148. load(Vga* vga, Ctlr* ctlr)
  149. {
  150. ulong l;
  151. trace("%s->load->s3generic\n", ctlr->name);
  152. vgaxo(Crtx, 0x31, vga->crt[0x31]);
  153. vgaxo(Crtx, 0x32, vga->crt[0x32]);
  154. vgaxo(Crtx, 0x33, vga->crt[0x33]);
  155. vgaxo(Crtx, 0x34, vga->crt[0x34]);
  156. vgaxo(Crtx, 0x35, vga->crt[0x35]);
  157. vgaxo(Crtx, 0x3A, vga->crt[0x3A]);
  158. vgaxo(Crtx, 0x3B, vga->crt[0x3B]);
  159. vgaxo(Crtx, 0x3C, vga->crt[0x3C]);
  160. vgaxo(Crtx, 0x40, vga->crt[0x40]|0x01);
  161. vgaxo(Crtx, 0x42, vga->crt[0x42]);
  162. vgaxo(Crtx, 0x43, vga->crt[0x43]);
  163. vgaxo(Crtx, 0x45, vga->crt[0x45]);
  164. vgaxo(Crtx, 0x50, vga->crt[0x50]);
  165. vgaxo(Crtx, 0x51, vga->crt[0x51]);
  166. vgaxo(Crtx, 0x53, vga->crt[0x53]);
  167. vgaxo(Crtx, 0x54, vga->crt[0x54]);
  168. vgaxo(Crtx, 0x55, vga->crt[0x55]);
  169. if(ctlr->flag & Ulinear){
  170. l = vga->vmb>>16;
  171. vga->crt[0x59] = (l>>8) & 0xFF;
  172. vga->crt[0x5A] = l & 0xFF;
  173. if(vga->vmz <= 1024*1024)
  174. vga->crt[0x58] |= 0x01;
  175. else if(vga->vmz <= 2*1024*1024)
  176. vga->crt[0x58] |= 0x02;
  177. else
  178. vga->crt[0x58] |= 0x03;
  179. }
  180. vgaxo(Crtx, 0x59, vga->crt[0x59]);
  181. vgaxo(Crtx, 0x5A, vga->crt[0x5A]);
  182. vgaxo(Crtx, 0x58, vga->crt[0x58]);
  183. vgaxo(Crtx, 0x5D, vga->crt[0x5D]);
  184. vgaxo(Crtx, 0x5E, vga->crt[0x5E]);
  185. vgaxo(Crtx, 0x6A, vga->crt[0x6A]);
  186. ctlr->flag |= Fload;
  187. }
  188. static void
  189. dump(Vga* vga, Ctlr* ctlr)
  190. {
  191. int i, id, interlace, mul, div;
  192. char *name;
  193. ushort shb, vrs, x;
  194. name = ctlr->name;
  195. printitem(name, "Crt30");
  196. for(i = 0x30; i < 0x3E; i++)
  197. printreg(vga->crt[i]);
  198. printitem(name, "Crt40");
  199. for(i = 0x40; i < 0x50; i++)
  200. printreg(vga->crt[i]);
  201. printitem(name, "Crt50");
  202. for(i = 0x50; i < 0x60; i++)
  203. printreg(vga->crt[i]);
  204. printitem(name, "Crt60");
  205. for(i = 0x60; i < 0x70; i++)
  206. printreg(vga->crt[i]);
  207. /*
  208. * Try to disassemble the snarfed values into
  209. * understandable numbers.
  210. * Only do this if we weren't called after Finit.
  211. */
  212. if(ctlr->flag & Finit)
  213. return;
  214. /*
  215. * If hde <= 400, assume this is a 928 or Vision964
  216. * and the horizontal values have been divided by 4.
  217. *
  218. * if ViRGE/[DG]X and 15 or 16bpp, horizontal values have
  219. * been multiplied by 2.
  220. */
  221. mul = 1;
  222. div = 1;
  223. if(strcmp(name, "virge") == 0){
  224. id = (vga->crt[0x2D]<<8)|vga->crt[0x2E];
  225. /* S3 ViRGE/[DG]X */
  226. if(id==0x8A01 && ((vga->crt[0x67] & 0x30) || (vga->crt[0x67] & 0x50))){
  227. mul = 1;
  228. div = 2;
  229. }
  230. }
  231. x = vga->crt[0x01];
  232. if(vga->crt[0x5D] & 0x02)
  233. x |= 0x100;
  234. x = (x+1)<<3;
  235. if(x <= 400){
  236. mul = 4;
  237. div = 1;
  238. }
  239. x = (x * mul) / div;
  240. printitem(name, "hde");
  241. printreg(x);
  242. Bprint(&stdout, "%6ud", x);
  243. shb = vga->crt[0x02];
  244. if(vga->crt[0x5D] & 0x04)
  245. shb |= 0x100;
  246. shb = (shb+1)<<3;
  247. shb = (shb * mul) / div;
  248. printitem(name, "shb");
  249. printreg(shb);
  250. Bprint(&stdout, "%6ud", shb);
  251. x = vga->crt[0x03] & 0x1F;
  252. if(vga->crt[0x05] & 0x80)
  253. x |= 0x20;
  254. x = (x * mul) / div;
  255. x = shb|x; /* ???? */
  256. if(vga->crt[0x5D] & 0x08)
  257. x += 64;
  258. printitem(name, "ehb");
  259. printreg(x);
  260. Bprint(&stdout, "%6ud", x);
  261. x = vga->crt[0x00];
  262. if(vga->crt[0x5D] & 0x01)
  263. x |= 0x100;
  264. x = (x+5)<<3;
  265. x = (x * mul) / div;
  266. printitem(name, "ht");
  267. printreg(x);
  268. Bprint(&stdout, "%6ud", x);
  269. interlace = vga->crt[0x42] & 0x20;
  270. x = vga->crt[0x12];
  271. if(vga->crt[0x07] & 0x02)
  272. x |= 0x100;
  273. if(vga->crt[0x07] & 0x40)
  274. x |= 0x200;
  275. if(vga->crt[0x5E] & 0x02)
  276. x |= 0x400;
  277. x += 1;
  278. if(interlace)
  279. x *= 2;
  280. printitem(name, "vde");
  281. printreg(x);
  282. Bprint(&stdout, "%6ud", x);
  283. vrs = vga->crt[0x10];
  284. if(vga->crt[0x07] & 0x04)
  285. vrs |= 0x100;
  286. if(vga->crt[0x07] & 0x80)
  287. vrs |= 0x200;
  288. if(vga->crt[0x5E] & 0x10)
  289. vrs |= 0x400;
  290. if(interlace)
  291. vrs *= 2;
  292. printitem(name, "vrs");
  293. printreg(vrs);
  294. Bprint(&stdout, "%6ud", vrs);
  295. if(interlace)
  296. vrs /= 2;
  297. x = (vrs & ~0x0F)|(vga->crt[0x11] & 0x0F);
  298. if(interlace)
  299. x *= 2;
  300. printitem(name, "vre");
  301. printreg(x);
  302. Bprint(&stdout, "%6ud", x);
  303. x = vga->crt[0x06];
  304. if(vga->crt[0x07] & 0x01)
  305. x |= 0x100;
  306. if(vga->crt[0x07] & 0x20)
  307. x |= 0x200;
  308. if(vga->crt[0x5E] & 0x01)
  309. x |= 0x400;
  310. x += 2;
  311. if(interlace)
  312. x *= 2;
  313. printitem(name, "vt");
  314. printreg(x);
  315. Bprint(&stdout, "%6ud", x);
  316. }
  317. Ctlr s3generic = {
  318. "s3", /* name */
  319. snarf, /* snarf */
  320. 0, /* options */
  321. init, /* init */
  322. load, /* load */
  323. dump, /* dump */
  324. };