func: int sd_do_command(SDState *sd, SDRequest *req,
  
                    uint8_t *response) {
  
      uint32_t last_status = sd->card_status;
  
      sd_rsp_type_t rtype;
  
      int rsplen;
  
  
  
      if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable) {
  
          return 0;
  
      }
  
  
  
      if (sd_req_crc_validate(req)) {
  
          sd->card_status |= COM_CRC_ERROR;
  
          rtype = sd_illegal;
  
          goto send_response;
  
      }
  
  
  
      sd->card_status &= ~CARD_STATUS_B;
  
      sd_set_status(sd);
  
  
  
      if (last_status & CARD_IS_LOCKED) {
  
          if (!cmd_valid_while_locked(sd, req)) {
  
              sd->card_status |= ILLEGAL_COMMAND;
  
              fprintf(stderr, "SD: Card is locked\n");
  
              rtype = sd_illegal;
  
              goto send_response;
  
          }
  
      }
  
  
  
      if (last_status & APP_CMD) {
  
          rtype = sd_app_command(sd, *req);
  
          sd->card_status &= ~APP_CMD;
  
      } else
  
          rtype = sd_normal_command(sd, *req);
  
  
  
      if (rtype == sd_illegal) {
  
          sd->card_status |= ILLEGAL_COMMAND;
  
      }
  
  
  
      sd->current_cmd = req->cmd;
  
  
  
  send_response:
  
      switch (rtype) {
  
      case sd_r1:
  
      case sd_r1b:
  
          sd_response_r1_make(sd, response, last_status);
  
          rsplen = 4;
  
          break;
  
  
  
      case sd_r2_i:
  
          memcpy(response, sd->cid, sizeof(sd->cid));
  
          rsplen = 16;
  
          break;
  
  
  
      case sd_r2_s:
  
          memcpy(response, sd->csd, sizeof(sd->csd));
  
          rsplen = 16;
  
          break;
  
  
  
      case sd_r3:
  
          sd_response_r3_make(sd, response);
  
          rsplen = 4;
  
          break;
  
  
  
      case sd_r6:
  
          sd_response_r6_make(sd, response);
  
          rsplen = 4;
  
          break;
  
  
  
      case sd_r7:
  
          sd_response_r7_make(sd, response);
  
          rsplen = 4;
  
          break;
  
  
  
      case sd_r0:
  
      case sd_illegal:
  
      default:
  
          rsplen = 0;
  
          break;
  
      }
  
  
  
  #ifdef DEBUG_SD
  
      if (rsplen) {
  
          int i;
  
          DPRINTF("Response:");
  
          for (i = 0; i < rsplen; i++)
  
              printf(" %02x", response[i]);
  
          printf(" state %d\n", sd->state);
  
      } else {
  
          DPRINTF("No response %d\n", sd->state);
  
      }
  
  #endif
  
  
  
      return rsplen;
  
  }
  