summaryrefslogtreecommitdiffstats
path: root/bsps/i386/pc386/console/fb_vga.c
diff options
context:
space:
mode:
Diffstat (limited to 'bsps/i386/pc386/console/fb_vga.c')
-rw-r--r--bsps/i386/pc386/console/fb_vga.c245
1 files changed, 245 insertions, 0 deletions
diff --git a/bsps/i386/pc386/console/fb_vga.c b/bsps/i386/pc386/console/fb_vga.c
new file mode 100644
index 0000000000..75ad56eb98
--- /dev/null
+++ b/bsps/i386/pc386/console/fb_vga.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2000 - Rosimildo da Silva ( rdasilva@connecttel.com )
+ *
+ * MODULE DESCRIPTION:
+ * This module implements FB driver for "Bare VGA". It uses the
+ * routines for "bare hardware" found in vgainit.c.
+ *
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#include <sys/types.h>
+#include <pthread.h>
+
+#include <bsp.h>
+#include <bsp/irq.h>
+#include <rtems/libio.h>
+
+#include <rtems/fb.h>
+#include <rtems/framebuffer.h>
+
+#include <rtems/score/atomic.h>
+
+/* these routines are defined in vgainit.c.*/
+extern void ega_hwinit( void );
+extern void ega_hwterm( void );
+
+/* flag to limit driver to protect against multiple opens */
+static Atomic_Flag driver_mutex;
+
+/* screen information for the VGA driver */
+static struct fb_var_screeninfo fb_var =
+{
+ .xres = 640,
+ .yres = 480,
+ .bits_per_pixel = 4
+};
+
+static struct fb_fix_screeninfo fb_fix =
+{
+ .smem_start = (volatile char *)0xA0000, /* buffer pointer */
+ .smem_len = 0x10000, /* buffer size */
+ .type = FB_TYPE_VGA_PLANES, /* type of dsplay */
+ .visual = FB_VISUAL_PSEUDOCOLOR, /* color scheme used */
+ .line_length = 80 /* chars per line */
+};
+
+
+static uint16_t red16[] = {
+ 0x0000, 0x0000, 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0xaaaa, 0xaaaa,
+ 0x5555, 0x5555, 0x5555, 0x5555, 0xffff, 0xffff, 0xffff, 0xffff
+};
+static uint16_t green16[] = {
+ 0x0000, 0x0000, 0xaaaa, 0xaaaa, 0x0000, 0x0000, 0x5555, 0xaaaa,
+ 0x5555, 0x5555, 0xffff, 0xffff, 0x5555, 0x5555, 0xffff, 0xffff
+};
+static uint16_t blue16[] = {
+ 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa, 0x0000, 0xaaaa,
+ 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff, 0x5555, 0xffff
+};
+
+/* Functionality to support multiple VGA frame buffers can be added easily,
+ * but is not supported at this moment because there is no need for two or
+ * more "classic" VGA adapters. Multiple frame buffer drivers may be
+ * implemented and If we had implement it they would be named as "/dev/fb0",
+ * "/dev/fb1", "/dev/fb2" and so on.
+ */
+/*
+ * fbvga device driver INITIALIZE entry point.
+ */
+rtems_device_driver frame_buffer_initialize(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_status_code status;
+
+ printk( "FBVGA -- driver initializing..\n" );
+
+ /*
+ * Register the device
+ */
+ status = rtems_io_register_name (FRAMEBUFFER_DEVICE_0_NAME, major, 0);
+ if (status != RTEMS_SUCCESSFUL) {
+ printk("Error registering " FRAMEBUFFER_DEVICE_0_NAME
+ " FBVGA framebuffer device!\n");
+ rtems_fatal_error_occurred( status );
+ }
+
+ _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * fbvga device driver OPEN entry point
+ */
+rtems_device_driver frame_buffer_open(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ if (_Atomic_Flag_test_and_set(&driver_mutex, ATOMIC_ORDER_ACQUIRE) != 0 ) {
+ /* restore previous state. for VGA this means return to text mode.
+ * leave out if graphics hardware has been initialized in
+ * frame_buffer_initialize()
+ */
+ ega_hwinit();
+ printk( "FBVGA open called.\n" );
+ return RTEMS_SUCCESSFUL;
+ }
+
+ return RTEMS_UNSATISFIED;
+}
+
+/*
+ * fbvga device driver CLOSE entry point
+ */
+rtems_device_driver frame_buffer_close(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ _Atomic_Flag_clear(&driver_mutex, ATOMIC_ORDER_RELEASE);
+ /* restore previous state. for VGA this means return to text mode.
+ * leave out if graphics hardware has been initialized in
+ * frame_buffer_initialize() */
+ ega_hwterm();
+ printk( "FBVGA close called.\n" );
+ return RTEMS_SUCCESSFUL;
+
+/*
+ * fbvga device driver READ entry point.
+ */
+rtems_device_driver frame_buffer_read(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+ rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+ memcpy(rw_args->buffer, (const void *) (fb_fix.smem_start + rw_args->offset), rw_args->bytes_moved);
+ return RTEMS_SUCCESSFUL;
+}
+
+/*
+ * frame_buffer device driver WRITE entry point.
+ */
+rtems_device_driver frame_buffer_write(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
+ rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fb_fix.smem_len ) ? (fb_fix.smem_len - rw_args->offset) : rw_args->count;
+ memcpy( (void *) (fb_fix.smem_start + rw_args->offset), rw_args->buffer, rw_args->bytes_moved);
+ return RTEMS_SUCCESSFUL;
+}
+
+static int get_fix_screen_info( struct fb_fix_screeninfo *info )
+{
+ *info = fb_fix;
+ return 0;
+}
+
+static int get_var_screen_info( struct fb_var_screeninfo *info )
+{
+ *info = fb_var;
+ return 0;
+}
+
+static int get_palette( struct fb_cmap *cmap )
+{
+ uint32_t i;
+
+ if ( cmap->start + cmap->len >= 16 )
+ return 1;
+
+ for( i = 0; i < cmap->len; i++ ) {
+ cmap->red[ cmap->start + i ] = red16[ cmap->start + i ];
+ cmap->green[ cmap->start + i ] = green16[ cmap->start + i ];
+ cmap->blue[ cmap->start + i ] = blue16[ cmap->start + i ];
+ }
+ return 0;
+}
+
+static int set_palette( struct fb_cmap *cmap )
+{
+ uint32_t i;
+
+ if ( cmap->start + cmap->len >= 16 )
+ return 1;
+
+ for( i = 0; i < cmap->len; i++ ) {
+ red16[ cmap->start + i ] = cmap->red[ cmap->start + i ];
+ green16[ cmap->start + i ] = cmap->green[ cmap->start + i ];
+ blue16[ cmap->start + i ] = cmap->blue[ cmap->start + i ];
+ }
+ return 0;
+}
+
+/*
+ * IOCTL entry point -- This method is called to carry
+ * all services of this interface.
+ */
+rtems_device_driver frame_buffer_control(
+ rtems_device_major_number major,
+ rtems_device_minor_number minor,
+ void *arg
+)
+{
+ rtems_libio_ioctl_args_t *args = arg;
+
+ printk( "FBVGA ioctl called, cmd=%x\n", args->command );
+
+ switch( args->command ) {
+ case FBIOGET_FSCREENINFO:
+ args->ioctl_return = get_fix_screen_info( ( struct fb_fix_screeninfo * ) args->buffer );
+ break;
+ case FBIOGET_VSCREENINFO:
+ args->ioctl_return = get_var_screen_info( ( struct fb_var_screeninfo * ) args->buffer );
+ break;
+ case FBIOPUT_VSCREENINFO:
+ /* not implemented yet*/
+ args->ioctl_return = -1;
+ return RTEMS_UNSATISFIED;
+ case FBIOGETCMAP:
+ args->ioctl_return = get_palette( ( struct fb_cmap * ) args->buffer );
+ break;
+ case FBIOPUTCMAP:
+ args->ioctl_return = set_palette( ( struct fb_cmap * ) args->buffer );
+ break;
+
+ default:
+ args->ioctl_return = 0;
+ break;
+ }
+ return RTEMS_SUCCESSFUL;
+}