8354 sync regcomp(3C) with upstream (fix make catalog)
[unleashed/tickless.git] / usr / src / uts / sun4u / io / pciex / pci_cfgacc_4u.c
blob146aaf5757a05bc4c465f0fc1582eca51094e785
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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>
28 #include <sys/pci.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))
42 static boolean_t
43 pci_cfgacc_valid(pci_cfgacc_req_t *req)
45 int sz = req->size;
47 if (IS_P2ALIGNED(req->offset, sz) &&
48 (req->offset + sz - 1 < PCIE_CFG_SPACE_SIZE) &&
49 ((sz & 0xf) && ISP2(sz)))
50 return (B_TRUE);
52 cmn_err(CE_WARN, "illegal PCI request: offset = %x, size = %d",
53 req->offset, sz);
54 return (B_FALSE);
58 * Unprotected raw reads/writes of fabric device's config space.
60 static uint64_t
61 pci_cfgacc_get(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size)
63 pcie_bus_t *bus_p;
64 uint64_t base_addr;
65 uint64_t val;
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);
73 switch (size) {
74 case 1:
75 val = ldbphysio(base_addr);
76 break;
77 case 2:
78 val = ldhphysio(base_addr);
79 break;
80 case 4:
81 val = ldphysio(base_addr);
82 break;
83 case 8:
84 val = lddphysio(base_addr);
85 break;
86 default:
87 return ((uint64_t)-1);
90 return (LE_64(val));
93 static void
94 pci_cfgacc_set(dev_info_t *dip, uint16_t bdf, uint16_t offset, uint8_t size,
95 uint64_t val)
97 pcie_bus_t *bus_p;
98 uint64_t base_addr;
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);
106 val = LE_64(val);
108 switch (size) {
109 case 1:
110 stbphysio(base_addr, val);
111 break;
112 case 2:
113 sthphysio(base_addr, val);
114 break;
115 case 4:
116 stphysio(base_addr, val);
117 break;
118 case 8:
119 stdphysio(base_addr, val);
120 break;
121 default:
122 break;
126 void
127 pci_cfgacc_acc(pci_cfgacc_req_t *req)
129 if (!req->write)
130 VAL64(req) = (uint64_t)-1;
132 if (!pci_cfgacc_valid(req))
133 return;
135 if (req->write) {
136 pci_cfgacc_set(req->rcdip, req->bdf, req->offset,
137 req->size, VAL64(req));
138 } else {
139 VAL64(req) = pci_cfgacc_get(req->rcdip, req->bdf,
140 req->offset, req->size);