vga3dfx.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258
  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. typedef struct {
  14. int vidProcCfg;
  15. int hwCurPatAddr;
  16. int hwCurLoc;
  17. int hwCurC0;
  18. int hwCurC1;
  19. } Cursor3dfx;
  20. enum {
  21. dramInit0 = 0x18,
  22. dramInit1 = 0x1C,
  23. hwCur = 0x5C,
  24. };
  25. static ulong
  26. tdfxlinear(VGAscr* scr, int* size, int* align)
  27. {
  28. Pcidev *p;
  29. int oapsize, wasupamem;
  30. ulong aperture, oaperture;
  31. oaperture = scr->aperture;
  32. oapsize = scr->apsize;
  33. wasupamem = scr->isupamem;
  34. aperture = 0;
  35. if(p = pcimatch(nil, 0x121A, 0)){
  36. switch(p->did){
  37. case 0x0003: /* Banshee */
  38. case 0x0005: /* Avenger (a.k.a. Voodoo3) */
  39. case 0x0009: /* Voodoo5 */
  40. aperture = p->mem[1].bar & ~0x0F;
  41. *size = p->mem[1].size;
  42. break;
  43. default:
  44. break;
  45. }
  46. }
  47. if(wasupamem){
  48. if(oaperture == aperture)
  49. return oaperture;
  50. upafree(oaperture, oapsize);
  51. }
  52. scr->isupamem = 0;
  53. aperture = upamalloc(aperture, *size, *align);
  54. if(aperture == 0){
  55. if(wasupamem && upamalloc(oaperture, oapsize, 0)){
  56. aperture = oaperture;
  57. scr->isupamem = 1;
  58. }
  59. else
  60. scr->isupamem = 0;
  61. }
  62. else
  63. scr->isupamem = 1;
  64. return aperture;
  65. }
  66. static void
  67. tdfxenable(VGAscr* scr)
  68. {
  69. Pcidev *p;
  70. ulong aperture;
  71. int align, i, *mmio, size;
  72. /*
  73. * Only once, can't be disabled for now.
  74. * scr->io holds the physical address of
  75. * the MMIO registers.
  76. */
  77. if(scr->io)
  78. return;
  79. if(p = pcimatch(nil, 0x121A, 0)){
  80. switch(p->did){
  81. case 0x0003: /* Banshee */
  82. case 0x0005: /* Avenger (a.k.a. Voodoo3) */
  83. break;
  84. default:
  85. return;
  86. }
  87. }
  88. else
  89. return;
  90. scr->io = upamalloc(p->mem[0].bar & ~0x0F, p->mem[0].size, 0);
  91. if(scr->io == 0)
  92. return;
  93. addvgaseg("3dfxmmio", (ulong)scr->io, p->mem[0].size);
  94. size = p->mem[1].size;
  95. align = 0;
  96. aperture = tdfxlinear(scr, &size, &align);
  97. if(aperture){
  98. scr->aperture = aperture;
  99. scr->apsize = size;
  100. addvgaseg("3dfxscreen", aperture, size);
  101. }
  102. /*
  103. * Find a place for the cursor data in display memory.
  104. * If SDRAM then there's 16MB memory else it's SGRAM
  105. * and can count it based on the power-on straps -
  106. * chip size can be 8Mb or 16Mb, and there can be 4 or
  107. * 8 of them.
  108. * Use the last 1KB of the framebuffer.
  109. */
  110. mmio = KADDR(scr->io + dramInit0);
  111. if(*(mmio+1) & 0x40000000)
  112. i = 16*1024*1024;
  113. else{
  114. if(*mmio & 0x08000000)
  115. i = 16*1024*1024/8;
  116. else
  117. i = 8*1024*1024/8;
  118. if(*mmio & 0x04000000)
  119. i *= 8;
  120. else
  121. i *= 4;
  122. }
  123. scr->storage = i - 1024;
  124. }
  125. static void
  126. tdfxcurdisable(VGAscr* scr)
  127. {
  128. Cursor3dfx *cursor3dfx;
  129. if(scr->io == 0)
  130. return;
  131. cursor3dfx = KADDR(scr->io+hwCur);
  132. cursor3dfx->vidProcCfg &= ~0x08000000;
  133. }
  134. static void
  135. tdfxcurload(VGAscr* scr, Cursor* curs)
  136. {
  137. int y;
  138. uchar *p;
  139. Cursor3dfx *cursor3dfx;
  140. if(scr->io == 0)
  141. return;
  142. cursor3dfx = KADDR(scr->io+hwCur);
  143. /*
  144. * Disable the cursor then load the new image in
  145. * the top-left of the 64x64 array.
  146. * The cursor data is stored in memory as 128-bit
  147. * words consisting of plane 0 in the least significant 64-bits
  148. * and plane 1 in the most significant.
  149. * The X11 cursor truth table is:
  150. * p0 p1 colour
  151. * 0 0 transparent
  152. * 0 1 transparent
  153. * 1 0 hwCurC0
  154. * 1 1 hwCurC1
  155. * Unused portions of the image have been initialised to be
  156. * transparent.
  157. */
  158. cursor3dfx->vidProcCfg &= ~0x08000000;
  159. p = KADDR(scr->aperture + scr->storage);
  160. for(y = 0; y < 16; y++){
  161. *p++ = curs->clr[2*y]|curs->set[2*y];
  162. *p++ = curs->clr[2*y+1]|curs->set[2*y+1];
  163. p += 6;
  164. *p++ = curs->set[2*y];
  165. *p++ = curs->set[2*y+1];
  166. p += 6;
  167. }
  168. /*
  169. * Save the cursor hotpoint and enable the cursor.
  170. * The 0,0 cursor point is bottom-right.
  171. */
  172. scr->offset.x = 63+curs->offset.x;
  173. scr->offset.y = 63+curs->offset.y;
  174. cursor3dfx->vidProcCfg |= 0x08000000;
  175. }
  176. static int
  177. tdfxcurmove(VGAscr* scr, Point p)
  178. {
  179. Cursor3dfx *cursor3dfx;
  180. if(scr->io == 0)
  181. return 1;
  182. cursor3dfx = KADDR(scr->io+hwCur);
  183. cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
  184. return 0;
  185. }
  186. static void
  187. tdfxcurenable(VGAscr* scr)
  188. {
  189. Cursor3dfx *cursor3dfx;
  190. tdfxenable(scr);
  191. if(scr->io == 0)
  192. return;
  193. cursor3dfx = KADDR(scr->io+hwCur);
  194. /*
  195. * Cursor colours.
  196. */
  197. cursor3dfx->hwCurC0 = 0xFFFFFFFF;
  198. cursor3dfx->hwCurC1 = 0x00000000;
  199. /*
  200. * Initialise the 64x64 cursor to be transparent (X11 mode).
  201. */
  202. cursor3dfx->hwCurPatAddr = scr->storage;
  203. memset(KADDR(scr->aperture + scr->storage), 0, 64*16);
  204. /*
  205. * Load, locate and enable the 64x64 cursor in X11 mode.
  206. */
  207. tdfxcurload(scr, &arrow);
  208. tdfxcurmove(scr, ZP);
  209. cursor3dfx->vidProcCfg |= 0x08000002;
  210. }
  211. VGAdev vga3dfxdev = {
  212. "3dfx",
  213. tdfxenable,
  214. nil,
  215. nil,
  216. tdfxlinear,
  217. };
  218. VGAcur vga3dfxcur = {
  219. "3dfxhwgc",
  220. tdfxcurenable,
  221. tdfxcurdisable,
  222. tdfxcurload,
  223. tdfxcurmove,
  224. };