[PATCH] pc386/console: alternative framebuffer implementation for cirrus GD5446 QEMU device
Gedare Bloom
gedare at rtems.org
Wed Jun 20 17:47:50 UTC 2012
Just quick comments:
fb_cirrus.c needs licensing info
vga_registers.h uses 3-clause BSD with mandatory advertisement clause
which is unacceptable.
Considering the simplicity of the .h file I think it should be easy
enough to re-engineer it cleanly. The statement "inspired by X11 and
Linux kernel sources" in the .c file is a little troublesome though.
-Gedare
On Wed, Jun 20, 2012 at 1:35 PM, Pavel Pisa <ppisa4lists at pikron.com> wrote:
> The driver is compatible with PCI GD5446 provided by QEMU.
> QEMU option "-vga cirrus".
>
> Driver locates PCI device and configures it for linear framebuffer
> when "/dev/fb0" is open. Default mode and bit depths are
> controlled by FB_CIRRUS_DEFAULT_MODE, FB_CIRRUS_DEFAULT_BPP
> defines. 32, 24 and 16 bits per pixel with FB_VISUAL_TRUECOLOR
> are supported. 8 bit mode is not finished - requires palette support.
>
> To use alternative Cirrus framebuffer, replace line
> libbsp_a_SOURCES += console/fb_vga.c
> in
> c/src/lib/libbsp/i386/pc386/Makefile.am b/c/src/lib/libbsp/i386/pc386/Makefile.am
> by
> libbsp_a_SOURCES += console/fb_cirrus.c
>
> Signed-off-by: Pavel Pisa <pisa at cmp.felk.cvut.cz>
> ---
> c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c | 709 ++++++++++++++++++++
> .../lib/libbsp/i386/pc386/console/vga_registers.h | 102 +++
> 2 files changed, 811 insertions(+)
> create mode 100644 c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c
> create mode 100644 c/src/lib/libbsp/i386/pc386/console/vga_registers.h
>
> diff --git a/c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c b/c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c
> new file mode 100644
> index 0000000..760003e
> --- /dev/null
> +++ b/c/src/lib/libbsp/i386/pc386/console/fb_cirrus.c
> @@ -0,0 +1,709 @@
> +/*
> + * Copyright (c) 2012 - Pavel Pisa ( pisa at cmp.felk.cvut.cz )
> + *
> + * MODULE DESCRIPTION:
> + * This module implements FB driver for "Cirrus GD5446" found in Qemu
> + * emulator.
> + *
> + * The code is based on fb_vga.c written by
> + * Copyright (c) 2000 Rosimildo da Silva ( rdasilva at connecttel.com )
> + * and it is inspired by X11 and Linux kernel sources
> + *
> + */
> +
> +#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/pci.h>
> +
> +#include <rtems/fb.h>
> +
> +#include "vga_registers.h"
> +
> +/* these routines are defined in vgainit.c.*/
> +extern void ega_hwinit( void );
> +extern void ega_hwterm( void );
> +
> +/* mutex attribure */
> +pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
> +
> +
> +#define FB_CIRRUS_MAX_CARDS 1
> +
> +#define CIRRUS_VENDOR_ID 0x1013
> +#define CIRRUS_GD5446_DEVICE_ID 0x00b8
> +
> +/* video modes
> + 640 x 480
> + 800 x 600
> + 1024 x 768
> + 1280 x 1024
> +*/
> +struct fb_cirrus_modeline {
> + int clock;
> + int hdisplay;
> + int hsync_start;
> + int hsync_end;
> + int htotal;
> + int hskew;
> + int vdisplay;
> + int vsync_start;
> + int vsync_end;
> + int vtotal;
> + int vscan;
> + unsigned int flags;
> +};
> +
> +struct fb_cirrus_state {
> + int found;
> + int pbus;
> + int pdev;
> + int pfun;
> + uint32_t pci_bar[4];
> + struct fb_var_screeninfo fb_var;
> + struct fb_fix_screeninfo fb_fix;
> + void *mmregs;
> + struct fb_cirrus_modeline *active_mode;
> +};
> +
> +/* 1/4bpp 8bpp 15/16bpp 24bpp 32bpp */
> +static int fb_cirrus_max_clocks[] = { 135100, 135100, 85500, 85500, 0 };
> +
> +static struct fb_cirrus_modeline fb_cirrus_std_modelines[] = {
> + { .clock = 31500,
> + .hdisplay = 640, .hsync_start = 664, .hsync_end = 704, .htotal = 832, .hskew = 0,
> + .vdisplay = 480, .vsync_start = 489, .vsync_end = 492, .vtotal = 520, .vscan = 0,
> + .flags = 0
> + },
> + { .clock = 40000,
> + .hdisplay = 800, .hsync_start = 840, .hsync_end = 968, .htotal = 1056, .hskew = 0,
> + .vdisplay = 600, .vsync_start = 601, .vsync_end = 605, .vtotal = 628, .vscan = 0,
> + .flags = 0
> + },
> + { .clock = 0,
> + },
> +};
> +
> +#ifndef FB_CIRRUS_DEFAULT_MODE
> +/* TUNABLE - until better place is found, the mode is selected there */
> +/* index 0 provides 640x480 at 60 Hz, index 1 800x600 at 60 Hz */
> +#define FB_CIRRUS_DEFAULT_MODE 0
> +#endif
> +
> +#ifndef FB_CIRRUS_DEFAULT_BPP
> +/* Bits per pixel, 8, 16, 24 and 32 are supported */
> +/* 8 bit mode requires palete support which is not finished yet */
> +#define FB_CIRRUS_DEFAULT_BPP 24
> +#endif
> +
> +static struct fb_cirrus_state fb_cirrus[FB_CIRRUS_MAX_CARDS];
> +
> +static int
> +fb_cirrus_read_config_dword(
> + struct fb_cirrus_state *fbst,
> + unsigned char where,
> + uint32_t *pval)
> +{
> + return pci_read_config_dword(
> + fbst->pbus, fbst->pdev, fbst->pfun,
> + where, pval);
> +}
> +
> +static int
> +fb_cirrus_write_config_dword(
> + struct fb_cirrus_state *fbst,
> + unsigned char where,
> + uint32_t val)
> +{
> + return pci_write_config_dword(
> + fbst->pbus, fbst->pdev, fbst->pfun,
> + where, val);
> +}
> +
> +static void
> +fb_cirrus_write_reg8 (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg,
> + unsigned int val)
> +{
> + *(volatile uint8_t*)((char *)fbst->mmregs + reg) = val;
> +}
> +
> +static void
> +fb_cirrus_write_reg32 (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg,
> + uint32_t val)
> +{
> + *(volatile uint32_t*)((char *)fbst->mmregs + reg) = val;
> +}
> +
> +static unsigned int
> +fb_cirrus_read_reg8 (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg)
> +{
> + return *(volatile uint8_t*)((char *)fbst->mmregs + reg);
> +}
> +
> +static uint32_t
> +fb_cirrus_read_reg32 (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg)
> +{
> + return *(volatile uint32_t*)((char *)fbst->mmregs + reg);
> +}
> +#define SEQ_INDEX 4
> +#define SEQ_DATA 5
> +
> +static void
> +fb_cirrus_write_seq_reg (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg,
> + unsigned int val)
> +{
> + fb_cirrus_write_reg8(fbst, SEQ_INDEX, reg);
> + fb_cirrus_write_reg8(fbst, SEQ_DATA, val);
> +}
> +
> +#define CRT_INDEX 0x14
> +#define CRT_DATA 0x15
> +
> +static void
> +fb_cirrus_write_crt_reg (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg,
> + unsigned int val)
> +{
> + fb_cirrus_write_reg8(fbst, CRT_INDEX, reg);
> + fb_cirrus_write_reg8(fbst, CRT_DATA, val);
> +}
> +
> +#define GDC_INDEX 0xe
> +#define GDC_DATA 0xf
> +
> +static void
> +fb_cirrus_write_gdc_reg (
> + const struct fb_cirrus_state *fbst,
> + unsigned int reg,
> + unsigned int val)
> +{
> + fb_cirrus_write_reg8(fbst, GDC_INDEX, reg);
> + fb_cirrus_write_reg8(fbst, GDC_DATA, val);
> +}
> +
> +
> +#define VGA_DAC_MASK 0x6
> +
> +static void
> +fb_cirrus_write_hdr_reg (
> + const struct fb_cirrus_state *fbst,
> + unsigned int val)
> +{
> + volatile unsigned int dummy __attribute__((unused));
> + dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
> + dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
> + dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
> + dummy = fb_cirrus_read_reg8(fbst, VGA_DAC_MASK);
> + fb_cirrus_write_reg8(fbst, VGA_DAC_MASK, val);
> +}
> +
> +static void
> +fb_cirrus_set_start_address(
> + struct fb_cirrus_state *fbst,
> + unsigned offset)
> +{
> + uint32_t addr;
> + uint8_t tmp;
> +
> + addr = offset >> 2;
> + fb_cirrus_write_crt_reg(fbst, 0x0c, (uint8_t)((addr >> 8) & 0xff));
> + fb_cirrus_write_crt_reg(fbst, 0x0d, (uint8_t)(addr & 0xff));
> +
> + fb_cirrus_write_reg8(fbst, CRT_INDEX, 0x1b);
> + tmp = fb_cirrus_read_reg8(fbst, CRT_DATA);
> + tmp &= 0xf2;
> + tmp |= (addr >> 16) & 0x01;
> + tmp |= (addr >> 15) & 0x0c;
> + fb_cirrus_write_crt_reg(fbst, 0x1b, tmp);
> + fb_cirrus_write_reg8(fbst, CRT_INDEX, 0x1d);
> + tmp = fb_cirrus_read_reg8(fbst, CRT_DATA);
> + tmp &= 0x7f;
> + tmp |= (addr >> 12) & 0x80;
> + fb_cirrus_write_crt_reg(fbst, 0x1d, tmp);
> +}
> +
> +
> +static int
> +fb_cirrus_set_crt_mode(
> + struct fb_cirrus_state *fbst,
> + struct fb_cirrus_modeline *mode)
> +{
> + int hsyncstart, hsyncend, htotal, hdispend;
> + int vtotal, vdispend;
> + int tmp;
> + int sr07 = 0, hdr = 0;
> + int x, y;
> +
> + htotal = mode->htotal / 8;
> + hsyncend = mode->hsync_end / 8;
> + hsyncstart = mode->hsync_start / 8;
> + hdispend = mode->hdisplay / 8;
> +
> + vtotal = mode->vtotal;
> + vdispend = mode->vdisplay;
> +
> + vdispend -= 1;
> + vtotal -= 2;
> +
> + htotal -= 5;
> + hdispend -= 1;
> + hsyncstart += 1;
> + hsyncend += 1;
> +
> + fb_cirrus_write_crt_reg(fbst, CRTC_EndVertRetrace, 0x20);
> + fb_cirrus_write_crt_reg(fbst, CRTC_HorzTotal, htotal);
> + fb_cirrus_write_crt_reg(fbst, CRTC_HorzDispEnd, hdispend);
> + fb_cirrus_write_crt_reg(fbst, CRTC_StartHorzRetrace, hsyncstart);
> + fb_cirrus_write_crt_reg(fbst, CRTC_EndHorzRetrace, hsyncend);
> + fb_cirrus_write_crt_reg(fbst, CRTC_VertTotal, vtotal & 0xff);
> + fb_cirrus_write_crt_reg(fbst, CRTC_VertDispEnd, vdispend & 0xff);
> +
> + tmp = 0x40;
> + if ((vdispend + 1) & 512)
> + tmp |= 0x20;
> + fb_cirrus_write_crt_reg(fbst, CRTC_MaxScanLine, tmp);
> +
> + tmp = 16;
> + if (vtotal & 256)
> + tmp |= 1;
> + if (vdispend & 256)
> + tmp |= 2;
> + if ((vdispend + 1) & 256)
> + tmp |= 8;
> + if (vtotal & 512)
> + tmp |= 32;
> + if (vdispend & 512)
> + tmp |= 64;
> + fb_cirrus_write_crt_reg(fbst, CRTC_Overflow, tmp);
> +
> + tmp = 0;
> +
> + if ((htotal + 5) & 64)
> + tmp |= 16;
> + if ((htotal + 5) & 128)
> + tmp |= 32;
> + if (vtotal & 256)
> + tmp |= 64;
> + if (vtotal & 512)
> + tmp |= 128;
> +
> + fb_cirrus_write_crt_reg(fbst, 0x1A, tmp);
> +
> + /* Disable Hercules/CGA compatibility */
> + fb_cirrus_write_crt_reg(fbst, CRTC_ModeCtrl, 0x03);
> +
> + fb_cirrus_write_reg8(fbst, SEQ_INDEX, 0x7);
> + sr07 = fb_cirrus_read_reg8(fbst, SEQ_DATA);
> + sr07 &= 0xe0;
> + hdr = 0;
> + switch (fbst->fb_var.bits_per_pixel) {
> + case 8:
> + sr07 |= 0x11;
> + break;
> + case 16:
> + sr07 |= 0xc7; /* has been 0xc1 */
> + hdr = 0xc0;
> + break;
> + case 24:
> + sr07 |= 0x15;
> + hdr = 0xc5;
> + break;
> + case 32:
> + sr07 |= 0x19;
> + hdr = 0xc5;
> + break;
> + default:
> + printk("FBCIRRUS fb_cirrus_set_crt_mode unsuported BPP\n");
> + return -1;
> + }
> +
> + fb_cirrus_write_seq_reg(fbst, 0x7, sr07);
> +
> + /* Program the pitch */
> + tmp = fbst->fb_fix.line_length / 8;
> + fb_cirrus_write_crt_reg(fbst, CRTC_Offset, tmp);
> +
> + /* Enable extended blanking and pitch bits, and enable full memory */
> + tmp = 0x22;
> + tmp |= (fbst->fb_fix.line_length >> 7) & 0x10;
> + tmp |= (fbst->fb_fix.line_length >> 6) & 0x40;
> + fb_cirrus_write_crt_reg(fbst, 0x1b, tmp);
> +
> + /* Enable high-colour modes */
> + fb_cirrus_write_gdc_reg(fbst, GDC_Mode, 0x40);
> +
> + /* And set graphics mode */
> + fb_cirrus_write_gdc_reg(fbst, GDC_Misc, 0x01);
> +
> + fb_cirrus_write_hdr_reg(fbst, hdr);
> +
> + fb_cirrus_set_start_address(fbst, 0);
> +
> +
> + if (1) {
> + uint32_t pixmask;
> +
> + if(fbst->fb_var.bits_per_pixel == 32)
> + pixmask = 0xffffff;
> + else
> + pixmask = (1 << fbst->fb_var.bits_per_pixel) - 1;
> +
> + printk("FBCIRRUS mode set, test patter output\n");
> +
> + /*while(1)*/
> + for(y = 0; y < fbst->fb_var.yres; y++) {
> + for(x = 0; x < fbst->fb_var.xres; x++) {
> + uint32_t color;
> + char *addr = (char *)fbst->fb_fix.smem_start;
> + addr += y * fbst->fb_fix.line_length;
> + addr += x * fbst->fb_var.bits_per_pixel / 8;
> + color = x & 1 ? 0 : y & 1 ? pixmask & 0x000ff00f : pixmask;
> + if(y == fbst->fb_var.yres - 1) {
> + if((x > 0) && (x < fbst->fb_var.xres-1))
> + color = pixmask & 0x00555555;
> + }
> + switch (fbst->fb_var.bits_per_pixel) {
> + case 8: *(volatile uint8_t*) addr = color;
> + break;
> + case 16: *(volatile uint16_t*) addr = color;
> + break;
> + case 24: *(volatile uint32_t*) addr =
> + (*(volatile uint32_t*) addr & 0xff000000) | color;
> + break;
> + case 32: *(volatile uint32_t*) addr = color;
> + break;
> + }
> + }
> + }
> + }
> +
> + return 0;
> +}
> +
> +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;
> + int res;
> + struct fb_cirrus_state *fbst;
> + char devname[12];
> + char *p;
> +
> + if(minor >= FB_CIRRUS_MAX_CARDS) {
> + printk( "FBCIRRUS initialize -- unsupported minor\n" );
> + return RTEMS_UNSATISFIED;
> + }
> +
> + fbst = &fb_cirrus[minor];
> +
> + res = pci_find_device(
> + CIRRUS_VENDOR_ID,
> + CIRRUS_GD5446_DEVICE_ID,
> + minor,
> + &fbst->pbus,
> + &fbst->pdev,
> + &fbst->pfun
> + );
> +
> + if ( res != PCIB_ERR_SUCCESS ) {
> + fbst->found = -1;
> + printk( "FBCIRRUS initialize -- device not found\n" );
> + return RTEMS_UNSATISFIED;
> + }
> +
> + printk( "FBCIRRUS -- driver initializing..\n" );
> +
> + /*
> + * Register the device
> + */
> + p = strcpy(devname, "/dev/fb0");
> + *(--p) = '0' + minor;
> +
> + status = rtems_io_register_name (devname, major, 0);
> + if (status != RTEMS_SUCCESSFUL) {
> + fbst->found = -1;
> + printk("Error registering /dev/fbX FBCIRRUS framebuffer device!\n");
> + rtems_fatal_error_occurred( status );
> + }
> +
> + fbst->found = 1;
> +
> + 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
> +)
> +{
> + struct fb_cirrus_state *fbst;
> + int line_bytes;
> +
> + if(minor >= FB_CIRRUS_MAX_CARDS) {
> + printk( "FBCIRRUS initialize -- unsupported minor\n" );
> + return RTEMS_UNSATISFIED;
> + }
> +
> + fbst = &fb_cirrus[minor];
> +
> + if (pthread_mutex_trylock(&mutex)!= 0) {
> + printk( "FBCIRRUS open cannot grab mutex.\n" );
> + return RTEMS_UNSATISFIED;
> + }
> +
> + printf("FBCIRRUS found %d pbus %d pdev %d pfun %d\n",
> + fbst->found, fbst->pbus, fbst->pdev, fbst->pfun);
> +
> + fb_cirrus_read_config_dword(fbst, PCI_BASE_ADDRESS_0, &fbst->pci_bar[0]);
> + fb_cirrus_read_config_dword(fbst, PCI_BASE_ADDRESS_1, &fbst->pci_bar[1]);
> + fb_cirrus_read_config_dword(fbst, PCI_BASE_ADDRESS_2, &fbst->pci_bar[2]);
> + fb_cirrus_read_config_dword(fbst, PCI_BASE_ADDRESS_3, &fbst->pci_bar[3]);
> +
> + fbst->pci_bar[0] &= PCI_BASE_ADDRESS_MEM_MASK;
> + fbst->pci_bar[1] &= PCI_BASE_ADDRESS_MEM_MASK;
> +
> + printf("FBCIRRUS PCI BARs 0x%08lx 0x%08lx 0x%08lx 0x%08lx\n",
> + fbst->pci_bar[0], fbst->pci_bar[1], fbst->pci_bar[2], fbst->pci_bar[3]);
> +
> + if (_CPU_is_paging_enabled()) {
> + _CPU_map_phys_address((void **) &(fbst->fb_fix.smem_start),
> + (void *)(fbst->pci_bar[0]),
> + 0x1000000 ,
> + PTE_CACHE_DISABLE | PTE_WRITABLE);
> + _CPU_map_phys_address((void **) &(fbst->mmregs),
> + (void *)(fbst->pci_bar[1]),
> + 0x1000,
> + PTE_CACHE_DISABLE | PTE_WRITABLE);
> + } else {
> + fbst->fb_fix.smem_start = (volatile char *)fbst->pci_bar[0];
> + fbst->mmregs = (void *)fbst->pci_bar[1];
> + }
> +
> + fbst->fb_fix.smem_len = 0x1000000;
> +
> + fbst->fb_fix.type = FB_TYPE_PACKED_PIXELS;
> + fbst->fb_fix.visual = FB_VISUAL_TRUECOLOR;
> +
> + printf("FBCIRRUS remapped fb 0x%08lx mmregs 0x%08lx\n",
> + (unsigned long)fbst->fb_fix.smem_start, (unsigned long)fbst->mmregs);
> +
> + fbst->active_mode = &fb_cirrus_std_modelines[FB_CIRRUS_DEFAULT_MODE];
> +
> + fbst->fb_var.bits_per_pixel = FB_CIRRUS_DEFAULT_BPP;
> +
> + fbst->fb_var.xres = fbst->active_mode->hdisplay;
> + fbst->fb_var.yres = fbst->active_mode->vdisplay;
> +
> + line_bytes = fbst->fb_var.xres * fbst->fb_var.bits_per_pixel;
> +
> + line_bytes = (line_bytes + 7) / 8;
> +
> + fbst->fb_fix.line_length = line_bytes;
> +
> + fb_cirrus_set_crt_mode(fbst, fbst->active_mode);
> +
> + printk( "FBCIRRUS open called.\n" );
> + return RTEMS_SUCCESSFUL;
> +
> +}
> +
> +/*
> + * fbvga device driver CLOSE entry point
> + */
> +rtems_device_driver frame_buffer_close(
> + rtems_device_major_number major,
> + rtems_device_minor_number minor,
> + void *arg
> +)
> +{
> + if (pthread_mutex_unlock(&mutex) == 0){
> + /* restore previous state. for VGA this means return to text mode.
> + * leave out if graphics hardware has been initialized in
> + * frame_buffer_initialize() */
> + printk( "FBCIRRUS close called.\n" );
> + return RTEMS_SUCCESSFUL;
> + }
> +
> + return RTEMS_UNSATISFIED;
> +}
> +
> +/*
> + * fbvga device driver READ entry point.
> + */
> +rtems_device_driver frame_buffer_read(
> + rtems_device_major_number major,
> + rtems_device_minor_number minor,
> + void *arg
> +)
> +{
> + struct fb_cirrus_state *fbst;
> +
> + if(minor >= FB_CIRRUS_MAX_CARDS) {
> + return RTEMS_UNSATISFIED;
> + }
> +
> + fbst = &fb_cirrus[minor];
> +
> + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
> + rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fbst->fb_fix.smem_len ) ? (fbst->fb_fix.smem_len -
> rw_args->offset) : rw_args->count;
> + memcpy(rw_args->buffer, (const void *) (fbst->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
> +)
> +{
> + struct fb_cirrus_state *fbst;
> +
> + if(minor >= FB_CIRRUS_MAX_CARDS) {
> + return RTEMS_UNSATISFIED;
> + }
> +
> + fbst = &fb_cirrus[minor];
> +
> + rtems_libio_rw_args_t *rw_args = (rtems_libio_rw_args_t *)arg;
> + rw_args->bytes_moved = ((rw_args->offset + rw_args->count) > fbst->fb_fix.smem_len ) ? (fbst->fb_fix.smem_len -
> rw_args->offset) : rw_args->count;
> + memcpy( (void *) (fbst->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_cirrus_state *fbst, struct fb_fix_screeninfo *info )
> +{
> + *info = fbst->fb_fix;
> + return 0;
> +}
> +
> +static int get_var_screen_info(struct fb_cirrus_state *fbst, struct fb_var_screeninfo *info )
> +{
> + *info = fbst->fb_var;
> + return 0;
> +}
> +
> +static int get_palette(struct fb_cirrus_state *fbst, 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_cirrus_state *fbst, 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;
> + struct fb_cirrus_state *fbst;
> +
> + if(minor >= FB_CIRRUS_MAX_CARDS) {
> + return RTEMS_UNSATISFIED;
> + }
> +
> + fbst = &fb_cirrus[minor];
> +
> + printk( "FBCIRRUS ioctl called, cmd=%x\n", args->command );
> +
> + switch( args->command ) {
> + case FBIOGET_FSCREENINFO:
> + args->ioctl_return = get_fix_screen_info( fbst, ( struct fb_fix_screeninfo * ) args->buffer );
> + break;
> + case FBIOGET_VSCREENINFO:
> + args->ioctl_return = get_var_screen_info( fbst, ( 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( fbst, ( struct fb_cmap * ) args->buffer );
> + break;
> + case FBIOPUTCMAP:
> + args->ioctl_return = set_palette( fbst, ( struct fb_cmap * ) args->buffer );
> + break;
> +
> + default:
> + args->ioctl_return = 0;
> + break;
> + }
> + return RTEMS_SUCCESSFUL;
> +}
> +
> diff --git a/c/src/lib/libbsp/i386/pc386/console/vga_registers.h b/c/src/lib/libbsp/i386/pc386/console/vga_registers.h
> new file mode 100644
> index 0000000..816269f
> --- /dev/null
> +++ b/c/src/lib/libbsp/i386/pc386/console/vga_registers.h
> @@ -0,0 +1,102 @@
> +
> +/*
> + * Copyright (c) 1992, 1993, 1996
> + * Berkeley Software Design, Inc. 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.
> + * 3. All advertising materials mentioning features or use of this software
> + * must display the following acknowledgement:
> + * This product includes software developed by Berkeley Software
> + * Design, Inc.
> + *
> + * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``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 Berkeley Software Design, Inc. 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.
> + *
> + * BSDI video.h,v 2.2 1996/04/08 19:33:12 bostic Exp
> + *
> + * Subset of the full header file adapted for RTEMS operating system from
> + *
> + * FreeBSD: src/usr.bin/doscmd/video.h,v 1.2.2.1 2002/04/25 11:04:51 tg Exp $
> + */
> +
> +/* CRTC registers
> +
> + We use the VGA register functions and don't care about the MDA. We also
> + leave out the undocumented registers at 0x22, 0x24, 0x3?. */
> +#define CRTC_HorzTotal 0x00
> +#define CRTC_HorzDispEnd 0x01
> +#define CRTC_StartHorzBlank 0x02
> +#define CRTC_EndHorzBlank 0x03
> +#define CRTC_StartHorzRetrace 0x04
> +#define CRTC_EndHorzRetrace 0x05
> +#define CRTC_VertTotal 0x06
> +#define CRTC_Overflow 0x07
> +#define CRTC_ResetRowScan 0x08
> +#define CRTC_MaxScanLine 0x09
> +#define CRTC_CursStart 0x0a
> +#define CRTC_CursEnd 0x0b
> +#define CRTC_StartAddrHi 0x0c
> +#define CRTC_StartAddrLo 0x0d
> +#define CRTC_CurLocHi 0x0e
> +#define CRTC_CurLocLo 0x0f
> +#define CRTC_StartVertRetrace 0x10
> +#define CRTC_EndVertRetrace 0x11
> +#define CRTC_VertDispEnd 0x12
> +#define CRTC_Offset 0x13
> +#define CRTC_UnderlineLoc 0x14
> +#define CRTC_StartVertBlank 0x15
> +#define CRTC_EndVertBlank 0x16
> +#define CRTC_ModeCtrl 0x17
> +#define CRTC_LineCompare 0x18
> +
> +#define CRTC_Size 0x19
> +
> +/* Port addresses for the CRTC
> +
> + The registers are read by
> + OUT index_port, reg_nr
> + IN data_port, res
> +
> + They are written by
> + OUT index_port, reg_nr
> + OUT data_port, value
> +*/
> +
> +#define CRTC_IndexPortColor 0x03d4 /* CRTC Address Register (Color) */
> +#define CRTC_DataPortColor 0x03d5 /* CRTC Data Register (Color) */
> +#define CRTC_IndexPortMono 0x03b4 /* CRTC Address Register (Mono) */
> +#define CRTC_DataPortMono 0x03b5 /* CRTC Data Register (Mono) */
> +
> +/* GDC registers */
> +#define GDC_SetReset 0x00
> +#define GDC_EnableSetReset 0x01
> +#define GDC_ColorCompare 0x02
> +#define GDC_DataRotate 0x03
> +#define GDC_ReadMapSelect 0x04
> +#define GDC_Mode 0x05
> +#define GDC_Misc 0x06
> +#define GDC_ColorDontCare 0x07
> +#define GDC_BitMask 0x08
> +
> +#define GDC_Size 0x09
> +
> +/* Port addresses for the GDC */
> +#define GDC_IndexPort 0x03ce
> +#define GDC_DataPort 0x03cf
> +
> --
> 1.7.10
>
More information about the devel
mailing list