xref: /illumos-gate/usr/src/cmd/bhyve/uart_emul.c (revision bf21cd9318e0a3a51b7f02c14a7c1b1aef2dc861)
1 /*-
2  * Copyright (c) 2012 NetApp, Inc.
3  * Copyright (c) 2013 Neel Natu <neel@freebsd.org>
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice, this list of conditions and the following disclaimer.
11  * 2. Redistributions in binary form must reproduce the above copyright
12  *    notice, this list of conditions and the following disclaimer in the
13  *    documentation and/or other materials provided with the distribution.
14  *
15  * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18  * ARE DISCLAIMED.  IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25  * SUCH DAMAGE.
26  *
27  * $FreeBSD: head/usr.sbin/bhyve/uart_emul.c 257293 2013-10-29 00:18:11Z neel $
28  */
29 /*
30  * This file and its contents are supplied under the terms of the
31  * Common Development and Distribution License ("CDDL"), version 1.0.
32  * You may only use this file in accordance with the terms of version
33  * 1.0 of the CDDL.
34  *
35  * A full copy of the text of the CDDL should have accompanied this
36  * source.  A copy of the CDDL is also available via the Internet at
37  * http://www.illumos.org/license/CDDL.
38  *
39  * Copyright 2015 Pluribus Networks Inc.
40  */
41 
42 #include <sys/cdefs.h>
43 __FBSDID("$FreeBSD: head/usr.sbin/bhyve/uart_emul.c 257293 2013-10-29 00:18:11Z neel $");
44 
45 #include <sys/types.h>
46 #include <dev/ic/ns16550.h>
47 
48 #ifndef	__FreeBSD__
49 #include <sys/socket.h>
50 #include <sys/stat.h>
51 #endif
52 #include <stdio.h>
53 #include <stdlib.h>
54 #include <assert.h>
55 #include <termios.h>
56 #include <unistd.h>
57 #include <stdbool.h>
58 #include <string.h>
59 #include <pthread.h>
60 #ifndef	__FreeBSD__
61 #include <errno.h>
62 #include <fcntl.h>
63 #include <poll.h>
64 #endif
65 
66 #ifndef	__FreeBSD__
67 #include <bhyve.h>
68 
69 #include "bhyverun.h"
70 #endif
71 #ifdef	__FreeBSD__
72 #include "mevent.h"
73 #endif
74 #include "uart_emul.h"
75 
76 #define	COM1_BASE	0x3F8
77 #define	COM1_IRQ	4
78 #define	COM2_BASE      	0x2F8
79 #define COM2_IRQ	3
80 
81 #define	DEFAULT_RCLK	1843200
82 #define	DEFAULT_BAUD	9600
83 
84 #define	FCR_RX_MASK	0xC0
85 
86 #define	MCR_OUT1	0x04
87 #define	MCR_OUT2	0x08
88 
89 #define	MSR_DELTA_MASK	0x0f
90 
91 #ifndef REG_SCR
92 #define REG_SCR		com_scr
93 #endif
94 
95 #define	FIFOSZ	16
96 
97 static bool uart_stdio;		/* stdio in use for i/o */
98 #ifndef	__FreeBSD__
99 static bool uart_bcons;		/* bhyveconsole in use for i/o */
100 #endif
101 
102 static struct {
103 	int	baseaddr;
104 	int	irq;
105 	bool	inuse;
106 } uart_lres[] = {
107 	{ COM1_BASE, COM1_IRQ, false},
108 	{ COM2_BASE, COM2_IRQ, false},
109 };
110 
111 #define	UART_NLDEVS	(sizeof(uart_lres) / sizeof(uart_lres[0]))
112 
113 struct fifo {
114 	uint8_t	buf[FIFOSZ];
115 	int	rindex;		/* index to read from */
116 	int	windex;		/* index to write to */
117 	int	num;		/* number of characters in the fifo */
118 	int	size;		/* size of the fifo */
119 };
120 
121 struct uart_softc {
122 	pthread_mutex_t mtx;	/* protects all softc elements */
123 	uint8_t data;		/* Data register (R/W) */
124 	uint8_t ier;		/* Interrupt enable register (R/W) */
125 	uint8_t lcr;		/* Line control register (R/W) */
126 	uint8_t mcr;		/* Modem control register (R/W) */
127 	uint8_t lsr;		/* Line status register (R/W) */
128 	uint8_t msr;		/* Modem status register (R/W) */
129 	uint8_t fcr;		/* FIFO control register (W) */
130 	uint8_t scr;		/* Scratch register (R/W) */
131 
132 	uint8_t dll;		/* Baudrate divisor latch LSB */
133 	uint8_t dlh;		/* Baudrate divisor latch MSB */
134 
135 	struct fifo rxfifo;
136 
137 	bool	opened;
138 	bool	stdio;
139 #ifndef	__FreeBSD__
140 	bool	bcons;
141 	struct {
142 		pid_t	clipid;
143 		int	clifd;		/* console client unix domain socket */
144 		int	servfd;		/* console server unix domain socket */
145 	} usc_bcons;
146 #endif
147 
148 	bool	thre_int_pending;	/* THRE interrupt pending */
149 
150 	void	*arg;
151 	uart_intr_func_t intr_assert;
152 	uart_intr_func_t intr_deassert;
153 };
154 
155 #ifdef	__FreeBSD__
156 static void uart_drain(int fd, enum ev_type ev, void *arg);
157 #else
158 static void uart_tty_drain(struct uart_softc *sc);
159 static int uart_bcons_drain(struct uart_softc *sc);
160 #endif
161 
162 static struct termios tio_orig, tio_new;	/* I/O Terminals */
163 
164 static void
165 ttyclose(void)
166 {
167 
168 	tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig);
169 }
170 
171 static void
172 ttyopen(void)
173 {
174 
175 	tcgetattr(STDIN_FILENO, &tio_orig);
176 
177 	tio_new = tio_orig;
178 	cfmakeraw(&tio_new);
179 	tcsetattr(STDIN_FILENO, TCSANOW, &tio_new);
180 
181 	atexit(ttyclose);
182 }
183 
184 static bool
185 tty_char_available(void)
186 {
187 	fd_set rfds;
188 	struct timeval tv;
189 
190 	FD_ZERO(&rfds);
191 	FD_SET(STDIN_FILENO, &rfds);
192 	tv.tv_sec = 0;
193 	tv.tv_usec = 0;
194 	if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0 ) {
195 		return (true);
196 	} else {
197 		return (false);
198 	}
199 }
200 
201 static int
202 ttyread(void)
203 {
204 	char rb;
205 
206 	if (tty_char_available()) {
207 		read(STDIN_FILENO, &rb, 1);
208 		return (rb & 0xff);
209 	} else {
210 		return (-1);
211 	}
212 }
213 
214 static void
215 ttywrite(unsigned char wb)
216 {
217 
218 	(void)write(STDIN_FILENO, &wb, 1);
219 }
220 
221 #ifndef	__FreeBSD__
222 static void
223 bconswrite(struct uart_softc *sc, unsigned char wb)
224 {
225 	(void) write(sc->usc_bcons.clifd, &wb, 1);
226 }
227 #endif
228 
229 static void
230 fifo_reset(struct fifo *fifo, int size)
231 {
232 	bzero(fifo, sizeof(struct fifo));
233 	fifo->size = size;
234 }
235 
236 static int
237 fifo_putchar(struct fifo *fifo, uint8_t ch)
238 {
239 
240 	if (fifo->num < fifo->size) {
241 		fifo->buf[fifo->windex] = ch;
242 		fifo->windex = (fifo->windex + 1) % fifo->size;
243 		fifo->num++;
244 		return (0);
245 	} else
246 		return (-1);
247 }
248 
249 static int
250 fifo_getchar(struct fifo *fifo)
251 {
252 	int c;
253 
254 	if (fifo->num > 0) {
255 		c = fifo->buf[fifo->rindex];
256 		fifo->rindex = (fifo->rindex + 1) % fifo->size;
257 		fifo->num--;
258 		return (c);
259 	} else
260 		return (-1);
261 }
262 
263 static int
264 fifo_numchars(struct fifo *fifo)
265 {
266 
267 	return (fifo->num);
268 }
269 
270 static int
271 fifo_available(struct fifo *fifo)
272 {
273 
274 	return (fifo->num < fifo->size);
275 }
276 
277 static void
278 uart_opentty(struct uart_softc *sc)
279 {
280 	struct mevent *mev;
281 
282 	assert(!sc->opened && sc->stdio);
283 
284 	ttyopen();
285 #ifdef	__FreeBSD__
286 	mev = mevent_add(STDIN_FILENO, EVF_READ, uart_drain, sc);
287 #endif
288 	assert(mev);
289 }
290 
291 /*
292  * The IIR returns a prioritized interrupt reason:
293  * - receive data available
294  * - transmit holding register empty
295  * - modem status change
296  *
297  * Return an interrupt reason if one is available.
298  */
299 static int
300 uart_intr_reason(struct uart_softc *sc)
301 {
302 
303 	if ((sc->lsr & LSR_OE) != 0 && (sc->ier & IER_ERLS) != 0)
304 		return (IIR_RLS);
305 	else if (fifo_numchars(&sc->rxfifo) > 0 && (sc->ier & IER_ERXRDY) != 0)
306 		return (IIR_RXTOUT);
307 	else if (sc->thre_int_pending && (sc->ier & IER_ETXRDY) != 0)
308 		return (IIR_TXRDY);
309 	else if ((sc->msr & MSR_DELTA_MASK) != 0 && (sc->ier & IER_EMSC) != 0)
310 		return (IIR_MLSC);
311 	else
312 		return (IIR_NOPEND);
313 }
314 
315 static void
316 uart_reset(struct uart_softc *sc)
317 {
318 	uint16_t divisor;
319 
320 	divisor = DEFAULT_RCLK / DEFAULT_BAUD / 16;
321 	sc->dll = divisor;
322 	sc->dlh = divisor >> 16;
323 
324 	fifo_reset(&sc->rxfifo, 1);	/* no fifo until enabled by software */
325 }
326 
327 /*
328  * Toggle the COM port's intr pin depending on whether or not we have an
329  * interrupt condition to report to the processor.
330  */
331 static void
332 uart_toggle_intr(struct uart_softc *sc)
333 {
334 	uint8_t intr_reason;
335 
336 	intr_reason = uart_intr_reason(sc);
337 
338 	if (intr_reason == IIR_NOPEND)
339 		(*sc->intr_deassert)(sc->arg);
340 	else
341 		(*sc->intr_assert)(sc->arg);
342 }
343 
344 #ifdef	__FreeBSD__
345 static void
346 uart_drain(int fd, enum ev_type ev, void *arg)
347 {
348 	struct uart_softc *sc;
349 	int ch;
350 
351 	sc = arg;
352 
353 	assert(fd == STDIN_FILENO);
354 	assert(ev == EVF_READ);
355 
356 	/*
357 	 * This routine is called in the context of the mevent thread
358 	 * to take out the softc lock to protect against concurrent
359 	 * access from a vCPU i/o exit
360 	 */
361 	pthread_mutex_lock(&sc->mtx);
362 
363 	if ((sc->mcr & MCR_LOOPBACK) != 0) {
364 		(void) ttyread();
365 	} else {
366 		while (fifo_available(&sc->rxfifo) &&
367 		       ((ch = ttyread()) != -1)) {
368 			fifo_putchar(&sc->rxfifo, ch);
369 		}
370 		uart_toggle_intr(sc);
371 	}
372 
373 	pthread_mutex_unlock(&sc->mtx);
374 }
375 #else
376 static void
377 uart_tty_drain(struct uart_softc *sc)
378 {
379 	int ch;
380 
381 	/*
382 	 * Take the softc lock to protect against concurrent
383 	 * access from a vCPU i/o exit
384 	 */
385 	pthread_mutex_lock(&sc->mtx);
386 
387 	if ((sc->mcr & MCR_LOOPBACK) != 0) {
388 		(void) ttyread();
389 	} else {
390 		while (fifo_available(&sc->rxfifo) &&
391 		       ((ch = ttyread()) != -1)) {
392 			fifo_putchar(&sc->rxfifo, ch);
393 		}
394 		uart_toggle_intr(sc);
395 	}
396 
397 	pthread_mutex_unlock(&sc->mtx);
398 }
399 
400 static int
401 uart_bcons_drain(struct uart_softc *sc)
402 {
403 	char ch;
404 	int nbytes;
405 	int ret = 0;
406 
407 	/*
408 	 * Take the softc lock to protect against concurrent
409 	 * access from a vCPU i/o exit
410 	 */
411 	pthread_mutex_lock(&sc->mtx);
412 
413 	if ((sc->mcr & MCR_LOOPBACK) != 0) {
414 		(void) read(sc->usc_bcons.clifd, &ch, 1);
415 	} else {
416 		for (;;) {
417 			nbytes = read(sc->usc_bcons.clifd, &ch, 1);
418 			if (nbytes == 0) {
419 				ret = 1;
420 				break;
421 			}
422 			if (nbytes == -1 &&
423 			    errno != EINTR && errno != EAGAIN) {
424 				ret = -1;
425 				break;
426 			}
427 			if (nbytes == -1) {
428 				break;
429 			}
430 
431 			if (fifo_available(&sc->rxfifo)) {
432 				fifo_putchar(&sc->rxfifo, ch);
433 			}
434 		}
435 		uart_toggle_intr(sc);
436 	}
437 
438 	pthread_mutex_unlock(&sc->mtx);
439 
440 	return (ret);
441 }
442 #endif
443 
444 void
445 uart_write(struct uart_softc *sc, int offset, uint8_t value)
446 {
447 	int fifosz;
448 	uint8_t msr;
449 
450 	pthread_mutex_lock(&sc->mtx);
451 
452 	/* Open terminal */
453 	if (!sc->opened && sc->stdio) {
454 		uart_opentty(sc);
455 		sc->opened = true;
456 	}
457 
458 	/*
459 	 * Take care of the special case DLAB accesses first
460 	 */
461 	if ((sc->lcr & LCR_DLAB) != 0) {
462 		if (offset == REG_DLL) {
463 			sc->dll = value;
464 			goto done;
465 		}
466 
467 		if (offset == REG_DLH) {
468 			sc->dlh = value;
469 			goto done;
470 		}
471 	}
472 
473         switch (offset) {
474 	case REG_DATA:
475 		if (sc->mcr & MCR_LOOPBACK) {
476 			if (fifo_putchar(&sc->rxfifo, value) != 0)
477 				sc->lsr |= LSR_OE;
478 		} else if (sc->stdio) {
479 			ttywrite(value);
480 #ifndef	__FreeBSD__
481 		} else if (sc->bcons) {
482 				bconswrite(sc, value);
483 #endif
484 		} /* else drop on floor */
485 		sc->thre_int_pending = true;
486 		break;
487 	case REG_IER:
488 		/*
489 		 * Apply mask so that bits 4-7 are 0
490 		 * Also enables bits 0-3 only if they're 1
491 		 */
492 		sc->ier = value & 0x0F;
493 		break;
494 		case REG_FCR:
495 			/*
496 			 * When moving from FIFO and 16450 mode and vice versa,
497 			 * the FIFO contents are reset.
498 			 */
499 			if ((sc->fcr & FCR_ENABLE) ^ (value & FCR_ENABLE)) {
500 				fifosz = (value & FCR_ENABLE) ? FIFOSZ : 1;
501 				fifo_reset(&sc->rxfifo, fifosz);
502 			}
503 
504 			/*
505 			 * The FCR_ENABLE bit must be '1' for the programming
506 			 * of other FCR bits to be effective.
507 			 */
508 			if ((value & FCR_ENABLE) == 0) {
509 				sc->fcr = 0;
510 			} else {
511 				if ((value & FCR_RCV_RST) != 0)
512 					fifo_reset(&sc->rxfifo, FIFOSZ);
513 
514 				sc->fcr = value &
515 					 (FCR_ENABLE | FCR_DMA | FCR_RX_MASK);
516 			}
517 			break;
518 		case REG_LCR:
519 			sc->lcr = value;
520 			break;
521 		case REG_MCR:
522 			/* Apply mask so that bits 5-7 are 0 */
523 			sc->mcr = value & 0x1F;
524 
525 			msr = 0;
526 			if (sc->mcr & MCR_LOOPBACK) {
527 				/*
528 				 * In the loopback mode certain bits from the
529 				 * MCR are reflected back into MSR
530 				 */
531 				if (sc->mcr & MCR_RTS)
532 					msr |= MSR_CTS;
533 				if (sc->mcr & MCR_DTR)
534 					msr |= MSR_DSR;
535 				if (sc->mcr & MCR_OUT1)
536 					msr |= MSR_RI;
537 				if (sc->mcr & MCR_OUT2)
538 					msr |= MSR_DCD;
539 			}
540 
541 			/*
542 			 * Detect if there has been any change between the
543 			 * previous and the new value of MSR. If there is
544 			 * then assert the appropriate MSR delta bit.
545 			 */
546 			if ((msr & MSR_CTS) ^ (sc->msr & MSR_CTS))
547 				sc->msr |= MSR_DCTS;
548 			if ((msr & MSR_DSR) ^ (sc->msr & MSR_DSR))
549 				sc->msr |= MSR_DDSR;
550 			if ((msr & MSR_DCD) ^ (sc->msr & MSR_DCD))
551 				sc->msr |= MSR_DDCD;
552 			if ((sc->msr & MSR_RI) != 0 && (msr & MSR_RI) == 0)
553 				sc->msr |= MSR_TERI;
554 
555 			/*
556 			 * Update the value of MSR while retaining the delta
557 			 * bits.
558 			 */
559 			sc->msr &= MSR_DELTA_MASK;
560 			sc->msr |= msr;
561 			break;
562 		case REG_LSR:
563 			/*
564 			 * Line status register is not meant to be written to
565 			 * during normal operation.
566 			 */
567 			break;
568 		case REG_MSR:
569 			/*
570 			 * As far as I can tell MSR is a read-only register.
571 			 */
572 			break;
573 		case REG_SCR:
574 			sc->scr = value;
575 			break;
576 		default:
577 			break;
578 	}
579 
580 done:
581 	uart_toggle_intr(sc);
582 	pthread_mutex_unlock(&sc->mtx);
583 }
584 
585 uint8_t
586 uart_read(struct uart_softc *sc, int offset)
587 {
588 	uint8_t iir, intr_reason, reg;
589 
590 	pthread_mutex_lock(&sc->mtx);
591 
592 	/* Open terminal */
593 	if (!sc->opened && sc->stdio) {
594 		uart_opentty(sc);
595 		sc->opened = true;
596 	}
597 
598 	/*
599 	 * Take care of the special case DLAB accesses first
600 	 */
601 	if ((sc->lcr & LCR_DLAB) != 0) {
602 		if (offset == REG_DLL) {
603 			reg = sc->dll;
604 			goto done;
605 		}
606 
607 		if (offset == REG_DLH) {
608 			reg = sc->dlh;
609 			goto done;
610 		}
611 	}
612 
613 	switch (offset) {
614 	case REG_DATA:
615 		reg = fifo_getchar(&sc->rxfifo);
616 		break;
617 	case REG_IER:
618 		reg = sc->ier;
619 		break;
620 	case REG_IIR:
621 		iir = (sc->fcr & FCR_ENABLE) ? IIR_FIFO_MASK : 0;
622 
623 		intr_reason = uart_intr_reason(sc);
624 
625 		/*
626 		 * Deal with side effects of reading the IIR register
627 		 */
628 		if (intr_reason == IIR_TXRDY)
629 			sc->thre_int_pending = false;
630 
631 		iir |= intr_reason;
632 
633 		reg = iir;
634 		break;
635 	case REG_LCR:
636 		reg = sc->lcr;
637 		break;
638 	case REG_MCR:
639 		reg = sc->mcr;
640 		break;
641 	case REG_LSR:
642 		/* Transmitter is always ready for more data */
643 		sc->lsr |= LSR_TEMT | LSR_THRE;
644 
645 		/* Check for new receive data */
646 		if (fifo_numchars(&sc->rxfifo) > 0)
647 			sc->lsr |= LSR_RXRDY;
648 		else
649 			sc->lsr &= ~LSR_RXRDY;
650 
651 		reg = sc->lsr;
652 
653 		/* The LSR_OE bit is cleared on LSR read */
654 		sc->lsr &= ~LSR_OE;
655 		break;
656 	case REG_MSR:
657 		/*
658 		 * MSR delta bits are cleared on read
659 		 */
660 		reg = sc->msr;
661 		sc->msr &= ~MSR_DELTA_MASK;
662 		break;
663 	case REG_SCR:
664 		reg = sc->scr;
665 		break;
666 	default:
667 		reg = 0xFF;
668 		break;
669 	}
670 
671 done:
672 	uart_toggle_intr(sc);
673 	pthread_mutex_unlock(&sc->mtx);
674 
675 	return (reg);
676 }
677 
678 #ifndef	__FreeBSD__
679 static void *
680 uart_tty_thread(void *param)
681 {
682 	struct uart_softc *sc = param;
683 	pollfd_t pollset;
684 
685 	pollset.fd = STDIN_FILENO;
686 	pollset.events = POLLIN | POLLPRI | POLLRDNORM | POLLRDBAND;
687 
688 	for (;;) {
689 		if (poll(&pollset, 1, -1) < 0) {
690 			if (errno != EINTR) {
691 				perror("poll failed");
692 				break;
693 			}
694 			continue;
695 		}
696 		uart_tty_drain(sc);
697 	}
698 
699 	return (NULL);
700 }
701 
702 /*
703  * Read the "ident" string from the client's descriptor; this routine also
704  * tolerates being called with pid=NULL, for times when you want to "eat"
705  * the ident string from a client without saving it.
706  */
707 static int
708 get_client_ident(int clifd, pid_t *pid)
709 {
710 	char buf[BUFSIZ], *bufp;
711 	size_t buflen = sizeof (buf);
712 	char c = '\0';
713 	int i = 0, r;
714 
715 	/* "eat up the ident string" case, for simplicity */
716 	if (pid == NULL) {
717 		while (read(clifd, &c, 1) == 1) {
718 			if (c == '\n')
719 				return (0);
720 		}
721 	}
722 
723 	bzero(buf, sizeof (buf));
724 	while ((buflen > 1) && (r = read(clifd, &c, 1)) == 1) {
725 		buflen--;
726 		if (c == '\n')
727 			break;
728 
729 		buf[i] = c;
730 		i++;
731 	}
732 	if (r == -1)
733 		return (-1);
734 
735 	/*
736 	 * We've filled the buffer, but still haven't seen \n.  Keep eating
737 	 * until we find it; we don't expect this to happen, but this is
738 	 * defensive.
739 	 */
740 	if (c != '\n') {
741 		while ((r = read(clifd, &c, sizeof (c))) > 0)
742 			if (c == '\n')
743 				break;
744 	}
745 
746 	/*
747 	 * Parse buffer for message of the form: IDENT <pid>
748 	 */
749 	bufp = buf;
750 	if (strncmp(bufp, "IDENT ", 6) != 0)
751 		return (-1);
752 	bufp += 6;
753 	errno = 0;
754 	*pid = strtoll(bufp, &bufp, 10);
755 	if (errno != 0)
756 		return (-1);
757 
758 	return (0);
759 }
760 
761 static int
762 uart_bcons_accept_client(struct uart_softc *sc)
763 {
764 	int connfd;
765 	struct sockaddr_un cliaddr;
766 	socklen_t clilen;
767 	pid_t pid;
768 
769 	clilen = sizeof (cliaddr);
770 	connfd = accept(sc->usc_bcons.servfd,
771 			(struct sockaddr *)&cliaddr, &clilen);
772 	if (connfd == -1)
773 		return (-1);
774 	if (get_client_ident(connfd, &pid) == -1) {
775 		(void) shutdown(connfd, SHUT_RDWR);
776 		(void) close(connfd);
777 		return (-1);
778 	}
779 
780 	if (fcntl(connfd, F_SETFL, O_NONBLOCK) < 0) {
781 		(void) shutdown(connfd, SHUT_RDWR);
782 		(void) close(connfd);
783 		return (-1);
784 	}
785 	(void) write(connfd, "OK\n", 3);
786 
787 	sc->usc_bcons.clipid = pid;
788 	sc->usc_bcons.clifd = connfd;
789 
790 	printf("Connection from process ID %lu.\n", pid);
791 
792 	return (0);
793 }
794 
795 static void
796 uart_bcons_reject_client(struct uart_softc *sc)
797 {
798 	int connfd;
799 	struct sockaddr_un cliaddr;
800 	socklen_t clilen;
801 	char nak[MAXPATHLEN];
802 
803 	clilen = sizeof (cliaddr);
804 	connfd = accept(sc->usc_bcons.servfd,
805 			(struct sockaddr *)&cliaddr, &clilen);
806 
807 	/*
808 	 * After hear its ident string, tell client to get lost.
809 	 */
810 	if (get_client_ident(connfd, NULL) == 0) {
811 		(void) snprintf(nak, sizeof (nak), "%lu\n",
812 		    sc->usc_bcons.clipid);
813 		(void) write(connfd, nak, strlen(nak));
814 	}
815 	(void) shutdown(connfd, SHUT_RDWR);
816 	(void) close(connfd);
817 }
818 
819 static int
820 uart_bcons_client_event(struct uart_softc *sc)
821 {
822 	int res;
823 
824 	res = uart_bcons_drain(sc);
825 	if (res < 0)
826 		return (-1);
827 
828 	if (res > 0) {
829 		fprintf(stderr, "Closing connection with bhyve console\n");
830 		(void) shutdown(sc->usc_bcons.clifd, SHUT_RDWR);
831 		(void) close(sc->usc_bcons.clifd);
832 		sc->usc_bcons.clifd = -1;
833 	}
834 
835 	return (0);
836 }
837 
838 static void
839 uart_bcons_server_event(struct uart_softc *sc)
840 {
841 	int clifd;
842 
843 	if (sc->usc_bcons.clifd != -1) {
844 		/* we're already handling a client */
845 		uart_bcons_reject_client(sc);
846 		return;
847 	}
848 
849 	if (uart_bcons_accept_client(sc) == 0) {
850 		pthread_mutex_lock(&bcons_wait_lock);
851 		bcons_connected = B_TRUE;
852 		pthread_cond_signal(&bcons_wait_done);
853 		pthread_mutex_unlock(&bcons_wait_lock);
854 	}
855 }
856 
857 static void *
858 uart_bcons_thread(void *param)
859 {
860 	struct uart_softc *sc = param;
861 	struct pollfd pollfds[2];
862 	int res;
863 
864 	/* read from client and write to vm */
865 	pollfds[0].events = POLLIN | POLLRDNORM | POLLRDBAND |
866 	    POLLPRI | POLLERR | POLLHUP;
867 
868 	/* the server socket; watch for events (new connections) */
869 	pollfds[1].events = pollfds[0].events;
870 
871 	for (;;) {
872 		pollfds[0].fd = sc->usc_bcons.clifd;
873 		pollfds[1].fd = sc->usc_bcons.servfd;
874 		pollfds[0].revents = pollfds[1].revents = 0;
875 
876 		res = poll(pollfds,
877 		    sizeof (pollfds) / sizeof (struct pollfd), -1);
878 
879 		if (res == -1 && errno != EINTR) {
880 			perror("poll failed");
881 			/* we are hosed, close connection */
882 			break;
883 		}
884 
885 		/* event from client side */
886 		if (pollfds[0].revents) {
887 			if (pollfds[0].revents &
888 			    (POLLIN | POLLRDNORM | POLLRDBAND | POLLPRI)) {
889 				if (uart_bcons_client_event(sc) < 0)
890 					break;
891 			} else {
892 				break;
893 			}
894 		}
895 
896 		/* event from server socket */
897 		if (pollfds[1].revents) {
898 			if (pollfds[1].revents & (POLLIN | POLLRDNORM)) {
899 				uart_bcons_server_event(sc);
900 			} else {
901 				break;
902 			}
903 		}
904 	}
905 
906 	if (sc->usc_bcons.clifd != -1) {
907 		fprintf(stderr, "Closing connection with bhyve console\n");
908 		(void) shutdown(sc->usc_bcons.clifd, SHUT_RDWR);
909 		(void) close(sc->usc_bcons.clifd);
910 		sc->usc_bcons.clifd = -1;
911 	}
912 
913 	return (NULL);
914 }
915 
916 static int
917 init_bcons_sock(void)
918 {
919 	int servfd;
920 	struct sockaddr_un servaddr;
921 
922 	if (mkdir(BHYVE_TMPDIR, S_IRWXU) < 0 && errno != EEXIST) {
923 		fprintf(stderr, "bhyve console setup: "
924 		    "could not mkdir %s", BHYVE_TMPDIR, strerror(errno));
925 		return (-1);
926 	}
927 
928 	bzero(&servaddr, sizeof (servaddr));
929 	servaddr.sun_family = AF_UNIX;
930 	(void) snprintf(servaddr.sun_path, sizeof (servaddr.sun_path),
931 	    BHYVE_CONS_SOCKPATH, vmname);
932 
933 	if ((servfd = socket(AF_UNIX, SOCK_STREAM, 0)) == -1) {
934 		fprintf(stderr, "bhyve console setup: "
935 		    "could not create socket\n");
936 		return (-1);
937 	}
938 	(void) unlink(servaddr.sun_path);
939 
940 	if (bind(servfd, (struct sockaddr *)&servaddr,
941 	    sizeof (servaddr)) == -1) {
942 		fprintf(stderr, "bhyve console setup: "
943 		    "could not bind to socket\n");
944 		goto out;
945         }
946 
947         if (listen(servfd, 4) == -1) {
948 		fprintf(stderr, "bhyve console setup: "
949 		    "could not listen on socket");
950 		goto out;
951         }
952         return (servfd);
953 
954 out:
955 	(void) unlink(servaddr.sun_path);
956         (void) close(servfd);
957         return (-1);
958 }
959 #endif
960 
961 int
962 uart_legacy_alloc(int which, int *baseaddr, int *irq)
963 {
964 
965 	if (which < 0 || which >= UART_NLDEVS || uart_lres[which].inuse)
966 		return (-1);
967 
968 	uart_lres[which].inuse = true;
969 	*baseaddr = uart_lres[which].baseaddr;
970 	*irq = uart_lres[which].irq;
971 
972 	return (0);
973 }
974 
975 struct uart_softc *
976 uart_init(uart_intr_func_t intr_assert, uart_intr_func_t intr_deassert,
977     void *arg)
978 {
979 	struct uart_softc *sc;
980 
981 	sc = malloc(sizeof(struct uart_softc));
982 	bzero(sc, sizeof(struct uart_softc));
983 
984 	sc->arg = arg;
985 	sc->intr_assert = intr_assert;
986 	sc->intr_deassert = intr_deassert;
987 
988 	pthread_mutex_init(&sc->mtx, NULL);
989 
990 	uart_reset(sc);
991 
992 	return (sc);
993 }
994 
995 int
996 uart_set_backend(struct uart_softc *sc, const char *opts)
997 {
998 #ifndef	__FreeBSD__
999 	int error;
1000 #endif
1001 	/*
1002 	 * XXX one stdio backend supported at this time.
1003 	 */
1004 	if (opts == NULL)
1005 		return (0);
1006 
1007 #ifdef	__FreeBSD__
1008 	if (strcmp("stdio", opts) == 0 && !uart_stdio) {
1009 		sc->stdio = true;
1010 		uart_stdio = true;
1011 		return (0);
1012 #else
1013 	if (strcmp("stdio", opts) == 0 && !uart_stdio && !uart_bcons) {
1014 		sc->stdio = true;
1015 		uart_stdio = true;
1016 
1017 		error = pthread_create(NULL, NULL, uart_tty_thread, sc);
1018 		assert(error == 0);
1019 
1020 		return (0);
1021 	} else if (strstr(opts, "bcons") != 0 && !uart_stdio && !uart_bcons) {
1022 		sc->bcons = true;
1023 		uart_bcons= true;
1024 
1025 		if (strstr(opts, "bcons,wait") != 0) {
1026 			bcons_wait = true;
1027 		}
1028 
1029 		sc->usc_bcons.clifd = -1;
1030 		if ((sc->usc_bcons.servfd = init_bcons_sock()) == -1) {
1031 			fprintf(stderr, "bhyve console setup: "
1032 			    "socket initialization failed\n");
1033 			return (-1);
1034 		}
1035 		error = pthread_create(NULL, NULL, uart_bcons_thread, sc);
1036 		assert(error == 0);
1037 
1038 		return (0);
1039 #endif
1040 	} else
1041 		return (-1);
1042 }
1043