1366f6083SPeter Grehan /*-
24d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
4366f6083SPeter Grehan * Copyright (c) 2011 NetApp, Inc.
5366f6083SPeter Grehan * All rights reserved.
6366f6083SPeter Grehan *
7366f6083SPeter Grehan * Redistribution and use in source and binary forms, with or without
8366f6083SPeter Grehan * modification, are permitted provided that the following conditions
9366f6083SPeter Grehan * are met:
10366f6083SPeter Grehan * 1. Redistributions of source code must retain the above copyright
11366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer.
12366f6083SPeter Grehan * 2. Redistributions in binary form must reproduce the above copyright
13366f6083SPeter Grehan * notice, this list of conditions and the following disclaimer in the
14366f6083SPeter Grehan * documentation and/or other materials provided with the distribution.
15366f6083SPeter Grehan *
16366f6083SPeter Grehan * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND
17366f6083SPeter Grehan * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18366f6083SPeter Grehan * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19366f6083SPeter Grehan * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE
20366f6083SPeter Grehan * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21366f6083SPeter Grehan * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22366f6083SPeter Grehan * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23366f6083SPeter Grehan * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24366f6083SPeter Grehan * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25366f6083SPeter Grehan * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26366f6083SPeter Grehan * SUCH DAMAGE.
27366f6083SPeter Grehan */
28366f6083SPeter Grehan
29366f6083SPeter Grehan #include <sys/cdefs.h>
30b72e06b1SCorvin Köhne #include <err.h>
31621b5090SJohn Baldwin #include <stdlib.h>
32621b5090SJohn Baldwin
33621b5090SJohn Baldwin #include "config.h"
34366f6083SPeter Grehan #include "pci_emul.h"
35366f6083SPeter Grehan
36366f6083SPeter Grehan static int
pci_hostbridge_init(struct pci_devinst * pi,nvlist_t * nvl)376a284cacSJohn Baldwin pci_hostbridge_init(struct pci_devinst *pi, nvlist_t *nvl)
38366f6083SPeter Grehan {
39621b5090SJohn Baldwin const char *value;
40621b5090SJohn Baldwin u_int vendor, device;
41621b5090SJohn Baldwin
42621b5090SJohn Baldwin vendor = 0x1275; /* NetApp */
43621b5090SJohn Baldwin device = 0x1275; /* NetApp */
44621b5090SJohn Baldwin
45621b5090SJohn Baldwin value = get_config_value_node(nvl, "vendor");
46621b5090SJohn Baldwin if (value != NULL)
47621b5090SJohn Baldwin vendor = strtol(value, NULL, 0);
48b72e06b1SCorvin Köhne else
49b72e06b1SCorvin Köhne vendor = pci_config_read_reg(NULL, nvl, PCIR_VENDOR, 2, vendor);
509f40a3beSJohn Baldwin value = get_config_value_node(nvl, "devid");
51621b5090SJohn Baldwin if (value != NULL)
52621b5090SJohn Baldwin device = strtol(value, NULL, 0);
53b72e06b1SCorvin Köhne else
54b72e06b1SCorvin Köhne device = pci_config_read_reg(NULL, nvl, PCIR_DEVICE, 2, device);
55366f6083SPeter Grehan
56366f6083SPeter Grehan /* config space */
57621b5090SJohn Baldwin pci_set_cfgdata16(pi, PCIR_VENDOR, vendor);
58621b5090SJohn Baldwin pci_set_cfgdata16(pi, PCIR_DEVICE, device);
59a0df62cdSTycho Nightingale pci_set_cfgdata8(pi, PCIR_HDRTYPE, PCIM_HDRTYPE_NORMAL);
60366f6083SPeter Grehan pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE);
61366f6083SPeter Grehan pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_HOST);
62366f6083SPeter Grehan
6374f80b23SNeel Natu pci_emul_add_pciecap(pi, PCIEM_TYPE_ROOT_PORT);
6474f80b23SNeel Natu
65366f6083SPeter Grehan return (0);
66366f6083SPeter Grehan }
67366f6083SPeter Grehan
68062b878fSPeter Grehan static int
pci_amd_hostbridge_legacy_config(nvlist_t * nvl,const char * opts __unused)6998d920d9SMark Johnston pci_amd_hostbridge_legacy_config(nvlist_t *nvl, const char *opts __unused)
70062b878fSPeter Grehan {
71b72e06b1SCorvin Köhne nvlist_t *pci_regs;
72b72e06b1SCorvin Köhne
73b72e06b1SCorvin Köhne pci_regs = create_relative_config_node(nvl, "pcireg");
74b72e06b1SCorvin Köhne if (pci_regs == NULL) {
75b72e06b1SCorvin Köhne warnx("amd_hostbridge: failed to create pciregs node");
76b72e06b1SCorvin Köhne return (-1);
77b72e06b1SCorvin Köhne }
78b72e06b1SCorvin Köhne
79b72e06b1SCorvin Köhne set_config_value_node(pci_regs, "vendor", "0x1022"); /* AMD */
80b72e06b1SCorvin Köhne set_config_value_node(pci_regs, "device", "0x7432"); /* made up */
81062b878fSPeter Grehan
82062b878fSPeter Grehan return (0);
83062b878fSPeter Grehan }
84062b878fSPeter Grehan
85*6f7d2cf8SVitaliy Gusev #ifdef BHYVE_SNAPSHOT
86*6f7d2cf8SVitaliy Gusev static int
pci_de_snapshot(struct vm_snapshot_meta * meta __unused)87*6f7d2cf8SVitaliy Gusev pci_de_snapshot(struct vm_snapshot_meta *meta __unused)
88*6f7d2cf8SVitaliy Gusev {
89*6f7d2cf8SVitaliy Gusev return (0);
90*6f7d2cf8SVitaliy Gusev }
91*6f7d2cf8SVitaliy Gusev #endif
92*6f7d2cf8SVitaliy Gusev
9337045dfaSMark Johnston static const struct pci_devemu pci_de_amd_hostbridge = {
94062b878fSPeter Grehan .pe_emu = "amd_hostbridge",
95621b5090SJohn Baldwin .pe_legacy_config = pci_amd_hostbridge_legacy_config,
96621b5090SJohn Baldwin .pe_alias = "hostbridge",
97062b878fSPeter Grehan };
98062b878fSPeter Grehan PCI_EMUL_SET(pci_de_amd_hostbridge);
99062b878fSPeter Grehan
10037045dfaSMark Johnston static const struct pci_devemu pci_de_hostbridge = {
101366f6083SPeter Grehan .pe_emu = "hostbridge",
102366f6083SPeter Grehan .pe_init = pci_hostbridge_init,
103*6f7d2cf8SVitaliy Gusev #ifdef BHYVE_SNAPSHOT
104*6f7d2cf8SVitaliy Gusev .pe_snapshot = pci_de_snapshot,
105*6f7d2cf8SVitaliy Gusev #endif
106366f6083SPeter Grehan };
107366f6083SPeter Grehan PCI_EMUL_SET(pci_de_hostbridge);
108