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 (c) 1998, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2011 Nexenta Systems, Inc. All rights reserved.
24 * Copyright (c) 2012, Joyent, Inc. All rights reserved.
25 */
26
27 #include <regex.h>
28 #include <devfsadm.h>
29 #include <stdio.h>
30 #include <strings.h>
31 #include <stdlib.h>
32 #include <limits.h>
33 #include <sys/zone.h>
34 #include <sys/zcons.h>
35 #include <sys/cpuid_drv.h>
36
37 static int display(di_minor_t minor, di_node_t node);
38 static int parallel(di_minor_t minor, di_node_t node);
39 static int node_slash_minor(di_minor_t minor, di_node_t node);
40 static int driver_minor(di_minor_t minor, di_node_t node);
41 static int node_name(di_minor_t minor, di_node_t node);
42 static int minor_name(di_minor_t minor, di_node_t node);
43 static int wifi_minor_name(di_minor_t minor, di_node_t node);
44 static int conskbd(di_minor_t minor, di_node_t node);
45 static int consms(di_minor_t minor, di_node_t node);
46 static int power_button(di_minor_t minor, di_node_t node);
47 static int fc_port(di_minor_t minor, di_node_t node);
48 static int printer_create(di_minor_t minor, di_node_t node);
49 static int se_hdlc_create(di_minor_t minor, di_node_t node);
50 static int ppm(di_minor_t minor, di_node_t node);
51 static int gpio(di_minor_t minor, di_node_t node);
52 static int av_create(di_minor_t minor, di_node_t node);
53 static int tsalarm_create(di_minor_t minor, di_node_t node);
54 static int ntwdt_create(di_minor_t minor, di_node_t node);
55 static int zcons_create(di_minor_t minor, di_node_t node);
56 static int cpuid(di_minor_t minor, di_node_t node);
57 static int glvc(di_minor_t minor, di_node_t node);
58 static int ses_callback(di_minor_t minor, di_node_t node);
59 static int kmdrv_create(di_minor_t minor, di_node_t node);
60
61 static devfsadm_create_t misc_cbt[] = {
62 { "pseudo", "ddi_pseudo", "(^sad$)",
63 TYPE_EXACT | DRV_RE, ILEVEL_0, node_slash_minor
64 },
65 { "pseudo", "ddi_pseudo", "zsh",
66 TYPE_EXACT | DRV_EXACT, ILEVEL_0, driver_minor
67 },
68 { "network", "ddi_network", NULL,
69 TYPE_EXACT, ILEVEL_0, minor_name
70 },
71 { "wifi", "ddi_network:wifi", NULL,
72 TYPE_EXACT, ILEVEL_0, wifi_minor_name
73 },
74 { "display", "ddi_display", NULL,
75 TYPE_EXACT, ILEVEL_0, display
76 },
77 { "parallel", "ddi_parallel", NULL,
78 TYPE_EXACT, ILEVEL_0, parallel
79 },
80 { "enclosure", DDI_NT_SCSI_ENCLOSURE, NULL,
81 TYPE_EXACT, ILEVEL_0, ses_callback
82 },
83 { "pseudo", "ddi_pseudo", "(^winlock$)|(^pm$)",
84 TYPE_EXACT | DRV_RE, ILEVEL_0, node_name
85 },
86 { "pseudo", "ddi_pseudo", "conskbd",
87 TYPE_EXACT | DRV_EXACT, ILEVEL_0, conskbd
88 },
89 { "pseudo", "ddi_pseudo", "consms",
90 TYPE_EXACT | DRV_EXACT, ILEVEL_0, consms
91 },
92 { "pseudo", "ddi_pseudo", "rsm",
93 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
94 },
95 { "pseudo", "ddi_pseudo",
96 "(^lockstat$)|(^SUNW,rtvc$)|(^vol$)|(^log$)|(^sy$)|"
97 "(^ksyms$)|(^clone$)|(^tl$)|(^tnf$)|(^kstat$)|(^mdesc$)|(^eeprom$)|"
98 "(^ptsl$)|(^mm$)|(^wc$)|(^dump$)|(^cn$)|(^svvslo$)|(^ptm$)|"
99 "(^ptc$)|(^openeepr$)|(^poll$)|(^sysmsg$)|(^random$)|(^trapstat$)|"
100 "(^cryptoadm$)|(^crypto$)|(^pool$)|(^poolctl$)|(^bl$)|(^kmdb$)|"
101 "(^sysevent$)|(^kssl$)|(^physmem$)",
102 TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
103 },
104 { "pseudo", "ddi_pseudo",
105 "(^ip$)|(^tcp$)|(^udp$)|(^icmp$)|"
106 "(^ip6$)|(^tcp6$)|(^udp6$)|(^icmp6$)|"
107 "(^rts$)|(^arp$)|(^ipsecah$)|(^ipsecesp$)|(^keysock$)|(^spdsock$)|"
108 "(^nca$)|(^rds$)|(^sdp$)|(^ipnet$)|(^dlpistub$)|(^bpf$)",
109 TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
110 },
111 { "pseudo", "ddi_pseudo", "ipd",
112 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
113 },
114 { "pseudo", "ddi_pseudo",
115 "(^ipf$)|(^ipnat$)|(^ipstate$)|(^ipauth$)|"
116 "(^ipsync$)|(^ipscan$)|(^iplookup$)",
117 TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
118 },
119 { "pseudo", "ddi_pseudo", "dld",
120 TYPE_EXACT | DRV_EXACT, ILEVEL_0, node_name
121 },
122 { "pseudo", "ddi_pseudo",
123 "(^kdmouse$)|(^rootprop$)",
124 TYPE_EXACT | DRV_RE, ILEVEL_0, node_name
125 },
126 { "pseudo", "ddi_pseudo", "tod",
127 TYPE_EXACT | DRV_EXACT, ILEVEL_0, node_name
128 },
129 { "pseudo", "ddi_pseudo", "envctrl(two)?",
130 TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name,
131 },
132 { "pseudo", "ddi_pseudo", "fcode",
133 TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
134 },
135 { "power_button", "ddi_power_button", NULL,
136 TYPE_EXACT, ILEVEL_0, power_button,
137 },
138 { "FC port", "ddi_ctl:devctl", "fp",
139 TYPE_EXACT | DRV_EXACT, ILEVEL_0, fc_port
140 },
141 { "printer", "ddi_printer", NULL,
142 TYPE_EXACT, ILEVEL_0, printer_create
143 },
144 { "pseudo", "ddi_pseudo", "se",
145 TYPE_EXACT | DRV_EXACT, ILEVEL_0, se_hdlc_create
146 },
147 { "ppm", "ddi_ppm", NULL,
148 TYPE_EXACT, ILEVEL_0, ppm
149 },
150 { "pseudo", "ddi_pseudo", "gpio_87317",
151 TYPE_EXACT | DRV_EXACT, ILEVEL_0, gpio
152 },
153 { "pseudo", "ddi_pseudo", "sckmdrv",
154 TYPE_EXACT | DRV_RE, ILEVEL_0, kmdrv_create,
155 },
156 { "pseudo", "ddi_pseudo", "oplkmdrv",
157 TYPE_EXACT | DRV_RE, ILEVEL_0, kmdrv_create,
158 },
159 { "av", "^ddi_av:(isoch|async)$", NULL,
160 TYPE_RE, ILEVEL_0, av_create,
161 },
162 { "pseudo", "ddi_pseudo", "tsalarm",
163 TYPE_EXACT | DRV_RE, ILEVEL_0, tsalarm_create,
164 },
165 { "pseudo", "ddi_pseudo", "ntwdt",
166 TYPE_EXACT | DRV_RE, ILEVEL_0, ntwdt_create,
167 },
168 { "pseudo", "ddi_pseudo", "daplt",
169 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
170 },
171 { "pseudo", "ddi_pseudo", "zcons",
172 TYPE_EXACT | DRV_EXACT, ILEVEL_0, zcons_create,
173 },
174 { "pseudo", "ddi_pseudo", CPUID_DRIVER_NAME,
175 TYPE_EXACT | DRV_EXACT, ILEVEL_0, cpuid,
176 },
177 { "pseudo", "ddi_pseudo", "glvc",
178 TYPE_EXACT | DRV_EXACT, ILEVEL_0, glvc,
179 },
180 { "pseudo", "ddi_pseudo", "dm2s",
181 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name,
182 },
183 { "pseudo", "ddi_pseudo", "nsmb",
184 TYPE_EXACT | DRV_EXACT, ILEVEL_1, minor_name,
185 },
186 { "pseudo", "ddi_pseudo", "mem_cache",
187 TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name,
188 },
189 { "pseudo", "ddi_pseudo", "fm",
190 TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name,
191 },
192 { "pseudo", "ddi_pseudo", "smbsrv",
193 TYPE_EXACT | DRV_EXACT, ILEVEL_1, minor_name,
194 },
195 { "pseudo", "ddi_pseudo", "tpm",
196 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
197 },
198 };
199
200 DEVFSADM_CREATE_INIT_V0(misc_cbt);
201
202 static devfsadm_remove_t misc_remove_cbt[] = {
203 { "pseudo", "^profile$",
204 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
205 },
206 { "pseudo", "^rsm$",
207 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
208 },
209 { "printer", "^printers/[0-9]+$",
210 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
211 },
212 { "av", "^av/[0-9]+/(async|isoch)$",
213 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
214 },
215 { "pseudo", "^daplt$",
216 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
217 },
218 { "pseudo", "^zcons/" ZONENAME_REGEXP "/(" ZCONS_MASTER_NAME "|"
219 ZCONS_SLAVE_NAME ")$",
220 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
221 },
222 { "pseudo", "^" CPUID_SELF_NAME "$", RM_ALWAYS | RM_PRE | RM_HOT,
223 ILEVEL_0, devfsadm_rm_all
224 },
225 { "enclosure", "^es/ses[0-9]+$", RM_POST,
226 ILEVEL_0, devfsadm_rm_all
227 },
228 { "pseudo", "^pfil$",
229 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
230 },
231 { "pseudo", "^tpm$",
232 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
233 },
234 { "pseudo", "^sctp|sctp6$",
235 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_link
236 }
237 };
238
239 /* Rules for gpio devices */
240 static devfsadm_enumerate_t gpio_rules[1] =
241 {"^gpio([0-9]+)$", 1, MATCH_ALL};
242
243 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
244
245 /*
246 * Handles minor node type "ddi_display".
247 *
248 * type=ddi_display fbs/\M0 fb\N0
249 */
250 static int
display(di_minor_t minor,di_node_t node)251 display(di_minor_t minor, di_node_t node)
252 {
253 char l_path[PATH_MAX + 1], contents[PATH_MAX + 1], *buf;
254 devfsadm_enumerate_t rules[1] = {"^fb([0-9]+)$", 1, MATCH_ALL};
255 char *mn = di_minor_name(minor);
256
257 /* create fbs/\M0 primary link */
258 (void) strcpy(l_path, "fbs/");
259 (void) strcat(l_path, mn);
260 (void) devfsadm_mklink(l_path, node, minor, 0);
261
262 /* create fb\N0 which links to fbs/\M0 */
263 if (devfsadm_enumerate_int(l_path, 0, &buf, rules, 1)) {
264 return (DEVFSADM_CONTINUE);
265 }
266 (void) strcpy(contents, l_path);
267 (void) strcpy(l_path, "fb");
268 (void) strcat(l_path, buf);
269 free(buf);
270 (void) devfsadm_secondary_link(l_path, contents, 0);
271 return (DEVFSADM_CONTINUE);
272 }
273
274 /*
275 * Handles minor node type "ddi_parallel".
276 * type=ddi_parallel;name=mcpp mcpp\N0
277 */
278 static int
parallel(di_minor_t minor,di_node_t node)279 parallel(di_minor_t minor, di_node_t node)
280 {
281 char path[PATH_MAX + 1], *buf;
282 devfsadm_enumerate_t rules[1] = {"mcpp([0-9]+)$", 1, MATCH_ALL};
283
284
285 if (strcmp(di_node_name(node), "mcpp") != 0) {
286 return (DEVFSADM_CONTINUE);
287 }
288
289 if (NULL == (buf = di_devfs_path(node))) {
290 return (DEVFSADM_CONTINUE);
291 }
292
293 (void) snprintf(path, sizeof (path), "%s:%s",
294 buf, di_minor_name(minor));
295
296 di_devfs_path_free(buf);
297
298 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
299 return (DEVFSADM_CONTINUE);
300 }
301 (void) snprintf(path, sizeof (path), "mcpp%s", buf);
302 free(buf);
303
304 (void) devfsadm_mklink(path, node, minor, 0);
305 return (DEVFSADM_CONTINUE);
306 }
307
308 static int
ses_callback(di_minor_t minor,di_node_t node)309 ses_callback(di_minor_t minor, di_node_t node)
310 {
311 char l_path[PATH_MAX];
312 char *buf;
313 char *devfspath;
314 char p_path[PATH_MAX];
315 devfsadm_enumerate_t re[] = {"^es$/^ses([0-9]+)$", 1, MATCH_ALL};
316
317 /* find devices path -- need to free mem */
318 if (NULL == (devfspath = di_devfs_path(node))) {
319 return (DEVFSADM_CONTINUE);
320 }
321
322 (void) snprintf(p_path, sizeof (p_path), "%s:%s", devfspath,
323 di_minor_name(minor));
324
325
326 /* find next number to use; buf is an ascii number */
327 if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) {
328 /* free memory */
329 di_devfs_path_free(devfspath);
330 return (DEVFSADM_CONTINUE);
331 }
332
333 (void) snprintf(l_path, sizeof (l_path), "es/ses%s", buf);
334
335 (void) devfsadm_mklink(l_path, node, minor, 0);
336 /* free memory */
337 free(buf);
338 di_devfs_path_free(devfspath);
339 return (DEVFSADM_CONTINUE);
340
341 }
342
343 static int
node_slash_minor(di_minor_t minor,di_node_t node)344 node_slash_minor(di_minor_t minor, di_node_t node)
345 {
346
347 char path[PATH_MAX + 1];
348
349 (void) strcpy(path, di_node_name(node));
350 (void) strcat(path, "/");
351 (void) strcat(path, di_minor_name(minor));
352 (void) devfsadm_mklink(path, node, minor, 0);
353 return (DEVFSADM_CONTINUE);
354 }
355
356 static int
driver_minor(di_minor_t minor,di_node_t node)357 driver_minor(di_minor_t minor, di_node_t node)
358 {
359 char path[PATH_MAX + 1];
360
361 (void) strcpy(path, di_driver_name(node));
362 (void) strcat(path, di_minor_name(minor));
363 (void) devfsadm_mklink(path, node, minor, 0);
364 return (DEVFSADM_CONTINUE);
365 }
366
367 /*
368 * Handles links of the form:
369 * type=ddi_pseudo;name=xyz \D
370 */
371 static int
node_name(di_minor_t minor,di_node_t node)372 node_name(di_minor_t minor, di_node_t node)
373 {
374 (void) devfsadm_mklink(di_node_name(node), node, minor, 0);
375 return (DEVFSADM_CONTINUE);
376 }
377
378 /*
379 * Handles links of the form:
380 * type=ddi_pseudo;name=xyz \M0
381 */
382 static int
minor_name(di_minor_t minor,di_node_t node)383 minor_name(di_minor_t minor, di_node_t node)
384 {
385 char *mn = di_minor_name(minor);
386
387 (void) devfsadm_mklink(mn, node, minor, 0);
388 if (strcmp(mn, "icmp") == 0) {
389 (void) devfsadm_mklink("rawip", node, minor, 0);
390 }
391 if (strcmp(mn, "icmp6") == 0) {
392 (void) devfsadm_mklink("rawip6", node, minor, 0);
393 }
394 if (strcmp(mn, "ipf") == 0) {
395 (void) devfsadm_mklink("ipl", node, minor, 0);
396 }
397 return (DEVFSADM_CONTINUE);
398 }
399
400 /*
401 * create links at /dev/wifi for wifi minor node
402 */
403 static int
wifi_minor_name(di_minor_t minor,di_node_t node)404 wifi_minor_name(di_minor_t minor, di_node_t node)
405 {
406 char buf[256];
407 char *mn = di_minor_name(minor);
408
409 (void) snprintf(buf, sizeof (buf), "%s%s", "wifi/", mn);
410 (void) devfsadm_mklink(buf, node, minor, 0);
411
412 return (DEVFSADM_CONTINUE);
413 }
414
415 static int
conskbd(di_minor_t minor,di_node_t node)416 conskbd(di_minor_t minor, di_node_t node)
417 {
418 (void) devfsadm_mklink("kbd", node, minor, 0);
419 return (DEVFSADM_CONTINUE);
420 }
421
422 static int
consms(di_minor_t minor,di_node_t node)423 consms(di_minor_t minor, di_node_t node)
424 {
425 (void) devfsadm_mklink("mouse", node, minor, 0);
426 return (DEVFSADM_CONTINUE);
427 }
428
429 static int
power_button(di_minor_t minor,di_node_t node)430 power_button(di_minor_t minor, di_node_t node)
431 {
432 (void) devfsadm_mklink("power_button", node, minor, 0);
433 return (DEVFSADM_CONTINUE);
434 }
435
436 static int
fc_port(di_minor_t minor,di_node_t node)437 fc_port(di_minor_t minor, di_node_t node)
438 {
439 devfsadm_enumerate_t rules[1] = {"fc/fp([0-9]+)$", 1, MATCH_ALL};
440 char *buf, path[PATH_MAX + 1];
441 char *ptr;
442
443 if (NULL == (ptr = di_devfs_path(node))) {
444 return (DEVFSADM_CONTINUE);
445 }
446
447 (void) strcpy(path, ptr);
448 (void) strcat(path, ":");
449 (void) strcat(path, di_minor_name(minor));
450
451 di_devfs_path_free(ptr);
452
453 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) {
454 return (DEVFSADM_CONTINUE);
455 }
456
457 (void) strcpy(path, "fc/fp");
458 (void) strcat(path, buf);
459 free(buf);
460
461 (void) devfsadm_mklink(path, node, minor, 0);
462 return (DEVFSADM_CONTINUE);
463 }
464
465 /*
466 * Handles:
467 * minor node type "ddi_printer".
468 * rules of the form: type=ddi_printer;name=bpp \M0
469 */
470 static int
printer_create(di_minor_t minor,di_node_t node)471 printer_create(di_minor_t minor, di_node_t node)
472 {
473 char *mn;
474 char path[PATH_MAX + 1], *buf;
475 devfsadm_enumerate_t rules[1] = {"^printers$/^([0-9]+)$", 1, MATCH_ALL};
476
477 mn = di_minor_name(minor);
478
479 if (strcmp(di_driver_name(node), "bpp") == 0) {
480 (void) devfsadm_mklink(mn, node, minor, 0);
481 }
482
483 if (NULL == (buf = di_devfs_path(node))) {
484 return (DEVFSADM_CONTINUE);
485 }
486
487 (void) snprintf(path, sizeof (path), "%s:%s", buf, mn);
488 di_devfs_path_free(buf);
489
490 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
491 return (DEVFSADM_CONTINUE);
492 }
493
494 (void) snprintf(path, sizeof (path), "printers/%s", buf);
495 free(buf);
496
497 (void) devfsadm_mklink(path, node, minor, 0);
498
499 return (DEVFSADM_CONTINUE);
500 }
501
502 /*
503 * Handles links of the form:
504 * type=ddi_pseudo;name=se;minor2=hdlc se_hdlc\N0
505 * type=ddi_pseudo;name=serial;minor2=hdlc se_hdlc\N0
506 */
507 static int
se_hdlc_create(di_minor_t minor,di_node_t node)508 se_hdlc_create(di_minor_t minor, di_node_t node)
509 {
510 devfsadm_enumerate_t rules[1] = {"^se_hdlc([0-9]+)$", 1, MATCH_ALL};
511 char *buf, path[PATH_MAX + 1];
512 char *ptr;
513 char *mn;
514
515 mn = di_minor_name(minor);
516
517 /* minor node should be of the form: "?,hdlc" */
518 if (strcmp(mn + 1, ",hdlc") != 0) {
519 return (DEVFSADM_CONTINUE);
520 }
521
522 if (NULL == (ptr = di_devfs_path(node))) {
523 return (DEVFSADM_CONTINUE);
524 }
525
526 (void) strcpy(path, ptr);
527 (void) strcat(path, ":");
528 (void) strcat(path, mn);
529
530 di_devfs_path_free(ptr);
531
532 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) {
533 return (DEVFSADM_CONTINUE);
534 }
535
536 (void) strcpy(path, "se_hdlc");
537 (void) strcat(path, buf);
538 free(buf);
539
540 (void) devfsadm_mklink(path, node, minor, 0);
541
542 return (DEVFSADM_CONTINUE);
543 }
544
545 static int
gpio(di_minor_t minor,di_node_t node)546 gpio(di_minor_t minor, di_node_t node)
547 {
548 char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath;
549 char *minor_nm, *drvr_nm;
550
551
552 minor_nm = di_minor_name(minor);
553 drvr_nm = di_driver_name(node);
554 if ((minor_nm == NULL) || (drvr_nm == NULL)) {
555 return (DEVFSADM_CONTINUE);
556 }
557
558 devfspath = di_devfs_path(node);
559
560 (void) strcpy(p_path, devfspath);
561 (void) strcat(p_path, ":");
562 (void) strcat(p_path, minor_nm);
563 di_devfs_path_free(devfspath);
564
565 /* build the physical path from the components */
566 if (devfsadm_enumerate_int(p_path, 0, &buf, gpio_rules, 1)) {
567 return (DEVFSADM_CONTINUE);
568 }
569
570 (void) snprintf(l_path, sizeof (l_path), "%s%s", "gpio", buf);
571
572 free(buf);
573
574 (void) devfsadm_mklink(l_path, node, minor, 0);
575
576 return (DEVFSADM_CONTINUE);
577 }
578
579 /*
580 * Creates /dev/ppm nodes for Platform Specific PM module
581 */
582 static int
ppm(di_minor_t minor,di_node_t node)583 ppm(di_minor_t minor, di_node_t node)
584 {
585 (void) devfsadm_mklink("ppm", node, minor, 0);
586 return (DEVFSADM_CONTINUE);
587 }
588
589 /*
590 * Handles:
591 * /dev/av/[0-9]+/(async|isoch)
592 */
593 static int
av_create(di_minor_t minor,di_node_t node)594 av_create(di_minor_t minor, di_node_t node)
595 {
596 devfsadm_enumerate_t rules[1] = {"^av$/^([0-9]+)$", 1, MATCH_ADDR};
597 char *minor_str;
598 char path[PATH_MAX + 1];
599 char *buf;
600
601 if ((buf = di_devfs_path(node)) == NULL) {
602 return (DEVFSADM_CONTINUE);
603 }
604
605 minor_str = di_minor_name(minor);
606 (void) snprintf(path, sizeof (path), "%s:%s", buf, minor_str);
607 di_devfs_path_free(buf);
608
609 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
610 return (DEVFSADM_CONTINUE);
611 }
612
613 (void) snprintf(path, sizeof (path), "av/%s/%s", buf, minor_str);
614 free(buf);
615
616 (void) devfsadm_mklink(path, node, minor, 0);
617
618 return (DEVFSADM_CONTINUE);
619 }
620
621 /*
622 * Creates /dev/lom and /dev/tsalarm:ctl for tsalarm node
623 */
624 static int
tsalarm_create(di_minor_t minor,di_node_t node)625 tsalarm_create(di_minor_t minor, di_node_t node)
626 {
627 char buf[PATH_MAX + 1];
628 char *mn = di_minor_name(minor);
629
630 (void) snprintf(buf, sizeof (buf), "%s%s", di_node_name(node), ":ctl");
631
632 (void) devfsadm_mklink(mn, node, minor, 0);
633 (void) devfsadm_mklink(buf, node, minor, 0);
634
635 return (DEVFSADM_CONTINUE);
636 }
637
638 /*
639 * Creates /dev/ntwdt for ntwdt node
640 */
641 static int
ntwdt_create(di_minor_t minor,di_node_t node)642 ntwdt_create(di_minor_t minor, di_node_t node)
643 {
644 (void) devfsadm_mklink("ntwdt", node, minor, 0);
645 return (DEVFSADM_CONTINUE);
646 }
647
648 static int
zcons_create(di_minor_t minor,di_node_t node)649 zcons_create(di_minor_t minor, di_node_t node)
650 {
651 char *minor_str;
652 char *zonename;
653 char path[MAXPATHLEN];
654
655 minor_str = di_minor_name(minor);
656
657 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename",
658 &zonename) == -1) {
659 return (DEVFSADM_CONTINUE);
660 }
661
662 (void) snprintf(path, sizeof (path), "zcons/%s/%s", zonename,
663 minor_str);
664 (void) devfsadm_mklink(path, node, minor, 0);
665
666 return (DEVFSADM_CONTINUE);
667 }
668
669 /*
670 * /dev/cpu/self/cpuid -> /devices/pseudo/cpuid@0:self
671 */
672 static int
cpuid(di_minor_t minor,di_node_t node)673 cpuid(di_minor_t minor, di_node_t node)
674 {
675 (void) devfsadm_mklink(CPUID_SELF_NAME, node, minor, 0);
676 return (DEVFSADM_CONTINUE);
677 }
678
679 /*
680 * For device
681 * /dev/spfma -> /devices/virtual-devices/fma@5:glvc
682 */
683 static int
glvc(di_minor_t minor,di_node_t node)684 glvc(di_minor_t minor, di_node_t node)
685 {
686 char node_name[MAXNAMELEN + 1];
687
688 (void) strcpy(node_name, di_node_name(node));
689
690 if (strncmp(node_name, "fma", 3) == 0) {
691 /* Only one fma channel */
692 (void) devfsadm_mklink("spfma", node, minor, 0);
693 }
694 return (DEVFSADM_CONTINUE);
695 }
696
697 /*
698 * Handles links of the form:
699 * type=ddi_pseudo;name=sckmdrv kmdrv\M0
700 * type=ddi_pseudo;name=oplkmdrv kmdrv\M0
701 */
702 static int
kmdrv_create(di_minor_t minor,di_node_t node)703 kmdrv_create(di_minor_t minor, di_node_t node)
704 {
705
706 (void) devfsadm_mklink("kmdrv", node, minor, 0);
707 return (DEVFSADM_CONTINUE);
708 }
709