diff options
author | Miod Vallat <miod@cvs.openbsd.org> | 2004-05-09 22:02:39 +0000 |
---|---|---|
committer | Miod Vallat <miod@cvs.openbsd.org> | 2004-05-09 22:02:39 +0000 |
commit | ce47637275a21e72b2f8d11c278fa40896ac7374 (patch) | |
tree | a50aab987f60169af49e0610fb49c7d013ff9cb2 /sys/arch | |
parent | b79e65db5ceb7390edb67bdb7d946393d2d1ff34 (diff) |
Replace the event queue with a bit mask of slots needing attention, as
done in stp(4).
Diffstat (limited to 'sys/arch')
-rw-r--r-- | sys/arch/sparc/dev/ts102.c | 128 |
1 files changed, 49 insertions, 79 deletions
diff --git a/sys/arch/sparc/dev/ts102.c b/sys/arch/sparc/dev/ts102.c index d779c35d888..3ffcad50119 100644 --- a/sys/arch/sparc/dev/ts102.c +++ b/sys/arch/sparc/dev/ts102.c @@ -1,6 +1,6 @@ -/* $OpenBSD: ts102.c,v 1.11 2004/05/04 16:59:31 grange Exp $ */ +/* $OpenBSD: ts102.c,v 1.12 2004/05/09 22:02:38 miod Exp $ */ /* - * Copyright (c) 2003, Miodrag Vallat. + * Copyright (c) 2003, 2004, Miodrag Vallat. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -67,7 +67,6 @@ #include <sys/conf.h> #include <sys/device.h> #include <sys/kthread.h> -#include <sys/malloc.h> #include <sys/proc.h> #include <sys/queue.h> @@ -99,23 +98,6 @@ struct tslot_softc; /* - * Slot event structure - */ -struct tslot_event { - SIMPLEQ_ENTRY(tslot_event) te_q; - int te_what; - int te_slot; -}; - -#define TSLOT_EVENT_INSERT 0 -#define TSLOT_EVENT_REMOVE 1 - -const char *tslot_event_descr[] = { - "insertion", - "removal" -}; - -/* * Per-slot data */ struct tslot_data { @@ -145,7 +127,7 @@ struct tslot_softc { pcmcia_chipset_tag_t sc_pct; struct proc *sc_thread; /* event thread */ - SIMPLEQ_HEAD(, tslot_event) sc_events; + unsigned int sc_events; /* sockets with pending events */ struct tslot_data sc_slot[TS102_NUM_SLOTS]; }; @@ -171,7 +153,7 @@ int tslot_mem_map(pcmcia_chipset_handle_t, int, bus_addr_t, bus_size_t, struct pcmcia_mem_handle *, bus_addr_t *, int *); void tslot_mem_unmap(pcmcia_chipset_handle_t, int); int tslot_print(void *, const char *); -int tslot_queue_event(struct tslot_softc *, int, int); +void tslot_queue_event(struct tslot_softc *, int); void tslot_reset(struct tslot_data *, u_int32_t); void tslot_slot_disable(pcmcia_chipset_handle_t); void tslot_slot_enable(pcmcia_chipset_handle_t); @@ -269,7 +251,7 @@ tslot_attach(struct device *parent, struct device *self, void *args) /* * Setup asynchronous event handler */ - SIMPLEQ_INIT(&sc->sc_events); + sc->sc_events = 0; kthread_create_deferred(tslot_create_event_thread, sc); sc->sc_pct = (pcmcia_chipset_tag_t)&tslot_functions; @@ -404,7 +386,8 @@ tslot_io_map(pcmcia_chipset_handle_t pch, int width, bus_addr_t offset, #endif pih->iot = &td->td_rr; - pih->ioh = (bus_space_handle_t)(td->td_space[TS102_RANGE_IO]); + bus_space_subregion(&td->td_rr, td->td_space[TS102_RANGE_IO], + offset, size, &pih->ioh); *windowp = TS102_RANGE_IO; #ifdef TSLOT_DEBUG @@ -464,7 +447,8 @@ tslot_mem_map(pcmcia_chipset_handle_t pch, int kind, bus_addr_t addr, addr += pmh->addr; pmh->memt = &td->td_rr; - pmh->memh = (bus_space_handle_t)(td->td_space[slot] + addr); + bus_space_subregion(&td->td_rr, td->td_space[slot], + addr, size, &pmh->memh); pmh->realsize = TS102_ARBITRARY_MAP_SIZE - addr; *offsetp = 0; *windowp = slot; @@ -517,7 +501,7 @@ tslot_slot_enable(pcmcia_chipset_handle_t pch) td->td_parent->sc_dev.dv_xname, td->td_slot); #endif - /* Pover down the socket to reset it */ + /* Power down the socket to reset it */ status = TSLOT_READ(td, TS102_REG_CARD_A_STS); TSLOT_WRITE(td, TS102_REG_CARD_A_STS, status | TS102_CARD_STS_VCCEN); @@ -568,6 +552,7 @@ tslot_slot_enable(pcmcia_chipset_handle_t pch) */ for (i = 30000; i != 0; i--) { status = TSLOT_READ(td, TS102_REG_CARD_A_STS); + /* If the card has been removed, abort */ if ((status & TS102_CARD_STS_PRES) == 0) { tslot_slot_disable(pch); return; @@ -619,47 +604,46 @@ tslot_event_thread(void *v) { struct tslot_softc *sc = v; struct tslot_data *td; - struct tslot_event *te; - int s; + int s, status; + unsigned int socket; for (;;) { s = splhigh(); - if ((te = SIMPLEQ_FIRST(&sc->sc_events)) == NULL) { + if ((socket = ffs(sc->sc_events)) == 0) { splx(s); tsleep(&sc->sc_events, PWAIT, "tslot_event", 0); continue; } - - SIMPLEQ_REMOVE_HEAD(&sc->sc_events, te_q); + socket--; + sc->sc_events &= ~(1 << socket); splx(s); - if (te->te_slot >= TS102_NUM_SLOTS) { + if (socket >= TS102_NUM_SLOTS) { +#ifdef DEBUG printf("%s: invalid slot number %d\n", sc->sc_dev.dv_xname, te->te_slot); +#endif + continue; + } + + td = &sc->sc_slot[socket]; + status = TSLOT_READ(td, TS102_REG_CARD_A_STS); + + if (status & TS102_CARD_STS_PRES) { + /* Card insertion */ + if ((td->td_status & TS_CARD) == 0) { + td->td_status |= TS_CARD; + pcmcia_card_attach(td->td_pcmcia); + } } else { - td = &sc->sc_slot[te->te_slot]; - switch (te->te_what) { - case TSLOT_EVENT_INSERT: - if ((td->td_status & TS_CARD) == 0) { - td->td_status |= TS_CARD; - pcmcia_card_attach(td->td_pcmcia); - } - break; - case TSLOT_EVENT_REMOVE: - if ((td->td_status & TS_CARD) != 0) { - td->td_status &= ~TS_CARD; - pcmcia_card_detach(td->td_pcmcia, - DETACH_FORCE); - } - break; - default: - printf("%s: invalid event type %d on slot %d\n", - sc->sc_dev.dv_xname, - te->te_slot, te->te_what); + /* Card removal */ + if ((td->td_status & TS_CARD) != 0) { + td->td_status &= ~TS_CARD; + pcmcia_card_detach(td->td_pcmcia, + DETACH_FORCE); } } - free(te, M_TEMP); } } @@ -717,38 +701,27 @@ tslot_intr(void *v) return (rc); } -int -tslot_queue_event(struct tslot_softc *sc, int slot, int what) +void +tslot_queue_event(struct tslot_softc *sc, int slot) { - struct tslot_event *te; int s; - te = malloc(sizeof(*te), M_TEMP, M_NOWAIT); - if (te == NULL) { - printf("%s: %s event lost on slot %d\n", - sc->sc_dev.dv_xname, tslot_event_descr[what], slot); - return (ENOMEM); - } - - te->te_what = what; - te->te_slot = slot; s = splhigh(); - SIMPLEQ_INSERT_TAIL(&sc->sc_events, te, te_q); + sc->sc_events |= (1 << slot); splx(s); wakeup(&sc->sc_events); - - return (0); } void tslot_slot_intr(struct tslot_data *td, int intreg) { + struct tslot_softc *sc = td->td_parent; int status, sockstat; status = TSLOT_READ(td, TS102_REG_CARD_A_STS); #ifdef TSLOT_DEBUG printf("%s: interrupt on socket %d ir %x sts %x\n", - td->td_parent->sc_dev.dv_xname, td->td_slot, intreg, status); + sc->sc_dev.dv_xname, td->td_slot, intreg, status); #endif sockstat = td->td_status; @@ -763,17 +736,10 @@ tslot_slot_intr(struct tslot_data *td, int intreg) if ((intreg & TS102_CARD_INT_STATUS_CARDDETECT_STATUS_CHANGED) != 0 && (intreg & TS102_CARD_INT_MASK_CARDDETECT_STATUS) != 0) { - if (status & TS102_CARD_STS_PRES) { - tslot_queue_event(td->td_parent, - td->td_slot, TSLOT_EVENT_INSERT); - } else { - tslot_queue_event(td->td_parent, td->td_slot, - TSLOT_EVENT_REMOVE); - } + tslot_queue_event(sc, td->td_slot); #ifdef TSLOT_DEBUG printf("%s: slot %d status changed from %d to %d\n", - td->td_parent->sc_dev.dv_xname, - td->td_slot, sockstat, td->td_status); + sc->sc_dev.dv_xname, td->td_slot, sockstat, td->td_status); #endif /* * Ignore extra interrupt bits, they are part of the change. @@ -783,9 +749,13 @@ tslot_slot_intr(struct tslot_data *td, int intreg) if ((intreg & TS102_CARD_INT_STATUS_IRQ) != 0 && (intreg & TS102_CARD_INT_MASK_IRQ) != 0) { - if (sockstat != TS_CARD) { + /* ignore interrupts if we have a pending state change */ + if (sc->sc_events & (1 << td->td_slot)) + return; + + if ((sockstat & TS_CARD) == 0) { printf("%s: spurious interrupt on slot %d isr %x\n", - td->td_parent->sc_dev.dv_xname, td->td_slot, intreg); + sc->sc_dev.dv_xname, td->td_slot, intreg); return; } |