drivers/mtd/chips/cfi_cmdset_0001.c

Source file repositories/reference/linux-study-clean/drivers/mtd/chips/cfi_cmdset_0001.c

File Facts

System
Linux kernel
Corpus path
drivers/mtd/chips/cfi_cmdset_0001.c
Extension
.c
Size
77111 bytes
Lines
2706
Domain
Driver Families
Bucket
drivers/mtd
Inferred role
Driver Families: exported/initcall integration point
Status
integration 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

if (extp->NumProtectionFields) {
			struct cfi_intelext_otpinfo *otp =
				(struct cfi_intelext_otpinfo *)&extp->extra[0];

			extra_size += (extp->NumProtectionFields - 1) *
				sizeof(struct cfi_intelext_otpinfo);

			if (extp_size >= sizeof(*extp) + extra_size) {
				int i;

				/* Do some byteswapping if necessary */
				for (i = 0; i < extp->NumProtectionFields - 1; i++) {
					otp->ProtRegAddr = le32_to_cpu(otp->ProtRegAddr);
					otp->FactGroups = le16_to_cpu(otp->FactGroups);
					otp->UserGroups = le16_to_cpu(otp->UserGroups);
					otp++;
				}
			}
		}
	}

	if (extp->MinorVersion >= '1') {
		/* Burst Read info */
		extra_size += 2;
		if (extp_size < sizeof(*extp) + extra_size)
			goto need_more;
		extra_size += extp->extra[extra_size - 1];
	}

	if (extp->MinorVersion >= '3') {
		int nb_parts, i;

		/* Number of hardware-partitions */
		extra_size += 1;
		if (extp_size < sizeof(*extp) + extra_size)
			goto need_more;
		nb_parts = extp->extra[extra_size - 1];

		/* skip the sizeof(partregion) field in CFI 1.4 */
		if (extp->MinorVersion >= '4')
			extra_size += 2;

		for (i = 0; i < nb_parts; i++) {
			struct cfi_intelext_regioninfo *rinfo;
			rinfo = (struct cfi_intelext_regioninfo *)&extp->extra[extra_size];
			extra_size += sizeof(*rinfo);
			if (extp_size < sizeof(*extp) + extra_size)
				goto need_more;
			rinfo->NumIdentPartitions=le16_to_cpu(rinfo->NumIdentPartitions);
			extra_size += (rinfo->NumBlockTypes - 1)
				      * sizeof(struct cfi_intelext_blockinfo);
		}

		if (extp->MinorVersion >= '4')
			extra_size += sizeof(struct cfi_intelext_programming_regioninfo);

		if (extp_size < sizeof(*extp) + extra_size) {
			need_more:
			extp_size = sizeof(*extp) + extra_size;
			kfree(extp);
			if (extp_size > 4096) {
				printk(KERN_ERR
					"%s: cfi_pri_intelext is too fat\n",
					__func__);
				return NULL;
			}
			goto again;
		}
	}

	return extp;
}

struct mtd_info *cfi_cmdset_0001(struct map_info *map, int primary)
{
	struct cfi_private *cfi = map->fldrv_priv;
	struct mtd_info *mtd;
	int i;

	mtd = kzalloc_obj(*mtd);
	if (!mtd)
		return NULL;
	mtd->priv = map;
	mtd->type = MTD_NORFLASH;

	/* Fill in the default mtd operations */
	mtd->_erase   = cfi_intelext_erase_varsize;
	mtd->_read    = cfi_intelext_read;
	mtd->_write   = cfi_intelext_write_words;
	mtd->_sync    = cfi_intelext_sync;

Annotation

Implementation Notes