summaryrefslogtreecommitdiffstats
path: root/sys/dev/mmc
diff options
context:
space:
mode:
authormav <mav@FreeBSD.org>2008-10-09 20:09:56 +0000
committermav <mav@FreeBSD.org>2008-10-09 20:09:56 +0000
commit8e7aede58a084378a6280bc959e27333ea6864da (patch)
tree1a343c055d8b92487f699a3b43134b7d2f38b268 /sys/dev/mmc
parent3f76f9879a26016976a8b198854f8be6daab800d (diff)
downloadFreeBSD-src-8e7aede58a084378a6280bc959e27333ea6864da.zip
FreeBSD-src-8e7aede58a084378a6280bc959e27333ea6864da.tar.gz
Add high capacity MMC cards support.
Diffstat (limited to 'sys/dev/mmc')
-rw-r--r--sys/dev/mmc/mmc.c22
1 files changed, 17 insertions, 5 deletions
diff --git a/sys/dev/mmc/mmc.c b/sys/dev/mmc/mmc.c
index 172f5e4..12b171f 100644
--- a/sys/dev/mmc/mmc.c
+++ b/sys/dev/mmc/mmc.c
@@ -93,7 +93,8 @@ struct mmc_ivars {
u_char read_only; /* True when the device is read-only */
u_char bus_width; /* Bus width to use */
u_char timing; /* Bus timing support */
- u_char high_cap; /* High Capacity card */
+ u_char high_cap; /* High Capacity card (block addressed) */
+ uint32_t sec_count; /* Card capacity in 512byte blocks */
uint32_t tran_speed; /* Max speed in normal mode */
uint32_t hs_tran_speed; /* Max speed in high speed mode */
};
@@ -1011,7 +1012,7 @@ mmc_discover_cards(struct mmc_softc *sc)
{
struct mmc_ivars *ivar;
int err;
- uint32_t resp;
+ uint32_t resp, sec_count;
device_t child;
uint16_t rca = 2;
u_char switch_res[64];
@@ -1039,6 +1040,7 @@ mmc_discover_cards(struct mmc_softc *sc)
/* Get card CSD. */
mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
mmc_decode_csd_sd(ivar->raw_csd, &ivar->csd);
+ ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE;
if (ivar->csd.csd_structure > 0)
ivar->high_cap = 1;
ivar->tran_speed = ivar->csd.tran_speed;
@@ -1071,18 +1073,28 @@ mmc_discover_cards(struct mmc_softc *sc)
/* Get card CSD. */
mmc_send_csd(sc, ivar->rca, ivar->raw_csd);
mmc_decode_csd_mmc(ivar->raw_csd, &ivar->csd);
+ ivar->sec_count = ivar->csd.capacity / MMC_SECTOR_SIZE;
ivar->tran_speed = ivar->csd.tran_speed;
/* Only MMC >= 4.x cards support EXT_CSD. */
if (ivar->csd.spec_vers >= 4) {
/* Card must be selected to fetch EXT_CSD. */
mmc_select_card(sc, ivar->rca);
mmc_send_ext_csd(sc, ivar->raw_ext_csd);
+ /* Handle extended capacity from EXT_CSD */
+ sec_count = ivar->raw_ext_csd[EXT_CSD_SEC_CNT] +
+ (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 1] << 8) +
+ (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 2] << 16) +
+ (ivar->raw_ext_csd[EXT_CSD_SEC_CNT + 3] << 24);
+ if (sec_count != 0) {
+ ivar->sec_count = sec_count;
+ ivar->high_cap = 1;
+ }
/* Get card speed in high speed mode. */
ivar->timing = bus_timing_hs;
- if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE]
+ if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
& EXT_CSD_CARD_TYPE_52)
ivar->hs_tran_speed = 52000000;
- else if (((uint8_t *)(ivar->raw_ext_csd))[EXT_CSD_CARD_TYPE]
+ else if (ivar->raw_ext_csd[EXT_CSD_CARD_TYPE]
& EXT_CSD_CARD_TYPE_26)
ivar->hs_tran_speed = 26000000;
else
@@ -1234,7 +1246,7 @@ mmc_read_ivar(device_t bus, device_t child, int which, u_char *result)
*(int *)result = ivar->csd.dsr_imp;
break;
case MMC_IVAR_MEDIA_SIZE:
- *(off_t *)result = ivar->csd.capacity / MMC_SECTOR_SIZE;
+ *(off_t *)result = ivar->sec_count;
break;
case MMC_IVAR_RCA:
*(int *)result = ivar->rca;
OpenPOWER on IntegriCloud