public inbox for ecos-devel@sourceware.org
 help / color / mirror / Atom feed
* Graphics routines for VMWare
@ 2006-10-13 15:01 Peter Dennett
  2006-10-18 19:25 ` Andrew Lunn
  0 siblings, 1 reply; 3+ messages in thread
From: Peter Dennett @ 2006-10-13 15:01 UTC (permalink / raw)
  To: ecos-devel

[-- Attachment #1: Type: text/plain, Size: 359 bytes --]


For those interested in developing eCos applications under VMWare 
attached are a couple of files that support access to the SVGA 
adapter emulated by VMWare.  This has been tested under Workstation 
5.5. 

Also attached is a wrapper for this interface to pwlib.

Peter Dennett       Office: 281 334 3800
www.padsoft.com       Cell: 713 899 6100


[-- Attachment #2: vmware-vga.c --]
[-- Type: application/octet-stream, Size: 16186 bytes --]

/*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/
/*                                                                           */
/* Developed by:          Peter Armistead Dennett                            */
/*                              PADSOFT, Inc                                 */
/*                            61 Harbor Lane                                 */
/*                          Kemah, Texas 77565                               */
/*                                                                           */
/*                          pdennett@padsoft.com                             */
/*                            (281) 334 3800                                 */
/*                         http://www.padsoft.com                            */
/*                                                                           */
/*                           NO rights reserved                              */
/*                                                                           */
/*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/

//  vmware-vga.c   Interface routines for VMWare frame buffer under eCos

//  Revision History
//    Oct 2006 by Peter Dennett
//      - Initial version, based on documents from the xfree86 VMWare driver 

//===========================================================================
// VMWARE-VGA is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// VMWARE-VGA is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with PW; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//===========================================================================

#include <unistd.h>                     // sleep()
#include <string.h>                     // memset()
#include <pkgconf/system.h>
#include <pkgconf/kernel.h>
#include <pkgconf/io_pci.h>
#include <cyg/io/pci.h>
#include <cyg/hal/hal_intr.h>           // HAL_DISABLE_INTERRUPT
#include <cyg/hal/hal_arch.h>
#include <cyg/hal/hal_io.h>             // HAL_WRITE & READ
#include <cyg/infra/diag.h>             // diag_printf
#include <cyg/kernel/kapi.h>            // thread defines

#include "vmware-vga.h"

//////////////////////////////////////////////////////////////////////////////
//  Register operations

static uint32 vmwareReadReg(pVMWareVGA pVMWARE, uint32 index)
{
uint32 ret;
CYG_INTERRUPT_STATE interruptState;

  HAL_DISABLE_INTERRUPTS(interruptState); // Dont allow interrupts between ops
  HAL_WRITE_UINT32(pVMWARE->indexReg, index);
  HAL_READ_UINT32(pVMWARE->valueReg, ret);
  HAL_RESTORE_INTERRUPTS(interruptState);

  return ret;
}

static void vmwareWriteReg(pVMWareVGA pVMWARE, uint32 index, uint32 value)
{
CYG_INTERRUPT_STATE interruptState;

  HAL_DISABLE_INTERRUPTS(interruptState); // Dont allow interrupts between ops
  HAL_WRITE_UINT32(pVMWARE->indexReg, index);
  HAL_WRITE_UINT32(pVMWARE->valueReg, value);
  HAL_RESTORE_INTERRUPTS(interruptState);

  return;
}

//////////////////////////////////////////////////////////////////////////////
//  FIFO operations

static void vmwareWaitForFIFO(pVMWareVGA pVMWARE)
{
  vmwareWriteReg(pVMWARE, SVGA_REG_SYNC, 1);

  while (vmwareReadReg(pVMWARE, SVGA_REG_BUSY)) ;

  return;
}

static void vmwareWriteWordToFIFO(pVMWareVGA pVMWARE, uint32 value)
{
uint32 *vmwareFIFO = pVMWARE->FIFO;

// Need to sync?

  if ((vmwareFIFO[SVGA_FIFO_NEXT_CMD] + sizeof(uint32) == vmwareFIFO[SVGA_FIFO_STOP]) || 
      (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32) &&
       vmwareFIFO[SVGA_FIFO_STOP] == vmwareFIFO[SVGA_FIFO_MIN])) 
  {
    diag_printf("vmware-vga: Syncing because of full fifo\n");
    vmwareWaitForFIFO(pVMWARE);
  }

  vmwareFIFO[vmwareFIFO[SVGA_FIFO_NEXT_CMD] / sizeof(uint32)] = value;

  if (vmwareFIFO[SVGA_FIFO_NEXT_CMD] == (vmwareFIFO[SVGA_FIFO_MAX] - sizeof(uint32)))
    vmwareFIFO[SVGA_FIFO_NEXT_CMD] = vmwareFIFO[SVGA_FIFO_MIN];
  else 
    vmwareFIFO[SVGA_FIFO_NEXT_CMD] += sizeof(uint32);

#if 0
  diag_printf("FIFO MIN: %08X MAX: %08X NEXT %08X STOP %08X VALUE %08X\n", 
              vmwareFIFO[SVGA_FIFO_MIN],
              vmwareFIFO[SVGA_FIFO_MAX],
              vmwareFIFO[SVGA_FIFO_NEXT_CMD],
              vmwareFIFO[SVGA_FIFO_STOP],
              value);
#endif

  return;
}

static void vmwareInitFIFO(pVMWareVGA pVMWARE)
{
uint32 *vmwareFIFO;

  vmwareFIFO = pVMWARE->FIFO;
  vmwareFIFO[SVGA_FIFO_MIN] = 4 * sizeof(uint32);
  vmwareFIFO[SVGA_FIFO_MAX] = pVMWARE->FIFOSize;
  vmwareFIFO[SVGA_FIFO_NEXT_CMD] = 4 * sizeof(uint32);
  vmwareFIFO[SVGA_FIFO_STOP] = 4 * sizeof(uint32);

#if 0
  diag_printf("FIFO MIN: %08X MAX: %08X NEXT %08X STOP %08X\n", vmwareFIFO[SVGA_FIFO_MIN],
              vmwareFIFO[SVGA_FIFO_MAX],
              vmwareFIFO[SVGA_FIFO_NEXT_CMD],
              vmwareFIFO[SVGA_FIFO_STOP]);
#endif

  vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 1);

  return;
}

static void vmwareStopFIFO(pVMWareVGA pVMWARE)
{
  vmwareWriteReg(pVMWARE, SVGA_REG_CONFIG_DONE, 0);
}

//////////////////////////////////////////////////////////////////////////////
//  FIFO commands

static void vmwareSendSVGACmdUpdate(pVMWareVGA pVMWARE, pBoxRec pBB)
{
  vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_UPDATE);
  vmwareWriteWordToFIFO(pVMWARE, pBB->x1);
  vmwareWriteWordToFIFO(pVMWARE, pBB->y1);
  vmwareWriteWordToFIFO(pVMWARE, pBB->x2 - pBB->x1);
  vmwareWriteWordToFIFO(pVMWARE, pBB->y2 - pBB->y1);

  return;
}

static void vmwareSendSVGACmdUpdateFullScreen(pVMWareVGA pVMWARE)
{
BoxRec BB;

  BB.x1 = 0;
  BB.y1 = 0;
  BB.x2 = pVMWARE->FBWidth;
  BB.y2 = pVMWARE->FBHeight;

  vmwareSendSVGACmdUpdate(pVMWARE, &BB);

  return;
}

static void vmwareSolidFill(pVMWareVGA pVMWARE, uint32 x, uint32 y, 
                            uint32 w, uint32 h, uint32 color)
{
  vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_FILL);
  vmwareWriteWordToFIFO(pVMWARE, color);
  vmwareWriteWordToFIFO(pVMWARE, x);
  vmwareWriteWordToFIFO(pVMWARE, y);
  vmwareWriteWordToFIFO(pVMWARE, w);
  vmwareWriteWordToFIFO(pVMWARE, h);

  return;
}

static void vmwareRectCopy(pVMWareVGA pVMWARE, uint32 x1, uint32 y1, 
                           uint32 x2, uint32 y2, uint32 w, uint32 h)
{
  vmwareWriteWordToFIFO(pVMWARE, SVGA_CMD_RECT_COPY);
  vmwareWriteWordToFIFO(pVMWARE, x1);
  vmwareWriteWordToFIFO(pVMWARE, y1);
  vmwareWriteWordToFIFO(pVMWARE, x2);
  vmwareWriteWordToFIFO(pVMWARE, y2);
  vmwareWriteWordToFIFO(pVMWARE, w);
  vmwareWriteWordToFIFO(pVMWARE, h);

  return;
}

//////////////////////////////////////////////////////////////////////////////
//  External interface routines

pVMWareVGA vmwareInitialize(void)
{
static VMWareVGA VMWARE;

cyg_pci_device dev_info;
cyg_pci_device_id devid;
cyg_uint16 cmd;
int i;

  //  Find and configuring PCI VGA devices

  cyg_pci_init();

  for (devid=CYG_PCI_NULL_DEVID; cyg_pci_find_next(devid, &devid); ) 
  {
    cyg_pci_get_device_info(devid, &dev_info); // Get device info

    if ((dev_info.vendor == PCI_VENDOR_ID_VMWARE) &&
        ((dev_info.device == PCI_DEVICE_ID_VMWARE_SVGA2) ||
         (dev_info.device == PCI_DEVICE_ID_VMWARE_SVGA)))
    {
      // Configure the device

      if (cyg_pci_configure_device(&dev_info)) 
      {
        // Don't use cyg_pci_set_device_info since it clears
        // some of the fields we want to print out below.

        cyg_pci_read_config_uint16(dev_info.devid,
                                   CYG_PCI_CFG_COMMAND, &cmd);
        cmd |= CYG_PCI_CFG_COMMAND_IO|CYG_PCI_CFG_COMMAND_MEMORY;
        cyg_pci_write_config_uint16(dev_info.devid,
                                    CYG_PCI_CFG_COMMAND, cmd);
      }
      else 
      {
        diag_printf(" Device configuration failed");

        if (dev_info.command & CYG_PCI_CFG_COMMAND_ACTIVE)
          diag_printf(" - device already enabled\n");
        else
          diag_printf(" - resource problem\n");
        continue;
      }

#if 0
      for (i=0; i<CYG_PCI_MAX_BAR; i++) 
      {
        diag_printf(" BAR[%d]    0x%08x /", i, dev_info.base_address[i]);
        diag_printf(" probed size 0x%08x / CPU addr 0x%08x\n",
                    dev_info.base_size[i], dev_info.base_map[i]);
      }
#endif

      //  We use th README.xfree86 documents to control our initialization

      // Compute base address for I/O registers

      if (dev_info.device == PCI_DEVICE_ID_VMWARE_SVGA)  // chip type 710
      {
        VMWARE.indexReg = SVGA_LEGACY_BASE_PORT + SVGA_INDEX_PORT*sizeof(uint32);
        VMWARE.valueReg = SVGA_LEGACY_BASE_PORT + SVGA_VALUE_PORT*sizeof(uint32);
      } 
      else      // chip type 405
      {         // Note:  This setting of valueReg causes unaligned I/O 
        VMWARE.indexReg = dev_info.base_map[0] + SVGA_INDEX_PORT;
        VMWARE.valueReg = dev_info.base_map[0] + SVGA_VALUE_PORT;
      }

#if 0
      diag_printf("  Base address for I/O: Index 0x%04X Value 0x%04X\n", 
                  VMWARE.indexReg, VMWARE.valueReg);
#endif

      // Report version we support

      vmwareWriteReg(&VMWARE, SVGA_REG_ID, SVGA_ID_2);
#if 0
      diag_printf("SVGA_REG_ID: 0x%08X\n", vmwareReadReg(&VMWARE, SVGA_REG_ID));
#endif

      //  Query the basics

      VMWARE.FB = (void *)vmwareReadReg(&VMWARE, SVGA_REG_FB_START);
      VMWARE.FBSize = vmwareReadReg(&VMWARE, SVGA_REG_FB_SIZE);
      VMWARE.FIFO = (void *)vmwareReadReg(&VMWARE, SVGA_REG_MEM_START);
      VMWARE.FIFOSize = vmwareReadReg(&VMWARE, SVGA_REG_MEM_SIZE);

      //  Report what OS we are

      vmwareWriteReg(&VMWARE, SVGA_REG_GUEST_ID, VMWARE_OS_OTHER);

      //  Set Mode

      VMWARE.FBWidth = 640;
      VMWARE.FBHeight = 400;
      VMWARE.FBBitsPerPixel = 8;

      vmwareWriteReg(&VMWARE, SVGA_REG_WIDTH, VMWARE.FBWidth);
      vmwareWriteReg(&VMWARE, SVGA_REG_HEIGHT, VMWARE.FBHeight);
      vmwareWriteReg(&VMWARE, SVGA_REG_BITS_PER_PIXEL, VMWARE.FBBitsPerPixel);

      //  Enable VGA

      vmwareWriteReg(&VMWARE, SVGA_REG_ENABLE, 1);

      //  Read back the values after configured

      VMWARE.Capabilities = vmwareReadReg(&VMWARE, SVGA_REG_CAPABILITIES);

      VMWARE.FBWidth =  vmwareReadReg(&VMWARE, SVGA_REG_WIDTH);
      VMWARE.FBHeight =  vmwareReadReg(&VMWARE, SVGA_REG_HEIGHT);
      VMWARE.FBBitsPerPixel = vmwareReadReg(&VMWARE, SVGA_REG_BITS_PER_PIXEL);

      VMWARE.FBOffset = vmwareReadReg(&VMWARE, SVGA_REG_FB_OFFSET);

      VMWARE.FBBytesPerLine = vmwareReadReg(&VMWARE, SVGA_REG_BYTES_PER_LINE);
      VMWARE.FBDepth = vmwareReadReg(&VMWARE, SVGA_REG_DEPTH);
      VMWARE.FBPseudoColor = vmwareReadReg(&VMWARE, SVGA_REG_PSEUDOCOLOR);
      VMWARE.FBRedMask = vmwareReadReg(&VMWARE, SVGA_REG_RED_MASK);
      VMWARE.FBGreenMask = vmwareReadReg(&VMWARE, SVGA_REG_GREEN_MASK);
      VMWARE.FBBlueMask = vmwareReadReg(&VMWARE, SVGA_REG_BLUE_MASK);

      //  Initialize the command FIFO

      vmwareInitFIFO(&VMWARE);

      //  Good to go...

      return &VMWARE;
    }
  }

  return (pVMWareVGA) 0;
}

void vmwareTerminate(pVMWareVGA pVMWARE)
{
  //  Disable VGA

  vmwareStopFIFO(pVMWARE);
  vmwareWriteReg(pVMWARE, SVGA_REG_ENABLE, 0);

  return;
}

void vmwareDrawPoint(pVMWareVGA pVMWARE, uint32 x, uint32 y, uint32 color)
{
uint8 *FB = pVMWARE->FB;

  *(FB+x+y*pVMWARE->FBBytesPerLine) = color;
}

void vmwareClear(pVMWareVGA pVMWARE, uint32 color)
{
uint8 *FB = pVMWARE->FB;

  memset(FB, (uint8)color, pVMWARE->FBWidth*pVMWARE->FBHeight);
  return;
}

void vmwareLoadPalette(pVMWareVGA pVMWARE, int numColors, int *indeces,
                       vmwareColors *colors)
{
int i;

  for (i=0; i<numColors; i++) 
  {
    vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + indeces[i] * 3 + 0, colors[i].red);
    vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + indeces[i] * 3 + 1, colors[i].green);
    vmwareWriteReg(pVMWARE, SVGA_PALETTE_BASE + indeces[i] * 3 + 2, colors[i].blue);
  }

  return;
}

#ifdef VMWARE_VGA_STANDALONE_TEST

unsigned char stack[CYGNUM_HAL_STACK_SIZE_TYPICAL];
cyg_thread thread_data;
cyg_handle_t thread_handle;

void vmware_vga_test( void )
{
pVMWareVGA pVMWARE;
int i;
#define N_COLORS 64
vmwareColors colors[N_COLORS];
int indeces[N_COLORS];

  sleep(5); // Let all the network stuff settle

  if ((pVMWARE = vmwareInitialize()) != (pVMWareVGA)0)
  {
    i = 0;
    indeces[i] = 0;
    colors[i].red = 0;
    colors[i].green = 0;
    colors[i].blue = 0;

    i++;
    indeces[i] = 255;
    colors[i].red = 255;
    colors[i].green = 255;
    colors[i].blue = 255;

    vmwareLoadPalette(pVMWARE, i+1, indeces, colors);

    vmwareClear(pVMWARE, 0);

    for (i=0; i<pVMWARE->FBHeight; i++)
      vmwareDrawPoint(pVMWARE, i, i, 255);

    vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
    sleep(5);

    for (i=0; i<pVMWARE->FBHeight; i++)
      vmwareDrawPoint(pVMWARE, i, pVMWARE->FBHeight-1-i, 255);

    vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
    sleep(5);

    if (pVMWARE->Capabilities & SVGA_CAP_RECT_FILL)
    {
      diag_printf("Test solid fill\n");
      vmwareSolidFill(pVMWARE, 50, 50, 35, 35, 255);

      vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
      sleep(5);
    }

    if (pVMWARE->Capabilities & SVGA_CAP_RECT_COPY)
    {
      diag_printf("Test rect copy\n");
      vmwareRectCopy(pVMWARE, 25, 25, 100, 50, 100, 100);

      vmwareSendSVGACmdUpdateFullScreen(pVMWARE);
      sleep(5);
    }

#if 1
    diag_printf("FBWidth:        %d\n", pVMWARE->FBWidth);
    diag_printf("FBHeight:       %d\n", pVMWARE->FBHeight);
    diag_printf("FBBitsPerPixel: %d\n", pVMWARE->FBBitsPerPixel);
    diag_printf("FBRedMask:      0x%X\n", pVMWARE->FBRedMask);
    diag_printf("FBGreenMask:    0x%X\n", pVMWARE->FBGreenMask);
    diag_printf("FBBlueMask:     0x%X\n", pVMWARE->FBBlueMask);
    diag_printf("FBDepth:        %d\n", pVMWARE->FBDepth);
    diag_printf("FBOffset:       %d\n", pVMWARE->FBOffset);
    diag_printf("FBBytesPerLine: %d\n", pVMWARE->FBBytesPerLine);
    diag_printf("FBSize:         %d\n", pVMWARE->FBSize);
    diag_printf("Capabilities:   0x%X\n", pVMWARE->Capabilities);
#endif
    vmwareTerminate(pVMWARE);
  }
  else
  {
    diag_printf("Did not find VMWare VGA\n");
  }

  while (1) sleep(1);
}

void cyg_start(void)
{
  cyg_thread_create(10,                   // Priority - just a number
                   (cyg_thread_entry_t*)vmware_vga_test,         // entry
                    0,                    // 
                    "vga_thread",         // Name
                    &stack[0],            // Stack
                    CYGNUM_HAL_STACK_SIZE_TYPICAL,               // Size
                    &thread_handle,       // Handle
                    &thread_data
    );
  cyg_thread_resume(thread_handle);
  cyg_scheduler_start();
}

#endif

[-- Attachment #3: vmware-vga.h --]
[-- Type: application/octet-stream, Size: 24901 bytes --]

/*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/
/*                                                                           */
/* Developed by:          Peter Armistead Dennett                            */
/*                              PADSOFT, Inc                                 */
/*                            61 Harbor Lane                                 */
/*                          Kemah, Texas 77565                               */
/*                                                                           */
/*                          pdennett@padsoft.com                             */
/*                            (281) 334 3800                                 */
/*                         http://www.padsoft.com                            */
/*                                                                           */
/*                           NO rights reserved                              */
/*                                                                           */
/*~*~*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*-*~*~*/

//  vmware-vga.h  Defines for the VMWare VGA framebuffer interface

//  Revision History
//    Oct 2006 by Peter Dennett
//      - Initial version, based on documents source examples from  XFree86 
//        VMWare driver

//===========================================================================
// VMWARE-VGA is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// VMWARE-VGA is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with PW; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//===========================================================================

#ifndef _VMWARE_VGA_H
#define _VMWARE_VGA_H

#ifdef __cplusplus
extern "C" {
#endif 

#define uint8  cyg_uint8
#define uint16 cyg_uint16
#define uint32 cyg_uint32

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree86/drivers/vmware/guest_os.h

#define VMWARE_OS_BASE  0x5000

#define VMWARE_OS_DOS        (VMWARE_OS_BASE+1)
#define VMWARE_OS_WIN31      (VMWARE_OS_BASE+2)
#define VMWARE_OS_WINDOWS95  (VMWARE_OS_BASE+3)
#define VMWARE_OS_WINDOWS98  (VMWARE_OS_BASE+4)
#define VMWARE_OS_WINDOWSME  (VMWARE_OS_BASE+5)
#define VMWARE_OS_NT         (VMWARE_OS_BASE+6)
#define VMWARE_OS_WIN2000    (VMWARE_OS_BASE+7)
#define VMWARE_OS_LINUX      (VMWARE_OS_BASE+8)
#define VMWARE_OS_OS2        (VMWARE_OS_BASE+9)
#define VMWARE_OS_OTHER      (VMWARE_OS_BASE+10)
#define VMWARE_OS_FREEBSD    (VMWARE_OS_BASE+11)
#define VMWARE_OS_WHISTLER   (VMWARE_OS_BASE+12)

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree/drivers/vmware/vm_device_version.h

#define PCI_VENDOR_ID_VMWARE        0x15AD
#define PCI_DEVICE_ID_VMWARE_SVGA2  0x0405
#define PCI_DEVICE_ID_VMWARE_SVGA   0x0710
#define PCI_DEVICE_ID_VMWARE_NET    0x0720
#define PCI_DEVICE_ID_VMWARE_SCSI   0x0730
#define PCI_DEVICE_ID_VMWARE_IDE    0x1729

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree/drivers/vmware/svga_limits.h

/*
 * Location and size of SVGA frame buffer and the FIFO.
 */
#define SVGA_VRAM_SIZE         (16*1024*1024)
#define SVGA_MEM_SIZE          (256*1024)

/*
 * SVGA_FB_START is the default starting address of the SVGA frame
 * buffer in the guest's physical address space.
 * SVGA_FB_START_BIGMEM is the starting address of the SVGA frame
 * buffer for VMs that have a large amount of physical memory.
 *
 * The address of SVGA_FB_START is set to 2GB - (SVGA_FB_MAX_SIZE + SVGA_MEM_SIZE), 
 * thus the SVGA frame buffer sits at [SVGA_FB_START .. 2GB-1] in the
 * physical address space.  Our older SVGA drivers for NT treat the
 * address of the frame buffer as a signed integer.  For backwards
 * compatibility, we keep the default location of the frame buffer
 * at under 2GB in the address space.  This restricts VMs to have "only"
 * up to ~2031MB (i.e., up to SVGA_FB_START) of physical memory.
 *
 * For VMs that want more memory than the ~2031MB, we place the SVGA
 * frame buffer at SVGA_FB_START_BIGMEM.  This allows VMs to have up
 * to 3584MB, at least as far as the SVGA frame buffer is concerned
 * (note that there may be other issues that limit the VM memory
 * size).  PCI devices use high memory addresses, so we have to put
 * SVGA_FB_START_BIGMEM low enough so that it doesn't overlap with any
 * of these devices.  Placing SVGA_FB_START_BIGMEM at 0xE0000000
 * should leave plenty of room for the PCI devices.
 *
 * NOTE: All of that is only true for the 0710 chipset.  As of the 0405
 * chipset, the framebuffer start is determined solely based on the value
 * the guest BIOS or OS programs into the PCI base address registers.
 */
#define SVGA_FB_LEGACY_START            0x7EFC0000
#define SVGA_FB_LEGACY_START_BIGMEM     0xE0000000

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree/drivers/vmware/svga_reg.h

/*
 * Memory and port addresses and fundamental constants
 */

/*
 * Note-- MAX_WIDTH and MAX_HEIGHT are largely ignored by the code.  This
 * isn't such a bad thing for forward compatibility. --Jeremy.
 */
#define SVGA_MAX_WIDTH                  2360
#define SVGA_MAX_HEIGHT                 1770
#define SVGA_MAX_BITS_PER_PIXEL         32

#define PAGE_SHIFT 12
#define SVGA_FB_MAX_SIZE \
   ((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT *                                    \
       SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT)

#if SVGA_FB_MAX_SIZE > SVGA_VRAM_SIZE
#error "Bad SVGA maximum sizes"
#endif
#define SVGA_MAX_PSEUDOCOLOR_DEPTH      8
#define SVGA_MAX_PSEUDOCOLORS           (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)

#define SVGA_MAGIC         0x900000
#define SVGA_MAKE_ID(ver)  (SVGA_MAGIC << 8 | (ver))

/* Version 2 let the address of the frame buffer be unsigned on Win32 */
#define SVGA_VERSION_2     2
#define SVGA_ID_2          SVGA_MAKE_ID(SVGA_VERSION_2)

/* Version 1 has new registers starting with SVGA_REG_CAPABILITIES so
   PALETTE_BASE has moved */
#define SVGA_VERSION_1     1
#define SVGA_ID_1          SVGA_MAKE_ID(SVGA_VERSION_1)

/* Version 0 is the initial version */
#define SVGA_VERSION_0     0
#define SVGA_ID_0          SVGA_MAKE_ID(SVGA_VERSION_0)

/* Invalid SVGA_ID_ */
#define SVGA_ID_INVALID    0xFFFFFFFF

/* More backwards compatibility, old location of color map: */
#define SVGA_OLD_PALETTE_BASE    17

/* Base and Offset gets us headed the right way for PCI Base Addr Registers */
#define SVGA_LEGACY_BASE_PORT   0x4560
#define SVGA_INDEX_PORT         0x0
#define SVGA_VALUE_PORT         0x1
#define SVGA_BIOS_PORT          0x2
#define SVGA_NUM_PORTS          0x3

/* This port is deprecated, but retained because of old drivers. */
#define SVGA_LEGACY_ACCEL_PORT  0x3

/* Legal values for the SVGA_REG_CURSOR_ON register in cursor bypass mode */
#define SVGA_CURSOR_ON_HIDE               0x0    /* Must be 0 to maintain backward compatibility */
#define SVGA_CURSOR_ON_SHOW               0x1    /* Must be 1 to maintain backward compatibility */
#define SVGA_CURSOR_ON_REMOVE_FROM_FB     0x2    /* Remove the cursor from the framebuffer because we need to see what's under it */
#define SVGA_CURSOR_ON_RESTORE_TO_FB      0x3    /* Put the cursor back in the framebuffer so the user can see it */

/*
 * Registers
 */

enum {
   SVGA_REG_ID = 0,
   SVGA_REG_ENABLE = 1,
   SVGA_REG_WIDTH = 2,
   SVGA_REG_HEIGHT = 3,
   SVGA_REG_MAX_WIDTH = 4,
   SVGA_REG_MAX_HEIGHT = 5,
   SVGA_REG_DEPTH = 6,
   SVGA_REG_BITS_PER_PIXEL = 7,     /* Current bpp in the guest */
   SVGA_REG_PSEUDOCOLOR = 8,
   SVGA_REG_RED_MASK = 9,
   SVGA_REG_GREEN_MASK = 10,
   SVGA_REG_BLUE_MASK = 11,
   SVGA_REG_BYTES_PER_LINE = 12,
   SVGA_REG_FB_START = 13,
   SVGA_REG_FB_OFFSET = 14,
   SVGA_REG_VRAM_SIZE = 15,
   SVGA_REG_FB_SIZE = 16,

   SVGA_REG_CAPABILITIES = 17,
   SVGA_REG_MEM_START = 18,        /* Memory for command FIFO and bitmaps */
   SVGA_REG_MEM_SIZE = 19,
   SVGA_REG_CONFIG_DONE = 20,      /* Set when memory area configured */
   SVGA_REG_SYNC = 21,             /* Write to force synchronization */
   SVGA_REG_BUSY = 22,             /* Read to check if sync is done */
   SVGA_REG_GUEST_ID = 23,         /* Set guest OS identifier */
   SVGA_REG_CURSOR_ID = 24,        /* ID of cursor */
   SVGA_REG_CURSOR_X = 25,         /* Set cursor X position */
   SVGA_REG_CURSOR_Y = 26,         /* Set cursor Y position */
   SVGA_REG_CURSOR_ON = 27,        /* Turn cursor on/off */
   SVGA_REG_HOST_BITS_PER_PIXEL = 28, /* Current bpp in the host */

   SVGA_REG_TOP = 30,              /* Must be 1 greater than the last register */

   SVGA_PALETTE_BASE = 1024        /* Base of SVGA color map */ 
};


/*
 *  Capabilities
 */

#define SVGA_CAP_NONE               0x0000
#define SVGA_CAP_RECT_FILL          0x0001
#define SVGA_CAP_RECT_COPY          0x0002 //
#define SVGA_CAP_RECT_PAT_FILL      0x0004
#define SVGA_CAP_LEGACY_OFFSCREEN   0x0008
#define SVGA_CAP_RASTER_OP          0x0010
#define SVGA_CAP_CURSOR             0x0020 //
#define SVGA_CAP_CURSOR_BYPASS      0x0040 //
#define SVGA_CAP_CURSOR_BYPASS_2    0x0080 //
#define SVGA_CAP_8BIT_EMULATION     0x0100 //
#define SVGA_CAP_ALPHA_CURSOR       0x0200 //
#define SVGA_CAP_GLYPH              0x0400
#define SVGA_CAP_GLYPH_CLIPPING     0x0800 //
#define SVGA_CAP_OFFSCREEN_1        0x1000
#define SVGA_CAP_ALPHA_BLEND        0x2000


/*
 *  Raster op codes (same encoding as X) used by FIFO drivers.
 */

#define SVGA_ROP_CLEAR          0x00     /* 0 */
#define SVGA_ROP_AND            0x01     /* src AND dst */
#define SVGA_ROP_AND_REVERSE    0x02     /* src AND NOT dst */
#define SVGA_ROP_COPY           0x03     /* src */
#define SVGA_ROP_AND_INVERTED   0x04     /* NOT src AND dst */
#define SVGA_ROP_NOOP           0x05     /* dst */
#define SVGA_ROP_XOR            0x06     /* src XOR dst */
#define SVGA_ROP_OR             0x07     /* src OR dst */
#define SVGA_ROP_NOR            0x08     /* NOT src AND NOT dst */
#define SVGA_ROP_EQUIV          0x09     /* NOT src XOR dst */
#define SVGA_ROP_INVERT         0x0a     /* NOT dst */
#define SVGA_ROP_OR_REVERSE     0x0b     /* src OR NOT dst */
#define SVGA_ROP_COPY_INVERTED  0x0c     /* NOT src */
#define SVGA_ROP_OR_INVERTED    0x0d     /* NOT src OR dst */
#define SVGA_ROP_NAND           0x0e     /* NOT src OR NOT dst */
#define SVGA_ROP_SET            0x0f     /* 1 */
#define SVGA_ROP_UNSUPPORTED    0x10

#define SVGA_NUM_SUPPORTED_ROPS   16
#define SVGA_ROP_ALL            (MASK(SVGA_NUM_SUPPORTED_ROPS))
#define SVGA_IS_VALID_ROP(rop)  (rop >= 0 && rop < SVGA_NUM_SUPPORTED_ROPS)

/*
 *  Ops
 *  For each pixel, the four channels of the image are computed with: 
 *
 *      C = Ca * Fa + Cb * Fb
 *
 *  where C, Ca, Cb are the values of the respective channels and Fa 
 *  and Fb come from the following table: 
 *
 *      BlendOp         Fa                      Fb
 *      ------------------------------------------
 *      Clear           0                       0
 *      Src             1                       0
 *      Dst             0                       1
 *      Over            1                       1-Aa
 *      OverReverse     1-Ab                    1
 *      In              Ab                      0
 *      InReverse       0                       Aa
 *      Out             1-Ab                    0
 *      OutReverse      0                       1-Aa
 *      Atop            Ab                      1-Aa
 *      AtopReverse     1-Ab                    Aa
 *      Xor             1-Ab                    1-Aa
 *      Add             1                       1
 *      Saturate        min(1,(1-Ab)/Aa)        1
 *
 *  Flags
 *  You can use the following flags to achieve additional affects:
 * 
 *      Flag                    Effect
 *      ------------------------------------------
 *      ConstantSourceAlpha     Ca = Ca * Param0
 *      ConstantDestAlpha       Cb = Cb * Param1
 *
 *  Flag effects resolve before the op.  For example
 *  BlendOp == Add && Flags == ConstantSourceAlpha |
 *  ConstantDestAlpha results in:
 *
 *       C = (Ca * Param0) + (Cb * Param1)
 */

#define SVGA_BLENDOP_CLEAR                      0
#define SVGA_BLENDOP_SRC                        1
#define SVGA_BLENDOP_DST                        2
#define SVGA_BLENDOP_OVER                       3
#define SVGA_BLENDOP_OVER_REVERSE               4
#define SVGA_BLENDOP_IN                         5
#define SVGA_BLENDOP_IN_REVERSE                 6
#define SVGA_BLENDOP_OUT                        7
#define SVGA_BLENDOP_OUT_REVERSE                8
#define SVGA_BLENDOP_ATOP                       9 
#define SVGA_BLENDOP_ATOP_REVERSE               10
#define SVGA_BLENDOP_XOR                        11
#define SVGA_BLENDOP_ADD                        12
#define SVGA_BLENDOP_SATURATE                   13

#define SVGA_NUM_BLENDOPS                       14
#define SVGA_IS_VALID_BLENDOP(op)               (op >= 0 && op < SVGA_NUM_BLENDOPS)

#define SVGA_BLENDFLAG_CONSTANT_SOURCE_ALPHA    0x01
#define SVGA_BLENDFLAG_CONSTANT_DEST_ALPHA      0x02
#define SVGA_NUM_BLENDFLAGS                     2
#define SVGA_BLENDFLAG_ALL                      (MASK(SVGA_NUM_BLENDFLAGS))
#define SVGA_IS_VALID_BLENDFLAG(flag)           ((flag & ~SVGA_BLENDFLAG_ALL) == 0)

/*
 *  Memory area offsets (viewed as an array of 32-bit words)
 */

/*
 *  The distance from MIN to MAX must be at least 10K
 */

#define  SVGA_FIFO_MIN        0
#define  SVGA_FIFO_MAX        1
#define  SVGA_FIFO_NEXT_CMD   2
#define  SVGA_FIFO_STOP       3

#define  SVGA_FIFO_USER_DEFINED     4

/*
 *  Drawing object ID's, in the range 0 to SVGA_MAX_ID
 */

#define  SVGA_MAX_ID          499

/*
 *  Macros to compute variable length items (sizes in 32-bit words, except
 *  for SVGA_GLYPH_SCANLINE_SIZE, which is in bytes).
 */

#define SVGA_BITMAP_SIZE(w,h) ((((w)+31) >> 5) * (h))
#define SVGA_BITMAP_SCANLINE_SIZE(w) (( (w)+31 ) >> 5)
#define SVGA_PIXMAP_SIZE(w,h,bpp) ((( ((w)*(bpp))+31 ) >> 5) * (h))
#define SVGA_PIXMAP_SCANLINE_SIZE(w,bpp) (( ((w)*(bpp))+31 ) >> 5)
#define SVGA_GLYPH_SIZE(w,h) ((((((w) + 7) >> 3) * (h)) + 3) >> 2)
#define SVGA_GLYPH_SCANLINE_SIZE(w) (((w) + 7) >> 3)

/*
 * Get the width and height of VRAM in the current mode (for offscreen memory)
 */
#define SVGA_VRAM_WIDTH_HEIGHT(width /* out */, height /* out */) { \
   uint32 pitch = svga->reg[SVGA_REG_BYTES_PER_LINE]; \
   width = (pitch * 8) / ((svga->reg[SVGA_REG_BITS_PER_PIXEL] + 7) & ~7); \
   height = (svga->reg[SVGA_REG_VRAM_SIZE] - \
                    svga->reg[SVGA_REG_FB_OFFSET]) / pitch; \
}

/*
 *  Increment from one scanline to the next of a bitmap or pixmap
 */
#define SVGA_BITMAP_INCREMENT(w) ((( (w)+31 ) >> 5) * sizeof (uint32))
#define SVGA_PIXMAP_INCREMENT(w,bpp) ((( ((w)*(bpp))+31 ) >> 5) * sizeof (uint32))

/*
 *  Transparent color for DRAW_GLYPH_CLIPPED
 */
#define SVGA_COLOR_TRANSPARENT (~0)

/*
 *  Commands in the command FIFO
 */

#define  SVGA_CMD_INVALID_CMD              0
         /* FIFO layout:
            <nothing> (well, undefined) */

#define  SVGA_CMD_UPDATE                   1
         /* FIFO layout:
            X, Y, Width, Height */

#define  SVGA_CMD_RECT_FILL                2
         /* FIFO layout:
            Color, X, Y, Width, Height */

#define  SVGA_CMD_RECT_COPY                3
         /* FIFO layout:
            Source X, Source Y, Dest X, Dest Y, Width, Height */

#define  SVGA_CMD_DEFINE_BITMAP            4
         /* FIFO layout:
            Pixmap ID, Width, Height, <scanlines> */

#define  SVGA_CMD_DEFINE_BITMAP_SCANLINE   5
         /* FIFO layout:
            Pixmap ID, Width, Height, Line #, scanline */

#define  SVGA_CMD_DEFINE_PIXMAP            6
         /* FIFO layout:
            Pixmap ID, Width, Height, Depth, <scanlines> */

#define  SVGA_CMD_DEFINE_PIXMAP_SCANLINE   7
         /* FIFO layout:
            Pixmap ID, Width, Height, Depth, Line #, scanline */

#define  SVGA_CMD_RECT_BITMAP_FILL         8
         /* FIFO layout:
            Bitmap ID, X, Y, Width, Height, Foreground, Background */

#define  SVGA_CMD_RECT_PIXMAP_FILL         9
         /* FIFO layout:
            Pixmap ID, X, Y, Width, Height */

#define  SVGA_CMD_RECT_BITMAP_COPY        10
         /* FIFO layout:
            Bitmap ID, Source X, Source Y, Dest X, Dest Y,
            Width, Height, Foreground, Background */

#define  SVGA_CMD_RECT_PIXMAP_COPY        11
         /* FIFO layout:
            Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width, Height */

#define  SVGA_CMD_FREE_OBJECT             12
         /* FIFO layout:
            Object (pixmap, bitmap, ...) ID */

#define  SVGA_CMD_RECT_ROP_FILL           13
         /* FIFO layout:
            Color, X, Y, Width, Height, ROP */

#define  SVGA_CMD_RECT_ROP_COPY           14
         /* FIFO layout:
            Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */

#define  SVGA_CMD_RECT_ROP_BITMAP_FILL    15
         /* FIFO layout:
            ID, X, Y, Width, Height, Foreground, Background, ROP */

#define  SVGA_CMD_RECT_ROP_PIXMAP_FILL    16
         /* FIFO layout:
            ID, X, Y, Width, Height, ROP */

#define  SVGA_CMD_RECT_ROP_BITMAP_COPY    17
         /* FIFO layout:
            ID, Source X, Source Y,
            Dest X, Dest Y, Width, Height, Foreground, Background, ROP */

#define  SVGA_CMD_RECT_ROP_PIXMAP_COPY    18
         /* FIFO layout:
            ID, Source X, Source Y, Dest X, Dest Y, Width, Height, ROP */

#define SVGA_CMD_DEFINE_CURSOR            19
        /* FIFO layout:
           ID, Hotspot X, Hotspot Y, Width, Height,
           Depth for AND mask, Depth for XOR mask,
           <scanlines for AND mask>, <scanlines for XOR mask> */

#define SVGA_CMD_DISPLAY_CURSOR           20
        /* FIFO layout:
           ID, On/Off (1 or 0) */

#define SVGA_CMD_MOVE_CURSOR              21
        /* FIFO layout:
           X, Y */

#define SVGA_CMD_DEFINE_ALPHA_CURSOR      22
        /* FIFO layout:
           ID, Hotspot X, Hotspot Y, Width, Height,
           <scanlines> */

#define SVGA_CMD_DRAW_GLYPH               23
        /* FIFO layout:
           X, Y, W, H, FGCOLOR, <stencil buffer> */

#define SVGA_CMD_DRAW_GLYPH_CLIPPED       24
        /* FIFO layout:
           X, Y, W, H, FGCOLOR, BGCOLOR, <cliprect>, <stencil buffer>
           Transparent color expands are done by setting BGCOLOR to ~0 */

#define SVGA_CMD_UPDATE_VERBOSE           25
        /* FIFO layout:
           X, Y, Width, Height, Reason */

#define SVGA_CMD_SURFACE_FILL             26
        /* FIFO layout:
           color, dstSurfaceOffset, x, y, w, h, rop */

#define SVGA_CMD_SURFACE_COPY             27
        /* FIFO layout:
           srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
           destX, destY, w, h, rop */

#define SVGA_CMD_SURFACE_ALPHA_BLEND      28
        /* FIFO layout:
           srcSurfaceOffset, dstSurfaceOffset, srcX, srcY,
           destX, destY, w, h, op (SVGA_BLENDOP*), flags (SVGA_BLENDFLAGS*), 
           param1, param2 */

#define SVGA_CMD_MAX                      29

/* SURFACE_ALPHA_BLEND currently has the most (non-data) arguments: 12 */
#define SVGA_CMD_MAX_ARGS                 12


/*
 * A sync request is sent via a non-zero write to the SVGA_REG_SYNC
 * register.  In devel builds, the driver will write a specific value
 * indicating exactly why the sync is necessary
 */
enum 
{
  SVGA_SYNC_INVALIDREASON = 0,     /* Don't ever write a zero */
  SVGA_SYNC_GENERIC = 1,           /* Legacy drivers will always write a 1 */
  SVGA_SYNC_FIFOFULL = 2,          /* Need to drain FIFO for next write */
  SVGA_SYNC_FB_WRITE = 3,          /* About write to shadow frame buffer (generic) */
  SVGA_SYNC_FB_BITBLT = 4,         /* Unaccelerated DrvBitBlt */
  SVGA_SYNC_FB_COPYBITS = 5,       /* Unacclerated DrvCopyBits bits */
  SVGA_SYNC_FB_FILLPATH = 6,       /* Unacclerated DrvFillPath */
  SVGA_SYNC_FB_LINETO = 7,         /* Unacclerated DrvLineTo */
  SVGA_SYNC_FB_PAINT = 8,          /* Unacclerated DrvPaint */
  SVGA_SYNC_FB_STRETCHBLT = 9,     /* Unacclerated DrvStretchBlt */
  SVGA_SYNC_FB_STROKEFILL = 10,    /* Unacclerated DrvStrokeAndFillPath */
  SVGA_SYNC_FB_STROKE = 11,        /* Unacclerated DrvStrokePath */
  SVGA_SYNC_FB_TEXTOUT = 12,       /* Unacclerated DrvTextOut */
  SVGA_SYNC_FB_ALPHABLEND = 13,    /* Unacclerated DrvAlphaBlend */
  SVGA_SYNC_FB_GRADIENT = 14,      /* Unacclerated DrvGradientFill */
  SVGA_SYNC_FB_PLGBLT = 15,        /* Unacclerated DrvPlgBlt */
  SVGA_SYNC_FB_STRETCHROP = 16,    /* Unacclerated DrvStretchBltROP */
  SVGA_SYNC_FB_TRANSPARENT = 17,   /* Unacclerated DrvTransparentBlt */
  SVGA_SYNC_FB_NEWCURSOR = 18,     /* Defined a new cursor */
  SVGA_SYNC_FB_SYNCSURFACE = 19,   /* DrvSynchrnoizeSurface call */
  SVGA_SYNC_FB_NUM_REASONS         /* Total number of reasons */
};

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree86: miscstruct.h

typedef struct _BoxRec 
{                       // Assume this is:
  uint16 x1, y1;        // Top left
  uint16 x2, y2;        // Bottom right
} BoxRec, *pBoxRec;

//////////////////////////////////////////////////////////////////////////////
//  Extracted from xfree/drivers/vmware/vmware.h

typedef struct _VMWareReg
{
  uint32 svga_reg_enable;
  uint32 svga_reg_width;
  uint32 svga_reg_height;
  uint32 svga_reg_bits_per_pixel;

  uint32 svga_reg_cursor_on;
  uint32 svga_reg_cursor_x;
  uint32 svga_reg_cursor_y;
  uint32 svga_reg_cursor_id;

  bool  svga_fifo_enabled;

  uint32 svga_reg_id;
} VMWARERegRec, *VMWARERegPtr;

typedef struct _VMWareVGA
{
  uint32 indexReg;              // Address in I/O space for the index register
  uint32 valueReg;              // Address in I/O space for the value register

  uint32 Capabilities;          // 

  void *FIFO;                   // Base address of the command FIFO
  uint32 FIFOSize;              // Size of FIFO in bytes
  void *FB;                     // Base address of the frame buffer

                                // We set the following mode values
  uint32 FBWidth;               // Screen width
  uint32 FBHeight;              // Screen height
  uint32 FBBitsPerPixel;        // Bits per pixel

  uint32 FBDepth;               //
  uint32 FBPseudoColor;         //
  uint32 FBRedMask;
  uint32 FBGreenMask;
  uint32 FBBlueMask;

  uint32 FBSize;                // Size of the FB in bytes
  uint32 FBOffset;              // Offset 
  uint32 FBBytesPerLine;        // Bytes per line

  VMWARERegRec ModeReg;         // Current mode register values
} VMWareVGA, *pVMWareVGA;

typedef struct _vmwareColors
{
  uint32 red;
  uint32 green;
  uint32 blue;
} vmwareColors, *pvmwareColors;

pVMWareVGA vmwareInitialize(void);
void vmwareTerminate(pVMWareVGA pVMWARE);
void vmwareDrawPoint(pVMWareVGA pVMWARE, uint32 x, uint32 y, uint32 color);
void vmwareClear(pVMWareVGA pVMWARE, uint32 color);
void vmwareLoadPalette(pVMWareVGA pVMWARE, int numColors, int *indeces,
                       vmwareColors *colors);

#ifdef __cplusplus
}
#endif 
#endif // _VMWARE_VGA_H

[-- Attachment #4: README.xfree86 --]
[-- Type: application/octet-stream, Size: 22609 bytes --]


Copyright (C) 1999-2002 VMware, Inc.
All Rights Reserved

The code here may be used/distributed under the terms of the standard
XFree86 license.


	VMware SVGA Device Interface and Programming Model
	--------------------------------------------------


Include Files
-------------

svga_reg.h
    SVGA register definitions, SVGA capabilities, and FIFO command definitions.

svga_limits.h
    Included by svga_reg.h, defines maximum frame buffer and memory region
    sizes.

guest_os.h
    Values for the GUEST_ID register.

vm_basic_types.h
    Common type definitions.

vm_device_version.h
    PCI vendor ID's and related information.


Programming the VMware SVGA Device
----------------------------------

1. Reading/writing a register:

    The SVGA registers are addressed by an index/value pair of 32 bit
    registers in the IO address space.
    
    The 0710 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA) has
    its index and value ports hardcoded at:
    
    	index: SVGA_LEGACY_BASE_PORT + 4 * SVGA_INDEX_PORT
    	value: SVGA_LEGACY_BASE_PORT + 4 * SVGA_VALUE_PORT
    
    The 0405 VMware SVGA chipset (PCI device ID PCI_DEVICE_ID_VMWARE_SVGA2)
    determines its index and value ports as a function of the first base
    address register in its PCI configuration space as:

    	index: <Base Address Register 0> + SVGA_INDEX_PORT
    	value: <Base Address Register 0> + SVGA_VALUE_PORT

    To read a register:
	Set the index port to the index of the register, using a dword OUT
	Do a dword IN from the value port

    To write a register:
	Set the index port to the index of the register, using a dword OUT
	Do a dword OUT to the value port

    Example, setting the width to 1024:

	mov	eax, SVGA_REG_WIDTH
	mov	edx, <SVGA Address Port>
	out	dx, eax
    	mov	eax, 1024
	mov	edx, <SVGA Value Port>
	out	dx, eax

2. Initialization
    Check the version number
     loop:
      Write into SVGA_REG_ID the maximum SVGA_ID_* the driver supports.
      Read from SVGA_REG_ID.
       Check if it is the value you wrote.
	If yes, VMware SVGA device supports it
	If no, decrement SVGA_ID_* and goto loop
     This algorithm converges.

    Map the frame buffer and the command FIFO
	Read SVGA_REG_FB_START, SVGA_REG_FB_SIZE, SVGA_REG_MEM_START,
	SVGA_REG_MEM_SIZE.
	Map the frame buffer (FB) and the FIFO memory (MEM)

    Get the device capabilities and frame buffer dimensions
	Read SVGA_REG_CAPABILITIES, SVGA_REG_MAX_WIDTH, SVGA_REG_MAX_HEIGHT,
	and SVGA_REG_HOST_BITS_PER_PIXEL / SVGA_REG_BITS_PER_PIXEL.

	Note: The capabilities can and do change without the PCI device ID
	changing or the SVGA_REG_ID changing.  A driver should always check
	the capabilities register when loading before expecting any
	capabilities-determined feature to be available.  See below for a list
	of capabilities as of this writing.

	Note: If SVGA_CAP_8BIT_EMULATION is not set, then it is possible that
	SVGA_REG_HOST_BITS_PER_PIXEL does not exist and
	SVGA_REG_BITS_PER_PIXEL should be read instead.

    Report the Guest Operating System
    	Write SVGA_REG_GUEST_ID with the appropriate value from <guest_os.h>.
	While not required in any way, this is useful information for the
	virtual machine to have available for reporting and sanity checking
	purposes.

    SetMode
	Set SVGA_REG_WIDTH, SVGA_REG_HEIGHT, SVGA_REG_BITS_PER_PIXEL
	Read SVGA_REG_FB_OFFSET
	(SVGA_REG_FB_OFFSET is the offset from SVGA_REG_FB_START of the
	 visible portion of the frame buffer)
	Read SVGA_REG_BYTES_PER_LINE, SVGA_REG_DEPTH, SVGA_REG_PSEUDOCOLOR,
	SVGA_REG_RED_MASK, SVGA_REG_GREEN_MASK, SVGA_REG_BLUE_MASK

	Note: SVGA_REG_BITS_PER_PIXEL is readonly if
	SVGA_CAP_8BIT_EMULATION is not set in the capabilities register.  Even
	if it is set, values other than 8 and SVGA_REG_HOST_BITS_PER_PIXEL
	will be ignored.

    Enable SVGA
	Set SVGA_REG_ENABLE to 1
	(to disable SVGA, set SVGA_REG_ENABLE to 0.  Setting SVGA_REG_ENABLE
	to 0 also enables VGA.)

    Initialize the command FIFO
	The FIFO is exclusively dword (32-bit) aligned.  The first four
	dwords define the portion of the MEM area that is used for the
	command FIFO.  These are values are all in byte offsets from the
	start of the MEM area.

	A minimum sized FIFO would have these values:
	    mem[SVGA_FIFO_MIN] = 16;
	    mem[SVGA_FIFO_MAX] = 16 + (10 * 1024);
	    mem[SVGA_FIFO_NEXT_CMD] = 16;
	    mem[SVGA_FIFO_STOP] = 16;

	Set SVGA_REG_CONFIG_DONE to 1 after these values have been set.
	
	Note: Setting SVGA_REG_CONFIG_DONE to 0 will stop the device from
	reading the FIFO until it is reinitialized and SVGA_REG_CONFIG_DONE is
	set to 1 again.

3. SVGA command FIFO protocol
    The FIFO is empty when SVGA_FIFO_NEXT_CMD == SVGA_FIFO_STOP.  The
    driver writes commands to the FIFO starting at the offset specified
    by SVGA_FIFO_NEXT_CMD, and then increments SVGA_FIFO_NEXT_CMD.

    The FIFO is full when SVGA_FIFO_NEXT_CMD is one word before SVGA_FIFO_STOP.

    When the FIFO becomes full, the FIFO should be sync'd

    To sync the FIFO
	Write SVGA_REG_SYNC
	Read SVGA_REG_BUSY
	Wait for the value in SVGA_REG_BUSY to be 0

    The FIFO should be sync'd before the driver touches the frame buffer, to
    guarantee that any outstanding BLT's are completed.

4. Cursor
    When SVGA_CAP_CURSOR is set, hardware cursor support is available.  In
    practice, SVGA_CAP_CURSOR will only be set when SVGA_CAP_CURSOR_BYPASS is
    also set and drivers supporting a hardware cursor should only worry about
    SVGA_CAP_CURSOR_BYPASS and only use the FIFO to define the cursor.  See
    below for more information.

5. Pseudocolor
    When the read-only register SVGA_REG_PSEUDOCOLOR is 1, the device is in a
    colormapped mode whose index width and color width are both SVGA_REG_DEPTH.
    Thus far, 8 is the only depth at which pseudocolor is ever used.

    In pseudocolor, the colormap is programmed by writing to the SVGA palette
    registers.  These start at SVGA_PALETTE_BASE and are interpreted as
    follows:

    	SVGA_PALETTE_BASE + 3*n		- The nth red component
    	SVGA_PALETTE_BASE + 3*n + 1	- The nth green component
    	SVGA_PALETTE_BASE + 3*n + 2	- The nth blue component
    
    And n ranges from 0 to ((1<<SVGA_REG_DEPTH) - 1).
    

Drawing to the Screen
---------------------

After initialization, the driver can write directly to the frame buffer.  The
updated frame buffer is not displayed immediately, but only when an update
command is sent.  The update command (SVGA_CMD_UPDATE) defines the rectangle
in the frame buffer that has been modified by the driver, and causes that
rectangle to be updated on the screen.

A complete driver can be developed this way.  For increased performance,
additional commands are available to accelerate common operations.  The two
most useful are SVGA_CMD_RECT_FILL and SVGA_CMD_RECT_COPY.

After issuing an accelerated command, the FIFO should be sync'd, as described
above, before writing to the frame buffer.

Addendum on 7/11/2000
---------------------

SVGA_REG_FB_OFFSET and SVGA_REG_BYTES_PER_LINE may change after SVGA_REG_WIDTH
or SVGA_REG_HEIGHT is set.  Also the VGA registers must be written to after
setting SVGA_REG_ENABLE to 0 to change the display to a VGA mode.

Addendum on 11/29/2001
---------------------

Actually, after changing any of SVGA_REG_WIDTH, SVGA_REG_HEIGHT, and
SVGA_REG_BITS_PER_PIXEL, all of the registers listed in the 'SetMode'
initialization section above should be reread.  Additionally, when changing
modes, it can be convenient to set SVGA_REG_ENABLE to 0, change
SVGA_REG_WIDTH, SVGA_REG_HEIGHT, and SVGA_REG_BITS_PER_PIXEL (if available),
and then set SVGA_REG_ENABLE to 1 again.


Capabilities
------------

The capabilities register (SVGA_REG_CAPABILITIES) is an array of bits that
indicates the capabilities of the SVGA emulation.  A driver should check
SVGA_REG_CAPABILITIES every time it loads before relying on any feature that
is only optionally available.

Some of the capabilities determine which FIFO commands are available.  This
table shows which capability indicates support for which command.

    FIFO Command			Capability
    ------------			----------

    SVGA_CMD_RECT_FILL			SVGA_CAP_RECT_FILL
    SVGA_CMD_RECT_COPY			SVGA_CAP_RECT_COPY
    SVGA_CMD_DEFINE_BITMAP		SVGA_CAP_OFFSCREEN
    SVGA_CMD_DEFINE_BITMAP_SCANLINE	SVGA_CAP_OFFSCREEN
    SVGA_CMD_DEFINE_PIXMAP		SVGA_CAP_OFFSCREEN
    SVGA_CMD_DEFINE_PIXMAP_SCANLINE	SVGA_CAP_OFFSCREEN
    SVGA_CMD_RECT_BITMAP_FILL		SVGA_CAP_RECT_PAT_FILL
    SVGA_CMD_RECT_PIXMAP_FILL		SVGA_CAP_RECT_PAT_FILL
    SVGA_CMD_RECT_BITMAP_COPY		SVGA_CAP_RECT_PAT_FILL
    SVGA_CMD_RECT_PIXMAP_COPY		SVGA_CAP_RECT_PAT_FILL
    SVGA_CMD_FREE_OBJECT		SVGA_CAP_OFFSCREEN
    SVGA_CMD_RECT_ROP_FILL		SVGA_CAP_RECT_FILL +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_RECT_ROP_COPY		SVGA_CAP_RECT_COPY +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_RECT_ROP_BITMAP_FILL	SVGA_CAP_RECT_PAT_FILL +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_RECT_ROP_PIXMAP_FILL	SVGA_CAP_RECT_PAT_FILL +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_RECT_ROP_BITMAP_COPY	SVGA_CAP_RECT_PAT_FILL +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_RECT_ROP_PIXMAP_COPY	SVGA_CAP_RECT_PAT_FILL +
					    SVGA_CAP_RASTER_OP
    SVGA_CMD_DEFINE_CURSOR		SVGA_CAP_CURSOR
    SVGA_CMD_DISPLAY_CURSOR		SVGA_CAP_CURSOR
    SVGA_CMD_MOVE_CURSOR		SVGA_CAP_CURSOR
    SVGA_CMD_DEFINE_ALPHA_CURSOR	SVGA_CAP_ALPHA_CURSOR
    SVGA_CMD_DRAW_GLYPH                 SVGA_CAP_GLYPH
    SVGA_CMD_DRAW_GLYPH_CLIPPED         SVGA_CAP_GLYPH_CLIPPING

Note:  SVGA_CMD_DISPLAY_CURSOR and SVGA_CMD_MOVE_CURSOR should not be used.
Drivers wishing hardware cursor support should use cursor bypass (see below).

Other capabilities indicate other functionality as described below:

    SVGA_CAP_CURSOR_BYPASS
	The hardware cursor can be drawn via SVGA Registers (without requiring
	the FIFO be synchronized and will be drawn potentially before any
	outstanding unprocessed FIFO commands).

	Note:  Without SVGA_CAP_CURSOR_BYPASS_2, cursors drawn this way still
	appear in the guest's framebuffer and need to be turned off before any
	save under / overlapping drawing and turned back on after.  This can
	cause very noticeable cursor flicker.

    SVGA_CAP_CURSOR_BYPASS_2
    	Instead of turning the cursor off and back on around any overlapping
	drawing, the driver can write SVGA_CURSOR_ON_REMOVE_FROM_FB and
	SVGA_CURSOR_ON_RESTORE_TO_FB to SVGA_REG_CURSOR_ON.  In almost all
	cases these are NOPs and the cursor will be remain visible without
	appearing in the guest framebuffer.  In 'direct graphics' modes like
	Linux host fullscreen local displays, however, the cursor will still
	be drawn in the framebuffer, still flicker, and be drawn incorrectly
	if a driver does not use SVGA_CURSOR_ON_REMOVE_FROM_FB / RESTORE_TO_FB.

    SVGA_CAP_8BIT_EMULATION
    	SVGA_REG_BITS_PER_PIXEL is writable and can be set to either 8 or
	SVGA_REG_HOST_BITS_PER_PIXEL.  Otherwise the only SVGA modes available
	inside a virtual machine must match the host's bits per pixel.
	
	Note: Some versions which lack SVGA_CAP_8BIT_EMULATION also lack the
	SVGA_REG_HOST_BITS_PER_PIXEL and a driver should assume
	SVGA_REG_BITS_PER_PIXEL is both read-only and initialized to the only
	available value if SVGA_CAP_8BIT_EMULATION is not set.
        
    SVGA_CAP_OFFSCREEN_1
        SVGA_CMD_RECT_FILL, SVGA_CMD_RECT_COPY, SVGA_CMD_RECT_ROP_FILL,
        SVGA_CMD_RECT_ROP_COPY can operate with a source or destination (or
        both) in offscreen memory. 
        
        Usable offscreen memory is a rectangle located below the last scanline
        of the visible memory:
        x1 = 0
        y1 = (SVGA_REG_FB_SIZE + SVGA_REG_BYTES_PER_LINE - 1) / 
             SVGA_REG_BYTES_PER_LINE
        x2 = SVGA_REG_BYTES_PER_LINE / SVGA_REG_DEPTH
        y2 = SVGA_REG_VRAM_SIZE / SVGA_REG_BYTES_PER_LINE


Cursor Handling
---------------

Starting with GSX Server Beta 3 (after 11/15/2000), hardware cursor support
was added.  Actually, both a hardware cursor via the FIFO (SVGA_CAP_CURSOR)
and a hardware cursor via the SVGA registers (SVGA_CAP_CURSOR_BYPASS) were
added.  SVGA_CAP_CURSOR was never available without SVGA_CAP_CURSOR_BYPASS and
the FIFO hardware cursor should never be used and may be removed without
warning in the future.

Cursor bypass is programmed using the two FIFO commands SVGA_CMD_DEFINE_CURSOR
and SVGA_CMD_DEFINE_ALPHA_CURSOR in conjunction with the SVGA registers
SVGA_REG_CURSOR_ID, SVGA_REG_CURSOR_X, SVGA_REG_CURSOR_Y, and
SVGA_REG_CURSOR_ON.

A driver defines an AND/XOR hardware cursor using SVGA_CMD_DEFINE_CURSOR to
assign an ID and establish the AND and XOR masks with the hardware.  A driver
uses SVGA_CMD_DEFINE_ALPHA_CURSOR to define a 32 bit mask whose top 8 bits are
used to blend the cursor image with the pixels it covers.  Alpha cursor
support is only available when SVGA_CAP_ALPHA_CURSOR is set.

Once a cursor is defined, a driver can draw it to the screen at any time by
writing the SVGA_REG_CURSOR_ID register with the ID used when the cursor was
defined, writing SVGA_REG_CURSOR_X and SVGA_REG_CURSOR_Y with the location of
the cursor, and SVGA_CURSOR_ON_SHOW to SVGA_REG_CURSOR_ON.  The drawing occurs
when SVGA_REG_CURSOR_ON is written.

Writing SVGA_CURSOR_ON_HIDE to SVGA_REG_CURSOR_ON will turn the cursor off and
make it vanish from the display and, if present, from the framebuffer.
SVGA_CURSOR_ON_REMOVE_FROM_FB will ensure the cursor is not in the
framebuffer, but will only turn it off if there's no other way to remove it.
SVGA_CURSOR_ON_RESTORE_TO_FB is the complement to
SVGA_CURSOR_ON_REMOVE_FROM_FB.  Whenever possible, the device will not put the
cursor in the framebuffer and Remove From / Restore To will be NOPs.

Note: The cursor must be out of the frame buffer before the driver (or any
agent in the virtual machine) touches an overlapping portion of the frame
buffer, because it is actually drawn into the frame buffer memory in the
case of direct graphics mode (e.g. full screen mode on Linux).  The cursor
does not have to be touched before issuing an accelerated command via the
command FIFO, this case is handled by the SVGA device.

Note: If SVGA_CAP_CURSOR_BYPASS2 is not present, the driver must use
SVGA_CURSOR_ON_HIDE and SVGA_CURSOR_ON_HIDE to be certain the cursor is out of
the framebuffer.


Driver Version Numbers
----------------------

The SVGA drivers use the following convention for their version numbers:

Version 10.0 - The first version that uses the FIFO
Version 10.1 - The version that uses the hardware cursor emulation via the FIFO
Version 10.2 - The version that uses the cursor that bypasses the FIFO
Version 10.3 - The version that can also support the 0405 chipset
Version 10.4 - The version that knows about SVGA_CAP_CURSOR_BYPASS2
Version 10.5 - [Never released or well defined]
Version 10.6 - The version that knows about SVGA_CAP_8BIT_EMULATION
Version 10.7 - The version that knows about SVGA_CAP_ALPHA_CURSOR
Version 10.8 - The version that knows about SVGA_CAP_GLYPH
Version 10.9 - The version that knows about SVGA_CAP_OFFSCREEN_1

Note that this is merely the convention used by SVGA drivers written and
maintained by VMware, Inc. and describes the capabilities of the driver, not
the virtual hardware.  An SVGA driver can only use the intersection of the
functionality it supports and the functionality available in the virtual SVGA
hardware.


Frequently Asked Questions
--------------------------

1.  My driver doesn't display anything, what's going on?

First check if you are issuing an SVGA_CMD_UPDATE after drawing to
the screen.  Another check you can do is to run your driver in full
screen mode on a Linux host.  In this case you are drawing directly
on the frame buffer, so what you draw to the screen will be immediately
visible.  If nothing is visible in this case, then most likely your
driver hasn't mapped the frame buffer correctly.

A discrepancy between what you get in full screen mode and what you
get in window mode indicates that you have a missing or incorrect
update command.


2.  What's the difference between bitmaps and pixmaps?

Pixmaps have the same depth as the screen, while bitmaps have depth one.
When a bitmap is drawn, the command also takes two colors, foreground and
background.  The set bits in the bitmap are replaced with the foreground
color, and the unset bits are replaced with the background color.

Pixmaps, on the other hand, can be directly copied to the screen.


3.  What's the significance of the ROP in the commands SVGA_CMD_RECT_ROP_FILL,
SVGA_CMD_RECT_ROP_BITMAP_COPY, etc. ?

The ROP in the ...ROP... commands is a raster operation.  It has the same
significance (and encoding) as it does in X.  The ROP value SVGA_ROP_COPY
means the source is copied to the destination, which makes these commands the
same as their non-ROP counterparts.  The most commonly used raster operation
other than copy is probably SVGA_ROP_XOR, which combines the source and
destination using exclusive-or.


4.  Tell me more about bitmaps and pixmaps.  For example, the macro
SVGA_CMD_DEFINE_BITMAP has a field <scanlines>.  What should this be
set to?  Likewise with SVGA_CMD_DEFINE_PIXMAP.  And when should the
SCANLINE macros be used?

OK, I'll use pixmaps as an example.  First you have to define the pixmap:

#define  SVGA_CMD_DEFINE_PIXMAP		6
	 /* FIFO layout:
	    Pixmap ID, Width, Height, Depth, <scanlines> */

The ID is something you choose, which you subsequently use to refer to
this pixmap.  It must be an integer between 0 and SVGA_MAX_ID.

The width and height and depth are the dimensions of the pixmap.  For now,
the depth of the pixmap has to match the depth of the screen.

The scanlines are the pixels that make up the pixmap, arranged one row
at a time.  Each row is required to be 32-bit aligned.  The macros
SVGA_PIXMAP_SCANLINE_SIZE and SVGA_PIXMAP_SIZE give the size of a
single scanline, and the size of the entire pixmap, respectively, in
32-bit words.

The second step is to use it:

#define  SVGA_CMD_RECT_PIXMAP_FILL	9
	 /* FIFO layout:
	    Pixmap ID, X, Y, Width, Height */

The ID here is the one you chose when defining the pixmap.  X, Y,
Width, and Height define a rectangle on the screen that is to be filled
with the pixmap.  The pixmap is screen aligned, which means that the
coordinates in the pixmap are defined by the screen coordinates modulo
the pixmap dimensions.

If you want a different alignment between the screen and the pixmap,
then you can use this command, which allows the pixmap coordinates to
be defined:

#define  SVGA_CMD_RECT_PIXMAP_COPY	11
	 /* FIFO layout:
	    Pixmap ID, Source X, Source Y, Dest X, Dest Y, Width,
	    Height */

The Source X and Source Y are pixmap coordinates, and the Dest X and
Dest Y are screen coordinates.


5.  OK, now it works briefly, then stops displaying anything.  Also,
my log file is filled with lines like:
  Unknown Command 0xff in SVGA command FIFO
What's happening?

The most common problem at this point is that the FIFO gets out
of sync.  This can happen if the amount of data in the FIFO doesn't
match what the VMware SVGA device expects.  To track this down, try
to isolate the particular command which causes the problem.

Another way this can happen is if the wraparound in the FIFO isn't
done correctly.  Here is some example code for writing to the FIFO
(mem is an array of 32-bit integers that points to the FIFO memory
region):

while (TRUE) {
    fifo_min = mem[SVGA_FIFO_MIN] / 4;
    fifo_max = mem[SVGA_FIFO_MAX] / 4;
    fifo_next = mem[SVGA_FIFO_NEXT_CMD] / 4;
    fifo_stop = mem[SVGA_FIFO_STOP] / 4;

    tmp_next = fifo_next+1;
    if (tmp_next == fifo_max)
	tmp_next = fifo_min;    // Wraparound

    if (tmp_next == fifo_stop) {
	sync_fifo();		// FIFO full
	continue;		// retry
    }

    mem[fifo_next] = item;
    mem[SVGA_FIFO_NEXT_CMD] = tmp_next * 4;
    break;
}

This isn't the most efficient code, but it should work.  It's important
to do the increment with wraparound before the FIFO full check, and to
check FIFO full before updating the next command pointer.


6. My driver tries to switch modes and either nothing happens or the
display becomes completely garbled.  What's going on?

When you change modes, make very sure you reread all of the registers listed
above under SetMode.  Getting the pitch (SVGA_REG_BYTES_PER_LINE) incorrect
will cause a heavily garbled display.  Also, if you change
SVGA_REG_BITS_PER_PIXEL, make certain that SVGA_CAP_8BIT_EMULATION is present
in the SVGA_REG_CAPABILITIES register.  Also, even with 8 bit emulation, the
driver must still use either 8 bpp or SVGA_REG_HOST_BITS_PER_PIXEL bpp,
nothing else.


7. Why does my driver's hardware cursor work when my virtual machine is in
window mode, but draw/erase incorrectly or in garbled locations in fullscreen
mode?

You need to make sure you use SVGA_CURSOR_ON_REMOVE_FROM_FB and
SVGA_CURSOR_ON_RESTORE_TO_FB _every_ time your driver or the virtual machine
touches a region of the framebuffer that overlaps the cursor.  If you forget
to remove it then it can show up when doing save-under operations or get mixed
in with other drawing.  If you forget to restore it then can disappear.  You
also need to make sure SVGA_CAP_CURSOR_BYPASS2 is available, or else you will
have to use SVGA_CURSOR_ON_SHOW and SVGA_CURSOR_ON_HIDE (which will flicker,
even in window mode), or else a software cursor.  Newer version of the virtual
SVGA hardware will never put the hardware cursor in the framebuffer while in
window mode, so everything will appear to work correctly there.


8. Why do my accelerated glyphs look funny?  OR  Why does the fifo complain
about invalid commands when I draw accelerated glyphs?

The bitmap data passed to SVGA_CMD_DRAW_GLYPH_* must not have any per-scanline
alignment.  If there are any remaining bits left in the last byte of a scanline,
the first bits of the next scanline should use them.  

The bitmap data as a whole must be 4 byte aligned.

$XFree86: xc/programs/Xserver/hw/xfree86/drivers/vmware/README,v 1.2 2001/04/05 21:09:37 dawes Exp $

[-- Attachment #5: dd_vmware_ecos.c --]
[-- Type: application/octet-stream, Size: 15324 bytes --]

/*===========================================================================
//
//        dd_vmware.c
//
//        PW display driver for eCos under VMWARE
//
//===========================================================================
//===========================================================================
// This file is part of PW graphic library.
// Copyright (C) 2006 Peter Dennett
//
// PW is free software; you can redistribute it and/or modify it under
// the terms of the GNU General Public License as published by the Free
// Software Foundation; either version 2 or (at your option) any later version.
//
// PW is distributed in the hope that it will be useful, but WITHOUT ANY
// WARRANTY; without even the implied warranty of MERCHANTABILITY or
// FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
// for more details.
//
// You should have received a copy of the GNU General Public License along
// with PW; if not, write to the Free Software Foundation, Inc.,
// 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
//
// As a special exception, if other files instantiate templates or use macros
// or inline functions from this file, or you compile this file and link it
// with other works to produce a work based on this file, this file does not
// by itself cause the resulting work to be covered by the GNU General Public
// License. However the source code for this file must still be made available
// in accordance with section (3) of the GNU General Public License.
//
// This exception does not invalidate any other reasons why a work based on
// this file might be covered by the GNU General Public License.
//===========================================================================
//===========================================================================
//
//  Author(s): Peter Dennett
//
//=========================================================================== */

#include "../../vmware/vmware-vga.c"

#include <cyg/error/codes.h>  /* Cyg_ErrNo, ENOENT */
#include <cyg/io/io.h>        /* cyg_io_handle_t */
#include <sys/select.h>       /* select() functions */
#include <fcntl.h>            /* open() */
#include <unistd.h>           /* read() */
#include <stdlib.h>           /* rand() */
#include <sys/time.h>

#include <i_pwin.h>

#define VMW_BLACK 0
#define VMW_WHITE 255

static pVMWareVGA pVMWARE=0; // Display info

static Pw_DD      dd;
static Pw_LLD     lld;
static Pw_Display dpy;

// -------------------------------------------------------------------------- 

static void 
draw_point(Pw_GC* gc, Pw_Coord x, Pw_Coord y)
{
int color = (Pw_GCGetColor(gc) == pw_black_pixel) ? VMW_BLACK : VMW_WHITE;

  vmwareDrawPoint(pVMWARE, x, y, color);

  return;
} 

static void
draw_points(Pw_GC* gc, Pw_Coord x, Pw_Coord y, Pw_Byte bits)
{
Pw_uInt w;
Pw_Byte mask = 0x80;
uint32 color = (Pw_GCGetColor(gc) == pw_black_pixel) ? VMW_BLACK : VMW_WHITE;

  for (w = 0; w < 8; w++)
  {    
    if ((bits & mask) != 0)
      vmwareDrawPoint(pVMWARE, (uint32)x, (uint32)y, color);

    x++;
    mask >>= 1;
  }

  return;
}

static void 
draw_hor_line(Pw_GC* gc, Pw_Coord x1, Pw_Coord y1, Pw_Coord x2)
{
uint32 color = (Pw_GCGetColor(gc) == pw_black_pixel) ? VMW_BLACK : VMW_WHITE;

  while (x1 <= x2)
    vmwareDrawPoint(pVMWARE, (uint32)x1++, (uint32)y1, color);

  return;
}

static void 
draw_ver_line(Pw_GC* gc, Pw_Coord x1, Pw_Coord y1, Pw_Coord y2)
{
uint32 color = (Pw_GCGetColor(gc) == pw_black_pixel) ? VMW_BLACK : VMW_WHITE;

 while (y1 <= y2)
    vmwareDrawPoint(pVMWARE, (uint32)x1, (uint32)y1++, color);

  return;
}

static void 
fill_rect(Pw_GC* gc, Pw_Coord x, Pw_Coord y, Pw_Coord w, Pw_Coord h)
{
Pw_Coord y2, x1, x2;

  x1 = x;
  x2 = x1 + w - 1;
  y2 = y + h - 1;

  while (y <= y2)
    draw_hor_line(gc, x1, y++, x2);

  return;
}

static void 
display_refresh(Pw_Display* dpy, Pw_Rectangle* area)
{
  vmwareSendSVGACmdUpdateFullScreen(pVMWARE);

  return;
}

static Pw_Int
display_get_xinput_value(Pw_Display* dpy, Pw_uInt num)
{
  return 0;
}

// -------------------------------------------------------------------------- 

extern Pw_Bool Pw_Init(Pw_Display* dpy);

bool
pw_dd_init(void)
{
int i;
#define N_COLORS 2
vmwareColors colors[N_COLORS];
int indeces[N_COLORS];

  if ((pVMWARE = vmwareInitialize()) == (pVMWareVGA)0)
  {
    diag_printf("VMWARE-VGA failed initialization\n");
    return FALSE;
  }

  i = 0;
  indeces[i] = VMW_BLACK;
  colors[i].red = 0;
  colors[i].green = 0;
  colors[i].blue = 0;

  i++;
  indeces[i] = VMW_WHITE;
  colors[i].red = 255;
  colors[i].green = 255;
  colors[i].blue = 255;

  vmwareLoadPalette(pVMWARE, i+1, indeces, colors);

  vmwareClear(pVMWARE, VMW_WHITE);

  lld.draw_point      = draw_point;
  lld.draw_points     = draw_points;
  lld.draw_hor_line   = draw_hor_line;
  lld.draw_ver_line   = draw_ver_line;
  lld.fill_rect       = fill_rect;
  dd.lld              = &lld;
  dd.display_refresh  = display_refresh;
  dd.get_xinput_value = display_get_xinput_value;
  dd.init_components  = Pw_Init;

  IPw_InitInternals();

  IPw_DisplayOpen((Pw_Coord)pVMWARE->FBWidth-1, (Pw_Coord)pVMWARE->FBHeight-1, &dd, &dpy);

  if (!IPw_InitComponents(&dpy))
  {
    IPw_DisplayClose(&dpy);
    return false;
  }

  IPw_DisplayRefresh(&dpy);

  return true;
}

//-----------------------------------------------------------------------------
// Keyboard definitions

#define KBDATAPORT  0x0060    // data I/O port
#define KBCMDPORT   0x0064    // command port (write)
#define KBSTATPORT  0x0064    // status port  (read)

// Scan codes

#define LSHIFT    0x2a
#define RSHIFT    0x36
#define CTRL      0x1d
#define ALT       0x38
#define CAPS      0x3a
#define NUMS      0x45

#define BREAK     0x80

// Bits for KBFlags

#define KBNormal  0x0000
#define KBShift   0x0001
#define KBCtrl    0x0002
#define KBAlt     0x0004
#define KBIndex   0x0007  // mask for the above

#define KBExtend  0x0010
#define KBAck     0x0020
#define KBResend  0x0040
#define KBShiftL  (0x0080 | KBShift)
#define KBShiftR  (0x0100 | KBShift)
#define KBCtrlL   (0x0200 | KBCtrl)
#define KBCtrlR   (0x0400 | KBCtrl)
#define KBAltL    (0x0800 | KBAlt)
#define KBAltR    (0x1000 | KBAlt)
#define KBCapsLock  0x2000
#define KBNumLock 0x4000

static  CYG_BYTE  KBScanTable[128][4] =
{
//  Normal    Shift   Control   Alt
// 0x00
{ 0xFF,   0xFF,   0xFF,   0xFF,   },
{ 0x1b,   0x1b,   0x1b,   0xFF, },
{ '1',    '!',    0xFF,   0xFF, },
{ '2',    '"',    0xFF,   0xFF, },
{ '3',    '#',    0xFF,   0xFF, },
{ '4',    '$',    0xFF,   0xFF, },
{ '5',    '%',    0xFF,   0xFF, },
{ '6',    '^',    0xFF,   0xFF, },
{ '7',    '&',    0xFF,   0xFF, },
{ '8',    '*',    0xFF,   0xFF, },
{ '9',    '(',    0xFF,   0xFF, },
{ '0',    ')',    0xFF,   0xFF, },
{ '-',    '_',    0xFF,   0xFF, },
{ '=',    '+',    0xFF,   0xFF, },
{ '\b',   '\b',   0xFF,   0xFF, },
{ '\t',   '\t',   0xFF,   0xFF, },
// 0x10
{ 'q',    'Q',    0x11,   0xFF, },
{ 'w',    'W',    0x17,   0xFF, },
{ 'e',    'E',    0x05,   0xFF, },
{ 'r',    'R',    0x12,   0xFF, },
{ 't',    'T',    0x14,   0xFF, },
{ 'y',    'Y',    0x19,   0xFF, },
{ 'u',    'U',    0x15,   0xFF, },
{ 'i',    'I',    0x09,   0xFF, },
{ 'o',    'O',    0x0F,   0xFF, },
{ 'p',    'P',    0x10,   0xFF, },
{ '[',    '{',    0x1b,   0xFF, },
{ ']',    '}',    0x1d,   0xFF, },
{ '\r',   '\r',   '\n',   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 'a',    'A',    0x01,   0xFF, },
{ 's',    'S',    0x13,   0xFF, },
// 0x20
{ 'd',    'D',    0x04,   0xFF, },
{ 'f',    'F',    0x06,   0xFF, },
{ 'g',    'G',    0x07,   0xFF, },
{ 'h',    'H',    0x08,   0xFF, },
{ 'j',    'J',    0x0a,   0xFF, },
{ 'k',    'K',    0x0b,   0xFF, },
{ 'l',    'L',    0x0c,   0xFF, },
{ ';',    ':',    0xFF,   0xFF, },
{ 0x27,   '@',    0xFF,   0xFF, },
{ '#',    '~',    0xFF,   0xFF, },
{ '`',    '~',    0xFF,   0xFF, },
{ '\\',   '|',    0x1C,   0xFF, },
{ 'z',    'Z',    0x1A,   0xFF, },
{ 'x',    'X',    0x18,   0xFF, },
{ 'c',    'C',    0x03,   0xFF, },
{ 'v',    'V',    0x16,   0xFF, },
// 0x30
{ 'b',    'B',    0x02,   0xFF, },
{ 'n',    'N',    0x0E,   0xFF, },
{ 'm',    'M',    0x0D,   0xFF, },
{ ',',    '<',    0xFF,   0xFF, },
{ '.',    '>',    0xFF,   0xFF, },
{ '/',    '?',    0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ '*',    0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ ' ',    ' ',    ' ',    ' ',  },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xF1,   0xE1,   0xFF,   0xFF, },
{ 0xF2,   0xE2,   0xFF,   0xFF, },
{ 0xF3,   0xE3,   0xFF,   0xFF, },
{ 0xF4,   0xE4,   0xFF,   0xFF, },
{ 0xF5,   0xE5,   0xFF,   0xFF, },
// 0x40
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ '7',    0xFF,   0xFF,   0xFF, },

