/* vi: set sw=4 ts=4: */ /* * CCE - Console Chinese Environment - * Copyright (C) 1998-2003 Rui He (rhe@3eti.com) * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * */ #include #include #include #include #include #include "defs.h" #include "errors.h" #include "vc.h" #include "vga.h" #include "fb.h" #ifdef HAVE_SYS_IOCTL_H #include #endif #ifdef HAVE_SYS_MMAN_H #include #endif #if defined(SUPPORT_FRAMEBUF) #if defined(__FreeBSD__) int FreeBSDVideoMode, origFreeBSDVideoMode; #elif defined(__NetBSD__) || defined(__OpenBSD__) #define SAVE_RESTORE_PALETTE 1 #elif defined(__Darwin__) #include #define NO_CFGPLUGIN #include #include static io_connect_t fbService; u_char DarwinColorMap8[8] = { 0xFF, 0xD2, 0xB9, 0xB4, 0x23, 0x18, 0x05, 0x00 }; #undef SAVE_RESTORE_PALETTE /* disable palette save/restore on Darwin, doesn't work! */ #endif /* Darwin */ #undef DEBUG /* Rui He, not debugging VgaFB */ FBCMAP fb_cmap; static u_int MmapOffset; #if defined(SAVE_RESTORE_PALETTE) #define HANDLE_PALETTE (dispInfo.bpp <= 8) /* palette-based ? */ #if defined(linux) || defined(__Darwin__) typedef u_short CMAPTYPE; #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) typedef u_char CMAPTYPE; #endif static int savedPel; /* save Palette successfully ? */ static CMAPTYPE savedRed[MAX_PELS], savedGreen[MAX_PELS],savedBlue[MAX_PELS]; static int VgaFBSetPels(CMAPTYPE *red, CMAPTYPE *green, CMAPTYPE *blue) { int ret = -1; #if defined(linux) struct fb_cmap cmap; cmap.start = 0; cmap.len = MAX_PELS; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; ret = ioctl(dispInfo.fd_fb, FBIOPUTCMAP, &cmap); #elif defined(__FreeBSD__) struct fbcmap cmap; /* int index,count; u_char *red, *green, *blue */ cmap.index = 0; cmap.count = MAX_PELS; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; ret = ioctl(0, FBIOPUTCMAP, &cmap); #elif defined(__NetBSD__) || defined(__OpenBSD__) struct wsdisplay_cmap cmap; /* int index,count; u_char *red, *green, *blue */ cmap.index = 0; cmap.count = MAX_PELS; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; ret = ioctl(0, WSDISPLAYIO_PUTCMAP, &cmap); #elif defined(__Darwin__) IOColorEntry newColors[MAX_PELS]; int i; if (!fbService) return; /* just for safety */ for(i = 0; i < MAX_PELS; i++) { newColors[i].index = i; newColors[i].red = red[i]; newColors[i].green = green[i]; newColors[i].blue = blue[i]; } if ( IOFBSetCLUT(fbService, 0/*StartIndex */, MAX_PELS, kSetCLUTByValue, newColors) == KERN_SUCCESS) ret = 0; #endif if (ret) /* 0 is success */ error("Failed to set palette!\r\n"); /* not fatal! */ return ret; } static int VgaFBGetPels(CMAPTYPE *red, CMAPTYPE *green, CMAPTYPE *blue) { int ret = -1; #if defined(linux) struct fb_cmap cmap; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; cmap.start = 0; cmap.len = MAX_PELS; ret = ioctl(dispInfo.fd_fb, FBIOGETCMAP, &cmap); #elif defined(__FreeBSD__) struct fbcmap cmap; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; cmap.index = 0; cmap.count = MAX_PELS; ret = ioctl(0, FBIOGETCMAP, &cmap); #elif defined(__NetBSD__) || defined(__OpenBSD__) struct wsdisplay_cmap cmap; cmap.red = (CMAPTYPE *)red; cmap.green = (CMAPTYPE *)green; cmap.blue = (CMAPTYPE *)blue; cmap.index = 0; cmap.count = MAX_PELS; ret = ioctl(0, WSDISPLAYIO_GETCMAP, &cmap); #elif defined(__Darwin__) #endif return ret; } #else #define HANDLE_PALETTE (0) #endif /* defined(SAVE_RESTORE_PALETTE) */ static u_int mask_bits[] = { 0x0, 0x1, 0x3, 0x7, 0xf, 0x1f, 0x3f, 0x7f, 0xff}; #define COLORBITS1(color, offset, length) ( ((mask_bits[length] << (16 - (length))) & (color)) >> (16 - (length) - (offset)) ) #define COLORBITS2(color, offset, length) (( mask_bits[length] & (color)) << (offset)) void VgaFBInitColorMap(void) { int i; u_int red, green, blue; for(i = 0; i < 16; i++) { red = red16[i]; green = green16[i]; blue = blue16[i]; switch(dispInfo.bpp) { #if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) case 15: fb_cmap.cfb16[i] = ((red & 0xf800) >> 1) | ((green & 0xf800) >> 6) | ((blue & 0xf800) >> 11); break; case 16: /* 0:5:6:5, usually green has 6 bits */ fb_cmap.cfb16[i] = ((red & 0xf800) ) | ((green & 0xfc00) >> 5) | ((blue & 0xf800) >> 11); break; case 24: fb_cmap.cfb24[i] = ((red & 0xff00) << 8) | (green & 0xff00) | (blue >> 8); break; case 32: fb_cmap.cfb32[i] = ((red & 0xff00) << 8) | (green & 0xff00) | (blue >> 8); break; #else /* if defined(linux) || defined(__Darwin__) */ case 15: /* 1:5:5:5 */ case 16: fb_cmap.cfb16[i] = COLORBITS1(red, dispInfo.redoff, dispInfo.redlen) | COLORBITS1(green, dispInfo.greenoff, dispInfo.greenlen) | COLORBITS1(blue, dispInfo.blueoff, dispInfo.bluelen) ; break; case 24: fb_cmap.cfb24[i] = COLORBITS2(red, dispInfo.redoff, dispInfo.redlen) | COLORBITS2(green, dispInfo.greenoff, dispInfo.greenlen) | COLORBITS2(blue, dispInfo.blueoff, dispInfo.bluelen) ; break; case 32: fb_cmap.cfb32[i] = COLORBITS2(red, dispInfo.redoff, dispInfo.redlen) | COLORBITS2(green, dispInfo.greenoff, dispInfo.greenlen) | COLORBITS2(blue, dispInfo.blueoff, dispInfo.bluelen) ; break; #endif } } } #ifdef SUPPORT_FREETYPE_FONT #include "ftfont.h" static inline u_int FBGetPixelColor(int color) { switch(dispInfo.bpp) { case 8: return color; /* palette, background */ case 15: case 16: return fb_cmap.cfb16[color]; case 24: return fb_cmap.cfb24[color]; case 32: return fb_cmap.cfb32[color]; } } void FBDrawFreeTypeChar(int xpos, int ypos, FT_GlyphSlot glyph, int fc, int bc, int width, int height) { int i,j, k; u_char bits = 0, *code; u_char *dest, *line; u_int pix = 0; int top, left, row, col, pitch; u_short red,green, blue; if (glyph == NULL) { left=top=row=col=pitch=0; code = NULL; } else { left = ftXOrig + glyph->bitmap_left; /* bitmap_left should be >= 0 ? */ top = ftYOrig - glyph->bitmap_top; if (top < 0) top = 0; row = glyph->bitmap.rows; /* rows/width >= 0 */ col = glyph->bitmap.width; code = glyph->bitmap.buffer; pitch = glyph->bitmap.pitch; /* bitmap scan line bytes */ } line = gramMem + ypos * dispInfo.glineByte + xpos * dispInfo.bpp/8; for(i = 0; i < height; i++) { dest = line; k = 0; for(j = 0; j < width; j++) { if (i < top || i >= top+row || j < left || j >= left+col) { pix = FBGetPixelColor(bc); } else /* in freetype font region */ { if (glyph->bitmap.pixel_mode == ft_pixel_mode_mono) /* bit oriented */ { if ((k & 0x7) == 0) bits = code[k/8]; pix = FBGetPixelColor( bits & (0x80 >> (k & 0x7)) ? fc : bc ); } else { bits = code[k]; /* 0-255 gray scale */ if (!DoAntiAlias) bits = (bits >= 128? 255: 0); red = (unsigned short)(red16[bc] + ((red16[fc]-red16[bc]) * bits)/255); green = (unsigned short)(green16[bc] + ((green16[fc]-green16[bc]) * bits)/255); blue = (unsigned short)(blue16[bc] + ((blue16[fc]-blue16[bc]) * bits)/255); switch(dispInfo.bpp) { case 8: pix = (bits >= 128 ? fc : bc); /* no anti-alias */ break; case 15: case 16: pix = COLORBITS1(red, dispInfo.redoff, dispInfo.redlen) | COLORBITS1(green, dispInfo.greenoff, dispInfo.greenlen) | COLORBITS1(blue, dispInfo.blueoff, dispInfo.bluelen) ; break; case 24: case 32: pix = ((red & 0xff00) << 8) | (green & 0xff00) | (blue >> 8); break; } } k++; } /* Fix deprecated cast-as-lvalue, which will cause warnings in GCC >= 3.3.4 */ switch(dispInfo.bpp) { case 8: #ifdef __Darwin__ pix = DarwinColorMap8[pix & DARWIN_COLOR_MASK]; #endif *dest++ = (u_char)(pix); break; case 15: case 16: { /* *((u_short *)dest)++ = (u_short)(pix); */ u_short *temp = (u_short *)dest; *temp = (u_short)(pix); dest = (u_char *)temp; dest = (u_char *)((u_short *)dest + 1); break; } case 24: *dest++ = (u_char)(pix); pix >>= 8; *dest++ = (u_char)(pix); pix >>= 8; *dest++ = (u_char)(pix); break; case 32: { /* *((u_int *)dest)++ = (u_int)(pix); */ u_int *temp = (u_int *)dest; *temp = (u_int)(pix); dest = (u_char *)temp; dest = (u_char *)((u_int *)dest + 1); break; } } } line += dispInfo.glineByte; if (k > 0) /* k>0 means code is used somehow, code could be NULL */ code += pitch; } } #endif /* SUPPORT_FREETYPE_FONT */ #if defined(linux) static int InitLinuxFB(void) { int fd; struct fb_fix_screeninfo fix; struct fb_var_screeninfo var; if ((fd = open(DEFAULT_FB, O_RDWR)) < 0) fd = open(DEFAULT_FB_DEVFS, O_RDWR); if (fd < 0 || ioctl(fd, FBIOGET_FSCREENINFO, &fix) || ioctl(fd, FBIOGET_VSCREENINFO, &var)) return FAILURE; #ifdef DEBUG fprintf(stderr, "x_vir=%d y_vir=%d xoff=%d yoff=%d\n", var.xres_virtual, var.yres_virtual, var.xoffset, var.yoffset); #endif var.xres_virtual = var.xres; var.yres_virtual = var.yres; var.xoffset = var.yoffset = 0; ioctl(fd, FBIOPUT_VSCREENINFO, &var); /* failure not critical? */ dispInfo.gxdim = var.xres; dispInfo.gydim = var.yres; dispInfo.bpp = var.bits_per_pixel; dispInfo.glineByte = fix.line_length; dispInfo.redlen = var.red.length; dispInfo.redoff = var.red.offset; dispInfo.greenlen = var.green.length; dispInfo.greenoff = var.green.offset; dispInfo.bluelen = var.blue.length; dispInfo.blueoff = var.blue.offset; dispInfo.fd_fb = fd; MmapOffset = 0; /* linux, always start at 0 */ #if defined(FB_TYPE_VGA_PLANES) /* Linux 2.0.x/2.2.x has no VGA_PLANES fb? */ if (fix.type == FB_TYPE_VGA_PLANES) /* EGA/VGA planes */ { dispInfo.type = TYPE_FB_VGAPLANES; if (dispInfo.bpp != 4) { message("Unsupported VGAPLANES frame buffer type(depth=%d)!\n", dispInfo.bpp); return FAILURE; } dispInfo.bpp = 1; #if defined(CCE_TARGETARCH_I386) ioperm(VGAGRP_ADDR, 1, 1); ioperm(VGAGRP_DATA, 1, 1); #endif } else #endif /* FB_TYPE_VGA_PLANES */ { if (fix.type != FB_TYPE_PACKED_PIXELS) { message("Unsupported frame buffer type!\n"); return FAILURE; } dispInfo.type = TYPE_FB_LINEAR; } return SUCCESS; } #elif defined(__FreeBSD__) static int InitFreeBSDFB(void) { int mode; video_info_t vmode; origFreeBSDVideoMode = GetOrigFreeBSDVideoMode(); FreeBSDVideoMode = -1; if (fbwidth > 0 && fbheight > 0 && fbdepth > 0) FreeBSDVideoMode = GetFreeBSDVideoMode( fbwidth, fbheight, fbdepth, &vmode); if (FreeBSDVideoMode == -1) /* one more try */ FreeBSDVideoMode = GetBestFreeBSDConsVidMode(&vmode); if (FreeBSDVideoMode == -1) { message("Unsupported framebuffer, please try 'kldload vesa'.\n"); return FAILURE; } dispInfo.gxdim = vmode.vi_width; dispInfo.gydim = vmode.vi_height; if (vmode.vi_mem_model == V_INFO_MM_PLANAR) /* 1 */ { if (vmode.vi_depth != 4 || vmode.vi_planes != 4) { message("Unsupported Planar Framebuffer(depth=%d, planes=%d).\n", vmode.vi_depth, vmode.vi_planes); return FAILURE; } dispInfo.bpp = 1; dispInfo.type = TYPE_FB_VGAPLANES; dispInfo.glineByte = dispInfo.gxdim/8; #if defined(CCE_TARGETARCH_I386) i386_set_ioperm(VGAGRP_ADDR, 1, 1); i386_set_ioperm(VGAGRP_DATA, 1, 1); #endif } else { if (vmode.vi_mem_model != V_INFO_MM_PACKED && vmode.vi_mem_model != V_INFO_MM_DIRECT) { message("Unsupported Framebuffer Type!\n"); return FAILURE; } dispInfo.bpp = vmode.vi_depth; dispInfo.type = TYPE_FB_LINEAR; dispInfo.glineByte = vmode.vi_pixel_size * vmode.vi_width; dispInfo.redlen = vmode.vi_pixel_fsizes[0]; dispInfo.redoff = vmode.vi_pixel_fields[0]; dispInfo.greenlen = vmode.vi_pixel_fsizes[1]; dispInfo.greenoff = vmode.vi_pixel_fields[1]; dispInfo.bluelen = vmode.vi_pixel_fsizes[2]; dispInfo.blueoff = vmode.vi_pixel_fields[2]; } dispInfo.fd_fb = 0; MmapOffset = 0; return SUCCESS; } #elif defined(__Darwin__) #define kern_assert(x) { if ((x) != KERN_SUCCESS) return FAILURE; } static int InitDarwinFB(void) { io_iterator_t fbIter; io_service_t service; mach_port_t masterPort; kern_return_t kr; IODisplayModeInformation modeInfo; IODisplayModeID displayMode; IOIndex displayDepth; IOFramebufferInformation fbInfo; IOPixelInformation pixelInfo; kr = IOMasterPort(bootstrap_port, &masterPort); kern_assert(kr); kr = IOServiceGetMatchingServices(masterPort, IOServiceMatching(IOFRAMEBUFFER_CONFORMSTO), &fbIter); kern_assert(kr); service = IOIteratorNext(fbIter); /* first screen, normally 32bpp? */ if (service == 0) return FAILURE; kr = IOServiceOpen(service, mach_task_self(), kIOFBServerConnectType, &fbService); kern_assert(kr); IOObjectRelease(service); kr = IOFBCreateSharedCursor( fbService, kIOFBCurrentShmemVersion, 32, 32 ); kern_assert(kr); kr = IOFBGetCurrentDisplayModeAndDepth(fbService, &displayMode, &displayDepth); kern_assert(kr); kr = IOFBGetDisplayModeInformation(fbService, displayMode, &modeInfo); kern_assert(kr); #ifdef DEBUG fprintf(stderr, "modeinfo.maxDepthIndex=%d\n", modeInfo.maxDepthIndex); #endif kr = IOFBGetPixelInformation( fbService, displayMode, displayDepth, kIOFBSystemAperture, &pixelInfo ); kern_assert(kr); kr = IOFBGetFramebufferInformationForAperture( fbService, kIOFBSystemAperture, &fbInfo ); kern_assert(kr); if (fbInfo.activeWidth <= 1 || fbInfo.activeHeight <= 1) { message("Discarding screen with width %d and height %d\r\n", fbInfo.activeWidth, fbInfo.activeHeight); return FAILURE; } #ifdef DEBUG fprintf(stderr, "w=%d h=%d pitch=%d bpp=%d PixCompCnt=%d BitsPerComp=%d\n", fbInfo.activeWidth, fbInfo.activeHeight, fbInfo.bytesPerRow, fbInfo.bitsPerPixel, pixelInfo.componentCount, pixelInfo.bitsPerComponent); #endif dispInfo.gxdim = fbInfo.activeWidth; dispInfo.gydim = fbInfo.activeHeight; dispInfo.bpp = fbInfo.bitsPerPixel; if (dispInfo.bpp == 16) dispInfo.bpp = 15; /* Apple only use 1555 format ?*/ dispInfo.glineByte = fbInfo.bytesPerRow; dispInfo.type = TYPE_FB_LINEAR; dispInfo.fd_fb = 0; /* a fake one, not used, <0 for error! */ MmapOffset = 0; /* not used */ if (dispInfo.bpp == 15) { dispInfo.redlen = dispInfo.greenlen = dispInfo.bluelen = 5; dispInfo.redoff = 10; dispInfo.greenoff = 5; dispInfo.blueoff = 0; } else /* 8, 24, 32bpp, Apple's 24bpp is same as 32 bpp? */ { dispInfo.redlen = dispInfo.greenlen = dispInfo.bluelen = 8; dispInfo.redoff = 16; dispInfo.greenoff = 8; dispInfo.blueoff = 0; } return SUCCESS; } #elif defined(__OpenBSD__) || defined(__NetBSD__) #include /* for NetBSD */ #include /* for all the WSDISPLAYIO_* ioctls */ static int InitWsconsFB(void) { int display_type, display_pitch; struct wsdisplay_fbinfo display_fb; int mode = WSDISPLAYIO_MODE_MAPPED; /* 1 */ if (ioctl(0, WSDISPLAYIO_GTYPE, &display_type) == -1 || ioctl(0, WSDISPLAYIO_GINFO, &display_fb) == -1 #if defined(__OpenBSD__) /* NetBSD has no such ioctl */ || ioctl(0, WSDISPLAYIO_LINEBYTES, &display_pitch) == -1 #endif ) { message("Framebuffer is not supported on this platform.\r\n"); return FAILURE; } if (display_fb.depth < 8) { message("Unsupported framebuffer depth: %d\r\n", display_fb.depth); return FAILURE; } dispInfo.gxdim = display_fb.width; dispInfo.gydim = display_fb.height; dispInfo.bpp = display_fb.depth; #if defined(__OpenBSD__) dispInfo.glineByte = display_pitch; #else dispInfo.glineByte = ((dispInfo.bpp + 7)/8) * dispInfo.gxdim; #endif dispInfo.type = TYPE_FB_LINEAR; dispInfo.fd_fb = 0; /* 0 is stdin, should be same as /dev/ttyCn */ MmapOffset = 0; /* OpenBSD mmap at offset 0 on /dev/ttyCn */ ioctl(0, WSDISPLAYIO_SMODE, &mode); return SUCCESS; } #endif /* linux, *BSD, Darwin */ static int VgaFBInitRegs(void) { int ret = FAILURE; #if defined(linux) ret = InitLinuxFB(); #elif defined(__FreeBSD__) ret = InitFreeBSDFB(); #elif defined(__NetBSD__) || defined(__OpenBSD__) ret = InitWsconsFB(); #elif defined(__Darwin__) ret = InitDarwinFB(); #else #error Framebuffer only supported on Linux/FreeBSD/NetBSD/OpenBSD/Darwin ! #endif if (ret != SUCCESS || dispInfo.fd_fb < 0 || dispInfo.gxdim < 320 || dispInfo.gydim < 240) return FAILURE; InitDispInfo(); if (dispInfo.type == TYPE_FB_VGAPLANES) /* EGA/VGA planes */ { CheckSuidRoot(); /* make sure it's suid-root */ if (fontwidth !=8 || fontheight != 16) fatal("Only 16x16 font is supported in 640x480x4/800x600x4 mode.\r\n"); message("Using %dx%d 4-bpp(VGAPlane) framebuffer, %dx%d terminal.\n", dispInfo.gxdim, dispInfo.gydim, dispInfo.txmax, dispInfo.tymax); } else /* TYPE_FB_LINEAR */ { if ( (dispInfo.bpp != 4 && dispInfo.bpp != 8 && dispInfo.bpp != 16 && dispInfo.bpp != 15 && dispInfo.bpp != 24 && dispInfo.bpp != 32) || (dispInfo.bpp >= 15 && (dispInfo.redlen > 8 || dispInfo.redlen <= 0 || dispInfo.greenlen > 8 || dispInfo.greenlen <=0 || dispInfo.bluelen > 8 || dispInfo.bluelen <= 0 )) ) { message("Unsupported color depth %d bpp(RGB %d:%d:%d)\r\n", dispInfo.bpp, dispInfo.redlen, dispInfo.greenlen, dispInfo.bluelen); return FAILURE; } message("Using %dx%d %d-bpp(RGB %d:%d:%d) framebuffer, %dx%d terminal.\n", dispInfo.gxdim, dispInfo.gydim, dispInfo.bpp, dispInfo.redlen, dispInfo.greenlen, dispInfo.bluelen, dispInfo.txmax, dispInfo.tymax); if (dispInfo.bpp > 8) VgaFBInitColorMap(); /* mainly for 15~32 bpps */ if (dispInfo.bpp == 15) dispInfo.bpp = 16; } return SUCCESS; } int VgaFBAttach(void) { #if defined(linux) || defined(__FreeBSD__) if (dispInfo.type == TYPE_FB_VGAPLANES) { if (ioctl(0, KDENABIO,0) < 0) { warn("ioctl CONSOLE_IO_ENABLE"); /* not critical? */ } } #endif #if defined(__FreeBSD__) if (ioctl(0, FreeBSDVideoMode, 0) == -1) { Perror("ioctl switch video mode fail"); return FAILURE; } if (dispInfo.type == TYPE_FB_VGAPLANES) VgaResetMode(); #endif #if defined(__Darwin__) { vm_address_t vram; vm_size_t shmemSize; if (IOConnectMapMemory( fbService, kIOFBSystemAperture, mach_task_self(), &vram, &shmemSize, kIOMapAnywhere ) != KERN_SUCCESS) return FAILURE; gramMem = (u_char *)vram; /* no need to do mmap for Darwin */ } #else gramMem = (u_char *)mmap( #if defined(linux) (__ptr_t)0, #else 0, #endif dispInfo.gsize, PROT_READ|PROT_WRITE, MAP_SHARED, dispInfo.fd_fb, MmapOffset); if ((void *)gramMem == MAP_FAILED) { Perror("mmap framebuffer memory fail"); return FAILURE; } #endif #ifdef DEBUG fprintf(stderr, "Now doing VgaFBAttach, gramMem=%p\n", gramMem); #endif return SUCCESS; } void VgaFBDetach(void) { #if defined(__FreeBSD__) ioctl(0, SW_TEXT_80x25, 0); #endif if (dispInfo.type == TYPE_FB_VGAPLANES) { #if defined(CCE_TARGETARCH_I386) #if defined(linux) ioperm(VGAGRP_ADDR, 1, 0); ioperm(VGAGRP_DATA, 1, 0); #elif defined(__FreeBSD__) i386_set_ioperm(VGAGRP_ADDR, 1, 0); i386_set_ioperm(VGAGRP_DATA, 1, 0); #endif #endif } #if defined(__Darwin__) if (fbService) { if (gramMem) IOConnectUnmapMemory(fbService, kIOFBSystemAperture, mach_task_self(), (vm_address_t)gramMem); IOServiceClose(fbService); /* necessary ? */ fbService = 0; } #else if (gramMem && (void *)gramMem != MAP_FAILED) munmap(gramMem, dispInfo.gsize); #endif gramMem = 0; /* set to zero to capture error! */ if (dispInfo.fd_fb > 0) close(dispInfo.fd_fb); dispInfo.fd_fb = -1; } int VgaFBInit(void) { if (VgaFBInitRegs() != SUCCESS) return FAILURE; return VgaFBAttach(); } void VgaFBScreenSaver(bool blank) { } void VgaFBTextMode(void) { #if defined(__FreeBSD__) ioctl(0, origFreeBSDVideoMode, 0); #endif #if defined(SAVE_RESTORE_PALETTE) && !defined(__Darwin__) if (HANDLE_PALETTE) { if (savedPel) VgaFBSetPels(savedRed, savedGreen, savedBlue); } #endif } void VgaFBGraphMode(void) { #if defined(__FreeBSD__) ioctl(0, FreeBSDVideoMode, 0); if (dispInfo.type == TYPE_FB_VGAPLANES) VgaResetMode(); #endif #if defined(SAVE_RESTORE_PALETTE) if (HANDLE_PALETTE) { #if defined(linux) || defined(__Darwin__) VgaFBSetPels(red16, green16, blue16); #elif defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) VgaFBSetPels(red8, green8, blue8); #endif } #endif CCEClear(CLEAR_DISPLAY, DEF_BGCOLOR); } void VgaFBStart(void) { cursorTop = fontheight - 2; cursorBtm = fontheight - 1; #if defined(SAVE_RESTORE_PALETTE) && !defined(__Darwin__) if (HANDLE_PALETTE) { if (VgaFBGetPels(savedRed, savedGreen, savedBlue) == 0) savedPel = 1; } #endif } VideoInfo VgaFBInfo = { VgaFBInit, VgaFBStart, VgaFBTextMode, VgaFBGraphMode, CCEWput, CCEInputWput, CCESput, CCEInputSput, CCEInputDrawIcon, CCECursor, CCEClear, VgaFBScreenSaver, VgaFBDetach }; #endif