vgaet4000.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270
  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. static void
  13. setet4000page(int page)
  14. {
  15. uchar p;
  16. p = page & 0x0F;
  17. p |= p<<4;
  18. outb(0x3CD, p);
  19. p = (page & 0x30);
  20. p |= p>>4;
  21. outb(0x3CB, p);
  22. }
  23. static void
  24. et4000page(VGAscr *scr, int page)
  25. {
  26. lock(&scr->devlock);
  27. setet4000page(page);
  28. unlock(&scr->devlock);
  29. }
  30. static void
  31. et4000disable(VGAscr*)
  32. {
  33. uchar imaF7;
  34. outb(0x217A, 0xF7);
  35. imaF7 = inb(0x217B) & ~0x80;
  36. outb(0x217B, imaF7);
  37. }
  38. static void
  39. et4000enable(VGAscr *scr)
  40. {
  41. uchar imaF7;
  42. et4000disable(scr);
  43. /*
  44. * Configure CRTCB for Sprite, 64x64,
  45. * CRTC pixel overlay.
  46. */
  47. outb(0x217A, 0xEF);
  48. outb(0x217B, 0x02);
  49. /*
  50. * Cursor goes in the top left corner
  51. * of the Sprite area, so the horizontal and
  52. * vertical presets are 0.
  53. */
  54. outb(0x217A, 0xE2);
  55. outb(0x217B, 0x00);
  56. outb(0x217A, 0xE3);
  57. outb(0x217B, 0x00);
  58. outb(0x217A, 0xE6);
  59. outb(0x217B, 0x00);
  60. outb(0x217A, 0xE7);
  61. outb(0x217B, 0x00);
  62. /*
  63. * Find a place for the cursor data in display memory.
  64. * Must be on a "doubleword" boundary, but put it on a
  65. * 1024-byte boundary so that there's no danger of it
  66. * crossing a page.
  67. */
  68. scr->storage = (scr->gscreen->width*BY2WD*scr->gscreen->r.max.y+1023)/1024;
  69. scr->storage *= 1024/4;
  70. outb(0x217A, 0xE8);
  71. outb(0x217B, scr->storage & 0xFF);
  72. outb(0x217A, 0xE9);
  73. outb(0x217B, (scr->storage>>8) & 0xFF);
  74. outb(0x217A, 0xEA);
  75. outb(0x217B, (scr->storage>>16) & 0x0F);
  76. scr->storage *= 4;
  77. /*
  78. * Row offset in "quadwords". Must be 2 for Sprite.
  79. * Bag the pixel-panning.
  80. * Colour depth, must be 2 for Sprite.
  81. */
  82. outb(0x217A, 0xEB);
  83. outb(0x217B, 0x02);
  84. outb(0x217A, 0xEC);
  85. outb(0x217B, 0x00);
  86. outb(0x217A, 0xED);
  87. outb(0x217B, 0x00);
  88. outb(0x217A, 0xEE);
  89. // if(vgascreen.ldepth == 3)
  90. outb(0x217B, 0x01);
  91. // else
  92. // outb(0x217B, 0x00);
  93. /*
  94. * Enable the CRTCB/Sprite.
  95. */
  96. outb(0x217A, 0xF7);
  97. imaF7 = inb(0x217B);
  98. outb(0x217B, 0x80|imaF7);
  99. }
  100. static void
  101. et4000load(VGAscr *scr, Cursor *c)
  102. {
  103. uchar p0, p1, *mem;
  104. int i, x, y;
  105. ushort p;
  106. uchar clr[2*16], set[2*16];
  107. /*
  108. * Lock the display memory so we can update the
  109. * cursor bitmap if necessary.
  110. */
  111. lock(&scr->devlock);
  112. /*
  113. * Disable the cursor.
  114. * Set the display page (do we need to restore
  115. * the current contents when done?) and the
  116. * pointer to the two planes. What if this crosses
  117. * into a new page?
  118. */
  119. et4000disable(scr);
  120. setet4000page(scr->storage>>16);
  121. mem = (uchar*)KADDR(scr->aperture) + (scr->storage & 0xFFFF);
  122. /*
  123. * Initialise the 64x64 cursor RAM array. There are 2 planes,
  124. * p0 and p1. Data is written 4 pixels per byte, with p1 the
  125. * MS bit of each pixel.
  126. * The cursor mode gives the following truth table:
  127. * p1 p0 colour
  128. * 0 0 Sprite Colour 0 (defined as 0x00)
  129. * 0 1 Sprite Colour 1 (defined as 0xFF)
  130. * 1 0 Transparent (allow CRTC pixel pass through)
  131. * 1 1 Invert (allow CRTC pixel invert through)
  132. * Put the cursor into the top-left of the 64x64 array.
  133. *
  134. * This is almost certainly wrong, since it has not
  135. * been updated for the 3rd edition color values.
  136. */
  137. memmove(clr, c->clr, sizeof(clr));
  138. // pixreverse(clr, sizeof(clr), 0);
  139. memmove(set, c->set, sizeof(set));
  140. // pixreverse(set, sizeof(set), 0);
  141. for(y = 0; y < 64; y++){
  142. for(x = 0; x < 64/8; x++){
  143. if(x < 16/8 && y < 16){
  144. p0 = clr[x+y*2];
  145. p1 = set[x+y*2];
  146. p = 0x0000;
  147. for(i = 0; i < 8; i++){
  148. if(p1 & (1<<(7-i))){
  149. /* nothing to do */
  150. }
  151. else if(p0 & (1<<(7-i)))
  152. p |= 0x01<<(2*i);
  153. else
  154. p |= 0x02<<(2*i);
  155. }
  156. *mem++ = p & 0xFF;
  157. *mem++ = (p>>8) & 0xFF;
  158. }
  159. else {
  160. *mem++ = 0xAA;
  161. *mem++ = 0xAA;
  162. }
  163. }
  164. }
  165. /*
  166. * enable the cursor.
  167. */
  168. outb(0x217A, 0xF7);
  169. p = inb(0x217B)|0x80;
  170. outb(0x217B, p);
  171. unlock(&scr->devlock);
  172. }
  173. static int
  174. et4000move(VGAscr *scr, Point p)
  175. {
  176. int x, xo, y, yo;
  177. if(canlock(&scr->devlock) == 0)
  178. return 1;
  179. /*
  180. * Mustn't position the cursor offscreen even partially,
  181. * or it disappears. Therefore, if x or y is -ve, adjust the
  182. * cursor presets instead.
  183. */
  184. if((x = p.x+scr->offset.x) < 0){
  185. xo = -x;
  186. x = 0;
  187. }
  188. else
  189. xo = 0;
  190. if((y = p.y+scr->offset.y) < 0){
  191. yo = -y;
  192. y = 0;
  193. }
  194. else
  195. yo = 0;
  196. /*
  197. * The cursor image is jerky if we don't do this.
  198. * The cursor information is probably fetched from
  199. * display memory during the horizontal blank active
  200. * time and it doesn't like it if the coordinates
  201. * are changed underneath.
  202. */
  203. while((vgai(Status1) & 0x08) == 0)
  204. ;
  205. outb(0x217A, 0xE2);
  206. outb(0x217B, xo);
  207. outb(0x217A, 0xE6);
  208. outb(0x217B, yo);
  209. outb(0x217A, 0xE1);
  210. outb(0x217B, (x>>8) & 0xFF);
  211. outb(0x217A, 0xE0);
  212. outb(0x217B, x & 0xFF);
  213. outb(0x217A, 0xE5);
  214. outb(0x217B, (y>>8) & 0xFF);
  215. outb(0x217A, 0xE4);
  216. outb(0x217B, y & 0xFF);
  217. unlock(&scr->devlock);
  218. return 0;
  219. }
  220. VGAcur vgaet4000cur = {
  221. "et4000hwgc",
  222. et4000enable,
  223. et4000disable,
  224. et4000load,
  225. et4000move,
  226. };
  227. VGAdev vgaet4000dev = {
  228. "et4000",
  229. 0,
  230. 0,
  231. et4000page,
  232. 0
  233. };