vgabt485.c 4.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246
  1. #include "u.h"
  2. #include "../port/lib.h"
  3. #include "mem.h"
  4. #include "dat.h"
  5. #include "fns.h"
  6. #include "io.h"
  7. #include "../port/error.h"
  8. #define Image IMAGE
  9. #include <draw.h>
  10. #include <memdraw.h>
  11. #include <cursor.h>
  12. #include "screen.h"
  13. /*
  14. * Hardware graphics cursor support for
  15. * Brooktree Bt485 Monolithic True-Color RAMDAC.
  16. * Assumes hooked up to an S3 86C928.
  17. *
  18. * BUGS:
  19. * 64x64x2 cursor always used;
  20. * no support for interlaced mode.
  21. */
  22. enum {
  23. AddrW = 0x00, /* Address register; palette/cursor RAM write */
  24. Palette = 0x01, /* 6/8-bit color palette data */
  25. Pmask = 0x02, /* Pixel mask register */
  26. AddrR = 0x03, /* Address register; palette/cursor RAM read */
  27. ColorW = 0x04, /* Address register; cursor/overscan color write */
  28. Color = 0x05, /* Cursor/overscan color data */
  29. Cmd0 = 0x06, /* Command register 0 */
  30. ColorR = 0x07, /* Address register; cursor/overscan color read */
  31. Cmd1 = 0x08, /* Command register 1 */
  32. Cmd2 = 0x09, /* Command register 2 */
  33. Status = 0x0A, /* Status */
  34. Cmd3 = 0x1A, /* Command register 3 */
  35. Cram = 0x0B, /* Cursor RAM array data */
  36. Cxlr = 0x0C, /* Cursor x-low register */
  37. Cxhr = 0x0D, /* Cursor x-high register */
  38. Cylr = 0x0E, /* Cursor y-low register */
  39. Cyhr = 0x0F, /* Cursor y-high register */
  40. Nreg = 0x10,
  41. };
  42. /*
  43. * Lower 2-bits of indirect DAC register
  44. * addressing.
  45. */
  46. static ushort dacxreg[4] = {
  47. PaddrW, Pdata, Pixmask, PaddrR
  48. };
  49. static uchar
  50. bt485io(uchar reg)
  51. {
  52. uchar crt55, cr0;
  53. crt55 = vgaxi(Crtx, 0x55) & 0xFC;
  54. if((reg & 0x0F) == Status){
  55. /*
  56. * 1,2: Set indirect addressing for Status or
  57. * Cmd3 - set bit7 of Cr0.
  58. */
  59. vgaxo(Crtx, 0x55, crt55|((Cmd0>>2) & 0x03));
  60. cr0 = vgai(dacxreg[Cmd0 & 0x03])|0x80;
  61. vgao(dacxreg[Cmd0 & 0x03], cr0);
  62. /*
  63. * 3,4: Set the index into the Write register,
  64. * index == 0x00 for Status, 0x01 for Cmd3.
  65. */
  66. vgaxo(Crtx, 0x55, crt55|((AddrW>>2) & 0x03));
  67. vgao(dacxreg[AddrW & 0x03], (reg == Status) ? 0x00: 0x01);
  68. /*
  69. * 5,6: Get the contents of the appropriate
  70. * register at 0x0A.
  71. */
  72. }
  73. return crt55;
  74. }
  75. static uchar
  76. bt485i(uchar reg)
  77. {
  78. uchar crt55, r;
  79. crt55 = bt485io(reg);
  80. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  81. r = vgai(dacxreg[reg & 0x03]);
  82. vgaxo(Crtx, 0x55, crt55);
  83. return r;
  84. }
  85. static void
  86. bt485o(uchar reg, uchar data)
  87. {
  88. uchar crt55;
  89. crt55 = bt485io(reg);
  90. vgaxo(Crtx, 0x55, crt55|((reg>>2) & 0x03));
  91. vgao(dacxreg[reg & 0x03], data);
  92. vgaxo(Crtx, 0x55, crt55);
  93. }
  94. static void
  95. bt485disable(VGAscr*)
  96. {
  97. uchar r;
  98. /*
  99. * Disable
  100. * cursor mode 3;
  101. * cursor control enable for Bt485 DAC;
  102. * the hardware cursor external operation mode.
  103. */
  104. r = bt485i(Cmd2) & ~0x03;
  105. bt485o(Cmd2, r);
  106. r = vgaxi(Crtx, 0x45) & ~0x20;
  107. vgaxo(Crtx, 0x45, r);
  108. r = vgaxi(Crtx, 0x55) & ~0x20;
  109. vgaxo(Crtx, 0x55, r);
  110. }
  111. static void
  112. bt485enable(VGAscr*)
  113. {
  114. uchar r;
  115. /*
  116. * Turn cursor off.
  117. */
  118. r = bt485i(Cmd2) & 0xFC;
  119. bt485o(Cmd2, r);
  120. /*
  121. * Overscan colour,
  122. * cursor colour 1 (white),
  123. * cursor colour 2, 3 (black).
  124. */
  125. bt485o(ColorW, 0x00);
  126. bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
  127. bt485o(Color, Pwhite); bt485o(Color, Pwhite); bt485o(Color, Pwhite);
  128. bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
  129. bt485o(Color, Pblack); bt485o(Color, Pblack); bt485o(Color, Pblack);
  130. /*
  131. * Finally, enable
  132. * the hardware cursor external operation mode;
  133. * cursor control enable for Bt485 DAC.
  134. * The #9GXE cards seem to need the 86C928 Bt485 support
  135. * enabled in order to work at all in enhanced mode.
  136. */
  137. r = vgaxi(Crtx, 0x55)|0x20;
  138. vgaxo(Crtx, 0x55, r);
  139. r = vgaxi(Crtx, 0x45)|0x20;
  140. vgaxo(Crtx, 0x45, r);
  141. }
  142. static void
  143. bt485load(VGAscr* scr, Cursor* curs)
  144. {
  145. uchar r;
  146. int x, y;
  147. /*
  148. * Turn cursor off;
  149. * put cursor into 64x64x2 mode and clear MSBs of address;
  150. * clear LSBs of address;
  151. */
  152. r = bt485i(Cmd2) & 0xFC;
  153. bt485o(Cmd2, r);
  154. r = (bt485i(Cmd3) & 0xFC)|0x04;
  155. bt485o(Cmd3, r);
  156. bt485o(AddrW, 0x00);
  157. /*
  158. * Now load the cursor RAM array, both planes.
  159. * The cursor is 16x16, the array 64x64; put
  160. * the cursor in the top left. The 0,0 cursor
  161. * point is bottom-right, so positioning will
  162. * have to take that into account.
  163. */
  164. for(y = 0; y < 64; y++){
  165. for(x = 0; x < 64/8; x++){
  166. if(x < 16/8 && y < 16)
  167. bt485o(Cram, curs->clr[x+y*2]);
  168. else
  169. bt485o(Cram, 0x00);
  170. }
  171. }
  172. for(y = 0; y < 64; y++){
  173. for(x = 0; x < 64/8; x++){
  174. if(x < 16/8 && y < 16)
  175. bt485o(Cram, curs->set[x+y*2]);
  176. else
  177. bt485o(Cram, 0x00);
  178. }
  179. }
  180. /*
  181. * Initialise the cursor hot-point
  182. * and enable the cursor.
  183. */
  184. scr->offset.x = 64+curs->offset.x;
  185. scr->offset.y = 64+curs->offset.y;
  186. r = (bt485i(Cmd2) & 0xFC)|0x01;
  187. bt485o(Cmd2, r);
  188. }
  189. static int
  190. bt485move(VGAscr* scr, Point p)
  191. {
  192. int x, y;
  193. x = p.x+scr->offset.x;
  194. y = p.y+scr->offset.y;
  195. bt485o(Cxlr, x & 0xFF);
  196. bt485o(Cxhr, (x>>8) & 0x0F);
  197. bt485o(Cylr, y & 0xFF);
  198. bt485o(Cyhr, (y>>8) & 0x0F);
  199. return 0;
  200. }
  201. VGAcur vgabt485cur = {
  202. "bt485hwgc",
  203. bt485enable,
  204. bt485disable,
  205. bt485load,
  206. bt485move,
  207. };