vga3dfx.c 4.8 KB

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