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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26
27 /*
28 * CPU nexus driver
29 */
30
31 #include <sys/types.h>
32 #include <sys/param.h>
33 #include <sys/conf.h>
34 #include <sys/devops.h>
35 #include <sys/modctl.h>
36 #include <sys/cmn_err.h>
37 #include <sys/ddi.h>
38 #include <sys/sunddi.h>
39 #include <sys/sunndi.h>
40
41 static int cpunex_attach(dev_info_t *, ddi_attach_cmd_t);
42 static int cpunex_detach(dev_info_t *, ddi_detach_cmd_t);
43 static int cpunex_bus_ctl(dev_info_t *, dev_info_t *, ddi_ctl_enum_t,
44 void *, void *);
45
46 static struct bus_ops cpunex_bus_ops = {
47 BUSO_REV,
48 nullbusmap,
49 NULL,
50 NULL,
51 NULL,
52 i_ddi_map_fault,
53 ddi_no_dma_map,
54 ddi_no_dma_allochdl,
55 ddi_no_dma_freehdl,
56 ddi_no_dma_bindhdl,
57 ddi_no_dma_unbindhdl,
58 ddi_no_dma_flush,
59 ddi_no_dma_win,
60 ddi_no_dma_mctl,
61 cpunex_bus_ctl,
62 ddi_bus_prop_op,
63 };
64
65 static struct dev_ops cpunex_ops = {
66 DEVO_REV,
67 0,
68 ddi_no_info,
69 nulldev,
70 nulldev,
71 cpunex_attach,
72 cpunex_detach,
73 nodev,
74 NULL,
75 &cpunex_bus_ops,
76 NULL,
77 ddi_quiesce_not_needed, /* quiesce */
78 };
79
80 static struct modldrv modldrv = {
81 &mod_driverops,
82 "cpu nexus driver",
83 &cpunex_ops
84 };
85
86 static struct modlinkage modlinkage = {
87 MODREV_1,
88 &modldrv,
89 NULL
90 };
91
92 /*
93 * cpunex_bus_ctl()
94 * This routine implements nexus bus ctl operations. Of importance are
95 * DDI_CTLOPS_REPORTDEV, DDI_CTLOPS_INITCHILD, DDI_CTLOPS_UNINITCHILD
96 * and DDI_CTLOPS_POWER. For DDI_CTLOPS_INITCHILD, it tries to lookup
97 * reg property on the child node and builds and sets the name.
98 */
99 static int
cpunex_bus_ctl(dev_info_t * dip,dev_info_t * rdip,ddi_ctl_enum_t op,void * arg,void * result)100 cpunex_bus_ctl(dev_info_t *dip, dev_info_t *rdip, ddi_ctl_enum_t op, void *arg,
101 void *result)
102 {
103 switch (op) {
104 case DDI_CTLOPS_REPORTDEV: {
105 dev_info_t *pdip = ddi_get_parent(rdip);
106 cmn_err(CE_CONT, "?%s%d at %s%d",
107 ddi_node_name(rdip), ddi_get_instance(rdip),
108 ddi_node_name(pdip), ddi_get_instance(pdip));
109 return (DDI_SUCCESS);
110 }
111
112 case DDI_CTLOPS_INITCHILD: {
113 dev_info_t *cdip = (dev_info_t *)arg;
114 int i;
115 char caddr[MAXNAMELEN];
116
117 i = ddi_prop_get_int(DDI_DEV_T_ANY, cdip,
118 DDI_PROP_DONTPASS, "reg", -1);
119
120 if (i == -1) {
121 cmn_err(CE_NOTE, "!%s(%d): \"reg\" property "
122 "not found", ddi_node_name(cdip),
123 ddi_get_instance(cdip));
124 return (DDI_NOT_WELL_FORMED);
125 }
126
127 (void) sprintf(caddr, "%d", i);
128 ddi_set_name_addr(cdip, caddr);
129
130 return (DDI_SUCCESS);
131 }
132
133 case DDI_CTLOPS_UNINITCHILD: {
134 ddi_prop_remove_all((dev_info_t *)arg);
135 ddi_set_name_addr((dev_info_t *)arg, NULL);
136 return (DDI_SUCCESS);
137 }
138
139 default: {
140 return (ddi_ctlops(dip, rdip, op, arg, result));
141 }
142 }
143 }
144
145 /*ARGSUSED*/
146 static int
cpunex_attach(dev_info_t * dip,ddi_attach_cmd_t cmd)147 cpunex_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
148 {
149 switch (cmd) {
150 case DDI_ATTACH:
151 case DDI_RESUME:
152 break;
153 default:
154 return (DDI_FAILURE);
155 }
156
157 return (DDI_SUCCESS);
158 }
159
160 /*ARGSUSED*/
161 static int
cpunex_detach(dev_info_t * dip,ddi_detach_cmd_t cmd)162 cpunex_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
163 {
164 switch (cmd) {
165 case DDI_DETACH:
166 case DDI_SUSPEND:
167 break;
168 default:
169 return (DDI_FAILURE);
170 }
171
172 return (DDI_SUCCESS);
173 }
174
175 int
_init(void)176 _init(void)
177 {
178 int error;
179
180 error = mod_install(&modlinkage);
181 return (error);
182 }
183
184 int
_fini(void)185 _fini(void)
186 {
187 int error;
188
189 error = mod_remove(&modlinkage);
190 return (error);
191 }
192
193 int
_info(struct modinfo * modinfop)194 _info(struct modinfo *modinfop)
195 {
196 return (mod_info(&modlinkage, modinfop));
197 }
198