Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 22 Dec 2011 12:55:13 +0100
From:      Stefan Bethke <stb@lassitu.de>
To:        Adrian Chadd <adrian@freebsd.org>
Cc:        Oleksandr Tymoshenko <gonzo@freebsd.org>, "freebsd-embedded@freebsd.org" <freebsd-embedded@freebsd.org>
Subject:   Re: Updated switch/glue patch?
Message-ID:  <45529EC2-73BE-4F69-A9BE-E22D9FEAADD7@lassitu.de>
In-Reply-To: <CAJ-VmokwSHN8U2=HJQT9kxFQ9oE-6H2h3KDb%2BMHN1Z8sur9=yw@mail.gmail.com>
References:  <CAJ-Vmon8%2BOXQ4g752zZEB-O0BR0sFWO0QUvw--xp2jsBDkx6tQ@mail.gmail.com> <0F6CC18F-6973-42A2-AC03-F01BF59458AE@lassitu.de> <CAJ-Vmo=Y8pp4iFnw%2B1hcPae6QXFboz=a7puwgC1kVSZ3JwMgPQ@mail.gmail.com> <1100F70E-9DA9-4163-AC9A-423ECE5AA9A3@lassitu.de> <CAJ-VmonrnJ7cC6u2LsL9AGusz_%2BkSwY62Rr1__sg5U_NynJ1SQ@mail.gmail.com> <CAJ-Vmo=WSN1oLM=B2HqSHrWyOaOD9BSwwu8=1Wys0CLRJ_N-TA@mail.gmail.com> <C637C171-A1A2-4296-84FA-6DE97137DC42@lassitu.de> <CAJ-Vmon2boy7OCh_4O0MeCi0yCdZu0OYb5dxHCEK=-%2B46zBGtg@mail.gmail.com> <CAJ-Vmoku5eLEYi5_DXVxK=0=4Ewn2aGepv3YUw4ApuVh_7y2%2Bw@mail.gmail.com> <CAJ-VmonvpnaS1rAO%2BsDRh1E5WfsrZTYE297Kc96prhfKjrM89Q@mail.gmail.com> <CAJ-VmokQxQs2DUKL=ONyxnnS7Q28ytmwZJ_thqvc4SvMkmS=cQ@mail.gmail.com> <18CABB46-9B9A-41CB-8742-6723C5FF4D67@lassitu.de> <C0BF20FD-E30F-4E9C-A0FE-500BE4807B99@bsdimp.com> <CAJ-VmokgiQCEG4et3X=3o_MuCMkO9MqkKqa-fjdpEqQNucn=Lw@mail.gmail.com> <2CBD8651-E132-49DC-A082-37A8F5C626EA@bsdimp.com> <AFE755D6-E462-40B4-A97B-9261303B3A4F@lassitu.de> <CAJ-Vm o=ERixAN96QSOaaej8avPHYkGC28AJZErdEhO0%2B=1R0Pw@mail.gmail.com> <09670C34-0D30-46BC-BA7E-4AAA22193B61@lassitu.de> <CAJ-VmokwSHN8U2=HJQT9kxFQ9oE-6H2h3KDb%2BMHN1Z8sur9=yw@mail.gmail.com>

next in thread | previous in thread | raw e-mail | index | archive | help

--Apple-Mail=_554C24B4-3E45-41F2-A1D1-A95DF5DD36A5
Content-Transfer-Encoding: quoted-printable
Content-Type: text/plain;
	charset=iso-8859-1


Am 22.12.2011 um 06:41 schrieb Adrian Chadd:

> On 21 December 2011 07:13, Stefan Bethke <stb@lassitu.de> wrote:
>=20
>> I've replaced the generic PHY status poll with a custom one that uses =
the switch registers instead of the PHYs.  I've cloned your git and have =
started adding my changes to it (branch also named work/ath):
>> http://gitorious.org/~stb/freebsd/stb-adrianchadd-freebsd-work
>>=20
>> I tried a merge request, but gitorious didn't like it (at least at =
the top level).
>=20
> Cool! Can you please either figure out why that's the case, or just
> throw me some diffs?

