drivers/w1/slaves/w1_ds28e04.c

Source file repositories/reference/linux-study-clean/drivers/w1/slaves/w1_ds28e04.c

File Facts

System
Linux kernel
Corpus path
drivers/w1/slaves/w1_ds28e04.c
Extension
.c
Size
9615 bytes
Lines
418
Domain
Driver Families
Bucket
drivers/w1
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 w1_f1C_data {
	u8	memory[W1_EEPROM_SIZE];
	u32	validcrc;
};

/*
 * Check the file size bounds and adjusts count as needed.
 * This would not be needed if the file size didn't reset to 0 after a write.
 */
static inline size_t w1_f1C_fix_count(loff_t off, size_t count, size_t size)
{
	if (off > size)
		return 0;

	if ((off + count) > size)
		return size - off;

	return count;
}

static int w1_f1C_refresh_block(struct w1_slave *sl, struct w1_f1C_data *data,
				int block)
{
	u8	wrbuf[3];
	int	off = block * W1_PAGE_SIZE;

	if (data->validcrc & (1 << block))
		return 0;

	if (w1_reset_select_slave(sl)) {
		data->validcrc = 0;
		return -EIO;
	}

	wrbuf[0] = W1_F1C_READ_EEPROM;
	wrbuf[1] = off & 0xff;
	wrbuf[2] = off >> 8;
	w1_write_block(sl->master, wrbuf, 3);
	w1_read_block(sl->master, &data->memory[off], W1_PAGE_SIZE);

	/* cache the block if the CRC is valid */
	if (crc16(CRC16_INIT, &data->memory[off], W1_PAGE_SIZE) == CRC16_VALID)
		data->validcrc |= (1 << block);

	return 0;
}

static int w1_f1C_read(struct w1_slave *sl, int addr, int len, char *data)
{
	u8 wrbuf[3];

	/* read directly from the EEPROM */
	if (w1_reset_select_slave(sl))
		return -EIO;

	wrbuf[0] = W1_F1C_READ_EEPROM;
	wrbuf[1] = addr & 0xff;
	wrbuf[2] = addr >> 8;

	w1_write_block(sl->master, wrbuf, sizeof(wrbuf));
	return w1_read_block(sl->master, data, len);
}

static ssize_t eeprom_read(struct file *filp, struct kobject *kobj,
			   const struct bin_attribute *bin_attr, char *buf,
			   loff_t off, size_t count)
{
	struct w1_slave *sl = kobj_to_w1_slave(kobj);
	struct w1_f1C_data *data = sl->family_data;
	int i, min_page, max_page;

	count = w1_f1C_fix_count(off, count, W1_EEPROM_SIZE);
	if (count == 0)
		return 0;

	mutex_lock(&sl->master->mutex);

	if (w1_enable_crccheck) {
		min_page = (off >> W1_PAGE_BITS);
		max_page = (off + count - 1) >> W1_PAGE_BITS;
		for (i = min_page; i <= max_page; i++) {
			if (w1_f1C_refresh_block(sl, data, i)) {
				count = -EIO;
				goto out_up;
			}
		}
		memcpy(buf, &data->memory[off], count);
	} else {
		count = w1_f1C_read(sl, off, count, buf);
	}

Annotation

Implementation Notes