vga3dfx.c 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  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 void
  27. tdfxenable(VGAscr* scr)
  28. {
  29. Pcidev *p;
  30. int i, *mmio;
  31. if(scr->mmio)
  32. return;
  33. if(p = pcimatch(nil, 0x121A, 0)){
  34. switch(p->did){
  35. case 0x0003: /* Banshee */
  36. case 0x0005: /* Avenger (a.k.a. Voodoo3) */
  37. break;
  38. default:
  39. return;
  40. }
  41. }
  42. else
  43. return;
  44. scr->mmio = vmap(p->mem[0].bar&~0x0F, p->mem[0].size);
  45. if(scr->mmio == nil)
  46. return;
  47. scr->pci = p;
  48. addvgaseg("3dfxmmio", p->mem[0].bar&~0x0F, p->mem[0].size);
  49. vgalinearpci(scr);
  50. if(scr->apsize)
  51. addvgaseg("3dfxscreen", scr->paddr, scr->apsize);
  52. /*
  53. * Find a place for the cursor data in display memory.
  54. * If SDRAM then there's 16MB memory else it's SGRAM
  55. * and can count it based on the power-on straps -
  56. * chip size can be 8Mb or 16Mb, and there can be 4 or
  57. * 8 of them.
  58. * Use the last 1KB of the framebuffer.
  59. */
  60. mmio = (void*)((uchar*)scr->mmio+dramInit0);
  61. if(*(mmio+1) & 0x40000000)
  62. i = 16*1024*1024;
  63. else{
  64. if(*mmio & 0x08000000)
  65. i = 16*1024*1024/8;
  66. else
  67. i = 8*1024*1024/8;
  68. if(*mmio & 0x04000000)
  69. i *= 8;
  70. else
  71. i *= 4;
  72. }
  73. scr->storage = i - 1024;
  74. }
  75. static void
  76. tdfxcurdisable(VGAscr* scr)
  77. {
  78. Cursor3dfx *cursor3dfx;
  79. if(scr->mmio == 0)
  80. return;
  81. cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
  82. cursor3dfx->vidProcCfg &= ~0x08000000;
  83. }
  84. static void
  85. tdfxcurload(VGAscr* scr, Cursor* curs)
  86. {
  87. int y;
  88. uchar *p;
  89. Cursor3dfx *cursor3dfx;
  90. if(scr->mmio == 0)
  91. return;
  92. cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
  93. /*
  94. * Disable the cursor then load the new image in
  95. * the top-left of the 64x64 array.
  96. * The cursor data is stored in memory as 128-bit
  97. * words consisting of plane 0 in the least significant 64-bits
  98. * and plane 1 in the most significant.
  99. * The X11 cursor truth table is:
  100. * p0 p1 colour
  101. * 0 0 transparent
  102. * 0 1 transparent
  103. * 1 0 hwCurC0
  104. * 1 1 hwCurC1
  105. * Unused portions of the image have been initialised to be
  106. * transparent.
  107. */
  108. cursor3dfx->vidProcCfg &= ~0x08000000;
  109. p = (uchar*)scr->vaddr + scr->storage;
  110. for(y = 0; y < 16; y++){
  111. *p++ = curs->clr[2*y]|curs->set[2*y];
  112. *p++ = curs->clr[2*y+1]|curs->set[2*y+1];
  113. p += 6;
  114. *p++ = curs->set[2*y];
  115. *p++ = curs->set[2*y+1];
  116. p += 6;
  117. }
  118. /*
  119. * Save the cursor hotpoint and enable the cursor.
  120. * The 0,0 cursor point is bottom-right.
  121. */
  122. scr->offset.x = 63+curs->offset.x;
  123. scr->offset.y = 63+curs->offset.y;
  124. cursor3dfx->vidProcCfg |= 0x08000000;
  125. }
  126. static int
  127. tdfxcurmove(VGAscr* scr, Point p)
  128. {
  129. Cursor3dfx *cursor3dfx;
  130. if(scr->mmio == 0)
  131. return 1;
  132. cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
  133. cursor3dfx->hwCurLoc = ((p.y+scr->offset.y)<<16)|(p.x+scr->offset.x);
  134. return 0;
  135. }
  136. static void
  137. tdfxcurenable(VGAscr* scr)
  138. {
  139. Cursor3dfx *cursor3dfx;
  140. tdfxenable(scr);
  141. if(scr->mmio == 0)
  142. return;
  143. cursor3dfx = (void*)((uchar*)scr->mmio+hwCur);
  144. /*
  145. * Cursor colours.
  146. */
  147. cursor3dfx->hwCurC0 = 0xFFFFFFFF;
  148. cursor3dfx->hwCurC1 = 0x00000000;
  149. /*
  150. * Initialise the 64x64 cursor to be transparent (X11 mode).
  151. */
  152. cursor3dfx->hwCurPatAddr = scr->storage;
  153. memset((uchar*)scr->vaddr + scr->storage, 0, 64*16);
  154. /*
  155. * Load, locate and enable the 64x64 cursor in X11 mode.
  156. */
  157. tdfxcurload(scr, &arrow);
  158. tdfxcurmove(scr, ZP);
  159. cursor3dfx->vidProcCfg |= 0x08000002;
  160. }
  161. VGAdev vga3dfxdev = {
  162. "3dfx",
  163. tdfxenable,
  164. nil,
  165. nil,
  166. nil,
  167. };
  168. VGAcur vga3dfxcur = {
  169. "3dfxhwgc",
  170. tdfxcurenable,
  171. tdfxcurdisable,
  172. tdfxcurload,
  173. tdfxcurmove,
  174. };