Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 28 Nov 2006 08:02:23 GMT
From:      Warner Losh <imp@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 110616 for review
Message-ID:  <200611280802.kAS82N64005954@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=110616

Change 110616 by imp@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[] = {



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200611280802.kAS82N64005954>