1234938Sgrehan/*- 2234938Sgrehan * Copyright (c) 2012 NetApp, Inc. 3234938Sgrehan * All rights reserved. 4234938Sgrehan * 5234938Sgrehan * Redistribution and use in source and binary forms, with or without 6234938Sgrehan * modification, are permitted provided that the following conditions 7234938Sgrehan * are met: 8234938Sgrehan * 1. Redistributions of source code must retain the above copyright 9234938Sgrehan * notice, this list of conditions and the following disclaimer. 10234938Sgrehan * 2. Redistributions in binary form must reproduce the above copyright 11234938Sgrehan * notice, this list of conditions and the following disclaimer in the 12234938Sgrehan * documentation and/or other materials provided with the distribution. 13234938Sgrehan * 14234938Sgrehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15234938Sgrehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16234938Sgrehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17234938Sgrehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18234938Sgrehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19234938Sgrehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20234938Sgrehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21234938Sgrehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22234938Sgrehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23234938Sgrehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24234938Sgrehan * SUCH DAMAGE. 25234938Sgrehan * 26234938Sgrehan * $FreeBSD$ 27234938Sgrehan */ 28234938Sgrehan 29234938Sgrehan#include <sys/cdefs.h> 30234938Sgrehan__FBSDID("$FreeBSD$"); 31234938Sgrehan 32234938Sgrehan#include <sys/types.h> 33234938Sgrehan 34234938Sgrehan#include <stdio.h> 35234938Sgrehan 36244167Sgrehan#include "bhyverun.h" 37234938Sgrehan#include "pci_emul.h" 38257396Sneel#include "uart_emul.h" 39234938Sgrehan 40234938Sgrehan/* 41234938Sgrehan * Pick a PCI vid/did of a chip with a single uart at 42234938Sgrehan * BAR0, that most versions of FreeBSD can understand: 43234938Sgrehan * Siig CyberSerial 1-port. 44234938Sgrehan */ 45234938Sgrehan#define COM_VENDOR 0x131f 46234938Sgrehan#define COM_DEV 0x2000 47234938Sgrehan 48234938Sgrehanstatic void 49257396Sneelpci_uart_intr_assert(void *arg) 50234938Sgrehan{ 51257396Sneel struct pci_devinst *pi = arg; 52234938Sgrehan 53257396Sneel pci_lintr_assert(pi); 54234938Sgrehan} 55234938Sgrehan 56234938Sgrehanstatic void 57257396Sneelpci_uart_intr_deassert(void *arg) 58234938Sgrehan{ 59257396Sneel struct pci_devinst *pi = arg; 60234938Sgrehan 61257396Sneel pci_lintr_deassert(pi); 62234938Sgrehan} 63234938Sgrehan 64234938Sgrehanstatic void 65241744Sgrehanpci_uart_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 66241744Sgrehan int baridx, uint64_t offset, int size, uint64_t value) 67234938Sgrehan{ 68234938Sgrehan 69241744Sgrehan assert(baridx == 0); 70234938Sgrehan assert(size == 1); 71234938Sgrehan 72257396Sneel uart_write(pi->pi_arg, offset, value); 73234938Sgrehan} 74234938Sgrehan 75241744Sgrehanuint64_t 76241744Sgrehanpci_uart_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi, 77241744Sgrehan int baridx, uint64_t offset, int size) 78234938Sgrehan{ 79257396Sneel uint8_t val; 80234938Sgrehan 81241744Sgrehan assert(baridx == 0); 82234938Sgrehan assert(size == 1); 83234938Sgrehan 84257396Sneel val = uart_read(pi->pi_arg, offset); 85257396Sneel return (val); 86257396Sneel} 87234938Sgrehan 88234938Sgrehanstatic int 89234938Sgrehanpci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 90234938Sgrehan{ 91257396Sneel struct uart_softc *sc; 92234938Sgrehan 93267341Sjhb pci_emul_alloc_bar(pi, 0, PCIBAR_IO, UART_IO_BAR_SIZE); 94267393Sjhb pci_lintr_request(pi); 95234938Sgrehan 96257396Sneel /* initialize config space */ 97257396Sneel pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV); 98257396Sneel pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR); 99257396Sneel pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM); 100257396Sneel 101257396Sneel sc = uart_init(pci_uart_intr_assert, pci_uart_intr_deassert, pi); 102257396Sneel pi->pi_arg = sc; 103257396Sneel 104257396Sneel if (uart_set_backend(sc, opts) != 0) { 105257396Sneel fprintf(stderr, "Unable to initialize backend '%s' for " 106257396Sneel "pci uart at %d:%d\n", opts, pi->pi_slot, pi->pi_func); 107257396Sneel return (-1); 108234938Sgrehan } 109234938Sgrehan 110234938Sgrehan return (0); 111234938Sgrehan} 112234938Sgrehan 113234938Sgrehanstruct pci_devemu pci_de_com = { 114241744Sgrehan .pe_emu = "uart", 115241744Sgrehan .pe_init = pci_uart_init, 116241744Sgrehan .pe_barwrite = pci_uart_write, 117241744Sgrehan .pe_barread = pci_uart_read 118234938Sgrehan}; 119234938SgrehanPCI_EMUL_SET(pci_de_com); 120