14c87aefeSPatrick Mooney /*-
2*32640292SAndy Fiddaman * SPDX-License-Identifier: BSD-2-Clause
34c87aefeSPatrick Mooney *
44c87aefeSPatrick Mooney * Copyright (c) 2012 NetApp, Inc.
54c87aefeSPatrick Mooney * All rights reserved.
64c87aefeSPatrick Mooney *
74c87aefeSPatrick Mooney * Redistribution and use in source and binary forms, with or without
84c87aefeSPatrick Mooney * modification, are permitted provided that the following conditions
94c87aefeSPatrick Mooney * are met:
104c87aefeSPatrick Mooney * 1. Redistributions of source code must retain the above copyright
114c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer.
124c87aefeSPatrick Mooney * 2. Redistributions in binary form must reproduce the above copyright
134c87aefeSPatrick Mooney * notice, this list of conditions and the following disclaimer in the
144c87aefeSPatrick Mooney * documentation and/or other materials provided with the distribution.
154c87aefeSPatrick Mooney *
164c87aefeSPatrick Mooney * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
174c87aefeSPatrick Mooney * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
184c87aefeSPatrick Mooney * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
194c87aefeSPatrick Mooney * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
204c87aefeSPatrick Mooney * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
214c87aefeSPatrick Mooney * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
224c87aefeSPatrick Mooney * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
234c87aefeSPatrick Mooney * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
244c87aefeSPatrick Mooney * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
254c87aefeSPatrick Mooney * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
264c87aefeSPatrick Mooney * SUCH DAMAGE.
274c87aefeSPatrick Mooney */
284c87aefeSPatrick Mooney
294c87aefeSPatrick Mooney #include <sys/cdefs.h>
304c87aefeSPatrick Mooney
314c87aefeSPatrick Mooney #include <sys/types.h>
324c87aefeSPatrick Mooney
334c87aefeSPatrick Mooney #include <stdio.h>
344c87aefeSPatrick Mooney
354c87aefeSPatrick Mooney #include "bhyverun.h"
362b948146SAndy Fiddaman #include "config.h"
37154972afSPatrick Mooney #include "debug.h"
384c87aefeSPatrick Mooney #include "pci_emul.h"
394c87aefeSPatrick Mooney #include "uart_emul.h"
404c87aefeSPatrick Mooney
414c87aefeSPatrick Mooney /*
424c87aefeSPatrick Mooney * Pick a PCI vid/did of a chip with a single uart at
434c87aefeSPatrick Mooney * BAR0, that most versions of FreeBSD can understand:
444c87aefeSPatrick Mooney * Siig CyberSerial 1-port.
454c87aefeSPatrick Mooney */
464c87aefeSPatrick Mooney #define COM_VENDOR 0x131f
474c87aefeSPatrick Mooney #define COM_DEV 0x2000
484c87aefeSPatrick Mooney
494c87aefeSPatrick Mooney static void
pci_uart_intr_assert(void * arg)504c87aefeSPatrick Mooney pci_uart_intr_assert(void *arg)
514c87aefeSPatrick Mooney {
524c87aefeSPatrick Mooney struct pci_devinst *pi = arg;
534c87aefeSPatrick Mooney
544c87aefeSPatrick Mooney pci_lintr_assert(pi);
554c87aefeSPatrick Mooney }
564c87aefeSPatrick Mooney
574c87aefeSPatrick Mooney static void
pci_uart_intr_deassert(void * arg)584c87aefeSPatrick Mooney pci_uart_intr_deassert(void *arg)
594c87aefeSPatrick Mooney {
604c87aefeSPatrick Mooney struct pci_devinst *pi = arg;
614c87aefeSPatrick Mooney
624c87aefeSPatrick Mooney pci_lintr_deassert(pi);
634c87aefeSPatrick Mooney }
644c87aefeSPatrick Mooney
654c87aefeSPatrick Mooney static void
pci_uart_write(struct pci_devinst * pi,int baridx,uint64_t offset,int size,uint64_t value)66*32640292SAndy Fiddaman pci_uart_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
6759d65d31SAndy Fiddaman uint64_t value)
684c87aefeSPatrick Mooney {
694c87aefeSPatrick Mooney assert(baridx == 0);
704c87aefeSPatrick Mooney assert(size == 1);
714c87aefeSPatrick Mooney
724c87aefeSPatrick Mooney uart_write(pi->pi_arg, offset, value);
734c87aefeSPatrick Mooney }
744c87aefeSPatrick Mooney
7559d65d31SAndy Fiddaman static uint64_t
pci_uart_read(struct pci_devinst * pi,int baridx,uint64_t offset,int size)76*32640292SAndy Fiddaman pci_uart_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
774c87aefeSPatrick Mooney {
784c87aefeSPatrick Mooney uint8_t val;
794c87aefeSPatrick Mooney
804c87aefeSPatrick Mooney assert(baridx == 0);
814c87aefeSPatrick Mooney assert(size == 1);
824c87aefeSPatrick Mooney
834c87aefeSPatrick Mooney val = uart_read(pi->pi_arg, offset);
844c87aefeSPatrick Mooney return (val);
854c87aefeSPatrick Mooney }
864c87aefeSPatrick Mooney
874c87aefeSPatrick Mooney static int
pci_uart_legacy_config(nvlist_t * nvl,const char * opts)882b948146SAndy Fiddaman pci_uart_legacy_config(nvlist_t *nvl, const char *opts)
892b948146SAndy Fiddaman {
902b948146SAndy Fiddaman
912b948146SAndy Fiddaman if (opts != NULL)
922b948146SAndy Fiddaman set_config_value_node(nvl, "path", opts);
932b948146SAndy Fiddaman return (0);
942b948146SAndy Fiddaman }
952b948146SAndy Fiddaman
962b948146SAndy Fiddaman static int
pci_uart_init(struct pci_devinst * pi,nvlist_t * nvl)97*32640292SAndy Fiddaman pci_uart_init(struct pci_devinst *pi, nvlist_t *nvl)
984c87aefeSPatrick Mooney {
994c87aefeSPatrick Mooney struct uart_softc *sc;
1002b948146SAndy Fiddaman const char *device;
1014c87aefeSPatrick Mooney
1024c87aefeSPatrick Mooney pci_emul_alloc_bar(pi, 0, PCIBAR_IO, UART_IO_BAR_SIZE);
1034c87aefeSPatrick Mooney pci_lintr_request(pi);
1044c87aefeSPatrick Mooney
1054c87aefeSPatrick Mooney /* initialize config space */
1064c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_DEVICE, COM_DEV);
1074c87aefeSPatrick Mooney pci_set_cfgdata16(pi, PCIR_VENDOR, COM_VENDOR);
1084c87aefeSPatrick Mooney pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_SIMPLECOMM);
1094c87aefeSPatrick Mooney
1104c87aefeSPatrick Mooney sc = uart_init(pci_uart_intr_assert, pci_uart_intr_deassert, pi);
1114c87aefeSPatrick Mooney pi->pi_arg = sc;
1124c87aefeSPatrick Mooney
1132b948146SAndy Fiddaman device = get_config_value_node(nvl, "path");
1142b948146SAndy Fiddaman if (uart_set_backend(sc, device) != 0) {
115154972afSPatrick Mooney EPRINTLN("Unable to initialize backend '%s' for "
1162b948146SAndy Fiddaman "pci uart at %d:%d", device, pi->pi_slot, pi->pi_func);
1174c87aefeSPatrick Mooney return (-1);
1184c87aefeSPatrick Mooney }
1194c87aefeSPatrick Mooney
1204c87aefeSPatrick Mooney return (0);
1214c87aefeSPatrick Mooney }
1224c87aefeSPatrick Mooney
1234f3f3e9aSAndy Fiddaman static const struct pci_devemu pci_de_com = {
1244c87aefeSPatrick Mooney .pe_emu = "uart",
1254c87aefeSPatrick Mooney .pe_init = pci_uart_init,
1262b948146SAndy Fiddaman .pe_legacy_config = pci_uart_legacy_config,
1274c87aefeSPatrick Mooney .pe_barwrite = pci_uart_write,
1284c87aefeSPatrick Mooney .pe_barread = pci_uart_read
1294c87aefeSPatrick Mooney };
1304c87aefeSPatrick Mooney PCI_EMUL_SET(pci_de_com);
131