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 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <regex.h>
29 #include <devfsadm.h>
30 #include <stdio.h>
31 #include <strings.h>
32 #include <stdlib.h>
33 #include <limits.h>
34 #include <sys/mkdev.h>
35 #include <bsm/devalloc.h>
36 
37 extern int system_labeled;
38 
39 
40 static int ddi_other(di_minor_t minor, di_node_t node);
41 static int diskette(di_minor_t minor, di_node_t node);
42 static int ecpp_create(di_minor_t minor, di_node_t node);
43 static int mc_node(di_minor_t minor, di_node_t node);
44 static int ddi_cardreader(di_minor_t minor, di_node_t node);
45 static int starcat_sbbc_node(di_minor_t minor, di_node_t node);
46 static int lom(di_minor_t minor, di_node_t node);
47 static int ntwdt_create(di_minor_t minor, di_node_t node);
48 static int bmc(di_minor_t minor, di_node_t node);
49 
50 static devfsadm_create_t misc_cbt[] = {
51 	{ "other", "ddi_other", NULL,
52 	    TYPE_EXACT, ILEVEL_0, ddi_other
53 	},
54 	{ "memory-controller", "ddi_mem_ctrl", NULL,
55 	    TYPE_EXACT, ILEVEL_0, mc_node
56 	},
57 	{ "pseudo", "ddi_pseudo", "sbbc",
58 	    TYPE_EXACT | DRV_EXACT, ILEVEL_1, starcat_sbbc_node
59 	},
60 	{ "disk",  "ddi_block:diskette", NULL,
61 	    TYPE_EXACT, ILEVEL_1, diskette
62 	},
63 	{ "printer",  "ddi_printer", NULL,
64 	    TYPE_EXACT, ILEVEL_1, ecpp_create
65 	},
66 	{ "card-reader", "ddi_smartcard_reader", NULL,
67 		TYPE_EXACT, ILEVEL_0, ddi_cardreader
68 	},
69 	{ "pseudo", "ddi_pseudo", "lw8",
70 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, lom
71 	},
72 	{ "pseudo", "ddi_pseudo", "ntwdt",
73 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, ntwdt_create
74 	},
75 	{ "pseudo", "ddi_pseudo", "bmc",
76 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, bmc
77 	}
78 };
79 
80 DEVFSADM_CREATE_INIT_V0(misc_cbt);
81 
82 /* Smart Card Reader device link */
83 #define	CARDREADER_LINK		"^scmi2c[0-9]+$"
84 
85 /* Rules for removing links */
86 static devfsadm_remove_t sparc_remove_cbt[] = {
87 	{ "card-reader", CARDREADER_LINK, RM_PRE | RM_ALWAYS,
88 		ILEVEL_0, devfsadm_rm_all }
89 };
90 
91 DEVFSADM_REMOVE_INIT_V0(sparc_remove_cbt);
92 
93 
94 /*
95  * Handles minor node type "ddi_other"
96  * type=ddi_other;name=SUNW,pmc    pmc
97  * type=ddi_other;name=SUNW,mic    mic\M0
98  */
99 static int
100 ddi_other(di_minor_t minor, di_node_t node)
101 {
102 	char path[PATH_MAX + 1];
103 	char *nn = di_node_name(node);
104 	char *mn = di_minor_name(minor);
105 
106 	if (strcmp(nn, "SUNW,pmc") == 0) {
107 		(void) devfsadm_mklink("pcm", node, minor, 0);
108 	} else if (strcmp(nn, "SUNW,mic") == 0) {
109 		(void) strcpy(path, "mic");
110 		(void) strcat(path, mn);
111 		(void) devfsadm_mklink(path, node, minor, 0);
112 	}
113 
114 	return (DEVFSADM_CONTINUE);
115 }
116 
117 /*
118  * This function is called for diskette nodes
119  */
120 static int
121 diskette(di_minor_t minor, di_node_t node)
122 {
123 	int	flags = 0;
124 	char	*mn = di_minor_name(minor);
125 
126 	if (system_labeled)
127 		flags = DA_ADD|DA_FLOPPY;
128 
129 	if (strcmp(mn, "c") == 0) {
130 		(void) devfsadm_mklink("diskette", node, minor, flags);
131 		(void) devfsadm_mklink("diskette0", node, minor, flags);
132 
133 	} else if (strcmp(mn, "c,raw") == 0) {
134 		(void) devfsadm_mklink("rdiskette", node, minor, flags);
135 		(void) devfsadm_mklink("rdiskette0", node, minor, flags);
136 
137 	}
138 	return (DEVFSADM_CONTINUE);
139 }
140 
141 /*
142  * Handles links of the form:
143  * type=ddi_printer;name=ecpp  ecpp\N0
144  */
145 static int
146 ecpp_create(di_minor_t minor, di_node_t node)
147 {
148 	char *buf;
149 	char path[PATH_MAX + 1];
150 	devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
151 
152 	if (strcmp(di_driver_name(node), "ecpp") != 0) {
153 		return (DEVFSADM_CONTINUE);
154 	}
155 
156 	if ((buf = di_devfs_path(node)) == NULL) {
157 		return (DEVFSADM_CONTINUE);
158 	}
159 
160 	(void) snprintf(path, sizeof (path), "%s:%s",
161 	    buf, di_minor_name(minor));
162 
163 	di_devfs_path_free(buf);
164 
165 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
166 		return (DEVFSADM_CONTINUE);
167 	}
168 
169 	(void) snprintf(path, sizeof (path), "ecpp%s", buf);
170 	free(buf);
171 
172 	(void) devfsadm_mklink(path, node, minor, 0);
173 	return (DEVFSADM_CONTINUE);
174 }
175 
176 /* Rules for memory controller */
177 static devfsadm_enumerate_t mc_rules[1] =
178 	{"^mc$/^mc([0-9]+)$", 1, MATCH_ALL};
179 
180 
181 static int
182 mc_node(di_minor_t minor, di_node_t node)
183 {
184 	char path[PATH_MAX], l_path[PATH_MAX], *buf, *devfspath;
185 	char *minor_nm;
186 
187 	minor_nm = di_minor_name(minor);
188 
189 	if (minor_nm == NULL) {
190 		return (DEVFSADM_CONTINUE);
191 	}
192 
193 	devfspath = di_devfs_path(node);
194 
195 	(void) strcpy(path, devfspath);
196 	(void) strcat(path, ":");
197 	(void) strcat(path, minor_nm);
198 	di_devfs_path_free(devfspath);
199 
200 	/* build the physical path from the components */
201 	if (devfsadm_enumerate_int(path, 0, &buf, mc_rules, 1)) {
202 		return (DEVFSADM_CONTINUE);
203 	}
204 
205 	(void) strcpy(l_path, "mc/mc");
206 	(void) strcat(l_path, buf);
207 
208 	free(buf);
209 
210 	(void) devfsadm_mklink(l_path, node, minor, 0);
211 	return (DEVFSADM_CONTINUE);
212 }
213 
214 
215 /*
216  * This function is called for Smartcard card reader nodes
217  * Handles minor node type "ddi_smartcard_reader"
218  * type=ddi_smartcard_reader;name=card-reader   scmi2c\N0
219  * Calls enumerate to assign logical card-reader id and then
220  * devfsadm_mklink to make the link.
221  */
222 static int
223 ddi_cardreader(di_minor_t minor, di_node_t node)
224 {
225 	char p_path[PATH_MAX +1], l_path[PATH_MAX +1];
226 	char *buf;
227 	char *ptr;
228 	char *nn, *mn;
229 
230 	devfsadm_enumerate_t rules[1] = {"^scmi2c([0-9]+)$", 1, MATCH_ALL};
231 
232 	nn = di_node_name(node);
233 	if (strcmp(nn, "card-reader")) {
234 		return (DEVFSADM_CONTINUE);
235 	}
236 
237 	if (NULL == (ptr = di_devfs_path(node))) {
238 		return (DEVFSADM_CONTINUE);
239 	}
240 
241 	(void) strcpy(p_path, ptr);
242 	(void) strcat(p_path, ":");
243 
244 	mn = di_minor_name(minor);
245 
246 	(void) strcat(p_path, mn);
247 	di_devfs_path_free(ptr);
248 
249 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
250 		return (DEVFSADM_CONTINUE);
251 	}
252 	(void) snprintf(l_path, sizeof (l_path), "scmi2c%s", buf);
253 	free(buf);
254 	(void) devfsadm_mklink(l_path, node, minor, 0);
255 
256 	return (DEVFSADM_CONTINUE);
257 }
258 
259 
260 
261 
262 
263 
264 
265 
266 /*
267  * Starcat sbbc node.  We only really care about generating a /dev
268  * link for the lone sbbc on the SC (as opposed to the potentially
269  * numerous sbbcs on the domain), so only operate on instance 0.
270  */
271 static int
272 starcat_sbbc_node(di_minor_t minor, di_node_t node)
273 {
274 	char *mn;
275 
276 	if (di_instance(node) == 0) {
277 		mn = di_minor_name(minor);
278 		(void) devfsadm_mklink(mn, node, minor, 0);
279 	}
280 	return (DEVFSADM_CONTINUE);
281 
282 }
283 
284 /*
285  * Creates /dev/lom nodes for Platform Specific lom driver
286  */
287 static int
288 lom(di_minor_t minor, di_node_t node)
289 {
290 	(void) devfsadm_mklink("lom", node, minor, 0);
291 	return (DEVFSADM_CONTINUE);
292 }
293 
294 /*
295  * Creates /dev/ntwdt nodes for Platform Specific ntwdt driver
296  */
297 static int
298 ntwdt_create(di_minor_t minor, di_node_t node)
299 {
300 	(void) devfsadm_mklink("ntwdt", node, minor, 0);
301 	return (DEVFSADM_CONTINUE);
302 }
303 
304 /*
305  * Creates /dev/bmc node.
306  */
307 static int
308 bmc(di_minor_t minor, di_node_t node)
309 {
310 	(void) devfsadm_mklink("bmc", node, minor, 0);
311 	return (DEVFSADM_CONTINUE);
312 }
313