vga.c 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. enum {
  7. NSeqx = 0x05,
  8. NCrtx = 0x19,
  9. NGrx = 0x09,
  10. NAttrx = 0x15,
  11. };
  12. uchar
  13. vgai(long port)
  14. {
  15. uchar data;
  16. switch(port){
  17. case MiscR:
  18. case Status0:
  19. case Status1:
  20. case FeatureR:
  21. case PaddrW:
  22. case Pdata:
  23. case Pixmask:
  24. case Pstatus:
  25. data = inportb(port);
  26. break;
  27. default:
  28. error("vgai(0x%4.4lX): unknown port\n", port);
  29. /*NOTREACHED*/
  30. data = 0xFF;
  31. break;
  32. }
  33. return data;
  34. }
  35. uchar
  36. vgaxi(long port, uchar index)
  37. {
  38. uchar data;
  39. switch(port){
  40. case Seqx:
  41. case Crtx:
  42. case Grx:
  43. outportb(port, index);
  44. data = inportb(port+1);
  45. break;
  46. case Attrx:
  47. /*
  48. * Allow processor access to the colour
  49. * palette registers. Writes to Attrx must
  50. * be preceded by a read from Status1 to
  51. * initialise the register to point to the
  52. * index register and not the data register.
  53. * Processor access is allowed by turning
  54. * off bit 0x20.
  55. */
  56. inportb(Status1);
  57. if(index < 0x10){
  58. outportb(Attrx, index);
  59. data = inportb(Attrx+1);
  60. inportb(Status1);
  61. outportb(Attrx, 0x20|index);
  62. }
  63. else{
  64. outportb(Attrx, 0x20|index);
  65. data = inportb(Attrx+1);
  66. }
  67. break;
  68. default:
  69. error("vgaxi(0x%4.4lx, 0x%2.2uX): unknown port\n", port, index);
  70. /*NOTREACHED*/
  71. data = 0xFF;
  72. break;
  73. }
  74. return data;
  75. }
  76. void
  77. vgao(long port, uchar data)
  78. {
  79. switch(port){
  80. case MiscW:
  81. case FeatureW:
  82. case PaddrW:
  83. case Pdata:
  84. case Pixmask:
  85. case PaddrR:
  86. outportb(port, data);
  87. break;
  88. default:
  89. error("vgao(0x%4.4lX, 0x%2.2uX): unknown port\n", port, data);
  90. /*NOTREACHED*/
  91. break;
  92. }
  93. }
  94. void
  95. vgaxo(long port, uchar index, uchar data)
  96. {
  97. switch(port){
  98. case Seqx:
  99. case Crtx:
  100. case Grx:
  101. /*
  102. * We could use an outport here, but some chips
  103. * (e.g. 86C928) have trouble with that for some
  104. * registers.
  105. */
  106. outportb(port, index);
  107. outportb(port+1, data);
  108. break;
  109. case Attrx:
  110. inportb(Status1);
  111. if(index < 0x10){
  112. outportb(Attrx, index);
  113. outportb(Attrx, data);
  114. inportb(Status1);
  115. outportb(Attrx, 0x20|index);
  116. }
  117. else{
  118. outportb(Attrx, 0x20|index);
  119. outportb(Attrx, data);
  120. }
  121. break;
  122. default:
  123. error("vgaxo(0x%4.4lX, 0x%2.2uX, 0x%2.2uX): unknown port\n",
  124. port, index, data);
  125. break;
  126. }
  127. }
  128. static void
  129. snarf(Vga* vga, Ctlr* ctlr)
  130. {
  131. int i;
  132. /*
  133. * Generic VGA registers:
  134. * misc, feature;
  135. * sequencer;
  136. * crt;
  137. * graphics;
  138. * attribute;
  139. * palette.
  140. */
  141. vga->misc = vgai(MiscR);
  142. vga->feature = vgai(FeatureR);
  143. for(i = 0; i < NSeqx; i++)
  144. vga->sequencer[i] = vgaxi(Seqx, i);
  145. for(i = 0; i < NCrtx; i++)
  146. vga->crt[i] = vgaxi(Crtx, i);
  147. for(i = 0; i < NGrx; i++)
  148. vga->graphics[i] = vgaxi(Grx, i);
  149. for(i = 0; i < NAttrx; i++)
  150. vga->attribute[i] = vgaxi(Attrx, i);
  151. if(dflag)
  152. palette.snarf(vga, ctlr);
  153. ctlr->flag |= Fsnarf;
  154. }
  155. static void
  156. init(Vga* vga, Ctlr* ctlr)
  157. {
  158. Mode *mode;
  159. int vt, vde, vrs, vre;
  160. ulong tmp;
  161. mode = vga->mode;
  162. memset(vga->sequencer, 0, NSeqx*sizeof(vga->sequencer[0]));
  163. memset(vga->crt, 0, NCrtx*sizeof(vga->crt[0]));
  164. memset(vga->graphics, 0, NGrx*sizeof(vga->graphics[0]));
  165. memset(vga->attribute, 0, NAttrx*sizeof(vga->attribute[0]));
  166. if(dflag)
  167. memset(vga->palette, 0, sizeof(vga->palette));
  168. /*
  169. * Misc. If both the horizontal and vertical sync polarity
  170. * options are set, use them. Otherwise use the defaults for
  171. * the given vertical size.
  172. */
  173. vga->misc = 0x23;
  174. if(mode->frequency == VgaFreq1)
  175. vga->misc |= 0x04;
  176. if(mode->hsync && mode->vsync){
  177. if(mode->hsync == '-')
  178. vga->misc |= 0x40;
  179. if(mode->vsync == '-')
  180. vga->misc |= 0x80;
  181. }
  182. else{
  183. if(mode->y < 480)
  184. vga->misc |= 0x40;
  185. else if(mode->y < 400)
  186. vga->misc |= 0x80;
  187. else if(mode->y < 768)
  188. vga->misc |= 0xC0;
  189. }
  190. /*
  191. * Sequencer
  192. */
  193. vga->sequencer[0x00] = 0x03;
  194. vga->sequencer[0x01] = 0x01;
  195. vga->sequencer[0x02] = 0x0F;
  196. vga->sequencer[0x03] = 0x00;
  197. if(mode->z >= 8)
  198. vga->sequencer[0x04] = 0x0A;
  199. else
  200. vga->sequencer[0x04] = 0x06;
  201. /*
  202. * Crt. Most of the work here is in dealing
  203. * with field overflow.
  204. */
  205. memset(vga->crt, 0, NCrtx);
  206. vga->crt[0x00] = (mode->ht>>3)-5;
  207. vga->crt[0x01] = (mode->x>>3)-1;
  208. vga->crt[0x02] = (mode->shb>>3)-1;
  209. /*
  210. * End Horizontal Blank is a 6-bit field, 5-bits
  211. * in Crt3, high bit in Crt5.
  212. */
  213. tmp = mode->ehb>>3;
  214. vga->crt[0x03] = 0x80|(tmp & 0x1F);
  215. if(tmp & 0x20)
  216. vga->crt[0x05] |= 0x80;
  217. if(mode->shs == 0)
  218. mode->shs = mode->shb;
  219. vga->crt[0x04] = mode->shs>>3;
  220. if(mode->ehs == 0)
  221. mode->ehs = mode->ehb;
  222. vga->crt[0x05] |= ((mode->ehs>>3) & 0x1F);
  223. /*
  224. * Vertical Total is 10-bits, 8 in Crt6, the high
  225. * two bits in Crt7. What if vt is >= 1024? We hope
  226. * the specific controller has some more overflow
  227. * bits.
  228. *
  229. * Interlace: if 'v', divide the vertical timing
  230. * values by 2.
  231. */
  232. vt = mode->vt;
  233. vde = mode->y;
  234. vrs = mode->vrs;
  235. vre = mode->vre;
  236. if(mode->interlace == 'v'){
  237. vt /= 2;
  238. vde /= 2;
  239. vrs /= 2;
  240. vre /= 2;
  241. }
  242. tmp = vt-2;
  243. vga->crt[0x06] = tmp;
  244. if(tmp & 0x100)
  245. vga->crt[0x07] |= 0x01;
  246. if(tmp & 0x200)
  247. vga->crt[0x07] |= 0x20;
  248. tmp = vrs;
  249. vga->crt[0x10] = tmp;
  250. if(tmp & 0x100)
  251. vga->crt[0x07] |= 0x04;
  252. if(tmp & 0x200)
  253. vga->crt[0x07] |= 0x80;
  254. vga->crt[0x11] = 0x20|(vre & 0x0F);
  255. tmp = vde-1;
  256. vga->crt[0x12] = tmp;
  257. if(tmp & 0x100)
  258. vga->crt[0x07] |= 0x02;
  259. if(tmp & 0x200)
  260. vga->crt[0x07] |= 0x40;
  261. vga->crt[0x15] = vrs;
  262. if(vrs & 0x100)
  263. vga->crt[0x07] |= 0x08;
  264. if(vrs & 0x200)
  265. vga->crt[0x09] |= 0x20;
  266. vga->crt[0x16] = (vrs+1);
  267. vga->crt[0x17] = 0x83;
  268. tmp = ((vga->virtx*mode->z)/8);
  269. if(tmp >= 512){
  270. vga->crt[0x14] |= 0x60;
  271. tmp /= 8;
  272. }
  273. else if(tmp >= 256){
  274. vga->crt[0x17] |= 0x08;
  275. tmp /= 4;
  276. }
  277. else{
  278. vga->crt[0x17] |= 0x40;
  279. tmp /= 2;
  280. }
  281. vga->crt[0x13] = tmp;
  282. if(mode->x*mode->y*mode->z/8 > 64*1024)
  283. vga->crt[0x17] |= 0x20;
  284. vga->crt[0x18] = 0x7FF;
  285. if(vga->crt[0x18] & 0x100)
  286. vga->crt[0x07] |= 0x10;
  287. if(vga->crt[0x18] & 0x200)
  288. vga->crt[0x09] |= 0x40;
  289. /*
  290. * Graphics
  291. */
  292. memset(vga->graphics, 0, NGrx);
  293. if((vga->sequencer[0x04] & 0x04) == 0)
  294. vga->graphics[0x05] |= 0x10;
  295. if(mode->z >= 8)
  296. vga->graphics[0x05] |= 0x40;
  297. vga->graphics[0x06] = 0x05;
  298. vga->graphics[0x07] = 0x0F;
  299. vga->graphics[0x08] = 0xFF;
  300. /*
  301. * Attribute
  302. */
  303. memset(vga->attribute, 0, NAttrx);
  304. for(tmp = 0; tmp < 0x10; tmp++)
  305. vga->attribute[tmp] = tmp;
  306. vga->attribute[0x10] = 0x01;
  307. if(mode->z >= 8)
  308. vga->attribute[0x10] |= 0x40;
  309. vga->attribute[0x11] = 0xFF;
  310. vga->attribute[0x12] = 0x0F;
  311. /*
  312. * Palette
  313. */
  314. if(dflag)
  315. palette.init(vga, ctlr);
  316. ctlr->flag |= Finit;
  317. }
  318. static void
  319. load(Vga* vga, Ctlr* ctlr)
  320. {
  321. int i;
  322. /*
  323. * Reset the sequencer and leave it off.
  324. * Load the generic VGA registers:
  325. * misc;
  326. * sequencer (but not seq01, display enable);
  327. * take the sequencer out of reset;
  328. * take off write-protect on crt[0x00-0x07];
  329. * crt;
  330. * graphics;
  331. * attribute;
  332. * palette.
  333. vgaxo(Seqx, 0x00, 0x00);
  334. */
  335. vgao(MiscW, vga->misc);
  336. for(i = 2; i < NSeqx; i++)
  337. vgaxo(Seqx, i, vga->sequencer[i]);
  338. /*vgaxo(Seqx, 0x00, 0x03);*/
  339. vgaxo(Crtx, 0x11, vga->crt[0x11] & ~0x80);
  340. for(i = 0; i < NCrtx; i++)
  341. vgaxo(Crtx, i, vga->crt[i]);
  342. for(i = 0; i < NGrx; i++)
  343. vgaxo(Grx, i, vga->graphics[i]);
  344. for(i = 0; i < NAttrx; i++)
  345. vgaxo(Attrx, i, vga->attribute[i]);
  346. if(dflag)
  347. palette.load(vga, ctlr);
  348. ctlr->flag |= Fload;
  349. }
  350. static void
  351. dump(Vga* vga, Ctlr* ctlr)
  352. {
  353. int i;
  354. printitem(ctlr->name, "misc");
  355. printreg(vga->misc);
  356. printitem(ctlr->name, "feature");
  357. printreg(vga->feature);
  358. printitem(ctlr->name, "sequencer");
  359. for(i = 0; i < NSeqx; i++)
  360. printreg(vga->sequencer[i]);
  361. printitem(ctlr->name, "crt");
  362. for(i = 0; i < NCrtx; i++)
  363. printreg(vga->crt[i]);
  364. printitem(ctlr->name, "graphics");
  365. for(i = 0; i < NGrx; i++)
  366. printreg(vga->graphics[i]);
  367. printitem(ctlr->name, "attribute");
  368. for(i = 0; i < NAttrx; i++)
  369. printreg(vga->attribute[i]);
  370. if(dflag)
  371. palette.dump(vga, ctlr);
  372. printitem(ctlr->name, "virtual");
  373. Bprint(&stdout, "%ld %ld\n", vga->virtx, vga->virty);
  374. printitem(ctlr->name, "panning");
  375. Bprint(&stdout, "%s\n", vga->panning ? "on" : "off");
  376. if(vga->f[0]){
  377. printitem(ctlr->name, "clock[0] f");
  378. Bprint(&stdout, "%9ld\n", vga->f[0]);
  379. printitem(ctlr->name, "clock[0] d i m");
  380. Bprint(&stdout, "%9ld %8ld - %8ld\n",
  381. vga->d[0], vga->i[0], vga->m[0]);
  382. printitem(ctlr->name, "clock[0] n p q r");
  383. Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n",
  384. vga->n[0], vga->p[0], vga->q[0], vga->r[0]);
  385. }
  386. if(vga->f[1]){
  387. printitem(ctlr->name, "clock[1] f");
  388. Bprint(&stdout, "%9ld\n", vga->f[1]);
  389. printitem(ctlr->name, "clock[1] d i m");
  390. Bprint(&stdout, "%9ld %8ld - %8ld\n",
  391. vga->d[1], vga->i[1], vga->m[1]);
  392. printitem(ctlr->name, "clock[1] n p q r");
  393. Bprint(&stdout, "%9ld %8ld - %8ld %8ld\n",
  394. vga->n[1], vga->p[1], vga->q[1], vga->r[1]);
  395. }
  396. if(vga->vma || vga->vmb){
  397. printitem(ctlr->name, "vm a b");
  398. Bprint(&stdout, "%9lud %8lud\n", vga->vma, vga->vmb);
  399. }
  400. if(vga->vmz){
  401. printitem(ctlr->name, "vmz");
  402. Bprint(&stdout, "%9lud\n", vga->vmz);
  403. }
  404. printitem(ctlr->name, "apz");
  405. Bprint(&stdout, "%9lud\n", vga->apz);
  406. printitem(ctlr->name, "linear");
  407. Bprint(&stdout, "%9d\n", vga->linear);
  408. }
  409. Ctlr generic = {
  410. "vga", /* name */
  411. snarf, /* snarf */
  412. 0, /* options */
  413. init, /* init */
  414. load, /* load */
  415. dump, /* dump */
  416. };