static const char *memsize_str(long sz);
static int get_mode_info(int mode, struct vbe_mode_info *mi);
static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi);
+static unsigned int calc_mask(int nbits, int pos);
-static struct vid_driver drv = {"vbe", 2};
+static struct vid_driver drv;
static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
-static struct vid_modeinfo *modes;
-static int num_modes;
static unsigned int vbe_ver;
+static int cur_mode;
+
void vid_register_vbe(void)
{
+ drv.name = "vbe";
+ drv.prio = 2;
drv.ops = &drvops;
vid_drvlist[vid_numdrv++] = &drv;
int i, count;
struct vid_modeinfo modeinf;
+ cur_mode = -1;
+
vbe = dpmi_lowbuf();
bufseg = (intptr_t)vbe >> 4;
vbe_ver = vbe->ver;
- printf("Found VBE %d.%d\n", vbe_ver >> 8, vbe_ver & 0xff);
+ printf("Found VBE %d.%d\n", VBE_VER_MAJOR(vbe_ver), VBE_VER_MINOR(vbe_ver));
printf("OEM: %s\n", (char*)farptr_to_linear(vbe->oem_name));
if(vbe_ver >= 0x0200) {
printf("%s - %s (%s)\n", (char*)farptr_to_linear(vbe->vendor),
modelist[i] = vbe_modelist[i];
}
- printf("found %d modes\n", count);
- return 0;
- num_modes = 0;
+ if(!(drv.modes = malloc(count * sizeof *drv.modes))) {
+ fprintf(stderr, "failed to allocate mode list\n");
+ free(modelist);
+ return -1;
+ }
+
+ drv.num_modes = 0;
for(i=0; i<count; i++) {
if(get_mode_info(modelist[i], &vbemi) == -1) {
continue;
}
- conv_vbeinfo(modelist[i], modes + num_modes++, &vbemi);
+ if(conv_vbeinfo(modelist[i], drv.modes + drv.num_modes, &vbemi) == -1) {
+ continue;
+ }
+ drv.num_modes++;
}
+ free(modelist);
return 0;
}
static void cleanup(void)
{
+ free(drv.modes);
+ drv.modes = 0;
+ drv.num_modes = 0;
}
static int setmode(int mode)
{
- return -1;
+ struct dpmi_regs regs = {0};
+
+ regs.eax = 0x4f02;
+ regs.ebx = mode | VBE_MODE_LFB;
+ dpmi_rmint(0x10, ®s);
+
+ if(regs.eax != 0x4f) {
+ regs.eax = 0x4f02;
+ regs.ebx = mode;
+ dpmi_rmint(0x10, ®s);
+ if(regs.eax != 0x4f) {
+ return -1;
+ }
+ cur_mode = mode;
+ } else {
+ cur_mode = mode | VBE_MODE_LFB;
+ }
+ return 0;
}
static int getmode(void)
{
- return -1;
+ return cur_mode;
}
static const char *memsize_str(long sz)
static const struct { int width, height, bpp; } stdmode[] = {
{640, 400, 8}, /* 100h */
{640, 480, 8}, /* 101h */
- {800, 600, 4}, /* 102h */
- {800, 600, 8}, /* 103h */
- {1024, 768, 4}, /* 104h */
- {1024, 768, 8}, /* 105h */
- {1280, 1024, 4}, /* 106h */
- {1280, 1024, 8} /* 107h */
+ {800, 600, 4}, {800, 600, 8}, /* 102h - 103h */
+ {1024, 768, 4}, {1024, 768, 8}, /* 104h - 105h */
+ {1280, 1024, 4}, {1280, 1024, 8}, /* 106h - 107h */
+ {80, 60, 4}, {132, 25, 4}, {132, 43, 4}, {132, 50, 4}, {132, 60, 4},
+ {320, 200, 15}, {320, 200, 16}, {320, 200, 24}, /* 10dh - 10fh */
+ {640, 480, 15}, {640, 480, 16}, {640, 480, 24}, /* 110h - 112h */
+ {800, 600, 15}, {800, 600, 16}, {800, 600, 24}, /* 113h - 115h */
+ {1024, 768, 15}, {1024, 768, 16}, {1024, 768, 24}, /* 116h - 118h */
+ {1280, 1024, 15}, {1280, 1024, 16}, {1280, 1024, 24} /* 119h - 11bh */
};
+
+ if(!(vbemi->attr & VBE_ATTR_AVAIL)) {
+ return -1; /* ignore unsupported modes */
+ }
+ if(!(vbemi->attr & VBE_ATTR_GFX)) {
+ return -1; /* ignore text modes */
+ }
+ if(vbemi->attr & VBE_ATTR_LFB) {
+ mi->lfb = 1;
+ }
+
+ mi->drv = &drv;
+ mi->modeno = mode;
+ mi->vmem_addr = 0xa0000;
+
if(vbe_ver >= 0x0102) {
mi->width = vbemi->xres;
mi->height = vbemi->yres;
mi->bpp = vbemi->bpp;
+ mi->rshift = vbemi->rpos;
+ mi->gshift = vbemi->gpos;
+ mi->bshift = vbemi->bpos;
+ mi->rmask = calc_mask(vbemi->rsize, vbemi->rpos);
+ mi->gmask = calc_mask(vbemi->gsize, vbemi->gpos);
+ mi->bmask = calc_mask(vbemi->bsize, vbemi->bpos);
+ mi->pages = vbemi->num_img_pages + 1;
+
+ if(vbe_ver >= 0x0200) {
+ mi->vmem_addr = vbemi->fb_addr;
+ mi->vmem_size = vbemi->scanline_bytes * mi->height * mi->pages;
+ }
} else {
if((mode & 0xff) > 7) {
return -1;
mi->height = stdmode[mode & 0xff].height;
mi->bpp = stdmode[mode & 0xff].bpp;
}
+ mi->ncolors = 1 << mi->bpp;
+ mi->pitch = vbemi->scanline_bytes;
+ mi->win_size = vbemi->win_size;
+ mi->win_gran = vbemi->win_gran;
return 0;
}
+
+static unsigned int calc_mask(int nbits, int pos)
+{
+ int i;
+ unsigned int mask = 0;
+
+ for(i=0; i<nbits; i++) {
+ mask = (mask << 1) | 1;
+ }
+ return mask << pos;
+}