/* * iicbus_block_read() * * Read a block of data from slave ; start/stop protocol managed */ int iicbus_block_read(device_t bus, u_char slave, char *buf, int len, int *read) { u_char addr = slave | LSB; int error; if ((error = iicbus_start(bus, addr, 0))) return (error); error = iicbus_read(bus, buf, len, read, IIC_LAST_READ, 0); iicbus_stop(bus); return (error); }
/* * Generic version of iicbus_transfer that calls the appropriate * routines to accomplish this. See note above about acceptable * buffer addresses. */ int iicbus_transfer_gen(device_t dev, struct iic_msg *msgs, uint32_t nmsgs) { int i, error, lenread, lenwrote, nkid, rpstart, addr; device_t *children, bus; if ((error = device_get_children(dev, &children, &nkid)) != 0) return (error); if (nkid != 1) { free(children, M_TEMP); return (EIO); } bus = children[0]; rpstart = 0; free(children, M_TEMP); for (i = 0, error = 0; i < nmsgs && error == 0; i++) { addr = msgs[i].slave; if (msgs[i].flags & IIC_M_RD) addr |= LSB; else addr &= ~LSB; if (!(msgs[i].flags & IIC_M_NOSTART)) { if (rpstart) error = iicbus_repeated_start(bus, addr, 0); else error = iicbus_start(bus, addr, 0); } if (error) break; if (msgs[i].flags & IIC_M_RD) error = iicbus_read(bus, msgs[i].buf, msgs[i].len, &lenread, IIC_LAST_READ, 0); else error = iicbus_write(bus, msgs[i].buf, msgs[i].len, &lenwrote, 0); if (!(msgs[i].flags & IIC_M_NOSTOP)) { rpstart = 0; iicbus_stop(bus); } else { rpstart = 1; /* Next message gets repeated start */ } } return (error); }
static int iicuio_move(struct iic_cdevpriv *priv, struct uio *uio, int last) { device_t parent; int error, num_bytes, transferred_bytes, written_bytes; char buffer[128]; parent = device_get_parent(priv->sc->sc_dev); error = 0; /* * We can only transfer up to sizeof(buffer) bytes in 1 shot, so loop until * everything has been transferred. */ while ((error == 0) && (uio->uio_resid > 0)) { num_bytes = MIN(uio->uio_resid, sizeof(buffer)); transferred_bytes = 0; if (uio->uio_rw == UIO_WRITE) { error = uiomove(buffer, num_bytes, uio); while ((error == 0) && (transferred_bytes < num_bytes)) { written_bytes = 0; error = iicbus_write(parent, &buffer[transferred_bytes], num_bytes - transferred_bytes, &written_bytes, 0); transferred_bytes += written_bytes; } } else if (uio->uio_rw == UIO_READ) { error = iicbus_read(parent, buffer, num_bytes, &transferred_bytes, ((uio->uio_resid <= sizeof(buffer)) ? last : 0), 0); if (error == 0) error = uiomove(buffer, transferred_bytes, uio); } } return (error); }