svn commit: r183731 - head/sys/dev/mmc

Alexander Motin mav at FreeBSD.org
Thu Oct 9 20:09:57 UTC 2008


Author: mav
Date: Thu Oct  9 20:09:56 2008
New Revision: 183731
URL: http://svn.freebsd.org/changeset/base/183731

Log:
  Add high capacity MMC cards support.

Modified:
  head/sys/dev/mmc/mmc.c

Modified: head/sys/dev/mmc/mmc.c
==============================================================================
--- head/sys/dev/mmc/mmc.c	Thu Oct  9 20:00:17 2008	(r183730)
+++ head/sys/dev/mmc/mmc.c	Thu Oct  9 20:09:56 2008	(r183731)
@@ -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 chi
 		*(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;


More information about the svn-src-head mailing list