/* * 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.
*/ staticinline size_t w1_f2d_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;
}
/* * Read a block from W1 ROM two times and compares the results. * If they are equal they are returned, otherwise the read * is repeated W1_F2D_READ_RETRIES times. * * count must not exceed W1_F2D_READ_MAXLEN.
*/ staticint w1_f2d_readblock(struct w1_slave *sl, int off, int count, char *buf)
{
u8 wrbuf[3];
u8 cmp[W1_F2D_READ_MAXLEN]; int tries = W1_F2D_READ_RETRIES;
do {
wrbuf[0] = W1_F2D_READ_EEPROM;
wrbuf[1] = off & 0xff;
wrbuf[2] = off >> 8;
if (w1_f2d_readblock(sl, off, block_read, buf) < 0)
count = -EIO;
todo -= W1_F2D_READ_MAXLEN;
buf += W1_F2D_READ_MAXLEN;
off += W1_F2D_READ_MAXLEN;
}
mutex_unlock(&sl->master->bus_mutex);
return count;
}
/* * Writes to the scratchpad and reads it back for verification. * Then copies the scratchpad to EEPROM. * The data must be aligned at W1_F2D_SCRATCH_SIZE bytes and * must be W1_F2D_SCRATCH_SIZE bytes long. * The master must be locked. * * @param sl The slave structure * @param addr Address for the write * @param len length must be <= (W1_F2D_PAGE_SIZE - (addr & W1_F2D_PAGE_MASK)) * @param data The data to write * @return 0=Success -1=failure
*/ staticint w1_f2d_write(struct w1_slave *sl, int addr, int len, const u8 *data)
{ int tries = W1_F2D_READ_RETRIES;
u8 wrbuf[4];
u8 rdbuf[W1_F2D_SCRATCH_SIZE + 3];
u8 es = (addr + len - 1) % W1_F2D_SCRATCH_SIZE;
retry:
/* Write the data to the scratchpad */ if (w1_reset_select_slave(sl)) return -1;
/* Read the scratchpad and verify */ if (w1_reset_select_slave(sl)) return -1;
w1_write_8(sl->master, W1_F2D_READ_SCRATCH);
w1_read_block(sl->master, rdbuf, len + 3);
/* Compare what was read against the data written */ if ((rdbuf[0] != wrbuf[1]) || (rdbuf[1] != wrbuf[2]) ||
(rdbuf[2] != es) || (memcmp(data, &rdbuf[3], len) != 0)) {
if (--tries) goto retry;
dev_err(&sl->dev, "could not write to eeprom, scratchpad compare failed %d times\n",
W1_F2D_READ_RETRIES);
return -1;
}
/* Copy the scratchpad to EEPROM */ if (w1_reset_select_slave(sl)) return -1;
/* Can only write data in blocks of the size of the scratchpad */
addr = off;
len = count; while (len > 0) {
/* if len too short or addr not aligned */ if (len < W1_F2D_SCRATCH_SIZE || addr & W1_F2D_SCRATCH_MASK) { char tmp[W1_F2D_SCRATCH_SIZE];
/* read the block and update the parts to be written */ if (w1_f2d_readblock(sl, addr & ~W1_F2D_SCRATCH_MASK,
W1_F2D_SCRATCH_SIZE, tmp)) {
count = -EIO; goto out_up;
}
/* copy at most to the boundary of the PAGE or len */
copy = W1_F2D_SCRATCH_SIZE -
(addr & W1_F2D_SCRATCH_MASK);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.