Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F144570500
D19674.1775511247.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D19674.1775511247.diff
View Options
Index: sbin/camcontrol/camcontrol.c
===================================================================
--- sbin/camcontrol/camcontrol.c
+++ sbin/camcontrol/camcontrol.c
@@ -7791,6 +7791,8 @@
mmc_d.len = mmc_data_len;
mmc_d.data = mmc_data;
mmc_d.flags = MMC_DATA_READ;
+ mmc_d.block_size = 0;
+ mmc_d.block_count = 0;
} else flags |= CAM_DIR_NONE;
cam_fill_mmcio(&ccb->mmcio,
Index: sys/arm/allwinner/aw_mmc.c
===================================================================
--- sys/arm/allwinner/aw_mmc.c
+++ sys/arm/allwinner/aw_mmc.c
@@ -57,6 +57,8 @@
#include "opt_mmccam.h"
+#define DEBUG 1
+
#ifdef MMCCAM
#include <cam/cam.h>
#include <cam/cam_ccb.h>
@@ -1104,8 +1106,20 @@
cmdreg |= AW_MMC_CMDR_DIR_WRITE;
blksz = min(cmd->data->len, MMC_SECTOR_SIZE);
+#ifdef MMCCAM
+ if (cmd->data->block_count > 0) {
+ AW_MMC_WRITE_4(sc, AW_MMC_BKSR, cmd->data->block_size);
+ /* This is a byte count register, not block
+ * count?! */
+ AW_MMC_WRITE_4(sc, AW_MMC_BYCR, cmd->data->len);
+ } else {
+ AW_MMC_WRITE_4(sc, AW_MMC_BKSR, blksz);
+ AW_MMC_WRITE_4(sc, AW_MMC_BYCR, cmd->data->len);
+ }
+#else
AW_MMC_WRITE_4(sc, AW_MMC_BKSR, blksz);
AW_MMC_WRITE_4(sc, AW_MMC_BYCR, cmd->data->len);
+#endif
} else {
imask |= AW_MMC_INT_CMD_DONE;
}
Index: sys/cam/mmc/mmc_da.c
===================================================================
--- sys/cam/mmc/mmc_da.c
+++ sys/cam/mmc/mmc_da.c
@@ -843,6 +843,7 @@
struct mmc_data d;
KASSERT(buf_len == 512, ("Buffer for ext csd must be 512 bytes"));
+ memset(&d, 0, sizeof(d));
d.data = rawextcsd;
d.len = buf_len;
d.flags = MMC_DATA_READ;
@@ -989,6 +990,7 @@
uint32_t arg;
memset(res, 0, 64);
+ memset(&mmc_d, 0, sizeof(mmc_d));
mmc_d.len = 64;
mmc_d.data = res;
mmc_d.flags = MMC_DATA_READ;
@@ -1777,6 +1779,7 @@
mmcio->cmd.data->data = bp->bio_data;
mmcio->cmd.data->len = 512 * count;
mmcio->cmd.data->flags = (bp->bio_cmd == BIO_READ ? MMC_DATA_READ : MMC_DATA_WRITE);
+ mmcio->cmd.data->block_count = mmcio->cmd.data->block_size = 0;
/* Direct h/w to issue CMD12 upon completion */
if (count > 1) {
mmcio->cmd.data->flags |= MMC_DATA_MULTI;
Index: sys/dev/mmc/mmcreg.h
===================================================================
--- sys/dev/mmc/mmcreg.h
+++ sys/dev/mmc/mmcreg.h
@@ -190,6 +190,8 @@
struct mmc_data {
size_t len; /* size of the data */
+ size_t block_size; /* block size for CMD53 */
+ size_t block_count; /* block count for CMD53 */
size_t xfer_len;
void *data; /* data buffer */
uint32_t flags;
@@ -546,7 +548,11 @@
#define SD_IO_RW_LEN(x) (((x) & 0xFF) << 0)
#define SD_IOE_RW_LEN(x) (((x) & 0x1FF) << 0)
+#define SD_IOE_RW_ADR(x) (((x) & 0x1FFFF) << 9)
+#define SD_IOE_RW_INCR (1u << 26)
#define SD_IOE_RW_BLK (1u << 27)
+#define SD_IOE_RW_FUNC(x) (((x) & 0x7) << 28)
+#define SD_IOE_RW_WR (1u << 31)
/* Card Common Control Registers (CCCR) */
#define SD_IO_CCCR_START 0x00000
@@ -561,11 +567,15 @@
#define CCCR_BUS_WIDTH_4 (1 << 1)
#define CCCR_BUS_WIDTH_1 (1 << 0)
#define SD_IO_CCCR_CARDCAP 0x08
-#define SD_IO_CCCR_CISPTR 0x09 /* XXX 9-10, 10-11, or 9-12 */
-
+#define CCCR_CC_SMB (1 << 1)
+#define SD_IO_CCCR_CISPTR 0x09 /* 0x09 - 0x0B */
+#define SD_IO_CCCR_FN0_BLKSZ 0x10 /* 0x10 - 0x11 */
/* Function Basic Registers (FBR) */
#define SD_IO_FBR_START 0x00100
#define SD_IO_FBR_SIZE 0x00700
+#define SD_IO_FBR_START_F(n) (SD_IO_FBR_START + (n-1) * 0x00100)
+#define SD_IO_FBR_CIS_OFFSET 0x9
+#define SD_IO_FBR_IOBLKSZ 0x10
/* Card Information Structure (CIS) */
#define SD_IO_CIS_START 0x01000
Index: sys/dev/sdhci/sdhci.c
===================================================================
--- sys/dev/sdhci/sdhci.c
+++ sys/dev/sdhci/sdhci.c
@@ -1623,9 +1623,10 @@
return;
mode = SDHCI_TRNS_BLK_CNT_EN;
- if (data->len > 512) {
+ if (data->len > 512 || data->block_count > 1) {
mode |= SDHCI_TRNS_MULTI;
- if (__predict_true(
+ slot_printf(slot, "Enabling SDHCI_TRNS_MULTI\n");
+ if (data->block_count == 0 && __predict_true(
#ifdef MMCCAM
slot->ccb->mmcio.stop.opcode == MMC_STOP_TRANSMISSION &&
#else
@@ -1888,11 +1889,26 @@
}
/* Current data offset for both PIO and DMA. */
slot->offset = 0;
+
+#ifdef MMCCAM
+ if (data->block_count > 0) {
+ blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, data->block_size);
+ blkcnt = data->block_count;
+ if (__predict_false(sdhci_debug > 0))
+ slot_printf(slot, "SDIO Custom block params: blksz: 0x%08x | Blk cnt: 0x%08x\n",
+ blksz, blkcnt);
+ } else {
+ /* Set block size and request border interrupts on the SDMA boundary. */
+ blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512));
+ blkcnt = howmany(data->len, 512);
+ }
+#else
/* Set block size and request border interrupts on the SDMA boundary. */
blksz = SDHCI_MAKE_BLKSZ(slot->sdma_boundary, ulmin(data->len, 512));
+ blkcnt = howmany(data->len, 512);
+#endif
WR2(slot, SDHCI_BLOCK_SIZE, blksz);
/* Set block count. */
- blkcnt = howmany(data->len, 512);
WR2(slot, SDHCI_BLOCK_COUNT, blkcnt);
if (__predict_false(sdhci_debug > 1))
slot_printf(slot, "Blk size: 0x%08x | Blk cnt: 0x%08x\n",
@@ -2771,10 +2787,12 @@
}
*/
if (__predict_false(sdhci_debug > 1)) {
- slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x\n",
- mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags,
- mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0,
- mmcio->cmd.data != NULL ? mmcio->cmd.data->flags: 0);
+ slot_printf(slot, "CMD%u arg %#x flags %#x dlen %u dflags %#x blksz=%zu blkcnt=%zu\n",
+ mmcio->cmd.opcode, mmcio->cmd.arg, mmcio->cmd.flags,
+ mmcio->cmd.data != NULL ? (unsigned int) mmcio->cmd.data->len : 0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->flags: 0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->block_size:0,
+ mmcio->cmd.data != NULL ? mmcio->cmd.data->block_count:0);
}
if (mmcio->cmd.data != NULL) {
if (mmcio->cmd.data->len == 0 || mmcio->cmd.data->flags == 0)
Index: usr.bin/sdiotool/cam_sdio.h
===================================================================
--- usr.bin/sdiotool/cam_sdio.h
+++ usr.bin/sdiotool/cam_sdio.h
@@ -71,12 +71,14 @@
uint8_t *resp);
int
sdio_rw_extended(struct cam_device *dev,
- uint8_t func_number,
- uint32_t addr,
- uint8_t is_write,
- caddr_t data, size_t datalen,
- uint8_t is_increment,
- uint16_t blk_count);
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_increment,
+ uint8_t is_write,
+ caddr_t data,
+ size_t blk_size,
+ uint16_t blk_count);
+
uint8_t sdio_read_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret);
int sdio_write_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint8_t val);
uint16_t sdio_read_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret);
@@ -95,3 +97,4 @@
int sdio_func_read_cis(struct cam_device *dev, uint8_t func_number,
uint32_t cis_addr, struct cis_info *info);
int sdio_card_set_bus_width(struct cam_device *dev, enum mmc_bus_width bw);
+int sdio_func_set_block_size(struct cam_device *dev, uint8_t func_number, uint16_t block_size);
Index: usr.bin/sdiotool/cam_sdio.c
===================================================================
--- usr.bin/sdiotool/cam_sdio.c
+++ usr.bin/sdiotool/cam_sdio.c
@@ -86,17 +86,26 @@
* CMD53 -- IO_RW_EXTENDED
* Use to read or write memory blocks
*
- * is_increment=1: FIFO mode
- * blk_count > 0: block mode
+ * is_increment: 0 for FIFO mode, 1 for normal.
+ * blk_size: block size to use for transfer.
+ * blk_count: how many blocks of size blk_size to operate on. 0 means
+ * use byte mode.
+ *
+ * This function does not check if the supplied block size is actually
+ * supported by the given SDIO function.
+ * Also this function does not attempt to change an effective block
+ * size for the given SDIO function.
+ * The total transfer size will be blk_size * blk_count.
*/
int
sdio_rw_extended(struct cam_device *dev,
- uint8_t func_number,
- uint32_t addr,
- uint8_t is_write,
- caddr_t data, size_t datalen,
- uint8_t is_increment,
- uint16_t blk_count) {
+ uint8_t func_number,
+ uint32_t addr,
+ uint8_t is_increment,
+ uint8_t is_write,
+ caddr_t data,
+ size_t blk_size,
+ uint16_t blk_count) {
union ccb *ccb;
uint32_t flags;
uint32_t arg;
@@ -105,8 +114,14 @@
struct mmc_data mmcd;
int retval = 0;
- if (blk_count != 0) {
- warnx("%s: block mode is not supported yet", __func__);
+ warnx("sdio_rw_extended(fn=%d, addr=0x%x, incr=%d, write=%d, datap=%p, blk_size=%zu, blk_count=%d)", func_number, addr, is_increment, is_write, data, blk_size, blk_count);
+ if (blk_count > 512) {
+ warnx("%s: cannot operate on more than 512 blocks", __func__);
+ return (-1);
+ }
+
+ if (blk_size > 1 && blk_count > 511) {
+ warnx("%s: cannot operate on more than 511 blocks in block mode", __func__);
return (-1);
}
@@ -119,25 +134,42 @@
sizeof(union ccb) - sizeof(struct ccb_hdr));
flags = MMC_RSP_R5 | MMC_CMD_ADTC;
- arg = SD_IO_RW_FUNC(func_number) | SD_IO_RW_ADR(addr) |
- SD_IOE_RW_LEN(datalen);
+ arg = SD_IOE_RW_FUNC(func_number) | SD_IOE_RW_ADR(addr);
+
+ /* Block mode if needed */
+ if (blk_count > 0) {
+ arg |= SD_IOE_RW_BLK;
+ /*
+ * In block mode, putting 0 here means "infinite block count",
+ * we don't support this.
+ */
+ arg |= SD_IOE_RW_LEN(blk_count);
+ } else {
+ /*
+ * In byte mode, 0 means "512 bytes".
+ */
+ arg |= blk_size == 512 ? 0 : SD_IOE_RW_LEN(blk_size);
+ }
if (is_increment)
- arg |= SD_IO_RW_INCR;
+ arg |= SD_IOE_RW_INCR;
mmcd.data = data;
- mmcd.len = datalen;
+ mmcd.len = blk_count > 0 ? blk_size * blk_count : blk_size;
+ mmcd.block_size = blk_size;
+ mmcd.block_count = blk_count;
mmcd.xfer_len = 0; /* not used by MMCCAM */
mmcd.mrq = NULL; /* not used by MMCCAM */
if (is_write) {
- arg |= SD_IO_RW_WR;
+ arg |= SD_IOE_RW_WR;
cam_flags = CAM_DIR_OUT;
mmcd.flags = MMC_DATA_WRITE;
} else {
cam_flags = CAM_DIR_IN;
mmcd.flags = MMC_DATA_READ;
}
+ printf("arg=%#x\n", arg);
cam_fill_mmcio(&ccb->mmcio,
/*retries*/ 0,
/*cbfcnp*/ NULL,
@@ -166,6 +198,35 @@
return (retval);
}
+int
+sdio_func_set_block_size(struct cam_device *dev, uint8_t func_number, uint16_t block_size) {
+ uint32_t addr;
+ int ret;
+
+ uint8_t card_cap = sdio_read_1(dev, 0, SD_IO_CCCR_START + SD_IO_CCCR_CARDCAP, &ret);
+ if (!(card_cap & CCCR_CC_SMB)) {
+ warnx("%s: block mode is not supported, card cap = %x", __func__, card_cap);
+ return (-1);
+ }
+
+ if (block_size > 2048) {
+ warnx("%s: block size cannot exceed 2048", __func__);
+ return (-1);
+ }
+
+ if (func_number == 0) {
+ addr = SD_IO_CCCR_START + SD_IO_CCCR_FN0_BLKSZ;
+ } else {
+ addr = SD_IO_FBR_START_F(func_number) + SD_IO_FBR_IOBLKSZ;
+ }
+
+ if (sdio_write_1(dev, 0, addr, (block_size & 0xFF)) < 0 ||
+ sdio_write_1(dev, 0, addr + 1, (block_size >> 8)) < 0) {
+ warnx("%s: cannot write new block size", __func__);
+ return (-1);
+ }
+ return (0);
+}
int
sdio_read_bool_for_func(struct cam_device *dev, uint32_t addr, uint8_t func_number, uint8_t *is_enab) {
@@ -216,18 +277,18 @@
int
sdio_write_1(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint8_t val) {
uint8_t _val;
- return sdio_rw_direct(dev, func_number, addr, 0, &val, &_val);
+ return sdio_rw_direct(dev, func_number, addr, 1, &val, &_val);
}
uint16_t
sdio_read_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret) {
uint16_t val;
*ret = sdio_rw_extended(dev, func_number, addr,
- /* is_write */ 0,
- /* data */ (caddr_t) &val,
- /* datalen */ sizeof(val),
- /* is_increment */ 1,
- /* blk_count */ 0
+ /* is_increment */ 1,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ sizeof(val),
+ /* blk_count */ 0
);
return val;
}
@@ -236,11 +297,11 @@
int
sdio_write_2(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint16_t val) {
return sdio_rw_extended(dev, func_number, addr,
- /* is_write */ 1,
- /* data */ (caddr_t) &val,
- /* datalen */ sizeof(val),
- /* is_increment */ 1,
- /* blk_count */ 0
+ /* is_increment */ 1,
+ /* is_write */ 1,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ sizeof(val),
+ /* blk_count */ 0
);
}
@@ -248,11 +309,11 @@
sdio_read_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, int *ret) {
uint32_t val;
*ret = sdio_rw_extended(dev, func_number, addr,
- /* is_write */ 0,
- /* data */ (caddr_t) &val,
- /* datalen */ sizeof(val),
- /* is_increment */ 1,
- /* blk_count */ 0
+ /* is_increment */ 1,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ sizeof(val),
+ /* blk_count */ 0
);
return val;
}
@@ -261,11 +322,11 @@
int
sdio_write_4(struct cam_device *dev, uint8_t func_number, uint32_t addr, uint32_t val) {
return sdio_rw_extended(dev, func_number, addr,
- /* is_write */ 1,
- /* data */ (caddr_t) &val,
- /* datalen */ sizeof(val),
- /* is_increment */ 1,
- /* blk_count */ 0
+ /* is_increment */ 1,
+ /* is_write */ 1,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ sizeof(val),
+ /* blk_count */ 0
);
}
Index: usr.bin/sdiotool/sdiotool.c
===================================================================
--- usr.bin/sdiotool/sdiotool.c
+++ usr.bin/sdiotool/sdiotool.c
@@ -486,6 +486,98 @@
}
}
+static void
+cmd53_experiments(struct cam_device *cam_dev) {
+ int ret;
+ uint8_t b0, b1, b2, b3;
+ uint32_t intval;
+ uint8_t val[32];
+
+ /* First set block size = 1 for F0 */
+ printf("Setting block size for F0 to 0...\n");
+ ret = sdio_func_set_block_size(cam_dev, 0, 0);
+ if (ret < 0) {
+ warnx("Cannot set block size = 1 for F0");
+ return;
+ }
+ printf("F0 Block size set to 0\n");
+
+ /* Try to read the same data with CMD52 and CMD53 */
+ b0 = sdio_read_1(cam_dev, 0, 0, &ret);
+ b1 = sdio_read_1(cam_dev, 0, 1, &ret);
+ b2 = sdio_read_1(cam_dev, 0, 2, &ret);
+ b3 = sdio_read_1(cam_dev, 0, 3, &ret);
+ printf("Read values (LE): %02x%02x%02x%02x\n", b3, b2, b1, b0);
+
+ intval = sdio_read_4(cam_dev, 0, 0, &ret);
+ printf("read_4: ret=%d, value=%04x\n", ret, intval);
+
+ /* Aggressive! Try 32 bytes from CCCR */
+ ret = sdio_rw_extended(cam_dev, 0, 0,
+ /* is_increment */ 1,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ sizeof(val),
+ /* blk_count */ 0
+ );
+ if (ret < 0) {
+ warnx("Cannot read in byte mode");
+ return;
+ }
+ printf("Read 32 bytes at once in BYTE mode:\n");
+ hexdump(val, sizeof(val), NULL, 0);
+
+ /* Super-aggressive ! Try reading 1 block of size 32 */
+ ret = sdio_func_set_block_size(cam_dev, 0, 32);
+ if (ret < 0) {
+ warnx("Cannot set non-1 block size for F0");
+ return;
+ }
+ bzero(&val, sizeof(val));
+ ret = sdio_rw_extended(cam_dev, 0, 0,
+ /* is_increment */ 1,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ 32,
+ /* blk_count */ 1
+ );
+ if (ret < 0) {
+ warnx("Cannot read in block mode");
+ return;
+ }
+
+ printf("Read 1 block x 32b in BLOCK mode:\n");
+ hexdump(val, sizeof(val), NULL, 0);
+
+ /* Mega-aggressive! Read 2 blocks of size 16 */
+ ret = sdio_func_set_block_size(cam_dev, 0, 16);
+ if (ret < 0) {
+ warnx("Cannot set non-1 block size for F0");
+ return;
+ }
+ bzero(&val, sizeof(val));
+ ret = sdio_rw_extended(cam_dev, 0, 0,
+ /* is_increment */ 1,
+ /* is_write */ 0,
+ /* data */ (caddr_t) &val,
+ /* blk_size */ 16,
+ /* blk_count */ 2
+ );
+ if (ret < 0) {
+ warnx("Cannot read in block mode");
+ return;
+ }
+
+ printf("Read 2 blocks x 16b in BLOCK mode:\n");
+ hexdump(val, sizeof(val), NULL, 0);
+
+ ret = sdio_func_set_block_size(cam_dev, 0, 0);
+ if (ret < 0) {
+ warnx("Cannot set block size to 0 for F0");
+ return;
+ }
+}
+
int
main(int argc, char **argv) {
char device[] = "pass";
@@ -514,10 +606,13 @@
}
argc -= optind;
argv += optind;
-
if ((cam_dev = cam_open_spec_device(device, unit, O_RDWR, NULL)) == NULL)
errx(1, "Cannot open device");
+ cmd53_experiments(cam_dev);
+ cam_close_spec_device(cam_dev);
+ return 0;
+
get_sdio_card_info(cam_dev, &ci);
/* For now, everything non-broadcom is out of the question */
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Mon, Apr 6, 9:34 PM (10 h, 29 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
28281512
Default Alt Text
D19674.1775511247.diff (16 KB)
Attached To
Mode
D19674: Implement CMD53 support for byte mode and block mode
Attached
Detach File
Event Timeline
Log In to Comment