summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGregory Nutt <gnutt@nuttx.org>2014-03-08 09:24:24 -0600
committerGregory Nutt <gnutt@nuttx.org>2014-03-08 09:24:24 -0600
commitd18f269cb714f05641b2e802655fac2eb25da9ca (patch)
treef19dfdcbda2df69d01d570330162c9a706d5035d
parentf04c77092da452c6e0e6ec21b8b72ccf0a34cffd (diff)
downloadnuttx-d18f269cb714f05641b2e802655fac2eb25da9ca.tar.gz
nuttx-d18f269cb714f05641b2e802655fac2eb25da9ca.tar.bz2
nuttx-d18f269cb714f05641b2e802655fac2eb25da9ca.zip
QEMU i486: New QEMU keyboard and VGA drivers from Lizhuoyi
-rw-r--r--apps/nshlib/nsh_parse.c2
-rw-r--r--nuttx/ChangeLog4
-rw-r--r--nuttx/arch/x86/src/qemu/Kconfig13
-rw-r--r--nuttx/arch/x86/src/qemu/Make.defs35
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_keypad.c322
-rw-r--r--nuttx/arch/x86/src/qemu/qemu_vga.c514
6 files changed, 876 insertions, 14 deletions
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 <gnutt@nuttx.org>
#
# 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 <lzyy.cn@gmail.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.
+ * 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 <nuttx/config.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/irq.h>
+#include <nuttx/fs/fs.h>
+
+#include <stdint.h>
+#include <semaphore.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sched.h>
+
+#include <arch/io.h>
+
+/****************************************************************************
+ * 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 <lzyy.cn@gmail.com>
+ * 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 <gnutt@nuttx.org>
+ *
+ * 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 <nuttx/config.h>
+
+#include <sys/types.h>
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <debug.h>
+
+#include <nuttx/arch.h>
+#include <nuttx/lcd/lcd.h>
+#include <nuttx/fs/fs.h>
+
+#include <arch/io.h>
+
+/****************************************************************************
+ * 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);
+}