static void vmsvga_fifo_run(struct vmsvga_state_s *s) { uint32_t cmd, colour; int args, len; int x, y, dx, dy, width, height; struct vmsvga_cursor_definition_s cursor; uint32_t cmd_start; len = vmsvga_fifo_length(s); while (len > 0) { /* May need to go back to the start of the command if incomplete */ cmd_start = s->cmd->stop; switch (cmd = vmsvga_fifo_read(s)) { case SVGA_CMD_UPDATE: case SVGA_CMD_UPDATE_VERBOSE: len -= 5; if (len < 0) { goto rewind; } x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); width = vmsvga_fifo_read(s); height = vmsvga_fifo_read(s); vmsvga_update_rect_delayed(s, x, y, width, height); break; case SVGA_CMD_RECT_FILL: len -= 6; if (len < 0) { goto rewind; } colour = vmsvga_fifo_read(s); x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); width = vmsvga_fifo_read(s); height = vmsvga_fifo_read(s); #ifdef HW_FILL_ACCEL if (vmsvga_fill_rect(s, colour, x, y, width, height) == 0) { break; } #endif args = 0; goto badcmd; case SVGA_CMD_RECT_COPY: len -= 7; if (len < 0) { goto rewind; } x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); dx = vmsvga_fifo_read(s); dy = vmsvga_fifo_read(s); width = vmsvga_fifo_read(s); height = vmsvga_fifo_read(s); #ifdef HW_RECT_ACCEL if (vmsvga_copy_rect(s, x, y, dx, dy, width, height) == 0) { break; } #endif args = 0; goto badcmd; case SVGA_CMD_DEFINE_CURSOR: len -= 8; if (len < 0) { goto rewind; } cursor.id = vmsvga_fifo_read(s); cursor.hot_x = vmsvga_fifo_read(s); cursor.hot_y = vmsvga_fifo_read(s); cursor.width = x = vmsvga_fifo_read(s); cursor.height = y = vmsvga_fifo_read(s); vmsvga_fifo_read(s); cursor.bpp = vmsvga_fifo_read(s); args = SVGA_BITMAP_SIZE(x, y) + SVGA_PIXMAP_SIZE(x, y, cursor.bpp); if (SVGA_BITMAP_SIZE(x, y) > sizeof cursor.mask || SVGA_PIXMAP_SIZE(x, y, cursor.bpp) > sizeof cursor.image) { goto badcmd; } len -= args; if (len < 0) { goto rewind; } for (args = 0; args < SVGA_BITMAP_SIZE(x, y); args++) { cursor.mask[args] = vmsvga_fifo_read_raw(s); } for (args = 0; args < SVGA_PIXMAP_SIZE(x, y, cursor.bpp); args++) { cursor.image[args] = vmsvga_fifo_read_raw(s); } #ifdef HW_MOUSE_ACCEL vmsvga_cursor_define(s, &cursor); break; #else args = 0; goto badcmd; #endif /* * Other commands that we at least know the number of arguments * for so we can avoid FIFO desync if driver uses them illegally. */ case SVGA_CMD_DEFINE_ALPHA_CURSOR: len -= 6; if (len < 0) { goto rewind; } vmsvga_fifo_read(s); vmsvga_fifo_read(s); vmsvga_fifo_read(s); x = vmsvga_fifo_read(s); y = vmsvga_fifo_read(s); args = x * y; goto badcmd; case SVGA_CMD_RECT_ROP_FILL: args = 6; goto badcmd; case SVGA_CMD_RECT_ROP_COPY: args = 7; goto badcmd; case SVGA_CMD_DRAW_GLYPH_CLIPPED: len -= 4; if (len < 0) { goto rewind; } vmsvga_fifo_read(s); vmsvga_fifo_read(s); args = 7 + (vmsvga_fifo_read(s) >> 2); goto badcmd; case SVGA_CMD_SURFACE_ALPHA_BLEND: args = 12; goto badcmd; /* * Other commands that are not listed as depending on any * CAPABILITIES bits, but are not described in the README either. */ case SVGA_CMD_SURFACE_FILL: case SVGA_CMD_SURFACE_COPY: case SVGA_CMD_FRONT_ROP_FILL: case SVGA_CMD_FENCE: case SVGA_CMD_INVALID_CMD: break; /* Nop */ default: args = 0; badcmd: len -= args; if (len < 0) { goto rewind; } while (args--) { vmsvga_fifo_read(s); } printf("%s: Unknown command 0x%02x in SVGA command FIFO\n", __func__, cmd); break; rewind: s->cmd->stop = cmd_start; break; } } s->syncing = 0; }