drivers/mmc/core/sdio_cis.c

Source file repositories/reference/linux-study-clean/drivers/mmc/core/sdio_cis.c

File Facts

System
Linux kernel
Corpus path
drivers/mmc/core/sdio_cis.c
Extension
.c
Size
9442 bytes
Lines
433
Domain
Driver Families
Bucket
drivers/mmc
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

struct cis_tpl {
	unsigned char code;
	unsigned char min_size;
	tpl_parse_t *parse;
};

static int cis_tpl_parse(struct mmc_card *card, struct sdio_func *func,
			 const char *tpl_descr,
			 const struct cis_tpl *tpl, int tpl_count,
			 unsigned char code,
			 const unsigned char *buf, unsigned size)
{
	int i, ret;

	/* look for a matching code in the table */
	for (i = 0; i < tpl_count; i++, tpl++) {
		if (tpl->code == code)
			break;
	}
	if (i < tpl_count) {
		if (size >= tpl->min_size) {
			if (tpl->parse)
				ret = tpl->parse(card, func, buf, size);
			else
				ret = -EILSEQ;	/* known tuple, not parsed */
		} else {
			/* invalid tuple */
			ret = -EINVAL;
		}
		if (ret && ret != -EILSEQ && ret != -ENOENT) {
			pr_err("%s: bad %s tuple 0x%02x (%u bytes)\n",
			       mmc_hostname(card->host), tpl_descr, code, size);
		}
	} else {
		/* unknown tuple */
		ret = -ENOENT;
	}

	return ret;
}

static int cistpl_funce_common(struct mmc_card *card, struct sdio_func *func,
			       const unsigned char *buf, unsigned size)
{
	/* Only valid for the common CIS (function 0) */
	if (func)
		return -EINVAL;

	/* TPLFE_FN0_BLK_SIZE */
	card->cis.blksize = buf[1] | (buf[2] << 8);

	/* TPLFE_MAX_TRAN_SPEED */
	card->cis.max_dtr = speed_val[(buf[3] >> 3) & 15] *
			    speed_unit[buf[3] & 7];

	return 0;
}

static int cistpl_funce_func(struct mmc_card *card, struct sdio_func *func,
			     const unsigned char *buf, unsigned size)
{
	unsigned vsn;
	unsigned min_size;

	/* Only valid for the individual function's CIS (1-7) */
	if (!func)
		return -EINVAL;

	/*
	 * This tuple has a different length depending on the SDIO spec
	 * version.
	 */
	vsn = func->card->cccr.sdio_vsn;
	min_size = (vsn == SDIO_SDIO_REV_1_00) ? 28 : 42;

	if (size == 28 && vsn == SDIO_SDIO_REV_1_10) {
		pr_warn("%s: card has broken SDIO 1.1 CIS, forcing SDIO 1.0\n",
			mmc_hostname(card->host));
		vsn = SDIO_SDIO_REV_1_00;
	} else if (size < min_size) {
		return -EINVAL;
	}

	/* TPLFE_MAX_BLK_SIZE */
	func->max_blksize = buf[12] | (buf[13] << 8);

	/* TPLFE_ENABLE_TIMEOUT_VAL, present in ver 1.1 and above */
	if (vsn > SDIO_SDIO_REV_1_00)
		func->enable_timeout = (buf[28] | (buf[29] << 8)) * 10;
	else

Annotation

Implementation Notes