diff -urN ../svgalib-1.4.3-orig/src/fbdev.c ./src/fbdev.c --- ../svgalib-1.4.3-orig/src/fbdev.c 2000-08-28 00:16:06 +0900 +++ src/fbdev.c 2003-09-01 18:36:50 +0900 @@ -1,514 +1,493 @@ -#include +/* Driver for Linux framebuffer + * Written by Andrew Church + * Loosely based on Cirrus driver code. + */ + +#include +#include +#include +#include +#include +#include #include #include #include -#include -#include -#include -#include -#include #include "vga.h" #include "libvga.h" #include "driver.h" #include "timing.h" #include "interface.h" +#include "vgaregs.h" +#include "accel.h" + +#ifdef BACKGROUND +# error fbdev does not work with BACKGROUND, please undefine it. +#endif + +/*************************************************************************/ -extern unsigned char * B8000_MEM_POINTER; +/* FD used for framebuffer device (/dev/fbN), -1 = not opened. */ +static int fb_fd = -1; + +/* Static information about the framebuffer device. */ +static struct fb_fix_screeninfo fb_fix; -static int fbdev_fd; -static size_t fbdev_memory; -static size_t fbdev_startaddressrange; static CardSpecs *cardspecs; -static struct console_font_op fbdev_font; -static struct fb_var_screeninfo fbdev_textmode; -/* Card Specs */ +static int fbdev_linear_flag = 0; -static int fbdev_match_programmable_clock(int clock) -{ - return clock; -} +/*************************************************************************/ -static int fbdev_map_clock(int bpp, int clock) -{ - return clock; -} +static int fbdev_test(void); +static int fbdev_init(int force, int par1, int par2); +static int fbdev_saveregs(unsigned char regs[]); +static void fbdev_setregs(const unsigned char regs[], int mode); +static void fbdev_getmodeinfo(int mode, vga_modeinfo *modeinfo); +static int fbdev_modeavailable(int mode); +static int fbdev_setmode(int mode, int prv_mode); +static void fbdev_unlock(void); +static void fbdev_lock(void); +static void fbdev_setpage(int page); +static void fbdev_setrdpage(int page); +static void fbdev_setwrpage(int page); +static void fbdev_setdisplaystart(int address); +static void fbdev_setlogicalwidth(int width); +static int fbdev_linear(int op, int param); +static int fbdev_setpalette(int index, int red, int green, int blue); +static void fbdev_getpalette(int index, int *red, int *green, int *blue); +static void fbdev_savepalette(unsigned char *red, unsigned char *green, + unsigned char *blue); +static void fbdev_restorepalette(const unsigned char *red, + const unsigned char *green, + const unsigned char *blue); -static int fbdev_map_horizontal_crtc(int bpp, int pixelclock, int htiming) -{ - return htiming; -} +/* Function tables. */ -/* Driver Specs */ +static Emulation fbdev_emul = { + setpalette: fbdev_setpalette, + getpalette: fbdev_getpalette, + savepalette: fbdev_savepalette, + restorepalette: fbdev_restorepalette, +}; -static int fbdev_saveregs(unsigned char *regs) +DriverSpecs __svgalib_fbdev_driverspecs = { - ioctl(fbdev_fd, FBIOGET_VSCREENINFO, regs+EXT); - return sizeof(struct fb_var_screeninfo); -} + fbdev_saveregs, + fbdev_setregs, + fbdev_unlock, + fbdev_lock, + fbdev_test, + fbdev_init, + fbdev_setpage, + fbdev_setrdpage, + fbdev_setwrpage, + fbdev_setmode, + fbdev_modeavailable, + fbdev_setdisplaystart, + fbdev_setlogicalwidth, + fbdev_getmodeinfo, + 0, /* old blit funcs */ + 0, + 0, + 0, + 0, + 0, /* ext_set */ + 0, /* accel */ + fbdev_linear, + NULL, /* Accelspecs */ + &fbdev_emul, /* Emulation */ +}; -static void fbdev_setregs(const unsigned char *regs, int mode) -{ - ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, regs+EXT); -} -static void fbdev_unlock(void) -{ -} +/*************************************************************************/ +/*************************************************************************/ -static void fbdev_lock(void) +/* Test for the presence of the framebuffer device. If found, initialize + * and return 1, else return 0. + */ + +static int fbdev_test(void) { + fb_fd = open("/dev/fb0", O_RDONLY); + if (fb_fd < 0) { + if (errno == EPERM) { + fprintf(stderr, "svgalib(fbdev): Permission denied on framebuffer device.\n"); + exit(1); + } + return 0; + } + return !fbdev_init(0,0,0); } -static int fbdev_init(int force, int par1, int par2) -{ - struct fb_fix_screeninfo info; - int fd; +/*************************************************************************/ - if ((fd = open("/dev/fb0", O_RDWR)) < 0) - { - return -1; - } +/* Initialize the framebuffer device. */ - if (ioctl(fd, FBIOGET_FSCREENINFO, &info)) - { - close(fd); - return -1; - } +static int fbdev_mapClock(int bpp, int pixelclock); +static int fbdev_matchProgrammableClock(int desiredclock); +static int fbdev_mapHorizontalCrtc(int bpp, int pixelclock, int htiming); - if (ioctl(fd, FBIOGET_VSCREENINFO, &fbdev_textmode)) - { - close(fd); - return -1; - } +static int fbdev_init(int force, int par1, int par2) +{ + if (fb_fd < 0 && !fbdev_test()) + return -1; + if (ioctl(fb_fd, FBIOGET_FSCREENINFO, &fb_fix) < 0) + return -1; - fbdev_memory = info.smem_len; - fbdev_fd = fd; + __svgalib_novga = 1; /* No user-serviceable parts inside */ - fbdev_startaddressrange = 65536; - while (fbdev_startaddressrange < fbdev_memory) - { - fbdev_startaddressrange <<= 1; - } - fbdev_startaddressrange -= 1; + cardspecs = malloc(sizeof(CardSpecs)); + cardspecs->videoMemory = fb_fix.smem_len; + /* The kernel takes care of clock setting, so put bogus values here */ + cardspecs->maxPixelClock4bpp = 999999; + cardspecs->maxPixelClock8bpp = 999999; + cardspecs->maxPixelClock16bpp = 999999; + cardspecs->maxPixelClock24bpp = 999999; + cardspecs->maxPixelClock32bpp = 999999; + cardspecs->nClocks = 0; + cardspecs->flags = CLOCK_PROGRAMMABLE; + cardspecs->mapClock = fbdev_mapClock; + cardspecs->matchProgrammableClock = fbdev_matchProgrammableClock; + cardspecs->mapHorizontalCrtc = fbdev_mapHorizontalCrtc; + cardspecs->maxHorizontalCrtc = 65535; - cardspecs = malloc(sizeof(CardSpecs)); - cardspecs->videoMemory = fbdev_memory; + __svgalib_fbdev_driverspecs.accelspecs = malloc(sizeof(AccelSpecs)); + __svgalib_clear_accelspecs(__svgalib_fbdev_driverspecs.accelspecs); + __svgalib_fbdev_driverspecs.accelspecs->flags = ACCELERATE_ANY_LINEWIDTH; -/* FIXME: autodetect these */ - cardspecs->maxPixelClock4bpp = 200000; - cardspecs->maxPixelClock8bpp = 200000; - cardspecs->maxPixelClock16bpp = 200000; - cardspecs->maxPixelClock24bpp = 200000; - cardspecs->maxPixelClock32bpp = 200000; - cardspecs->maxHorizontalCrtc = 8192; - - cardspecs->flags = CLOCK_PROGRAMMABLE; - - cardspecs->nClocks = 0; - cardspecs->clocks = 0; - - cardspecs->mapClock = fbdev_map_clock; - cardspecs->matchProgrammableClock = fbdev_match_programmable_clock; - cardspecs->mapHorizontalCrtc = fbdev_map_horizontal_crtc; - - __svgalib_driverspecs = &__svgalib_fbdev_driverspecs; - __svgalib_banked_mem_base = info.smem_start; - __svgalib_banked_mem_size = 0x10000; - __svgalib_linear_mem_base = info.smem_start; - __svgalib_linear_mem_size = fbdev_memory; - - __svgalib_novga = 1; - B8000_MEM_POINTER = (void *)0xB8000; - BANKED_MEM_POINTER = mmap(0, __svgalib_banked_mem_size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - LINEAR_MEM_POINTER = mmap(0, __svgalib_linear_mem_size, - PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + __svgalib_driverspecs = &__svgalib_fbdev_driverspecs; - return 0; + __svgalib_banked_mem_base = fb_fix.smem_start; + __svgalib_banked_mem_size = 0x10000; + __svgalib_linear_mem_base = fb_fix.smem_start; + __svgalib_linear_mem_size = fb_fix.smem_len; + __svgalib_mmio_size = 0; + __svgalib_mmio_base = 0; + return 0; } -static int fbdev_test(void) -{ - return !fbdev_init(0, 0, 0); +static int fbdev_mapClock(int bpp, int pixelclock) { + return pixelclock; } -static void fbdev_setpage(int page) -{ - static int oldpage = 0; - - if (page != oldpage) - { -// munmap(BANKED_MEM_POINTER, __svgalib_banked_mem_size); - mmap(BANKED_MEM_POINTER, __svgalib_banked_mem_size, - PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, - fbdev_fd, page * __svgalib_banked_mem_size); - oldpage = page; - } +static int fbdev_matchProgrammableClock(int desiredclock) { + return desiredclock; } -static int fbdev_screeninfo(struct fb_var_screeninfo *info, int mode) -{ - ModeTiming modetiming; - ModeInfo *modeinfo; - - /* The VGA modes don't work */ - - if ((mode < G640x480x256 ) || mode == G720x348x2) - return 1; +static int fbdev_mapHorizontalCrtc(int bpp, int pixelclock, int htiming) { + return htiming; +} - if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, info)) - return 1; +/*************************************************************************/ - modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); +/* Read and save chipset-specific registers */ - if (__svgalib_getmodetiming(&modetiming, modeinfo, cardspecs)) - { - free(modeinfo); - return 1; - } +static int fbdev_saveregs(unsigned char regs[]) +{ + ioctl(fb_fd, FBIOGET_VSCREENINFO, ®s[VGA_TOTAL_REGS]); + return sizeof(struct fb_var_screeninfo); +} - info->xres = modeinfo->width; - info->yres = modeinfo->height; - info->xres_virtual = modeinfo->width; - info->yres_virtual = modeinfo->height; - info->xoffset = 0; - info->yoffset = 0; - info->bits_per_pixel = modeinfo->bitsPerPixel; - info->grayscale = 0; - info->red.offset = modeinfo->redOffset; - info->red.length = modeinfo->redWeight; - info->red.msb_right = 0; - info->green.offset = modeinfo->greenOffset; - info->green.length = modeinfo->greenWeight; - info->green.msb_right = 0; - info->blue.offset = modeinfo->blueOffset; - info->blue.length = modeinfo->blueWeight; - info->blue.msb_right = 0; - info->nonstd = 0; - - free(modeinfo); - - info->vmode &= FB_VMODE_MASK; - - if (modetiming.flags & INTERLACED) - info->vmode |= FB_VMODE_INTERLACED; - if (modetiming.flags & DOUBLESCAN) - { - info->vmode |= FB_VMODE_DOUBLE; - modetiming.VDisplay >>= 1; - modetiming.VSyncStart >>= 1; - modetiming.VSyncEnd >>= 1; - modetiming.VTotal >>= 1; - } +/*************************************************************************/ - info->pixclock = 1000000000 / modetiming.pixelClock; - info->left_margin = modetiming.HTotal - modetiming.HSyncEnd; - info->right_margin = modetiming.HSyncStart - modetiming.HDisplay; - info->upper_margin = modetiming.VTotal - modetiming.VSyncEnd; - info->lower_margin = modetiming.VSyncStart - modetiming.VDisplay; - info->hsync_len = modetiming.HSyncEnd - modetiming.HSyncStart; - info->vsync_len = modetiming.VSyncEnd - modetiming.VSyncStart; - - info->sync &= ~(FB_SYNC_HOR_HIGH_ACT|FB_SYNC_VERT_HIGH_ACT); - - if (modetiming.flags & PHSYNC) - info->sync |= FB_SYNC_HOR_HIGH_ACT; - if (modetiming.flags & PVSYNC) - info->sync |= FB_SYNC_VERT_HIGH_ACT; +/* Set chipset-specific registers */ - return 0; +static void fbdev_setregs(const unsigned char regs[], int mode) +{ + struct fb_var_screeninfo *fb_var = + (struct fb_var_screeninfo *) ®s[VGA_TOTAL_REGS]; + fb_var->activate = FB_ACTIVATE_NOW; + ioctl(fb_fd, FBIOPUT_VSCREENINFO, fb_var); } -static void fbdev_set_virtual_height(struct fb_var_screeninfo *info) -{ - int maxpixels = fbdev_memory; - int bytesperpixel = info->bits_per_pixel / 8; - - if (bytesperpixel) - maxpixels /= bytesperpixel; +/*************************************************************************/ - info->yres_virtual = maxpixels / info->xres_virtual; -} +/* Fill in chipset specific mode information */ -static int fbdev_setmode(int mode, int prv_mode) +static void fbdev_getmodeinfo(int mode, vga_modeinfo *modeinfo) { - struct fb_var_screeninfo info; + if (modeinfo->bytesperpixel > 0) + modeinfo->maxpixels = fb_fix.smem_len / modeinfo->bytesperpixel; + else /* 16-color mode */ + modeinfo->maxpixels = fb_fix.smem_len * 2; + modeinfo->maxlogicalwidth = 65535; + modeinfo->startaddressrange = fb_fix.smem_len * 1024 - 1; + modeinfo->haveblit = 0; +#if 0 /* Who cares. */ + if (fbdev_interlaced(mode)) + modeinfo->flags |= IS_INTERLACED; +#endif + modeinfo->flags &= ~HAVE_RWPAGE; + modeinfo->flags |= CAPABLE_LINEAR | fbdev_linear_flag; +} - if (mode == TEXT) - { - if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &fbdev_textmode)) - return 1; - - memset(LINEAR_MEM_POINTER, 0, - fbdev_textmode.bits_per_pixel ? - fbdev_textmode.xres_virtual * - fbdev_textmode.yres_virtual * - fbdev_textmode.bits_per_pixel / 8 : 65536); - } - else - { - if (fbdev_screeninfo(&info, mode)) - return 1; +/*************************************************************************/ - fbdev_set_virtual_height(&info); +/* Return nonzero if mode is available */ - if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &info)) - return 1; - } +static int fbdev_modeavailable(int mode) +{ + struct info *info; + info = &__svgalib_infotable[mode]; + if (fb_fix.smem_len < info->ydim * info->xbytes) return 0; + return SVGADRV; } -static int fbdev_modeavailable(int mode) -{ - struct fb_var_screeninfo info; - unsigned g; - - if (fbdev_screeninfo(&info, mode)) - return 0; +/*************************************************************************/ +/*************************************************************************/ - g = info.green.length; +/* Set a mode. Returns 0 on success, 1 on failure. */ - info.activate = FB_ACTIVATE_TEST; - if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &info)) - return 0; +static int fbdev_real_setmode(ModeTiming *modetiming, ModeInfo *modeinfo); - if (info.bits_per_pixel == 16 && - info.green.length != g) - return 0; +static int fbdev_setmode(int mode, int prv_mode) +{ + ModeTiming modetiming; + ModeInfo *modeinfo; + int n = 999999, lastclock = -1; + + if (!fbdev_modeavailable(mode)) + return 1; + + modeinfo = __svgalib_createModeInfoStructureForSvgalibMode(mode); + + for (;;) { + /* Abort if our temporary max pixel clock (see below) drops + * below 5MHz. */ + if (cardspecs->maxPixelClock8bpp < 5000 + || __svgalib_getmodetiming(&modetiming, modeinfo, cardspecs) + ) { + free(modeinfo); + cardspecs->maxPixelClock4bpp = 999999; + cardspecs->maxPixelClock8bpp = 999999; + cardspecs->maxPixelClock16bpp = 999999; + cardspecs->maxPixelClock24bpp = 999999; + cardspecs->maxPixelClock32bpp = 999999; + return 1; + } +/*printf("fbdev: got timing for mode %dx%d-%d:\n%d %d %d %d %d %d %d %d %d\n", +modeinfo->width,modeinfo->height,modeinfo->bitsPerPixel,modetiming.pixelClock, +modetiming.HDisplay,modetiming.HSyncStart,modetiming.HSyncEnd,modetiming.HTotal, +modetiming.VDisplay,modetiming.VSyncStart,modetiming.VSyncEnd,modetiming.VTotal);*/ + if (fbdev_real_setmode(&modetiming, modeinfo)) { + /* We were able to set the mode */ + cardspecs->maxPixelClock4bpp = 999999; + cardspecs->maxPixelClock8bpp = 999999; + cardspecs->maxPixelClock16bpp = 999999; + cardspecs->maxPixelClock24bpp = 999999; + cardspecs->maxPixelClock32bpp = 999999; + break; + } + /* Temporarily redefine maximum pixel clock to make getmodetiming() + * give us the next best mode available. If we got back the same + * clock as last time, cut the previous value down further (avoid + * infinite loops). */ + if (modetiming.pixelClock != lastclock) + n = modetiming.pixelClock; + n = n*989 / 1000; + cardspecs->maxPixelClock4bpp = n; + cardspecs->maxPixelClock8bpp = n; + cardspecs->maxPixelClock16bpp = n; + cardspecs->maxPixelClock24bpp = n; + cardspecs->maxPixelClock32bpp = n; + } + + __svgalib_InitializeAcceleratorInterface(modeinfo); + + free(modeinfo); + return 0; +} + +/*************************************************************************/ + +/* Attempt to actually set the specified mode. Return 1 on success, 0 on + * failure. + */ + +static int fbdev_real_setmode(ModeTiming *modetiming, ModeInfo *modeinfo) +{ + struct fb_var_screeninfo var; + int res; + + memset(&var, 0, sizeof(var)); + var.xres = modeinfo->width; + var.yres = modeinfo->height; + var.xres_virtual = modeinfo->width; + var.yres_virtual = modeinfo->height; + var.bits_per_pixel = modeinfo->bitsPerPixel; + var.red .offset = modeinfo->redOffset; + var.red .length = modeinfo->redWeight; + var.green.offset = modeinfo->greenOffset; + var.green.length = modeinfo->greenWeight; + var.blue .offset = modeinfo->blueOffset; + var.blue .length = modeinfo->blueWeight; + var.height = modeinfo->height; /* FIXME: Are these 2 correct? */ + var.width = modeinfo->lineWidth; + var.pixclock = 1000000000 / modetiming->pixelClock; /* picoseconds */ + var.left_margin = modetiming->HTotal - modetiming->HSyncEnd; + var.right_margin = modetiming->HSyncStart - modetiming->HDisplay; + var.upper_margin = modetiming->VTotal - modetiming->VSyncEnd; + var.lower_margin = modetiming->VSyncStart - modetiming->VDisplay; + var.hsync_len = modetiming->HSyncEnd - modetiming->HSyncStart; + var.vsync_len = modetiming->VSyncEnd - modetiming->VSyncStart; + if (modetiming->flags & PHSYNC) + var.sync |= FB_SYNC_HOR_HIGH_ACT; + if (modetiming->flags & PVSYNC) + var.sync |= FB_SYNC_VERT_HIGH_ACT; + if (modetiming->flags & INTERLACED) + var.vmode = FB_VMODE_INTERLACED; + else if (modetiming->flags & DOUBLESCAN) { + var.vmode = FB_VMODE_DOUBLE; + var.upper_margin >>= 1; + var.lower_margin >>= 1; + var.vsync_len >>= 1; + } + + res = ioctl(fb_fd, FBIOPUT_VSCREENINFO, &var); +/*printf("put_var: res=%d (%s)\n",res,strerror(errno));*/ + return res == 0; +} - /* We may need to add more checks here. */ +/*************************************************************************/ +/*************************************************************************/ - return SVGADRV; -} +/* Unlock chipset-specific registers (not used by fbdev) */ -static void fbdev_setdisplaystart(int address) +static void fbdev_unlock(void) { - struct fb_var_screeninfo info; - - if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &info)) - return; +} - info.xoffset = address % info.xres_virtual; - info.yoffset = address / info.xres_virtual; +/*************************************************************************/ - ioctl(fbdev_fd, FBIOPAN_DISPLAY, &info); -} +/* Relock chipset-specific registers (not used by fbdev) */ -static void fbdev_setlogicalwidth(int width) +static void fbdev_lock(void) { - struct fb_var_screeninfo info; +} - if (ioctl(fbdev_fd, FBIOGET_VSCREENINFO, &info)) - return; +/*************************************************************************/ - info.xres_virtual = width; - fbdev_set_virtual_height(&info); +/* Bank switching functions. + * fbdev does not use rdpage and wrpage. setpage is emulated by changing + * __svgalib_graph_mem to point at the appropriate part of the framebuffer + * memory, which may or may not be entirely safe. + */ - ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &info); +static void fbdev_setpage(int page) +{ + __svgalib_graph_mem = LINEAR_MEM_POINTER + (page<<16); } -static void fbdev_getmodeinfo(int mode, vga_modeinfo * modeinfo) +static void fbdev_setrdpage(int page) { - struct fb_var_screeninfo info; - int maxpixels = fbdev_memory; - - if (modeinfo->bytesperpixel) - maxpixels /= modeinfo->bytesperpixel; - - modeinfo->maxlogicalwidth = maxpixels / modeinfo->height; - modeinfo->startaddressrange = fbdev_startaddressrange; - modeinfo->maxpixels = maxpixels; - modeinfo->haveblit = 0; - modeinfo->flags |= (__svgalib_modeinfo_linearset | CAPABLE_LINEAR); - - if (fbdev_screeninfo(&info, mode)) - return; - - info.activate = FB_ACTIVATE_TEST; - if (ioctl(fbdev_fd, FBIOPUT_VSCREENINFO, &info)) - return; - - modeinfo->linewidth = info.xres_virtual * info.bits_per_pixel / 8; } -static int fbdev_linear(int op, int param) +static void fbdev_setwrpage(int page) { - switch(op) - { - case LINEAR_QUERY_BASE: - return __svgalib_linear_mem_base; - case LINEAR_ENABLE: - case LINEAR_DISABLE: - return 0; - } - return -1; } -/* Emulation */ +/*************************************************************************/ -static void fbdev_savepalette(unsigned char *red, - unsigned char *green, - unsigned char *blue) -{ - __u16 r[256], g[256], b[256], t[256]; - struct fb_cmap cmap; - unsigned i; - - cmap.start = 0; - cmap.len = 256; - cmap.red = r; - cmap.green = g; - cmap.blue = b; - cmap.transp = t; - - if (ioctl(fbdev_fd, FBIOGETCMAP, &cmap)) - return; - - for (i = 0; i < 256; i++) - { - red[i] = r[i] >> 10; - green[i] = g[i] >> 10; - blue[i] = b[i] >> 10; - } -} +/* Set display start address (not for 16 color modes) */ +/* fbdev currently only allows Y scrolling */ -static void fbdev_restorepalette(const unsigned char *red, - const unsigned char *green, - const unsigned char *blue) +static void fbdev_setdisplaystart(int address) { - __u16 r[256], g[256], b[256], t[256]; - struct fb_cmap cmap; - unsigned i; - - for (i = 0; i < 256; i++) - { - r[i] = (red[i] << 10) | (red[i] << 4) | (red[i] >> 2); - g[i] = (green[i] << 10) | (green[i] << 4) | (green[i] >> 2); - b[i] = (blue[i] << 10) | (blue[i] << 4) | (blue[i] >> 2); - t[i] = 0; - } + struct fb_var_screeninfo var; + int yoffset; - cmap.start = 0; - cmap.len = 256; - cmap.red = r; - cmap.green = g; - cmap.blue = b; - cmap.transp = t; - - ioctl(fbdev_fd, FBIOPUTCMAP, &cmap); + if (ioctl(fb_fd, FBIOGET_VSCREENINFO, &var) < 0) + return; + yoffset = address / (var.xres_virtual * var.bits_per_pixel / 8); + ioctl(fb_fd, FBIOPAN_DISPLAY, 0, yoffset); } -static int fbdev_setpalette(int index, int red, int green, int blue) -{ - __u16 r, g, b, t; - struct fb_cmap cmap; - - r = (red << 10) | (red << 4) | (red >> 2); - g = (green << 10) | (green << 4) | (green >> 2); - b = (blue << 10) | (blue << 4) | (blue >> 2); - t = 0; - - cmap.start = index; - cmap.len = 1; - cmap.red = &r; - cmap.green = &g; - cmap.blue = &b; - cmap.transp = &t; - ioctl(fbdev_fd, FBIOPUTCMAP, &cmap); +/*************************************************************************/ - return 0; -} +/* Set logical scanline length (usually multiple of 8) */ +/* Not currently supported by fbdev */ -static void fbdev_getpalette(int index, int *red, int *green, int *blue) +static void fbdev_setlogicalwidth(int width) { - __u16 r, g, b, t; - struct fb_cmap cmap; +} - cmap.start = 0; - cmap.len = 1; - cmap.red = &r; - cmap.green = &g; - cmap.blue = &b; - cmap.transp = &t; +/*************************************************************************/ - if (ioctl(fbdev_fd, FBIOGETCMAP, &cmap)) - return; +/* Set/query linear mode. */ - *red = r >> 10; - *green = g >> 10; - *blue = b >> 10; +static int fbdev_linear(int op, int param) +{ + if (op == LINEAR_ENABLE) { + fbdev_linear_flag = IS_LINEAR; + return 0; + } + if (op == LINEAR_DISABLE) { + fbdev_linear_flag = 0; + return 0; + } + if (op == LINEAR_QUERY_BASE) + return fb_fix.smem_start; + if (op == LINEAR_QUERY_RANGE || op == LINEAR_QUERY_GRANULARITY) + return 0; /* No granularity or range. */ + else + return -1; /* Unknown function. */ } -static void fbdev_savefont(void) +/*************************************************************************/ +/*************************************************************************/ + +static int fbdev_setpalette(int index, int red, int green, int blue) { - fbdev_font.op = KD_FONT_OP_GET; - fbdev_font.flags = 0; - fbdev_font.width = 32; - fbdev_font.height = 32; - fbdev_font.charcount = 512; - fbdev_font.data = malloc(65536); + struct fb_cmap cmap; + __u16 red16, green16, blue16; - ioctl(fbdev_fd, KDFONTOP, &fbdev_font); + red16 = red<<10; + green16 = green<<10; + blue16 = blue<<10; + cmap.start = index; + cmap.len = 1; + cmap.red = &red16; + cmap.green = &green16; + cmap.blue = &blue16; + cmap.transp = NULL; + return ioctl(fb_fd, FBIOPUTCMAP, &cmap); } -static void fbdev_restorefont(void) +/*************************************************************************/ + +static void fbdev_getpalette(int index, int *red, int *green, int *blue) { - struct fb_var_screeninfo info; + struct fb_cmap cmap; + __u16 red16 = 0, green16 = 0, blue16 = 0; - fbdev_font.op = KD_FONT_OP_SET; - ioctl(fbdev_fd, KDFONTOP, &fbdev_font); + cmap.start = index; + cmap.len = 1; + cmap.red = &red16; + cmap.green = &green16; + cmap.blue = &blue16; + cmap.transp = NULL; + ioctl(fb_fd, FBIOGETCMAP, &cmap); + *red = red16>>10; + *green = green16>>10; + *blue = blue16>>10; } -static void fbdev_waitretrace(void) +/*************************************************************************/ + +static void fbdev_savepalette(unsigned char *red, unsigned char *green, + unsigned char *blue) { - /* This is from SDL */ -#ifdef FBIOWAITRETRACE - ioctl(console_fd, FBIOWAITRETRACE, 0); -#endif } -/* Function tables */ +/*************************************************************************/ -static Emulation fbdev_vgaemul = +static void fbdev_restorepalette(const unsigned char *red, + const unsigned char *green, + const unsigned char *blue) { - fbdev_savepalette, - fbdev_restorepalette, - fbdev_setpalette, - fbdev_getpalette, - fbdev_savefont, - fbdev_restorefont, - 0, /* screenoff */ - 0, /* screenon */ - fbdev_waitretrace -}; +} -DriverSpecs __svgalib_fbdev_driverspecs = -{ - fbdev_saveregs, - fbdev_setregs, - fbdev_unlock, - fbdev_lock, - fbdev_test, - fbdev_init, - fbdev_setpage, - 0, /* setrdpage */ - 0, /* setwrpage */ - fbdev_setmode, - fbdev_modeavailable, - fbdev_setdisplaystart, - fbdev_setlogicalwidth, - fbdev_getmodeinfo, - 0, /* bitblt */ - 0, /* imageblt */ - 0, /* fillblt */ - 0, /* hlinelistblt */ - 0, /* bltwait */ - 0, /* extset */ - 0, /* accel */ - fbdev_linear, - 0, /* Accelspecs */ - &fbdev_vgaemul -}; +/*************************************************************************/ diff -urN ../svgalib-1.4.3-orig/src/vga.c ./src/vga.c --- ../svgalib-1.4.3-orig/src/vga.c 2001-05-29 23:37:55 +0900 +++ src/vga.c 2003-09-01 18:38:15 +0900 @@ -720,7 +720,7 @@ "I740", "NEOMAGIC", "LAGUNA", -"FBDev", +"FBDEV", "G400", "R128", "Savage", @@ -837,8 +837,8 @@ #endif #endif - if (CHIPSET == FBDEV) - return; +// if (CHIPSET == FBDEV) +// return; /* Ensure that the open will get a file descriptor greater * than 2, else problems can occur with stdio functions @@ -1491,6 +1491,11 @@ CHIPSET = ALI; else #endif +#ifdef INCLUDE_FBDEV_DRIVER_TEST + if (__svgalib_fbdev_driverspecs.test()) + CHIPSET = FBDEV; + else +#endif #ifdef INCLUDE_APM_DRIVER_TEST /* Note: On certain cards this may toggle the video signal on/off which is ugly. Hence we test this last. */ @@ -2212,6 +2217,7 @@ int vga_setmode(int mode) { int modeflags=mode&0xfffff000; + int i; if(mode==-1)return vga_version; @@ -2385,7 +2391,8 @@ if (!__svgalib_secondary) ioctl(__svgalib_tty_fd, KDSETMODE, KD_GRAPHICS); - if (SVGAMODE(prv_mode)) { + /* Not needed for fbdev --achurch */ + if (SVGAMODE(prv_mode) && CHIPSET != FBDEV) { /* The current mode is an SVGA mode, and we now want to */ /* set a standard VGA mode. Make sure the extended regs */ /* are restored. */ @@ -2404,7 +2411,16 @@ CI.xbytes = infotable[mode].xbytes; CI.bytesperpixel = infotable[mode].bytesperpixel; - chipset_setmode(mode, prv_mode); + /* With the fbdev driver, we don't know whether we can set a mode + * until we actually try to do so. Check the return value of + * chipset_setmode and abort as needed. + * We really should do that for all chipsets, but when actually + * banging the hardware some additional adjustments may be + * necessary. These are left as an exercise for the reader. --achurch + */ + i = chipset_setmode(mode, prv_mode); + if (CHIPSET == FBDEV && i != 0) + return -1; MODEX = 0; /* Set default claimed memory (moved here from initialize - Michael.) */ @@ -2575,7 +2591,8 @@ modeinfo.flags &= modeinfo_mask; /* Many cards have problems with linear 320x200x256 mode */ - if(mode==G320x200x256)modeinfo.flags &= (~CAPABLE_LINEAR) & (~IS_LINEAR) ; + if(mode==G320x200x256 && CHIPSET != FBDEV) + modeinfo.flags &= (~CAPABLE_LINEAR) & (~IS_LINEAR) ; /* If all needed info is here, signal if linear support has been enabled */ if ((modeinfo.flags & (CAPABLE_LINEAR | EXT_INFO_AVAILABLE)) ==