{ '8',    0x15,   0x15,   0x15, },
{ '9',    0x10,   0x10,   0x10, },
{ '-',    0xFF,   0xFF,   0xFF, },
{ '4',    0xFF,   0xFF,   0xFF, },
{ '5',    0xFF,   0xFF,   0xFF, },
{ '6',    0xFF,   0xFF,   0xFF, },
{ '+',    0xFF,   0xFF,   0xFF, },
{ '1',    0xFF,   0xFF,   0xFF, },
// 0x50
{ '2',    0x04,   0x04,   0x04, },
{ '3',    0x0e,   0x0e,   0x0e, },
{ '0',    0xFF,   0xFF,   0xFF, },
{ '.',    0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
// 0x60
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
// 0x70
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
{ 0xFF,   0xFF,   0xFF,   0xFF, },
  
};

static int KBIndexTab[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };

static  int KBFlags = 0;

//-----------------------------------------------------------------------------

static CYG_BYTE KeyboardAscii(CYG_BYTE  scancode)
{
    CYG_BYTE ascii = 0xFF;

    // Start by handling all shift/ctl keys:

    switch( scancode )
    {
    case 0x53:  // delete
        if (KBFlags & KBCtrl && KBFlags & KBAlt)
        {
          ; // CYGACC_CALL_IF_RESET();
        }
        break;

    case 0xe0:
        KBFlags |= KBExtend;
        return 0xFF;

    case 0xfa:
        KBFlags |= KBAck;
        return 0xFF;

    case 0xfe:
        KBFlags |= KBResend;
        return 0xFF;

    case LSHIFT:
        KBFlags |= KBShiftL;
        return 0xFF;

    case LSHIFT | BREAK:
        KBFlags &= ~KBShiftL;
        return 0xFF;

    case RSHIFT:
        KBFlags |= KBShiftR;
        return 0xFF;

    case RSHIFT | BREAK:
        KBFlags &= ~KBShiftR;
        return 0xFF;

    case CTRL:
        if( KBFlags & KBExtend )
        {
            KBFlags |= KBCtrlR;
            KBFlags &= ~KBExtend;
        }
        else  KBFlags |= KBCtrlL;
        return 0xFF;

    case CTRL | BREAK:
        if( KBFlags & KBExtend )
        {
            KBFlags &= ~KBCtrlR;
            KBFlags &= ~KBExtend;
        }
        else  KBFlags &= ~KBCtrlL;
        return 0xFF;


    case ALT:
        if( KBFlags & KBExtend )
        {
            KBFlags |= KBAltR;
            KBFlags &= ~KBExtend;
        }
        else  KBFlags |= KBAltL;
        return 0xFF;

    case ALT | BREAK:
        if( KBFlags & KBExtend )
        {
            KBFlags &= ~KBAltR;
            KBFlags &= ~KBExtend;
        }
        else  KBFlags &= ~KBAltL;
        return 0xFF;

    case CAPS:
        KBFlags ^= KBCapsLock;
    case CAPS | BREAK:
        return 0xFF;

    case NUMS:
        KBFlags ^= KBNumLock;
    case NUMS | BREAK:
        return 0xFF;
    }

    // Clear Extend flag if set
    KBFlags &= ~KBExtend;

    // Ignore all other BREAK codes
    if( scancode & 0x80 ) return 0xFF;

    // Here the scancode is for something we can turn
    // into an ASCII value

    ascii = KBScanTable[scancode & 0x7F][KBIndexTab[KBFlags & KBIndex]];

    return ascii;

} /* KeyboardAscii */