It complains about the merge being too big to display in a browser?

Anyway, here's two diffs.  I believe you can track my tree by adding it =
to your local repository, and then merge it locally. That should be =
easier and less error prone than applying diffs.

> We should figure out how to merge stuff back into your tree to mine
> (and then propagate the changes back to you) so we don't have to face
> this when the changes are bigger.

I'm tracking your tree and merging changes into mine.  One option could =
be to allow me write access to your repo and let me stuff my changes =
into a branch there.

> After that's done, I'll work on you to tidy up the management utility.
> Then we can start merging in whatever's needed from zrouter, and start
> pushing this into -HEAD. I don't mind if it's a work in progress - at
> least something will be in the tree.

Cool!

I've got a WRT160NL here with an RTL8306S which I could write a driver =
for.  I started bringing FreeBSD up on that last night, but accidentally =
overwrote half my uboot.  Waiting for the JTAG adapter to ship...


Stefan

--=20
Stefan Bethke <stb@lassitu.de>   Fon +49 151 14070811



--Apple-Mail=_554C24B4-3E45-41F2-A1D1-A95DF5DD36A5
Content-Disposition: attachment;
	filename=rtl8366rb.patch
Content-Type: application/octet-stream;
	name="rtl8366rb.patch"
Content-Transfer-Encoding: 7bit

diff --git a/sys/dev/etherswitch/rtl8366rb.c b/sys/dev/etherswitch/rtl8366rb.c
index f41a425..6f3e378 100644
--- a/sys/dev/etherswitch/rtl8366rb.c
+++ b/sys/dev/etherswitch/rtl8366rb.c
@@ -139,7 +139,7 @@ rtl8366rb_attach(device_t dev)
 
 	sc = device_get_softc(dev);
 	sc->dev = dev;
-	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), MTX_NETWORK_LOCK,
+	mtx_init(&sc->sc_mtx, device_get_nameunit(dev), "rtl8366rb",
 	    MTX_DEF);
 	rtl8366rb_init(dev);
 	smi_read(dev, RTL8366RB_CVCR, &rev);
@@ -201,16 +201,60 @@ rtl8366rb_detach(device_t dev)
 }
 
 static void
+rtl833rb_miipollstat(struct rtl8366rb_softc *sc)
+{
+	int i;
+	struct mii_data *mii;
+	struct mii_softc *child;
+	uint16_t value;
+	int portstatus;
+
+	for (i = 0; i < RTL8366RB_NUM_PORTS-1; i++) {
+		mii = device_get_softc(sc->miibus[i]);
+		if ((i % 2) == 0) {
+			smi_read(sc->dev, RTL8366RB_PLSR_BASE + i/2, &value);
+			portstatus = value & 0xff;
+		} else {
+			portstatus = (value >> 8) & 0xff;
+		}
+		mii->mii_media_status = IFM_AVALID;
+		mii->mii_media_active = IFM_ETHER;
+		if ((portstatus & RTL8366RB_PLSR_LINK) != 0) {
+			switch (portstatus & RTL8366RB_PLSR_SPEED_MASK) {
+			case RTL8366RB_PLSR_SPEED_10:
+				mii->mii_media_active |= IFM_10_T;
+				break;
+			case RTL8366RB_PLSR_SPEED_100:
+				mii->mii_media_active |= IFM_100_TX;
+				break;
+			case RTL8366RB_PLSR_SPEED_1000:
+				mii->mii_media_active |= IFM_1000_T;
+				break;
+			}
+			if ((portstatus & RTL8366RB_PLSR_FULLDUPLEX) != 0)
+				mii->mii_media_active |= IFM_FDX;
+			else
+				mii->mii_media_active |= IFM_HDX;
+			if ((portstatus & RTL8366RB_PLSR_TXPAUSE) != 0)
+				mii->mii_media_active |= IFM_ETH_TXPAUSE;
+			if ((portstatus & RTL8366RB_PLSR_RXPAUSE) != 0)
+				mii->mii_media_active |= IFM_ETH_RXPAUSE;
+		} else
+			mii->mii_media_active |= IFM_NONE;
+		LIST_FOREACH(child, &mii->mii_phys, mii_list) {
+			if (IFM_INST(mii->mii_media.ifm_cur->ifm_media) != child->mii_inst)
+				continue;
+			(void)PHY_SERVICE(child, mii, MII_POLLSTAT);
+		}
+	}	
+}
+
+static void
 rtl8366rb_tick(void *arg)
 {
 	struct rtl8366rb_softc *sc = arg;
-	int i;
 	
-	for (i=0; i < RTL8366RB_NUM_PORTS-1; i++) {
-		if (sc->miibus[i] != NULL)
-			mii_tick(device_get_softc(sc->miibus[i]));
-			mii_pollstat(device_get_softc(sc->miibus[i]));
-	}
+	rtl833rb_miipollstat(sc);
 	callout_reset(&sc->callout_tick, hz, rtl8366rb_tick, sc);
 }
 
