Page MenuHomeFreeBSD

D19674.1775511247.diff
No OneTemporary

Size
16 KB
Referenced Files
None
Subscribers
None

D19674.1775511247.diff

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

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)

Event Timeline