vgaet4000.c 5.0 KB

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