static uint32_t sdhci_read(SDHCIState *s, unsigned int offset, unsigned size) { uint32_t ret = 0; switch (offset & ~0x3) { case SDHC_SYSAD: ret = s->sdmasysad; break; case SDHC_BLKSIZE: ret = s->blksize | (s->blkcnt << 16); break; case SDHC_ARGUMENT: ret = s->argument; break; case SDHC_TRNMOD: ret = s->trnmod | (s->cmdreg << 16); break; case SDHC_RSPREG0 ... SDHC_RSPREG3: ret = s->rspreg[((offset & ~0x3) - SDHC_RSPREG0) >> 2]; break; case SDHC_BDATA: if (sdhci_buff_access_is_sequential(s, offset - SDHC_BDATA)) { ret = SDHCI_GET_CLASS(s)->bdata_read(s, size); DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, offset, ret, ret); return ret; } break; case SDHC_PRNSTS: ret = s->prnsts; break; case SDHC_HOSTCTL: ret = s->hostctl | (s->pwrcon << 8) | (s->blkgap << 16) | (s->wakcon << 24); break; case SDHC_CLKCON: ret = s->clkcon | (s->timeoutcon << 16); break; case SDHC_NORINTSTS: ret = s->norintsts | (s->errintsts << 16); break; case SDHC_NORINTSTSEN: ret = s->norintstsen | (s->errintstsen << 16); break; case SDHC_NORINTSIGEN: ret = s->norintsigen | (s->errintsigen << 16); break; case SDHC_ACMD12ERRSTS: ret = s->acmd12errsts; break; case SDHC_CAPAREG: ret = s->capareg; break; case SDHC_MAXCURR: ret = s->maxcurr; break; case SDHC_ADMAERR: ret = s->admaerr; break; case SDHC_ADMASYSADDR: ret = (uint32_t)s->admasysaddr; break; case SDHC_ADMASYSADDR + 4: ret = (uint32_t)(s->admasysaddr >> 32); break; case SDHC_SLOT_INT_STATUS: ret = (SD_HOST_SPECv2_VERS << 16) | sdhci_slotint(s); break; default: ERRPRINT("bad %ub read: addr[0x%04x]\n", size, offset); break; } ret >>= (offset & 0x3) * 8; ret &= (1ULL << (size * 8)) - 1; DPRINT_L2("read %ub: addr[0x%04x] -> %u(0x%x)\n", size, offset, ret, ret); return ret; }