vgai81x.c 4.3 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
  14. {
  15. ushort ctl;
  16. ushort pad;
  17. ulong base;
  18. ulong pos;
  19. } CursorI81x;
  20. enum {
  21. Fbsize = 8*MB,
  22. hwCur = 0x70080,
  23. SRX = 0x3c4,
  24. DPMSsync = 0x5002,
  25. };
  26. static void
  27. i81xblank(VGAscr *scr, int blank)
  28. {
  29. char *srx, *srxd, *dpms;
  30. char sr01, mode;
  31. srx = (char *)scr->mmio+SRX;
  32. srxd = srx+1;
  33. dpms = (char *)scr->mmio+DPMSsync;
  34. *srx = 0x01;
  35. sr01 = *srxd & ~0x20;
  36. mode = *dpms & 0xf0;
  37. if(blank) {
  38. sr01 |= 0x20;
  39. mode |= 0x0a;
  40. }
  41. *srxd = sr01;
  42. *dpms = mode;
  43. }
  44. static Pcidev *
  45. i81xpcimatch(void)
  46. {
  47. Pcidev *p;
  48. p = nil;
  49. while((p = pcimatch(p, 0x8086, 0)) != nil){
  50. switch(p->did){
  51. default:
  52. continue;
  53. case 0x7121:
  54. case 0x7123:
  55. case 0x7125:
  56. case 0x1102:
  57. case 0x1112:
  58. case 0x1132:
  59. case 0x3577: /* IBM R31 uses intel 830M chipset */
  60. return p;
  61. }
  62. }
  63. return nil;
  64. }
  65. static void
  66. i81xenable(VGAscr* scr)
  67. {
  68. Pcidev *p;
  69. int size;
  70. Mach *mach0;
  71. ulong *pgtbl, *rp, cursor, *pte, fbuf, fbend;
  72. if(scr->mmio)
  73. return;
  74. p = i81xpcimatch();
  75. if(p == nil)
  76. return;
  77. scr->mmio = vmap(p->mem[1].bar & ~0x0F, p->mem[1].size);
  78. if(scr->mmio == 0)
  79. return;
  80. addvgaseg("i81xmmio", p->mem[1].bar&~0x0F, p->mem[1].size);
  81. /* allocate page table */
  82. pgtbl = xspanalloc(64*1024, BY2PG, 0);
  83. scr->mmio[0x2020/4] = PADDR(pgtbl) | 1;
  84. size = p->mem[0].size;
  85. if(size > 0)
  86. size = Fbsize;
  87. vgalinearaddr(scr, p->mem[0].bar&~0xF, size);
  88. addvgaseg("i81xscreen", p->mem[0].bar&~0xF, size);
  89. /*
  90. * allocate backing store for frame buffer
  91. * and populate device page tables.
  92. */
  93. fbuf = PADDR(xspanalloc(size, BY2PG, 0));
  94. fbend = PGROUND(fbuf+size);
  95. rp = scr->mmio+0x10000/4;
  96. while(fbuf < fbend) {
  97. *rp++ = fbuf | 1;
  98. fbuf += BY2PG;
  99. }
  100. /*
  101. * allocate space for the cursor data in system memory.
  102. * must be uncached.
  103. */
  104. cursor = (ulong)xspanalloc(BY2PG, BY2PG, 0);
  105. mach0 = MACHP(0);
  106. pte = mmuwalk(mach0->pdb, cursor, 2, 0);
  107. if(pte == nil)
  108. panic("i81x cursor mmuwalk");
  109. *pte |= PTEUNCACHED;
  110. scr->storage = cursor;
  111. scr->blank = i81xblank;
  112. hwblank = 1;
  113. }
  114. static void
  115. i81xcurdisable(VGAscr* scr)
  116. {
  117. CursorI81x *hwcurs;
  118. if(scr->mmio == 0)
  119. return;
  120. hwcurs = (void*)((uchar*)scr->mmio+hwCur);
  121. hwcurs->ctl = (1<<4);
  122. }
  123. static void
  124. i81xcurload(VGAscr* scr, Cursor* curs)
  125. {
  126. int y;
  127. uchar *p;
  128. CursorI81x *hwcurs;
  129. if(scr->mmio == 0)
  130. return;
  131. hwcurs = (void*)((uchar*)scr->mmio+hwCur);
  132. /*
  133. * Disable the cursor then load the new image in
  134. * the top-left of the 32x32 array.
  135. * Unused portions of the image have been initialised to be
  136. * transparent.
  137. */
  138. hwcurs->ctl = (1<<4);
  139. p = (uchar*)scr->storage;
  140. for(y = 0; y < 16; y += 2) {
  141. *p++ = ~(curs->clr[2*y]|curs->set[2*y]);
  142. *p++ = ~(curs->clr[2*y+1]|curs->set[2*y+1]);
  143. p += 2;
  144. *p++ = ~(curs->clr[2*y+2]|curs->set[2*y+2]);
  145. *p++ = ~(curs->clr[2*y+3]|curs->set[2*y+3]);
  146. p += 2;
  147. *p++ = curs->set[2*y];
  148. *p++ = curs->set[2*y+1];
  149. p += 2;
  150. *p++ = curs->set[2*y+2];
  151. *p++ = curs->set[2*y+3];
  152. p += 2;
  153. }
  154. /*
  155. * Save the cursor hotpoint and enable the cursor.
  156. * The 0,0 cursor point is top-left.
  157. */
  158. scr->offset.x = curs->offset.x;
  159. scr->offset.y = curs->offset.y;
  160. hwcurs->ctl = (1<<4)|1;
  161. }
  162. static int
  163. i81xcurmove(VGAscr* scr, Point p)
  164. {
  165. int x, y;
  166. ulong pos;
  167. CursorI81x *hwcurs;
  168. if(scr->mmio == 0)
  169. return 1;
  170. hwcurs = (void*)((uchar*)scr->mmio+hwCur);
  171. x = p.x+scr->offset.x;
  172. y = p.y+scr->offset.y;
  173. pos = 0;
  174. if(x < 0) {
  175. pos |= (1<<15);
  176. x = -x;
  177. }
  178. if(y < 0) {
  179. pos |= (1<<31);
  180. y = -y;
  181. }
  182. pos |= ((y&0x7ff)<<16)|(x&0x7ff);
  183. hwcurs->pos = pos;
  184. return 0;
  185. }
  186. static void
  187. i81xcurenable(VGAscr* scr)
  188. {
  189. int i;
  190. uchar *p;
  191. CursorI81x *hwcurs;
  192. i81xenable(scr);
  193. if(scr->mmio == 0)
  194. return;
  195. hwcurs = (void*)((uchar*)scr->mmio+hwCur);
  196. /*
  197. * Initialise the 32x32 cursor to be transparent in 2bpp mode.
  198. */
  199. hwcurs->base = PADDR(scr->storage);
  200. p = (uchar*)scr->storage;
  201. for(i = 0; i < 32/2; i++) {
  202. memset(p, 0xff, 8);
  203. memset(p+8, 0, 8);
  204. p += 16;
  205. }
  206. /*
  207. * Load, locate and enable the 32x32 cursor in 2bpp mode.
  208. */
  209. i81xcurload(scr, &arrow);
  210. i81xcurmove(scr, ZP);
  211. }
  212. VGAdev vgai81xdev = {
  213. "i81x",
  214. i81xenable,
  215. nil,
  216. nil,
  217. nil,
  218. };
  219. VGAcur vgai81xcur = {
  220. "i81xhwgc",
  221. i81xcurenable,
  222. i81xcurdisable,
  223. i81xcurload,
  224. i81xcurmove,
  225. };