diff options
Diffstat (limited to 'sys/sun4v/sun4v/hvcons.c')
-rw-r--r-- | sys/sun4v/sun4v/hvcons.c | 162 |
1 files changed, 49 insertions, 113 deletions
diff --git a/sys/sun4v/sun4v/hvcons.c b/sys/sun4v/sun4v/hvcons.c index 0217a85..314d15c 100644 --- a/sys/sun4v/sun4v/hvcons.c +++ b/sys/sun4v/sun4v/hvcons.c @@ -53,16 +53,14 @@ __FBSDID("$FreeBSD$"); #define HVCN_POLL_FREQ 10 - -static d_open_t hvcn_open; -static d_close_t hvcn_close; - -static struct cdevsw hvcn_cdevsw = { - .d_version = D_VERSION, - .d_open = hvcn_open, - .d_close = hvcn_close, - .d_name = "hvcn", - .d_flags = D_TTY | D_NEEDGIANT, +static tsw_open_t hvcn_open; +static tsw_outwakeup_t hvcn_outwakeup; +static tsw_close_t hvcn_close; + +static struct ttydevsw hvcn_class = { + .tsw_open = hvcn_open, + .tsw_outwakeup = hvcn_outwakeup, + .tsw_close = hvcn_close, }; #define PCBURST 16 @@ -81,9 +79,6 @@ static struct callout_handle hvcn_timeouthandle static int alt_break_state; #endif -static void hvcn_tty_start(struct tty *); -static int hvcn_tty_param(struct tty *, struct termios *); -static void hvcn_tty_stop(struct tty *, int); static void hvcn_timeout(void *); static cn_probe_t hvcn_cnprobe; @@ -113,67 +108,27 @@ hv_cnputs(char *p) } static int -hvcn_open(struct cdev *dev, int flag, int mode, struct thread *td) +hvcn_open(struct tty *tp) { - struct tty *tp; - int error, setuptimeout; - - setuptimeout = 0; - - if (dev->si_tty == NULL) { - hvcn_tp = ttyalloc(); - dev->si_tty = hvcn_tp; - hvcn_tp->t_dev = dev; - } - tp = dev->si_tty; - - tp->t_oproc = hvcn_tty_start; - tp->t_param = hvcn_tty_param; - tp->t_stop = hvcn_tty_stop; - if ((tp->t_state & TS_ISOPEN) == 0) { - tp->t_state |= TS_CARR_ON; - ttyconsolemode(tp, 0); - - setuptimeout = 1; - } else if ((tp->t_state & TS_XCLUDE) && priv_check(td, - PRIV_TTY_EXCLUSIVE)) { - return (EBUSY); - } - - error = ttyld_open(tp, dev); -#if defined(SIMULATOR) || 1 - if (error == 0 && setuptimeout) { - int polltime; + /* + * Set up timeout to trigger fake interrupts to transmit + * trailing data. + */ + polltime = hz / HVCN_POLL_FREQ; + if (polltime < 1) + polltime = 1; + hvcn_timeouthandle = timeout(hvcn_timeout, tp, polltime); - polltime = hz / HVCN_POLL_FREQ; - if (polltime < 1) { - polltime = 1; - } + buflen = 0; - hvcn_timeouthandle = timeout(hvcn_timeout, tp, polltime); - } -#endif - return (error); + return (0); } -static int -hvcn_close(struct cdev *dev, int flag, int mode, struct thread *td) +static void +hvcn_close(struct tty *tp) { - int unit; - struct tty *tp; - - unit = minor(dev); - tp = dev->si_tty; - - if (unit != 0) - return (ENXIO); - untimeout(hvcn_timeout, tp, hvcn_timeouthandle); - ttyld_close(tp, flag); - tty_close(tp); - - return (0); } static void @@ -210,7 +165,8 @@ done: static void hvcn_cninit(struct consdev *cp) { - sprintf(cp->cn_name, "hvcn"); + + strcpy(cp->cn_name, "hvcn"); } static int @@ -295,64 +251,43 @@ hvcn_cnputc(struct consdev *cp, int c) } while (error == H_EWOULDBLOCK); } -static int -hvcn_tty_param(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 void -hvcn_tty_start(struct tty *tp) +hvcn_outwakeup(struct tty *tp) { - if (!(tp->t_state & (TS_TIMEOUT | TS_BUSY | TS_TTSTOP))) { - tp->t_state |= TS_BUSY; + for (;;) { + /* Refill the input buffer. */ + if (buflen == 0) { + buflen = ttydisc_getc(tp, buf, PCBURST); + bufindex = 0; + } - do { - if (buflen == 0) { - buflen = q_to_b(&tp->t_outq, buf, PCBURST); - bufindex = 0; - } - while (buflen) { - if (hv_cons_putchar(buf[bufindex]) == H_EWOULDBLOCK) - goto done; - bufindex++; - buflen--; - } - } while (tp->t_outq.c_cc != 0); - done: - tp->t_state &= ~TS_BUSY; - ttwwakeup(tp); + /* Transmit the input buffer. */ + while (buflen) { + if (hv_cons_putchar(buf[bufindex]) == H_EWOULDBLOCK) + return; + bufindex++; + buflen--; + } } } static void -hvcn_tty_stop(struct tty *tp, int flag) -{ - if ((tp->t_state & TS_BUSY) && !(tp->t_state & TS_TTSTOP)) - tp->t_state |= TS_FLUSH; - - -} - -static void hvcn_intr(void *v) { - struct tty *tp; + struct tty *tp = v; int c; - tp = (struct tty *)v; + tty_lock(tp); + /* Receive data. */ while ((c = hvcn_cncheckc(NULL)) != -1) - if (tp->t_state & TS_ISOPEN) - ttyld_rint(tp, c); + ttydisc_rint(tp, c, 0); + ttydisc_rint_done(tp); - if (tp->t_outq.c_cc != 0 || buflen != 0) - hvcn_tty_start(tp); + /* Transmit trailing data. */ + hvcn_outwakeup(tp); + tty_unlock(tp); } static void @@ -381,7 +316,7 @@ static int hvcn_dev_attach(device_t dev) { - struct cdev *cdev; + struct tty *tp; int error, rid; /* belongs in attach - but attach is getting called multiple times @@ -392,8 +327,9 @@ hvcn_dev_attach(device_t dev) hvcn_consdev.cn_name[0] == '\0') return (ENXIO); - cdev = make_dev(&hvcn_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, "ttyv%r", 1); - make_dev_alias(cdev, "hvcn"); + tp = tty_alloc(&hvcn_class, NULL, NULL); + tty_makedev(tp, NULL, "v%r", 1); + tty_makealias(tp, "hvcn"); rid = 0; |