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.
This commit is contained in:
parent
1f332d86bf
commit
5c55d9c1df
@ -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);
|
||||
|
||||
@ -87,6 +88,27 @@ adb_bus_probe(device_t dev)
|
||||
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++;
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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];
|
||||
|
Loading…
x
Reference in New Issue
Block a user