//-----------------------------------------------------------------------------

static Pw_Bool
ReadKeySym (Pw_uInt *keysym)
{
CYG_BYTE stat, code;
CYG_BYTE c;
        
  HAL_READ_UINT8(KBSTATPORT, stat);

  if ((stat & 0x01) == 0)
    return FALSE;

  HAL_READ_UINT8(KBDATAPORT, code);

  // Translate to ASCII

  c = KeyboardAscii(code);
		
  if (c != 0xFF)
  {
    *keysym = c;
    return TRUE;
  }

  return FALSE;
}

static Pw_Bool 
TranslateKeyCode(Pw_uInt keysym, Pw_uInt* keycode)
{
  switch (keysym)
  {
     case '1': // 0xFF52:
       *keycode = PW_UP_KEY_CODE;
       return TRUE;

     case '2': // 0xFF54:
       *keycode = PW_DOWN_KEY_CODE;
       return TRUE;

     case '3': // 0xFF51:
       *keycode = PW_LEFT_KEY_CODE;
       return TRUE;

     case '4': // 0xFF53:
       *keycode = PW_RIGHT_KEY_CODE;
       return TRUE;

     case '5': // 0xFF56:
       *keycode = PW_NEXT_KEY_CODE;
       return TRUE;

     case '6': // 0xFF55:
       *keycode = PW_PREV_KEY_CODE;
       return TRUE;    

     case '7': // 0xFF0D:
       *keycode = PW_YES_KEY_CODE;
       return TRUE;

     default:
       return FALSE;
  }
} 

