From d18f269cb714f05641b2e802655fac2eb25da9ca Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Sat, 8 Mar 2014 09:24:24 -0600 Subject: QEMU i486: New QEMU keyboard and VGA drivers from Lizhuoyi --- apps/nshlib/nsh_parse.c | 2 +- nuttx/ChangeLog | 4 + nuttx/arch/x86/src/qemu/Kconfig | 13 + nuttx/arch/x86/src/qemu/Make.defs | 35 ++- nuttx/arch/x86/src/qemu/qemu_keypad.c | 322 +++++++++++++++++++++ nuttx/arch/x86/src/qemu/qemu_vga.c | 514 ++++++++++++++++++++++++++++++++++ 6 files changed, 876 insertions(+), 14 deletions(-) create mode 100644 nuttx/arch/x86/src/qemu/qemu_keypad.c create mode 100644 nuttx/arch/x86/src/qemu/qemu_vga.c diff --git a/apps/nshlib/nsh_parse.c b/apps/nshlib/nsh_parse.c index a83fbe79f..d08608bed 100644 --- a/apps/nshlib/nsh_parse.c +++ b/apps/nshlib/nsh_parse.c @@ -1052,7 +1052,7 @@ static FAR char *nsh_argexpand(FAR struct nsh_vtbl_s *vtbl, FAR char *cmdline, if (*ptr == '`') { - FAR char *tmpalloc; + FAR char *tmpalloc = NULL; FAR char *result; FAR char *rptr; diff --git a/nuttx/ChangeLog b/nuttx/ChangeLog index 25614499d..7ff45824b 100644 --- a/nuttx/ChangeLog +++ b/nuttx/ChangeLog @@ -6949,3 +6949,7 @@ * configs/pic32-starterkit, pic32mx7mmb, stm3210e-eval, stm3220g-eval, and stm3240g-eval: Refresh all configurations with the latest Kconfig files (2014-3-7). + * configs/qemu-i486/src: Files renamed to correspond with current + thinking about naming (2014-3-8). + * arch/x86/src/qemu/qemu_keypad.c and qemu_vga.c: New QEMU keyboard + and VGA drivers from Lizhuoyi (2014-3-8). diff --git a/nuttx/arch/x86/src/qemu/Kconfig b/nuttx/arch/x86/src/qemu/Kconfig index 5623ab063..96e57bbb3 100644 --- a/nuttx/arch/x86/src/qemu/Kconfig +++ b/nuttx/arch/x86/src/qemu/Kconfig @@ -6,4 +6,17 @@ if ARCH_CHIP_QEMU comment "QEMU Configuration Options" +config QEMU_KEYPAD + bool "QEMU Keypad" + default n + ---help--- + Enable support for the QEMU keypad. See qemu_keypad.h for + interfaces. + +config QEMU_VGA + bool "QEMU VGA" + default n + ---help--- + Enable support for the QEMU VGA. See qemu_vga.h for interfaces. + endif diff --git a/nuttx/arch/x86/src/qemu/Make.defs b/nuttx/arch/x86/src/qemu/Make.defs index 3c6e99fcc..63cee191f 100644 --- a/nuttx/arch/x86/src/qemu/Make.defs +++ b/nuttx/arch/x86/src/qemu/Make.defs @@ -1,7 +1,7 @@ ############################################################################ # arch/x86/src/qemu/Make.defs # -# Copyright (C) 2011 Gregory Nutt. All rights reserved. +# Copyright (C) 2011, 2014 Gregory Nutt. All rights reserved. # Author: Gregory Nutt # # Redistribution and use in source and binary forms, with or without @@ -35,23 +35,32 @@ # The start-up, "head", file -HEAD_ASRC = qemu_head.S +HEAD_ASRC = qemu_head.S # Common x86 and i486 files -CMN_ASRCS = i486_utils.S up_syscall6.S -CMN_CSRCS = up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c \ - up_createstack.c up_mdelay.c up_udelay.c up_exit.c\ - up_initialize.c up_initialstate.c up_interruptcontext.c up_irq.c \ - up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c up_regdump.c \ - up_releasepending.c up_releasestack.c up_reprioritizertr.c \ - up_savestate.c up_sigdeliver.c up_schedulesigaction.c up_unblocktask.c \ - up_usestack.c +CMN_ASRCS = i486_utils.S up_syscall6.S +CMN_CSRCS += up_allocateheap.c up_assert.c up_blocktask.c up_copystate.c +CMN_CSRCS += up_createstack.c up_mdelay.c up_udelay.c up_exit.c +CMN_CSRCS += up_initialize.c up_initialstate.c up_interruptcontext.c +CMN_CSRCS += up_irq.c up_modifyreg8.c up_modifyreg16.c up_modifyreg32.c +CMN_CSRCS += up_regdump.c up_releasepending.c up_releasestack.c +CMN_CSRCS += up_reprioritizertr.c up_savestate.c up_sigdeliver.c +CMN_CSRCS += up_schedulesigaction.c up_unblocktask.c up_usestack.c # Required QEMU files -CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S qemu_vectors.S -CHIP_CSRCS = qemu_handlers.c qemu_idle.c qemu_lowputc.c qemu_lowsetup.c \ - qemu_serial.c qemu_timerisr.c +CHIP_ASRCS = qemu_saveusercontext.S qemu_fullcontextrestore.S qemu_vectors.S +CHIP_CSRCS = qemu_handlers.c qemu_idle.c qemu_lowputc.c qemu_lowsetup.c +CHIP_CSRCS += qemu_serial.c qemu_timerisr.c # Configuration-dependent QEMU files + +ifeq ($(CONFIG_QEMU_KEYPAD),y) +CHIP_CSRCS += qemu_keypad.c +endif + +ifeq ($(CONFIG_QEMU_VGA),y) +CHIP_CSRCS += qemu_vga.c +endif + diff --git a/nuttx/arch/x86/src/qemu/qemu_keypad.c b/nuttx/arch/x86/src/qemu/qemu_keypad.c new file mode 100644 index 000000000..5efd1f5b0 --- /dev/null +++ b/nuttx/arch/x86/src/qemu/qemu_keypad.c @@ -0,0 +1,322 @@ +/**************************************************************************** + * arch/x86/src/qemu_keypad.c + * + * Copyright (C) 2013 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * + * 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +/**************************************************************************** + * Private Types + ****************************************************************************/ + +typedef enum +{ + /* The keyboard syms have been cleverly chosen to map to ASCII */ + + KEY_UNKNOWN = 0, + KEY_NOKEY = 0, + KEY_FIRST = 0, + KEY_BACKSPACE = 8, + KEY_TAB = 9, + KEY_CLEAR = 12, + KEY_RETURN = 13, + KEY_PAUSE = 19, + KEY_ESCAPE = 27, + + KEY_SPACE = 32, + KEY_EXCLAIM = 33, + KEY_QUOTEDBL = 34, + KEY_HASH = 35, + KEY_DOLLAR = 36, + KEY_AMPERSAND = 38, + KEY_QUOTE = 39, + KEY_LEFTPAREN = 40, + KEY_RIGHTPAREN = 41, + KEY_ASTERISK = 42, + KEY_PLUS = 43, + KEY_COMMA = 44, + KEY_MINUS = 45, + KEY_PERIOD = 46, + KEY_SLASH = 47, + KEY_0 = 48, + KEY_1 = 49, + KEY_2 = 50, + KEY_3 = 51, + KEY_4 = 52, + KEY_5 = 53, + KEY_6 = 54, + KEY_7 = 55, + KEY_8 = 56, + KEY_9 = 57, + + KEY_COLON = 58, + KEY_SEMICOLON = 59, + KEY_LESS = 60, + KEY_EQUALS = 61, + KEY_GREATER = 62, + KEY_QUESTION = 63, + KEY_AT = 64, + + KEY_LEFTBRACKET = 91, + KEY_BACKSLASH = 92, + KEY_RIGHTBRACKET = 93, + KEY_CARET = 94, + KEY_UNDERSCORE = 95, + KEY_BACKQUOTE = 96, + KEY_a = 97, + KEY_b = 98, + KEY_c = 99, + KEY_d = 100, + KEY_e = 101, + KEY_f = 102, + KEY_g = 103, + KEY_h = 104, + KEY_i = 105, + KEY_j = 106, + KEY_k = 107, + KEY_l = 108, + KEY_m = 109, + KEY_n = 110, + KEY_o = 111, + KEY_p = 112, + KEY_q = 113, + KEY_r = 114, + KEY_s = 115, + KEY_t = 116, + KEY_u = 117, + KEY_v = 118, + KEY_w = 119, + KEY_x = 120, + KEY_y = 121, + KEY_z = 122, + KEY_DELETE = 127, + KEY_DEBUG = 138, /* 0x80+0x0a */ + + /* Arrows + Home/End pad */ + + KEY_S100 = 173, + KEY_UP = 173, + KEY_DOWN = 174, + KEY_RIGHT = 175, + KEY_LEFT = 176, + KEY_INSERT = 177, + KEY_HOME = 178, + KEY_END = 179, + KEY_PAGEUP = 180, + KEY_PAGEDOWN = 181, + + /* Function keys */ + + KEY_F1 = 182, + KEY_F2 = 183, + KEY_F3 = 184, + KEY_F4 = 185, + KEY_F5 = 186, + KEY_F6 = 187, + KEY_F7 = 188, + KEY_F8 = 189, + KEY_F9 = 190, + KEY_F10 = 191, + KEY_F11 = 192, + KEY_F12 = 193, + KEY_F13 = 194, + KEY_F14 = 195, + KEY_F15 = 196, + + /* Key state modifier keys */ + + KEY_NUMLOCK = 200, + KEY_CAPSLOCK = 201, + KEY_SCROLLOCK = 202, + KEY_RSHIFT = 203, + KEY_LSHIFT = 204, + KEY_RCTRL = 205, + KEY_LCTRL = 206, + KEY_RALT = 207, + KEY_LALT = 208, + KEY_RMETA = 209, + KEY_LMETA = 210, + KEY_LSUPER = 211, /* Left "Windows" key */ + KEY_RSUPER = 212, /* Right "Windows" key */ + KEY_MODE = 213, /* "Alt Gr" key */ + KEY_COMPOSE = 214, /* Multi-key compose key */ + + /* Miscellaneous function keys */ + + KEY_HELP = 215, + KEY_PRINT = 216, + KEY_SYSREQ = 217, + KEY_BREAK = 218, + KEY_QUIT = 250, + + /* Add any other keys here */ + + KEY_LAST +} MDKKey; + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int keypad_open(struct file *filep); +static int keypad_close(struct file *filep); +static ssize_t keypad_read(struct file *filep, FAR char *buf, size_t buflen); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const unsigned char g_kdbus[128] = +{ + 0, KEY_QUIT, '1', '2', '3', '4', '5', '6', '7', '8', /* 9 */ + '9', '0', '-', '=', '\b', /* Backspace */ + '\t', /* Tab */ + 'q', 'w', 'e', 'r', /* 19 */ + 't', 'y', 'u', 'i', 'o', 'p', '[', ']', '\n', /* Enter key */ + 0, /* 29 - Control */ + 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', /* 39 */ + '\'', '`', 0, /* Left shift */ + '\\', 'z', 'x', 'c', 'v', 'b', 'n', /* 49 */ + 'm', ',', '.', '/', 0, /* Right shift */ + '*', + 0, /* Alt */ + ' ', /* Space bar */ + 0, /* Caps lock */ + KEY_F1, /* 59 - F1 key ... > */ + KEY_F2, KEY_F3, KEY_F4, KEY_F5, KEY_F6, KEY_F7, KEY_F8, KEY_F9, + KEY_F10, /* < ... F10 */ + 0, /* 69 - Num lock*/ + 0, /* Scroll Lock */ + KEY_HOME, /* Home key */ + KEY_UP, /* Up Arrow */ + KEY_PAGEUP, /* Page Up */ + '-', + KEY_LEFT, /* Left Arrow */ + 0, + KEY_RIGHT, /* Right Arrow */ + '+', + KEY_END, /* 79 - End key*/ + KEY_DOWN, /* Down Arrow */ + KEY_PAGEDOWN, /* Page Down */ + KEY_INSERT, /* Insert Key */ + KEY_DELETE, /* Delete Key */ + 0, 0, 0, + 0, /* F11 Key */ + 0, /* F12 Key */ + 0, /* All other keys are undefined */ +}; + +static const struct file_operations g_keypadops = +{ + keypad_open, /* open */ + keypad_close, /* close */ + keypad_read, /* read */ + 0, /* write */ + 0, /* seek */ + 0, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +static int keypad_open(struct file *filep) +{ + return OK; +} + +static int keypad_close(struct file *filep) +{ + return OK; +} + +static ssize_t keypad_read(struct file *filep, FAR char *buf, size_t buflen) +{ + uint_fast8_t keycode = 0; + uint_fast8_t scancode = 0; + uint_fast8_t keyflags; + + if (buf == NULL || buflen < 1) + { + /* Well... nothing to do */ + + return -EINVAL; + } + + keyflags = inb(0x64); + if (keyflags & 0x01) + { + scancode = inb(0x60); + if ((scancode & 0x80) == 0) + { + keycode = g_kdbus[scancode]; + //printf("%02x ",scancode); + buf[0] = keycode; + return 1; + } + } + + return 0; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ +/**************************************************************************** + * Name: qemu_keypad + * + * Description: + * Registers the QEMU keypad driver + * + ****************************************************************************/ + +void qemu_keypad(void) +{ + (void)register_driver("/dev/keypad", &g_keypadops, 0444, NULL); +} diff --git a/nuttx/arch/x86/src/qemu/qemu_vga.c b/nuttx/arch/x86/src/qemu/qemu_vga.c new file mode 100644 index 000000000..0032b521a --- /dev/null +++ b/nuttx/arch/x86/src/qemu/qemu_vga.c @@ -0,0 +1,514 @@ +/**************************************************************************** + * drivers/lcd/vga.c + * + * Copyright (C) 2011 Li Zhuoyi. All rights reserved. + * Author: Li Zhuoyi + * History: 0.1 2012-11-30 initial version + * + * Derived from drivers/lcd/skeleton.c + * + * Copyright (C) 2008-2009 Gregory Nutt. All rights reserved. + * Author: Gregory Nutt + * + * 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. + * 3. Neither the name NuttX nor the names of its contributors may be + * used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "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 + * COPYRIGHT OWNER OR CONTRIBUTORS 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. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include + +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define R_COM 0x63 /* "common" bits */ + +#define R_W256 0x00 +#define R_W320 0x00 +#define R_W360 0x04 +#define R_W376 0x04 +#define R_W400 0x04 + +#define R_H200 0x00 +#define R_H224 0x80 +#define R_H240 0x80 +#define R_H256 0x80 +#define R_H270 0x80 +#define R_H300 0x80 +#define R_H360 0x00 +#define R_H400 0x00 +#define R_H480 0x80 +#define R_H564 0x80 +#define R_H600 0x80 + +#define SZ(x) (sizeof(x)/sizeof(x[0])) + +#define VGA_XRES 320 +#define VGA_YRES 240 +#define VGA_BPP 8 +#define VGA_FBSIZE (VGA_XRES * VGA_YRES * VGA_BPP / 8) +#define VGA_COLORFMT FB_FMT_RGB8 + +/**************************************************************************** + * Private Function Prototypes + ****************************************************************************/ + +static int init_graph_vga(int width, int height,int chain4); +static int vga_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels); +static int vga_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels); +static int vga_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo); +static int vga_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo); +static int vga_getpower(struct lcd_dev_s *dev); +static int vga_setpower(struct lcd_dev_s *dev, int power); +static int vga_getcontrast(struct lcd_dev_s *dev); +static int vga_setcontrast(struct lcd_dev_s *dev, unsigned int contrast); +static int vga_open(struct file *filep); +static int vga_close(struct file *filep); +static ssize_t vga_read(struct file *filep, FAR char *buf, size_t buflen); +static ssize_t vga_write(struct file *filep, FAR const char *buf, size_t buflen); +static off_t vga_seek(FAR struct file *filp, off_t offset, int whence); + +/**************************************************************************** + * Private Data + ****************************************************************************/ + +static const uint8_t g_hor_regs[] = { 0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x13 }; + +static const uint8_t g_width_256[] = { 0x5f, 0x3f, 0x40, 0x82, 0x4a,0x9a, 0x20 }; +static const uint8_t g_width_320[] = { 0x5f, 0x4f, 0x50, 0x82, 0x54,0x80, 0x28 }; +static const uint8_t g_width_360[] = { 0x6b, 0x59, 0x5a, 0x8e, 0x5e,0x8a, 0x2d }; +static const uint8_t g_width_376[] = { 0x6e, 0x5d, 0x5e, 0x91, 0x62,0x8f, 0x2f }; +static const uint8_t g_width_400[] = { 0x70, 0x63, 0x64, 0x92, 0x65,0x82, 0x32 }; + +static const uint8_t g_ver_regs[] = { 0x6, 0x7, 0x9, 0x10, 0x11,0x12, 0x15, 0x16 }; + +static const uint8_t height_200[] = { 0xbf, 0x1f, 0x41, 0x9c, 0x8e,0x8f, 0x96, 0xb9 }; +static const uint8_t height_224[] = { 0x0b, 0x3e, 0x41, 0xda, 0x9c,0xbf, 0xc7, 0x04 }; +static const uint8_t height_240[] = { 0x0d, 0x3e, 0x41, 0xea, 0xac,0xdf, 0xe7, 0x06 }; +static const uint8_t height_256[] = { 0x23, 0xb2, 0x61, 0x0a, 0xac,0xff, 0x07, 0x1a }; +static const uint8_t height_270[] = { 0x30, 0xf0, 0x61, 0x20, 0xa9,0x1b, 0x1f, 0x2f }; +static const uint8_t height_300[] = { 0x70, 0xf0, 0x61, 0x5b, 0x8c,0x57, 0x58, 0x70 }; +static const uint8_t height_360[] = { 0xbf, 0x1f, 0x40, 0x88, 0x85,0x67, 0x6d, 0xba }; +static const uint8_t height_400[] = { 0xbf, 0x1f, 0x40, 0x9c, 0x8e,0x8f, 0x96, 0xb9 }; +static const uint8_t height_480[] = { 0x0d, 0x3e, 0x40, 0xea, 0xac,0xdf, 0xe7, 0x06 }; +static const uint8_t height_564[] = { 0x62, 0xf0, 0x60, 0x37, 0x89,0x33, 0x3c, 0x5c }; +static const uint8_t height_600[] = { 0x70, 0xf0, 0x60, 0x5b, 0x8c,0x57, 0x58, 0x70 }; + +static const uint8_t g_bg_color = 0x0f; +static const uint8_t g_fg_color = 0x01; + +static uint8_t g_runbuffer[VGA_XRES]; +static uint8_t *g_pscreen = (uint8_t*)(0xa0000); + +static off_t g_curpos; + +/* This is the standard, NuttX LCD driver object */ + +static struct lcd_dev_s g_lcddev = +{ + .getvideoinfo = vga_getvideoinfo, + .getplaneinfo = vga_getplaneinfo, + + .getpower = vga_getpower, + .setpower = vga_setpower, + .getcontrast = vga_getcontrast, + .setcontrast = vga_setcontrast, +}; + +static const struct file_operations g_vgaops = +{ + vga_open, /* open */ + vga_close, /* close */ + vga_read, /* read */ + vga_write, /* write */ + vga_seek, /* seek */ + 0, /* ioctl */ +}; + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/* The chain4 parameter should be 1 for normal 13h-type mode, but + * only allows 320x200 256x200, 256x240 and 256x256 because you + * can only access the first 64kb + * + * If chain4 is 0, then plane mode is used (tweaked modes), and + * you'll need to switch planes to access the whole screen but + * that allows you using any resolution, up to 400x600 + * + * Returns 0=ok, -n=fail + */ + +static int init_graph_vga(int width, int height,int chain4) +{ + const uint8_t *w; + const uint8_t *h; + uint8_t val; + int a; + + switch (width) + { + case 256: + w = g_width_256; + val = R_COM + R_W256; + break; + + case 320: + w = g_width_320; + val = R_COM + R_W320; + break; + + case 360: + w = g_width_360; + val = R_COM + R_W360; + break; + + case 376: + w = g_width_376; + val = R_COM + R_W376; + break; + + case 400: + w = g_width_400; + val = R_COM + R_W400; + break; + + default: + return -1; /* fail */ + } + + switch (height) + { + case 200: + h = height_200; + val |= R_H200; + break; + + case 224: + h = height_224; + val |= R_H224; + break; + + case 240: + h = height_240; + val |= R_H240; + break; + + case 256: + h = height_256; + val |= R_H256; + break; + + case 270: + h = height_270; + val |= R_H270; + break; + + case 300: + h = height_300; + val |= R_H300; + break; + + case 360: + h = height_360; + val |= R_H360; + break; + + case 400: + h = height_400; + val |= R_H400; + break; + + case 480: + h = height_480; + val |= R_H480; + break; + + case 564: + h = height_564; + val |= R_H564; + break; + + case 600: + h = height_600; + val |= R_H600; + break; + + default: + return -2; /* fail */ + } + + /* chain4 not available if mode takes over 64k */ + + /* if(chain4 && (long)width*(long)height>65536L) return -3; */ + + /* here goes the actual modeswitch */ + + outb(val, 0x3c2); + outw(0x0e11, 0x3d4); /* enable regs 0-7 */ + + for(a = 0; a < SZ(g_hor_regs); ++a) + { + outw((uint16_t)((w[a] << 8) + g_hor_regs[a]), 0x3d4); + } + + for(a = 0; a < SZ(g_ver_regs); ++a) + { + outw((uint16_t)((h[a] << 8) + g_ver_regs[a]), 0x3d4); + } + + outw(0x0008, 0x3d4); /* vert.panning = 0 */ + + if(chain4) + { + outw(0x4014, 0x3d4); + outw(0xa317, 0x3d4); + outw(0x0e04, 0x3c4); + } + else + { + outw(0x0014, 0x3d4); + outw(0xe317, 0x3d4); + outw(0x0604, 0x3c4); + } + + outw(0x0101, 0x3c4); + outw(0x0f02, 0x3c4); /* Enable writing to all planes */ + outw(0x4005, 0x3ce); /* 256 color mode */ + outw(0x0106, 0x3ce); /* Extend graph mode & a000-bfff */ + + inb(0x3da); + outb(0x30, 0x3c0); + outb(0x41, 0x3c0); + outb(0x33, 0x3c0); + outb(0x00, 0x3c0); + + for(a = 0; a < 16; a++) /* ega pal */ + { + outb((uint8_t)a, 0x3c0); + outb((uint8_t)a, 0x3c0); + } + + outb( 0x20, 0x3c0); /* enable video */ + + return 0; +} + +static int vga_putrun(fb_coord_t row, fb_coord_t col, FAR const uint8_t *buffer, + size_t npixels) +{ + memcpy(&g_pscreen[row*VGA_XRES + col],buffer, npixels); + return OK; +} + +static int vga_getrun(fb_coord_t row, fb_coord_t col, FAR uint8_t *buffer, + size_t npixels) +{ + memcpy(buffer,&g_pscreen[row*VGA_XRES + col],npixels); + return OK; +} + +static int vga_getvideoinfo(FAR struct lcd_dev_s *dev, + FAR struct fb_videoinfo_s *vinfo) +{ + vinfo->fmt = VGA_COLORFMT; + vinfo->xres = VGA_XRES; /* Horizontal resolution in pixel columns */ + vinfo->yres = VGA_YRES; /* Vertical resolution in pixel rows */ + vinfo->nplanes = 1; /* Number of color planes supported */ + return OK; +} + +static int vga_getplaneinfo(FAR struct lcd_dev_s *dev, unsigned int planeno, + FAR struct lcd_planeinfo_s *pinfo) +{ + pinfo->putrun = vga_putrun; /* Put a run into LCD memory */ + pinfo->getrun = vga_getrun; /* Get a run from LCD memory */ + pinfo->buffer = g_runbuffer; /* Run scratch buffer */ + pinfo->bpp = VGA_BPP; /* Bits-per-pixel */ + return OK; +} + +static int vga_getpower(struct lcd_dev_s *dev) +{ + return 0; +} + +static int vga_setpower(struct lcd_dev_s *dev, int power) +{ + return OK; +} + +static int vga_getcontrast(struct lcd_dev_s *dev) +{ + return -ENOSYS; +} + +static int vga_setcontrast(struct lcd_dev_s *dev, unsigned int contrast) +{ + return -ENOSYS; +} + +static int vga_open(struct file * filep) +{ + return OK; +} + +static int vga_close(struct file * filep) +{ + return OK; +} + +static ssize_t vga_read(struct file *filep, FAR char *buf, size_t buflen) +{ + if (buf == NULL || buflen < 1) + { + return -EINVAL; + } + + /* memcpy(&buf,&g_pscreen[y*VGA_XRES + x],buflen); */ + return buflen; +} + +static ssize_t vga_write(struct file *filep, FAR const char *buf, size_t buflen) +{ + int i; + int j; + + if (buf == NULL || buflen < 1) + { + return -EINVAL; + } + + for (j = 0; j < buflen && g_curpos < VGA_FBSIZE; j++) + { + uint8_t dots = buf[j]; + for (i = 0; i < 8 && g_curpos < VGA_FBSIZE; i++) + { + g_pscreen[g_curpos++] = dots & 0x80 ? g_fg_color : g_bg_color; + dots <<= 1; + } + } + + return buflen; +} + +static off_t vga_seek(FAR struct file *filp, off_t offset, int whence) +{ + ssize_t newpos; + + /* Adjust the cursor position as requested */ + + switch (whence) + { + case SEEK_SET: /* From the start of the file */ + newpos = (ssize_t)offset; + break; + + case SEEK_CUR: /* From the current file offset */ + newpos = g_curpos + offset; + break; + + case SEEK_END: /* From the end of the file */ + newpos = (VGA_FBSIZE - 1) - offset; + break; + } + + /* Make sure that the new cursor position lies within the frame buffer */ + + if (newpos < 0) + { + newpos = 0; + } + else if (newpos > VGA_FBSIZE) + { + newpos = VGA_FBSIZE; + } + + /* Set the new cursor position */ + + g_curpos = (off_t)newpos; + return g_curpos; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: qemu_vga_initialize + * + * Description: + * Initialize the QEMU VGA video hardware. + * + ****************************************************************************/ + +FAR struct lcd_dev_s *qemu_vga_initialize(void) +{ + int ret = init_graph_vga(VGA_XRES, VGA_YRES, 1); + if (ret < 0) + { + gdbg("ERROR: init_graph_vga returned %d\n",ret); + } + + memset(g_pscreen, 0, VGA_XRES * VGA_YRES); + return &g_lcddev; +} + +void qemu_vga(void) +{ + int ret = init_graph_vga(VGA_XRES, VGA_YRES, 1); + if (ret < 0) + { + gdbg("ERROR: init_graph_vga returned %d\n",ret); + } + + memset(g_pscreen, g_bg_color, VGA_XRES * VGA_YRES); + (void)register_driver("/dev/lcd", &g_vgaops, 0666, NULL); +} -- cgit v1.2.3