VMWare SVGA-II: Difference between revisions
[unchecked revision] | [unchecked revision] |
(structure) |
No edit summary |
||
Line 6: | Line 6: | ||
== I/O Ports == |
== I/O Ports == |
||
The base I/O port (SVGA_PORT_BASE) is not fixed. The driver has to substract 1 from the BAR0 in the PCI configuration to get it. |
|||
The following port offsets are exposed by the device: |
|||
* '''SVGA_INDEX''' (offset 0) |
|||
* '''SVGA_VALUE''' (offset 1) |
|||
* '''SVGA_BIOS''' (offset 2) |
|||
* '''SVGA_IRQSTATUS''' (offset 8) |
|||
== |
== Internal Registers == |
||
Although there are more registers (all shown in the Official Developer Kit linked below), the most important ones are: |
|||
* '''SVGA_REG_ID''' (0) - register used to negociate specification ID |
|||
* '''SVGA_REG_ENABLE''' (1) - flag set by the driver when the device should enter SVGA mode |
|||
* '''SVGA_REG_WIDTH''' (2) - current screen width |
|||
* '''SVGA_REG_HEIGHT''' (3) - current screen height |
|||
* '''SVGA_REG_MAX_WIDTH''' (4) - maximum supported screen width |
|||
* '''SVGA_REG_MAX_HEIGHT''' (5) - maximum supported screen height |
|||
* '''SVGA_REG_BPP''' (7) - current screen bits per pixel |
|||
* '''SVGA_REG_FB_START''' (13) - address in system memory of the frame buffer |
|||
* '''SVGA_REG_FB_OFFSET''' (14) - offset in the frame buffer to the visible pixel data |
|||
* '''SVGA_REG_VRAM_SIZE''' (15) - size of the video RAM |
|||
* '''SVGA_REG_FB_SIZE''' (16) - size of the frame buffer |
|||
* '''SVGA_REG_CAPABILITIES''' (17) - device capabilities |
|||
* '''SVGA_REG_FIFO_START''' (18) - address in system memory of the FIFO |
|||
* '''SVGA_REG_FIFO_SIZE''' (19) - FIFO size |
|||
* '''SVGA_REG_CONFIG_DONE''' (20) - flag to enable FIFO operation |
|||
* '''SVGA_REG_SYNC''' (21) - flag set by the driver to flush FIFO changes |
|||
* '''SVGA_REG_BUSY''' (22) - flag set by the FIFO when it's processed |
|||
Reading or writing to an internal register is very easy. The driver has to write a long to the port '''SVGA_PORT_BASE''' + '''SVGA_INDEX''' corresponding to the register index then write the data or read it from the port '''SVGA_PORT_BASE''' + '''SVGA_VALUE'''. |
|||
== Reading and Writing to Internal Registers == |
|||
== Initialising the Device == |
|||
The procedure of initialisation is: |
|||
* Detect the device on the PCI bus (vendor 0x15AD, device 0x0405) |
|||
* Enable memory, I/O and bus mastering by ORing the command field (in the PCI configuration) with 0x7; |
|||
* Calculate the I/O base port from substracting 1 from the PCI BAR0. |
|||
* Set the '''SVGA_REG_ID''' register to 0x90000002 (indicate latest specification ID) |
|||
* Check if it is supported by reading back the register and comparing the result |
|||
* Read the frame buffer and FIFO addresses from the registers '''SVGA_REG_FB_START''' and '''SVGA_REG_FIFO_START''' |
|||
* Read the frame buffer offset and the capabilities field from the registers '''SVGA_REG_FB_OFFSET''' and '''SVGA_REG_CAPABILITIES''' |
|||
* Read the FIFO size from the register '''SVGA_REG_FIFO_SIZE''' |
|||
* Identity map the FIFO memory |
|||
* Initialise the FIFO (explained in next chapter) |
|||
* Write 1 to '''SVGA_REG_ENABLE''' |
|||
== Using the FIFO == |
== Using the FIFO == |
||
The FIFO is a 32-bit array which is filled by the driver with commands that the device has to execute. |
|||
The supported FIFO commands are: |
|||
* '''SVGA_CMD_UPDATE''' (1) |
|||
* '''SVGA_CMD_RECT_COPY''' (3) |
|||
* '''SVGA_CMD_DEFINE_CURSOR''' (19) |
|||
* '''SVGA_CMD_DEFINE_ALPHA_CURSOR''' (22) |
|||
* '''SVGA_CMD_UPDATE_VERBOSE''' (25) |
|||
* '''SVGA_CMD_FRONT_ROP_FILL''' (29) |
|||
* '''SVGA_CMD_FENCE''' (30) |
|||
* '''SVGA_CMD_ESCAPE''' (33) |
|||
* '''SVGA_CMD_DEFINE_SCREEN''' (34) |
|||
* '''SVGA_CMD_DESTROY_SCREEN''' (35) |
|||
* '''SVGA_CMD_DEFINE_GMRFB''' (36) |
|||
* '''SVGA_CMD_BLIT_GMRFB_TO_SCREEN''' (37) |
|||
* '''SVGA_CMD_BLIT_SCREEN_TO_GMRFB''' (38) |
|||
* '''SVGA_CMD_ANNOTATION_FILL''' (39) |
|||
* '''SVGA_CMD_ANNOTATION_COPY''' (40) |
|||
* '''SVGA_CMD_DEFINE_GMR2''' (41) |
|||
* '''SVGA_CMD_REMAP_GMR2''' (42) |
|||
The FIFO has many registers that the driver can mess with (293). The most important ones are: |
|||
* '''SVGA_FIFO_MIN''' (0) - start of command queue |
|||
* '''SVGA_FIFO_MAX''' (1) - end of command queue |
|||
* '''SVGA_FIFO_NEXT_CMD''' (2) - next command (offset in bytes) |
|||
* '''SVGA_FIFO_STOP''' (3) - todo: explain what SVGA_FIFO_STOP does |
|||
Writing/reading to/from those is as easy as to write/read data to/from the FIFO address + register index. |
|||
To initialise the FIFO, the driver has to: |
|||
* Set '''SVGA_FIFO_MIN''', '''SVGA_FIFO_NEXT_CMD''' and '''SVGA_FIFO_STOP''' registers to 293 * 4 (point right after the 293 32-bit registers) |
|||
* Set '''SVGA_FIFO_MAX''' to the FIFO size |
|||
* Set '''SVGA_REG_CONFIG_DONE''' to 1 |
|||
To sequentially write data to the FIFO the driver has to: |
|||
* Write the data to the FIFO address + value of '''SVGA_FIFO_NEXT_CMD''' (Warning! SVGA_FIFO_NEXT_CMD provides the offset in '''bytes''') |
|||
* Increment '''SVGA_FIFO_NEXT_CMD''' by 4 |
|||
To write a command, the driver has to first sequentially write its ID and then the operands to the FIFO. |
|||
== Setting the Mode == |
== Setting the Mode == |
||
Line 18: | Line 95: | ||
== 3D Acceleration == |
== 3D Acceleration == |
||
== Official Developer Kit == |
|||
[https://sourceforge.net/p/vmware-svga/git/ci/master/tree VMware SVGA Device Developer Kit] |
Revision as of 17:46, 22 December 2022
The VMware SVGA-II device is a graphics card simulated by VMware and QEMU. It is a PCI SVGA-compatible graphics card that implements 2D and 3D acceleration as well as hardware cursor support.
Hardware Detection
The procedure of detecting its presence is by detecting if there is a PCI device with the vendor ID 0x15AD and the device ID 0x0405 on the bus.
I/O Ports
The base I/O port (SVGA_PORT_BASE) is not fixed. The driver has to substract 1 from the BAR0 in the PCI configuration to get it. The following port offsets are exposed by the device:
- SVGA_INDEX (offset 0)
- SVGA_VALUE (offset 1)
- SVGA_BIOS (offset 2)
- SVGA_IRQSTATUS (offset 8)
Internal Registers
Although there are more registers (all shown in the Official Developer Kit linked below), the most important ones are:
- SVGA_REG_ID (0) - register used to negociate specification ID
- SVGA_REG_ENABLE (1) - flag set by the driver when the device should enter SVGA mode
- SVGA_REG_WIDTH (2) - current screen width
- SVGA_REG_HEIGHT (3) - current screen height
- SVGA_REG_MAX_WIDTH (4) - maximum supported screen width
- SVGA_REG_MAX_HEIGHT (5) - maximum supported screen height
- SVGA_REG_BPP (7) - current screen bits per pixel
- SVGA_REG_FB_START (13) - address in system memory of the frame buffer
- SVGA_REG_FB_OFFSET (14) - offset in the frame buffer to the visible pixel data
- SVGA_REG_VRAM_SIZE (15) - size of the video RAM
- SVGA_REG_FB_SIZE (16) - size of the frame buffer
- SVGA_REG_CAPABILITIES (17) - device capabilities
- SVGA_REG_FIFO_START (18) - address in system memory of the FIFO
- SVGA_REG_FIFO_SIZE (19) - FIFO size
- SVGA_REG_CONFIG_DONE (20) - flag to enable FIFO operation
- SVGA_REG_SYNC (21) - flag set by the driver to flush FIFO changes
- SVGA_REG_BUSY (22) - flag set by the FIFO when it's processed
Reading or writing to an internal register is very easy. The driver has to write a long to the port SVGA_PORT_BASE + SVGA_INDEX corresponding to the register index then write the data or read it from the port SVGA_PORT_BASE + SVGA_VALUE.
Initialising the Device
The procedure of initialisation is:
- Detect the device on the PCI bus (vendor 0x15AD, device 0x0405)
- Enable memory, I/O and bus mastering by ORing the command field (in the PCI configuration) with 0x7;
- Calculate the I/O base port from substracting 1 from the PCI BAR0.
- Set the SVGA_REG_ID register to 0x90000002 (indicate latest specification ID)
- Check if it is supported by reading back the register and comparing the result
- Read the frame buffer and FIFO addresses from the registers SVGA_REG_FB_START and SVGA_REG_FIFO_START
- Read the frame buffer offset and the capabilities field from the registers SVGA_REG_FB_OFFSET and SVGA_REG_CAPABILITIES
- Read the FIFO size from the register SVGA_REG_FIFO_SIZE
- Identity map the FIFO memory
- Initialise the FIFO (explained in next chapter)
- Write 1 to SVGA_REG_ENABLE
Using the FIFO
The FIFO is a 32-bit array which is filled by the driver with commands that the device has to execute.
The supported FIFO commands are:
- SVGA_CMD_UPDATE (1)
- SVGA_CMD_RECT_COPY (3)
- SVGA_CMD_DEFINE_CURSOR (19)
- SVGA_CMD_DEFINE_ALPHA_CURSOR (22)
- SVGA_CMD_UPDATE_VERBOSE (25)
- SVGA_CMD_FRONT_ROP_FILL (29)
- SVGA_CMD_FENCE (30)
- SVGA_CMD_ESCAPE (33)
- SVGA_CMD_DEFINE_SCREEN (34)
- SVGA_CMD_DESTROY_SCREEN (35)
- SVGA_CMD_DEFINE_GMRFB (36)
- SVGA_CMD_BLIT_GMRFB_TO_SCREEN (37)
- SVGA_CMD_BLIT_SCREEN_TO_GMRFB (38)
- SVGA_CMD_ANNOTATION_FILL (39)
- SVGA_CMD_ANNOTATION_COPY (40)
- SVGA_CMD_DEFINE_GMR2 (41)
- SVGA_CMD_REMAP_GMR2 (42)
The FIFO has many registers that the driver can mess with (293). The most important ones are:
- SVGA_FIFO_MIN (0) - start of command queue
- SVGA_FIFO_MAX (1) - end of command queue
- SVGA_FIFO_NEXT_CMD (2) - next command (offset in bytes)
- SVGA_FIFO_STOP (3) - todo: explain what SVGA_FIFO_STOP does
Writing/reading to/from those is as easy as to write/read data to/from the FIFO address + register index.
To initialise the FIFO, the driver has to:
- Set SVGA_FIFO_MIN, SVGA_FIFO_NEXT_CMD and SVGA_FIFO_STOP registers to 293 * 4 (point right after the 293 32-bit registers)
- Set SVGA_FIFO_MAX to the FIFO size
- Set SVGA_REG_CONFIG_DONE to 1
To sequentially write data to the FIFO the driver has to:
- Write the data to the FIFO address + value of SVGA_FIFO_NEXT_CMD (Warning! SVGA_FIFO_NEXT_CMD provides the offset in bytes)
- Increment SVGA_FIFO_NEXT_CMD by 4
To write a command, the driver has to first sequentially write its ID and then the operands to the FIFO.