@@ -435,10 +479,7 @@ rtl8366rb_ifmedia_upd(struct ifnet *ifp)
 {
 	struct rtl8366rb_softc *sc = ifp->if_softc;
 	struct mii_data *mii = device_get_softc(sc->miibus[ifp->if_dunit]);
-	struct mii_softc *miisc;
 	
-	LIST_FOREACH(miisc, &mii->mii_phys, mii_list)
-		PHY_RESET(miisc);
 	mii_mediachg(mii);
 	return (0);
 }
diff --git a/sys/dev/etherswitch/rtl8366rbvar.h b/sys/dev/etherswitch/rtl8366rbvar.h
index f14373a..df17cb6 100644
--- a/sys/dev/etherswitch/rtl8366rbvar.h
+++ b/sys/dev/etherswitch/rtl8366rbvar.h
@@ -65,7 +65,8 @@
 #define RTL8366RB_PLSR_SPEED_10		0x00
 #define RTL8366RB_PLSR_SPEED_100	0x01
 #define RTL8366RB_PLSR_SPEED_1000	0x02
-#define RTL8366RB_PLSR_FULLDUPLEX	0x10
+#define RTL8366RB_PLSR_FULLDUPLEX	0x08
+#define RTL8366RB_PLSR_LINK		0x10
 #define RTL8366RB_PLSR_TXPAUSE		0x20
 #define RTL8366RB_PLSR_RXPAUSE		0x40
 #define RTL8366RB_PLSR_NO_AUTO		0x80

--Apple-Mail=_554C24B4-3E45-41F2-A1D1-A95DF5DD36A5
Content-Disposition: attachment;
	filename=iicbb.patch
Content-Type: application/octet-stream; x-unix-mode=0644; name="iicbb.patch"
Content-Transfer-Encoding: 7bit

diff --git a/sys/dev/iicbus/iicbb.c b/sys/dev/iicbus/iicbb.c
index fed203c..e060a75 100644
--- a/sys/dev/iicbus/iicbb.c
+++ b/sys/dev/iicbus/iicbb.c
@@ -25,7 +25,7 @@
  */
 
 #include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+__FBSDID("$FreeBSD: head/sys/dev/iicbus/iicbb.c 188461 2009-02-10 22:50:23Z imp $");
 
 /*
  * Generic I2C bit-banging code
@@ -48,9 +48,9 @@ __FBSDID("$FreeBSD$");
 #include <sys/systm.h>
 #include <sys/module.h>
 #include <sys/bus.h>
+#include <sys/sysctl.h>
 #include <sys/uio.h>
 
-
 #include <dev/iicbus/iiconf.h>
 #include <dev/iicbus/iicbus.h>
 
@@ -59,9 +59,31 @@ __FBSDID("$FreeBSD$");
 #include "iicbus_if.h"
 #include "iicbb_if.h"
 
+#define IIC_DELAY_100KHZ	3	/* 3 microseconds per quarter cycle, should be 2.5 */
+
+#if defined(DEBUG)
+static int i2c_debug = 0;
+#define I2C_DEBUG(x)				\
+	do {					\
+		if (i2c_debug) (x);		\
+	} while (0)
+
+#define I2C_LOG(args...)			\
+	do {					\
+		if (i2c_debug) printf(args);	\
+	} while (0)
+static SYSCTL_NODE(_debug, OID_AUTO, iicbb, CTLFLAG_RD, 0, "iicbb");
+SYSCTL_INT(_debug_iicbb, OID_AUTO, debug, CTLFLAG_RW, &i2c_debug, 0,
+	"print bus transactions");
+#else
+#define I2C_DEBUG(x)
+#define	I2C_LOG(args...)
+#endif
+
 struct iicbb_softc {
 	device_t iicbus;
-	int udelay;		/* signal toggle delay in usec */
+	int iicdelay;
+	int iictimeout;
 };
 
 static int iicbb_attach(device_t);