void
pw_dd_main_loop(void)
{
struct timeval selTimeout;
int  key_sym;
int  key_pressed = -1;

  selTimeout.tv_sec = 0;
  selTimeout.tv_usec = 100000;

  while(1)
  {
    if (select(0, NULL, NULL, NULL, &selTimeout) == 0)
    {
      if (ReadKeySym(&key_sym))
        if (TranslateKeyCode(key_sym, &key_pressed))
          IPw_EventKeyPressed(&dpy, key_pressed);

      IPw_TimeoutProcess(&dpy, 100);

      selTimeout.tv_sec = 0;
      selTimeout.tv_usec = 100000;
    }
  }
}

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: Graphics routines for VMWare
  2006-10-13 15:01 Graphics routines for VMWare Peter Dennett
@ 2006-10-18 19:25 ` Andrew Lunn
  2006-10-18 22:29   ` Peter Dennett
  0 siblings, 1 reply; 3+ messages in thread
From: Andrew Lunn @ 2006-10-18 19:25 UTC (permalink / raw)
  To: Peter Dennett; +Cc: ecos-devel

On Fri, Oct 13, 2006 at 10:03:10AM -0500, Peter Dennett wrote:
> 
> For those interested in developing eCos applications under VMWare 
> attached are a couple of files that support access to the SVGA 
> adapter emulated by VMWare. ?This has been tested under Workstation 
> 5.5. 

