11 #define farptr_to_linear(rmaddr) \
12 ((((intptr_t)(rmaddr) >> 12) & 0xffff0) + ((intptr_t)(rmaddr) & 0xffff))
14 static int init(void);
15 static void cleanup(void);
16 static struct vid_modeinfo *find_mode(int mode);
17 static int setmode(int mode);
18 static int getmode(void);
19 static const char *memsize_str(long sz);
20 static int get_mode_info(int mode, struct vbe_mode_info *mi);
21 static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi);
22 static unsigned int calc_mask(int nbits, int pos);
23 static void print_mode_info(int mode, struct vid_modeinfo *mi);
25 static void pack(uint32_t *pix, int r, int g, int b);
26 static void unpack(uint32_t pix, int *r, int *g, int *b);
27 static void clear(uint32_t color);
28 static void blit_lfb(int x, int y, int w, int h, void *fb, int pitch);
29 static void blit_banked(int x, int y, int w, int h, void *fb, int pitch);
30 static void blitfb_lfb(void *fb, int pitch);
31 static void blitfb_banked(void *fb, int pitch);
32 static void flip(int vsync);
34 static struct vid_driver drv;
35 static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
36 static unsigned int vbe_ver;
39 static struct vid_modeinfo *cur_mi;
40 static int cur_pgsize;
43 void vid_register_vbe(void)
49 vid_drvlist[vid_numdrv++] = &drv;
55 struct dpmi_regs regs = {0};
57 struct vbe_mode_info vbemi;
58 unsigned short bufseg;
59 uint16_t *vbe_modelist, *modelist;
61 struct vid_modeinfo modeinf;
67 bufseg = (intptr_t)vbe >> 4;
69 /* call VBE function 00 (get controller information) */
70 memcpy(vbe->sig, "VBE2", 4); /* denote we want VBE 2.0 info */
73 dpmi_rmint(0x10, ®s);
74 if((regs.eax & 0xffff) != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) {
75 errormsg("failed to get VBE controller information\n");
81 infomsg("Found VBE %d.%d\n", VBE_VER_MAJOR(vbe_ver), VBE_VER_MINOR(vbe_ver));
82 infomsg("OEM: %s\n", (char*)farptr_to_linear(vbe->oem_name));
83 if(vbe_ver >= 0x0200) {
84 infomsg("%s - %s (%s)\n", (char*)farptr_to_linear(vbe->vendor),
85 (char*)farptr_to_linear(vbe->product),
86 (char*)farptr_to_linear(vbe->revstr));
88 infomsg("Video RAM: %s\n", memsize_str((long)vbe->vmem_blk * 65536));
90 vbe_modelist = (uint16_t*)farptr_to_linear(vbe->modelist_addr);
92 for(i=0; i<1024; i++) {
93 if(vbe_modelist[i] == 0xffff) break;
97 if(!(modelist = malloc(count * sizeof *modelist))) {
98 errormsg("failed to allocate mode list\n");
101 for(i=0; i<count; i++) {
102 modelist[i] = vbe_modelist[i];
105 if(!(drv.modes = malloc(count * sizeof *drv.modes))) {
106 errormsg("failed to allocate mode list\n");
112 for(i=0; i<count; i++) {
113 if(get_mode_info(modelist[i], &vbemi) == -1) {
116 if(conv_vbeinfo(modelist[i], drv.modes + drv.num_modes, &vbemi) == -1) {
126 static void cleanup(void)
133 static struct vid_modeinfo *find_mode(int mode)
136 for(i=0; i<drv.num_modes; i++) {
137 if(drv.modes[i].modeno == mode) {
138 return drv.modes + i;
144 static int setmode(int mode)
146 struct vid_modeinfo *minf;
147 struct dpmi_regs regs = {0};
149 if((minf = find_mode(mode)) && minf->lfb) {
150 mode |= VBE_MODE_LFB;
156 dpmi_rmint(0x10, ®s);
158 if((regs.eax & 0xffff) != 0x4f) {
159 if(mode & VBE_MODE_LFB) {
160 mode &= ~VBE_MODE_LFB;
167 if(!(cur_mi = minf)) return 0;
169 cur_pgsize = minf->height * minf->pitch;
171 if(mode & VBE_MODE_LFB) {
172 minf->ops.blit = blit_lfb;
173 minf->ops.blitfb = blitfb_lfb;
175 minf->ops.blit = blit_banked;
176 minf->ops.blitfb = blitfb_banked;
179 print_mode_info(mode, minf);
183 static int getmode(void)
188 static const char *memsize_str(long sz)
190 static const char *suffix[] = {"bytes", "kb", "mb", "gb", 0};
194 while(sz > 1024 && suffix[cnt + 1]) {
199 sprintf(buf, "%ld %s", sz, suffix[cnt]);
203 static int get_mode_info(int mode, struct vbe_mode_info *mi)
205 struct dpmi_regs regs = {0};
206 struct vbe_mode_info *miptr;
209 miptr = dpmi_lowbuf();
210 bufseg = (intptr_t)miptr >> 4;
215 dpmi_rmint(0x10, ®s);
216 if((regs.eax & 0xffff) != 0x4f) {
224 int vid_setwin(int wid, int pos)
226 struct dpmi_regs regs = {0};
231 dpmi_rmint(0x10, ®s);
232 if((regs.eax & 0xffff) != 0x4f) {
238 static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi)
240 static int gran_shift;
241 static const struct { int width, height, bpp; } stdmode[] = {
242 {640, 400, 8}, /* 100h */
243 {640, 480, 8}, /* 101h */
244 {800, 600, 4}, {800, 600, 8}, /* 102h - 103h */
245 {1024, 768, 4}, {1024, 768, 8}, /* 104h - 105h */
246 {1280, 1024, 4}, {1280, 1024, 8}, /* 106h - 107h */
247 {80, 60, 4}, {132, 25, 4}, {132, 43, 4}, {132, 50, 4}, {132, 60, 4},
248 {320, 200, 15}, {320, 200, 16}, {320, 200, 24}, /* 10dh - 10fh */
249 {640, 480, 15}, {640, 480, 16}, {640, 480, 24}, /* 110h - 112h */
250 {800, 600, 15}, {800, 600, 16}, {800, 600, 24}, /* 113h - 115h */
251 {1024, 768, 15}, {1024, 768, 16}, {1024, 768, 24}, /* 116h - 118h */
252 {1280, 1024, 15}, {1280, 1024, 16}, {1280, 1024, 24} /* 119h - 11bh */
255 if(!(vbemi->attr & VBE_ATTR_AVAIL)) {
256 return -1; /* ignore unsupported modes */
258 if(!(vbemi->attr & VBE_ATTR_GFX)) {
259 return -1; /* ignore text modes */
261 if(vbemi->attr & VBE_ATTR_LFB) {
267 mi->vmem_addr = 0xa0000;
269 if(vbe_ver >= 0x0102) {
270 mi->width = vbemi->xres;
271 mi->height = vbemi->yres;
272 mi->bpp = vbemi->bpp;
273 mi->rshift = vbemi->rpos;
274 mi->gshift = vbemi->gpos;
275 mi->bshift = vbemi->bpos;
276 mi->rmask = calc_mask(vbemi->rsize, vbemi->rpos);
277 mi->gmask = calc_mask(vbemi->gsize, vbemi->gpos);
278 mi->bmask = calc_mask(vbemi->bsize, vbemi->bpos);
279 mi->pages = vbemi->num_img_pages + 1;
281 if(vbe_ver >= 0x0200) {
282 mi->vmem_addr = vbemi->fb_addr;
283 mi->vmem_size = vbemi->scanline_bytes * mi->height * mi->pages;
286 if((mode & 0xff) > 7) {
289 mi->width = stdmode[mode & 0xff].width;
290 mi->height = stdmode[mode & 0xff].height;
291 mi->bpp = stdmode[mode & 0xff].bpp;
293 mi->ncolors = 1 << mi->bpp;
294 mi->pitch = vbemi->scanline_bytes;
295 mi->win_size = vbemi->win_size;
296 mi->win_gran = vbemi->win_gran;
300 if(mi->win_gran > 0 && mi->win_gran < 64) {
301 int gran = mi->win_gran;
306 mi->win_step = 1 << gran_shift;
310 mi->ops.unpack = unpack;
311 mi->ops.setpal = vga_setpal;
312 mi->ops.getpal = vga_getpal;
313 mi->ops.vsync = vid_vsync;
314 mi->ops.clear = clear;
321 static unsigned int calc_mask(int nbits, int pos)
324 unsigned int mask = 0;
326 for(i=0; i<nbits; i++) {
327 mask = (mask << 1) | 1;
332 static void print_mode_info(int mode, struct vid_modeinfo *mi)
334 infomsg("VBE mode %04x\n", mode);
335 infomsg(" %dx%d %d bpp (%d colors)\n", mi->width, mi->height,
336 mi->bpp, mi->ncolors);
337 infomsg(" pitch: %d bytes, %d vmem pages\n", mi->pitch, mi->pages);
340 infomsg(" RGB mask %06x %06x %06x (pos: %d %d %d)\n", (unsigned int)mi->rmask,
341 (unsigned int)mi->gmask, (unsigned int)mi->bmask, mi->rshift,
342 mi->gshift, mi->bshift);
345 if(mode & VBE_MODE_LFB) {
346 infomsg(" LFB address %xh, size: %d\n", (unsigned int)mi->vmem_addr,
349 infomsg(" banked window %d kb, granularity: %d kb, step: %d\n", mi->win_size,
350 mi->win_gran, mi->win_step);
355 static void pack(uint32_t *pix, int r, int g, int b)
357 *pix = (((uint32_t)r << cur_mi->rshift) & cur_mi->rmask) |
358 (((uint32_t)g << cur_mi->gshift) & cur_mi->gmask) |
359 (((uint32_t)b << cur_mi->bshift) & cur_mi->bmask);
362 static void unpack(uint32_t pix, int *r, int *g, int *b)
364 *r = (pix & cur_mi->rmask) >> cur_mi->rshift;
365 *g = (pix & cur_mi->gmask) >> cur_mi->gshift;
366 *b = (pix & cur_mi->bmask) >> cur_mi->bshift;
369 static void clear(uint32_t color)
373 static void blit_lfb(int x, int y, int w, int h, void *fb, int pitch)
375 int i, pixsz, spansz;
376 unsigned char *dest, *src;
378 /*dbgmsg("blit: %d,%d (%dx%d)\n", x, y, w, h);*/
380 pixsz = (cur_mi->bpp + 7) >> 3;
383 dest = (char*)vid_vmem + cur_mi->pitch * y + x * pixsz;
387 memcpy(dest, src, spansz);
388 dest += cur_mi->pitch;
393 static void blit_banked(int x, int y, int w, int h, void *fb, int pitch)
398 static void blitfb_lfb(void *fb, int pitch)
400 int i, pixsz, spansz;
401 unsigned char *dest, *src;
403 pixsz = (cur_mi->bpp + 7) >> 3;
404 spansz = cur_mi->width * pixsz;
409 for(i=0; i<cur_mi->height; i++) {
410 memcpy(dest, src, spansz);
411 dest += cur_mi->pitch;
416 static void blitfb_banked(void *fb, int pitch)
418 int sz, offs, pending, winsz;
419 unsigned char *pptr = fb;
421 winsz = cur_mi->win_size << 10;
423 /* assume initial window offset at 0 */
425 pending = cur_pgsize;
427 sz = pending > winsz ? winsz : pending;
428 memcpy((void*)0xa0000, pptr, sz);
431 offs += cur_mi->win_step;
437 static void flip(int vsync)