func: void ide_atapi_cmd(IDEState *s)
  
  {
  
      uint8_t *buf;
  
  
  
      buf = s->io_buffer;
  
  #ifdef DEBUG_IDE_ATAPI
  
      {
  
          int i;
  
          printf("ATAPI limit=0x%x packet:", s->lcyl | (s->hcyl << 8));
  
          for(i = 0; i < ATAPI_PACKET_SIZE; i++) {
  
              printf(" %02x", buf[i]);
  
          }
  
          printf("\n");
  
      }
  
  #endif
  
      /*
  
       * If there's a UNIT_ATTENTION condition pending, only command flagged with
  
       * ALLOW_UA are allowed to complete. with other commands getting a CHECK
  
       * condition response unless a higher priority status, defined by the drive
  
       * here, is pending.
  
       */
  
      if (s->sense_key == UNIT_ATTENTION &&
  
          !(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA)) {
  
          ide_atapi_cmd_check_status(s);
  
          return;
  
      }
  
      /*
  
       * When a CD gets changed, we have to report an ejected state and
  
       * then a loaded state to guests so that they detect tray
  
       * open/close and media change events.  Guests that do not use
  
       * GET_EVENT_STATUS_NOTIFICATION to detect such tray open/close
  
       * states rely on this behavior.
  
       */
  
      if (!(atapi_cmd_table[s->io_buffer[0]].flags & ALLOW_UA) &&
  
          !s->tray_open && bdrv_is_inserted(s->bs) && s->cdrom_changed) {
  
  
  
          if (s->cdrom_changed == 1) {
  
              ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
  
              s->cdrom_changed = 2;
  
          } else {
  
              ide_atapi_cmd_error(s, UNIT_ATTENTION, ASC_MEDIUM_MAY_HAVE_CHANGED);
  
              s->cdrom_changed = 0;
  
          }
  
  
  
          return;
  
      }
  
  
  
      /* Report a Not Ready condition if appropriate for the command */
  
      if ((atapi_cmd_table[s->io_buffer[0]].flags & CHECK_READY) &&
  
          (!media_present(s) || !bdrv_is_inserted(s->bs)))
  
      {
  
          ide_atapi_cmd_error(s, NOT_READY, ASC_MEDIUM_NOT_PRESENT);
  
          return;
  
      }
  
  
  
      /* Execute the command */
  
      if (atapi_cmd_table[s->io_buffer[0]].handler) {
  
          atapi_cmd_table[s->io_buffer[0]].handler(s, buf);
  
          return;
  
      }
  
  
  
      ide_atapi_cmd_error(s, ILLEGAL_REQUEST, ASC_ILLEGAL_OPCODE);
  
  }
  