diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c index 7eaf2f7745c..1bef6384678 100644 --- a/sys/dev/uart/uart_tty.c +++ b/sys/dev/uart/uart_tty.c @@ -53,6 +53,7 @@ __FBSDID("$FreeBSD$"); static cn_probe_t uart_cnprobe; static cn_init_t uart_cninit; +static cn_init_t uart_cnresume; static cn_term_t uart_cnterm; static cn_getc_t uart_cngetc; static cn_putc_t uart_cnputc; @@ -69,7 +70,10 @@ static tsw_modem_t uart_tty_modem; static tsw_free_t uart_tty_free; static tsw_busy_t uart_tty_busy; -CONSOLE_DRIVER(uart); +CONSOLE_DRIVER( + uart, + .cn_resume = uart_cnresume, +); static struct uart_devinfo uart_console; @@ -114,6 +118,13 @@ uart_cninit(struct consdev *cp) uart_init(di); } +static void +uart_cnresume(struct consdev *cp) +{ + + uart_init(cp->cn_arg); +} + static void uart_cnterm(struct consdev *cp) { diff --git a/sys/kern/kern_cons.c b/sys/kern/kern_cons.c index ab8660e99d3..4e2d4c6acbe 100644 --- a/sys/kern/kern_cons.c +++ b/sys/kern/kern_cons.c @@ -384,6 +384,19 @@ cnungrab() } } +void +cnresume() +{ + struct cn_device *cnd; + struct consdev *cn; + + STAILQ_FOREACH(cnd, &cn_devlist, cnd_next) { + cn = cnd->cnd_cn; + if (cn->cn_ops->cn_resume != NULL) + cn->cn_ops->cn_resume(cn); + } +} + /* * Low level console routines. */ diff --git a/sys/sys/cons.h b/sys/sys/cons.h index aded0459d1a..047846463bf 100644 --- a/sys/sys/cons.h +++ b/sys/sys/cons.h @@ -66,6 +66,8 @@ struct consdev_ops { /* grab console for exclusive kernel use */ cn_ungrab_t *cn_ungrab; /* ungrab console */ + cn_init_t *cn_resume; + /* set up console after sleep, optional */ }; struct consdev { @@ -105,8 +107,9 @@ extern struct tty *constty; /* Temporary virtual console. */ }; \ DATA_SET(cons_set, name) -#define CONSOLE_DRIVER(name) \ +#define CONSOLE_DRIVER(name, ...) \ static const struct consdev_ops name##_consdev_ops = { \ + /* Mandatory methods. */ \ .cn_probe = name##_cnprobe, \ .cn_init = name##_cninit, \ .cn_term = name##_cnterm, \ @@ -114,6 +117,8 @@ extern struct tty *constty; /* Temporary virtual console. */ .cn_putc = name##_cnputc, \ .cn_grab = name##_cngrab, \ .cn_ungrab = name##_cnungrab, \ + /* Optional fields. */ \ + __VA_ARGS__ \ }; \ CONSOLE_DEVICE(name##_consdev, name##_consdev_ops, NULL) @@ -126,6 +131,7 @@ void cnremove(struct consdev *); void cnselect(struct consdev *); void cngrab(void); void cnungrab(void); +void cnresume(void); int cncheckc(void); int cngetc(void); void cngets(char *, size_t, int); diff --git a/sys/x86/acpica/acpi_wakeup.c b/sys/x86/acpica/acpi_wakeup.c index ef910cca605..69951226625 100644 --- a/sys/x86/acpica/acpi_wakeup.c +++ b/sys/x86/acpica/acpi_wakeup.c @@ -46,6 +46,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -296,6 +297,12 @@ acpi_sleep_machdep(struct acpi_softc *sc, int state) for (;;) ia32_pause(); } else { + /* + * Re-initialize console hardware as soon as possibe. + * No console output (e.g. printf) is allowed before + * this point. + */ + cnresume(); #ifdef __amd64__ fpuresume(susppcbs[0]->sp_fpususpend); #else