@@ -126,11 +148,11 @@ iicbb_attach(device_t dev)
 	if (!sc->iicbus)
 		return (ENXIO);
 
-	sc->udelay = 10;		/* 10 uS default */
+	sc->udelay = IIC_DELAY_100KHZ;
 	if (resource_int_value(device_get_name(dev),
 	    device_get_unit(dev), "udelay", &udelay) == 0)
-	    sc->udelay = udelay;
-	device_printf(dev, "udelay=%d microseconds\n", sc->udelay);
+	    sc->iicdelay = udelay;
+	device_printf(dev, "udelay=%d microseconds\n", sc->iicdelay);
 
 	bus_generic_attach(dev);
 
@@ -193,149 +215,191 @@ iicbb_print_child(device_t bus, device_t dev)
 	return (retval);
 }
 
-#define I2C_SETSDA(sc,dev,val) do {			\
-	IICBB_SETSDA(device_get_parent(dev), val);	\
-	DELAY(sc->udelay);				\
-	} while (0)
-
-#define I2C_SETSCL(dev,val) do {			\
-	iicbb_setscl(dev, val, 100);			\
-	} while (0)
-
-#define I2C_SET(sc,dev,ctrl,data) do {			\
-	I2C_SETSCL(dev, ctrl);				\
-	I2C_SETSDA(sc, dev, data);			\
-	} while (0)
-
-#define I2C_GETSDA(dev) (IICBB_GETSDA(device_get_parent(dev)))
-
-#define I2C_GETSCL(dev) (IICBB_GETSCL(device_get_parent(dev)))
-
-static int i2c_debug = 0;
-#define I2C_DEBUG(x)	do {					\
-				if (i2c_debug) (x);		\
-			} while (0)
 
-#define I2C_LOG(format,args...)	do {				\
-					printf(format, args);	\
-				} while (0)
+/*
+ * Low-level bus state functions.  The following functions implement the
+ * basic bus states for I2C.  We divide the full clock cycle into four
+ * phases.  Transitions of SCL and SDA occur between these phases.  The
+ * nominal duration of each phase is 100 kHz/4, or 2.5 us.  Implementations
+ * for busses and devices can choose a lower delay for faster operation.
+ *
+ * Each of the functions returns -1 if the operation could not be completed.
+ */
 
