13 static uchar *fb, *tfb;
17 VgaMode *curmode, *nextmode, *modes, **modeslast = &modes;
18 int curhbytes, nexthbytes;
19 int vesamode, maxw, maxh;
26 static Image *img, *bg;
28 static Rectangle picr;
29 Channel *kbdch, *mousech;
31 extern u8int mouseactive;
34 typedef struct VGA VGA;
37 u8int cidx; /* crtc */
38 u8int aidx; /* attribute (bit 7: access flipflop) */
39 u8int gidx; /* graphics */
40 u8int sidx; /* sequencer */
41 u16int rdidx, wdidx; /* bit 0-1: color */
52 .attr { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 },
53 .crtc { [10] 13, [11] 14 },
55 0x000000ff, 0x0000a8ff, 0x00a800ff, 0x00a8a8ff, 0xa80000ff, 0xa800a8ff, 0xa85400ff, 0xa8a8a8ff,
56 0x545454ff, 0x5454fcff, 0x54fc54ff, 0x54fcfcff, 0xfc5454ff, 0xfc54fcff, 0xfcfc54ff, 0xfcfcfcff,
57 0x000000ff, 0x141414ff, 0x202020ff, 0x2c2c2cff, 0x383838ff, 0x444444ff, 0x505050ff, 0x606060ff,
58 0x707070ff, 0x808080ff, 0x909090ff, 0xa0a0a0ff, 0xb4b4b4ff, 0xc8c8c8ff, 0xe0e0e0ff, 0xfcfcfcff,
59 0x0000fcff, 0x4000fcff, 0x7c00fcff, 0xbc00fcff, 0xfc00fcff, 0xfc00bcff, 0xfc007cff, 0xfc0040ff,
60 0xfc0000ff, 0xfc4000ff, 0xfc7c00ff, 0xfcbc00ff, 0xfcfc00ff, 0xbcfc00ff, 0x7cfc00ff, 0x40fc00ff,
61 0x00fc00ff, 0x00fc40ff, 0x00fc7cff, 0x00fcbcff, 0x00fcfcff, 0x00bcfcff, 0x007cfcff, 0x0040fcff,
62 0x7c7cfcff, 0x9c7cfcff, 0xbc7cfcff, 0xdc7cfcff, 0xfc7cfcff, 0xfc7cdcff, 0xfc7cbcff, 0xfc7c9cff,
63 0xfc7c7cff, 0xfc9c7cff, 0xfcbc7cff, 0xfcdc7cff, 0xfcfc7cff, 0xdcfc7cff, 0xbcfc7cff, 0x9cfc7cff,
64 0x7cfc7cff, 0x7cfc9cff, 0x7cfcbcff, 0x7cfcdcff, 0x7cfcfcff, 0x7cdcfcff, 0x7cbcfcff, 0x7c9cfcff,
65 0xb4b4fcff, 0xc4b4fcff, 0xd8b4fcff, 0xe8b4fcff, 0xfcb4fcff, 0xfcb4e8ff, 0xfcb4d8ff, 0xfcb4c4ff,
66 0xfcb4b4ff, 0xfcc4b4ff, 0xfcd8b4ff, 0xfce8b4ff, 0xfcfcb4ff, 0xe8fcb4ff, 0xd8fcb4ff, 0xc4fcb4ff,
67 0xb4fcb4ff, 0xb4fcc4ff, 0xb4fcd8ff, 0xb4fce8ff, 0xb4fcfcff, 0xb4e8fcff, 0xb4d8fcff, 0xb4c4fcff,
68 0x000070ff, 0x1c0070ff, 0x380070ff, 0x540070ff, 0x700070ff, 0x700054ff, 0x700038ff, 0x70001cff,
69 0x700000ff, 0x701c00ff, 0x703800ff, 0x705400ff, 0x707000ff, 0x547000ff, 0x387000ff, 0x1c7000ff,
70 0x007000ff, 0x00701cff, 0x007038ff, 0x007054ff, 0x007070ff, 0x005470ff, 0x003870ff, 0x001c70ff,
71 0x383870ff, 0x443870ff, 0x543870ff, 0x603870ff, 0x703870ff, 0x703860ff, 0x703854ff, 0x703844ff,
72 0x703838ff, 0x704438ff, 0x705438ff, 0x706038ff, 0x707038ff, 0x607038ff, 0x547038ff, 0x447038ff,
73 0x387038ff, 0x387044ff, 0x387054ff, 0x387060ff, 0x387070ff, 0x386070ff, 0x385470ff, 0x384470ff,
74 0x505070ff, 0x585070ff, 0x605070ff, 0x685070ff, 0x705070ff, 0x705068ff, 0x705060ff, 0x705058ff,
75 0x705050ff, 0x705850ff, 0x706050ff, 0x706850ff, 0x707050ff, 0x687050ff, 0x607050ff, 0x587050ff,
76 0x507050ff, 0x507058ff, 0x507060ff, 0x507068ff, 0x507070ff, 0x506870ff, 0x506070ff, 0x505870ff,
77 0x000040ff, 0x100040ff, 0x200040ff, 0x300040ff, 0x400040ff, 0x400030ff, 0x400020ff, 0x400010ff,
78 0x400000ff, 0x401000ff, 0x402000ff, 0x403000ff, 0x404000ff, 0x304000ff, 0x204000ff, 0x104000ff,
79 0x004000ff, 0x004010ff, 0x004020ff, 0x004030ff, 0x004040ff, 0x003040ff, 0x002040ff, 0x001040ff,
80 0x202040ff, 0x282040ff, 0x302040ff, 0x382040ff, 0x402040ff, 0x402038ff, 0x402030ff, 0x402028ff,
81 0x402020ff, 0x402820ff, 0x403020ff, 0x403820ff, 0x404020ff, 0x384020ff, 0x304020ff, 0x284020ff,
82 0x204020ff, 0x204028ff, 0x204030ff, 0x204038ff, 0x204040ff, 0x203840ff, 0x203040ff, 0x202840ff,
83 0x2c2c40ff, 0x302c40ff, 0x342c40ff, 0x3c2c40ff, 0x402c40ff, 0x402c3cff, 0x402c34ff, 0x402c30ff,
84 0x402c2cff, 0x40302cff, 0x40342cff, 0x403c2cff, 0x40402cff, 0x3c402cff, 0x34402cff, 0x30402cff,
85 0x2c402cff, 0x2c4030ff, 0x2c4034ff, 0x2c403cff, 0x2c4040ff, 0x2c3c40ff, 0x2c3440ff, 0x2c3040ff,
86 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff, 0x000000ff,
91 newpal(int l, int n, int dofree)
95 assert(l >= 0 && n + l <= 256);
98 freeimage(vga.col[l]);
99 vga.col[l] = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, vga.pal[l]);
100 if(vga.col[l] == nil) sysfatal("allocimage: %r");
102 for(l = 0; l < 16; l++){
103 x = vga.attr[0x14] << 4 & 0xc0 | vga.attr[l] & 0x3f;
104 if((vga.attr[0x10] & 0x80) != 0)
105 x = x & 0xcf | vga.attr[0x14] << 4 & 0x30;
106 vga.acol[l] = vga.col[x];
117 vgasetpal(u8int n, u32int v)
126 screeninit(int resize)
134 bg = allocimage(display, Rect(0, 0, 1, 1), screen->chan, 1, 0xCCCCCCFF);
137 p = divpt(addpt(screen->r.min, screen->r.max), 2);
138 picr = (Rectangle){subpt(p, Pt(curmode->w/2, curmode->h/2)), addpt(p, Pt((curmode->w+1)/2, (curmode->h+1)/2))};
139 switch(curmode->chan){
140 case 0: ch = screen->chan; break;
141 case CHAN1(CMap, 4): case CMAP8:
147 default: ch = curmode->chan; break;
149 img = allocimage(display, Rect(0, 0, curmode->w, curmode->h), ch, 0, 0);
150 draw(screen, screen->r, bg, nil, ZP);
154 vgaio(int isin, u16int port, u32int val, int sz, void *)
160 if(port != 0x3df && sz == 2 && !isin){
161 vgaio(0, port, (u8int)val, 1, nil);
162 return vgaio(0, port+1, (u8int)(val >> 8), 1, nil);
164 if(sz != 1) vmdebug("vga: non-byte access to port %#ux, sz=%d", port, sz);
166 switch(isin << 16 | port){
168 if((vga.aidx & 0x80) != 0){
169 vmdebug("vga: attribute write %#.2x = %#.2x", vga.aidx & 0x1f, val);
170 vga.attr[vga.aidx & 0x1f] = val;
171 qlock(&vga); newpal(0, 0, 0); qunlock(&vga);
173 vga.aidx = val & 0x3f;
176 case 0x3c2: vga.miscout = val; return 0;
177 case 0x3c4: vga.sidx = val; return 0;
180 case 0: vga.seq[vga.sidx] = val & 3; return 0;
181 case 4: vga.seq[vga.sidx] = val & 0xe; return 0;
182 default: vmerror("vga: write to unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
184 case 0x3c6: return 0;
185 case 0x3c7: vga.rdidx = val << 2; return 0;
186 case 0x3c8: vga.wdidx = val << 2; return 0;
188 vga.pal[vga.wdidx >> 2] = vga.pal[vga.wdidx >> 2] & ~(0xff << (~vga.wdidx << 3 & 24)) | val << 2 + (~vga.wdidx << 3 & 24);
189 qlock(&vga); newpal(vga.wdidx >> 2, 1, 1); qunlock(&vga);
190 vga.wdidx = vga.wdidx + 1 + (vga.wdidx >> 1 & 1) & 0x3ff;
192 case 0x3ce: vga.gidx = val; return 0;
195 case 4: vga.graph[vga.gidx] = val & 3; break;
196 case 8: vga.graph[vga.gidx] = val; break;
198 vmerror("vga: write to unknown graphics register %#ux (val=%#ux)", vga.gidx, val);
201 case 0x3d4: vga.cidx = val; return 0;
204 case 10: case 11: case 12: case 13: case 14: case 15:
205 vga.crtc[vga.cidx] = val;
208 vmerror("vga: write to unknown CRTC register %#ux (val=%#ux)", vga.cidx, val);
211 case 0x103c0: return vga.aidx & 0x3f;
212 case 0x103c1: return vga.attr[vga.aidx & 0x1f];
213 case 0x103c4: return vga.sidx;
218 return vga.seq[vga.sidx];
219 default: vmerror("vga: read from unknown sequencer register %#ux (val=%#ux)", vga.sidx, val); return 0;
221 case 0x103c6: return 0xff;
222 case 0x103c7: return vga.rdidx >> 2;
223 case 0x103c8: return vga.wdidx >> 2;
225 m = vga.pal[vga.rdidx >> 2] >> (~vga.rdidx << 3 & 24) + 2;
226 vga.rdidx = vga.rdidx + 1 + (vga.rdidx >> 1 & 1) & 0x3ff;
228 case 0x103cc: return vga.miscout;
229 case 0x103ce: return vga.gidx;
234 return vga.graph[vga.gidx];
236 vmerror("vga: read from unknown graphics register %#ux", vga.gidx);
239 case 0x103d4: return vga.cidx;
242 case 10: case 11: case 12: case 13: case 14: case 15:
243 return vga.crtc[vga.cidx];
245 vmerror("vga: read from unknown CRTC register %#ux", vga.cidx);
253 return iowhine(isin, port, val, sz, "vga");
256 typedef struct Key Key;
265 defkey(Rune r, int code)
269 for(kp = &kbdmap[r % nelem(kbdmap)]; *kp != nil; kp = &(*kp)->next)
272 k = emalloc(sizeof(Key));
286 defkey(Kshift, 0x2a);
290 defkey(Kprint, 0x137);
291 defkey(Kaltgr, 0x138);
292 defkey(Kbreak, 0x146);
293 defkey(Khome, 0x147);
295 defkey(Kpgup, 0x149);
296 defkey(Kleft, 0x14b);
297 defkey(Kright, 0x14d);
299 defkey(Kdown, 0x150);
300 defkey(Kpgdown, 0x151);
305 bp = Bopen(fn, OREAD);
307 vmerror("kbdlayout: %r");
311 s = Brdstr(bp, '\n', 1);
313 nf = getfields(s, f, nelem(f), 1, " \t");
315 x = strtol(f[0], &p, 0);
316 if(*p != 0) continue;
317 y = strtol(f[1], &p, 0);
318 if(*p != 0) continue;
319 if(*f[2] == '\'' || *f[2] == '^'){
320 chartorune(&z, f[2]+1);
321 if(*f[2] == '^') z -= '@';
323 z = strtol(f[2], &p, 0);
324 if(*p != 0) continue;
327 if(x != 0 || z == 0) continue;
333 static vlong kbwatchdog; /* used to release mouse grabbing if keyproc is stuck */
339 static char buf[256];
340 static uvlong kdown[8], nkdown[8];
347 threadsetname("keyproc");
348 fd = open("/dev/kbd", OREAD);
350 sysfatal("open: %r");
354 memmove(buf, buf+n, sizeof(buf)-n);
358 n = read(fd, buf, sizeof(buf)-1);
360 sysfatal("read /dev/kbd: %r");
365 if(buf[0] != 'k' && buf[0] != 'K')
368 memset(nkdown, 0, sizeof(nkdown));
370 s += chartorune(&r, s);
371 for(k = kbdmap[r % nelem(kbdmap)]; k != nil; k = k->next)
373 nkdown[k->code >> 6] |= 1ULL<<(k->code&63);
376 if(k == nil) vmerror("unknown key %d", r);
378 if(mousegrab && (nkdown[0]>>29 & 1) != 0 && (nkdown[0]>>56 & 1) != 0){
382 for(i = 0; i < 8; i++){
383 if(nkdown[i] == kdown[i]) continue;
384 set = nkdown[i] & ~kdown[i];
385 rls = ~nkdown[i] & kdown[i];
386 for(j = 0; j < 64; j++, set>>=1, rls >>= 1)
387 if(((set|rls) & 1) != 0){
390 sendul(kbdch, j | i<<6&0xff | ((rls&1) != 0 ? 0x80 : 0));
391 sendnotif(i8042kick, nil);
393 kdown[i] = nkdown[i];
413 {mc->c, &m, CHANRCV},
414 {mousech, &mm, gotm ? CHANSND : CHANNOP},
420 mid = divpt(addpt(picr.max, picr.min), 2);
421 grabout = insetrect(Rpt(mid, mid), -50);
422 if(!ptinrect(m.xy, picr)){
427 if(clicked && (m.buttons & 1) == 0 && mouseactive){
429 setcursor(mc, &blank);
431 clicked = m.buttons & 1;
434 if(kbwatchdog != 0 && nsec() - kbwatchdog > 1000ULL*1000*1000)
437 if(!ptinrect(m.xy, grabout)){
442 mm.xy = addpt(mm.xy, subpt(m.xy, om.xy));
444 mm.buttons = m.buttons;
447 sendnotif(i8042kick, nil);
455 static Rune cp437[256] = {
456 0x0020, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022, 0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
457 0x25ba, 0x25c4, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8, 0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
458 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, 0x0029, 0x002a, 0x002b, 0x002c, 0x002d, 0x002e, 0x002f,
459 0x0030, 0x0031, 0x0032, 0x0033, 0x0034, 0x0035, 0x0036, 0x0037, 0x0038, 0x0039, 0x003a, 0x003b, 0x003c, 0x003d, 0x003e, 0x003f,
460 0x0040, 0x0041, 0x0042, 0x0043, 0x0044, 0x0045, 0x0046, 0x0047, 0x0048, 0x0049, 0x004a, 0x004b, 0x004c, 0x004d, 0x004e, 0x004f,
461 0x0050, 0x0051, 0x0052, 0x0053, 0x0054, 0x0055, 0x0056, 0x0057, 0x0058, 0x0059, 0x005a, 0x005b, 0x005c, 0x005d, 0x005e, 0x005f,
462 0x0060, 0x0061, 0x0062, 0x0063, 0x0064, 0x0065, 0x0066, 0x0067, 0x0068, 0x0069, 0x006a, 0x006b, 0x006c, 0x006d, 0x006e, 0x006f,
463 0x0070, 0x0071, 0x0072, 0x0073, 0x0074, 0x0075, 0x0076, 0x0077, 0x0078, 0x0079, 0x007a, 0x007b, 0x007c, 0x007d, 0x007e, 0x2302,
464 0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7, 0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
465 0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9, 0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
466 0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba, 0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
467 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
468 0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f, 0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
469 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b, 0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
470 0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4, 0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
471 0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248, 0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0,
482 static uchar rbuf[80*25*2];
485 sa = vga.crtc[12] << 8 | vga.crtc[13];
486 if(sa + 80*25 >= 0x10000){
487 memset(rbuf, 0, sizeof(rbuf));
488 memmove(rbuf, tfb + sa * 2, 0x10000 - 80*25 - sa);
492 for(y = 0; y < 25; y++){
493 for(x = 0; x < 80; x++)
494 buf[x] = cp437[p[2*x]];
495 for(x = 0; x < 80; x = x1){
497 for(x1 = x; x1 < 80 && p[2*x1+1] == attr; x1++)
499 r = Rect(x * 8, y * 16, x1 * 8, (y + 1) * 16);
500 draw(img, r, vga.acol[attr >> 4], nil, ZP);
501 runestringn(img, r.min, vga.acol[attr & 0xf], ZP, display->defaultfont, buf + x, x1 - x);
505 cp = (vga.crtc[14] << 8 | vga.crtc[15]);
506 if(cp >= sa && cp < sa + 80*25 && (vga.crtc[10] & 0x20) == 0 && nsec() / 500000000 % 2 == 0){
507 buf[0] = cp437[tfb[cp*2]];
509 r.min = Pt((cp - sa) % 80 * 8, (cp - sa) / 80 * 16);
510 r.max = Pt(r.min.x + 8, r.min.y + (vga.crtc[11] & 0x1f) + 1);
511 r.min.y += vga.crtc[10] & 0x1f;
512 draw(img, r, vga.acol[attr & 0xf], nil, ZP);
514 draw(screen, picr, img, nil, ZP);
515 flushimage(display, 1);
530 upd.min.y = upd.max.y = -1;
534 while(p < (u32int*)(fb + curmode->sz)){
535 if(*p != *q || redraw){
536 if(upd.min.y < 0) upd.min.y = y;
537 upd.max.y = y + 1 + (xb + 4 > hb);
548 if(upd.min.y == upd.max.y) return;
550 upd.max.x = curmode->w;
551 if(vesamode && (curmode->chan >> 4 == CMap)){
552 buf = emalloc(curmode->w * 4 * (upd.max.y - upd.min.y));
554 for(y = upd.min.y; y < upd.max.y; y++){
556 for(xb = 0; xb < curmode->w; xb++){
557 if(curmode->chan == CMAP8)
559 else if((xb & 1) == 0)
566 loadimage(img, upd, (void *) buf, curmode->w * 4 * (upd.max.y - upd.min.y));
568 draw(screen, rectaddpt(upd, picr.min), img, nil, upd.min);
569 }else if(curmode->chan != screen->chan || !rectinrect(picr, screen->r)){
570 if(curmode->hbytes != hb){
571 for(y = upd.min.y; y < upd.max.y; y++)
572 loadimage(img, Rect(0, y, curmode->w, y+1), sfb + y * hb, curmode->hbytes);
574 loadimage(img, upd, sfb + upd.min.y * hb, (upd.max.y - upd.min.y) * hb);
575 draw(screen, rectaddpt(upd, picr.min), img, nil, upd.min);
577 if(curmode->hbytes != hb){
578 for(y = upd.min.y; y < upd.max.y; y++)
579 loadimage(screen, Rect(picr.min.x, picr.min.y + y, picr.max.x, picr.min.y + y + 1), sfb + y * hb, curmode->hbytes);
581 loadimage(screen, rectaddpt(upd, picr.min), sfb + upd.min.y * hb, (upd.max.y - upd.min.y) * hb);
583 flushimage(display, 1);
593 threadsetname("draw");
602 curhbytes = m->hbytes;
604 if(nexthbytes != curhbytes){
606 curhbytes = nexthbytes;
608 while(nbrecv(mc->resizec, &ul) > 0)
610 if((event & 3) != 0){
611 if((event & 2) != 0 && getwindow(display, Refnone) < 0)
612 sysfatal("resize failed: %r");
613 screeninit((event & 2) != 0);
615 if(curmode == &textmode)
631 for(i = 0; i < 4; i++){
632 t = ch >> 8 * i + 4 & 15;
633 if((ch >> 8 * i & 15) == 0) continue;
634 if(t >= NChan) return 0;
635 if((got & 1<<t) != 0) return 0;
638 if(!vesamode) return 1;
640 case 1<<CRed|1<<CGreen|1<<CBlue:
641 case 1<<CRed|1<<CGreen|1<<CBlue|1<<CAlpha:
642 case 1<<CRed|1<<CGreen|1<<CBlue|1<<CIgnore:
645 return chantodepth(ch) == 4 || chantodepth(ch) == 8;
652 vgamodeparse(char *p, VgaMode **mp)
658 m = emalloc(sizeof(VgaMode));
661 modeslast = &m->next;
662 m->w = strtoul(p, &r, 10);
665 sysfatal("invalid mode specifier");
667 m->h = strtoul(p, &r, 10);
677 m->chan = strtochan(p);
679 if(m->chan == 0 || !chancheck(m->chan))
682 if(m->w > maxw) maxw = m->w;
683 if(m->h > maxh) maxh = m->h;
688 vgafbparse(char *fbstring)
693 if(strcmp(fbstring, "text") == 0){
698 }else if(strncmp(fbstring, "vesa:", 5) == 0){
704 q = vgamodeparse(p, &m);
705 if(p == q || m->w <= 0 || m->h <= 0)
706 no: sysfatal("invalid mode specifier");
707 m->hbytes = chantodepth(m->chan) * m->w + 7 >> 3;
708 m->sz = m->hbytes * m->h;
709 if(m->sz > fbsz) fbsz = m->sz;
714 fbaddr = strtoul(p, &q, 0);
720 if(modes == nil || vesamode == 0 && modes->next != nil)
724 curhbytes = curmode->hbytes;
725 fbsz = -(-fbsz & -4096);
732 fbsz = roundpow2(fbsz);
743 extern void vesainit(void);
745 if(curmode == nil) return;
747 nexthbytes = curhbytes;
748 tfb = gptr(0xb8000, 0x8000);
750 sysfatal("got nil ptr for text framebuffer");
751 for(i = 0; i < 0x8000; i += 2)
752 PUT16(tfb, i, 0x0720);
754 fb = gptr(fbaddr, fbsz);
756 sysfatal("got nil ptr for framebuffer");
758 snprint(buf, sizeof(buf), "-dx %d -dy %d", maxw+50, maxh+50);
760 initdraw(nil, nil, "vmx");
762 flushimage(display, 1);
763 kbdlayout("/sys/lib/kbmap/us");
764 mc = initmouse(nil, screen);
765 kbdch = chancreate(sizeof(ulong), 128);
766 mousech = chancreate(sizeof(Mouse), 32);
767 proccreate(mousethread, nil, 4096);
768 proccreate(keyproc, nil, 4096);
769 proccreate(drawproc, nil, 4096);
771 d = mkpcidev(allocbdf(), 0x06660666, 0x03000000, 0);
772 mkpcibar(d, BARMEM32 | BARPREF, fbaddr, fbsz, nil, nil);