-/* $OpenBSD: sbbc.c,v 1.3 2008/07/10 20:27:36 kettenis Exp $ */
+/* $OpenBSD: sbbc.c,v 1.4 2008/07/12 23:12:52 kettenis Exp $ */
/*
* Copyright (c) 2008 Mark Kettenis
*
struct sparc_bus_space_tag sc_bbt;
struct tty *sc_tty;
- struct timeout sc_to;
caddr_t sc_sram_cons;
uint32_t *sc_sram_solscie;
uint32_t *sc_sram_solscir;
uint32_t *sc_sram_scsolie;
uint32_t *sc_sram_scsolir;
+ void *sc_cons_si;
};
struct sbbc_softc *sbbc_cons_input;
int sbbc_tod_settime(todr_chip_handle_t, struct timeval *);
void sbbc_attach_cons(struct sbbc_softc *, uint32_t);
+void sbbc_intr_cons(struct sbbc_softc *, uint32_t);
+void sbbc_softintr_cons(void *);
int sbbc_cnlookc(dev_t, int *);
int sbbc_cngetc(dev_t);
void sbbc_cnputc(dev_t, int);
void sbbcstart(struct tty *);
int sbbcparam(struct tty *, struct termios *);
-void sbbctimeout(void *);
int
sbbc_match(struct device *parent, void *match, void *aux)
reason = *sc->sc_sram_scsolir;
*sc->sc_sram_scsolir = 0;
-#ifdef DDB
- if (reason & SBBC_SRAM_CONS_BRK && sc == sbbc_cons_input) {
- if (db_console)
- Debugger();
- }
-#endif
+ sbbc_intr_cons(sc, reason);
/* Ack interrupt. */
bus_space_write_4(sc->sc_iot, sc->sc_regs_ioh,
sbbc_cons_input = sbbc_cons_output = sc;
sgcn_is_input = sgcn_is_output = 0;
- timeout_set(&sc->sc_to, sbbctimeout, sc);
+ sc->sc_cons_si = softintr_establish(IPL_TTY, sbbc_softintr_cons, sc);
+ if (sc->sc_cons_si == NULL)
+ panic("%s: can't establish soft interrupt",
+ sc->sc_dv.dv_xname);
*sc->sc_sram_solscie |= SBBC_SRAM_CONS_OUT;
- *sc->sc_sram_scsolie |= SBBC_SRAM_CONS_BRK;
+ *sc->sc_sram_scsolie |= SBBC_SRAM_CONS_IN | SBBC_SRAM_CONS_BRK;
/* Take over console input. */
prom_serengeti_set_console_input("CON_CLNT");
}
}
+void
+sbbc_intr_cons(struct sbbc_softc *sc, uint32_t reason)
+{
+#ifdef DDB
+ if ((reason & SBBC_SRAM_CONS_BRK) && sc == sbbc_cons_input) {
+ if (db_console)
+ Debugger();
+ }
+#endif
+
+ if ((reason & SBBC_SRAM_CONS_IN) && sc->sc_tty)
+ softintr_schedule(sc->sc_cons_si);
+}
+
+void
+sbbc_softintr_cons(void *arg)
+{
+ struct sbbc_softc *sc = arg;
+ struct sbbc_sram_cons *cons = (void *)sc->sc_sram_cons;
+ uint32_t rdptr = cons->cons_in_rdptr;
+ struct tty *tp = sc->sc_tty;
+ int c;
+
+ while (rdptr != cons->cons_in_wrptr) {
+ if (tp->t_state & TS_ISOPEN) {
+ c = *(sc->sc_sram_cons + rdptr);
+ (*linesw[tp->t_line].l_rint)(c, tp);
+ }
+
+ if (++rdptr == cons->cons_in_end)
+ rdptr = cons->cons_in_begin;
+ }
+
+ cons->cons_in_rdptr = rdptr;
+}
+
int
sbbc_cnlookc(dev_t dev, int *cp)
{
struct sbbc_softc *sc;
struct tty *tp;
int unit = minor(dev);
- int error, setuptimeout;
if (unit > sbbc_cd.cd_ndevs)
return (ENXIO);
tp->t_lflag = TTYDEF_LFLAG;
tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
ttsetwater(tp);
-
- setuptimeout = 1;
} else if ((tp->t_state & TS_XCLUDE) && suser(p, 0))
return (EBUSY);
tp->t_state |= TS_CARR_ON;
- error = (*linesw[tp->t_line].l_open)(dev, tp);
- if (error == 0 && setuptimeout)
- sbbctimeout(sc);
-
- return (error);
+ return ((*linesw[tp->t_line].l_open)(dev, tp));
}
int
return (ENXIO);
tp = sc->sc_tty;
- timeout_del(&sc->sc_to);
(*linesw[tp->t_line].l_close)(tp, flag);
ttyclose(tp);
return (0);
tp->t_cflag = t->c_cflag;
return (0);
}
-
-void
-sbbctimeout(void *v)
-{
- struct sbbc_softc *sc = v;
- struct tty *tp = sc->sc_tty;
- int c;
-
- while (sbbc_cnlookc(tp->t_dev, &c)) {
- if (tp->t_state & TS_ISOPEN)
- (*linesw[tp->t_line].l_rint)(c, tp);
- }
- timeout_add(&sc->sc_to, 1);
-}