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: releng/11.0/usr.sbin/bhyve/pci_uart.c 261268 2014-01-29 14:56:48Z jhb $
27234938Sgrehan */
28234938Sgrehan
29234938Sgrehan#include <sys/cdefs.h>
30234938Sgrehan__FBSDID("$FreeBSD: releng/11.0/usr.sbin/bhyve/pci_uart.c 261268 2014-01-29 14:56:48Z jhb $");
31234938Sgrehan
32234938Sgrehan#include <sys/types.h>
33234938Sgrehan
34234938Sgrehan#include <stdio.h>
35234938Sgrehan
36244167Sgrehan#include "bhyverun.h"
37234938Sgrehan#include "pci_emul.h"
38257293Sneel#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
49257293Sneelpci_uart_intr_assert(void *arg)
50234938Sgrehan{
51257293Sneel	struct pci_devinst *pi = arg;
52234938Sgrehan
53257293Sneel	pci_lintr_assert(pi);
54234938Sgrehan}
55234938Sgrehan
56234938Sgrehanstatic void
57257293Sneelpci_uart_intr_deassert(void *arg)
58234938Sgrehan{
59257293Sneel	struct pci_devinst *pi = arg;
60234938Sgrehan
61257293Sneel	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
72257293Sneel	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{
79257293Sneel	uint8_t val;
80234938Sgrehan
81241744Sgrehan	assert(baridx == 0);
82234938Sgrehan	assert(size == 1);
83234938Sgrehan
84257293Sneel	val = uart_read(pi->pi_arg, offset);
85257293Sneel	return (val);
86257293Sneel}
87234938Sgrehan
88234938Sgrehanstatic int
89234938Sgrehanpci_uart_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
90234938Sgrehan{
91257293Sneel	struct uart_softc *sc;
92234938Sgrehan
93261217Sjhb	pci_emul_alloc_bar(pi, 0, PCIBAR_IO, UART_IO_BAR_SIZE);
94261268Sjhb	pci_lintr_request(pi);
95234938Sgrehan
96257293Sneel	/* initialize config space */
97257293Sneel	pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
98257293Sneel	pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
99257293Sneel	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM);
100257293Sneel
101257293Sneel	sc = uart_init(pci_uart_intr_assert, pci_uart_intr_deassert, pi);
102257293Sneel	pi->pi_arg = sc;
103257293Sneel
104257293Sneel	if (uart_set_backend(sc, opts) != 0) {
105257293Sneel		fprintf(stderr, "Unable to initialize backend '%s' for "
106257293Sneel		    "pci uart at %d:%d\n", opts, pi->pi_slot, pi->pi_func);
107257293Sneel		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