Added Eric Petit's VMware graphics driver - thanks!

Made the following changes from the version I got from Eric:
* made BppForSpace() in DriverInterface.h inline to remove some warnings
* renamed driver source files to lower case.
* removed Be Inc. copyright from kernel driver as I couldn't see anything coming
  from Be Inc. there - correct me if I was wrong, Eric.
* Minor other changes like added missing header guards.
* The README provided in the main directory is only included in the accelerant
  directory.


git-svn-id: file:///srv/svn/repos/haiku/haiku/trunk@19793 a95241bf-73f2-0310-859d-f6bbb57e9c96
This commit is contained in:
Axel Dörfler
2007-01-14 14:16:06 +00:00
parent e57d2e1b09
commit 00d65a521d
23 changed files with 2641 additions and 0 deletions
@@ -0,0 +1,119 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <[email protected]>
*/
#ifndef DRIVERINTERFACE_H
#define DRIVERINTERFACE_H
#include <GraphicsDefs.h>
#include <Accelerant.h>
#include <Drivers.h>
#include <PCI.h>
#include <OS.h>
#include "vm_device_version.h"
#include "svga_reg.h"
#define MAX_SAMPLE_DEVICE_NAME_LENGTH 32
#define CURSOR_ID 1
/*--------------------------------------------------------------------*/
/* Benaphores */
typedef struct {
sem_id sem;
int32 ben;
} Benaphore;
#define INIT_BEN(x) x.sem = create_sem(0, "VMware "#x); x.ben = 0;
#define ACQUIRE_BEN(x) if((atomic_add(&(x.ben), 1)) >= 1) acquire_sem(x.sem);
#define RELEASE_BEN(x) if((atomic_add(&(x.ben), -1)) > 1) release_sem(x.sem);
#define DELETE_BEN(x) delete_sem(x.sem);
/*--------------------------------------------------------------------*/
/* Utils */
#define ROUND_TO_PAGE_SIZE(x) (((x)+(B_PAGE_SIZE)-1)&~((B_PAGE_SIZE)-1))
static inline int
BppForSpace(int space)
{
switch (space) {
case B_RGB32:
return 32;
case B_RGB24:
return 24;
case B_RGB16:
return 16;
case B_RGB15:
return 15;
case B_CMAP8:
return 8;
}
return 0;
}
/*--------------------------------------------------------------------*/
/* Request codes for ioctl() */
enum {
VMWARE_GET_PRIVATE_DATA = B_DEVICE_OP_CODES_END + 1,
VMWARE_FIFO_START,
VMWARE_FIFO_STOP,
VMWARE_FIFO_SYNC,
VMWARE_SET_MODE,
VMWARE_SHOW_CURSOR,
VMWARE_MOVE_CURSOR,
};
/*--------------------------------------------------------------------*/
/* Structure shared between the kernel driver and the accelerant */
typedef struct {
/* Device info and capabilities */
uint16 vendorId;
uint16 deviceId;
uint8 revision;
uint32 maxWidth;
uint32 maxHeight;
void *fbDma;
uint32 fbSize;
void *fifoDma;
uint32 fifoSize;
uint32 fifoMin;
uint32 capabilities;
uint32 fifoCapabilities;
uint32 fifoFlags;
/* For registers access */
uint16 indexPort;
uint16 valuePort;
/* Mapped areas */
area_id fbArea;
void *fb;
area_id fifoArea;
void *fifo;
/* This changes when we switch to another mode */
uint32 fbOffset;
uint32 bytesPerRow;
/* Current display mode */
display_mode dm;
Benaphore engineLock;
Benaphore fifoLock;
uint32 fifoNext;
} SharedInfo;
#endif
+518
View File
@@ -0,0 +1,518 @@
/*
* Copyright 1998-2001, VMware, Inc.
* Distributed under the terms of the MIT License.
*
*/
/*
* svga_reg.h --
*
* SVGA hardware definitions
*/
#ifndef _SVGA_REG_H_
#define _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 SVGA_MAX_DEPTH 24
#define SVGA_FB_MAX_SIZE \
((((SVGA_MAX_WIDTH * SVGA_MAX_HEIGHT * \
SVGA_MAX_BITS_PER_PIXEL / 8) >> PAGE_SHIFT) + 1) << PAGE_SHIFT)
#define SVGA_MAX_PSEUDOCOLOR_DEPTH 8
#define SVGA_MAX_PSEUDOCOLORS (1 << SVGA_MAX_PSEUDOCOLOR_DEPTH)
#define SVGA_NUM_PALETTE_REGS (3 * SVGA_MAX_PSEUDOCOLORS)
#define SVGA_MAGIC 0x900000UL
#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,
/* ID 0 implementation only had the above registers, then the palette */
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_SCRATCH_SIZE = 29, /* Number of scratch registers */
SVGA_REG_MEM_REGS = 30, /* Number of FIFO registers */
SVGA_REG_NUM_DISPLAYS = 31, /* Number of guest displays */
SVGA_REG_PITCHLOCK = 32, /* Fixed pitch for all modes */
SVGA_REG_TOP = 33, /* Must be 1 more than the last register */
SVGA_PALETTE_BASE = 1024, /* Base of SVGA color map */
/* Next 768 (== 256*3) registers exist for colormap */
SVGA_SCRATCH_BASE = SVGA_PALETTE_BASE + SVGA_NUM_PALETTE_REGS
/* Base of scratch registers */
/* Next reg[SVGA_REG_SCRATCH_SIZE] registers exist for scratch usage:
First 4 are reserved for VESA BIOS Extension; any remaining are for
the use of the current SVGA driver. */
};
/*
* Capabilities
*/
#define SVGA_CAP_NONE 0x00000
#define SVGA_CAP_RECT_FILL 0x00001
#define SVGA_CAP_RECT_COPY 0x00002
#define SVGA_CAP_RECT_PAT_FILL 0x00004
#define SVGA_CAP_LEGACY_OFFSCREEN 0x00008
#define SVGA_CAP_RASTER_OP 0x00010
#define SVGA_CAP_CURSOR 0x00020
#define SVGA_CAP_CURSOR_BYPASS 0x00040
#define SVGA_CAP_CURSOR_BYPASS_2 0x00080
#define SVGA_CAP_8BIT_EMULATION 0x00100
#define SVGA_CAP_ALPHA_CURSOR 0x00200
#define SVGA_CAP_GLYPH 0x00400
#define SVGA_CAP_GLYPH_CLIPPING 0x00800
#define SVGA_CAP_OFFSCREEN_1 0x01000
#define SVGA_CAP_ALPHA_BLEND 0x02000
#define SVGA_CAP_3D 0x04000
#define SVGA_CAP_EXTENDED_FIFO 0x08000
#define SVGA_CAP_MULTIMON 0x10000
#define SVGA_CAP_PITCHLOCK 0x20000
/*
* 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 < 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)
/*
* FIFO offsets (viewed as an array of 32-bit words)
*/
enum {
/*
* The original defined FIFO offsets
*/
SVGA_FIFO_MIN = 0,
SVGA_FIFO_MAX, /* The distance from MIN to MAX must be at least 10K */
SVGA_FIFO_NEXT_CMD,
SVGA_FIFO_STOP,
/*
* Additional offsets added as of SVGA_CAP_EXTENDED_FIFO
*/
SVGA_FIFO_CAPABILITIES = 4,
SVGA_FIFO_FLAGS,
SVGA_FIFO_FENCE,
SVGA_FIFO_3D_HWVERSION, /* Check SVGA3dHardwareVersion in svga3d_reg.h */
SVGA_FIFO_PITCHLOCK,
/*
* Always keep this last. It's not an offset with semantic value, but
* rather a convenient way to produce the value of fifo[SVGA_FIFO_NUM_REGS]
*/
SVGA_FIFO_NUM_REGS
};
/*
* FIFO Capabilities
*
* Fence -- Fence register and command are supported
* Accel Front -- Front buffer only commands are supported
* Pitch Lock -- Pitch lock register is supported
*/
#define SVGA_FIFO_CAP_NONE 0
#define SVGA_FIFO_CAP_FENCE (1<<0)
#define SVGA_FIFO_CAP_ACCELFRONT (1<<1)
#define SVGA_FIFO_CAP_PITCHLOCK (1<<2)
/*
* FIFO Flags
*
* Accel Front -- Driver should use front buffer only commands
*/
#define SVGA_FIFO_FLAG_NONE 0
#define SVGA_FIFO_FLAG_ACCELFRONT (1<<0)
/*
* 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)
/*
* 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_FRONT_ROP_FILL 29
/* FIFO layout:
Color, X, Y, Width, Height, ROP */
#define SVGA_CMD_FENCE 30
/* FIFO layout:
Fence value */
#define SVGA_CMD_MAX 31
#define SVGA_CMD_MAX_ARGS 64
/*
* Location and size of SVGA frame buffer and the FIFO.
*/
#define SVGA_VRAM_MAX_SIZE (16 * 1024 * 1024)
#define SVGA_VRAM_SIZE_WS (16 * 1024 * 1024) // 16 MB
#define SVGA_MEM_SIZE_WS (2 * 1024 * 1024) // 2 MB
#define SVGA_VRAM_SIZE_SERVER (4 * 1024 * 1024) // 4 MB
#define SVGA_MEM_SIZE_SERVER (256 * 1024) // 256 KB
#if /* defined(VMX86_WGS) || */ defined(VMX86_SERVER)
#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_SERVER
#define SVGA_MEM_SIZE SVGA_MEM_SIZE_SERVER
#else
#define SVGA_VRAM_SIZE SVGA_VRAM_SIZE_WS
#define SVGA_MEM_SIZE SVGA_MEM_SIZE_WS
#endif
/*
* 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
#endif
@@ -0,0 +1,14 @@
/*
* Copyright 1998-2001, VMware, Inc.
* Distributed under the terms of the MIT License.
*
*/
#ifndef VM_DEVICE_VERSION_H
#define VM_DEVICE_VERSION_H
#define PCI_VENDOR_ID_VMWARE 0x15AD
#define PCI_DEVICE_ID_VMWARE_SVGA2 0x0405
#define PCI_DEVICE_ID_VMWARE_SVGA 0x0710
#endif /* VM_DEVICE_VERSION_H */
+1
View File
@@ -12,5 +12,6 @@ SubInclude HAIKU_TOP src add-ons accelerants tdfx ;
SubInclude HAIKU_TOP src add-ons accelerants skeleton ;
SubInclude HAIKU_TOP src add-ons accelerants vesa ;
SubInclude HAIKU_TOP src add-ons accelerants via ;
SubInclude HAIKU_TOP src add-ons accelerants vmware ;
SubIncludeGPL HAIKU_TOP src add-ons accelerants atimach64 ;
@@ -0,0 +1,69 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <[email protected]>
*/
#include "GlobalData.h"
void
SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count)
{
int i;
blit_params * b;
for (i = 0; i < count; i++) {
b = &list[i];
#if 0
TRACE("BLIT %dx%d, %dx%d->%dx%d\n", b->width + 1, b->height + 1,
b->src_left, b->src_top, b->dest_left, b->dest_top);
#endif
FifoBeginWrite();
FifoWrite(SVGA_CMD_RECT_COPY);
FifoWrite(b->src_left);
FifoWrite(b->src_top);
FifoWrite(b->dest_left);
FifoWrite(b->dest_top);
FifoWrite(b->width + 1);
FifoWrite(b->height + 1);
FifoEndWrite();
}
}
void
FILL_RECTANGLE(engine_token *et, uint32 colorIndex,
fill_rect_params *list, uint32 count)
{
int i;
fill_rect_params * f;
for (i = 0; i < count; i++) {
f = &list[i];
#if 0
TRACE("FILL %lX, %dx%d->%dx%d\n", colorIndex,
f->left, f->top, f->right, f->bottom);
#endif
/* TODO */
}
}
void
INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count)
{
/* TODO */
}
void
FILL_SPAN(engine_token * et, uint32 colorIndex, uint16 * list, uint32 count)
{
/* TODO */
}
+82
View File
@@ -0,0 +1,82 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
status_t
SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x,
uint16 hot_y, uint8 * andMask, uint8 * xorMask)
{
int i, shift;
uint32 * alphaCursor;
TRACE("SET_CURSOR_SHAPE (%d, %d, %d, %d)\n", width, height, hot_x, hot_y);
/* Sanity check */
if (hot_x >= width || hot_y >= height)
return B_ERROR;
/* Build ARGB image */
alphaCursor = calloc(1, height * width * sizeof(uint32));
shift = 7;
for (i = 0; i < height * width; i++) {
if (!((*andMask >> shift) & 1)) {
/* Opaque */
alphaCursor[i] |= 0xFF000000;
if (!((*xorMask >> shift) & 1))
/* White */
alphaCursor[i] |= 0x00FFFFFF;
}
if (--shift < 0) {
shift = 7;
andMask++;
xorMask++;
}
}
/* Give it to VMware */
FifoBeginWrite();
FifoWrite(SVGA_CMD_DEFINE_ALPHA_CURSOR);
FifoWrite(CURSOR_ID);
FifoWrite(hot_x);
FifoWrite(hot_y);
FifoWrite(width);
FifoWrite(height);
for (i = 0; i < height * width; i++)
FifoWrite(alphaCursor[i]);
FifoEndWrite();
free(alphaCursor);
return B_OK;
}
void
MOVE_CURSOR(uint16 x, uint16 y)
{
uint16 pos[2];
//TRACE("MOVE_CURSOR (%d, %d)\n", x, y);
pos[0] = x;
pos[1] = y;
ioctl(gFd, VMWARE_MOVE_CURSOR, pos, sizeof(pos));
}
void
SHOW_CURSOR(bool isVisible)
{
TRACE("SHOW_CURSOR (%d)\n", isVisible);
ioctl(gFd, VMWARE_SHOW_CURSOR, &isVisible, sizeof(bool));
}
@@ -0,0 +1,66 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
static engine_token vmwareEngineToken = {1, B_2D_ACCELERATION, NULL};
uint32
ACCELERANT_ENGINE_COUNT()
{
return 1;
}
status_t
ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token * st,
engine_token ** et)
{
ACQUIRE_BEN(gSi->engineLock);
if (st)
SYNC_TO_TOKEN(st);
*et = &vmwareEngineToken;
return B_OK;
}
status_t
RELEASE_ENGINE(engine_token * et, sync_token * st)
{
if (st)
GET_SYNC_TOKEN(et, st);
RELEASE_BEN(gSi->engineLock);
return B_OK;
}
void
WAIT_ENGINE_IDLE()
{
FifoSync();
}
status_t
GET_SYNC_TOKEN(engine_token * et, sync_token * st)
{
st->engine_id = et->engine_id;
st->counter = 0;
return B_OK;
}
status_t
SYNC_TO_TOKEN(sync_token * st)
{
WAIT_ENGINE_IDLE();
return B_OK;
}
+140
View File
@@ -0,0 +1,140 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
/*--------------------------------------------------------------------*/
/* UpdateThread: we explicitely need to tell VMware what and when
* something should be refreshed from the frame buffer. Since the
* app_server doesn't tell us what it's doing, we simply force a full
* screen update every 1/50 second */
static int32
UpdateThread(void *data)
{
bigtime_t begin, end, wait;
while (!gUpdateThreadDie) {
begin = system_time();
FifoUpdateFullscreen();
end = system_time();
/* 50 Hz refresh */
wait = 20000 - (end - begin);
if (wait > 0)
snooze(wait);
}
return B_OK;
}
static void
FifoPrintCapabilities(int c)
{
TRACE("fifo capabilities:\n");
if (c & SVGA_FIFO_CAP_FENCE) TRACE("FENCE\n");
if (c & SVGA_FIFO_CAP_ACCELFRONT) TRACE("ACCELFRONT\n");
if (c & SVGA_FIFO_CAP_PITCHLOCK) TRACE("PITCHLOCK\n");
}
void
FifoInit()
{
uint32 *fifo = gSi->fifo;
/* Stop update thread, if any */
if (gUpdateThread > B_OK) {
status_t exitValue;
gUpdateThreadDie = 1;
wait_for_thread(gUpdateThread, &exitValue);
}
gSi->fifoCapabilities = 0;
gSi->fifoFlags = 0;
if (gSi->capabilities & SVGA_CAP_EXTENDED_FIFO) {
gSi->fifoCapabilities = fifo[SVGA_FIFO_CAPABILITIES];
gSi->fifoFlags = fifo[SVGA_FIFO_FLAGS];
FifoPrintCapabilities(gSi->fifoCapabilities);
}
fifo[SVGA_FIFO_MIN] = gSi->fifoMin * 4;
fifo[SVGA_FIFO_MAX] = gSi->fifoSize;
fifo[SVGA_FIFO_NEXT_CMD] = fifo[SVGA_FIFO_MIN];
fifo[SVGA_FIFO_STOP] = fifo[SVGA_FIFO_MIN];
gSi->fifoNext = fifo[SVGA_FIFO_NEXT_CMD];
/* Launch a new update thread */
gUpdateThreadDie = 0;
gUpdateThread = spawn_thread(UpdateThread, "VMware",
B_REAL_TIME_DISPLAY_PRIORITY, NULL);
resume_thread(gUpdateThread);
TRACE("init fifo: %ld -> %ld\n",
fifo[SVGA_FIFO_MIN], fifo[SVGA_FIFO_MAX]);
}
void
FifoSync()
{
ioctl(gFd, VMWARE_FIFO_SYNC, NULL, 0);
}
void
FifoBeginWrite()
{
ACQUIRE_BEN(gSi->fifoLock);
}
void
FifoWrite(uint32 value)
{
uint32 *fifo = gSi->fifo;
uint32 fifoCapacity = fifo[SVGA_FIFO_MAX] - fifo[SVGA_FIFO_MIN];
/* If the fifo is full, sync it */
if (fifo[SVGA_FIFO_STOP] == fifo[SVGA_FIFO_NEXT_CMD] + 4 ||
fifo[SVGA_FIFO_STOP] + fifoCapacity == fifo[SVGA_FIFO_NEXT_CMD] + 4)
FifoSync();
fifo[gSi->fifoNext / 4] = value;
gSi->fifoNext = (gSi->fifoNext + 4) % fifoCapacity;
}
void
FifoEndWrite()
{
uint32 *fifo = gSi->fifo;
fifo[SVGA_FIFO_NEXT_CMD] = gSi->fifoNext;
RELEASE_BEN(gSi->fifoLock);
}
void
FifoUpdateFullscreen()
{
FifoBeginWrite();
FifoWrite(SVGA_CMD_UPDATE);
FifoWrite(0);
FifoWrite(0);
FifoWrite(gSi->dm.virtual_width);
FifoWrite(gSi->dm.virtual_height);
FifoEndWrite();
}
@@ -0,0 +1,79 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
void *
get_accelerant_hook(uint32 feature, void *data)
{
switch (feature) {
#define HOOK(x) case B_##x: return (void *)x
#define ZERO(x) case B_##x: return (void *)0
/* initialization */
HOOK(INIT_ACCELERANT);
HOOK(CLONE_ACCELERANT);
HOOK(ACCELERANT_CLONE_INFO_SIZE);
HOOK(GET_ACCELERANT_CLONE_INFO);
HOOK(UNINIT_ACCELERANT);
//HOOK(GET_ACCELERANT_DEVICE_INFO);
HOOK(ACCELERANT_RETRACE_SEMAPHORE);
/* mode configuration */
HOOK(ACCELERANT_MODE_COUNT);
HOOK(GET_MODE_LIST);
HOOK(PROPOSE_DISPLAY_MODE);
HOOK(SET_DISPLAY_MODE);
HOOK(GET_DISPLAY_MODE);
HOOK(GET_FRAME_BUFFER_CONFIG);
HOOK(GET_PIXEL_CLOCK_LIMITS);
ZERO(MOVE_DISPLAY);
HOOK(SET_INDEXED_COLORS);
ZERO(GET_TIMING_CONSTRAINTS);
/* Power Managment (SetDisplayMode.c) */
HOOK(DPMS_CAPABILITIES);
HOOK(DPMS_MODE);
HOOK(SET_DPMS_MODE);
/* Cursor managment (Cursor.c) */
#if 0
if (gSi->capabilities & SVGA_CAP_ALPHA_CURSOR) {
HOOK(SET_CURSOR_SHAPE);
HOOK(MOVE_CURSOR);
HOOK(SHOW_CURSOR);
}
#endif
/* synchronization */
HOOK(ACCELERANT_ENGINE_COUNT);
HOOK(ACQUIRE_ENGINE);
HOOK(RELEASE_ENGINE);
HOOK(WAIT_ENGINE_IDLE);
HOOK(GET_SYNC_TOKEN);
HOOK(SYNC_TO_TOKEN);
/* 2D acceleration (Acceleration.c) */
if (gSi->capabilities & SVGA_CAP_RECT_COPY)
HOOK(SCREEN_TO_SCREEN_BLIT);
ZERO(FILL_RECTANGLE);
ZERO(INVERT_RECTANGLE);
ZERO(FILL_SPAN);
ZERO(SCREEN_TO_SCREEN_TRANSPARENT_BLIT);
ZERO(SCREEN_TO_SCREEN_SCALED_FILTERED_BLIT);
#undef HOOK
#undef ZERO
}
return 0;
}
@@ -0,0 +1,57 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
status_t
GET_DISPLAY_MODE(display_mode *currentMode)
{
TRACE("GET_DISPLAY_MODE\n");
*currentMode = gSi->dm;
return B_OK;
}
status_t
GET_FRAME_BUFFER_CONFIG(frame_buffer_config *afb)
{
TRACE("GET_FRAME_BUFFER_CONFIG\n");
afb->frame_buffer = gSi->fb + gSi->fbOffset;
afb->frame_buffer_dma = gSi->fbDma + gSi->fbOffset;
afb->bytes_per_row = gSi->bytesPerRow;
TRACE("fb: %p, fb_dma: %p, row: %d bytes\n", afb->frame_buffer,
afb->frame_buffer_dma, afb->bytes_per_row);
return B_OK;
}
status_t
GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high)
{
TRACE("GET_PIXEL_CLOCK_LIMITS\n");
/* ? */
*low = 1;
*high = 0xFFFFFFFF;
return B_OK;
}
sem_id
ACCELERANT_RETRACE_SEMAPHORE()
{
return B_ERROR;
}
@@ -0,0 +1,18 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
int gFd;
SharedInfo * gSi;
area_id gSharedArea;
int gAccelerantIsClone;
thread_id gUpdateThread = B_ERROR;
volatile int gUpdateThreadDie;
@@ -0,0 +1,37 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#ifndef GLOBAL_DATA_H
#define GLOBAL_DATA_H
#include <support/Debug.h>
#undef TRACE
#define TRACE(a...) _sPrintf("VMware: " ##a)
#include "DriverInterface.h"
#include "generic.h"
/* Global variables */
extern int gFd;
extern SharedInfo *gSi;
extern area_id gSharedArea;
extern int gAccelerantIsClone;
extern thread_id gUpdateThread;
extern volatile int gUpdateThreadDie;
/* Fifo.c */
void FifoInit();
void FifoSync();
void FifoBeginWrite();
void FifoWrite(uint32 value);
void FifoEndWrite();
void FifoUpdateFullscreen();
#endif // GLOBAL_DATA_H
@@ -0,0 +1,111 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "string.h"
#include "unistd.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "fcntl.h"
#include <sys/ioctl.h>
#include "GlobalData.h"
/* Initialization code shared between primary and cloned accelerants */
static
status_t InitCommon(int fd)
{
status_t ret;
/* Memorize the file descriptor */
gFd = fd;
/* Contact driver and get a pointer to the registers and shared data */
if ((ret = ioctl(fd, VMWARE_GET_PRIVATE_DATA, &gSharedArea,
sizeof(area_id))) != B_OK) {
TRACE("VMWARE_GET_PRIVATE_DATA failed (%d\n", ret);
return ret;
}
/* Clone the shared area for our use */
if ((gSharedArea = clone_area("VMware shared", (void **)&gSi,
B_ANY_ADDRESS, B_READ_AREA|B_WRITE_AREA, gSharedArea)) < 0) {
TRACE("could not clone shared area (%d)\n", gSharedArea);
return gSharedArea;
}
return B_OK;
}
static void
UninitCommon()
{
delete_area(gSharedArea);
}
status_t
INIT_ACCELERANT(int fd)
{
status_t ret;
TRACE("INIT_ACCELERANT (%d)\n", fd);
gAccelerantIsClone = 0;
/* Common initialization for the primary accelerant and clones */
if ((ret = InitCommon(fd)) == B_OK) {
/* Init semaphores */
INIT_BEN(gSi->engineLock);
INIT_BEN(gSi->fifoLock);
}
TRACE("INIT_ACCELERANT: %d\n", ret);
return ret;
}
ssize_t
ACCELERANT_CLONE_INFO_SIZE()
{
return MAX_SAMPLE_DEVICE_NAME_LENGTH;
}
void
GET_ACCELERANT_CLONE_INFO(void *data)
{
/* TODO */
}
status_t
CLONE_ACCELERANT(void *data)
{
/* TODO */
return B_ERROR;
}
void
UNINIT_ACCELERANT()
{
UninitCommon();
if (gAccelerantIsClone)
close(gFd);
else if (gUpdateThread > B_OK) {
status_t exitValue;
gUpdateThreadDie = 1;
wait_for_thread(gUpdateThread, &exitValue);
}
ioctl(gFd, VMWARE_FIFO_STOP, NULL, 0);
}
+20
View File
@@ -0,0 +1,20 @@
SubDir HAIKU_TOP src add-ons accelerants vmware ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders [ FDirName graphics vmware ] ;
UsePrivateHeaders graphics ;
Addon vmware.accelerant : accelerants :
Acceleration.c
Cursor.c
EngineManagment.c
Fifo.c
GetAccelerantHook.c
GetModeInfo.c
GlobalData.c
InitAccelerant.c
ProposeDisplayMode.c
SetDisplayMode.c
: false
;
@@ -0,0 +1,77 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
#include <string.h>
#define MODE_FLAGS (B_8_BIT_DAC|B_PARALLEL_ACCESS)
#define MODE_COUNT (sizeof(kModeList) / sizeof(display_mode))
static const display_mode kModeList[] =
{ { { 19660, 640, 672, 744, 776, 480, 490, 494, 505, 0 }, B_RGB32_LITTLE, 640, 480, 0, 0, MODE_FLAGS }, /* 640x480@50Hz */
{ { 25250, 800, 832, 920, 952, 500, 511, 515, 526, 0 }, B_RGB32_LITTLE, 800, 500, 0, 0, MODE_FLAGS }, /* 800x500@50Hz */
{ { 30970, 800, 832, 944, 976, 600, 613, 618, 631, 0 }, B_RGB32_LITTLE, 800, 600, 0, 0, MODE_FLAGS }, /* 800x600@50Hz */
{ { 41980, 1024, 1056, 1208, 1240, 640, 653, 659, 673, 0 }, B_RGB32_LITTLE, 1024, 640, 0, 0, MODE_FLAGS }, /* 1024x640@50Hz */
{ { 51850, 1024, 1056, 1248, 1280, 768, 784, 791, 807, 0 }, B_RGB32_LITTLE, 1024, 768, 0, 0, MODE_FLAGS }, /* 1024x768@50Hz */
{ { 59420, 1280, 1312, 1536, 1568, 720, 735, 741, 757, 0 }, B_RGB32_LITTLE, 1280, 720, 0, 0, MODE_FLAGS }, /* 1280x720@50Hz */
{ { 64050, 1280, 1312, 1552, 1584, 768, 784, 791, 807, 0 }, B_RGB32_LITTLE, 1280, 768, 0, 0, MODE_FLAGS }, /* 1280x768@50Hz */
{ { 65740, 1152, 1184, 1432, 1464, 854, 872, 879, 897, 0 }, B_RGB32_LITTLE, 1152, 854, 0, 0, MODE_FLAGS }, /* 1152x854@50Hz */
{ { 67260, 1280, 1312, 1560, 1592, 800, 817, 824, 841, 0 }, B_RGB32_LITTLE, 1280, 800, 0, 0, MODE_FLAGS }, /* 1280x800@50Hz */
{ { 86730, 1440, 1472, 1800, 1832, 900, 919, 927, 946, 0 }, B_RGB32_LITTLE, 1440, 900, 0, 0, MODE_FLAGS }, /* 1440x900@50Hz */
{ { 90890, 1280, 1312, 1656, 1688, 1024, 1045, 1054, 1076, 0 }, B_RGB32_LITTLE, 1280, 1024, 0, 0, MODE_FLAGS }, /* 1280x1024@50Hz */
{ { 102150, 1400, 1432, 1816, 1848, 1050, 1072, 1081, 1103, 0 }, B_RGB32_LITTLE, 1400, 1050, 0, 0, MODE_FLAGS }, /* 1400x1050@50Hz */
{ { 121680, 1680, 1712, 2168, 2200, 1050, 1072, 1081, 1103, 0 }, B_RGB32_LITTLE, 1680, 1050, 0, 0, MODE_FLAGS }, /* 1680x1050@50Hz */
{ { 137970, 1600, 1632, 2152, 2184, 1200, 1225, 1235, 1261, 0 }, B_RGB32_LITTLE, 1600, 1200, 0, 0, MODE_FLAGS }, /* 1600x1200@50Hz */
{ { 164500, 1920, 1952, 2576, 2608, 1200, 1225, 1235, 1261, 0 }, B_RGB32_LITTLE, 1920, 1200, 0, 0, MODE_FLAGS }, /* 1920x1200@50Hz */
{ { 179080, 1792, 1824, 2504, 2536, 1344, 1372, 1383, 1412, 0 }, B_RGB32_LITTLE, 1792, 1344, 0, 0, MODE_FLAGS }, /* 1792x1344@50Hz */
{ { 194330, 1856, 1888, 2624, 2656, 1392, 1421, 1432, 1462, 0 }, B_RGB32_LITTLE, 1856, 1392, 0, 0, MODE_FLAGS }, /* 1856x1392@50Hz */
{ { 210640, 1920, 1952, 2752, 2784, 1440, 1470, 1482, 1513, 0 }, B_RGB32_LITTLE, 1920, 1440, 0, 0, MODE_FLAGS }, /* 1920x1440@50Hz */
{ { 245600, 2048, 2080, 3008, 3040, 1536, 1568, 1581, 1613, 0 }, B_RGB32_LITTLE, 2048, 1536, 0, 0, MODE_FLAGS }, /* 2048x1536@50Hz */
};
status_t
PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low,
const display_mode *high)
{
TRACE("PROPOSE_DISPLAY_MODE\n");
/* Arbitrary - I don't know if VMware really has a lower limit */
if (target->virtual_width < 320 || target->virtual_height < 240)
return B_ERROR;
if (target->virtual_width > gSi->maxWidth ||
target->virtual_height > gSi->maxHeight)
return B_ERROR;
if (target->space != B_RGB32_LITTLE)
return B_ERROR;
/* Any such mode is OK, even if it isn't in our propose list */
return B_OK;
}
uint32
ACCELERANT_MODE_COUNT()
{
TRACE("ACCELERANT_MODE_COUNT: %d\n", MODE_COUNT);
return MODE_COUNT;
}
status_t
GET_MODE_LIST(display_mode * dm)
{
TRACE("GET_MODE_LIST\n");
memcpy(dm, kModeList, sizeof(kModeList));
return B_OK;
}
+541
View File
@@ -0,0 +1,541 @@
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.
@@ -0,0 +1,97 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#include "GlobalData.h"
status_t
SET_DISPLAY_MODE(display_mode * modeToSet)
{
display_mode bounds, target;
int bpp;
TRACE("SET_DISPLAY_MODE\n");
/* Ask for the specific mode */
target = bounds = *modeToSet;
if (PROPOSE_DISPLAY_MODE(&target, &bounds, &bounds) == B_ERROR)
return B_ERROR;
bpp = BppForSpace(target.space);
TRACE("setting %dx%dx%d\n", target.virtual_width,
target.virtual_height, bpp);
gSi->dm = target;
/* Disable SVGA while we switch */
ioctl(gFd, VMWARE_FIFO_STOP, NULL, 0);
/* Re-init fifo */
FifoInit();
/* Set resolution. This also updates the frame buffer config in the
* shared area */
ioctl(gFd, VMWARE_SET_MODE, &target, sizeof(target));
/* Blank the screen to avoid ugly glitches until the app_server redraws */
memset(gSi->fb, 0, target.virtual_height * gSi->bytesPerRow);
FifoUpdateFullscreen();
/* Re-enable SVGA */
ioctl(gFd, VMWARE_FIFO_START, NULL, 0);
return B_OK;
}
status_t
MOVE_DISPLAY(uint16 hDisplayStart, uint16 vDisplayStart)
{
TRACE("MOVE_DISPLAY (%d, %d)\n", hDisplayStart, vDisplayStart);
return B_ERROR;
}
void
SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags)
{
TRACE("SET_INDEXED_COLORS\n");
}
/*--------------------------------------------------------------------*/
/* DPMS_CAPABILITIES: reports DPMS capabilities (on, stand by,
* suspend, off) */
uint32
DPMS_CAPABILITIES()
{
/* We stay always on */
return B_DPMS_ON;
}
/*--------------------------------------------------------------------*/
/* DPMS_MODE: reports the current DPMS mode */
uint32
DPMS_MODE()
{
return B_DPMS_ON;
}
/*--------------------------------------------------------------------*/
/* SET_DPMS_MODE: puts the display into one of the DPMS modes */
status_t
SET_DPMS_MODE(uint32 flags)
{
return B_ERROR;
}
+54
View File
@@ -0,0 +1,54 @@
/*
* Copyright 1999, Be Incorporated.
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Be Incorporated
* Eric Petit <eric.petit@lapsus.org>
*/
#ifndef GENERIC_H
#define GENERIC_H
status_t INIT_ACCELERANT(int fd);
ssize_t ACCELERANT_CLONE_INFO_SIZE(void);
void GET_ACCELERANT_CLONE_INFO(void *data);
status_t CLONE_ACCELERANT(void *data);
void UNINIT_ACCELERANT(void);
status_t GET_ACCELERANT_DEVICE_INFO(accelerant_device_info *adi);
sem_id ACCELERANT_RETRACE_SEMAPHORE(void);
uint32 ACCELERANT_MODE_COUNT(void);
status_t GET_MODE_LIST(display_mode *dm);
status_t PROPOSE_DISPLAY_MODE(display_mode *target, const display_mode *low, const display_mode *high);
status_t SET_DISPLAY_MODE(display_mode *mode_to_set);
status_t GET_DISPLAY_MODE(display_mode *current_mode);
status_t GET_FRAME_BUFFER_CONFIG(frame_buffer_config *a_frame_buffer);
status_t GET_PIXEL_CLOCK_LIMITS(display_mode *dm, uint32 *low, uint32 *high);
status_t MOVE_DISPLAY(uint16 h_display_start, uint16 v_display_start);
status_t GET_TIMING_CONSTRAINTS(display_timing_constraints *dtc);
void SET_INDEXED_COLORS(uint count, uint8 first, uint8 *color_data, uint32 flags);
uint32 DPMS_CAPABILITIES(void);
uint32 DPMS_MODE(void);
status_t SET_DPMS_MODE(uint32 dpms_flags);
status_t SET_CURSOR_SHAPE(uint16 width, uint16 height, uint16 hot_x, uint16 hot_y, uint8 *andMask, uint8 *xorMask);
void MOVE_CURSOR(uint16 x, uint16 y);
void SHOW_CURSOR(bool is_visible);
uint32 ACCELERANT_ENGINE_COUNT(void);
status_t ACQUIRE_ENGINE(uint32 capabilities, uint32 max_wait, sync_token *st, engine_token **et);
status_t RELEASE_ENGINE(engine_token *et, sync_token *st);
void WAIT_ENGINE_IDLE(void);
status_t GET_SYNC_TOKEN(engine_token *et, sync_token *st);
status_t SYNC_TO_TOKEN(sync_token *st);
void SCREEN_TO_SCREEN_BLIT(engine_token *et, blit_params *list, uint32 count);
void FILL_RECTANGLE(engine_token *et, uint32 color, fill_rect_params *list, uint32 count);
void INVERT_RECTANGLE(engine_token *et, fill_rect_params *list, uint32 count);
void FILL_SPAN(engine_token *et, uint32 color, uint16 *list, uint32 count);
#endif
@@ -12,5 +12,6 @@ SubInclude HAIKU_TOP src add-ons kernel drivers graphics tdfx ;
SubInclude HAIKU_TOP src add-ons kernel drivers graphics skeleton ;
SubInclude HAIKU_TOP src add-ons kernel drivers graphics vesa ;
SubInclude HAIKU_TOP src add-ons kernel drivers graphics via ;
SubInclude HAIKU_TOP src add-ons kernel drivers graphics vmware ;
SubIncludeGPL HAIKU_TOP src add-ons kernel drivers graphics atimach64 ;
@@ -0,0 +1,12 @@
SubDir HAIKU_TOP src add-ons kernel drivers graphics vmware ;
SetSubDirSupportedPlatformsBeOSCompatible ;
UsePrivateHeaders [ FDirName graphics vmware ] ;
UsePrivateHeaders [ FDirName graphics common ] ;
UsePrivateHeaders graphics ;
KernelAddon vmware :
driver.c
device.c
;
@@ -0,0 +1,341 @@
/*
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Eric Petit <eric.petit@lapsus.org>
*/
#include "driver.h"
#include <KernelExport.h>
#include <PCI.h>
#include <OS.h>
#include <graphic_driver.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define get_pci(o, s) (*gPciBus->read_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s))
#define set_pci(o, s, v) (*gPciBus->write_pci_config)(pcii->bus, pcii->device, pcii->function, (o), (s), (v))
static void
PrintCapabilities(uint32 c)
{
TRACE("capabilities:\n");
if (c & SVGA_CAP_RECT_FILL) TRACE("RECT_FILL\n");
if (c & SVGA_CAP_RECT_COPY) TRACE("RECT_COPY\n");
if (c & SVGA_CAP_RECT_PAT_FILL) TRACE("RECT_PAT_FILL\n");
if (c & SVGA_CAP_LEGACY_OFFSCREEN) TRACE("LEGACY_OFFSCREEN\n");
if (c & SVGA_CAP_RASTER_OP) TRACE("RASTER_OP\n");
if (c & SVGA_CAP_CURSOR) TRACE("CURSOR\n");
if (c & SVGA_CAP_CURSOR_BYPASS) TRACE("CURSOR_BYPASS\n");
if (c & SVGA_CAP_CURSOR_BYPASS_2) TRACE("CURSOR_BYPASS_2\n");
if (c & SVGA_CAP_8BIT_EMULATION) TRACE("8BIT_EMULATION\n");
if (c & SVGA_CAP_ALPHA_CURSOR) TRACE("ALPHA_CURSOR\n");
if (c & SVGA_CAP_GLYPH) TRACE("GLYPH\n");
if (c & SVGA_CAP_GLYPH_CLIPPING) TRACE("GLYPH_CLIPPING\n");
if (c & SVGA_CAP_OFFSCREEN_1) TRACE("OFFSCREEN_1\n");
if (c & SVGA_CAP_ALPHA_BLEND) TRACE("ALPHA_BLEND\n");
if (c & SVGA_CAP_3D) TRACE("3D\n");
if (c & SVGA_CAP_EXTENDED_FIFO) TRACE("EXTENDED_FIFO\n");
}
static status_t
CheckCapabilities()
{
SharedInfo *si = gPd->si;
uint32 id;
/* Needed to read/write registers */
si->indexPort = gPd->pcii.u.h0.base_registers[0] + SVGA_INDEX_PORT;
si->valuePort = gPd->pcii.u.h0.base_registers[0] + SVGA_VALUE_PORT;
TRACE("index port: %d, value port: %d\n",
si->indexPort, si->valuePort);
/* This should be SVGA II according to the PCI device_id,
* but just in case... */
WriteReg(SVGA_REG_ID, SVGA_ID_2);
if ((id = ReadReg(SVGA_REG_ID)) != SVGA_ID_2) {
TRACE("SVGA_REG_ID is %ld, not %d\n", id, SVGA_REG_ID);
return B_ERROR;
}
TRACE("SVGA_REG_ID OK\n");
/* Grab some info */
si->maxWidth = ReadReg(SVGA_REG_MAX_WIDTH);
si->maxHeight = ReadReg(SVGA_REG_MAX_HEIGHT);
TRACE("max resolution: %ldx%ld\n", si->maxWidth, si->maxHeight);
si->fbDma = (void *)ReadReg(SVGA_REG_FB_START);
si->fbSize = ReadReg(SVGA_REG_VRAM_SIZE);
TRACE("frame buffer: %p, size %ld\n", si->fbDma, si->fbSize);
si->fifoDma = (void *)ReadReg(SVGA_REG_MEM_START);
si->fifoSize = ReadReg(SVGA_REG_MEM_SIZE) & ~3;
TRACE("fifo: %p, size %ld\n", si->fifoDma, si->fifoSize);
si->capabilities = ReadReg(SVGA_REG_CAPABILITIES);
PrintCapabilities(si->capabilities);
si->fifoMin = (si->capabilities & SVGA_CAP_EXTENDED_FIFO) ?
ReadReg(SVGA_REG_MEM_REGS) : 4;
return B_OK;
}
static status_t
MapDevice()
{
SharedInfo *si = gPd->si;
int writeCombined = 1;
/* Map the frame buffer */
si->fbArea = map_physical_memory("VMware frame buffer",
si->fbDma, si->fbSize, B_ANY_KERNEL_BLOCK_ADDRESS|B_MTR_WC,
B_READ_AREA|B_WRITE_AREA, (void **)&si->fb);
if (si->fbArea < 0) {
/* Try again without write combining */
writeCombined = 0;
si->fbArea = map_physical_memory("VMware frame buffer",
si->fbDma, si->fbSize, B_ANY_KERNEL_BLOCK_ADDRESS,
B_READ_AREA|B_WRITE_AREA, (void **)&si->fb);
}
if (si->fbArea < 0) {
TRACE("failed to map frame buffer\n");
return si->fbArea;
}
TRACE("frame buffer mapped: %p->%p, area %ld, size %ld, write "
"combined: %d\n", si->fbDma, si->fb, si->fbArea,
si->fbSize, writeCombined);
/* Map the fifo */
si->fifoArea = map_physical_memory("VMware fifo",
si->fifoDma, si->fifoSize, B_ANY_KERNEL_BLOCK_ADDRESS,
B_READ_AREA|B_WRITE_AREA, (void **)&si->fifo);
if (si->fifoArea < 0) {
TRACE("failed to map fifo\n");
delete_area(si->fbArea);
return si->fifoArea;
}
TRACE("fifo mapped: %p->%p, area %ld, size %ld\n", si->fifoDma,
si->fifo, si->fifoArea, si->fifoSize);
return B_OK;
}
static void
UnmapDevice()
{
SharedInfo *si = gPd->si;
pci_info *pcii = &gPd->pcii;
uint32 tmpUlong;
/* Disable memory mapped IO */
tmpUlong = get_pci(PCI_command, 2);
tmpUlong &= ~PCI_command_memory;
set_pci(PCI_command, 2, tmpUlong);
/* Delete the areas */
if (si->fifoArea >= 0)
delete_area(si->fifoArea);
if (si->fbArea >= 0)
delete_area(si->fbArea);
si->fifoArea = si->fbArea = -1;
si->fb = si->fifo = NULL;
}
static status_t
CreateShared()
{
gPd->sharedArea = create_area("VMware shared", (void **)&gPd->si,
B_ANY_KERNEL_ADDRESS, ROUND_TO_PAGE_SIZE(sizeof(SharedInfo)),
B_FULL_LOCK, 0);
if (gPd->sharedArea < B_OK) {
TRACE("failed to create shared area\n");
return gPd->sharedArea;
}
TRACE("shared area created\n");
memset(gPd->si, 0, sizeof(SharedInfo));
return B_OK;
}
static void
FreeShared()
{
delete_area(gPd->sharedArea);
gPd->sharedArea = -1;
gPd->si = NULL;
}
static status_t
OpenHook(const char *name, uint32 flags, void **cookie)
{
status_t ret = B_OK;
pci_info *pcii = &gPd->pcii;
uint32 tmpUlong;
TRACE("OpenHook (%s, %ld)\n", name, flags);
ACQUIRE_BEN(gPd->kernel);
if (gPd->isOpen)
goto markAsOpen;
/* Enable memory mapped IO and VGA I/O */
tmpUlong = get_pci(PCI_command, 2);
tmpUlong |= PCI_command_memory;
tmpUlong |= PCI_command_io;
set_pci(PCI_command, 2, tmpUlong);
if ((ret = CreateShared()) != B_OK)
goto done;
if ((ret = CheckCapabilities()) != B_OK)
goto freeShared;
if ((ret = MapDevice()) != B_OK)
goto freeShared;
markAsOpen:
gPd->isOpen++;
*cookie = gPd;
goto done;
freeShared:
FreeShared();
done:
RELEASE_BEN(gPd->kernel);
TRACE("OpenHook: %ld\n", ret);
return ret;
}
/*--------------------------------------------------------------------*/
/* ReadHook, WriteHook, CloseHook: do nothing */
static status_t
ReadHook(void *dev, off_t pos, void *buf, size_t *len)
{
*len = 0;
return B_NOT_ALLOWED;
}
static status_t
WriteHook(void *dev, off_t pos, const void *buf, size_t *len)
{
*len = 0;
return B_NOT_ALLOWED;
}
static status_t
CloseHook(void *dev)
{
return B_OK;
}
/*--------------------------------------------------------------------*/
/* FreeHook: closes down the device */
static status_t
FreeHook(void *dev)
{
TRACE("FreeHook\n");
ACQUIRE_BEN(gPd->kernel);
if (gPd->isOpen < 2) {
UnmapDevice();
FreeShared();
}
gPd->isOpen--;
RELEASE_BEN(gPd->kernel);
TRACE("FreeHook ends\n");
return B_OK;
}
/*--------------------------------------------------------------------*/
/* ControlHook: responds the the ioctl from the accelerant */
static status_t
ControlHook(void *dev, uint32 msg, void *buf, size_t len)
{
SharedInfo *si = gPd->si;
switch (msg) {
case B_GET_ACCELERANT_SIGNATURE:
strcpy((char *)buf, "vmware.accelerant");
return B_OK;
case VMWARE_GET_PRIVATE_DATA:
*((area_id *)buf) = gPd->sharedArea;
return B_OK;
case VMWARE_FIFO_START:
WriteReg(SVGA_REG_ENABLE, 1);
WriteReg(SVGA_REG_CONFIG_DONE, 1);
return B_OK;
case VMWARE_FIFO_STOP:
WriteReg(SVGA_REG_CONFIG_DONE, 0);
WriteReg(SVGA_REG_ENABLE, 0);
return B_OK;
case VMWARE_FIFO_SYNC:
WriteReg(SVGA_REG_SYNC, 1);
while (ReadReg(SVGA_REG_BUSY));
return B_OK;
case VMWARE_SET_MODE:
{
display_mode *dm = buf;
WriteReg(SVGA_REG_WIDTH, dm->virtual_width);
WriteReg(SVGA_REG_HEIGHT, dm->virtual_height);
WriteReg(SVGA_REG_BITS_PER_PIXEL, BppForSpace(dm->space));
si->fbOffset = ReadReg(SVGA_REG_FB_OFFSET);
si->bytesPerRow = ReadReg(SVGA_REG_BYTES_PER_LINE);
return B_OK;
}
case VMWARE_MOVE_CURSOR:
{
uint16 *pos = buf;
WriteReg(SVGA_REG_CURSOR_ID, CURSOR_ID);
WriteReg(SVGA_REG_CURSOR_X, pos[0]);
WriteReg(SVGA_REG_CURSOR_Y, pos[1]);
return B_OK;
}
case VMWARE_SHOW_CURSOR:
{
bool show = *((bool *)buf);
WriteReg(SVGA_REG_CURSOR_ON, show ? SVGA_CURSOR_ON_HIDE :
SVGA_CURSOR_ON_SHOW);
return B_OK;
}
}
TRACE("ioctl: %ld, %p, %ld\n", msg, buf, len);
return B_DEV_INVALID_IOCTL;
}
device_hooks gGraphicsDeviceHooks =
{
OpenHook,
CloseHook,
FreeHook,
ControlHook,
ReadHook,
WriteHook,
NULL,
NULL,
NULL,
NULL
};
@@ -0,0 +1,122 @@
/*
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Eric Petit <eric.petit@lapsus.org>
*/
#include "driver.h"
#include <KernelExport.h>
#include <PCI.h>
#include <OS.h>
#include <stdlib.h>
#include <string.h>
DeviceData *gPd;
pci_module_info *gPciBus;
int32 api_version = B_CUR_DRIVER_API_VERSION;
status_t
init_hardware(void)
{
status_t ret = B_ERROR;
pci_info pcii;
int i;
TRACE("init_hardware\n");
if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPciBus) != B_OK)
return B_ERROR;
for (i = 0; (*gPciBus->get_nth_pci_info)(i, &pcii) == B_OK; i++) {
if (pcii.vendor_id == PCI_VENDOR_ID_VMWARE &&
pcii.device_id == PCI_DEVICE_ID_VMWARE_SVGA2) {
ret = B_OK;
break;
}
}
put_module(B_PCI_MODULE_NAME);
TRACE("init_hardware: %ld\n", ret);
return ret;
}
status_t
init_driver(void)
{
status_t ret = B_OK;
int i;
TRACE("init_driver\n");
if (get_module(B_PCI_MODULE_NAME, (module_info **)&gPciBus) != B_OK) {
ret = B_ERROR;
goto done;
}
if (!(gPd = calloc(1, sizeof(DeviceData)))) {
put_module(B_PCI_MODULE_NAME);
ret = B_ERROR;
goto done;
}
/* Remember the PCI information */
for (i = 0; (*gPciBus->get_nth_pci_info)(i, &gPd->pcii) == B_OK; i++)
if (gPd->pcii.vendor_id == PCI_VENDOR_ID_VMWARE &&
gPd->pcii.device_id == PCI_DEVICE_ID_VMWARE_SVGA2)
break;
/* Create a benaphore for exclusive access in OpenHook/FreeHook */
INIT_BEN(gPd->kernel);
/* The device name */
gPd->names[0] = strdup("graphics/vmware");
gPd->names[1] = NULL;
/* Usual initializations */
gPd->isOpen = 0;
gPd->sharedArea = -1;
gPd->si = NULL;
done:
TRACE("init_driver: %ld\n", ret);
return ret;
}
const char **
publish_devices(void)
{
TRACE("publish_devices\n");
return (const char **)gPd->names;
}
device_hooks *
find_device(const char *name)
{
TRACE("find_device (%s)\n", name);
if (gPd->names[0] && !strcmp(gPd->names[0], name))
return &gGraphicsDeviceHooks;
return NULL;
}
void
uninit_driver()
{
TRACE("uninit_driver\n");
free(gPd);
put_module(B_PCI_MODULE_NAME);
}
@@ -0,0 +1,65 @@
/*
* Copyright 2007, Haiku.
* Distributed under the terms of the MIT License.
*
* Authors:
* Eric Petit <eric.petit@lapsus.org>
*/
#ifndef DRIVER_H
#define DRIVER_H
#define TRACE(a...) dprintf("VMware: " ##a)
#include "DriverInterface.h"
typedef struct {
char *names[2];
Benaphore kernel;
uint32 isOpen;
area_id sharedArea;
SharedInfo *si;
pci_info pcii;
} DeviceData;
/*--------------------------------------------------------------------*/
/* Global variables */
extern DeviceData *gPd;
extern pci_module_info *gPciBus;
extern device_hooks gGraphicsDeviceHooks;
/*--------------------------------------------------------------------*/
/* Access to 32 bit registers in the IO address space. */
static inline uint32
inl(uint16 port)
{
uint32 ret;
__asm__ __volatile__("inl %w1, %0" : "=a" (ret) : "Nd" (port));
return ret;
}
static inline void
outl(uint16 port, uint32 value)
{
__asm__ __volatile__("outl %1, %w0" :: "Nd" (port), "a" (value));
}
static inline uint32
ReadReg(uint32 index)
{
outl(gPd->si->indexPort, index);
return inl(gPd->si->valuePort);
}
static inline void
WriteReg(uint32 index, uint32 value)
{
outl(gPd->si->indexPort, index);
outl(gPd->si->valuePort, value);
}
#endif // DRIVER_H