diff options
author | Dale Rahn <drahn@cvs.openbsd.org> | 2008-12-08 20:50:21 +0000 |
---|---|---|
committer | Dale Rahn <drahn@cvs.openbsd.org> | 2008-12-08 20:50:21 +0000 |
commit | 32586c93d9c8486427718b1e0f474c37a30a2bc8 (patch) | |
tree | c303bf93840d6a27b36500b9bf622c308b0cdf2c | |
parent | e635ed2fe5cf33d147a802ab7ca27cbe5c73d1a5 (diff) |
some sscom and interrupt cleanup, closer to usable userland.
-rw-r--r-- | sys/arch/arm/s3c2xx0/s3c2410_intr.c | 53 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/s3c2410_intr.h | 3 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/s3c24x0_intr.h | 12 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/s3c2xx0_intr.c | 19 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/s3c2xx0_intr.h | 74 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/sscom.c | 142 | ||||
-rw-r--r-- | sys/arch/arm/s3c2xx0/sscom_s3c2410.c | 7 |
7 files changed, 124 insertions, 186 deletions
diff --git a/sys/arch/arm/s3c2xx0/s3c2410_intr.c b/sys/arch/arm/s3c2xx0/s3c2410_intr.c index 79089f8ddd2..67472fbc56d 100644 --- a/sys/arch/arm/s3c2xx0/s3c2410_intr.c +++ b/sys/arch/arm/s3c2xx0/s3c2410_intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3c2410_intr.c,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: s3c2410_intr.c,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: s3c2410_intr.c,v 1.11 2008/11/24 11:29:52 dogcow Exp $ */ /* @@ -50,6 +50,7 @@ __KERNEL_RCSID(0, "$NetBSD: s3c2410_intr.c,v 1.11 2008/11/24 11:29:52 dogcow Exp #include <arm/s3c2xx0/s3c2410reg.h> #include <arm/s3c2xx0/s3c2410var.h> +#include <arm/s3c2xx0/s3c2xx0_intr.h> /* * interrupt dispatch table. @@ -59,11 +60,6 @@ struct s3c2xx0_intr_dispatch handler[ICU_LEN]; extern volatile uint32_t *s3c2xx0_intr_mask_reg; -volatile int intr_mask; -#ifdef __HAVE_FAST_SOFTINTS -volatile int softint_pending; -volatile int soft_intr_mask; -#endif volatile int global_intr_mask = 0; /* mask some interrupts at all spl level */ /* interrupt masks for each level */ @@ -83,7 +79,9 @@ vaddr_t intctl_base; /* interrupt controller registers */ * Map a software interrupt queue to an interrupt priority level. */ static const int si_to_ipl[] = { +#ifdef SI_SOFTBIO [SI_SOFTBIO] = IPL_SOFTBIO, +#endif [SI_SOFTCLOCK] = IPL_SOFTCLOCK, [SI_SOFTNET] = IPL_SOFTNET, [SI_SOFTSERIAL] = IPL_SOFTSERIAL, @@ -92,10 +90,23 @@ static const int si_to_ipl[] = { #define PENDING_CLEAR_MASK (~0) +int debug_update_hw; +void +s3c2xx0_update_hw_mask(void) +{ + if (debug_update_hw != NULL) + printf("setting irq mask to ~(%x & %x) = %x\n", + s3c2xx0_imask[s3c2xx0_curcpl()], global_intr_mask, + ~(s3c2xx0_imask[s3c2xx0_curcpl()] & global_intr_mask)); + (*s3c2xx0_intr_mask_reg = + ~(s3c2xx0_imask[s3c2xx0_curcpl()] & global_intr_mask)); +} + /* * called from irq_entry. */ void s3c2410_irq_handler(struct clockframe *); + void s3c2410_irq_handler(struct clockframe *frame) { @@ -145,7 +156,11 @@ s3c2410_irq_handler(struct clockframe *frame) } #ifdef __HAVE_FAST_SOFTINTS +#if 0 cpu_dosoftints(); +#else + s3c2xx0_irq_do_pending(); +#endif #endif } @@ -265,32 +280,6 @@ init_interrupt_masks(void) for (i=0; i < NIPL; ++i) s3c2xx0_imask[i] = 0; -#ifdef __HAVE_FAST_SOFTINTS - s3c24x0_soft_imask[IPL_NONE] = SI_TO_IRQBIT(SI_SOFTSERIAL) | - SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK) | - SI_TO_IRQBIT(SI_SOFT); - - s3c24x0_soft_imask[IPL_SOFT] = SI_TO_IRQBIT(SI_SOFTSERIAL) | - SI_TO_IRQBIT(SI_SOFTNET) | SI_TO_IRQBIT(SI_SOFTCLOCK); - - /* - * splsoftclock() is the only interface that users of the - * generic software interrupt facility have to block their - * soft intrs, so splsoftclock() must also block IPL_SOFT. - */ - s3c24x0_soft_imask[IPL_SOFTCLOCK] = SI_TO_IRQBIT(SI_SOFTSERIAL) | - SI_TO_IRQBIT(SI_SOFTNET); - - /* - * splsoftnet() must also block splsoftclock(), since we don't - * want timer-driven network events to occur while we're - * processing incoming packets. - */ - s3c24x0_soft_imask[IPL_SOFTNET] = SI_TO_IRQBIT(SI_SOFTSERIAL); - - for (i = IPL_BIO; i < IPL_SOFTSERIAL; ++i) - s3c24x0_soft_imask[i] = SI_TO_IRQBIT(SI_SOFTSERIAL); -#endif } void diff --git a/sys/arch/arm/s3c2xx0/s3c2410_intr.h b/sys/arch/arm/s3c2xx0/s3c2410_intr.h index 8f03fa5d639..fba531be34e 100644 --- a/sys/arch/arm/s3c2xx0/s3c2410_intr.h +++ b/sys/arch/arm/s3c2xx0/s3c2410_intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: s3c2410_intr.h,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: s3c2410_intr.h,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: s3c2410_intr.h,v 1.2 2005/12/11 12:16:51 christos Exp $ */ /* @@ -34,6 +34,7 @@ #define _S3C2410_INTR_H_ #define ARM_IRQ_HANDLER _C_LABEL(s3c2410_irq_handler) +#define __HAVE_FAST_SOFTINTS #include <arm/s3c2xx0/s3c24x0_intr.h> diff --git a/sys/arch/arm/s3c2xx0/s3c24x0_intr.h b/sys/arch/arm/s3c2xx0/s3c24x0_intr.h index 79f86bc1b43..b713536cbb4 100644 --- a/sys/arch/arm/s3c2xx0/s3c24x0_intr.h +++ b/sys/arch/arm/s3c2xx0/s3c24x0_intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: s3c24x0_intr.h,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: s3c24x0_intr.h,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: s3c24x0_intr.h,v 1.8 2008/04/27 18:58:45 matt Exp $ */ /* @@ -39,16 +39,10 @@ #define SI_TO_IRQBIT(si) (1<<(si)) /* no room for softinterrupts in intr_mask. */ -extern int volatile soft_intr_mask; -extern int s3c24x0_soft_imask[]; - -#define get_pending_softint() (softint_pending & soft_intr_mask) -#define update_softintr_mask() \ - (soft_intr_mask = s3c24x0_soft_imask[curcpl()]) +extern int s3c24x0_smask[]; #endif -#define s3c2xx0_update_hw_mask() \ - (*s3c2xx0_intr_mask_reg = ~(intr_mask & global_intr_mask)) +void s3c2xx0_update_hw_mask(void); #include <arm/s3c2xx0/s3c2xx0_intr.h> diff --git a/sys/arch/arm/s3c2xx0/s3c2xx0_intr.c b/sys/arch/arm/s3c2xx0/s3c2xx0_intr.c index d737885eaa0..e31ccb12dfe 100644 --- a/sys/arch/arm/s3c2xx0/s3c2xx0_intr.c +++ b/sys/arch/arm/s3c2xx0/s3c2xx0_intr.c @@ -1,4 +1,4 @@ -/* $OpenBSD: s3c2xx0_intr.c,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: s3c2xx0_intr.c,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: s3c2xx0_intr.c,v 1.13 2008/04/27 18:58:45 matt Exp $ */ /* @@ -92,12 +92,13 @@ __KERNEL_RCSID(0, "$NetBSD: s3c2xx0_intr.c,v 1.13 2008/04/27 18:58:45 matt Exp $ #include <arm/s3c2xx0/s3c2xx0_intr.h> volatile uint32_t *s3c2xx0_intr_mask_reg; -extern volatile int intr_mask; extern volatile int global_intr_mask; int s3c2xx0_cpl; +#if 0 #define SI_TO_IRQBIT(x) (1 << (x)) +#endif int s3c2xx0_curcpl() @@ -255,11 +256,7 @@ void s3c2xx0_setipl(int new) { s3c2xx0_set_curcpl(new); - intr_mask = s3c2xx0_imask[s3c2xx0_curcpl()]; s3c2xx0_update_hw_mask(); -#ifdef __HAVE_FAST_SOFTINTS - update_softintr_mask(); -#endif } @@ -273,7 +270,7 @@ s3c2xx0_splx(int new) restore_interrupts(psw); #ifdef __HAVE_FAST_SOFTINTS - cpu_dosoftints(); + s3c2xx0_irq_do_pending(); #endif } @@ -304,9 +301,8 @@ s3c2xx0_spllower(int ipl) } /* XXX */ -void s3c2xx0_do_pending(void); -int softint_pending; +volatile int softint_pending; void s3c2xx0_setsoftintr(int si) { @@ -318,12 +314,12 @@ s3c2xx0_setsoftintr(int si) /* Process unmasked pending soft interrupts. */ if (softint_pending & s3c2xx0_smask[s3c2xx0_curcpl()]) - s3c2xx0_do_pending(); + s3c2xx0_irq_do_pending(); } void -s3c2xx0_do_pending(void) +s3c2xx0_irq_do_pending(void) { static int processing = 0; int oldirqstate, spl_save; @@ -360,4 +356,3 @@ s3c2xx0_do_pending(void) processing = 0; restore_interrupts(oldirqstate); } - diff --git a/sys/arch/arm/s3c2xx0/s3c2xx0_intr.h b/sys/arch/arm/s3c2xx0/s3c2xx0_intr.h index e311e265747..db6bbec75d8 100644 --- a/sys/arch/arm/s3c2xx0/s3c2xx0_intr.h +++ b/sys/arch/arm/s3c2xx0/s3c2xx0_intr.h @@ -1,4 +1,4 @@ -/* $OpenBSD: s3c2xx0_intr.h,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: s3c2xx0_intr.h,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: s3c2xx0_intr.h,v 1.13 2008/11/19 06:35:55 matt Exp $ */ /* @@ -121,7 +121,6 @@ typedef int (* s3c2xx0_irq_handler_t)(void *); extern volatile uint32_t *s3c2xx0_intr_mask_reg; -extern volatile int intr_mask; extern volatile int global_intr_mask; #ifdef __HAVE_FAST_SOFTINTS extern volatile int softint_pending; @@ -131,75 +130,6 @@ extern int s3c2xx0_ilevel[]; void s3c2xx0_update_intr_masks( int, int ); -static inline void -s3c2xx0_mask_interrupts(int mask) -{ - int save = disable_interrupts(I32_bit); - global_intr_mask &= ~mask; - s3c2xx0_update_hw_mask(); - restore_interrupts(save); -} - -static inline void -s3c2xx0_unmask_interrupts(int mask) -{ - int save = disable_interrupts(I32_bit); - global_intr_mask |= mask; - s3c2xx0_update_hw_mask(); - restore_interrupts(save); -} - -static inline void -s3c2xx0_setipl(int new) -{ - set_curcpl(new); - intr_mask = s3c2xx0_imask[curcpl()]; - s3c2xx0_update_hw_mask(); -#ifdef __HAVE_FAST_SOFTINTS - update_softintr_mask(); -#endif -} - - -static inline void -s3c2xx0_splx(int new) -{ - int psw; - - psw = disable_interrupts(I32_bit); - s3c2xx0_setipl(new); - restore_interrupts(psw); - -#ifdef __HAVE_FAST_SOFTINTS - cpu_dosoftints(); -#endif -} - - -static inline int -s3c2xx0_splraise(int ipl) -{ - int old, psw; - - old = curcpl(); - if( ipl > old ){ - psw = disable_interrupts(I32_bit); - s3c2xx0_setipl(ipl); - restore_interrupts(psw); - } - - return (old); -} - -static inline int -s3c2xx0_spllower(int ipl) -{ - int old = curcpl(); - int psw = disable_interrupts(I32_bit); - s3c2xx0_splx(ipl); - restore_interrupts(psw); - return(old); -} int _splraise(int); int _spllower(int); @@ -263,4 +193,6 @@ void s3c2xx0_intr_init(struct s3c2xx0_intr_dispatch *, int ); void s3c2xx0_intr_bootstrap(vaddr_t); #endif +void s3c2xx0_irq_do_pending(void); + #endif /* _S3C2XX0_INTR_H_ */ diff --git a/sys/arch/arm/s3c2xx0/sscom.c b/sys/arch/arm/s3c2xx0/sscom.c index 5720382d626..8c1abac25d9 100644 --- a/sys/arch/arm/s3c2xx0/sscom.c +++ b/sys/arch/arm/s3c2xx0/sscom.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sscom.c,v 1.3 2008/11/27 11:38:02 drahn Exp $ */ +/* $OpenBSD: sscom.c,v 1.4 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: sscom.c,v 1.29 2008/06/11 22:37:21 cegger Exp $ */ /* @@ -154,6 +154,9 @@ __KERNEL_RCSID(0, "$NetBSD: sscom.c,v 1.29 2008/06/11 22:37:21 cegger Exp $"); #endif #include <arm/s3c2xx0/sscom_var.h> #include <dev/cons.h> +#ifdef DDB +#include <ddb/db_var.h> +#endif dev_type_open(sscomopen); dev_type_close(sscomclose); @@ -172,7 +175,6 @@ void sscomcnpollc (dev_t, int); void sscomsoft (void *); void sscom_rxsoft (struct sscom_softc *, struct tty *); -void sscom_txsoft (struct sscom_softc *, struct tty *); void sscom_stsoft (struct sscom_softc *, struct tty *); void sscom_schedrx (struct sscom_softc *); @@ -1385,25 +1387,6 @@ sscomstart(struct tty *tp) goto out; if (sc->sc_tx_stopped) goto out; -#if 0 - if (!ttypull(tp)) - goto out; - - /* Grab the first contiguous region of buffer space. */ - { - u_char *tba; - int tbc; - - tba = tp->t_outq.c_cf; - tbc = ndqb(&tp->t_outq, 0); - - (void)splserial(); - SSCOM_LOCK(sc); - - sc->sc_tba = tba; - sc->sc_tbc = tbc; - } -#else if (tp->t_outq.c_cc <= tp->t_lowat) { if (ISSET(tp->t_state, TS_ASLEEP)) { CLR(tp->t_state, TS_ASLEEP); @@ -1413,20 +1396,20 @@ sscomstart(struct tty *tp) goto out; selwakeup(&tp->t_wsel); } -#endif SET(tp->t_state, TS_BUSY); sc->sc_tx_busy = 1; - /* Output the first chunk of the contiguous buffer. */ + /* Output the first fifo worth of the buffer. */ sscom_output_chunk(sc); +out: /* Enable transmit completion interrupts if necessary. */ - if ((sc->sc_hwflags & SSCOM_HW_TXINT) == 0) + if (tp->t_outq.c_cc != 0) sscom_enable_txint(sc); + else + sscom_disable_txint(sc); /* track state in software? */ - SSCOM_UNLOCK(sc); -out: splx(s); return; } @@ -1511,7 +1494,9 @@ sscom_rxsoft(struct sscom_softc *sc, struct tty *tp) if (ISSET(rsr, UERSTAT_PARITY)) SET(code, TTY_PE); } - (*linesw[tp->t_line].l_rint)(rsr << 8 | code, tp); +// (*linesw[tp->t_line].l_rint)(rsr << 8 | code, tp); + /* what to do with rsr?, -> TTY_PE, TTYFE, or both */ + (*linesw[tp->t_line].l_rint)(code, tp); #if 0 if ((*rint)(code, tp) == -1) { @@ -1576,19 +1561,6 @@ sscom_rxsoft(struct sscom_softc *sc, struct tty *tp) } void -sscom_txsoft(struct sscom_softc *sc, struct tty *tp) -{ - - CLR(tp->t_state, TS_BUSY); - if (ISSET(tp->t_state, TS_FLUSH)) - CLR(tp->t_state, TS_FLUSH); - else - ndflush(&tp->t_outq, (int)(sc->sc_tba - tp->t_outq.c_cf)); - (*linesw[tp->t_line].l_start)(tp); - -} - -void sscom_stsoft(struct sscom_softc *sc, struct tty *tp) { u_char msr, delta; @@ -1613,9 +1585,11 @@ sscom_stsoft(struct sscom_softc *sc, struct tty *tp) if (ISSET(delta, sc->sc_msr_cts)) { /* Block or unblock output according to flow control. */ if (ISSET(msr, sc->sc_msr_cts)) { + struct tty *tp = sc->sc_tty; sc->sc_tx_stopped = 0; (*linesw[tp->t_line].l_start)(tp); } else { + printf("txstopped\n"); sc->sc_tx_stopped = 1; } } @@ -1647,11 +1621,6 @@ sscomsoft(void *arg) sc->sc_st_check = 0; sscom_stsoft(sc, tp); } - - if (sc->sc_tx_done) { - sc->sc_tx_done = 0; - sscom_txsoft(sc, tp); - } } #ifndef __HAVE_GENERIC_SOFT_INTERRUPTS timeout_add(&sc->sc_comsoft_tmo, 1); @@ -1684,13 +1653,14 @@ sscomrxintr(void *arg) do { u_char msts, delta; - u_char uerstat; uint16_t ufstat; + uint8_t utrstat, uerstat; ufstat = bus_space_read_2(iot, ioh, SSCOM_UFSTAT); /* XXX: break interrupt with no character? */ +#if 0 if ( (ufstat & (UFSTAT_RXCOUNT|UFSTAT_RXFULL)) && !ISSET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED)) { @@ -1768,6 +1738,68 @@ sscomrxintr(void *arg) bus_space_write_2(iot, ioh, SSCOM_UCON, sc->sc_ucon); } } +#else + utrstat = bus_space_read_2(iot, ioh, SSCOM_UTRSTAT); + if (utrstat & UTRSTAT_RXREADY) { + uerstat = bus_space_read_1((iot), (ioh), SSCOM_UERSTAT); + if (uerstat & UERSTAT_BREAK) { +#if defined(DDB) + if (db_console) + Debugger(); +#endif + goto next; + + } + /* xxx overflow */ + put[0] = bus_space_read_1((iot), (ioh), + SSCOM_URXH); + put[1] = uerstat; + put += 2; + if (put >= end) + put = sc->sc_rbuf; + cc--; +next: + ufstat = bus_space_read_2(iot, ioh, SSCOM_UFSTAT); + } + /* + * Current string of incoming characters ended because + * no more data was available or we ran out of space. + * Schedule a receive event if any data was received. + * If we're out of space, turn off receive interrupts. + */ + sc->sc_rbput = put; + sc->sc_rbavail = cc; + if (!ISSET(sc->sc_rx_flags, RX_TTY_OVERFLOWED)) + sc->sc_rx_ready = 1; + + /* + * See if we are in danger of overflowing a buffer. If + * so, use hardware flow control to ease the pressure. + */ + if (!ISSET(sc->sc_rx_flags, RX_IBUF_BLOCKED) && + cc < sc->sc_r_hiwat) { + SET(sc->sc_rx_flags, RX_IBUF_BLOCKED); + sscom_hwiflow(sc); + } + + /* + * If we're out of space, disable receive interrupts + * until the queue has drained a bit. + */ + if (!cc) { + SET(sc->sc_rx_flags, RX_IBUF_OVERFLOWED); + sscom_disable_rxint(sc); + sc->sc_ucon &= ~UCON_ERRINT; + bus_space_write_2(iot, ioh, SSCOM_UCON, sc->sc_ucon); + } +#endif + if (sc->sc_rbput != put) { + sc->sc_rx_ready = 1; + softintr_schedule(sc->sc_si); + sc->sc_st_check = 1; + } + sc->sc_rbput = put; + sc->sc_rbavail = cc; msts = sc->read_modem_status(sc); @@ -1928,24 +1960,16 @@ sscomtxintr(void *arg) */ if (sc->sc_hwflags & SSCOM_HW_TXINT) sscom_disable_txint(sc); - if (sc->sc_tx_busy) { - sc->sc_tx_busy = 0; - sc->sc_tx_done = 1; - } } #else if ( sc->sc_tty->t_outq.c_cc > 0) { - __sscom_output_chunk(sc, ufstat); + struct tty *tp = sc->sc_tty; + if (ISSET(tp->t_state, TS_BUSY)) { + CLR(tp->t_state, TS_BUSY | TS_FLUSH); + } + (*linesw[tp->t_line].l_start)(tp); } else { - /* - * Disable transmit sscompletion - * interrupts. - */ sscom_disable_txint(sc); - if (sc->sc_tx_busy) { - sc->sc_tx_busy = 0; - sc->sc_tx_done = 1; - } } #endif } diff --git a/sys/arch/arm/s3c2xx0/sscom_s3c2410.c b/sys/arch/arm/s3c2xx0/sscom_s3c2410.c index 07c03b9b762..0b84d383ef1 100644 --- a/sys/arch/arm/s3c2xx0/sscom_s3c2410.c +++ b/sys/arch/arm/s3c2xx0/sscom_s3c2410.c @@ -1,4 +1,4 @@ -/* $OpenBSD: sscom_s3c2410.c,v 1.1 2008/11/26 14:39:14 drahn Exp $ */ +/* $OpenBSD: sscom_s3c2410.c,v 1.2 2008/12/08 20:50:20 drahn Exp $ */ /* $NetBSD: sscom_s3c2410.c,v 1.2 2005/12/11 12:16:51 christos Exp $ */ /* @@ -143,7 +143,6 @@ sscom_attach(struct device *parent, struct device *self, void *aux) return; } - printf("\n"); s3c24x0_intr_establish(s3c2410_uart_config[unit].tx_int, IPL_SERIAL, IST_LEVEL, sscomtxintr, sc); @@ -152,6 +151,10 @@ sscom_attach(struct device *parent, struct device *self, void *aux) s3c24x0_intr_establish(s3c2410_uart_config[unit].err_int, IPL_SERIAL, IST_LEVEL, sscomrxintr, sc); sscom_disable_txrxint(sc); + printf(" txirq %d rxirq %d mirq %d\n", + s3c2410_uart_config[unit].tx_int, + s3c2410_uart_config[unit].rx_int, + s3c2410_uart_config[unit].err_int); sscom_attach_subr(sc); } |