Integrate the Xen console driver.

I initially didn't want to integrate the Xen console driver, because it
did not receive any testing. Kip Macy suggested that I'd better check it
in right now, because this is the easiest way for him to test it while
he is working on the Xen import.

Requested by:	kmacy
This commit is contained in:
Ed Schouten 2008-08-20 09:03:03 +00:00
parent 00ba6aade4
commit 1781f8bd6d

View File

@ -32,9 +32,7 @@ __FBSDID("$FreeBSD$");
static char driver_name[] = "xc";
devclass_t xc_devclass; /* do not make static */
static void xcstart (struct tty *);
static int xcparam (struct tty *, struct termios *);
static void xcstop (struct tty *, int);
static void xcoutwakeup(struct tty *);
static void xc_timeout(void *);
static void __xencons_tx_flush(void);
static boolean_t xcons_putc(int c);
@ -95,27 +93,14 @@ static unsigned int wc, wp; /* write_cons, write_prod */
static struct tty *xccons;
struct xc_softc {
int xc_unit;
struct cdev *xc_dev;
};
static tsw_open_t xcopen;
static tsw_close_t xcclose;
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 struct ttydevsw xc_ttydevsw = {
.tsw_flags = TF_NOPREFIX,
.tsw_open = xcopen,
.tsw_close = xcclose,
.tsw_outwakeup = xcoutwakeup,
};
static void
@ -225,32 +210,20 @@ 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;
}
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;
xccons = tty_alloc(&xc_ttydevsw, NULL, NULL);
tty_makedev(xccons, NULL, "xc%r", 0);
callout_init(&xc_callout, 0);
@ -294,11 +267,15 @@ xencons_rx(char *buf, unsigned len)
{
int i;
struct tty *tp = xccons;
for (i = 0; i < len; i++) {
if (xen_console_up)
(*linesw[tp->t_line]->l_rint)(buf[i], tp);
else
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++)
rbuf[RBUF_MASK(rp++)] = buf[i];
}
}
@ -306,7 +283,7 @@ xencons_rx(char *buf, unsigned len)
static void
__xencons_tx_flush(void)
{
int sz, work_done = 0;
int sz;
CN_LOCK(cn_mtx);
while (wc != wp) {
@ -323,16 +300,8 @@ __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
@ -354,76 +323,19 @@ xencons_priv_interrupt(void *arg)
xencons_tx();
}
int
xcopen(struct cdev *dev, int flag, int mode, struct thread *td)
static int
xcopen(struct tty *tp)
{
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 && priv_check(td, PRIV_ROOT)) {
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);
}
int
xcioctl(struct cdev *dev, u_long cmd, caddr_t data, int flag, struct thread *td)
static void
xcclose(struct tty *tp)
{
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);
error = ttioctl(tp, cmd, data, flag);
if (error != ENOIOCTL)
return (error);
return (ENOTTY);
xen_console_up = 0;
}
static inline int
@ -438,48 +350,21 @@ __xencons_put_char(int ch)
static void
xcstart(struct tty *tp)
xcoutwakeup(struct tty *tp)
{
boolean_t cons_full = FALSE;
char c;
CN_LOCK(cn_mtx);
if (tp->t_state & (TS_TIMEOUT | TS_TTSTOP)) {
CN_UNLOCK(cn_mtx);
while (ttydisc_getc(tp, &c, 1) == 1 && !cons_full)
cons_full = xcons_putc(c);
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 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 {
if (cons_full) {
/* let the timeout kick us in a bit */
xc_start_needed = TRUE;
}
}
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)
{
@ -488,33 +373,19 @@ xc_timeout(void *v)
tp = (struct tty *)v;
while ((c = xccncheckc(NULL)) != -1) {
if (tp->t_state & TS_ISOPEN) {
(*linesw[tp->t_line]->l_rint)(c, tp);
}
}
tty_lock(tp);
while ((c = xccncheckc(NULL)) != -1)
ttydisc_rint(tp, c, 0);
tty_unlock(tp);
if (xc_start_needed) {
xc_start_needed = FALSE;
xcstart(tp);
xcoutwakeup(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),
@ -525,7 +396,7 @@ static device_method_t xc_methods[] = {
static driver_t xc_driver = {
driver_name,
xc_methods,
sizeof(struct xc_softc),
0,
};
/*** Forcibly flush console data before dying. ***/