9 #define farptr_to_linear(rmaddr) \
10 ((((intptr_t)(rmaddr) >> 12) & 0xffff0) + ((intptr_t)(rmaddr) & 0xffff))
12 static int init(void);
13 static void cleanup(void);
14 static int setmode(int mode);
15 static int getmode(void);
16 static const char *memsize_str(long sz);
17 static int get_mode_info(int mode, struct vbe_mode_info *mi);
18 static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi);
19 static unsigned int calc_mask(int nbits, int pos);
21 static struct vid_driver drv;
22 static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
23 static unsigned int vbe_ver;
28 void vid_register_vbe(void)
34 vid_drvlist[vid_numdrv++] = &drv;
40 struct dpmi_regs regs = {0};
42 struct vbe_mode_info vbemi;
43 unsigned short bufseg;
44 uint16_t *vbe_modelist, *modelist;
46 struct vid_modeinfo modeinf;
51 bufseg = (intptr_t)vbe >> 4;
53 /* call VBE function 00 (get controller information) */
54 memcpy(vbe->sig, "VBE2", 4); /* denote we want VBE 2.0 info */
57 dpmi_rmint(0x10, ®s);
58 if(regs.eax != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) {
59 fprintf(stderr, "failed to get VBE controller information\n");
65 printf("Found VBE %d.%d\n", VBE_VER_MAJOR(vbe_ver), VBE_VER_MINOR(vbe_ver));
66 printf("OEM: %s\n", (char*)farptr_to_linear(vbe->oem_name));
67 if(vbe_ver >= 0x0200) {
68 printf("%s - %s (%s)\n", (char*)farptr_to_linear(vbe->vendor),
69 (char*)farptr_to_linear(vbe->product),
70 (char*)farptr_to_linear(vbe->revstr));
72 printf("Video RAM: %s\n", memsize_str((long)vbe->vmem_blk * 65536));
74 vbe_modelist = (uint16_t*)farptr_to_linear(vbe->modelist_addr);
76 for(i=0; i<1024; i++) {
77 if(vbe_modelist[i] == 0xffff) break;
81 if(!(modelist = malloc(count * sizeof *modelist))) {
82 fprintf(stderr, "failed to allocate mode list\n");
85 for(i=0; i<count; i++) {
86 modelist[i] = vbe_modelist[i];
89 if(!(drv.modes = malloc(count * sizeof *drv.modes))) {
90 fprintf(stderr, "failed to allocate mode list\n");
96 for(i=0; i<count; i++) {
97 if(get_mode_info(modelist[i], &vbemi) == -1) {
100 if(conv_vbeinfo(modelist[i], drv.modes + drv.num_modes, &vbemi) == -1) {
110 static void cleanup(void)
117 static int setmode(int mode)
119 struct dpmi_regs regs = {0};
122 regs.ebx = mode | VBE_MODE_LFB;
123 dpmi_rmint(0x10, ®s);
125 if(regs.eax != 0x4f) {
128 dpmi_rmint(0x10, ®s);
129 if(regs.eax != 0x4f) {
134 cur_mode = mode | VBE_MODE_LFB;
139 static int getmode(void)
144 static const char *memsize_str(long sz)
146 static const char *suffix[] = {"bytes", "kb", "mb", "gb", 0};
150 while(sz > 1024 && suffix[cnt + 1]) {
155 sprintf(buf, "%ld %s", sz, suffix[cnt]);
159 static int get_mode_info(int mode, struct vbe_mode_info *mi)
161 struct dpmi_regs regs = {0};
162 struct vbe_mode_info *miptr;
165 miptr = dpmi_lowbuf();
166 bufseg = (intptr_t)miptr >> 4;
171 dpmi_rmint(0x10, ®s);
172 if(regs.eax != 0x4f) {
180 static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi)
182 static const struct { int width, height, bpp; } stdmode[] = {
183 {640, 400, 8}, /* 100h */
184 {640, 480, 8}, /* 101h */
185 {800, 600, 4}, {800, 600, 8}, /* 102h - 103h */
186 {1024, 768, 4}, {1024, 768, 8}, /* 104h - 105h */
187 {1280, 1024, 4}, {1280, 1024, 8}, /* 106h - 107h */
188 {80, 60, 4}, {132, 25, 4}, {132, 43, 4}, {132, 50, 4}, {132, 60, 4},
189 {320, 200, 15}, {320, 200, 16}, {320, 200, 24}, /* 10dh - 10fh */
190 {640, 480, 15}, {640, 480, 16}, {640, 480, 24}, /* 110h - 112h */
191 {800, 600, 15}, {800, 600, 16}, {800, 600, 24}, /* 113h - 115h */
192 {1024, 768, 15}, {1024, 768, 16}, {1024, 768, 24}, /* 116h - 118h */
193 {1280, 1024, 15}, {1280, 1024, 16}, {1280, 1024, 24} /* 119h - 11bh */
196 if(!(vbemi->attr & VBE_ATTR_AVAIL)) {
197 return -1; /* ignore unsupported modes */
199 if(!(vbemi->attr & VBE_ATTR_GFX)) {
200 return -1; /* ignore text modes */
202 if(vbemi->attr & VBE_ATTR_LFB) {
208 mi->vmem_addr = 0xa0000;
210 if(vbe_ver >= 0x0102) {
211 mi->width = vbemi->xres;
212 mi->height = vbemi->yres;
213 mi->bpp = vbemi->bpp;
214 mi->rshift = vbemi->rpos;
215 mi->gshift = vbemi->gpos;
216 mi->bshift = vbemi->bpos;
217 mi->rmask = calc_mask(vbemi->rsize, vbemi->rpos);
218 mi->gmask = calc_mask(vbemi->gsize, vbemi->gpos);
219 mi->bmask = calc_mask(vbemi->bsize, vbemi->bpos);
220 mi->pages = vbemi->num_img_pages + 1;
222 if(vbe_ver >= 0x0200) {
223 mi->vmem_addr = vbemi->fb_addr;
224 mi->vmem_size = vbemi->scanline_bytes * mi->height * mi->pages;
227 if((mode & 0xff) > 7) {
230 mi->width = stdmode[mode & 0xff].width;
231 mi->height = stdmode[mode & 0xff].height;
232 mi->bpp = stdmode[mode & 0xff].bpp;
234 mi->ncolors = 1 << mi->bpp;
235 mi->pitch = vbemi->scanline_bytes;
236 mi->win_size = vbemi->win_size;
237 mi->win_gran = vbemi->win_gran;
241 static unsigned int calc_mask(int nbits, int pos)
244 unsigned int mask = 0;
246 for(i=0; i<nbits; i++) {
247 mask = (mask << 1) | 1;