vgai81x.c 4.8 KB

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