ct65540.c 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. enum
  7. {
  8. X= 0x3D6, /* index reg */
  9. D= 0x3D7, /* data reg */
  10. };
  11. static int misc[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0xE, 0x28, 0x29,
  12. 0x70, 0x72, 0x73, 0x7D, 0x7F, -1};
  13. static int map[] = { 0x7, 0x8, 0xB, 0xC, 0x10, 0x11, -1};
  14. static int flags[] = { 0xF, 0x2B, 0x44, 0x45, -1};
  15. static int compat[] = { 0x14, 0x15, 0x1F, 0x7E, -1};
  16. static int clock[] = { 0x30, 0x31, 0x32, 0x33, -1};
  17. static int mm[] = { 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F, -1};
  18. static int alt[] = { 0x0D, 0x16, 0x17, 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E,
  19. 0x24, 0x25, 0x26, 0x64, 0x65, 0x66, 0x67, -1};
  20. static int flat[] = { 0x2C, 0x2D, 0x2E, 0x2F, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54,
  21. 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E,
  22. 0x5F, 0x60, 0x61, 0x62, 0x63, 0x68, 0x6C, 0x6E, 0x6F, -1};
  23. typedef struct Group Group;
  24. struct Group {
  25. char *name;
  26. int *x;
  27. };
  28. static Group group[] =
  29. {
  30. { "misc", misc, },
  31. { "map", map, },
  32. { "compatability", compat, },
  33. { "clock", clock, },
  34. { "multimedia", mm, },
  35. { "alternate", alt, },
  36. { "flat-panel", flat, },
  37. { 0 },
  38. };
  39. static uchar greg[256];
  40. static uchar
  41. ctxi(uchar index)
  42. {
  43. outportb(X, index);
  44. return inportb(D);
  45. }
  46. static void
  47. ctxo(uchar index, uchar data)
  48. {
  49. outportb(X, index);
  50. outportb(D, data);
  51. }
  52. /*
  53. * ct65540.
  54. */
  55. static void
  56. snarf(Vga*, Ctlr* ctlr)
  57. {
  58. Group *g;
  59. int *xp;
  60. ctlr->flag |= Fsnarf;
  61. for(g = group; g->name; g++)
  62. for(xp = g->x; *xp >= 0; xp++)
  63. greg[*xp] = ctxi(*xp);
  64. }
  65. static void
  66. options(Vga*, Ctlr* ctlr)
  67. {
  68. ctlr->flag |= Hlinear|Foptions;
  69. }
  70. /*
  71. * brute force and ignorance
  72. */
  73. static int
  74. setclock(Vga* vga)
  75. {
  76. ulong fvco, t;
  77. ulong m, n;
  78. ulong bestm, bestn, diff, bestdiff, lastdiff;
  79. ulong p;
  80. if(vga->mode->frequency > 220000000)
  81. return -1;
  82. vga->misc &= ~(3<<2);
  83. vga->feature &= ~3;
  84. greg[0x33] &= ~0x20; /* set VCLK not MCLK */
  85. greg[0x33] &= ~0x80; /* clk0 & clk1 are 25.175 & 28.322 MHz */
  86. vga->misc |= (2<<2);
  87. vga->feature |= 2;
  88. fvco = vga->mode->frequency;
  89. if(fvco == 0)
  90. return -1;
  91. p = 0;
  92. while(fvco < 100000000){
  93. fvco *= 2;
  94. p++;
  95. }
  96. m = (1<<31)/(4*RefFreq);
  97. if(m > 127)
  98. m = 127;
  99. bestdiff = 1<<31;
  100. bestm = 3;
  101. bestn = 3;
  102. for(; m > 2; m--){
  103. lastdiff = 1<<31;
  104. for(n = 3; n < 128; n++){
  105. t = (RefFreq*4*m)/n;
  106. diff = abs(fvco-t);
  107. if(diff < bestdiff){
  108. bestdiff = diff;
  109. bestm = m;
  110. bestn = n;
  111. } else {
  112. if(diff > lastdiff)
  113. break;
  114. }
  115. lastdiff = diff;
  116. }
  117. }
  118. greg[0x31] = bestm - 2;
  119. greg[0x32] = bestn - 2;
  120. greg[0x30] = (p<<1) | 1;
  121. return 0;
  122. }
  123. static void
  124. init(Vga* vga, Ctlr* ctlr)
  125. {
  126. int x;
  127. greg[0x15] = 0; /* allow writes to all registers */
  128. if(vga->mode->z > 8)
  129. error("depth %d not supported\n", vga->mode->z);
  130. if(vga->mode->z == 8){
  131. if(vga->linear && (ctlr->flag & Hlinear))
  132. ctlr->flag |= Ulinear;
  133. vga->vmz = 1024*1024;
  134. vga->vmb = 1024*1024;
  135. /* linear mapping - extension regs*/
  136. greg[0x04] = (1<<2); /* enable CRTC bits 16 & 17, 32 bit mode */
  137. greg[0x0b] = 0x15; /* linear addressing, > 256k, sequential addr */
  138. greg[0x28] = 0x90; /* non-interlaced, 256 colors */
  139. /* normal regs */
  140. vga->sequencer[0x04] = 0x0A; /* sequential memory access */
  141. vga->graphics[0x05] = 0x00; /* sequential access, shift out 8 bits at */
  142. /* a time */
  143. vga->attribute[0x10] &= ~(1<<6); /* 1 dot clock per pixel */
  144. vga->crt[0x14] = 0x00;
  145. vga->crt[0x17] = 0xe3; /* always byte mode */
  146. } else {
  147. /* mapped to 0xa0000 - extension regs*/
  148. greg[0x04] = (1<<2); /* enable CRTC bits 16 & 17, 32 bit mode */
  149. greg[0x0b] = 0x01; /* 0xA0000 - 0xAFFFF, planar addressing */
  150. greg[0x28] = 0x80; /* non-interlaced, 16 colors */
  151. }
  152. /* the extension registers have even more overflow bits */
  153. x = 0;
  154. if(vga->mode->vt & (1<<10))
  155. x |= (1<<0);
  156. if(vga->mode->vrs & (1<<10))
  157. x |= (1<<2);
  158. greg[0x16] = x;
  159. x = 0;
  160. if(vga->mode->ht & (1<<(8+3)))
  161. x |= (1<<0);
  162. if(vga->mode->shb & (1<<(8+3)))
  163. x |= (1<<4);
  164. if(vga->mode->ehb & (1<<(6+3)))
  165. x |= (1<<5);
  166. greg[0x17] = x;
  167. if(vga->mode->y > 480)
  168. vga->misc &= 0x3F;
  169. setclock(vga);
  170. ctlr->flag |= Finit;
  171. }
  172. static void
  173. load(Vga* vga, Ctlr* ctlr)
  174. {
  175. Group *g;
  176. int *xp;
  177. /* must be first */
  178. ctxo(0x15, greg[0x15]); /* write protect */
  179. ctxo(0x33, greg[0x33]); /* select clock */
  180. if(ctlr->flag & Ulinear){
  181. greg[0x8] = vga->vmb>>20;
  182. ctxo(0x08, greg[0x08]);
  183. }
  184. /* only write what changed */
  185. for(g = group; g->name; g++)
  186. for(xp = g->x; *xp >= 0; xp++)
  187. ctxo(*xp, greg[*xp]);
  188. ctlr->flag |= Fload;
  189. }
  190. static void
  191. dump(Vga*, Ctlr* ctlr)
  192. {
  193. Group *g;
  194. int *xp;
  195. char *name;
  196. int lastx;
  197. char item[32];
  198. name = ctlr->name;
  199. for(g = group; g->name; g++){
  200. lastx = -2;
  201. for(xp = g->x; *xp >= 0; xp++){
  202. if(*xp != lastx+1){
  203. sprint(item, "%s %2.2ux:", g->name, *xp);
  204. printitem(name, item);
  205. }
  206. lastx = *xp;
  207. printreg(greg[*xp]);
  208. }
  209. }
  210. }
  211. Ctlr ct65540 = {
  212. "ct65540", /* name */
  213. snarf, /* snarf */
  214. options, /* options */
  215. init, /* init */
  216. load, /* load */
  217. dump, /* dump */
  218. };
  219. Ctlr ct65545 = {
  220. "ct65545", /* name */
  221. snarf, /* snarf */
  222. options, /* options */
  223. init, /* init */
  224. load, /* load */
  225. dump, /* dump */
  226. };
  227. Ctlr ct65545hwgc = {
  228. "ct65545hwgc", /* name */
  229. 0, /* snarf */
  230. 0, /* options */
  231. 0, /* init */
  232. 0, /* load */
  233. 0, /* dump */
  234. };