PERFORCE change 110616 for review
Warner Losh
imp at FreeBSD.org
Tue Nov 28 00:02:24 PST 2006
http://perforce.freebsd.org/chv.cgi?CH=110616
Change 110616 by imp at imp_lighthouse on 2006/11/28 08:01:24
First stab at a write implementation. This one uses readback
to pace itself. Need to read more datasheets to discover some of
the tunable parameters.
Affected files ...
.. //depot/projects/arm/src/sys/dev/iicbus/icee.c#2 edit
Differences ...
==== //depot/projects/arm/src/sys/dev/iicbus/icee.c#2 (text+ko) ====
@@ -162,7 +162,7 @@
while (uio->uio_resid > 0) {
if (uio->uio_offset >= sc->size)
break;
- len = MAX(256 - (uio->uio_offset & 0xff), uio->uio_resid);
+ len = MIN(256 - (uio->uio_offset & 0xff), uio->uio_resid);
switch (sc->type) {
case 8:
for (i = 0; i < 2; i++)
@@ -191,10 +191,23 @@
return (error);
}
+/*
+ * Write to the part. We use three transfers here since we're actually
+ * doing a write followed by a read to make sure that the write finished.
+ * It is easier to encode the dummy read here than to break things up
+ * into smaller chunks...
+ */
static int
icee_write(struct cdev *dev, struct uio *uio, int ioflag)
{
struct icee_softc *sc;
+ int error, len, i;
+ uint8_t data[16 + 2];
+ struct iic_msg msgs[3] = {
+ { 0, IIC_M_WR, 0, data },
+ { 0, IIC_M_WR, 0, data },
+ { 0, IIC_M_RD, 0, data },
+ };
sc = CDEV2SOFTC(dev);
if (uio->uio_offset > sc->size)
@@ -202,8 +215,41 @@
if (sc->type != 8 && sc->type != 16)
return (EINVAL);
ICEE_LOCK(sc);
+ error = 0;
+ while (uio->uio_resid > 0) {
+ if (uio->uio_offset >= sc->size)
+ break;
+ len = MIN(16 - (uio->uio_offset & 0xf), uio->uio_resid);
+ error = uiomove(data + sc->type / 8, len, uio);
+ if (error)
+ break;
+ switch (sc->type) {
+ case 8:
+ for (i = 0; i < 3; i++)
+ msgs[i].slave = uio->uio_offset >> 8 | sc->addr;
+ msgs[0].len = 1 + len;
+ msgs[1].len = 1;
+ msgs[2].len = len;
+ msgs[2].buf = data + 1;
+ data[0] = uio->uio_offset & 0xff;
+ break;
+ case 16:
+ for (i = 0; i < 3; i++)
+ msgs[i].slave = sc->addr;
+ msgs[0].len = 2 + len;
+ msgs[1].len = 2;
+ msgs[2].len = len;
+ msgs[2].buf = data + 2;
+ data[0] = uio->uio_offset & 0xff;
+ data[1] = (uio->uio_offset >> 8) & 0xff;
+ break;
+ }
+ error = iicbus_transfer(sc->sc_dev, msgs, 3);
+ if (error)
+ break;
+ }
ICEE_UNLOCK(sc);
- return EIO;
+ return error;
}
static device_method_t icee_methods[] = {
More information about the p4-projects
mailing list