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" 42221828Sgrehan 43221828Sgrehan#define BVM_CONSOLE_PORT 0x220 44222105Sgrehan#define BVM_CONS_SIG ('b' << 8 | 'v') 45221828Sgrehan 46221828Sgrehanstatic struct termios tio_orig, tio_new; 47221828Sgrehan 48221828Sgrehanstatic void 49221828Sgrehanttyclose(void) 50221828Sgrehan{ 51221828Sgrehan tcsetattr(STDIN_FILENO, TCSANOW, &tio_orig); 52221828Sgrehan} 53221828Sgrehan 54221828Sgrehanstatic void 55221828Sgrehanttyopen(void) 56221828Sgrehan{ 57221828Sgrehan tcgetattr(STDIN_FILENO, &tio_orig); 58221828Sgrehan 59221828Sgrehan cfmakeraw(&tio_new); 60221828Sgrehan tcsetattr(STDIN_FILENO, TCSANOW, &tio_new); 61221828Sgrehan 62221828Sgrehan atexit(ttyclose); 63221828Sgrehan} 64221828Sgrehan 65221828Sgrehanstatic bool 66221828Sgrehantty_char_available(void) 67221828Sgrehan{ 68221828Sgrehan fd_set rfds; 69221828Sgrehan struct timeval tv; 70221828Sgrehan 71221828Sgrehan FD_ZERO(&rfds); 72221828Sgrehan FD_SET(STDIN_FILENO, &rfds); 73221828Sgrehan tv.tv_sec = 0; 74221828Sgrehan tv.tv_usec = 0; 75221828Sgrehan if (select(STDIN_FILENO + 1, &rfds, NULL, NULL, &tv) > 0) { 76221828Sgrehan return (true); 77221828Sgrehan } else { 78221828Sgrehan return (false); 79221828Sgrehan } 80221828Sgrehan} 81221828Sgrehan 82221828Sgrehanstatic int 83221828Sgrehanttyread(void) 84221828Sgrehan{ 85221828Sgrehan char rb; 86221828Sgrehan 87221828Sgrehan if (tty_char_available()) { 88221828Sgrehan read(STDIN_FILENO, &rb, 1); 89221828Sgrehan return (rb & 0xff); 90221828Sgrehan } else { 91221828Sgrehan return (-1); 92221828Sgrehan } 93221828Sgrehan} 94221828Sgrehan 95221828Sgrehanstatic void 96221828Sgrehanttywrite(unsigned char wb) 97221828Sgrehan{ 98221828Sgrehan (void) write(STDOUT_FILENO, &wb, 1); 99221828Sgrehan} 100221828Sgrehan 101221828Sgrehanstatic int 102221828Sgrehanconsole_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 103221828Sgrehan uint32_t *eax, void *arg) 104221828Sgrehan{ 105221828Sgrehan static int opened; 106221828Sgrehan 107222105Sgrehan if (bytes == 2 && in) { 108222105Sgrehan *eax = BVM_CONS_SIG; 109222105Sgrehan return (0); 110222105Sgrehan } 111222105Sgrehan 112221828Sgrehan if (bytes != 4) 113221828Sgrehan return (-1); 114221828Sgrehan 115221828Sgrehan if (!opened) { 116221828Sgrehan ttyopen(); 117221828Sgrehan opened = 1; 118221828Sgrehan } 119221828Sgrehan 120221828Sgrehan if (in) 121221828Sgrehan *eax = ttyread(); 122221828Sgrehan else 123221828Sgrehan ttywrite(*eax); 124221828Sgrehan 125221828Sgrehan return (0); 126221828Sgrehan} 127242192Sneel 128242192Sneelstatic struct inout_port consport = { 129242192Sneel "bvmcons", 130242192Sneel BVM_CONSOLE_PORT, 131249321Sneel 1, 132242192Sneel IOPORT_F_INOUT, 133242192Sneel console_handler 134242192Sneel}; 135242192Sneel 136242192Sneelvoid 137242192Sneelinit_bvmcons(void) 138242192Sneel{ 139242192Sneel 140242192Sneel register_inout(&consport); 141242192Sneel} 142