Module Name: src
Committed By: jmcneill
Date: Thu Aug 25 11:45:26 UTC 2011
Added Files:
src/sys/arch/usermode/dev: genfb_thunkbus.c
src/sys/arch/usermode/usermode: thunk_sdl.c
Log Message:
- build thunk code with warnings
- add option SDL which pulls in thunk_sdl code and links the kernel to libSDL
- add an experimental framebuffer driver based on thunk_sdl, enable with:
options SDL
genfb* at mainbus?
wsdisplay* at genfb?
options WS_KERNEL_FG=WSCOL_GREEN
options WSEMUL_VT100
- reserve a major # for wsdisplay
- add thunk_getenv()
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/sys/arch/usermode/dev/genfb_thunkbus.c
cvs rdiff -u -r0 -r1.1 src/sys/arch/usermode/usermode/thunk_sdl.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Added files:
Index: src/sys/arch/usermode/dev/genfb_thunkbus.c
diff -u /dev/null src/sys/arch/usermode/dev/genfb_thunkbus.c:1.1
--- /dev/null Thu Aug 25 11:45:26 2011
+++ src/sys/arch/usermode/dev/genfb_thunkbus.c Thu Aug 25 11:45:25 2011
@@ -0,0 +1,156 @@
+/* $NetBSD: genfb_thunkbus.c,v 1.1 2011/08/25 11:45:25 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: genfb_thunkbus.c,v 1.1 2011/08/25 11:45:25 jmcneill Exp $");
+
+#include <sys/param.h>
+#include <sys/proc.h>
+#include <sys/systm.h>
+#include <sys/device.h>
+
+#include <dev/wsfb/genfbvar.h>
+
+#include <machine/mainbus.h>
+#include <machine/thunk.h>
+
+#ifdef _KERNEL_OPT
+#include "opt_sdl.h"
+#endif
+
+#if !defined(SDL)
+#error genfb_thunkbus requires options SDL
+#endif
+
+#define GENFB_THUNKBUS_WIDTH 640
+#define GENFB_THUNKBUS_HEIGHT 480
+#define GENFB_THUNKBUS_DEPTH 32
+#define GENFB_THUNKBUS_FBSIZE \
+ (GENFB_THUNKBUS_WIDTH * GENFB_THUNKBUS_HEIGHT * (GENFB_THUNKBUS_DEPTH / 8))
+
+static int genfb_thunkbus_match(device_t, cfdata_t, void *);
+static void genfb_thunkbus_attach(device_t, device_t, void *);
+static int genfb_thunkbus_ioctl(void *, void *, u_long, void *, int, lwp_t *);
+static paddr_t genfb_thunkbus_mmap(void *, void *, off_t, int);
+
+int genfb_thunkbus_cnattach(void);
+
+struct genfb_thunkbus_softc {
+ struct genfb_softc sc_gen;
+};
+
+static void * genfb_thunkbus_fbaddr;
+
+CFATTACH_DECL_NEW(genfb_thunkbus, sizeof(struct genfb_thunkbus_softc),
+ genfb_thunkbus_match, genfb_thunkbus_attach, NULL, NULL);
+
+static int
+genfb_thunkbus_match(device_t parent, cfdata_t match, void *opaque)
+{
+ struct thunkbus_attach_args *taa = opaque;
+
+ if (taa->taa_type != THUNKBUS_TYPE_GENFB)
+ return 0;
+
+ if (thunk_getenv("DISPLAY") == NULL)
+ return 0;
+
+ return 1;
+}
+
+static void
+genfb_thunkbus_attach(device_t parent, device_t self, void *opaque)
+{
+ struct genfb_thunkbus_softc *sc = device_private(self);
+ struct genfb_ops ops;
+ prop_dictionary_t dict = device_properties(self);
+
+ aprint_naive("\n");
+ aprint_normal("\n");
+
+ sc->sc_gen.sc_dev = self;
+ sc->sc_gen.sc_fbaddr = genfb_thunkbus_fbaddr;
+
+ prop_dictionary_set_bool(dict, "is_console", true);
+ prop_dictionary_set_uint32(dict, "width", GENFB_THUNKBUS_WIDTH);
+ prop_dictionary_set_uint32(dict, "height", GENFB_THUNKBUS_HEIGHT);
+ prop_dictionary_set_uint8(dict, "depth", GENFB_THUNKBUS_DEPTH);
+ prop_dictionary_set_uint16(dict, "linebytes",
+ GENFB_THUNKBUS_WIDTH * (GENFB_THUNKBUS_DEPTH / 8));
+ prop_dictionary_set_uint64(dict, "address", 0);
+ prop_dictionary_set_uint64(dict, "virtual_address",
+ (vaddr_t)sc->sc_gen.sc_fbaddr);
+
+ genfb_init(&sc->sc_gen);
+
+ memset(&ops, 0, sizeof(ops));
+ ops.genfb_ioctl = genfb_thunkbus_ioctl;
+ ops.genfb_mmap = genfb_thunkbus_mmap;
+
+ if (genfb_attach(&sc->sc_gen, &ops) != 0)
+ panic("%s: couldn't attach genfb", __func__);
+
+}
+
+static int
+genfb_thunkbus_ioctl(void *v, void *vs, u_long cmd, void *data, int flag, lwp_t *l)
+{
+ switch (cmd) {
+ case WSDISPLAYIO_GTYPE:
+ *(unsigned int *)data = WSDISPLAY_TYPE_UNKNOWN;
+ return 0;
+ }
+
+ return EPASSTHROUGH;
+}
+
+static paddr_t
+genfb_thunkbus_mmap(void *v, void *vs, off_t off, int prot)
+{
+ return -1;
+}
+
+int
+genfb_thunkbus_cnattach(void)
+{
+ int error;
+
+ if (thunk_getenv("DISPLAY") == NULL)
+ return 0;
+
+ genfb_thunkbus_fbaddr = thunk_sdl_getfb(GENFB_THUNKBUS_FBSIZE);
+ if (genfb_thunkbus_fbaddr == NULL)
+ return 0;
+
+ error = thunk_sdl_init(GENFB_THUNKBUS_WIDTH,
+ GENFB_THUNKBUS_HEIGHT, GENFB_THUNKBUS_DEPTH);
+ if (error)
+ return 0;
+
+ return 1;
+}
Index: src/sys/arch/usermode/usermode/thunk_sdl.c
diff -u /dev/null src/sys/arch/usermode/usermode/thunk_sdl.c:1.1
--- /dev/null Thu Aug 25 11:45:26 2011
+++ src/sys/arch/usermode/usermode/thunk_sdl.c Thu Aug 25 11:45:26 2011
@@ -0,0 +1,239 @@
+/* $NetBSD: thunk_sdl.c,v 1.1 2011/08/25 11:45:26 jmcneill Exp $ */
+
+/*-
+ * Copyright (c) 2011 Jared D. McNeill <[email protected]>
+ * All rights reserved.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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.
+ */
+
+#include <sys/cdefs.h>
+__RCSID("$NetBSD: thunk_sdl.c,v 1.1 2011/08/25 11:45:26 jmcneill Exp $");
+
+#include <sys/types.h>
+#include <sys/signal.h>
+#include <sys/reboot.h>
+#include <sys/shm.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#include <SDL.h>
+
+#include "../include/thunk.h"
+
+extern const char ostype[];
+extern const char osrelease[];
+extern const char kernel_ident[];
+
+#define THUNK_SDL_REDRAW_INTERVAL 100 /* 10 Hz */
+
+#define THUNK_SDL_EV_REDRAW 1
+
+static int thunk_sdl_running = 0; /* SDL event loop run status */
+static void *thunk_sdl_fbaddr = NULL; /* framebuffer va */
+static int thunk_sdl_shmid;
+
+/* Framebuffer parameters */
+static unsigned int thunk_sdl_width;
+static unsigned int thunk_sdl_height;
+static unsigned short thunk_sdl_depth;
+
+/*
+ * Create an SDL surface from the framebuffer memory, then blit
+ * it to the screen.
+ */
+static void
+thunk_sdl_redraw(SDL_Surface *screen)
+{
+ SDL_Surface *wsfb;
+ Uint32 rmask, gmask, bmask, amask;
+
+ if (thunk_sdl_fbaddr == NULL)
+ return;
+
+ rmask = 0x000000ff;
+ gmask = 0x0000ff00;
+ bmask = 0x00ff0000;
+ amask = 0x00000000;
+
+ wsfb = SDL_CreateRGBSurfaceFrom(thunk_sdl_fbaddr,
+ thunk_sdl_width, thunk_sdl_height, thunk_sdl_depth,
+ thunk_sdl_width * (thunk_sdl_depth / 8),
+ rmask, gmask, bmask, amask);
+ if (wsfb == NULL)
+ abort();
+ if (SDL_BlitSurface(wsfb, NULL, screen, NULL) == -1)
+ abort();
+ SDL_Flip(screen);
+ SDL_FreeSurface(wsfb);
+}
+
+/*
+ * Timer callback used to inject a redraw event into the SDL event loop
+ */
+static Uint32
+thunk_sdl_tick(Uint32 interval, void *param)
+{
+ SDL_Event ev;
+
+ if (!thunk_sdl_running)
+ return 0;
+
+ ev.type = SDL_USEREVENT;
+ ev.user.code = THUNK_SDL_EV_REDRAW;
+ ev.user.data1 = ev.user.data2 = NULL;
+ SDL_PushEvent(&ev);
+
+ return interval;
+}
+
+/*
+ * SDL event loop
+ */
+static int
+thunk_sdl_eventloop(void *priv)
+{
+ SDL_Surface *screen;
+ char caption[81];
+ //int stdin_fd;
+ SDL_Event ev;
+ key_t k;
+
+ thunk_sdl_running = 1;
+
+ k = ftok("/dev/null", 1);
+ if (k == (key_t)-1)
+ return errno;
+ thunk_sdl_shmid = shmget(k,
+ thunk_sdl_width * thunk_sdl_height * (thunk_sdl_depth / 8), 0600);
+ thunk_sdl_fbaddr = shmat(thunk_sdl_shmid, NULL, 0);
+ if (thunk_sdl_fbaddr == NULL)
+ abort();
+
+ /* SDL_Init closes stdin, so we need to restore it after it returns */
+ //stdin_fd = dup(0);
+ if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_TIMER) < 0)
+ abort();
+ atexit(SDL_Quit);
+ //close(0);
+ //dup2(stdin_fd, 0);
+
+ /* Clear SDL signal handler so ^C will work */
+ //signal(SIGINT, SIG_DFL);
+
+ /* Configure key repeat */
+ SDL_EnableKeyRepeat(SDL_DEFAULT_REPEAT_DELAY, SDL_DEFAULT_REPEAT_DELAY);
+
+ /* Set the window title */
+ memset(caption, 0, sizeof(caption));
+ snprintf(caption, sizeof(caption), "%s %s (%s)",
+ ostype, osrelease, kernel_ident);
+ SDL_WM_SetCaption(caption, NULL);
+
+ /* Try to configure the requested video mode */
+ screen = SDL_SetVideoMode(thunk_sdl_width, thunk_sdl_height,
+ thunk_sdl_depth, 0);
+ if (screen == NULL)
+ abort();
+
+ /* Hide the mouse cursor */
+ SDL_ShowCursor(SDL_DISABLE);
+
+ SDL_AddTimer(THUNK_SDL_REDRAW_INTERVAL, thunk_sdl_tick, NULL);
+
+ while (thunk_sdl_running) {
+ if (!SDL_WaitEvent(&ev))
+ abort();
+ printf("ev.type = %d\n", ev.type);
+ switch (ev.type) {
+ case SDL_QUIT:
+ thunk_sdl_running = 0;
+ break;
+ case SDL_KEYDOWN:
+ printf("key %X scancode %X\n", ev.key.keysym.sym,
+ ev.key.keysym.scancode);
+ break;
+ case SDL_USEREVENT:
+ switch (ev.user.code) {
+ case THUNK_SDL_EV_REDRAW:
+ thunk_sdl_redraw(screen);
+ break;
+ }
+ }
+
+ thunk_sdl_redraw(screen);
+ }
+
+ printf("shutting down...\n");
+ abort();
+ return 0;
+}
+
+int
+thunk_sdl_init(unsigned int width, unsigned int height, unsigned short depth)
+{
+ static int thunk_sdl_inited = 0;
+ static int thunk_sdl_init_status = -1;
+
+ if (thunk_sdl_inited)
+ goto done;
+ thunk_sdl_inited = 1;
+
+ /* Save a copy of the video mode parameters for later */
+ thunk_sdl_width = width;
+ thunk_sdl_height = height;
+ thunk_sdl_depth = depth;
+
+ /* run event loop */
+ switch (fork()) {
+ case 0:
+ thunk_sdl_eventloop(NULL);
+ break;
+ case -1:
+ abort();
+ default:
+ break;
+ }
+
+ thunk_sdl_init_status = 0;
+
+done:
+ return thunk_sdl_init_status;
+}
+
+/*
+ * Get the framebuffer virtual address
+ */
+void *
+thunk_sdl_getfb(size_t fbsize)
+{
+ key_t k;
+
+ k = ftok("/dev/null", 1);
+ if (k == (key_t)-1)
+ return NULL;
+
+ thunk_sdl_shmid = shmget(k, fbsize, IPC_CREAT | 0600);
+ return shmat(thunk_sdl_shmid, NULL, 0);
+}