mach32.c 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  1. #include <u.h>
  2. #include <libc.h>
  3. #include <bio.h>
  4. #include "pci.h"
  5. #include "vga.h"
  6. /*
  7. * ATI Mach32. Some hope.
  8. * No support for accelerator so can only do up to 1024x768.
  9. *
  10. * All ATI Extended Registers are addressed using the modified index
  11. * index = (0x02<<6)|(index & 0x3F);
  12. * so registers 0x00->0x3F map to 0x80->0xBF, but we will only ever
  13. * look at a few in the range 0xA0->0xBF. In this way we can stash
  14. * them in the vga->crt[] array.
  15. */
  16. enum {
  17. Advfunc = 0x4AE8, /* Advanced Function Control Register */
  18. Clocksel = 0x4AEE, /* Clock Select Register */
  19. Misc = 0x36EE, /* Miscellaneous Register */
  20. Membndry = 0x42EE, /* Memory Boundary Register */
  21. Memcfg = 0x5EEE, /* Memory Control Register */
  22. };
  23. typedef struct {
  24. ushort advfunc;
  25. ushort clocksel;
  26. ushort misc;
  27. ushort membndry;
  28. ushort memcfg;
  29. } Mach32;
  30. /*
  31. * There are a number of possible clock generator chips for these
  32. * boards, and I don't know how to find out which is installed, other
  33. * than by looking at the board. So, pick a subset that will work for
  34. * all.
  35. */
  36. typedef struct {
  37. ulong frequency;
  38. uchar b8; /* <6> - divide by 2 */
  39. uchar b9; /* <1> - bit <3> of frequency index */
  40. uchar be; /* <4> - bit <2> of frequency index */
  41. uchar misc; /* <3:2> - bits <1:0> of frequency index */
  42. } Clock;
  43. static Clock clocks[] = {
  44. { VgaFreq0, 0x40, 0x02, 0x00, 0x00, },
  45. { 32000000, 0x00, 0x00, 0x10, 0x04, },
  46. { 40000000, 0x00, 0x02, 0x10, 0x00, },
  47. { 44900000, 0x00, 0x02, 0x00, 0x0C, },
  48. { 65000000, 0x00, 0x02, 0x10, 0x0C, },
  49. { 75000000, 0x00, 0x02, 0x10, 0x08, },
  50. { 0, },
  51. };
  52. static ulong atix;
  53. static uchar
  54. atixi(uchar index)
  55. {
  56. outportb(atix, index);
  57. return inportb(atix+1);
  58. }
  59. static void
  60. atixo(uchar index, uchar data)
  61. {
  62. outportw(atix, (data<<8)|index);
  63. }
  64. static void
  65. atixinit(Vga* vga, Ctlr*)
  66. {
  67. uchar b;
  68. Mach32 *mach32;
  69. /*
  70. * We could try to read in a part of the BIOS and try to determine
  71. * the extended register address, but since we can't determine the offset value,
  72. * we'll just have to assume the defaults all round.
  73. */
  74. atix = 0x1CE;
  75. /*
  76. * Unlock the ATI Extended Registers.
  77. * We leave them unlocked from now on.
  78. * Why does this chip have so many
  79. * lock bits?
  80. */
  81. if((b = atixi(0xB8)) & 0x3F)
  82. atixo(0xB8, b & 0xC0);
  83. b = atixi(0xAB);
  84. atixo(0xAB, b & ~0x18);
  85. atixo(0xB4, 0x00);
  86. b = atixi(0xB9);
  87. atixo(0xB9, b & ~0x80);
  88. b = atixi(0xBE);
  89. atixo(0xBE, b|0x09);
  90. if(vga->private == 0)
  91. vga->private = alloc(sizeof(mach32));
  92. }
  93. static void
  94. snarf(Vga* vga, Ctlr* ctlr)
  95. {
  96. int i;
  97. Mach32 *mach32;
  98. atixinit(vga, ctlr);
  99. for(i = 0xA0; i < 0xC0; i++)
  100. vga->crt[i] = atixi(i);
  101. mach32 = vga->private;
  102. mach32->advfunc = inportw(Advfunc);
  103. mach32->clocksel = inportw(Clocksel);
  104. mach32->misc = inportw(Misc);
  105. mach32->membndry = inportw(Membndry);
  106. mach32->memcfg = inportw(Memcfg);
  107. /*
  108. * Memory size.
  109. */
  110. switch((mach32->misc>>2) & 0x03){
  111. case 0:
  112. vga->vmz = 512*1024;
  113. break;
  114. case 1:
  115. vga->vmz = 1024*1024;
  116. break;
  117. case 2:
  118. vga->vmz = 2*1024*1024;
  119. break;
  120. case 3:
  121. vga->vmz = 4*1024*1024;
  122. break;
  123. }
  124. ctlr->flag |= Fsnarf;
  125. }
  126. static void
  127. options(Vga*, Ctlr* ctlr)
  128. {
  129. ctlr->flag |= Foptions;
  130. }
  131. static void
  132. init(Vga* vga, Ctlr* ctlr)
  133. {
  134. Clock *clockp;
  135. Mode *mode;
  136. mode = vga->mode;
  137. if(vga->f[0] == 0)
  138. vga->f[0] = vga->mode->frequency;
  139. for(clockp = clocks; clockp->frequency; clockp++){
  140. if(clockp->frequency > vga->f[0]+100000)
  141. continue;
  142. if(clockp->frequency > vga->f[0]-100000)
  143. break;
  144. }
  145. if(clockp->frequency == 0)
  146. error("%s: no suitable clock for %lud\n",
  147. ctlr->name, vga->f[0]);
  148. vga->crt[0xB0] &= 0xDA;
  149. vga->crt[0xB1] &= 0x87;
  150. vga->crt[0xB5] &= 0x7E;
  151. vga->crt[0xB6] &= 0xE2;
  152. vga->crt[0xB3] &= 0xAF;
  153. vga->crt[0xA6] &= 0xFE;
  154. vga->crt[0xA7] &= 0xF4;
  155. /*
  156. * 256-colour linear addressing.
  157. */
  158. if(mode->z == 8){
  159. vga->graphics[0x05] = 0x00;
  160. vga->attribute[0x10] &= ~0x40;
  161. vga->crt[0x13] = (mode->x/8)/2;
  162. vga->crt[0x14] = 0x00;
  163. vga->crt[0x17] = 0xE3;
  164. vga->crt[0xB0] |= 0x20;
  165. vga->crt[0xB6] |= 0x04;
  166. }
  167. vga->attribute[0x11] = 0x00;
  168. vga->crt[0xB6] |= 0x01;
  169. vga->crt[0xBE] &= ~0x04;
  170. /*
  171. * Do the clock index bits.
  172. */
  173. vga->crt[0xB9] &= 0xFD;
  174. vga->crt[0xB8] &= 0x3F;
  175. vga->crt[0xBE] &= 0xE5;
  176. vga->crt[0xB8] |= clockp->b8;
  177. vga->crt[0xB9] |= clockp->b9;
  178. vga->crt[0xBE] |= clockp->be;
  179. vga->misc |= clockp->misc;
  180. if(vga->mode->interlace == 'v')
  181. vga->crt[0xBE] |= 0x02;
  182. /*
  183. * Turn off 128Kb CPU address bit so
  184. * we only have a 64Kb aperture at 0xA0000.
  185. */
  186. vga->crt[0xBD] &= ~0x04;
  187. ctlr->flag |= Finit;
  188. }
  189. static void
  190. load(Vga* vga, Ctlr* ctlr)
  191. {
  192. ushort x;
  193. /*
  194. * Make sure we are in VGA mode,
  195. * and that we have access to all the video memory through
  196. * the 64Kb VGA aperture by disabling and linear aperture
  197. * and memory boundary.
  198. */
  199. outportw(Clocksel, 0x0000);
  200. x = inportw(Memcfg) & ~0x0003;
  201. outportw(Memcfg, x);
  202. outportw(Membndry, 0x0000);
  203. atixo(0xB0, vga->crt[0xB0]);
  204. atixo(0xB1, vga->crt[0xB1]);
  205. atixo(0xB5, vga->crt[0xB5]);
  206. atixo(0xB6, vga->crt[0xB6]);
  207. atixo(0xB3, vga->crt[0xB3]);
  208. atixo(0xA6, vga->crt[0xA6]);
  209. atixo(0xA7, vga->crt[0xA7]);
  210. atixo(0xB8, vga->crt[0xB8]);
  211. atixo(0xB9, vga->crt[0xB9]);
  212. atixo(0xBE, vga->crt[0xBE]);
  213. vgao(MiscW, vga->misc);
  214. ctlr->flag |= Fload;
  215. }
  216. static void
  217. dump(Vga* vga, Ctlr* ctlr)
  218. {
  219. int i;
  220. Mach32 *mach32;
  221. printitem(ctlr->name, "ATIX");
  222. for(i = 0xA0; i < 0xC0; i++)
  223. printreg(vga->crt[i]);
  224. if((mach32 = vga->private) == 0)
  225. return;
  226. printitem(ctlr->name, "ADVFUNC");
  227. Bprint(&stdout, "%.4ux\n", mach32->advfunc);
  228. printitem(ctlr->name, "CLOCKSEL");
  229. Bprint(&stdout, "%.4ux\n", mach32->clocksel);
  230. printitem(ctlr->name, "MISC");
  231. Bprint(&stdout, "%.4ux\n", mach32->misc);
  232. printitem(ctlr->name, "MEMBNDRY");
  233. Bprint(&stdout, "%.4ux\n", mach32->membndry);
  234. printitem(ctlr->name, "MEMCFG");
  235. Bprint(&stdout, "%.4ux\n", mach32->memcfg);
  236. }
  237. Ctlr mach32 = {
  238. "mach32", /* name */
  239. snarf, /* snarf */
  240. options, /* options */
  241. init, /* init */
  242. load, /* load */
  243. dump, /* dump */
  244. };