summaryrefslogtreecommitdiffstats
path: root/sys/dev/xen
diff options
context:
space:
mode:
authorkmacy <kmacy@FreeBSD.org>2008-10-15 05:43:13 +0000
committerkmacy <kmacy@FreeBSD.org>2008-10-15 05:43:13 +0000
commit8234483524c47dd64314d223337b39a0e81606b2 (patch)
treefaebeefe977aa0afffd2138ed2de02e8d42a6fae /sys/dev/xen
parent4e2060df683f170e4078b370206e7fa9f552fbd1 (diff)
downloadFreeBSD-src-8234483524c47dd64314d223337b39a0e81606b2.zip
FreeBSD-src-8234483524c47dd64314d223337b39a0e81606b2.tar.gz
update console to pre-MPSAFE tty interfaces
Diffstat (limited to 'sys/dev/xen')
-rw-r--r--sys/dev/xen/console/console.c207
1 files changed, 167 insertions, 40 deletions
diff --git a/sys/dev/xen/console/console.c b/sys/dev/xen/console/console.c
index da778d6..64c2dfd 100644
--- a/sys/dev/xen/console/console.c
+++ b/sys/dev/xen/console/console.c
@@ -1,5 +1,5 @@
#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <sys/module.h>
@@ -18,7 +18,6 @@ __FBSDID("$FreeBSD$");
#include <machine/xen/hypervisor.h>
#include <machine/xen/xen_intr.h>
#include <sys/cons.h>
-#include <sys/priv.h>
#include <sys/proc.h>
#include <dev/xen/console/xencons_ring.h>
@@ -32,7 +31,9 @@ __FBSDID("$FreeBSD$");
static char driver_name[] = "xc";
devclass_t xc_devclass; /* do not make static */
-static void xcoutwakeup(struct tty *);
+static void xcstart (struct tty *);
+static int xcparam (struct tty *, struct termios *);
+static void xcstop (struct tty *, int);
static void xc_timeout(void *);
static void __xencons_tx_flush(void);
static boolean_t xcons_putc(int c);
@@ -72,7 +73,7 @@ static unsigned int cnsl_evt_reg;
static unsigned int wc, wp; /* write_cons, write_prod */
#define CDEV_MAJOR 12
-#define XCUNIT(x) (dev2unit(x))
+#define XCUNIT(x) (minor(x))
#define ISTTYOPEN(tp) ((tp) && ((tp)->t_state & TS_ISOPEN))
#define CN_LOCK_INIT(x, _name) \
mtx_init(&x, _name, NULL, MTX_SPIN|MTX_RECURSE)
@@ -93,14 +94,27 @@ static unsigned int wc, wp; /* write_cons, write_prod */
static struct tty *xccons;
-static tsw_open_t xcopen;
-static tsw_close_t xcclose;
+struct xc_softc {
+ int xc_unit;
+ struct cdev *xc_dev;
+};
+
-static struct ttydevsw xc_ttydevsw = {
- .tsw_flags = TF_NOPREFIX,
- .tsw_open = xcopen,
- .tsw_close = xcclose,
- .tsw_outwakeup = xcoutwakeup,
+static d_open_t xcopen;
+static d_close_t xcclose;
+static d_ioctl_t xcioctl;
+
+static struct cdevsw xc_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = D_TTY | D_NEEDGIANT,
+ .d_name = driver_name,
+ .d_open = xcopen,
+ .d_close = xcclose,
+ .d_read = ttyread,
+ .d_write = ttywrite,
+ .d_ioctl = xcioctl,
+ .d_poll = ttypoll,
+ .d_kqfilter = ttykqfilter,
};
static void
@@ -210,20 +224,32 @@ xc_identify(driver_t *driver, device_t parent)
static int
xc_probe(device_t dev)
{
+ struct xc_softc *sc = (struct xc_softc *)device_get_softc(dev);
+ sc->xc_unit = device_get_unit(dev);
return (0);
}
static int
xc_attach(device_t dev)
{
+ struct xc_softc *sc = (struct xc_softc *)device_get_softc(dev);
+
if (xen_start_info->flags & SIF_INITDOMAIN) {
xc_consdev.cn_putc = xccnputc_dom0;
}
- xccons = tty_alloc(&xc_ttydevsw, NULL, NULL);
- tty_makedev(xccons, NULL, "xc%r", 0);
+ sc->xc_dev = make_dev(&xc_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "xc%r", 0);
+ xccons = ttyalloc();
+
+ sc->xc_dev->si_drv1 = (void *)sc;
+ sc->xc_dev->si_tty = xccons;
+
+ xccons->t_oproc = xcstart;
+ xccons->t_param = xcparam;
+ xccons->t_stop = xcstop;
+ xccons->t_dev = sc->xc_dev;
callout_init(&xc_callout, 0);
@@ -237,7 +263,6 @@ xc_attach(device_t dev)
VIRQ_CONSOLE,
0,
"console",
- NULL,
xencons_priv_interrupt,
INTR_TYPE_TTY) < 0);
@@ -267,15 +292,11 @@ xencons_rx(char *buf, unsigned len)
{
int i;
struct tty *tp = xccons;
-
- if (xen_console_up) {
- tty_lock(tp);
- for (i = 0; i < len; i++)
- ttydisc_rint(tp, buf[i], 0);
- ttydisc_rint_done(tp);
- tty_unlock(tp);
- } else {
- for (i = 0; i < len; i++)
+
+ for (i = 0; i < len; i++) {
+ if (xen_console_up)
+ (*linesw[tp->t_line]->l_rint)(buf[i], tp);
+ else
rbuf[RBUF_MASK(rp++)] = buf[i];
}
}
@@ -283,7 +304,7 @@ xencons_rx(char *buf, unsigned len)
static void
__xencons_tx_flush(void)
{
- int sz;
+ int sz, work_done = 0;
CN_LOCK(cn_mtx);
while (wc != wp) {
@@ -300,8 +321,16 @@ __xencons_tx_flush(void)
break;
wc += sent;
}
+ work_done = 1;
}
CN_UNLOCK(cn_mtx);
+
+ /*
+ * ttwakeup calls routines using blocking locks
+ *
+ */
+ if (work_done && xen_console_up && curthread->td_critnest == 0)
+ ttwakeup(xccons);
}
void
@@ -323,19 +352,76 @@ xencons_priv_interrupt(void *arg)
xencons_tx();
}
-static int
-xcopen(struct tty *tp)
+int
+xcopen(struct cdev *dev, int flag, int mode, struct thread *td)
{
+ struct xc_softc *sc;
+ int unit = XCUNIT(dev);
+ struct tty *tp;
+ int s, error;
+
+ sc = (struct xc_softc *)device_get_softc(
+ devclass_get_device(xc_devclass, unit));
+ if (sc == NULL)
+ return (ENXIO);
+
+ tp = dev->si_tty;
+ s = spltty();
+ if (!ISTTYOPEN(tp)) {
+ tp->t_state |= TS_CARR_ON;
+ ttychars(tp);
+ tp->t_iflag = TTYDEF_IFLAG;
+ tp->t_oflag = TTYDEF_OFLAG;
+ tp->t_cflag = TTYDEF_CFLAG|CLOCAL;
+ tp->t_lflag = TTYDEF_LFLAG;
+ tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
+ xcparam(tp, &tp->t_termios);
+ ttsetwater(tp);
+ } else if (tp->t_state & TS_XCLUDE && suser(td)) {
+ splx(s);
+ return (EBUSY);
+ }
+ splx(s);
xen_console_up = 1;
+
+ error = (*linesw[tp->t_line]->l_open)(dev, tp);
+ return error;
+}
+
+int
+xcclose(struct cdev *dev, int flag, int mode, struct thread *td)
+{
+ struct tty *tp = dev->si_tty;
+
+ if (tp == NULL)
+ return (0);
+ xen_console_up = 0;
+
+ spltty();
+ (*linesw[tp->t_line]->l_close)(tp, flag);
+ tty_close(tp);
+ spl0();
return (0);
}
-static void
-xcclose(struct tty *tp)
+
+int
+xcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
{
+ struct tty *tp = dev->si_tty;
+ int error;
+
+ error = (*linesw[tp->t_line]->l_ioctl)(tp, cmd, data, flag, td);
+ if (error != ENOIOCTL)
+ return (error);
- xen_console_up = 0;
+ error = ttioctl(tp, cmd, data, flag);
+
+ if (error != ENOIOCTL)
+ return (error);
+
+ return (ENOTTY);
}
static inline int
@@ -350,15 +436,31 @@ __xencons_put_char(int ch)
static void
-xcoutwakeup(struct tty *tp)
+xcstart(struct tty *tp)
{
boolean_t cons_full = FALSE;
- char c;
- while (ttydisc_getc(tp, &c, 1) == 1 && !cons_full)
- cons_full = xcons_putc(c);
+ CN_LOCK(cn_mtx);
+ if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
+ CN_UNLOCK(cn_mtx);
+
+ ttwwakeup(tp);
+ return;
+ }
+
+ tp->t_state |= TS_BUSY;
+ CN_UNLOCK(cn_mtx);
+
+ while (tp->t_outq.c_cc != 0 && !cons_full)
+ cons_full = xcons_putc(getc(&tp->t_outq));
- if (cons_full) {
+ /* if the console is close to full leave our state as busy */
+ if (!cons_full) {
+ CN_LOCK(cn_mtx);
+ tp->t_state &= ~TS_BUSY;
+ CN_UNLOCK(cn_mtx);
+ ttwwakeup(tp);
+ } else {
/* let the timeout kick us in a bit */
xc_start_needed = TRUE;
}
@@ -366,6 +468,17 @@ xcoutwakeup(struct tty *tp)
}
static void
+xcstop(struct tty *tp, int flag)
+{
+
+ if (tp->t_state & TS_BUSY) {
+ if ((tp->t_state & TS_TTSTOP) == 0) {
+ tp->t_state |= TS_FLUSH;
+ }
+ }
+}
+
+static void
xc_timeout(void *v)
{
struct tty *tp;
@@ -373,19 +486,33 @@ xc_timeout(void *v)
tp = (struct tty *)v;
- tty_lock(tp);
- while ((c = xccncheckc(NULL)) != -1)
- ttydisc_rint(tp, c, 0);
+ while ((c = xccncheckc(NULL)) != -1) {
+ if (tp->t_state & TS_ISOPEN) {
+ (*linesw[tp->t_line]->l_rint)(c, tp);
+ }
+ }
if (xc_start_needed) {
xc_start_needed = FALSE;
- xcoutwakeup(tp);
+ xcstart(tp);
}
- tty_unlock(tp);
callout_reset(&xc_callout, XC_POLLTIME, xc_timeout, tp);
}
+/*
+ * Set line parameters.
+ */
+int
+xcparam(struct tty *tp, struct termios *t)
+{
+ tp->t_ispeed = t->c_ispeed;
+ tp->t_ospeed = t->c_ospeed;
+ tp->t_cflag = t->c_cflag;
+ return (0);
+}
+
+
static device_method_t xc_methods[] = {
DEVMETHOD(device_identify, xc_identify),
DEVMETHOD(device_probe, xc_probe),
@@ -396,7 +523,7 @@ static device_method_t xc_methods[] = {
static driver_t xc_driver = {
driver_name,
xc_methods,
- 0,
+ sizeof(struct xc_softc),
};
/*** Forcibly flush console data before dying. ***/
OpenPOWER on IntegriCloud