Hi Peter

Unfortunately, this is GPL code. So we cannot incorporate it into the
eCos repository. The GPL license would spread from this code into the
rest of eCos and then into the application, so requiring that people
who develop applications using this code would have to make there
application sources available under the terms of the GPL. Most people
don't want to do this, they have the intellectual property of there
product in those sources.

        Andrew

^ permalink raw reply	[flat|nested] 3+ messages in thread

* RE: Graphics routines for VMWare
  2006-10-18 19:25 ` Andrew Lunn
@ 2006-10-18 22:29   ` Peter Dennett
  0 siblings, 0 replies; 3+ messages in thread
From: Peter Dennett @ 2006-10-18 22:29 UTC (permalink / raw)
  To: 'Andrew Lunn'; +Cc: ecos-devel

Andrew:

Thanks for the reminder but I was quite aware of this.   My main interest in
this code is during the development phase of a project.  One can test and
debug a graphical interface prior to having the actual target hardware.  The
distributed product can be based on non-GPL code working with the target
hardware. As such the GPL is not so onerous since the code will not be
distributed.

If there is enough interest in a contribution I can provide an assignable
version.  The .c code is largely a clean room development.  I would need to
groom the .h file to sanitize it.

Others have suggested it in the past but I will again.  It would be useful
to have a separate GPL eCos repository (or branch) for such bits and pieces.


