1221828Sgrehan/*- 2221828Sgrehan * Copyright (c) 2011 NetApp, Inc. 3221828Sgrehan * All rights reserved. 4221828Sgrehan * 5221828Sgrehan * Redistribution and use in source and binary forms, with or without 6221828Sgrehan * modification, are permitted provided that the following conditions 7221828Sgrehan * are met: 8221828Sgrehan * 1. Redistributions of source code must retain the above copyright 9221828Sgrehan * notice, this list of conditions and the following disclaimer. 10221828Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11221828Sgrehan * notice, this list of conditions and the following disclaimer in the 12221828Sgrehan * documentation and/or other materials provided with the distribution. 13221828Sgrehan * 14221828Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15221828Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16221828Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17221828Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18221828Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19221828Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20221828Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21221828Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22221828Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23221828Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24221828Sgrehan * SUCH DAMAGE. 25221828Sgrehan * 26221828Sgrehan * $FreeBSD$ 27221828Sgrehan */ 28221828Sgrehan 29221828Sgrehan#include <sys/cdefs.h> 30221828Sgrehan__FBSDID("$FreeBSD$"); 31221828Sgrehan 32221828Sgrehan#include <sys/types.h> 33221828Sgrehan#include <sys/select.h> 34221828Sgrehan 35221828Sgrehan#include <stdio.h> 36221828Sgrehan#include <stdlib.h> 37221828Sgrehan#include <termios.h> 38221828Sgrehan#include <unistd.h> 39221828Sgrehan#include <stdbool.h> 40221828Sgrehan 41221828Sgrehan#include "inout.h" 42262227Sjhb#include "pci_lpc.h" 43221828Sgrehan 44221828Sgrehan#define BVM_CONSOLE_PORT 0x220 45222105Sgrehan#define BVM_CONS_SIG ('b' << 8 | 'v') 46221828Sgrehan 47221828Sgrehanstatic struct termios tio_orig, tio_new; 48221828Sgrehan 49221828Sgrehanstatic void 50221828Sgrehanttyclose(void) 51221828Sgrehan{ 52221828Sgrehan tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig); 53221828Sgrehan} 54221828Sgrehan 55221828Sgrehanstatic void 56221828Sgrehanttyopen(void) 57221828Sgrehan{ 58221828Sgrehan tcgetattr(STDIN_FILENO, &tio_orig); 59221828Sgrehan 60221828Sgrehan cfmakeraw(&tio_new); 61221828Sgrehan tcsetattr(STDIN_FILENO, TCSANOW, &tio_new); 62221828Sgrehan 63221828Sgrehan atexit(ttyclose); 64221828Sgrehan} 65221828Sgrehan 66221828Sgrehanstatic bool 67221828Sgrehantty_char_available(void) 68221828Sgrehan{ 69221828Sgrehan fd_set rfds; 70221828Sgrehan struct timeval tv; 71221828Sgrehan 72221828Sgrehan FD_ZERO(&rfds); 73221828Sgrehan FD_SET(STDIN_FILENO, &rfds); 74221828Sgrehan tv.tv_sec = 0; 75221828Sgrehan tv.tv_usec = 0; 76221828Sgrehan if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0) { 77221828Sgrehan return (true); 78221828Sgrehan } else { 79221828Sgrehan return (false); 80221828Sgrehan } 81221828Sgrehan} 82221828Sgrehan 83221828Sgrehanstatic int 84221828Sgrehanttyread(void) 85221828Sgrehan{ 86221828Sgrehan char rb; 87221828Sgrehan 88221828Sgrehan if (tty_char_available()) { 89221828Sgrehan read(STDIN_FILENO, &rb, 1); 90221828Sgrehan return (rb & 0xff); 91221828Sgrehan } else { 92221828Sgrehan return (-1); 93221828Sgrehan } 94221828Sgrehan} 95221828Sgrehan 96221828Sgrehanstatic void 97221828Sgrehanttywrite(unsigned char wb) 98221828Sgrehan{ 99221828Sgrehan (void) write(STDOUT_FILENO, &wb, 1); 100221828Sgrehan} 101221828Sgrehan 102221828Sgrehanstatic int 103221828Sgrehanconsole_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 104221828Sgrehan uint32_t *eax, void *arg) 105221828Sgrehan{ 106221828Sgrehan static int opened; 107221828Sgrehan 108222105Sgrehan if (bytes == 2 && in) { 109222105Sgrehan *eax = BVM_CONS_SIG; 110222105Sgrehan return (0); 111222105Sgrehan } 112222105Sgrehan 113267928Sjhb /* 114267928Sjhb * Guests might probe this port to look for old ISA devices 115267928Sjhb * using single-byte reads. Return 0xff for those. 116267928Sjhb */ 117267928Sjhb if (bytes == 1 && in) { 118267928Sjhb *eax = 0xff; 119267928Sjhb return (0); 120267928Sjhb } 121267928Sjhb 122221828Sgrehan if (bytes != 4) 123221828Sgrehan return (-1); 124221828Sgrehan 125221828Sgrehan if (!opened) { 126221828Sgrehan ttyopen(); 127221828Sgrehan opened = 1; 128221828Sgrehan } 129221828Sgrehan 130221828Sgrehan if (in) 131221828Sgrehan *eax = ttyread(); 132221828Sgrehan else 133221828Sgrehan ttywrite(*eax); 134221828Sgrehan 135221828Sgrehan return (0); 136221828Sgrehan} 137242192Sneel 138262227SjhbSYSRES_IO(BVM_CONSOLE_PORT, 4); 139262227Sjhb 140242192Sneelstatic struct inout_port consport = { 141242192Sneel "bvmcons", 142242192Sneel BVM_CONSOLE_PORT, 143249321Sneel 1, 144242192Sneel IOPORT_F_INOUT, 145242192Sneel console_handler 146242192Sneel}; 147242192Sneel 148242192Sneelvoid 149242192Sneelinit_bvmcons(void) 150242192Sneel{ 151242192Sneel 152242192Sneel register_inout(&consport); 153242192Sneel} 154