4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
25 #include <sys/sunddi.h>
26 #include <sys/sunndi.h>
27 #include <sys/promif.h>
29 #include <sys/sysmacros.h>
30 #include <sys/pcie_impl.h>
31 #include <sys/machsystm.h>
32 #include <sys/byteorder.h>
33 #include <sys/pci_cfgacc.h>
35 #define PCI_CFG_SPACE (PCI_REG_ADDR_G(PCI_ADDR_CONFIG))
36 #define PCIE_CFG_SPACE_SIZE (PCI_CONF_HDR_SIZE << 4)
38 /* RC BDF Shift in a Phyiscal Address */
39 #define RC_PA_BDF_SHIFT 12
40 #define RC_BDF_TO_CFGADDR(bdf, offset) (((bdf) << RC_PA_BDF_SHIFT) + (offset))
43 pci_cfgacc_valid(pci_cfgacc_req_t
*req
)
47 if (IS_P2ALIGNED(req
->offset
, sz
) &&
48 (req
->offset
+ sz
- 1 < PCIE_CFG_SPACE_SIZE
) &&
49 ((sz
& 0xf) && ISP2(sz
)))
52 cmn_err(CE_WARN
, "illegal PCI request: offset = %x, size = %d",
58 * Unprotected raw reads/writes of fabric device's config space.
61 pci_cfgacc_get(dev_info_t
*dip
, uint16_t bdf
, uint16_t offset
, uint8_t size
)
67 bus_p
= PCIE_DIP2DOWNBUS(dip
);
68 ASSERT(bus_p
!= NULL
);
70 base_addr
= bus_p
->bus_cfgacc_base
;
71 base_addr
+= RC_BDF_TO_CFGADDR(bdf
, offset
);
75 val
= ldbphysio(base_addr
);
78 val
= ldhphysio(base_addr
);
81 val
= ldphysio(base_addr
);
84 val
= lddphysio(base_addr
);
87 return ((uint64_t)-1);
94 pci_cfgacc_set(dev_info_t
*dip
, uint16_t bdf
, uint16_t offset
, uint8_t size
,
100 bus_p
= PCIE_DIP2DOWNBUS(dip
);
101 ASSERT(bus_p
!= NULL
);
103 base_addr
= bus_p
->bus_cfgacc_base
;
104 base_addr
+= RC_BDF_TO_CFGADDR(bdf
, offset
);
110 stbphysio(base_addr
, val
);
113 sthphysio(base_addr
, val
);
116 stphysio(base_addr
, val
);
119 stdphysio(base_addr
, val
);
127 pci_cfgacc_acc(pci_cfgacc_req_t
*req
)
130 VAL64(req
) = (uint64_t)-1;
132 if (!pci_cfgacc_valid(req
))
136 pci_cfgacc_set(req
->rcdip
, req
->bdf
, req
->offset
,
137 req
->size
, VAL64(req
));
139 VAL64(req
) = pci_cfgacc_get(req
->rcdip
, req
->bdf
,
140 req
->offset
, req
->size
);