I will also shortly be contributing a patch to if_lancepci.c to support
multicasting under VMWare.

Regards,

Peter Dennett       Office: 281 334 3800
www.padsoft.com       Cell: 713 899 6100
 
> -----Original Message-----
> From: ecos-devel-owner@ecos.sourceware.org [mailto:ecos-devel-
> owner@ecos.sourceware.org] On Behalf Of Andrew Lunn
> Sent: Wednesday, October 18, 2006 2:25 PM
> To: Peter Dennett
> Cc: ecos-devel@ecos.sourceware.org
> Subject: Re: Graphics routines for VMWare
> 
> On Fri, Oct 13, 2006 at 10:03:10AM -0500, Peter Dennett wrote:
> >
> > For those interested in developing eCos applications under VMWare
> > attached are a couple of files that support access to the SVGA
> > adapter emulated by VMWare. ?This has been tested under Workstation
> > 5.5.
> 
> Hi Peter
> 
> Unfortunately, this is GPL code. So we cannot incorporate it into the
> eCos repository. The GPL license would spread from this code into the
> rest of eCos and then into the application, so requiring that people
> who develop applications using this code would have to make there
> application sources available under the terms of the GPL. Most people
> don't want to do this, they have the intellectual property of there
> product in those sources.
> 
>         Andrew
> 



^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2006-10-18 22:29 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2006-10-13 15:01 Graphics routines for VMWare Peter Dennett
2006-10-18 19:25 ` Andrew Lunn
2006-10-18 22:29   ` Peter Dennett

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).