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 #include "ureg.h" 9 10 #define Image IMAGE 11 #include <draw.h> 12 #include <memdraw.h> 13 #include <cursor.h> 14 #include "screen.h" 15 16 #define WORD(p) ((p)[0] | ((p)[1]<<8)) 17 #define LONG(p) ((p)[0] | ((p)[1]<<8) | ((p)[2]<<16) | ((p)[3]<<24)) 18 #define PWORD(p, v) (p)[0] = (v); (p)[1] = (v)>>8 19 #define PLONG(p, v) (p)[0] = (v); (p)[1] = (v)>>8; (p)[2] = (v)>>16; (p)[3] = (v)>>24 20 21 extern void realmode(Ureg*); 22 23 static uchar* 24 vbesetup(Ureg *u, int ax) 25 { 26 ulong pa; 27 28 pa = PADDR(RMBUF); 29 memset(u, 0, sizeof *u); 30 u->ax = ax; 31 u->es = (pa>>4)&0xF000; 32 u->di = pa&0xFFFF; 33 return (void*)RMBUF; 34 } 35 36 static void 37 vbecall(Ureg *u) 38 { 39 u->trap = 0x10; 40 realmode(u); 41 if((u->ax&0xFFFF) != 0x004F) 42 error("vesa bios error"); 43 } 44 45 static void 46 vbecheck(void) 47 { 48 Ureg u; 49 uchar *p; 50 51 p = vbesetup(&u, 0x4F00); 52 strcpy((char*)p, "VBE2"); 53 vbecall(&u); 54 if(memcmp((char*)p, "VESA", 4) != 0) 55 error("bad vesa signature"); 56 if(p[5] < 2) 57 error("bad vesa version"); 58 } 59 60 static int 61 vbegetmode(void) 62 { 63 Ureg u; 64 65 vbesetup(&u, 0x4F03); 66 vbecall(&u); 67 return u.bx; 68 } 69 70 static uchar* 71 vbemodeinfo(int mode) 72 { 73 uchar *p; 74 Ureg u; 75 76 p = vbesetup(&u, 0x4F01); 77 u.cx = mode; 78 vbecall(&u); 79 return p; 80 } 81 82 static void 83 vesalinear(VGAscr* scr, int, int) 84 { 85 int i, mode, size; 86 uchar *p; 87 ulong paddr; 88 Pcidev *pci; 89 90 vbecheck(); 91 mode = vbegetmode(); 92 /* bochs loses the top bits - cannot use this 93 if((mode&(1<<14)) == 0) 94 error("not in linear graphics mode"); 95 */ 96 mode &= 0x3FFF; 97 p = vbemodeinfo(mode); 98 if(!(WORD(p+0) & (1<<4))) 99 error("not in VESA graphics mode"); 100 if(!(WORD(p+0) & (1<<7))) 101 error("not in linear graphics mode"); 102 103 paddr = LONG(p+40); 104 size = WORD(p+20)*WORD(p+16); 105 size = PGROUND(size); 106 107 /* 108 * figure out max size of memory so that we have 109 * enough if the screen is resized. 110 */ 111 pci = nil; 112 while((pci = pcimatch(pci, 0, 0)) != nil){ 113 if(pci->ccrb != 3) 114 continue; 115 for(i=0; i<nelem(pci->mem); i++) 116 if(paddr == (pci->mem[i].bar&~0x0F)){ 117 if(pci->mem[i].size > size) 118 size = pci->mem[i].size; 119 goto havesize; 120 } 121 } 122 123 /* no pci - heuristic guess */ 124 if(size < 4*1024*1024) 125 size = 4*1024*1024; 126 else 127 size = ROUND(size, 1024*1024); 128 129 havesize: 130 vgalinearaddr(scr, paddr, size); 131 } 132 133 VGAdev vgavesadev = { 134 "vesa", 135 0, 136 0, 137 0, 138 vesalinear, 139 0, 140 0, 141 0, 142 0, 143 0, 144 }; 145 146