-static void
-iicbb_setscl(device_t dev, int val, int timeout)
+/*
+ * I2C start (S) and repeated start (Sr) condition
+ *     0  1  2  3
+ *         __.__
+ * SCL XXXX     \__.
+ *         __
+ * SDA XXXX  \__.__.
+ * 
+ */
+static __inline int
+i2c_start(device_t dev)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
-	int k = 0;
-
-	IICBB_SETSCL(device_get_parent(dev), val);
-	DELAY(sc->udelay);
-
-	while (val && !I2C_GETSCL(dev) && k++ < timeout) {
-		IICBB_SETSCL(device_get_parent(dev), val);
-		DELAY(sc->udelay);
+	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
+	int timeout = sc->iictimeout;
+
+	/* 0 */
+	IICBB_SETSDA(device_get_parent(dev), 1);
+	IICBB_SETSCL(device_get_parent(dev), 1);
+	/* wait for the bus to become idle */
+	while(1) {
+		DELAY(sc->iicdelay);
+		if (IICBB_GETSDA(device_get_parent(dev)) != 0 &&
+			IICBB_GETSCL(device_get_parent(dev)) != 0)
+			break;
+		if (timeout <= 0)
+			return (-1);
+		timeout -= sc->iicdelay;
 	}
-
-	return;
+	/* 1 */
+	DELAY(sc->iicdelay);
+	/* 2 */
+	IICBB_SETSDA(device_get_parent(dev), 0);
+	DELAY(sc->iicdelay);
+	/* 3 */
+	IICBB_SETSCL(device_get_parent(dev), 0);
+	DELAY(sc->iicdelay);
+	return (0);
 }
 
-static void
-iicbb_one(device_t dev, int timeout)
+/*
+ * I2C stop (P) condition
+ *     0  1  2  3
+ *         __.__.__.
+ * SCL .__/     
+ *            _____.
+ * SDA XXXX__/
+ */
+static __inline int
+i2c_stop(device_t dev)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
+	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
 
-	I2C_SET(sc,dev,0,1);
-	I2C_SET(sc,dev,1,1);
-	I2C_SET(sc,dev,0,1);
-	return;
+	/* 0 */
+	IICBB_SETSDA(device_get_parent(dev), 0);
+	DELAY(sc->iicdelay);
+	/* 1 */
+	IICBB_SETSCL(device_get_parent(dev), 1);
+	DELAY(sc->iicdelay);
+	/* 2 */
+	IICBB_SETSDA(device_get_parent(dev), 1);
+	DELAY(sc->iicdelay);
+	/*
+	 * we can skip the last delay since the bus will either be idle,
+	 * or the next S will wait long enough to keep the timing correct.
+	 */
+	return (0);
 }
 
-static void
-iicbb_zero(device_t dev, int timeout)
+/*
+ * I2C transmit one bit
+ *     0  1  2  3
+ *         __.__
+ * SCL .__/     \__.
+ *         __.__
+ * SDA .XXX__.__XXX.
+ */
+static __inline int
+i2c_xmitbit(device_t dev, int value)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
-
-	I2C_SET(sc,dev,0,0);
-	I2C_SET(sc,dev,1,0);
-	I2C_SET(sc,dev,0,0);
-	return;
+	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
+	int timeout = sc->iictimeout;
+
+	/* 0 */
+	IICBB_SETSDA(device_get_parent(dev), value);
+	DELAY(sc->iicdelay);
+	/* 1 */
+	IICBB_SETSCL(device_get_parent(dev), 1);
+	while (1) {
+		DELAY(sc->iicdelay);
+		if (IICBB_GETSCL(device_get_parent(dev)) != 0)
+			break;
+		if (timeout <= 0)
+			return (-1);
+		timeout -= sc->iicdelay;
+	}
+	/* 2 */
+	if (value != 0 && IICBB_GETSDA(device_get_parent(dev)) == 0)
+		return (-1); /* another master is pulling down SDA */
+	DELAY(sc->iicdelay);
+	/* 3 */
+	IICBB_SETSCL(device_get_parent(dev), 0);
+	DELAY(sc->iicdelay);
+	return (0);
 }
 
 /*
- * Waiting for ACKNOWLEDGE.
- *
- * When a chip is being addressed or has received data it will issue an
- * ACKNOWLEDGE pulse. Therefore the MASTER must release the DATA line
- * (set it to high level) and then release the CLOCK line.
- * Now it must wait for the SLAVE to pull the DATA line low.
- * Actually on the bus this looks like a START condition so nothing happens
- * because of the fact that the IC's that have not been addressed are doing
- * nothing.
- *
- * When the SLAVE has pulled this line low the MASTER will take the CLOCK
- * line low and then the SLAVE will release the SDA (data) line.
+ * I2C receive one bit
+ *     0  1  2  3
+ *         __.__
+ * SCL .__/     \__.
+ *         __.__
+ * SDA .XXX__.__XXX.
  */
