xref: /titanic_41/usr/src/cmd/devfsadm/sparc/misc_link_sparc.c (revision fd9cb95cbb2f626355a60efb9d02c5f0a33c10e6)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <regex.h>
30 #include <devfsadm.h>
31 #include <stdio.h>
32 #include <strings.h>
33 #include <stdlib.h>
34 #include <limits.h>
35 #include <sys/mkdev.h>
36 
37 static int node_name(di_minor_t minor, di_node_t node);
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 wrsm(di_minor_t minor, di_node_t node);
47 static int lom(di_minor_t minor, di_node_t node);
48 static int ntwdt_create(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$)|(^ddi_ctl:devctl$)", "wrsm",
70 	    TYPE_RE | DRV_EXACT, ILEVEL_0, wrsm,
71 	},
72 	{ "network", "ddi_net", "wrsmd",
73 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, node_name,
74 	},
75 	{ "pseudo", "ddi_pseudo", "lw8",
76 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, lom
77 	},
78 	{ "pseudo", "ddi_pseudo", "ntwdt",
79 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, ntwdt_create
80 	},
81 };
82 
83 DEVFSADM_CREATE_INIT_V0(misc_cbt);
84 
85 /* Smart Card Reader device link */
86 #define	CARDREADER_LINK		"^scmi2c[0-9]+$"
87 
88 /* Rules for removing links */
89 static devfsadm_remove_t sparc_remove_cbt[] = {
90 	{ "card-reader", CARDREADER_LINK, RM_PRE | RM_ALWAYS,
91 		ILEVEL_0, devfsadm_rm_all }
92 };
93 
94 DEVFSADM_REMOVE_INIT_V0(sparc_remove_cbt);
95 
96 
97 /*
98  * Handles minor node type "ddi_other"
99  * type=ddi_other;name=SUNW,pmc    pmc
100  * type=ddi_other;name=SUNW,mic    mic\M0
101  */
102 static int
103 ddi_other(di_minor_t minor, di_node_t node)
104 {
105 	char path[PATH_MAX + 1];
106 	char *nn = di_node_name(node);
107 	char *mn = di_minor_name(minor);
108 
109 	if (strcmp(nn, "SUNW,pmc") == 0) {
110 		(void) devfsadm_mklink("pcm", node, minor, 0);
111 	} else if (strcmp(nn, "SUNW,mic") == 0) {
112 		(void) strcpy(path, "mic");
113 		(void) strcat(path, mn);
114 		(void) devfsadm_mklink(path, node, minor, 0);
115 	}
116 
117 	return (DEVFSADM_CONTINUE);
118 }
119 
120 /*
121  * This function is called for diskette nodes
122  */
123 static int
124 diskette(di_minor_t minor, di_node_t node)
125 {
126 	char *mn = di_minor_name(minor);
127 	if (strcmp(mn, "c") == 0) {
128 		(void) devfsadm_mklink("diskette", node, minor, 0);
129 		(void) devfsadm_mklink("diskette0", node, minor, 0);
130 
131 	} else if (strcmp(mn, "c,raw") == 0) {
132 		(void) devfsadm_mklink("rdiskette", node, minor, 0);
133 		(void) devfsadm_mklink("rdiskette0", node, minor, 0);
134 
135 	}
136 	return (DEVFSADM_CONTINUE);
137 }
138 
139 /*
140  * Handles links of the form:
141  * type=ddi_pseudo;name=xyz  \D
142  */
143 static int
144 node_name(di_minor_t minor, di_node_t node)
145 {
146 	(void) devfsadm_mklink(di_node_name(node), node, minor, 0);
147 	return (DEVFSADM_CONTINUE);
148 }
149 
150 /*
151  * Handles links of the form:
152  * type=ddi_printer;name=ecpp  ecpp\N0
153  */
154 static int
155 ecpp_create(di_minor_t minor, di_node_t node)
156 {
157 	char *buf;
158 	char path[PATH_MAX + 1];
159 	devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
160 
161 	if (strcmp(di_driver_name(node), "ecpp") != 0) {
162 		return (DEVFSADM_CONTINUE);
163 	}
164 
165 	if ((buf = di_devfs_path(node)) == NULL) {
166 		return (DEVFSADM_CONTINUE);
167 	}
168 
169 	(void) snprintf(path, sizeof (path), "%s:%s",
170 	    buf, di_minor_name(minor));
171 
172 	di_devfs_path_free(buf);
173 
174 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
175 		return (DEVFSADM_CONTINUE);
176 	}
177 
178 	(void) snprintf(path, sizeof (path), "ecpp%s", buf);
179 	free(buf);
180 
181 	(void) devfsadm_mklink(path, node, minor, 0);
182 	return (DEVFSADM_CONTINUE);
183 }
184 
185 /* Rules for memory controller */
186 static devfsadm_enumerate_t mc_rules[1] =
187 	{"^mc$/^mc([0-9]+)$", 1, MATCH_ALL};
188 
189 
190 static int
191 mc_node(di_minor_t minor, di_node_t node)
192 {
193 	char path[PATH_MAX], l_path[PATH_MAX], *buf, *devfspath;
194 	char *minor_nm;
195 
196 	minor_nm = di_minor_name(minor);
197 
198 	if (minor_nm == NULL) {
199 		return (DEVFSADM_CONTINUE);
200 	}
201 
202 	devfspath = di_devfs_path(node);
203 
204 	(void) strcpy(path, devfspath);
205 	(void) strcat(path, ":");
206 	(void) strcat(path, minor_nm);
207 	di_devfs_path_free(devfspath);
208 
209 	/* build the physical path from the components */
210 	if (devfsadm_enumerate_int(path, 0, &buf, mc_rules, 1)) {
211 		return (DEVFSADM_CONTINUE);
212 	}
213 
214 	(void) strcpy(l_path, "mc/mc");
215 	(void) strcat(l_path, buf);
216 
217 	free(buf);
218 
219 	(void) devfsadm_mklink(l_path, node, minor, 0);
220 	return (DEVFSADM_CONTINUE);
221 }
222 
223 
224 /*
225  * This function is called for Smartcard card reader nodes
226  * Handles minor node type "ddi_smartcard_reader"
227  * type=ddi_smartcard_reader;name=card-reader   scmi2c\N0
228  * Calls enumerate to assign logical card-reader id and then
229  * devfsadm_mklink to make the link.
230  */
231 static int
232 ddi_cardreader(di_minor_t minor, di_node_t node)
233 {
234 	char p_path[PATH_MAX +1], l_path[PATH_MAX +1];
235 	char *buf;
236 	char *ptr;
237 	char *nn, *mn;
238 
239 	devfsadm_enumerate_t rules[1] = {"^scmi2c([0-9]+)$", 1, MATCH_ALL};
240 
241 	nn = di_node_name(node);
242 	if (strcmp(nn, "card-reader")) {
243 		return (DEVFSADM_CONTINUE);
244 	}
245 
246 	if (NULL == (ptr = di_devfs_path(node))) {
247 		return (DEVFSADM_CONTINUE);
248 	}
249 
250 	(void) strcpy(p_path, ptr);
251 	(void) strcat(p_path, ":");
252 
253 	mn = di_minor_name(minor);
254 
255 	(void) strcat(p_path, mn);
256 	di_devfs_path_free(ptr);
257 
258 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
259 		return (DEVFSADM_CONTINUE);
260 	}
261 	(void) snprintf(l_path, sizeof (l_path), "scmi2c%s", buf);
262 	free(buf);
263 	(void) devfsadm_mklink(l_path, node, minor, 0);
264 
265 	return (DEVFSADM_CONTINUE);
266 }
267 
268 
269 
270 
271 
272 
273 
274 
275 /*
276  * Starcat sbbc node.  We only really care about generating a /dev
277  * link for the lone sbbc on the SC (as opposed to the potentially
278  * numerous sbbcs on the domain), so only operate on instance 0.
279  */
280 static int
281 starcat_sbbc_node(di_minor_t minor, di_node_t node)
282 {
283 	char *mn;
284 
285 	if (di_instance(node) == 0) {
286 		mn = di_minor_name(minor);
287 		(void) devfsadm_mklink(mn, node, minor, 0);
288 	}
289 	return (DEVFSADM_CONTINUE);
290 
291 }
292 
293 int
294 wrsm(di_minor_t minor, di_node_t node)
295 {
296 	const char *node_name = di_node_name(node);
297 	const char *minor_name = di_minor_name(minor);
298 	char path[PATH_MAX + 1];
299 
300 	if (minor_name == NULL || node_name == NULL) {
301 		return (DEVFSADM_CONTINUE);
302 	}
303 	if (strcmp(minor_name, "admin") == 0) {
304 		/* admin pseudo device */
305 		(void) snprintf(path, sizeof (path), "%s%s", node_name,
306 		    minor_name);
307 	} else if (strcmp(minor_name, "ctrl") == 0) {
308 		/* controller pseudo device */
309 		dev_t dev = di_minor_devt(minor);
310 		minor_t dev_minor = minor(dev);
311 		(void) snprintf(path, sizeof (path), "%s%u", node_name,
312 		    (uint_t)dev_minor);
313 	} else {
314 		/*
315 		 * For hardware devices, the devlink must be
316 		 * /dev/<node_name><portid>. devpath is of the format
317 		 * ".../<node_name>@<portid>,0". Need to extract the
318 		 * <portid> for use in bulding devlink.
319 		 */
320 		char devpath[PATH_MAX + 1];
321 		char *devfs_path;
322 		int i;
323 
324 		devfs_path = di_devfs_path(node);
325 		if (devfs_path == NULL) {
326 			return (DEVFSADM_CONTINUE);
327 		}
328 		(void) strcpy(devpath, devfs_path);
329 		di_devfs_path_free(devfs_path);
330 
331 		for (i = strlen(devpath); devpath[i] != '@' && i > 0; i--) {
332 			if (devpath[i] == ',') {
333 				devpath[i] = 0;
334 			}
335 		}
336 		if (i == 0) {
337 			return (DEVFSADM_CONTINUE);
338 		}
339 		(void) snprintf(path, sizeof (path), "wci%s", &devpath[i+1]);
340 	}
341 	(void) devfsadm_mklink(path, node, minor, 0);
342 
343 	return (DEVFSADM_CONTINUE);
344 }
345 
346 /*
347  * Creates /dev/lom nodes for Platform Specific lom driver
348  */
349 static int
350 lom(di_minor_t minor, di_node_t node)
351 {
352 	(void) devfsadm_mklink("lom", node, minor, 0);
353 	return (DEVFSADM_CONTINUE);
354 }
355 
356 /*
357  * Creates /dev/ntwdt nodes for Platform Specific ntwdt driver
358  */
359 static int
360 ntwdt_create(di_minor_t minor, di_node_t node)
361 {
362 	(void) devfsadm_mklink("ntwdt", node, minor, 0);
363 	return (DEVFSADM_CONTINUE);
364 }
365