summaryrefslogtreecommitdiffstats
path: root/sys/dev/adb
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 /sys/dev/adb
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.
Diffstat (limited to 'sys/dev/adb')
-rw-r--r--sys/dev/adb/adb_bus.c37
-rw-r--r--sys/dev/adb/adbvar.h3
2 files changed, 33 insertions, 7 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];
OpenPOWER on IntegriCloud