]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - sys/dev/vmd/vmd_bus.c
Import device-tree files from Linux 5.13
[FreeBSD/FreeBSD.git] / sys / dev / vmd / vmd_bus.c
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright 2019 Cisco Systems, Inc.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 #include <sys/cdefs.h>
30 __FBSDID("$FreeBSD$");
31
32 #include <sys/types.h>
33 #include <sys/param.h>
34 #include <sys/bus.h>
35 #include <sys/conf.h>
36 #include <sys/kernel.h>
37 #include <sys/module.h>
38 #include <sys/systm.h>
39 #include <sys/malloc.h>
40
41 #include <machine/bus.h>
42 #include <machine/resource.h>
43 #include <sys/rman.h>
44 #include <sys/taskqueue.h>
45
46 #include <sys/pciio.h>
47 #include <dev/pci/pcivar.h>
48 #include <dev/pci/pcireg.h>
49 #include <dev/pci/pci_private.h>
50 #include <dev/pci/pcib_private.h>
51 #include <dev/pci/pci_host_generic.h>
52 #include <dev/vmd/vmd.h>
53
54 #include "pcib_if.h"
55 #include "pci_if.h"
56
57 static int
58 vmd_bus_probe(device_t dev)
59 {
60         device_set_desc(dev, "VMD bus");
61
62         return (-1000);
63 }
64
65 /* PCI interface. */
66
67 static int
68 vmd_bus_attach(device_t dev)
69 {
70         struct vmd_softc *sc;
71         struct pci_devinfo *dinfo;
72         rman_res_t start, end;
73         int b, s, f;
74         int found;
75
76         sc = device_get_softc(device_get_parent(dev));
77
78         /*
79          * Start at max PCI vmd_domain and work down.  Only VMD
80          * starting bus is connect to VMD device directly.  Scan al
81          * lslots and function connected to starting bus.
82          */
83
84         b = sc->vmd_bus_start;
85
86         found = 0;
87         for (s = 0; s < PCI_SLOTMAX; s++) {
88                 for (f = 0; f < PCI_FUNCMAX; f++) {
89                         dinfo = pci_read_device(device_get_parent(dev), dev,
90                              PCI_DOMAINMAX - device_get_unit(
91                              device_get_parent(dev)), b, s, f);
92                         if (dinfo != NULL) {
93                                 found = 1;
94                                 pci_add_child(dev, dinfo);
95
96                                 start = rman_get_start(sc->vmd_regs_resource[1]);
97                                 end = rman_get_end(sc->vmd_regs_resource[1]);
98                                 resource_list_add_next(&dinfo->resources,
99                                     SYS_RES_MEMORY, start, end, end - start + 1);
100
101                                 start = rman_get_start(sc->vmd_io_resource);
102                                 end = rman_get_end(sc->vmd_io_resource);
103                                 resource_list_add_next(&dinfo->resources,
104                                     SYS_RES_IOPORT, start, end, end - start + 1);
105
106                         }
107                 }
108         }
109
110         if (found) {
111                 bus_generic_attach(dev);
112         }
113
114         return (0);
115 }
116
117 static int
118 vmd_bus_detach(device_t dev)
119 {
120         struct vmd_softc *sc;
121         struct pci_devinfo *dinfo;
122         int b, s, f;
123
124         device_delete_children(dev);
125
126         sc = device_get_softc(device_get_parent(dev));
127         b = sc->vmd_bus_start;
128
129         for (s = 0; s < PCI_SLOTMAX; s++) {
130                 for (f = 0; f < PCI_FUNCMAX; f++) {
131                         dinfo = pci_read_device(device_get_parent(dev), dev,
132                              PCI_DOMAINMAX - device_get_unit(
133                              device_get_parent(dev)), b, s, f);
134                         if (dinfo != NULL)
135                                 resource_list_free(&dinfo->resources);
136                 }
137         }
138         return (0);
139 }
140
141 static int
142 vmd_bus_adjust_resource(device_t dev, device_t child, int type,
143     struct resource *r, rman_res_t start, rman_res_t end)
144 {
145         struct resource *res = r;
146         if (type == SYS_RES_MEMORY) {
147                 /* VMD device controls this */
148                 return (0);
149         }
150
151         return (bus_generic_adjust_resource(dev, child, type, res, start, end));
152 }
153
154 static int
155 vmd_bus_release_resource(device_t dev, device_t child, int type, int rid,
156     struct resource *r)
157 {
158         if (type == SYS_RES_MEMORY) {
159                 /* VMD device controls this */
160                 return (0);
161         }
162
163         return (pci_release_resource(dev, child, type, rid, r));
164 }
165
166 static struct resource *
167 vmd_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
168     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
169 {
170         struct vmd_softc *sc;
171
172         sc = device_get_softc(device_get_parent(dev));
173
174         if (type == SYS_RES_MEMORY) {
175                 /* remap to VMD resources */
176                 if (*rid == PCIR_MEMBASE_1) {
177                         return (sc->vmd_regs_resource[1]);
178                 } else  if (*rid == PCIR_PMBASEL_1) {
179                         return (sc->vmd_regs_resource[2]);
180                 } else {
181                         return (sc->vmd_regs_resource[2]);
182                 }
183         }
184         return (pci_alloc_resource(dev, child, type, rid, start, end,
185            count, flags));
186 }
187
188 static int
189 vmd_bus_shutdown(device_t dev)
190 {
191         return (0);
192 }
193
194 static device_method_t vmd_bus_pci_methods[] = {
195         /* Device interface */
196         DEVMETHOD(device_probe,         vmd_bus_probe),
197         DEVMETHOD(device_attach,        vmd_bus_attach),
198         DEVMETHOD(device_detach,        vmd_bus_detach),
199         DEVMETHOD(device_shutdown,      vmd_bus_shutdown),
200
201         /* Bus interface */
202         DEVMETHOD(bus_alloc_resource,   vmd_bus_alloc_resource),
203         DEVMETHOD(bus_adjust_resource,  vmd_bus_adjust_resource),
204         DEVMETHOD(bus_release_resource, vmd_bus_release_resource),
205
206         /* pci interface */
207         DEVMETHOD(pci_read_config,      pci_read_config_method),
208         DEVMETHOD(pci_write_config,     pci_write_config_method),
209         DEVMETHOD(pci_alloc_devinfo,    pci_alloc_devinfo_method),
210
211         DEVMETHOD_END
212 };
213
214 static devclass_t vmd_bus_devclass;
215
216 DEFINE_CLASS_1(vmd_bus, vmd_bus_pci_driver, vmd_bus_pci_methods,
217     sizeof(struct pci_softc), pci_driver);
218
219 DRIVER_MODULE(vmd_bus, vmd, vmd_bus_pci_driver, vmd_bus_devclass, NULL, NULL);
220 MODULE_VERSION(vmd_bus, 1);