func: uint8_t sd_read_data(SDState *sd)
  
  {
  
      /* TODO: Append CRCs */
  
      uint8_t ret;
  
      int io_len;
  
  
  
      if (!sd->bdrv || !bdrv_is_inserted(sd->bdrv) || !sd->enable)
  
          return 0x00;
  
  
  
      if (sd->state != sd_sendingdata_state) {
  
          fprintf(stderr, "sd_read_data: not in Sending-Data state\n");
  
          return 0x00;
  
      }
  
  
  
      if (sd->card_status & (ADDRESS_ERROR | WP_VIOLATION))
  
          return 0x00;
  
  
  
      io_len = (sd->ocr & (1 << 30)) ? 512 : sd->blk_len;
  
  
  
      switch (sd->current_cmd) {
  
      case 6:	/* CMD6:   SWITCH_FUNCTION */
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= 64)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 9:	/* CMD9:   SEND_CSD */
  
      case 10:	/* CMD10:  SEND_CID */
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= 16)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 11:	/* CMD11:  READ_DAT_UNTIL_STOP */
  
          if (sd->data_offset == 0)
  
              BLK_READ_BLOCK(sd->data_start, io_len);
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= io_len) {
  
              sd->data_start += io_len;
  
              sd->data_offset = 0;
  
              if (sd->data_start + io_len > sd->size) {
  
                  sd->card_status |= ADDRESS_ERROR;
  
                  break;
  
              }
  
          }
  
          break;
  
  
  
      case 13:	/* ACMD13: SD_STATUS */
  
          ret = sd->sd_status[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= sizeof(sd->sd_status))
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 17:	/* CMD17:  READ_SINGLE_BLOCK */
  
          if (sd->data_offset == 0)
  
              BLK_READ_BLOCK(sd->data_start, io_len);
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= io_len)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 18:	/* CMD18:  READ_MULTIPLE_BLOCK */
  
          if (sd->data_offset == 0)
  
              BLK_READ_BLOCK(sd->data_start, io_len);
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= io_len) {
  
              sd->data_start += io_len;
  
              sd->data_offset = 0;
  
              if (sd->data_start + io_len > sd->size) {
  
                  sd->card_status |= ADDRESS_ERROR;
  
                  break;
  
              }
  
          }
  
          break;
  
  
  
      case 22:	/* ACMD22: SEND_NUM_WR_BLOCKS */
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= 4)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 30:	/* CMD30:  SEND_WRITE_PROT */
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= 4)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 51:	/* ACMD51: SEND_SCR */
  
          ret = sd->scr[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= sizeof(sd->scr))
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      case 56:	/* CMD56:  GEN_CMD */
  
          if (sd->data_offset == 0)
  
              APP_READ_BLOCK(sd->data_start, sd->blk_len);
  
          ret = sd->data[sd->data_offset ++];
  
  
  
          if (sd->data_offset >= sd->blk_len)
  
              sd->state = sd_transfer_state;
  
          break;
  
  
  
      default:
  
          fprintf(stderr, "sd_read_data: unknown command\n");
  
          return 0x00;
  
      }
  
  
  
      return ret;
  
  }
  