X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=drv_vbe.c;h=69c89eb54c9b43008aa6df74b73b98d75972b4b4;hb=75aa7ef609cbda625e6c19bc07acf744eb3bfc5a;hp=e051692325e577c4f2d899dd8f6d64efbb1f5baa;hpb=ee6be1955413171a03391c6b171d50bb3f2a5001;p=vidsys diff --git a/drv_vbe.c b/drv_vbe.c index e051692..69c89eb 100644 --- a/drv_vbe.c +++ b/drv_vbe.c @@ -4,6 +4,7 @@ #include "vidsys.h" #include "drv.h" #include "vbe.h" +#include "vga.h" #include "cdpmi.h" #define farptr_to_linear(rmaddr) \ @@ -11,21 +12,35 @@ static int init(void); static void cleanup(void); +static struct vid_modeinfo *find_mode(int mode); static int setmode(int mode); static int getmode(void); static const char *memsize_str(long sz); static int get_mode_info(int mode, struct vbe_mode_info *mi); +static int setwin(int wid, int pos); 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 void pack(uint32_t *pix, int r, int g, int b); +static void unpack(uint32_t pix, int *r, int *g, int *b); +static void clear(uint32_t color); +static void blitfb_lfb(void *fb, int pitch); +static void blitfb_banked(void *fb, int pitch); +static void flip(int vsync); + +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; +static struct vid_modeinfo *cur_mi; +static int cur_pgsize; + void vid_register_vbe(void) { + drv.name = "vbe"; + drv.prio = 2; drv.ops = &drvops; vid_drvlist[vid_numdrv++] = &drv; @@ -42,6 +57,9 @@ static int init(void) int i, count; struct vid_modeinfo modeinf; + cur_mode = -1; + cur_mi = 0; + vbe = dpmi_lowbuf(); bufseg = (intptr_t)vbe >> 4; @@ -50,14 +68,14 @@ static int init(void) regs.eax = 0x4f00; regs.es = bufseg; dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) { + if((regs.eax & 0xffff) != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) { fprintf(stderr, "failed to get VBE controller information\n"); return -1; } 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), @@ -81,31 +99,83 @@ static int init(void) 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; ilfb) { + mode |= VBE_MODE_LFB; + } + +retry: + regs.eax = 0x4f02; + regs.ebx = mode; + dpmi_rmint(0x10, ®s); + + if((regs.eax & 0xffff) != 0x4f) { + if(mode & VBE_MODE_LFB) { + mode &= ~VBE_MODE_LFB; + goto retry; + } + return -1; + } + cur_mode = mode; + + if(!(cur_mi = minf)) return 0; + + cur_pgsize = minf->height * minf->pitch; + + if(mode & VBE_MODE_LFB) { + minf->ops.blitfb = blitfb_lfb; + } else { + minf->ops.blitfb = blitfb_banked; + } + return 0; } static int getmode(void) { - return -1; + return cur_mode; } static const char *memsize_str(long sz) @@ -136,7 +206,7 @@ static int get_mode_info(int mode, struct vbe_mode_info *mi) regs.ecx = mode; regs.es = bufseg; dpmi_rmint(0x10, ®s); - if(regs.eax != 0x4f) { + if((regs.eax & 0xffff) != 0x4f) { return -1; } @@ -144,22 +214,67 @@ static int get_mode_info(int mode, struct vbe_mode_info *mi) return 0; } +static int setwin(int wid, int pos) +{ + struct dpmi_regs regs = {0}; + + regs.eax = 0x4f05; + regs.ebx = wid; + regs.edx = pos; + dpmi_rmint(0x10, ®s); + if((regs.eax & 0xffff) != 0x4f) { + return -1; + } + return 0; +} + static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi) { + static int gran_shift; 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; @@ -168,5 +283,98 @@ static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info 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; + + gran_shift = 0; + mi->win_step = 1; + if(mi->win_gran > 0 && mi->win_gran < 64) { + int gran = mi->win_gran; + while(gran < 64) { + gran_shift++; + gran <<= 1; + } + mi->win_step = 1 << gran_shift; + } + + mi->ops.pack = pack; + mi->ops.unpack = unpack; + mi->ops.setpal = vga_setpal; + mi->ops.getpal = vga_getpal; + mi->ops.vsync = vga_vsync; + mi->ops.clear = clear; + mi->ops.blitfb = 0; + mi->ops.flip = flip; return 0; } + +static unsigned int calc_mask(int nbits, int pos) +{ + int i; + unsigned int mask = 0; + + for(i=0; irshift) & cur_mi->rmask) | + (((uint32_t)g << cur_mi->gshift) & cur_mi->gmask) | + (((uint32_t)b << cur_mi->bshift) & cur_mi->bmask); +} + +static void unpack(uint32_t pix, int *r, int *g, int *b) +{ + *r = (pix & cur_mi->rmask) >> cur_mi->rshift; + *g = (pix & cur_mi->gmask) >> cur_mi->gshift; + *b = (pix & cur_mi->bmask) >> cur_mi->bshift; +} + +static void clear(uint32_t color) +{ +} + +static void blitfb_lfb(void *fb, int pitch) +{ + int i; + unsigned char *dest, *src; + + dest = vid_vmem; + src = fb; + + for(i=0; iheight; i++) { + memcpy(dest, src, cur_mi->pitch); + dest += cur_mi->pitch; + src += pitch; + } +} + +static void blitfb_banked(void *fb, int pitch) +{ + int sz, offs, pending; + unsigned char *pptr = fb; + + /* assume initial window offset at 0 */ + offs = 0; + pending = cur_pgsize; + while(pending > 0) { + sz = pending > 65536 ? 65536 : pending; + memcpy((void*)0xa0000, pptr, sz); + pptr += sz; + pending -= sz; + offs += cur_mi->win_step; + setwin(0, offs); + } + setwin(0, 0); +} + +static void flip(int vsync) +{ + /* TODO */ +}