erythros/System/Drivers/VMSVGA.HC

255 lines
8.6 KiB
HolyC

class @vmsvga_info
{
U16 io_base;
U32* fifo;
U16 width;
U16 height;
U16 bpp;
U64 fb;
U32 capabilities;
};
#define VMWGFX_FIFO_STATIC_SIZE (1024 * 1024)
#define VMSVGA_MAGIC 0x900000
#define VMSVGA_ID_2 (VMSVGA_MAGIC << 8 | 2)
#define VMSVGA_MOUSE_ID 1
#define VMSVGA_CAP_GMR 0x00100000
#define VMSVGA_CMD_INVALID_CMD 0
#define VMSVGA_CMD_UPDATE 1
#define VMSVGA_CMD_RECT_COPY 3
#define VMSVGA_CMD_DEFINE_CURSOR 19
#define VMSVGA_CMD_DEFINE_ALPHA_CURSOR 22
#define VMSVGA_CMD_UPDATE_VERBOSE 25
#define VMSVGA_CMD_FRONT_ROP_FILL 29
#define VMSVGA_CMD_FENCE 30
#define VMSVGA_CMD_ESCAPE 33
#define VMSVGA_CMD_DEFINE_SCREEN 34
#define VMSVGA_CMD_DESTROY_SCREEN 35
#define VMSVGA_CMD_DEFINE_GMRFB 36
#define VMSVGA_CMD_BLIT_GMRFB_TO_SCREEN 37
#define VMSVGA_CMD_BLIT_SCREEN_TO_GMRFB 38
#define VMSVGA_CMD_ANNOTATION_FILL 39
#define VMSVGA_CMD_ANNOTATION_COPY 40
#define VMSVGA_CMD_DEFINE_GMR2 41
#define VMSVGA_CMD_REMAP_GMR2 42
#define VMSVGA_REG_ID 0
#define VMSVGA_REG_ENABLE 1
#define VMSVGA_REG_WIDTH 2
#define VMSVGA_REG_HEIGHT 3
#define VMSVGA_REG_MAX_WIDTH 4
#define VMSVGA_REG_MAX_HEIGHT 5
#define VMSVGA_REG_DEPTH 6
#define VMSVGA_REG_BITS_PER_PIXEL 7 /* Current bpp in the guest */
#define VMSVGA_REG_PSEUDOCOLOR 8
#define VMSVGA_REG_RED_MASK 9
#define VMSVGA_REG_GREEN_MASK 10
#define VMSVGA_REG_BLUE_MASK 11
#define VMSVGA_REG_BYTES_PER_LINE 12
#define VMSVGA_REG_FB_START 13 /* (Deprecated) */
#define VMSVGA_REG_FB_OFFSET 14
#define VMSVGA_REG_VRAM_SIZE 15
#define VMSVGA_REG_FB_SIZE 16
/* ID 0 implementation only had the above registers then the palette */
#define VMSVGA_REG_CAPABILITIES 17
#define VMSVGA_REG_MEM_START 18 /* (Deprecated) */
#define VMSVGA_REG_MEM_SIZE 19
#define VMSVGA_REG_CONFIG_DONE 20 /* Set when memory area configured */
#define VMSVGA_REG_SYNC 21 /* See "FIFO Synchronization Registers" */
#define VMSVGA_REG_BUSY 22 /* See "FIFO Synchronization Registers" */
#define VMSVGA_REG_GUEST_ID 23 /* Set guest OS identifier */
#define VMSVGA_REG_CURSOR_ID 24 /* (Deprecated) */
#define VMSVGA_REG_CURSOR_X 25 /* (Deprecated) */
#define VMSVGA_REG_CURSOR_Y 26 /* (Deprecated) */
#define VMSVGA_REG_CURSOR_ON 27 /* (Deprecated) */
#define VMSVGA_REG_HOST_BITS_PER_PIXEL 28 /* (Deprecated) */
#define VMSVGA_REG_SCRATCH_SIZE 29 /* Number of scratch registers */
#define VMSVGA_REG_MEM_REGS 30 /* Number of FIFO registers */
#define VMSVGA_REG_NUM_DISPLAYS 31 /* (Deprecated) */
#define VMSVGA_REG_PITCHLOCK 32 /* Fixed pitch for all modes */
#define VMSVGA_REG_IRQMASK 33 /* Interrupt mask */
/* Legacy multi-monitor support */
#define VMSVGA_REG_NUM_GUEST_DISPLAYS \
34 /* Number of guest displays in X/Y direction */
#define VMSVGA_REG_DISPLAY_ID \
35 /* Display ID for the following display attributes */
#define VMSVGA_REG_DISPLAY_IS_PRIMARY \
36 /* Whether this is a primary display \
*/
#define VMSVGA_REG_DISPLAY_POSITION_X 37 /* The display position x */
#define VMSVGA_REG_DISPLAY_POSITION_Y 38 /* The display position y */
#define VMSVGA_REG_DISPLAY_WIDTH 39 /* The display's width */
#define VMSVGA_REG_DISPLAY_HEIGHT 40 /* The display's height */
/* See "Guest memory regions" below. */
#define VMSVGA_REG_GMR_ID 41
#define VMSVGA_REG_GMR_DESCRIPTOR 42
#define VMSVGA_REG_GMR_MAX_IDS 43
#define VMSVGA_REG_GMR_MAX_DESCRIPTOR_LENGTH 44
#define VMSVGA_REG_TRACES \
45 /* Enable trace-based updates even when FIFO is on */
#define VMSVGA_REG_GMRS_MAX_PAGES \
46 /* Maximum number of 4KB pages for all GMRs */
#define VMSVGA_REG_MEMORY_SIZE \
47 /* Total dedicated device memory excluding FIFO */
#define VMSVGA_REG_TOP 48 /* Must be 1 more than the last register */
#define VMSVGA_FIFO_MIN 0
#define VMSVGA_FIFO_MAX 1
#define VMSVGA_FIFO_NEXT_CMD 2
#define VMSVGA_FIFO_STOP 3
#define VMSVGA_FIFO_CAPABILITIES 4
#define VMSVGA_FIFO_FLAGS 5
#define VMSVGA_FIFO_FENCE 6
#define VMSVGA_FIFO_3D_HWVERSION 7
#define VMSVGA_FIFO_PITCHLOCK 8
#define VMSVGA_FIFO_CURSOR_ON 9
#define VMSVGA_FIFO_CURSOR_X 10
#define VMSVGA_FIFO_CURSOR_Y 11
#define VMSVGA_FIFO_CURSOR_COUNT 12
#define VMSVGA_FIFO_CURSOR_LAST_UPDATED 13
#define VMSVGA_FIFO_RESERVED 14
#define VMSVGA_FIFO_CURSOR_SCREEN_ID 15
#define VMSVGA_FIFO_DEAD 16
#define VMSVGA_FIFO_3D_HWVERSION_REVISED 17
#define VMSVGA_FIFO_3D_CAPS 18
#define VMSVGA_FIFO_3D_CAPS_LAST = 19
#define VMSVGA_FIFO_GUEST_3D_HWVERSION 20
#define VMSVGA_FIFO_FENCE_GOAL 21
#define VMSVGA_FIFO_BUSY 22
#define VMSVGA_FIFO_NUM_REGS 23
#define VMSVGA_FIFO_CAP_NONE 0
#define VMSVGA_FIFO_CAP_FENCE (1 << 0)
#define VMSVGA_FIFO_CAP_ACCELFRONT (1 << 1)
#define VMSVGA_FIFO_CAP_PITCHLOCK (1 << 2)
#define VMSVGA_FIFO_CAP_VIDEO (1 << 3)
#define VMSVGA_FIFO_CAP_CURSOR_BYPASS_3 (1 << 4)
#define VMSVGA_FIFO_CAP_ESCAPE (1 << 5)
#define VMSVGA_FIFO_CAP_RESERVE (1 << 6)
#define VMSVGA_FIFO_CAP_SCREEN_OBJECT (1 << 7)
#define VMSVGA_FIFO_CAP_GMR2 (1 << 8)
// #define VMSVGA_FIFO_CAP_3D_HWVERSION_REVISED VMSVGA_FIFO_CAP_GMR2
#define VMSVGA_FIFO_CAP_SCREEN_OBJECT_2 (1 << 9)
#define VMSVGA_FIFO_CAP_DEAD (1 << 10)
@vmsvga_info vmsvga;
MemSet(&vmsvga, 0, sizeof(@vmsvga_info));
U32 @vmsvga_reg_read(I64 index)
{
OutU32(vmsvga.io_base, index);
return InU32(vmsvga.io_base + 1);
}
U0 @vmsvga_reg_write(I64 index, U32 val)
{
OutU32(vmsvga.io_base, index);
OutU32(vmsvga.io_base + 1, val);
}
U0 @vmsvga_fifo_write(U32 value)
{
/* Need to sync? */
if ((vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] + sizeof(U32) == vmsvga.fifo[VMSVGA_FIFO_STOP]) || (vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] == vmsvga.fifo[VMSVGA_FIFO_MAX] - sizeof(U32) && vmsvga.fifo[VMSVGA_FIFO_STOP] == vmsvga.fifo[VMSVGA_FIFO_MIN])) {
//"Syncing because of full fifo\n";
// vmwareWaitForFB(pVMWARE);
}
vmsvga.fifo[vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] / sizeof(U32)] = value;
if (vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] == vmsvga.fifo[VMSVGA_FIFO_MAX] - sizeof(U32)) {
vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] = vmsvga.fifo[VMSVGA_FIFO_MIN];
} else {
vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] += sizeof(U32);
}
}
U0 @vmsvga_fifo_get_cap(U8* s, I64 cap)
{
"%32s:", s;
if ((vmsvga.fifo[VMSVGA_FIFO_CAPABILITIES] & cap) == cap)
"%s\n", "True";
else
"%s\n", "False";
}
I64 @vmsvga_init(I64 w, I64 h, I64 bpp)
{
I64 j;
j = PCIClassFind(0x030000, 0);
if (j < 0) {
//"VMSVGA device not found.\n";
return -1;
}
vmsvga.io_base = PCIReadU16(j.u8[2], j.u8[1], j.u8[0], 0x10) & ~(0x0F);
@vmsvga_reg_write(VMSVGA_REG_ID, VMSVGA_ID_2);
if (@vmsvga_reg_read(VMSVGA_REG_ID) == VMSVGA_ID_2) {
//"VMSVGA driver version 2 supported.\n";
} else {
//"VMSVGA device not supported.\n";
return -1;
}
vmsvga.width = w;
vmsvga.height = h;
vmsvga.bpp = bpp;
vmsvga.fb = @vmsvga_reg_read(VMSVGA_REG_FB_START);
vmsvga.fifo = @vmsvga_reg_read(VMSVGA_REG_MEM_START);
//"FIFO @ 0x%08X (%d bytes)\n", vmsvga.fifo,
// @vmsvga_reg_read(VMSVGA_REG_MEM_SIZE);
@vmsvga_reg_write(VMSVGA_REG_WIDTH, 1920);
@vmsvga_reg_write(VMSVGA_REG_HEIGHT, 1080);
@vmsvga_reg_write(VMSVGA_REG_BITS_PER_PIXEL, 32);
@vmsvga_reg_write(VMSVGA_REG_ENABLE, 1);
vmsvga.fifo[VMSVGA_FIFO_MIN] = 16;
vmsvga.fifo[VMSVGA_FIFO_MAX] = 16 + (10 * 1024);
vmsvga.fifo[VMSVGA_FIFO_NEXT_CMD] = 16;
vmsvga.fifo[VMSVGA_FIFO_STOP] = 16;
@vmsvga_reg_write(VMSVGA_REG_CONFIG_DONE, 0);
@vmsvga_fifo_write(VMSVGA_CMD_UPDATE);
@vmsvga_fifo_write(0);
@vmsvga_fifo_write(0);
@vmsvga_fifo_write(0);
@vmsvga_fifo_write(0);
@vmsvga_reg_write(VMSVGA_REG_CONFIG_DONE, 1);
return 0;
}
U0 @vmsvga_mouse_pointer_set(U32* pointer, I64 width, I64 height)
{
@vmsvga_reg_write(VMSVGA_REG_CONFIG_DONE, 0);
@vmsvga_fifo_write(VMSVGA_CMD_DEFINE_ALPHA_CURSOR);
@vmsvga_fifo_write(VMSVGA_MOUSE_ID);
@vmsvga_fifo_write(0);
@vmsvga_fifo_write(0);
@vmsvga_fifo_write(width);
@vmsvga_fifo_write(height);
I64 x, y;
for (y = 0; y < height; y++) {
for (x = 0; x < width; x++) {
@vmsvga_fifo_write(pointer[(y * width) + x]);
}
}
@vmsvga_reg_write(VMSVGA_REG_CONFIG_DONE, 1);
}
U64 @vmsvga_get_framebuffer() { return vmsvga.fb; }
U0 @vmsvga_display_update() { @vmsvga_reg_write(VMSVGA_REG_ENABLE, 1); }
class @vmsvga
{
U0(*Init)
(I64 w, I64 h, I64 bpp);
U64(*FrameBuffer)
();
};
@vmsvga VMSVGA;
VMSVGA.FrameBuffer = &@vmsvga_get_framebuffer;
VMSVGA.Init = &@vmsvga_init;
"vmsvga ";