summaryrefslogtreecommitdiff
path: root/sys/dev
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@cvs.openbsd.org>2010-08-06 21:04:15 +0000
committerMark Kettenis <kettenis@cvs.openbsd.org>2010-08-06 21:04:15 +0000
commitf8c8cbd4878bcefedf694590065b23e0448eab9e (patch)
tree1c57355a82d2c1d6dda4317c101e34ff3cfec4e5 /sys/dev
parent3a9ea2e93fee484779e0bb9a4fe777899f0ba0ea (diff)
Initial stab at making com@puc suspend and resume properly. Works fine
for using cu(1) between two OpenBSD machines. Probably doesn't work for serial consoles but we don't support those on puc(4) anyway. ok deraadt@
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/ic/com.c106
-rw-r--r--sys/dev/ic/comvar.h3
-rw-r--r--sys/dev/pci/puc.c4
3 files changed, 109 insertions, 4 deletions
diff --git a/sys/dev/ic/com.c b/sys/dev/ic/com.c
index de71a6408e5..0cf3a35bf83 100644
--- a/sys/dev/ic/com.c
+++ b/sys/dev/ic/com.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: com.c,v 1.142 2010/07/02 17:27:01 nicm Exp $ */
+/* $OpenBSD: com.c,v 1.143 2010/08/06 21:04:14 kettenis Exp $ */
/* $NetBSD: com.c,v 1.82.4.1 1996/06/02 09:08:00 mrg Exp $ */
/*
@@ -567,6 +567,110 @@ compwroff(struct com_softc *sc)
}
void
+com_resume(struct com_softc *sc)
+{
+ struct tty *tp = sc->sc_tty;
+ bus_space_tag_t iot = sc->sc_iot;
+ bus_space_handle_t ioh = sc->sc_ioh;
+ int ospeed;
+
+ if (!tp || !ISSET(tp->t_state, TS_ISOPEN))
+ return;
+
+ /*
+ * Wake up the sleepy heads.
+ */
+ switch (sc->sc_uarttype) {
+ case COM_UART_ST16650:
+ case COM_UART_ST16650V2:
+ bus_space_write_1(iot, ioh, com_lcr, LCR_EFR);
+ bus_space_write_1(iot, ioh, com_efr, EFR_ECB);
+ bus_space_write_1(iot, ioh, com_ier, 0);
+ bus_space_write_1(iot, ioh, com_efr, 0);
+ bus_space_write_1(iot, ioh, com_lcr, 0);
+ break;
+ case COM_UART_TI16750:
+ bus_space_write_1(iot, ioh, com_ier, 0);
+ break;
+ case COM_UART_PXA2X0:
+ bus_space_write_1(iot, ioh, com_ier, IER_EUART);
+ break;
+ }
+
+ ospeed = comspeed(sc->sc_frequency, tp->t_ospeed);
+
+ if (ospeed != 0) {
+ bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr | LCR_DLAB);
+ bus_space_write_1(iot, ioh, com_dlbl, ospeed);
+ bus_space_write_1(iot, ioh, com_dlbh, ospeed >> 8);
+ bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
+ } else {
+ bus_space_write_1(iot, ioh, com_lcr, sc->sc_lcr);
+ }
+
+ if (ISSET(sc->sc_hwflags, COM_HW_FIFO)) {
+ u_int8_t fifo = FIFO_ENABLE|FIFO_RCV_RST|FIFO_XMT_RST;
+ u_int8_t lcr;
+
+ if (tp->t_ispeed <= 1200)
+ fifo |= FIFO_TRIGGER_1;
+ else if (tp->t_ispeed <= 38400)
+ fifo |= FIFO_TRIGGER_4;
+ else
+ fifo |= FIFO_TRIGGER_8;
+ if (sc->sc_uarttype == COM_UART_TI16750) {
+ fifo |= FIFO_ENABLE_64BYTE;
+ lcr = bus_space_read_1(iot, ioh, com_lcr);
+ bus_space_write_1(iot, ioh, com_lcr,
+ lcr | LCR_DLAB);
+ }
+
+ /*
+ * (Re)enable and drain FIFOs.
+ *
+ * Certain SMC chips cause problems if the FIFOs are
+ * enabled while input is ready. Turn off the FIFO
+ * if necessary to clear the input. Test the input
+ * ready bit after enabling the FIFOs to handle races
+ * between enabling and fresh input.
+ *
+ * Set the FIFO threshold based on the receive speed.
+ */
+ for (;;) {
+ bus_space_write_1(iot, ioh, com_fifo, 0);
+ delay(100);
+ (void) bus_space_read_1(iot, ioh, com_data);
+ bus_space_write_1(iot, ioh, com_fifo, fifo |
+ FIFO_RCV_RST | FIFO_XMT_RST);
+ delay(100);
+ if(!ISSET(bus_space_read_1(iot, ioh,
+ com_lsr), LSR_RXRDY))
+ break;
+ }
+ if (sc->sc_uarttype == COM_UART_TI16750)
+ bus_space_write_1(iot, ioh, com_lcr, lcr);
+ }
+
+ /* Flush any pending I/O. */
+ while (ISSET(bus_space_read_1(iot, ioh, com_lsr), LSR_RXRDY))
+ (void) bus_space_read_1(iot, ioh, com_data);
+
+ /* You turn me on, baby! */
+ bus_space_write_1(iot, ioh, com_mcr, sc->sc_mcr);
+ bus_space_write_1(iot, ioh, com_ier, sc->sc_ier);
+
+#ifdef COM_PXA2X0
+ if (sc->sc_uarttype == COM_UART_PXA2X0 &&
+ ISSET(sc->sc_hwflags, COM_HW_SIR)) {
+ bus_space_write_1(iot, ioh, com_isr, ISR_RECV);
+#ifdef __zaurus__
+ scoop_set_irled(1);
+#endif
+ }
+#endif
+}
+
+void
com_raisedtr(void *arg)
{
struct com_softc *sc = arg;
diff --git a/sys/dev/ic/comvar.h b/sys/dev/ic/comvar.h
index d6c015584ed..3e80241e9f2 100644
--- a/sys/dev/ic/comvar.h
+++ b/sys/dev/ic/comvar.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: comvar.h,v 1.49 2010/08/01 23:55:38 yasuoka Exp $ */
+/* $OpenBSD: comvar.h,v 1.50 2010/08/06 21:04:14 kettenis Exp $ */
/* $NetBSD: comvar.h,v 1.5 1996/05/05 19:50:47 christos Exp $ */
/*
@@ -138,6 +138,7 @@ int comstop(struct tty *, int);
int comintr(void *);
int com_detach(struct device *, int);
int com_activate(struct device *, int);
+void com_resume(struct com_softc *);
void comdiag(void *);
int comspeed(long, long);
diff --git a/sys/dev/pci/puc.c b/sys/dev/pci/puc.c
index 9ec1af4d59d..fb1c14f0d8f 100644
--- a/sys/dev/pci/puc.c
+++ b/sys/dev/pci/puc.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: puc.c,v 1.17 2010/07/22 17:16:10 pirofti Exp $ */
+/* $OpenBSD: puc.c,v 1.18 2010/08/06 21:04:14 kettenis Exp $ */
/* $NetBSD: puc.c,v 1.3 1999/02/06 06:29:54 cgd Exp $ */
/*
@@ -79,7 +79,7 @@ void *puc_pci_intr_establish(struct puc_attach_args *, int,
struct cfattach puc_pci_ca = {
sizeof(struct puc_pci_softc), puc_pci_match,
- puc_pci_attach, puc_pci_detach
+ puc_pci_attach, puc_pci_detach, config_activate_children
};
struct cfdriver puc_cd = {