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 <jmcne...@invisible.ca> + * 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 <jmcne...@invisible.ca> + * 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); +}