i81x.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * Intel 81x chipset family.
  8. * mem[0]: AGP aperture memory, 64MB for 810-DC100, from 0xF4000000
  9. * mem[1]: GC Register mmio space, 512KB for 810-DC100, from 0xFF000000
  10. * For the memory of David Hogan, died April 9, 2003, who wrote this driver
  11. * first for LCD.
  12. * August 28, 2003 Kenji Okamoto
  13. */
  14. typedef struct {
  15. Pcidev* pci;
  16. uchar* mmio;
  17. ulong clk[6];
  18. ulong lcd[9];
  19. ulong pixconf;
  20. } I81x;
  21. static void
  22. snarf(Vga* vga, Ctlr* ctlr)
  23. {
  24. int f, i;
  25. uchar *mmio;
  26. ulong *rp;
  27. Pcidev *p;
  28. I81x *i81x;
  29. if(vga->private == nil){
  30. vga->private = alloc(sizeof(I81x));
  31. p = nil;
  32. while((p = pcimatch(p, 0x8086, 0)) != nil) {
  33. switch(p->did) {
  34. default:
  35. continue;
  36. case 0x7121: /* Vanilla 82810 */
  37. case 0x7123: /* 810-DC100, DELL OptiPlex GX100 */
  38. case 0x7125: /* 82810E */
  39. case 0x1102: /* 82815 FSB limited to 100MHz */
  40. case 0x1112: /* 82815 no AGP */
  41. case 0x1132: /* 82815 fully featured Solano */
  42. case 0x3577: /* IBM R31 uses intel 830M chipset */
  43. vga->f[1] = 230000000; /* MAX speed of internal DAC (Hz)*/
  44. break;
  45. }
  46. break;
  47. }
  48. if(p == nil)
  49. error("%s: Intel 81x graphics function not found\n", ctlr->name);
  50. if((f = open("#v/vgactl", OWRITE)) < 0)
  51. error("%s: can't open vgactl\n", ctlr->name);
  52. if(write(f, "type i81x", 9) != 9)
  53. error("%s: can't set type\n", ctlr->name);
  54. close(f);
  55. mmio = segattach(0, "i81xmmio", 0, p->mem[1].size);
  56. if(mmio == (void*)-1)
  57. error("%s: can't attach mmio segment\n", ctlr->name);
  58. i81x = vga->private;
  59. i81x->pci = p;
  60. i81x->mmio = mmio;
  61. }
  62. i81x = vga->private;
  63. /* must give aperture memory size for frame buffer memory
  64. such as 64*1024*1024 */
  65. vga->vma = vga->vmz = i81x->pci->mem[0].size;
  66. // vga->vmz = 8*1024*1024;
  67. vga->apz = i81x->pci->mem[0].size;
  68. ctlr->flag |= Hlinear;
  69. vga->graphics[0x10] = vgaxi(Grx, 0x10);
  70. vga->attribute[0x11] = vgaxi(Attrx, 0x11); /* overscan color */
  71. for(i=0; i < 0x19; i++)
  72. vga->crt[i] = vgaxi(Crtx, i);
  73. for(i=0x30; i <= 0x82; i++) /* set CRT Controller Register (CR) */
  74. vga->crt[i] = vgaxi(Crtx, i);
  75. /* 0x06000: Clock Control Register base address (3 VCO frequency control) */
  76. rp = (ulong*)(i81x->mmio+0x06000);
  77. for(i = 0; i < nelem(i81x->clk); i++)
  78. i81x->clk[i] = *rp++;
  79. /* i830 CRTC registers (A) */
  80. rp = (ulong*)(i81x->mmio+0x60000);
  81. for(i = 0; i < nelem(i81x->lcd); i++)
  82. i81x->lcd[i] = *rp++;
  83. rp = (ulong*)(i81x->mmio+0x70008); /* Pixel Pipeline Control register A */
  84. i81x->pixconf = *rp;
  85. ctlr->flag |= Fsnarf;
  86. }
  87. static void
  88. options(Vga*, Ctlr* ctlr)
  89. {
  90. ctlr->flag |= Hlinear|Foptions;
  91. }
  92. static void
  93. i81xdclk(I81x *i81x, Vga *vga) /* freq = MHz */
  94. {
  95. int m, n, post, mtp, ntp;
  96. double md, freq, error;
  97. freq = vga->mode->deffrequency/1000000.0;
  98. if (freq == 0)
  99. sysfatal("i81xdclk: deffrequency %d becomes freq 0.0\n",
  100. vga->mode->deffrequency);
  101. post = log(600.0/freq)/log(2.0);
  102. for(ntp=3;;ntp++) {
  103. md = freq*(1<<post)/(24.0/(double)ntp)/4.0;
  104. mtp = (int)(md+0.5);
  105. if(mtp<3) mtp=3;
  106. error = 1.0-freq/(md/(ntp*(1<<post))*4*24.0);
  107. if((fabs(error) < 0.001) || ((ntp > 30) && (fabs(error) < 0.005)))
  108. break;
  109. }
  110. m = vga->m[1] = mtp-2;
  111. n = vga->n[1] = ntp-2;
  112. vga->r[1] = post;
  113. i81x->clk[2] = ((n & 0x3FF)<<16) | (m & 0x3FF);
  114. i81x->clk[4] = (i81x->clk[4] & ~0x700000) | ((post & 0x07)<<20);
  115. vga->mode->frequency = (m+2)/((n+2)*(1<<post))*4*24*1000000;
  116. }
  117. static void
  118. init(Vga* vga, Ctlr* ctlr)
  119. {
  120. I81x *i81x;
  121. int vt, vde, vrs, vre;
  122. ulong *rp;
  123. i81x = vga->private;
  124. /* <<TODO>>
  125. i81x->clk[3]: LCD_CLKD: 0x0600c~0x0600f, default=00030013h
  126. (VCO N-divisor=03h, M-divisor=13h)
  127. i81x->clk[4]: DCLK_0DS: 0x06010~0x06013, Post value, default=40404040h means
  128. Post Divisor=16, VCO Loop divisor = 4xM for all clocks.
  129. Display&LCD Clock Devisor Select Reg = 0x40404040 ==> (LCD)(Clock2)(Clock1)(Clock0)
  130. */
  131. i81x->clk[0] = 0x00030013;
  132. i81x->clk[1] = 0x00100053;
  133. rp = (ulong*)i81x->mmio+0x6010;
  134. i81x->clk[4] = *rp;
  135. i81x->clk[4] |= 0x4040;
  136. vga->misc = vgai(MiscR);
  137. switch(vga->virtx) {
  138. case 640: /* 640x480 DCLK_0D 25.175MHz dot clock */
  139. vga->misc &= ~0x0A;
  140. break;
  141. case 720: /* 720x480 DCLK_1D 28.322MHz dot clock */
  142. vga->misc = (vga->misc & ~0x08) | (1<<2);
  143. break;
  144. case 800:
  145. case 1024:
  146. case 1152:
  147. case 1280:
  148. case 1376:
  149. vga->misc = vga->misc | (2<<2) & ~0x02; /* prohibit to access frame buffer */
  150. i81xdclk(i81x, vga);
  151. break;
  152. default: /* for other higher resolution DCLK_2D */
  153. error("%s: Only 800, 1024, 1152, 1280, 1376 resolutions are supported\n", ctlr->name);
  154. }
  155. /* <<TODO>>
  156. i830 LCD Controller, at i81x->mmio+0x60000
  157. i81x->lcd[0]: Horizontal Total Reg. 0x60000
  158. i81x->lcd[1]: Horizontal Blanking Reg. 0x60004
  159. i81x->lcd[2]: Horizontal Sync Reg. 0x60008
  160. i81x->lcd[3]: Vertical Total Reg. 0x6000c
  161. i81x->lcd[4]: Vertical Blanking Reg. 0x60010
  162. i81x->lcd[5]: Vertical Sync Reg. 0x60014
  163. i81x->lcd[6]: Pixel Pipeline A Sequencer Register Control(SRC,0~7) 0x6001c
  164. i81x->lcd[7]: BCLRPAT_A 0x60020
  165. i81x->lcd[8]: 0
  166. */
  167. /*
  168. * Pixel pipeline control register 0x70008:
  169. * 16/24bp bypasses palette,
  170. * hw cursor enabled(1<<12), hi-res mode(1<<0), depth(16-19 bit)
  171. * 8bit DAC enable (1<<15), don't wrap to 256kM memory of VGA(1<<1).
  172. * enable extended palette addressing (1<<8)
  173. */
  174. i81x->pixconf = (1<<12)|(1<<0);
  175. i81x->pixconf &= 0xFFFFFBFF; /* disable overscan color */
  176. switch(vga->mode->z) { /* vga->mode->z: color depth */
  177. case 8:
  178. i81x->pixconf |= (2<<16);
  179. break;
  180. case 16: /* (5:6:5 bit) */
  181. i81x->pixconf |= (5<<16);
  182. break;
  183. case 24:
  184. i81x->pixconf |= (6<<16);
  185. break;
  186. case 32: /* not supported */
  187. i81x->pixconf |= (7<<16);
  188. break;
  189. default:
  190. error("%s: depth %d not supported\n", ctlr->name, vga->mode->z);
  191. }
  192. /* DON'T CARE of Sequencer Reg. */
  193. /* DON'T CARE of Attribute registers other than this */
  194. vga->attribute[0x11] = 0; /* over scancolor = black */
  195. /* DON't CARE of graphics[1], [2], [3], [4], [5], [6], [7] and [8] value */
  196. if(vga->linear && (ctlr->flag & Hlinear)) {
  197. /* enable linear mapping, no VGA memory and no page mapping */
  198. vga->graphics[0x10] = 0x0A;
  199. ctlr->flag |= Ulinear;
  200. }
  201. vt = vga->mode->vt;
  202. vde = vga->virty;
  203. vrs = vga->mode->vrs;
  204. vre = vga->mode->vre+6; /* shift 7 pixel up */
  205. if(vga->mode->interlace == 'v') {
  206. vt /= 2;
  207. vde /= 2;
  208. vrs /= 2;
  209. vre /= 2;
  210. }
  211. /* Reset Row scan */
  212. vga->crt[8] = 0;
  213. /* Line Compare, bit 6 of crt[9], bit 4 of crt[7] and crt[0x18], should be
  214. * vga->crt[9] = vgaxi(Crtx, 9) | ((vde>>9 & 1)<<6) & 0x7F;
  215. * vga->crt[7] = vgaxi(Crtx, 7) | ((vde>>8 & 1)<<4);
  216. * vga->crt[0x18] = vde & 0xFF;
  217. * However, above values don't work!! I don't know why. K.Okamoto
  218. */
  219. vga->crt[9] = 0; /* I don't know why ? */
  220. vga->crt[7] = 0; /* I don't know why ? */
  221. vga->crt[0x18] = 0; /* I don't know why ? */
  222. /* 32 bits Start Address of frame buffer (AGP aperture memory)
  223. vga->crt[0x42] = MSB 8 bits of Start Address Register, extended high start address Reg.
  224. vga->crt[0x40] = higer 6 bits in 0~5 bits, and the MSB = 1, extebded start address Reg.
  225. vga->crt[0x0C] = Start Address High Register
  226. vga->crt[0x0D] = Start Address Low Register
  227. LSB 2 bits of Start Address are always 0
  228. */
  229. vga->crt[0x42] = vga->pci->mem[0].bar>>24 & 0xFF;
  230. vga->crt[0x40] = vga->pci->mem[0].bar>>18 & 0x3F | 0x80;
  231. /* Start Address High */
  232. vga->crt[0x0C] = vga->pci->mem[0].bar>>10 & 0xFF;
  233. /* Start Address Low */
  234. vga->crt[0x0D] = (vga->pci->mem[0].bar >>2 + 1)& 0xFF;
  235. /* Underline Location, Memory Mode, DON'T CARE THIS VALUE */
  236. vga->crt[0x14] = 0x0;
  237. /* CRT Mode Control */
  238. vga->crt[0x17] = 0x80; /* CRT normal mode */
  239. /* Frame buffer memory offset (memory amount for a line) */
  240. /* vga->crt[0x13] = lower 8 bits of Offset Register
  241. vga->crt[0x41] = MSB 4 bits, those value should be
  242. vga->crt[0x13] = (vga->virtx*(vga->mode->z>>3)/4) & 0xFF;
  243. vga->crt[0x41] = (vga->virtx*(vga->mode->z>>3)/4)>>8 & 0x0F;
  244. However, those doesn't work properly K.Okamoto
  245. */
  246. vga->crt[0x41] = (vga->crt[0x13]>>8) & 0x0F; //dhog
  247. /* Horizontal Total */
  248. vga->crt[0] = ((vga->mode->ht>>3)-6) & 0xFF;
  249. /* Extended Horizontal Total Time Reg (ht) */
  250. vga->crt[0x35] = vga->mode->ht>>12 & 0x01;
  251. // vga->crt[0x35] = (((vga->mode->ht>>1)-5)>>8) & 0x01; //dhog
  252. /* Horizontal Display Enable End == horizontal width */
  253. vga->crt[1] = (vga->virtx-1)>>3 & 0xFF;
  254. /* Horizontal Blanking Start */
  255. vga->crt[2] = ((vga->mode->shb>>3)-1) & 0xFF;
  256. /* Horizontal blanking End crt[39](0),crt[5](7),crt[3](4:0) */
  257. vga->crt[3] = (vga->mode->shb - vga->virtx)>>3 & 0x1F;
  258. vga->crt[5] = ((vga->mode->shb - vga->virtx)>>3 & 0x20) <<2;
  259. vga->crt[0x39] = ((vga->mode->shb - vga->virtx)>>3 & 0x40) >>6;
  260. // vga->crt[0x39] = (vga->mode->ehb>>9) & 0x01; //dhog
  261. /* Horizontal Sync Start */
  262. vga->crt[4] = vga->mode->shb>>3 & 0xFF;
  263. /* Horizontal Sync End */
  264. vga->crt[5] |= vga->mode->ehb>>3 & 0x1F;
  265. /* Extended Vertical Total (vt) */
  266. vga->crt[6] = (vt - 2) & 0xFF;
  267. vga->crt[0x30] = (vt - 2)>>8 & 0x0F;
  268. /* Vertical Sync Period */
  269. vga->crt[0x11] = (vre - vrs - 2) & 0x0F;
  270. /* Vertical Blanking End */
  271. vga->crt[0x16] = (vre - vrs) & 0xFF;
  272. /* Extended Vertical Display End (y) */
  273. vga->crt[0x12] = (vde-1) & 0xFF;
  274. vga->crt[0x31] = (vde-1)>>8 & 0x0f;
  275. /* Extended Vertical Sync Start (vrs) */
  276. vga->crt[0x10] = (vrs-1) & 0xFF;
  277. vga->crt[0x32] = (vrs-1)>>8 & 0x0F;
  278. /* Extended Vertical Blanking Start (vrs) */
  279. vga->crt[0x15] = vrs & 0xFF;
  280. vga->crt[0x33] = vrs>>8 & 0x0F;
  281. if(vga->mode->interlace == 'v')
  282. vga->crt[0x70] = vrs | 0x80;
  283. else
  284. vga->crt[0x70] = 0;
  285. vga->crt[0x80] = 1;
  286. ctlr->flag |= Finit;
  287. }
  288. static void
  289. load(Vga* vga, Ctlr* ctlr)
  290. {
  291. int i;
  292. ulong *rp;
  293. I81x *i81x;
  294. char *p;
  295. i81x = vga->private;
  296. vgaxo(Attrx, 0x11, vga->attribute[0x11]);
  297. /* set the screen graphic mode */
  298. vgaxo(Crtx, 0x80, vga->crt[0x80]);
  299. vgaxo(Grx, 0x10, vga->graphics[0x10]);
  300. vgao(MiscW, vga->misc);
  301. for(i=0; i <= 0x18; i++)
  302. vgaxo(Crtx, i, vga->crt[i]);
  303. for(i=0x30; i <= 0x82; i++)
  304. vgaxo(Crtx, i, vga->crt[i]);
  305. vga->crt[0x40] |= 0x80; /* set CR40, then set the MSB bit of it */
  306. vgaxo(Crtx, 0x40, vga->crt[0x40]);
  307. /* 0x06000 = offset of Vertical Clock Devisor VGA0 */
  308. rp = (ulong*)(i81x->mmio+0x06000);
  309. for(i=0; i < nelem(i81x->clk); i++)
  310. *rp++ = i81x->clk[i];
  311. rp = (ulong*)(i81x->mmio+0x60000);
  312. for(i = 0; i < nelem(i81x->lcd); i++)
  313. *rp++ = i81x->lcd[i];
  314. /* set cursor, graphic mode */
  315. rp = (ulong*)(i81x->mmio+0x70008);
  316. *rp = i81x->pixconf | (1<<8);
  317. p = (char*)(i81x->mmio+Pixmask); /* DACMASK */
  318. *p = 0xff;
  319. p = (char*)(i81x->mmio+PaddrW); /* DACWX */
  320. *p = 0x04;
  321. p = (char*)(i81x->mmio+Pdata); /* DACDATA */
  322. *p = 0xff;
  323. *p = 0xff;
  324. *p = 0xff;
  325. *p = 0x00;
  326. *p = 0x00;
  327. *p = 0x00;
  328. *rp = i81x->pixconf;
  329. ctlr->flag |= Fload;
  330. }
  331. static void
  332. dump(Vga* vga, Ctlr* ctlr)
  333. {
  334. int i;
  335. Pcidev *p;
  336. I81x *i81x;
  337. char *name;
  338. name = ctlr->name;
  339. i81x = vga->private;
  340. printitem(name, "Crt30");
  341. for(i = 0x30; i <= 0x39; i++)
  342. printreg(vga->crt[i]);
  343. printitem(name, "Crt40");
  344. for(i = 0x40; i <= 0x42; i++)
  345. printreg(vga->crt[i]);
  346. printitem(name, "Crt70");
  347. for(i = 0x70; i <= 0x79; i++)
  348. printreg(vga->crt[i]);
  349. printitem(name, "Crt80");
  350. for(i = 0x80; i <= 0x82; i++)
  351. printreg(vga->crt[i]);
  352. printitem(name, "Graphics10");
  353. for(i = 0x10; i <= 0x1f; i++)
  354. printreg(vga->graphics[i]);
  355. printitem(name, "clk");
  356. for(i = 0; i < nelem(i81x->clk); i++)
  357. printreg(i81x->clk[i]);
  358. printitem(name, "lcd");
  359. for(i = 0; i < nelem(i81x->lcd); i++)
  360. printreg(i81x->lcd[i]);
  361. printitem(name, "pixconf");
  362. printreg(i81x->pixconf);
  363. p = i81x->pci;
  364. printitem(name, "mem[0]");
  365. Bprint(&stdout, "base %lux size %d\n", p->mem[0].bar & ~0x0F, p->mem[0].size);
  366. printitem(name, "mem[1]");
  367. Bprint(&stdout, "base %lux size %d\n", p->mem[1].bar & ~0x0F, p->mem[1].size);
  368. }
  369. Ctlr i81x = {
  370. "i81x", /* name */
  371. snarf, /* snarf */
  372. options, /* options */
  373. init, /* init */
  374. load, /* load */
  375. dump, /* dump */
  376. };
  377. Ctlr i81xhwgc = {
  378. "i81xhwgc", /* name */
  379. 0, /* snarf */
  380. 0, /* options */
  381. 0, /* init */
  382. 0, /* load */
  383. 0, /* dump */
  384. };