svn commit: r184473 - in head/sys: dev/adb powerpc/powermac

Nathan Whitehorn nwhitehorn at FreeBSD.org
Thu Oct 30 08:27:13 PDT 2008


Author: nwhitehorn
Date: Thu Oct 30 15:27:13 2008
New Revision: 184473
URL: http://svn.freebsd.org/changeset/base/184473

Log:
  Fix some possible infinite loops in the ADB code, and remove some hacks
  that were inserted in desperation during bring-up. In addition, move ADB bus
  enumeration and child attachment to when interrupts are available.

Modified:
  head/sys/dev/adb/adb_bus.c
  head/sys/dev/adb/adbvar.h
  head/sys/powerpc/powermac/cuda.c
  head/sys/powerpc/powermac/pmu.c

Modified: head/sys/dev/adb/adb_bus.c
==============================================================================
--- head/sys/dev/adb/adb_bus.c	Thu Oct 30 14:30:49 2008	(r184472)
+++ head/sys/dev/adb/adb_bus.c	Thu Oct 30 15:27:13 2008	(r184473)
@@ -44,6 +44,7 @@
 static int adb_bus_probe(device_t dev);
 static int adb_bus_attach(device_t dev);
 static int adb_bus_detach(device_t dev);
+static void adb_bus_enumerate(void *xdev);
 static void adb_probe_nomatch(device_t dev, device_t child);
 static int adb_print_child(device_t dev, device_t child);
 
@@ -88,6 +89,27 @@ static int
 adb_bus_attach(device_t dev)
 {
 	struct adb_softc *sc = device_get_softc(dev);
+	sc->enum_hook.ich_func = adb_bus_enumerate;
+	sc->enum_hook.ich_arg = dev;
+
+	/*
+	 * We should wait until interrupts are enabled to try to probe
+	 * the bus. Enumerating the ADB involves receiving packets,
+	 * which works best with interrupts enabled.
+	 */
+	
+	if (config_intrhook_establish(&sc->enum_hook) != 0)
+		return (ENOMEM);
+
+	return (0);
+}
+	
+static void
+adb_bus_enumerate(void *xdev)
+{
+	device_t dev = (device_t)xdev;
+
+	struct adb_softc *sc = device_get_softc(dev);
 	uint8_t i, next_free;
 	uint16_t r3;
 
@@ -165,7 +187,9 @@ adb_bus_attach(device_t dev)
 		}
 	}
 
-	return (bus_generic_attach(dev));
+	bus_generic_attach(dev);
+
+	config_intrhook_disestablish(&sc->enum_hook);
 }
 
 static int adb_bus_detach(device_t dev)
@@ -315,10 +339,13 @@ adb_send_raw_packet_sync(device_t dev, u
 	ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, len, data, 1);
 
 	while (!atomic_fetchadd_int(&sc->packet_reply,0)) {
-		/* Sometimes CUDA controllers hang up during cold boots.
-		   Try poking them. */
-		if (i > 10)
-			ADB_HB_CONTROLLER_POLL(sc->parent);
+		/*
+		 * Maybe the command got lost? Try resending and polling the 
+		 * controller.
+		 */
+		if (i > 40)
+			ADB_HB_SEND_RAW_PACKET(sc->parent, command_byte, 
+			    len, data, 1);
 
 		DELAY(100);
 		i++;

Modified: head/sys/dev/adb/adbvar.h
==============================================================================
--- head/sys/dev/adb/adbvar.h	Thu Oct 30 14:30:49 2008	(r184472)
+++ head/sys/dev/adb/adbvar.h	Thu Oct 30 15:27:13 2008	(r184473)
@@ -37,16 +37,15 @@ enum {
 
 struct adb_softc {
 	device_t	sc_dev;
-
 	device_t	parent;
 
+	struct intr_config_hook enum_hook;
 	struct mtx	sc_sync_mtx;
 	
 	volatile int 	sync_packet;
 	volatile int	packet_reply;
 
 	uint16_t	autopoll_mask;
-
 	uint8_t		syncreg[8];
 
 	device_t	children[16];

Modified: head/sys/powerpc/powermac/cuda.c
==============================================================================
--- head/sys/powerpc/powermac/cuda.c	Thu Oct 30 14:30:49 2008	(r184472)
+++ head/sys/powerpc/powermac/cuda.c	Thu Oct 30 15:27:13 2008	(r184473)
@@ -341,10 +341,7 @@ cuda_send(void *cookie, int poll, int le
 
 	mtx_lock(&sc->sc_mutex);
 
-	if ((sc->sc_state == CUDA_IDLE) /*&& 
-	    ((cuda_read_reg(sc, vBufB) & vPB3) == vPB3)*/) {
-		/* fine */
-	} else {
+	if (sc->sc_state != CUDA_IDLE) {
 		if (sc->sc_waiting == 0) {
 			sc->sc_waiting = 1;
 		} else {
@@ -381,12 +378,12 @@ cuda_poll(device_t dev)
 {
 	struct cuda_softc *sc = device_get_softc(dev);
 
-	while ((sc->sc_state != CUDA_IDLE) ||
-	       (cuda_intr_state(sc)) ||
-	       (sc->sc_waiting == 1)) {
-		if ((cuda_read_reg(sc, vIFR) & vSR_INT) == vSR_INT)
-			cuda_intr(dev);
-	}
+	if (sc->sc_state == CUDA_IDLE && !cuda_intr_state(sc) && 
+	    !sc->sc_waiting)
+		return;
+
+	if ((cuda_read_reg(sc, vIFR) & vSR_INT) == vSR_INT)
+		cuda_intr(dev);
 }
 
 static void
@@ -615,6 +612,7 @@ cuda_adb_autopoll(device_t dev, uint16_t
 	uint8_t cmd[] = {CUDA_PSEUDO, CMD_AUTOPOLL, mask != 0};
 
 	mtx_lock(&sc->sc_mutex);
+
 	if (cmd[2] == sc->sc_autopoll) {
 		mtx_unlock(&sc->sc_mutex);
 		return 0;
@@ -624,18 +622,10 @@ cuda_adb_autopoll(device_t dev, uint16_t
 		mtx_sleep(dev,&sc->sc_mutex,0,"cuda",1);
 
 	sc->sc_autopoll = -1;
-	mtx_unlock(&sc->sc_mutex);
-
 	cuda_send(sc, 0, 3, cmd);
-	
-	mtx_lock(&sc->sc_mutex);
-	while(sc->sc_autopoll == -1) {
-		mtx_sleep(dev,&sc->sc_mutex,0,"cuda",100);
-		cuda_poll(dev);
-	}
 
 	mtx_unlock(&sc->sc_mutex);
-
+	
 	return 0;
 }
 

Modified: head/sys/powerpc/powermac/pmu.c
==============================================================================
--- head/sys/powerpc/powermac/pmu.c	Thu Oct 30 14:30:49 2008	(r184472)
+++ head/sys/powerpc/powermac/pmu.c	Thu Oct 30 15:27:13 2008	(r184473)
@@ -591,8 +591,6 @@ pmu_adb_autopoll(device_t dev, uint16_t 
 {
 	struct pmu_softc *sc = device_get_softc(dev);
 
-	mask = 0xffff;
-
 	/* magical incantation to re-enable autopolling */
 	uint8_t cmd[] = {0, PMU_SET_POLL_MASK, (mask >> 8) & 0xff, mask & 0xff};
 	uint8_t resp[16];


More information about the svn-src-all mailing list