summaryrefslogtreecommitdiffstats
path: root/sys/dev/uart
diff options
context:
space:
mode:
authorimp <imp@FreeBSD.org>2013-12-23 01:24:32 +0000
committerimp <imp@FreeBSD.org>2013-12-23 01:24:32 +0000
commit8313ffe0353eb13f1fe633cc21dc1fdb720949b5 (patch)
tree1d3720759b7a56a576b3b717d0f900c9350b951e /sys/dev/uart
parentd08ecc86b4bcc22a4c54676370e6d87b43de66d0 (diff)
downloadFreeBSD-src-8313ffe0353eb13f1fe633cc21dc1fdb720949b5.zip
FreeBSD-src-8313ffe0353eb13f1fe633cc21dc1fdb720949b5.tar.gz
MFC r259685:
Plumb the cn_grab and cn_ungrab routines down into the uart clients. Mask RX interrupts while grabbed on the atmel serial driver. This UART interrupts every character. When interrupts are enabled at the mountroot> prompt, this means the ISR eats the characters. Rather than try to create a cooperative buffering system for the low level kernel console, instead just mask out the ISR. For NS8250 and decsendents this isn't needed, since interrupts only happen after 14 or more characters (depending on the fifo settings). Plumb such that these are optional so there's no change in behavior for all the other UART clients. ddb worked on this platform because all interrupts were disabled while it was running, so this problem wasn't noticed. The mountroot> issue has been around for a very very long time. Approved by: re@ (gjb@)
Diffstat (limited to 'sys/dev/uart')
-rw-r--r--sys/dev/uart/uart_cpu.h23
-rw-r--r--sys/dev/uart/uart_tty.c4
2 files changed, 27 insertions, 0 deletions
diff --git a/sys/dev/uart/uart_cpu.h b/sys/dev/uart/uart_cpu.h
index db64d49..99ced1a 100644
--- a/sys/dev/uart/uart_cpu.h
+++ b/sys/dev/uart/uart_cpu.h
@@ -43,6 +43,8 @@ struct uart_ops {
void (*putc)(struct uart_bas *, int);
int (*rxready)(struct uart_bas *);
int (*getc)(struct uart_bas *, struct mtx *);
+ void (*grab)(struct uart_bas *);
+ void (*ungrab)(struct uart_bas *);
};
extern bus_space_tag_t uart_bus_space_io;
@@ -135,6 +137,27 @@ uart_putc(struct uart_devinfo *di, int c)
uart_unlock(di->hwmtx);
}
+static __inline void
+uart_grab(struct uart_devinfo *di)
+{
+
+ uart_lock(di->hwmtx);
+ if (di->ops->grab)
+ di->ops->grab(&di->bas);
+ uart_unlock(di->hwmtx);
+}
+
+static __inline void
+uart_ungrab(struct uart_devinfo *di)
+{
+
+ uart_lock(di->hwmtx);
+ if (di->ops->ungrab)
+ di->ops->ungrab(&di->bas);
+ uart_unlock(di->hwmtx);
+}
+
+
static __inline int
uart_rxready(struct uart_devinfo *di)
{
diff --git a/sys/dev/uart/uart_tty.c b/sys/dev/uart/uart_tty.c
index 97ee08d..56f879b 100644
--- a/sys/dev/uart/uart_tty.c
+++ b/sys/dev/uart/uart_tty.c
@@ -112,11 +112,15 @@ uart_cnterm(struct consdev *cp)
static void
uart_cngrab(struct consdev *cp)
{
+
+ uart_grab(cp->cn_arg);
}
static void
uart_cnungrab(struct consdev *cp)
{
+
+ uart_ungrab(cp->cn_arg);
}
static void
OpenPOWER on IntegriCloud