1 /*
2 * Based on Linux drivers/pci/ecam.c
3 *
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License version 2 as
6 * published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16
17 #include <xen/pci.h>
18 #include <xen/sched.h>
19
20 /*
21 * Function to implement the pci_ops->map_bus method.
22 */
pci_ecam_map_bus(struct pci_host_bridge * bridge,pci_sbdf_t sbdf,uint32_t where)23 void __iomem *pci_ecam_map_bus(struct pci_host_bridge *bridge,
24 pci_sbdf_t sbdf, uint32_t where)
25 {
26 const struct pci_config_window *cfg = bridge->cfg;
27 const struct pci_ecam_ops *ops =
28 container_of(bridge->ops, const struct pci_ecam_ops, pci_ops);
29 unsigned int devfn_shift = ops->bus_shift - 8;
30 void __iomem *base;
31 unsigned int busn = sbdf.bus;
32
33 if ( busn < cfg->busn_start || busn > cfg->busn_end )
34 return NULL;
35
36 busn -= cfg->busn_start;
37 base = cfg->win + (busn << ops->bus_shift);
38
39 return base + (sbdf.devfn << devfn_shift) + where;
40 }
41
pci_ecam_need_p2m_hwdom_mapping(struct domain * d,struct pci_host_bridge * bridge,uint64_t addr)42 bool __init pci_ecam_need_p2m_hwdom_mapping(struct domain *d,
43 struct pci_host_bridge *bridge,
44 uint64_t addr)
45 {
46 struct pci_config_window *cfg = bridge->cfg;
47
48 /*
49 * We do not want ECAM address space to be mapped in Domain-0's p2m,
50 * so we can trap access to it.
51 */
52 return cfg->phys_addr != addr;
53 }
54
55 /* ECAM ops */
56 const struct pci_ecam_ops pci_generic_ecam_ops = {
57 .bus_shift = 20,
58 .pci_ops = {
59 .map_bus = pci_ecam_map_bus,
60 .read = pci_generic_config_read,
61 .write = pci_generic_config_write,
62 .need_p2m_hwdom_mapping = pci_ecam_need_p2m_hwdom_mapping,
63 }
64 };
65
66 /*
67 * Local variables:
68 * mode: C
69 * c-file-style: "BSD"
70 * c-basic-offset: 4
71 * tab-width: 4
72 * indent-tabs-mode: nil
73 * End:
74 */
75