-static int
-iicbb_ack(device_t dev, int timeout)
+static __inline int
+i2c_recvbit(device_t dev)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
-	int noack;
-	int k = 0;
-
-	I2C_SET(sc,dev,0,1);
-	I2C_SET(sc,dev,1,1);
-	do {
-		noack = I2C_GETSDA(dev);
-		if (!noack)
+	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
+	int timeout = sc->iictimeout;
+	int value;
+
+	/* 0 */
+	IICBB_SETSDA(device_get_parent(dev), 1);
+	DELAY(sc->iicdelay);
+	IICBB_SETSCL(device_get_parent(dev), 1);
+	while (1) {
+		DELAY(sc->iicdelay);
+		if (IICBB_GETSCL(device_get_parent(dev)) != 0)
 			break;
-		DELAY(1);
-		k++;
-	} while (k < timeout);
-
-	I2C_SET(sc,dev,0,1);
-	I2C_DEBUG(printf("%c ",noack?'-':'+'));
-
-	return (noack);
+		if (timeout <= 0)
+			return (-1);
+		timeout -= sc->iicdelay;
+	}
+	value = IICBB_GETSDA(device_get_parent(dev));
+	DELAY(sc->iicdelay);
+	IICBB_SETSCL(device_get_parent(dev), 0);
+	DELAY(sc->iicdelay);
+	return (value != 0 ? 1 : 0);
 }
 
