Subject: working(?) bpp driver
To: None <port-sparc@netbsd.org>
From: der Mouse <mouse@Rodents.Montreal.QC.CA>
List: port-sparc
Date: 02/05/2000 02:58:20
I am pleased to be able to say that I now have a bpp driver that
appears to minimally work (at least, it works with my printer;
admittedly, I have only one parallel-interface printer to test with).
I suspect some of the codepaths have not been exercised at all, and
there are surely plenty of bugs left even in the code that has been
run.

I shall be testing it more myself, of course.  But for the benefit of
the people who expressed interest in it, if any of them are interested
enough to want to help shake down a very early prerelease, here's the
driver I've got.

These patches are relative to sys/dev/sbus/bpp.c version 1.2.  Note
that this is most definitely alpha-quality code - or worse.  I do not
consider it ready for prime time; throwing it out here is an attempt to
get it pounded on by multiple people on multiple printers and such, not
an attempt to `release' a `finished product', or anything of the sort.
Trouble reports showing evidence of not understanding this concept will
be ignored. :-)

If you don't have bpp.c version 1.2 at ready hand I can send you the
whole patched file; just drop me email....

I also invite comments on how I've done things.  In some cases, changes
that `shouldn't matter' have broken or fixed it, so I'm hesitant to
mess with anything just for the sake of making it prettier.

--- OLD/sys/dev/sbus/bpp.c	Mon Apr  5 17:02:47 1999
+++ NEW/sys/dev/sbus/bpp.c	Sat Feb  5 02:49:14 2000
@@ -61,6 +61,8 @@
 #include <dev/sbus/sbusvar.h>
 #include <dev/sbus/bppreg.h>
 
+#define BPPPRI (PZERO+1)
+
 #define splbpp()	spltty()	/* XXX */
 
 #if 0
@@ -104,6 +106,8 @@
 	struct hwstate		sc_hwcurrent;
 };
 
+static unsigned int spincounts[102];
+
 static int	bppmatch	__P((struct device *, struct cfdata *, void *));
 static void	bppattach	__P((struct device *, struct device *, void *));
 static int	bppintr		__P((void *));
@@ -181,10 +185,13 @@
 	sc->sc_channel = L64854_CHANNEL_PP;
 	lsi64854_attach(sc);
 
-	sc->sc_intrchain = bppintr;
-	sc->sc_intrchainarg = dsc;
-	(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, 0,
-				 lsi64854_pp_intr, sc);
+	/* Establish interrupt handler */
+	if (sa->sa_nintr) {
+		sc->sc_intrchain = bppintr;
+		sc->sc_intrchainarg = dsc;
+		(void)bus_intr_establish(sa->sa_bustag, sa->sa_pri, 0,
+					 lsi64854_pp_intr, sc);
+	}
 
 	/* Allocate buffer XXX - should actually use dmamap_uio() */
 	dsc->sc_bufsz = 1024;
@@ -199,6 +206,14 @@
 	hw->hw_tcr = bus_space_read_1(sc->sc_bustag, h, L64854_REG_TCR);
 	hw->hw_or = bus_space_read_1(sc->sc_bustag, h, L64854_REG_OR);
 	}
+
+	/* Disable interrupts */
+	{
+	u_int16_t irq;
+	irq = dsc->sc_hwdefault.hw_irq | BPP_ALLIRQ;
+	irq &= ~BPP_ALLEN;
+	bus_space_write_2(sc->sc_bustag, sc->sc_regs, L64854_REG_ICR, irq);
+	}
 }
 
 void
@@ -222,6 +237,29 @@
 	bus_space_write_2(t, h, L64854_REG_ICR, irq);
 }
 
+/* returns true on failure */
+static int tcr_wait(struct bpp_softc *sc, unsigned int set, unsigned int clr, const char *wchan)
+{
+	int spin;
+	u_int8_t tcr;
+	bus_space_tag_t t;
+	bus_space_handle_t h;
+
+	t = sc->sc_lsi64854.sc_bustag;
+	h = sc->sc_lsi64854.sc_regs;
+	for (spin=100;spin>0;spin--) {
+		tcr = bus_space_read_1(t,h,L64854_REG_TCR);
+		if (((tcr & set) == set) && ((tcr & clr) == 0)) break;
+	}
+	spincounts[spin] ++;
+	while (((tcr & set) != set) || ((tcr & clr) != 0)) {
+		spincounts[101] ++;
+		if (tsleep((caddr_t)sc,BPPPRI|PCATCH,wchan,1) == EINTR) return(1);
+		tcr = bus_space_read_1(t,h,L64854_REG_TCR);
+	}
+	return(0);
+}
+
 int
 bppopen(dev, flags, mode, p)
 	dev_t dev;
@@ -233,6 +271,7 @@
 	struct lsi64854_softc *lsi;
 	u_int16_t irq;
 	int s;
+	int err;
 
 	if (unit >= bpp_cd.cd_ndevs)
 		return (ENXIO);
@@ -249,10 +288,28 @@
 	bpp_setparams(sc, &sc->sc_hwdefault);
 	splx(s);
 
-	/* Enable interrupts */
-	irq = BPP_ALLEN;
-	irq |= sc->sc_hwdefault.hw_irq;
+	/* Disable interrupts */
+	irq = sc->sc_hwdefault.hw_irq | BPP_ALLIRQ;
+	irq &= ~BPP_ALLEN;
 	bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq);
+
+	/* Assert INIT for 100ms, and assert SELECT */
+	bus_space_write_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_OR, BPP_OR_SLCTIN|BPP_OR_INIT);
+	err = tsleep((caddr_t)sc,BPPPRI|PCATCH,"bppopen1",hz/10);
+	if (err && (err != EWOULDBLOCK)) return(err);
+
+	/* Deassert INIT, wait until ready */
+	bus_space_write_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_OR, BPP_OR_SLCTIN);
+	if (tcr_wait(sc,0,BPP_TCR_BUSY,"bppopen2")) return(EINTR);
+
+	/* Clear direction control bit (is this actually necessary?) */
+	{
+	u_int8_t tcr;
+	tcr = bus_space_read_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_TCR);
+	tcr &= ~BPP_TCR_DIR;
+	bus_space_write_1(lsi->sc_bustag, lsi->sc_regs, L64854_REG_TCR, tcr);
+	}
+
 	return (0);
 }
 
@@ -264,12 +321,9 @@
 {
 	struct bpp_softc *sc = bpp_cd.cd_devs[BPPUNIT(dev)];
 	struct lsi64854_softc *lsi = &sc->sc_lsi64854;
-	u_int16_t irq;
 
-	/* Turn off all interrupt enables */
-	irq = sc->sc_hwdefault.hw_irq | BPP_ALLIRQ;
-	irq &= ~BPP_ALLEN;
-	bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_ICR, irq);
+	/* Deassert SELECT */
+	bus_space_write_2(lsi->sc_bustag, lsi->sc_regs, L64854_REG_OR, 0);
 
 	sc->sc_asyncproc = NULL;
 	sc->sc_flags = 0;
@@ -282,8 +336,7 @@
 	struct uio *uio;
 	int flags;
 {
-
-	return (ENXIO);
+	return(uiomove(&spincounts[0],sizeof(spincounts),uio)); /* ENXIO */
 }
 
 int
@@ -298,7 +351,7 @@
 	int s;
 
 	/*
-	 * Wait until the DMA engibe is free.
+	 * Wait until free.
 	 */
 	s = splbpp();
 	while ((sc->sc_flags & BPP_LOCKED) != 0) {
@@ -319,36 +372,26 @@
 
 	/*
 	 * Move data from user space into our private buffer
-	 * and start DMA.
+	 * and ship it out, a byte at a time (sigh).
 	 */
 	while (uio->uio_resid > 0) {
 		caddr_t bp = sc->sc_buf;
 		size_t len = min(sc->sc_bufsz, uio->uio_resid);
-
-		if ((error = uiomove(bp, len, uio)) != 0)
-			break;
-
+		int x;
+		error = uiomove(bp, len, uio);
+		if (error) break;
+		x = 0;
 		while (len > 0) {
-			u_int8_t tcr;
-			size_t size = len;
-			DMA_SETUP(lsi, &bp, &len, 0, &size);
-
-			/* Clear direction control bit */
-			tcr = bus_space_read_1(lsi->sc_bustag, lsi->sc_regs,
-						L64854_REG_TCR);
-			tcr &= ~BPP_TCR_DIR;
+			if (tcr_wait(sc,0,BPP_TCR_BUSY|BPP_TCR_ACK,"bppwr1")) goto out;
 			bus_space_write_1(lsi->sc_bustag, lsi->sc_regs,
-					  L64854_REG_TCR, tcr);
-
-			/* Enable DMA */
-			DMA_GO(lsi);
-			error = tsleep(sc, PZERO|PCATCH, "bppdma", 0);
-			if (error != 0)
-				goto out;
-
-			/* Bail out if bottom half reported an error */
-			if ((error = sc->sc_error) != 0)
-				goto out;
+				L64854_REG_DR, ((unsigned char *)bp)[x]);
+			bus_space_write_1(lsi->sc_bustag, lsi->sc_regs,
+				L64854_REG_TCR, 0);
+			if (tcr_wait(sc,BPP_TCR_BUSY,0,"bppwr2")) goto out;
+			bus_space_write_1(lsi->sc_bustag, lsi->sc_regs,
+				L64854_REG_TCR, BPP_TCR_DS);
+			x ++;
+			len --;
 		}
 	}
 
@@ -492,3 +535,56 @@
 	}
 	return (1);
 }
+
+#if 0
+
+/* Old goop from bppwrite */
+
+	/*
+	 * Move data from user space into our private buffer
+	 * and start DMA.
+	 */
+	while (uio->uio_resid > 0) {
+		caddr_t bp = sc->sc_buf;
+		size_t len = min(sc->sc_bufsz, uio->uio_resid);
+
+printf("bppwrite: uio_resid %d",(int)uio->uio_resid);
+
+		if ((error = uiomove(bp, len, uio)) != 0)
+			break;
+
+printf(" uiomoved %d\n",(int)len);
+
+		while (len > 0) {
+			u_int8_t tcr;
+			size_t size = len;
+printf("bppwrite: len=%d",(int)len);
+			DMA_SETUP(lsi, &bp, &len, 0, &size);
+
+printf(" size=%d",(int)size);
+			/* Clear direction control bit */
+			tcr = bus_space_read_1(lsi->sc_bustag, lsi->sc_regs,
+						L64854_REG_TCR);
+			tcr &= ~BPP_TCR_DIR;
+			bus_space_write_1(lsi->sc_bustag, lsi->sc_regs,
+					  L64854_REG_TCR, tcr);
+
+			/* Enable DMA */
+s = splbpp();
+			DMA_GO(lsi);
+			error = tsleep(sc, PZERO|PCATCH, "bppdma", 0);
+splx(s);
+			if (error != 0)
+				goto out;
+
+			/* Bail out if bottom half reported an error */
+			if ((error = sc->sc_error) != 0)
+				goto out;
+
+printf(" done\n");
+			/* done via sc_dmalen, by lsi64854_pp_intr */
+			/* len -= size; */
+		}
+	}
+
+#endif

					der Mouse

			       mouse@rodents.montreal.qc.ca
		     7D C8 61 52 5D E7 2D 39  4E F1 31 3E E8 B3 27 4B