summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authornwhitehorn <nwhitehorn@FreeBSD.org>2008-10-30 15:27:13 +0000
committernwhitehorn <nwhitehorn@FreeBSD.org>2008-10-30 15:27:13 +0000
commit5c55d9c1df94b43c6addfdaa79a82e6f779b6cd1 (patch)
tree809d8cc03b1cf718c388d7e5d5e3820507adf952
parent1f332d86bf5e4cfc63df682d8859c4f4fac21026 (diff)
downloadFreeBSD-src-5c55d9c1df94b43c6addfdaa79a82e6f779b6cd1.zip
FreeBSD-src-5c55d9c1df94b43c6addfdaa79a82e6f779b6cd1.tar.gz
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.
-rw-r--r--sys/dev/adb/adb_bus.c37
-rw-r--r--sys/dev/adb/adbvar.h3
-rw-r--r--sys/powerpc/powermac/cuda.c28
-rw-r--r--sys/powerpc/powermac/pmu.c2
4 files changed, 42 insertions, 28 deletions
diff --git a/sys/dev/adb/adb_bus.c b/sys/dev/adb/adb_bus.c
index cc31a9d..9a2a7fa 100644
--- a/sys/dev/adb/adb_bus.c
+++ b/sys/dev/adb/adb_bus.c
@@ -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, uint8_t to, uint8_t command,
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++;
diff --git a/sys/dev/adb/adbvar.h b/sys/dev/adb/adbvar.h
index da0965d..e70aa75 100644
--- a/sys/dev/adb/adbvar.h
+++ b/sys/dev/adb/adbvar.h
@@ -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];
diff --git a/sys/powerpc/powermac/cuda.c b/sys/powerpc/powermac/cuda.c
index 162c639..c17ca82 100644
--- a/sys/powerpc/powermac/cuda.c
+++ b/sys/powerpc/powermac/cuda.c
@@ -341,10 +341,7 @@ cuda_send(void *cookie, int poll, int length, uint8_t *msg)
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 mask) {
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 mask) {
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;
}
diff --git a/sys/powerpc/powermac/pmu.c b/sys/powerpc/powermac/pmu.c
index a5a5450..b5dcdf8 100644
--- a/sys/powerpc/powermac/pmu.c
+++ b/sys/powerpc/powermac/pmu.c
@@ -591,8 +591,6 @@ pmu_adb_autopoll(device_t dev, uint16_t mask)
{
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];
OpenPOWER on IntegriCloud