[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