1 /*
2  * CDDL HEADER START
3  *
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.
7  *
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.
12  *
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]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #include <sys/types.h>
28 #include <sys/cmn_err.h>
29 #include <sys/errno.h>
30 #include <sys/systm.h>
31 #include <sys/sunddi.h>
32 #include <sys/pci_cfgspace.h>
33 #include <sys/pci.h>
34 #include <sys/pcie.h>
35 #include <vm/seg_kmem.h>
36 #include <sys/mman.h>
37 #include <sys/cpu_module.h>
38 #include "nb5000.h"
39 
40 static ddi_acc_handle_t dev_16_hdl[NB_PCI_NFUNC];
41 static ddi_acc_handle_t dev_17_hdl[NB_PCI_NFUNC];
42 static ddi_acc_handle_t dev_pci_hdl[NB_PCI_DEV];
43 
44 void
45 nb_pci_cfg_setup(dev_info_t *dip)
46 {
47 	pci_regspec_t reg;
48 	int i;
49 
50 	reg.pci_phys_hi = 16 << PCI_REG_DEV_SHIFT; /* Bus=0, Dev=16, Func=0 */
51 	reg.pci_phys_mid = 0;
52 	reg.pci_phys_low = 0;
53 	reg.pci_size_hi = 0;
54 	reg.pci_size_low = PCIE_CONF_HDR_SIZE; /* overriden in pciex */
55 
56 	for (i = 0; i < NB_PCI_NFUNC; i++) {
57 		if (ddi_prop_update_int_array(DDI_MAJOR_T_UNKNOWN, dip, "reg",
58 		    (int *)&reg, sizeof (reg)/sizeof (int)) != DDI_PROP_SUCCESS)
59 		cmn_err(CE_WARN,
60 		    "nb_pci_cfg_setup: cannot create reg property");
61 
62 		if (pci_config_setup(dip, &dev_16_hdl[i]) != DDI_SUCCESS)
63 			cmn_err(CE_WARN,
64 			    "intel_nb5000: pci_config_setup failed");
65 		reg.pci_phys_hi += 1 << PCI_REG_FUNC_SHIFT;
66 	}
67 	reg.pci_phys_hi = 17 << PCI_REG_DEV_SHIFT; /* Bus=0, Dev=17, Func=0 */
68 	for (i = 0; i < NB_PCI_NFUNC; i++) {
69 		if (ddi_prop_update_int_array(DDI_MAJOR_T_UNKNOWN, dip, "reg",
70 		    (int *)&reg, sizeof (reg)/sizeof (int)) != DDI_PROP_SUCCESS)
71 		cmn_err(CE_WARN,
72 		    "nb_pci_cfg_setup: cannot create reg property");
73 
74 		if (pci_config_setup(dip, &dev_17_hdl[i]) != DDI_SUCCESS)
75 			cmn_err(CE_WARN,
76 			    "intel_nb5000: pci_config_setup failed");
77 		reg.pci_phys_hi += 1 << PCI_REG_FUNC_SHIFT;
78 	}
79 	reg.pci_phys_hi = 0;		/* Bus=0, Dev=0, Func=0 */
80 	for (i = 0; i < NB_PCI_DEV; i++) {
81 		if (ddi_prop_update_int_array(DDI_MAJOR_T_UNKNOWN, dip, "reg",
82 		    (int *)&reg, sizeof (reg)/sizeof (int)) != DDI_PROP_SUCCESS)
83 		cmn_err(CE_WARN,
84 		    "nb_pci_cfg_setup: cannot create reg property");
85 
86 		if (pci_config_setup(dip, &dev_pci_hdl[i]) != DDI_SUCCESS)
87 			cmn_err(CE_WARN,
88 			    "intel_nb5000: pci_config_setup failed");
89 		reg.pci_phys_hi += 1 << PCI_REG_DEV_SHIFT;
90 	}
91 }
92 
93 void
94 nb_pci_cfg_free()
95 {
96 	int i;
97 
98 	for (i = 0; i < NB_PCI_NFUNC; i++) {
99 		pci_config_teardown(&dev_16_hdl[i]);
100 	}
101 	for (i = 0; i < NB_PCI_NFUNC; i++) {
102 		pci_config_teardown(&dev_17_hdl[i]);
103 	}
104 	for (i = 0; i < NB_PCI_DEV; i++)
105 		pci_config_teardown(&dev_pci_hdl[i]);
106 }
107 
108 static ddi_acc_handle_t
109 nb_get_hdl(int bus, int dev, int func)
110 {
111 	ddi_acc_handle_t hdl;
112 
113 	if (bus == 0 && dev == 16 && func < NB_PCI_NFUNC) {
114 		hdl = dev_16_hdl[func];
115 	} else if (bus == 0 && dev == 17 && func < NB_PCI_NFUNC) {
116 		hdl = dev_17_hdl[func];
117 	} else if (bus == 0 && dev < NB_PCI_DEV && func == 0) {
118 		hdl = dev_pci_hdl[dev];
119 	} else {
120 		hdl = 0;
121 	}
122 	return (hdl);
123 }
124 
125 uint8_t
126 nb_pci_getb(int bus, int dev, int func, int reg, int *interpose)
127 {
128 	ddi_acc_handle_t hdl;
129 
130 	hdl = nb_get_hdl(bus, dev, func);
131 	return (cmi_pci_getb(bus, dev, func, reg, interpose, hdl));
132 }
133 
134 uint16_t
135 nb_pci_getw(int bus, int dev, int func, int reg, int *interpose)
136 {
137 	ddi_acc_handle_t hdl;
138 
139 	hdl = nb_get_hdl(bus, dev, func);
140 	return (cmi_pci_getw(bus, dev, func, reg, interpose, hdl));
141 }
142 
143 uint32_t
144 nb_pci_getl(int bus, int dev, int func, int reg, int *interpose)
145 {
146 	ddi_acc_handle_t hdl;
147 
148 	hdl = nb_get_hdl(bus, dev, func);
149 	return (cmi_pci_getl(bus, dev, func, reg, interpose, hdl));
150 }
151 
152 void
153 nb_pci_putb(int bus, int dev, int func, int reg, uint8_t val)
154 {
155 	ddi_acc_handle_t hdl;
156 
157 	hdl = nb_get_hdl(bus, dev, func);
158 	cmi_pci_putb(bus, dev, func, reg, hdl, val);
159 }
160 
161 void
162 nb_pci_putw(int bus, int dev, int func, int reg, uint16_t val)
163 {
164 	ddi_acc_handle_t hdl;
165 
166 	hdl = nb_get_hdl(bus, dev, func);
167 	cmi_pci_putw(bus, dev, func, reg, hdl, val);
168 }
169 
170 void
171 nb_pci_putl(int bus, int dev, int func, int reg, uint32_t val)
172 {
173 	ddi_acc_handle_t hdl;
174 
175 	hdl = nb_get_hdl(bus, dev, func);
176 	cmi_pci_putl(bus, dev, func, reg, hdl, val);
177 }
178