/* vi: set sw=4 ts=4: */ /* * KON2 - Kanji ON Console - * Copyright (C) 1992-1996 Takashi MANABE (manabe@papilio.tutics.tut.ac.jp) * * 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. * */ /* This file provides generic VGA operation 640x480x16 colors (4 planes) tested on all supported platforms 80 bytes * 480 = 38400 bytes (37KB) 800x600x16 colors (4 planes) tested on FreeBSD 100 bytes * 600 = 60000 bytes (58KB) It can only support 8/16/24-pixel width font. */ #include #include #include #include #include #include #include #include #include "errors.h" #if defined(SUPPORT_VGA) || defined(SUPPORT_FRAMEBUF) #ifdef HAVE_SYS_MMAN_H #include #endif static inline void VgaSetColor(int color) { static int oldcol = -1; if (oldcol == color) return; PortOutw(color << 8, VGAGRP_ADDR); oldcol = color; } static inline void VgaOutByte(u_char value) { PortOutw( (((u_short)value) << 8) | 0x08, VGAGRP_ADDR); } #if !defined(USE_DEVMEM_FILE) || defined(SUPPORT_FRAMEBUF) void VgaOpDraw(u_char *code, u_char fc, u_char bc, int width, int height) { volatile char *gram, *vcls; int x, i, bytes; vcls = gram = gramMem + writeAddr; bytes = (width+7)/8; VgaResetMode(); VgaSetColor( bc & 7); for (x = 0; x < /* dispInfo.glineChar */ height; x++) { for(i = 0; i < bytes; i++) vcls[i] = 0; vcls += dispInfo.glineByte; } VgaSetColor(fc); if (bc & 0x8) /* underline? */ { vcls -= dispInfo.glineByte; for(i = 0; i < bytes; i++) vcls[i] = 0; /* FIXME: For what? */ } for ( x = 0; x < height; x++) { for(i = 0; i < bytes; i++) { if (*code) /* non-zero, output, otherwise keep background */ { VgaOutByte(*code); gram[i] = gram[i]; } code++; } gram += dispInfo.glineByte; } VgaOutByte(0xFF); } void VgaOpCursor(CursorInfo *ci, int xpos, int ypos) { volatile char *gram; u_char x; int i, bytes; int bottom = (cursorBtm + 1 <= dispInfo.glineChar ? cursorBtm + 1 : dispInfo.glineChar); VgaSetColor(15); gram = gramMem + ypos * dispInfo.glineByte + xpos /8; PortOutw(0x0F00, VGAGRP_ADDR); /* color white */ PortOutw(0x1803, VGAGRP_ADDR); /* XOR mode */ x = cursorTop; if (kanjiCursor && ci->kanji) bytes = (fontwidth * 2 + 7)/8; else bytes = (fontwidth + 7)/8; for (;x < bottom;x ++, gram += dispInfo.glineByte) { for(i = 0; i < bytes; i++) gram[i] = gram[i]; } PortOutw(0x0003, VGAGRP_ADDR); /* unmodify mode */ } void VgaOpClear(int y, int height, int color) { VgaResetMode(); VgaSetColor(color); /* 0xXX00 color (index=0) */ lzero(gramMem + y * dispInfo.glineByte, height * dispInfo.glineByte); } void VgaOpFont(u_char *font, int size, int op) { if (!gramMem) return; switch(op) { case SAVE_FONT: memcpy(font, gramMem, size); break; case RESTORE_FONT: memcpy(gramMem, font, size); break; } } #if defined(linux) #define MEM_DEVICE "/dev/mem" #elif defined(__SunOS__) #define MEM_DEVICE "/dev/xsvc" #elif defined(__FreeBSD__) #if (__FreeBSD__ <= 3) #define MEM_DEVICE "/dev/vga" /* "/dev/ttyv0" */ #else #define MEM_DEVICE "/dev/mem" #endif #elif defined(__OpenBSD__) #define MEM_DEVICE "/dev/xf86" #else #define MEM_DEVICE "/dev/mem" #endif int VgaOpMapVidMem(void) { #if defined(__QNX__) #undef mmap /* otherwise mmap is defined as mmap_file */ gramMem = (unsigned char *)mmap(0, dispInfo.gsize, PROT_READ|PROT_WRITE, MAP_PHYS|MAP_SHARED, NOFD, GRAPH_BASE); #elif defined(__Minix__) extern int MinixMmapVideoRAM(unsigned char **gMem); return MinixMmapVideoRAM(&gramMem); #elif defined(__Mach__) extern int MachMmapVideoRAM(unsigned char **gMem); return MachMmapVideoRAM(&gramMem); #elif defined(__MSDOS__) extern int DJGPPMmapVideoRAM(unsigned char **gMem); return DJGPPMmapVideoRAM(&gramMem); #else /* non-QNX non-Minix */ int devMem; if ((devMem = open(MEM_DEVICE, O_RDWR|O_NONBLOCK) ) < 0) { if (strcmp(MEM_DEVICE, "/dev/mem")) /* try it one more time with /dev/mem */ devMem = open("/dev/mem", O_RDWR|O_NONBLOCK); if (devMem < 0) { Perror("Failed to open " MEM_DEVICE); return FAILURE; } } gramMem = (unsigned char *)mmap( #if defined(linux) (__ptr_t)0, #else 0, #endif dispInfo.gsize, /* GRAPH_MEM, */ PROT_READ|PROT_WRITE, MAP_SHARED, devMem, GRAPH_BASE); close(devMem); #endif if (gramMem == (unsigned char *)MAP_FAILED) { Perror("mmap graphics memory failed"); return FAILURE; } return SUCCESS; } void VgaOpUnmapVidMem(void) { #if defined(__Minix__) extern void MinixMunmapVideoRAM(void); MinixMunmapVideoRAM(); /* do MIOCUNMAP */ #elif defined(__Mach__) extern void MachMunmapVideoRAM(void); MachMunmapVideoRAM(); #elif defined(__MSDOS__) extern void DJGPPMunmapVideoRAM(void); DJGPPMunmapVideoRAM(); /* DJGPP stuff */ #elif defined(__QNX__) #undef munmap /* cancel the munmap_file */ #endif munmap(gramMem, dispInfo.gsize); /* For Minix, it'll free it */ } #else /* USE_DEVMEM_FILE */ static u_char zeroline[80]; /* 80x8 = 640 width glineByte==80 */ static inline LseekVram(int y, int x) { lseek(gramFile, 0xA0000 + y * dispInfo.glineByte + x, SEEK_SET); } void VgaOpDraw(u_char *code, u_char fc, u_char bc, int width, int height) { int x, i, bytes; bytes = (width+7)/8; VgaResetMode(); VgaSetColor( bc & 7); for (x = 0; x < /* dispInfo.glineChar */ height; x++) { LseekVram(x, writeAddr); write(gramFile, zeroline, bytes); } VgaSetColor(fc); for ( x = 0; x < height; x++) { for(i = 0; i < bytes; i++) { u_char tmp; if (*code) /* non-zero, output, otherwise keep background */ { VgaOutByte(*code); LseekVram(x, writeAddr + i); read(gramFile, &tmp, 1); lseek(gramFile, -1, SEEK_CUR); write(gramFile, &tmp, 1); } code++; } } VgaOutByte(0xFF); } void VgaOpCursor(CursorInfo *ci, int xpos, int ypos) { u_char x; int i, bytes; int bottom = (cursorBtm + 1 <= dispInfo.glineChar ? cursorBtm + 1 : dispInfo.glineChar) - cursorTop; u_int addr; VgaSetColor(15); addr = ypos * dispInfo.glineByte + xpos /8; PortOutw(0x0F00, VGAGRP_ADDR); /* color white */ PortOutw(0x1803, VGAGRP_ADDR); /* XOR mode */ if (kanjiCursor && ci->kanji) bytes = (fontwidth * 2 + 7)/8; else bytes = (fontwidth + 7)/8; for ( x = 0; x < bottom; x++ /*, gram += dispInfo.glineByte */) { LseekVram(x, addr); for(i = 0; i < bytes; i++) { u_char tmp; read(gramFile, &tmp, 1); lseek(gramFile, -1, SEEK_CUR); write(gramFile, &tmp, 1); } } PortOutw(0x0003, VGAGRP_ADDR); /* unmodify mode */ } void VgaOpClear(int y, int height, int color) { u_char zero = 0x0; int i; VgaResetMode(); VgaSetColor(color); /* 0xXX00 color (index=0) */ LseekVram(y, 0); for(i = 0; i < height; i++) write(gramFile, zeroline, sizeof(zeroline)); } void VgaOpFont(u_char *font, int size, int op) { if (gramFile < 0) return; LseekVram(0, 0); switch(op) { case SAVE_FONT: read(gramFile, font, size); break; case RESTORE_FONT: write(gramFile, font, size); break; } } #define MEM_DEVICE "/dev/mem" int VgaOpMapVidMem(void) { gramFile = open(MEM_DEVICE, O_RDWR|O_NONBLOCK); /* non-blocking */ if (gramFile < 0) return FAILURE; return SUCCESS; } void VgaOpUnmapVidMem(void) { if (gramFile >= 0) { close(gramFile); gramFile = -1; } } #endif /* USE_DEVMEM_FILE */ #endif /* defined(SUPPORT_VGA) || defined(SUPPORT_FRAMEBUF) */