Initial stab at making com@puc suspend and resume properly. Works fine
authorkettenis <kettenis@openbsd.org>
Fri, 6 Aug 2010 21:04:14 +0000 (21:04 +0000)
committerkettenis <kettenis@openbsd.org>
Fri, 6 Aug 2010 21:04:14 +0000 (21:04 +0000)
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@

sys/dev/ic/com.c
sys/dev/ic/comvar.h
sys/dev/pci/puc.c
sys/dev/puc/com_puc.c

index de71a64..0cf3a35 100644 (file)
@@ -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 $ */
 
 /*
@@ -566,6 +566,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)
 {
index d6c0155..3e80241 100644 (file)
@@ -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);
index 9ec1af4..fb1c14f 100644 (file)
@@ -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 = {
index 84ba7d1..8069f21 100644 (file)
@@ -1,4 +1,4 @@
-/*     $OpenBSD: com_puc.c,v 1.17 2010/06/26 23:24:45 guenther Exp $   */
+/*     $OpenBSD: com_puc.c,v 1.18 2010/08/06 21:07:27 kettenis Exp $   */
 
 /*
  * Copyright (c) 1997 - 1999, Jason Downs.  All rights reserved.
 
 #define        com_lcr         com_cfcr
 
-int com_puc_match(struct device *, void *, void *);
-void com_puc_attach(struct device *, struct device *, void *);
-int com_puc_detach(struct device *, int );
+int    com_puc_match(struct device *, void *, void *);
+void   com_puc_attach(struct device *, struct device *, void *);
+int    com_puc_detach(struct device *, int);
+int    com_puc_activate(struct device *, int);
 
 struct cfattach com_puc_ca = {
-       sizeof(struct com_softc), com_puc_match, com_puc_attach, com_puc_detach
+       sizeof(struct com_softc), com_puc_match,
+       com_puc_attach, com_puc_detach, com_puc_activate
 };
 
 int
@@ -118,3 +120,19 @@ com_puc_detach(struct device *self, int flags)
 {
        return com_detach(self, flags);
 }
+
+int
+com_puc_activate(struct device *self, int act)
+{
+       struct com_softc *sc = (struct com_softc *)self;
+
+       switch (act) {
+       case DVACT_SUSPEND:
+               break;
+       case DVACT_RESUME:
+               com_resume(sc);
+               break;
+       }
+
+       return (0);
+}