/* * iicbus_write_byte() * * Write a byte to the slave previously started by iicbus_start() call */ int iicbus_write_byte(device_t bus, char byte, int timeout) { char data = byte; int sent; return (iicbus_write(bus, &data, 1, &sent, timeout)); }
static int iicioctl(dev_t dev, u_long cmd, caddr_t data, int flags, struct thread *td) { device_t iicdev = IIC_DEVICE(minor(dev)); struct iic_softc *sc = IIC_SOFTC(minor(dev)); device_t parent = device_get_parent(iicdev); struct iiccmd *s = (struct iiccmd *)data; int error, count; if (!sc) return (EINVAL); if ((error = iicbus_request_bus(device_get_parent(iicdev), iicdev, (flags & O_NONBLOCK) ? IIC_DONTWAIT : (IIC_WAIT | IIC_INTR)))) return (error); switch (cmd) { case I2CSTART: error = iicbus_start(parent, s->slave, 0); /* * Implicitly set the chip addr to the slave addr passed as * parameter. Consequently, start/stop shall be called before * the read or the write of a block. */ if (!error) sc->sc_addr = s->slave; break; case I2CSTOP: error = iicbus_stop(parent); break; case I2CRSTCARD: error = iicbus_reset(parent, 0, 0, NULL); break; case I2CWRITE: error = iicbus_write(parent, s->buf, s->count, &count, 10); break; case I2CREAD: error = iicbus_read(parent, s->buf, s->count, &count, s->last, 10); break; default: error = ENODEV; } iicbus_release_bus(device_get_parent(iicdev), iicdev); 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; bool nostop; if ((error = device_get_children(dev, &children, &nkid)) != 0) return (IIC_ERESOURCE); if (nkid != 1) { free(children, M_TEMP); return (IIC_ENOTSUPP); } bus = children[0]; rpstart = 0; free(children, M_TEMP); nostop = iicbus_get_nostop(dev); 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 != 0) 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 (error != 0) break; if ((msgs[i].flags & IIC_M_NOSTOP) != 0 || (nostop && i + 1 < nmsgs)) { rpstart = 1; /* Next message gets repeated start */ } else { rpstart = 0; iicbus_stop(bus); } } if (error != 0 && !nostop) iicbus_stop(bus); return (error); }
/* * iicbus_write_byte() * * Write a byte to the slave previously started by iicbus_start() call */ int iicbus_write_byte(device_t bus, char byte, int timeout) { struct iicbus_softc *sc = device_get_softc(bus); char data = byte; int sent; /* a slave must have been started for writing */ if (sc->started == 0 || (sc->strict != 0 && (sc->started & LSB) != 0)) return (IIC_ESTATUS); return (iicbus_write(bus, &data, 1, &sent, timeout)); }
/* * iicbus_block_write() * * Write a block of data to slave ; start/stop protocol managed */ int iicbus_block_write(device_t bus, u_char slave, char *buf, int len, int *sent) { u_char addr = slave & ~LSB; int error; if ((error = iicbus_start(bus, addr, 0))) return (error); error = iicbus_write(bus, buf, len, sent, 0); iicbus_stop(bus); 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); }