func: 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;
  
  }
  