-static void
-iicbb_sendbyte(device_t dev, u_char data, int timeout)
+/*
+ * Transmit a byte. Returns -1 on error.
+ */
+static int
+i2c_xmitbyte(device_t dev, int value)
 {
-	int i;
-    
-	for (i=7; i>=0; i--) {
-		if (data&(1<<i)) {
-			iicbb_one(dev, timeout);
-		} else {
-			iicbb_zero(dev, timeout);
-		}
+	int i, error;
+	
+	for (i = 7; i >= 0; i--) {
+		error = i2c_xmitbit(dev, (value >> i) & 0x01);
+		if (error < 0)
+			return (error);
 	}
-	I2C_DEBUG(printf("w%02x",(int)data));
-	return;
+	return (error);
 }
 
-static u_char
-iicbb_readbyte(device_t dev, int last, int timeout)
+/*
+ * Receive a byte. Returns the byte value (0..255), or -1 on error.
+ */
+static int
+i2c_recvbyte(device_t dev)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
-	int i;
-	unsigned char data=0;
-
-	I2C_SET(sc,dev,0,1);
-	for (i=7; i>=0; i--) 
-	{
-		I2C_SET(sc,dev,1,1);
-		if (I2C_GETSDA(dev))
-			data |= (1<<i);
-		I2C_SET(sc,dev,0,1);
-	}
-	if (last) {
-		iicbb_one(dev, timeout);
-	} else {
-		iicbb_zero(dev, timeout);
+	int i, error, value;
+	
+	value = 0;
+	for (i = 7; i >= 0; i--) {
+		error = i2c_recvbit(dev);
+		if (error < 0)
+			return (error);
+		value |= error << i;
 	}
-	I2C_DEBUG(printf("r%02x%c ",(int)data,last?'-':'+'));
-	return data;
+	return (value);
 }
 
+
 static int
 iicbb_callback(device_t dev, int index, caddr_t data)
 {
@@ -351,34 +415,32 @@ iicbb_reset(device_t dev, u_char speed, u_char addr, u_char *oldaddr)
 static int
 iicbb_start(device_t dev, u_char slave, int timeout)
 {
-	struct iicbb_softc *sc = device_get_softc(dev);
 	int error;
+	struct iicbb_softc *sc = (struct iicbb_softc *)device_get_softc(dev);
 
-	I2C_DEBUG(printf("<"));
-
-	I2C_SET(sc,dev,1,1);
-	I2C_SET(sc,dev,1,0);
-	I2C_SET(sc,dev,0,0);
-
-	/* send address */
-	iicbb_sendbyte(dev, slave, timeout);
-
-	/* check for ack */
-	if (iicbb_ack(dev, timeout)) {
-		error = IIC_ENOACK;
-		goto error;
-	}
-
-	return(0);
-
-error:
-	iicbb_stop(dev);
-	return (error);
+	I2C_LOG("<");
+
+	sc->iictimeout = timeout;
+	if (i2c_start(dev) < 0)
+		return (IIC_ENOACK);
+	error = i2c_xmitbyte(dev, slave);
+	if (error < 0)
+		return (IIC_EBUSERR); /* lost arbitration */
+	I2C_LOG("%02x", slave);
+	error = i2c_recvbit(dev);
+	if (error < 0)
+		return (IIC_EBUSERR); /* lost arbitration */
+	I2C_LOG("%c", error != 0 ? '-' : '+');
+	return(error != 0 ? IIC_ENOACK : 0);
 }
 
 static int
 iicbb_stop(device_t dev)
 {
+<<<<<<< HEAD
+	i2c_stop(dev);
+	I2C_LOG(">\n");
+=======
 	struct iicbb_softc *sc = device_get_softc(dev);
 
 	I2C_SET(sc,dev,0,0);
@@ -386,26 +448,30 @@ iicbb_stop(device_t dev)
 	I2C_SET(sc,dev,1,1);
 	I2C_DEBUG(printf(">"));
 	I2C_DEBUG(printf("\n"));
+>>>>>>> adrian/work/ath
 	return (0);
 }
 
 static int
 iicbb_write(device_t dev, const char *buf, int len, int *sent, int timeout)
 {
-	int bytes, error = 0;
+	int bytes, ack, error = 0;
 
+	I2C_LOG(" W%d:", len);
 	bytes = 0;
 	while (len) {
-		/* send byte */
-		iicbb_sendbyte(dev,(u_char)*buf++, timeout);
-
-		/* check for ack */
-		if (iicbb_ack(dev, timeout)) {
+		I2C_LOG(" %02x", (u_char)*buf);
+		i2c_xmitbyte(dev,(u_char)*buf++);
+		ack = i2c_recvbit(dev);
+		if (ack < 0)
+			return (IIC_EBUSERR);
+		I2C_LOG("%c", ack != 0 ? '-' : '+');
+		if (len != 1 && ack != 0) {
 			error = IIC_ENOACK;
 			goto error;
 		}
-		bytes ++;
-		len --;
+		bytes++;
+		len--;
 	}
 
 error:
@@ -416,19 +482,31 @@ error:
 static int
 iicbb_read(device_t dev, char * buf, int len, int *read, int last, int delay)
 {
-	int bytes;
+	int bytes, value, error = 0;
 
+	I2C_LOG(" R%d:", len);
 	bytes = 0;
 	while (len) {
-		/* XXX should insert delay here */
-		*buf++ = (char)iicbb_readbyte(dev, (len == 1) ? last : 0, delay);
-
-		bytes ++;
-		len --;
+		value = i2c_recvbyte(dev);
+		if (value < 0) {
+			error = IIC_EBUSERR;
+			goto error;
+		}
+		I2C_LOG(" %02x", value);
+		error = i2c_xmitbit(dev, len == 1 && last ? 1 : 0);
+		if (value < 0) {
+			error = IIC_EBUSERR;
+			goto error;
+		}
+		I2C_LOG("%c", len == 1 && last ? '-' : '+');
+		*buf++ = value;
+		bytes++;
+		len--;
 	}
 
+error:
 	*read = bytes;
-	return (0);
+	return (error);
 }
 
 DRIVER_MODULE(iicbus, iicbb, iicbus_driver, iicbus_devclass, 0, 0);

--Apple-Mail=_554C24B4-3E45-41F2-A1D1-A95DF5DD36A5--



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?45529EC2-73BE-4F69-A9BE-E22D9FEAADD7>