vgabt485.c 4.9 KB

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