10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <regex.h>
300Sstevel@tonic-gate #include <devfsadm.h>
310Sstevel@tonic-gate #include <stdio.h>
320Sstevel@tonic-gate #include <strings.h>
330Sstevel@tonic-gate #include <stdlib.h>
340Sstevel@tonic-gate #include <limits.h>
350Sstevel@tonic-gate #include <sys/zone.h>
360Sstevel@tonic-gate #include <sys/zcons.h>
370Sstevel@tonic-gate #include <sys/cpuid_drv.h>
380Sstevel@tonic-gate 
390Sstevel@tonic-gate static int display(di_minor_t minor, di_node_t node);
400Sstevel@tonic-gate static int parallel(di_minor_t minor, di_node_t node);
410Sstevel@tonic-gate static int node_slash_minor(di_minor_t minor, di_node_t node);
420Sstevel@tonic-gate static int driver_minor(di_minor_t minor, di_node_t node);
430Sstevel@tonic-gate static int node_name(di_minor_t minor, di_node_t node);
440Sstevel@tonic-gate static int minor_name(di_minor_t minor, di_node_t node);
45*995Shx147065 static int wifi_minor_name(di_minor_t minor, di_node_t node);
460Sstevel@tonic-gate static int conskbd(di_minor_t minor, di_node_t node);
470Sstevel@tonic-gate static int consms(di_minor_t minor, di_node_t node);
480Sstevel@tonic-gate static int power_button(di_minor_t minor, di_node_t node);
490Sstevel@tonic-gate static int fc_port(di_minor_t minor, di_node_t node);
500Sstevel@tonic-gate static int printer_create(di_minor_t minor, di_node_t node);
510Sstevel@tonic-gate static int se_hdlc_create(di_minor_t minor, di_node_t node);
520Sstevel@tonic-gate static int ppm(di_minor_t minor, di_node_t node);
530Sstevel@tonic-gate static int gpio(di_minor_t minor, di_node_t node);
540Sstevel@tonic-gate static int av_create(di_minor_t minor, di_node_t node);
550Sstevel@tonic-gate static int tsalarm_create(di_minor_t minor, di_node_t node);
56467Ssc121708 static int ntwdt_create(di_minor_t minor, di_node_t node);
570Sstevel@tonic-gate static int zcons_create(di_minor_t minor, di_node_t node);
580Sstevel@tonic-gate static int cpuid(di_minor_t minor, di_node_t node);
590Sstevel@tonic-gate static int glvc(di_minor_t minor, di_node_t node);
600Sstevel@tonic-gate static int ses_callback(di_minor_t minor, di_node_t node);
610Sstevel@tonic-gate 
620Sstevel@tonic-gate static devfsadm_create_t misc_cbt[] = {
630Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "(^pts$)|(^sad$)",
640Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, node_slash_minor
650Sstevel@tonic-gate 	},
660Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "zsh",
670Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, driver_minor
680Sstevel@tonic-gate 	},
690Sstevel@tonic-gate 	{ "network", "ddi_network", NULL,
700Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, minor_name
710Sstevel@tonic-gate 	},
72*995Shx147065 	{ "wifi", "ddi_network:wifi", NULL,
73*995Shx147065 	    TYPE_EXACT, ILEVEL_0, wifi_minor_name
74*995Shx147065 	},
750Sstevel@tonic-gate 	{ "display", "ddi_display", NULL,
760Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, display
770Sstevel@tonic-gate 	},
780Sstevel@tonic-gate 	{ "parallel", "ddi_parallel", NULL,
790Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, parallel
800Sstevel@tonic-gate 	},
810Sstevel@tonic-gate 	{ "enclosure", DDI_NT_SCSI_ENCLOSURE, NULL,
820Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, ses_callback
830Sstevel@tonic-gate 	},
840Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "(^winlock$)|(^pm$)",
850Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, node_name
860Sstevel@tonic-gate 	},
870Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "conskbd",
880Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, conskbd
890Sstevel@tonic-gate 	},
900Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "consms",
910Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, consms
920Sstevel@tonic-gate 	},
930Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "rsm",
940Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
950Sstevel@tonic-gate 	},
960Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo",
970Sstevel@tonic-gate 	    "(^lockstat$)|(^SUNW,rtvc$)|(^vol$)|(^log$)|(^sy$)|"
980Sstevel@tonic-gate 	    "(^ksyms$)|(^clone$)|(^tl$)|(^tnf$)|(^kstat$)|(^mdesc$)|"
990Sstevel@tonic-gate 	    "(^eeprom$)|(^ptsl$)|(^mm$)|(^wc$)|(^dump$)|(^cn$)|(^lo$)|(^ptm$)|"
1000Sstevel@tonic-gate 	    "(^ptc$)|(^openeepr$)|(^poll$)|(^sysmsg$)|(^random$)|(^trapstat$)|"
1010Sstevel@tonic-gate 	    "(^cryptoadm$)|(^crypto$)|(^pool$)|(^poolctl$)|(^bl$)|(^kmdb$)|"
102898Skais 	    "(^sysevent$)|(^kssl$)",
1030Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
1040Sstevel@tonic-gate 	},
1050Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo",
1060Sstevel@tonic-gate 	    "(^ip$)|(^tcp$)|(^udp$)|(^icmp$)|(^sctp$)|"
1070Sstevel@tonic-gate 	    "(^ip6$)|(^tcp6$)|(^udp6$)|(^icmp6$)|(^sctp6$)|"
1080Sstevel@tonic-gate 	    "(^rts$)|(^arp$)|(^ipsecah$)|(^ipsecesp$)|(^keysock$)|(^spdsock$)|"
1090Sstevel@tonic-gate 	    "(^nca$)",
1100Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name
1110Sstevel@tonic-gate 	},
1120Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo",
1130Sstevel@tonic-gate 	    "(^pfil$)|(^ipf$)|(^ipnat$)|(^ipstate$)|(^ipauth$)|"
1140Sstevel@tonic-gate 	    "(^ipsync$)|(^ipscan$)|(^iplookup$)",
1150Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
1160Sstevel@tonic-gate 	},
1170Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo",
1180Sstevel@tonic-gate 	    "(^kdmouse$)|(^logi$)|(^rootprop$)|(^msm$)",
1190Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, node_name
1200Sstevel@tonic-gate 	},
1210Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "tod",
1220Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, node_name
1230Sstevel@tonic-gate 	},
1240Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "envctrl(two)?",
1250Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_1, minor_name,
1260Sstevel@tonic-gate 	},
1270Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "fcode",
1280Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
1290Sstevel@tonic-gate 	},
1300Sstevel@tonic-gate 	{ "power_button", "ddi_power_button", NULL,
1310Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, power_button,
1320Sstevel@tonic-gate 	},
1330Sstevel@tonic-gate 	{ "FC port", "ddi_ctl:devctl", "fp",
1340Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, fc_port
1350Sstevel@tonic-gate 	},
1360Sstevel@tonic-gate 	{ "printer", "ddi_printer", NULL,
1370Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, printer_create
1380Sstevel@tonic-gate 	},
1390Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "se",
1400Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, se_hdlc_create
1410Sstevel@tonic-gate 	},
1420Sstevel@tonic-gate 	{ "ppm",  "ddi_ppm", NULL,
1430Sstevel@tonic-gate 	    TYPE_EXACT, ILEVEL_0, ppm
1440Sstevel@tonic-gate 	},
1450Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "gpio_87317",
1460Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, gpio
1470Sstevel@tonic-gate 	},
1480Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "sckmdrv",
1490Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, minor_name,
1500Sstevel@tonic-gate 	},
1510Sstevel@tonic-gate 	{ "av", "^ddi_av:(isoch|async)$", NULL,
1520Sstevel@tonic-gate 	    TYPE_RE, ILEVEL_0, av_create,
1530Sstevel@tonic-gate 	},
1540Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "tsalarm",
1550Sstevel@tonic-gate 	    TYPE_EXACT | DRV_RE, ILEVEL_0, tsalarm_create,
1560Sstevel@tonic-gate 	},
157467Ssc121708 	{ "pseudo", "ddi_pseudo", "ntwdt",
158467Ssc121708 	    TYPE_EXACT | DRV_RE, ILEVEL_0, ntwdt_create,
159467Ssc121708 	},
1600Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "daplt",
1610Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name
1620Sstevel@tonic-gate 	},
1630Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "zcons",
1640Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, zcons_create,
1650Sstevel@tonic-gate 	},
1660Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", CPUID_DRIVER_NAME,
1670Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, cpuid,
1680Sstevel@tonic-gate 	},
1690Sstevel@tonic-gate 	{ "pseudo", "ddi_pseudo", "glvc",
1700Sstevel@tonic-gate 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, glvc,
1710Sstevel@tonic-gate 	},
1720Sstevel@tonic-gate };
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate DEVFSADM_CREATE_INIT_V0(misc_cbt);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static devfsadm_remove_t misc_remove_cbt[] = {
1770Sstevel@tonic-gate 	{ "pseudo", "^profile$",
1780Sstevel@tonic-gate 	    RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1790Sstevel@tonic-gate 	},
1800Sstevel@tonic-gate 	{ "pseudo", "^rsm$",
1810Sstevel@tonic-gate 	    RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1820Sstevel@tonic-gate 	},
1830Sstevel@tonic-gate 	{ "printer", "^printers/[0-9]+$",
1840Sstevel@tonic-gate 	    RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1850Sstevel@tonic-gate 	},
1860Sstevel@tonic-gate 	{ "av", "^av/[0-9]+/(async|isoch)$",
1870Sstevel@tonic-gate 	    RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1880Sstevel@tonic-gate 	},
1890Sstevel@tonic-gate 	{ "pseudo", "^daplt$",
1900Sstevel@tonic-gate 	    RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1910Sstevel@tonic-gate 	},
1920Sstevel@tonic-gate 	{ "pseudo", "^zcons/" ZONENAME_REGEXP "/(" ZCONS_MASTER_NAME "|"
1930Sstevel@tonic-gate 		ZCONS_SLAVE_NAME ")$",
1940Sstevel@tonic-gate 	    RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all
1950Sstevel@tonic-gate 	},
1960Sstevel@tonic-gate 	{ "pseudo", "^cpu/self/cpuid$", RM_ALWAYS | RM_PRE | RM_HOT,
1970Sstevel@tonic-gate 	    ILEVEL_0, devfsadm_rm_all
1980Sstevel@tonic-gate 	},
1990Sstevel@tonic-gate 	{ "enclosure", "^es/ses[0-9]+$", RM_POST,
2000Sstevel@tonic-gate 		ILEVEL_0, devfsadm_rm_all
2010Sstevel@tonic-gate 	}
2020Sstevel@tonic-gate };
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate /* Rules for gpio devices */
2050Sstevel@tonic-gate static devfsadm_enumerate_t gpio_rules[1] =
2060Sstevel@tonic-gate 	{"^gpio([0-9]+)$", 1, MATCH_ALL};
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
2090Sstevel@tonic-gate 
2100Sstevel@tonic-gate /*
2110Sstevel@tonic-gate  * Handles minor node type "ddi_display".
2120Sstevel@tonic-gate  *
2130Sstevel@tonic-gate  * type=ddi_display fbs/\M0 fb\N0
2140Sstevel@tonic-gate  */
2150Sstevel@tonic-gate static int
2160Sstevel@tonic-gate display(di_minor_t minor, di_node_t node)
2170Sstevel@tonic-gate {
2180Sstevel@tonic-gate 	char l_path[PATH_MAX + 1], contents[PATH_MAX + 1], *buf;
2190Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"^fb([0-9]+)$", 1, MATCH_ALL};
2200Sstevel@tonic-gate 	char *mn = di_minor_name(minor);
2210Sstevel@tonic-gate 
2220Sstevel@tonic-gate 	/* create fbs/\M0 primary link */
2230Sstevel@tonic-gate 	(void) strcpy(l_path, "fbs/");
2240Sstevel@tonic-gate 	(void) strcat(l_path, mn);
2250Sstevel@tonic-gate 	(void) devfsadm_mklink(l_path, node, minor, 0);
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	/* create fb\N0 which links to fbs/\M0 */
2280Sstevel@tonic-gate 	if (devfsadm_enumerate_int(l_path, 0, &buf, rules, 1)) {
2290Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2300Sstevel@tonic-gate 	}
2310Sstevel@tonic-gate 	(void) strcpy(contents, l_path);
2320Sstevel@tonic-gate 	(void) strcpy(l_path, "fb");
2330Sstevel@tonic-gate 	(void) strcat(l_path, buf);
2340Sstevel@tonic-gate 	free(buf);
2350Sstevel@tonic-gate 	(void) devfsadm_secondary_link(l_path, contents, 0);
2360Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
2370Sstevel@tonic-gate }
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate /*
2400Sstevel@tonic-gate  * Handles minor node type "ddi_parallel".
2410Sstevel@tonic-gate  * type=ddi_parallel;name=mcpp     mcpp\N0
2420Sstevel@tonic-gate  */
2430Sstevel@tonic-gate static int
2440Sstevel@tonic-gate parallel(di_minor_t minor, di_node_t node)
2450Sstevel@tonic-gate {
2460Sstevel@tonic-gate 	char path[PATH_MAX + 1], *buf;
2470Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"mcpp([0-9]+)$", 1, MATCH_ALL};
2480Sstevel@tonic-gate 
2490Sstevel@tonic-gate 
2500Sstevel@tonic-gate 	if (strcmp(di_node_name(node), "mcpp") != 0) {
2510Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2520Sstevel@tonic-gate 	}
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 	if (NULL == (buf = di_devfs_path(node))) {
2550Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2560Sstevel@tonic-gate 	}
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "%s:%s",
2590Sstevel@tonic-gate 	    buf, di_minor_name(minor));
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	di_devfs_path_free(buf);
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
2640Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2650Sstevel@tonic-gate 	}
2660Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "mcpp%s", buf);
2670Sstevel@tonic-gate 	free(buf);
2680Sstevel@tonic-gate 
2690Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
2700Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
2710Sstevel@tonic-gate }
2720Sstevel@tonic-gate 
2730Sstevel@tonic-gate static int
2740Sstevel@tonic-gate ses_callback(di_minor_t minor, di_node_t node)
2750Sstevel@tonic-gate {
2760Sstevel@tonic-gate 	char l_path[PATH_MAX];
2770Sstevel@tonic-gate 	char *buf;
2780Sstevel@tonic-gate 	char *devfspath;
2790Sstevel@tonic-gate 	char p_path[PATH_MAX];
2800Sstevel@tonic-gate 	devfsadm_enumerate_t re[] = {"^es$/^ses([0-9]+)$", 1, MATCH_ALL};
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 	/* find devices path -- need to free mem */
2830Sstevel@tonic-gate 	if (NULL == (devfspath = di_devfs_path(node))) {
2840Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	(void) snprintf(p_path, sizeof (p_path), "%s:%s", devfspath,
2880Sstevel@tonic-gate 	    di_minor_name(minor));
2890Sstevel@tonic-gate 
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	/* find next number to use; buf is an ascii number */
2920Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) {
2930Sstevel@tonic-gate 		/* free memory */
2940Sstevel@tonic-gate 		di_devfs_path_free(devfspath);
2950Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	(void) snprintf(l_path, sizeof (l_path), "es/ses%s", buf);
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	(void) devfsadm_mklink(l_path, node, minor, 0);
3010Sstevel@tonic-gate 	/* free memory */
3020Sstevel@tonic-gate 	free(buf);
3030Sstevel@tonic-gate 	di_devfs_path_free(devfspath);
3040Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3050Sstevel@tonic-gate 
3060Sstevel@tonic-gate }
3070Sstevel@tonic-gate 
3080Sstevel@tonic-gate static int
3090Sstevel@tonic-gate node_slash_minor(di_minor_t minor, di_node_t node)
3100Sstevel@tonic-gate {
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	char path[PATH_MAX + 1];
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	(void) strcpy(path, di_node_name(node));
3150Sstevel@tonic-gate 	(void) strcat(path, "/");
3160Sstevel@tonic-gate 	(void) strcat(path, di_minor_name(minor));
3170Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
3180Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3190Sstevel@tonic-gate }
3200Sstevel@tonic-gate 
3210Sstevel@tonic-gate static int
3220Sstevel@tonic-gate driver_minor(di_minor_t minor, di_node_t node)
3230Sstevel@tonic-gate {
3240Sstevel@tonic-gate 	char path[PATH_MAX + 1];
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	(void) strcpy(path, di_driver_name(node));
3270Sstevel@tonic-gate 	(void) strcat(path, di_minor_name(minor));
3280Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
3290Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3300Sstevel@tonic-gate }
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate  * Handles links of the form:
3340Sstevel@tonic-gate  * type=ddi_pseudo;name=xyz  \D
3350Sstevel@tonic-gate  */
3360Sstevel@tonic-gate static int
3370Sstevel@tonic-gate node_name(di_minor_t minor, di_node_t node)
3380Sstevel@tonic-gate {
3390Sstevel@tonic-gate 	(void) devfsadm_mklink(di_node_name(node), node, minor, 0);
3400Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate /*
3440Sstevel@tonic-gate  * Handles links of the form:
3450Sstevel@tonic-gate  * type=ddi_pseudo;name=xyz  \M0
3460Sstevel@tonic-gate  */
3470Sstevel@tonic-gate static int
3480Sstevel@tonic-gate minor_name(di_minor_t minor, di_node_t node)
3490Sstevel@tonic-gate {
3500Sstevel@tonic-gate 	char *mn = di_minor_name(minor);
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 	(void) devfsadm_mklink(mn, node, minor, 0);
3530Sstevel@tonic-gate 	if (strcmp(mn, "icmp") == 0) {
3540Sstevel@tonic-gate 		(void) devfsadm_mklink("rawip", node, minor, 0);
3550Sstevel@tonic-gate 	}
3560Sstevel@tonic-gate 	if (strcmp(mn, "icmp6") == 0) {
3570Sstevel@tonic-gate 		(void) devfsadm_mklink("rawip6", node, minor, 0);
3580Sstevel@tonic-gate 	}
3590Sstevel@tonic-gate 	if (strcmp(mn, "ipf") == 0) {
3600Sstevel@tonic-gate 		(void) devfsadm_mklink("ipl", node, minor, 0);
3610Sstevel@tonic-gate 	}
3620Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3630Sstevel@tonic-gate }
3640Sstevel@tonic-gate 
365*995Shx147065 /*
366*995Shx147065  * create links at /dev/wifi for wifi minor node
367*995Shx147065  */
368*995Shx147065 static int
369*995Shx147065 wifi_minor_name(di_minor_t minor, di_node_t node)
370*995Shx147065 {
371*995Shx147065 	char buf[256];
372*995Shx147065 	char *mn = di_minor_name(minor);
373*995Shx147065 
374*995Shx147065 	(void) snprintf(buf, sizeof (buf), "%s%s", "wifi/", mn);
375*995Shx147065 	(void) devfsadm_mklink(buf, node, minor, 0);
376*995Shx147065 
377*995Shx147065 	return (DEVFSADM_CONTINUE);
378*995Shx147065 }
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate static int
3810Sstevel@tonic-gate conskbd(di_minor_t minor, di_node_t node)
3820Sstevel@tonic-gate {
3830Sstevel@tonic-gate 	(void) devfsadm_mklink("kbd", node, minor, 0);
3840Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3850Sstevel@tonic-gate }
3860Sstevel@tonic-gate 
3870Sstevel@tonic-gate static int
3880Sstevel@tonic-gate consms(di_minor_t minor, di_node_t node)
3890Sstevel@tonic-gate {
3900Sstevel@tonic-gate 	(void) devfsadm_mklink("mouse", node, minor, 0);
3910Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate static int
3950Sstevel@tonic-gate power_button(di_minor_t minor, di_node_t node)
3960Sstevel@tonic-gate {
3970Sstevel@tonic-gate 	(void) devfsadm_mklink("power_button", node, minor, 0);
3980Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
3990Sstevel@tonic-gate }
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate static int
4020Sstevel@tonic-gate fc_port(di_minor_t minor, di_node_t node)
4030Sstevel@tonic-gate {
4040Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"fc/fp([0-9]+)$", 1, MATCH_ALL};
4050Sstevel@tonic-gate 	char *buf, path[PATH_MAX + 1];
4060Sstevel@tonic-gate 	char *ptr;
4070Sstevel@tonic-gate 
4080Sstevel@tonic-gate 	if (NULL == (ptr = di_devfs_path(node))) {
4090Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4100Sstevel@tonic-gate 	}
4110Sstevel@tonic-gate 
4120Sstevel@tonic-gate 	(void) strcpy(path, ptr);
4130Sstevel@tonic-gate 	(void) strcat(path, ":");
4140Sstevel@tonic-gate 	(void) strcat(path, di_minor_name(minor));
4150Sstevel@tonic-gate 
4160Sstevel@tonic-gate 	di_devfs_path_free(ptr);
4170Sstevel@tonic-gate 
4180Sstevel@tonic-gate 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) {
4190Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4200Sstevel@tonic-gate 	}
4210Sstevel@tonic-gate 
4220Sstevel@tonic-gate 	(void) strcpy(path, "fc/fp");
4230Sstevel@tonic-gate 	(void) strcat(path, buf);
4240Sstevel@tonic-gate 	free(buf);
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
4270Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
4280Sstevel@tonic-gate }
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate /*
4310Sstevel@tonic-gate  * Handles:
4320Sstevel@tonic-gate  *	minor node type "ddi_printer".
4330Sstevel@tonic-gate  * 	rules of the form: type=ddi_printer;name=bpp  \M0
4340Sstevel@tonic-gate  */
4350Sstevel@tonic-gate static int
4360Sstevel@tonic-gate printer_create(di_minor_t minor, di_node_t node)
4370Sstevel@tonic-gate {
4380Sstevel@tonic-gate 	char *mn;
4390Sstevel@tonic-gate 	char path[PATH_MAX + 1], *buf;
4400Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"^printers$/^([0-9]+)$", 1, MATCH_ALL};
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	mn = di_minor_name(minor);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	if (strcmp(di_driver_name(node), "bpp") == 0) {
4450Sstevel@tonic-gate 		(void) devfsadm_mklink(mn, node, minor, 0);
4460Sstevel@tonic-gate 	}
4470Sstevel@tonic-gate 
4480Sstevel@tonic-gate 	if (NULL == (buf = di_devfs_path(node))) {
4490Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4500Sstevel@tonic-gate 	}
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "%s:%s", buf, mn);
4530Sstevel@tonic-gate 	di_devfs_path_free(buf);
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
4560Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4570Sstevel@tonic-gate 	}
4580Sstevel@tonic-gate 
4590Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "printers/%s", buf);
4600Sstevel@tonic-gate 	free(buf);
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
4630Sstevel@tonic-gate 
4640Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
4650Sstevel@tonic-gate }
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate  * Handles links of the form:
4690Sstevel@tonic-gate  * type=ddi_pseudo;name=se;minor2=hdlc	se_hdlc\N0
4700Sstevel@tonic-gate  * type=ddi_pseudo;name=serial;minor2=hdlc	se_hdlc\N0
4710Sstevel@tonic-gate  */
4720Sstevel@tonic-gate static int
4730Sstevel@tonic-gate se_hdlc_create(di_minor_t minor, di_node_t node)
4740Sstevel@tonic-gate {
4750Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"^se_hdlc([0-9]+)$", 1, MATCH_ALL};
4760Sstevel@tonic-gate 	char *buf, path[PATH_MAX + 1];
4770Sstevel@tonic-gate 	char *ptr;
4780Sstevel@tonic-gate 	char *mn;
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	mn = di_minor_name(minor);
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	/* minor node should be of the form: "?,hdlc" */
4830Sstevel@tonic-gate 	if (strcmp(mn + 1, ",hdlc") != 0) {
4840Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 	if (NULL == (ptr = di_devfs_path(node))) {
4880Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4890Sstevel@tonic-gate 	}
4900Sstevel@tonic-gate 
4910Sstevel@tonic-gate 	(void) strcpy(path, ptr);
4920Sstevel@tonic-gate 	(void) strcat(path, ":");
4930Sstevel@tonic-gate 	(void) strcat(path, mn);
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	di_devfs_path_free(ptr);
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) {
4980Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
4990Sstevel@tonic-gate 	}
5000Sstevel@tonic-gate 
5010Sstevel@tonic-gate 	(void) strcpy(path, "se_hdlc");
5020Sstevel@tonic-gate 	(void) strcat(path, buf);
5030Sstevel@tonic-gate 	free(buf);
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
5060Sstevel@tonic-gate 
5070Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
5080Sstevel@tonic-gate }
5090Sstevel@tonic-gate 
5100Sstevel@tonic-gate static int
5110Sstevel@tonic-gate gpio(di_minor_t minor, di_node_t node)
5120Sstevel@tonic-gate {
5130Sstevel@tonic-gate 	char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath;
5140Sstevel@tonic-gate 	char *minor_nm, *drvr_nm;
5150Sstevel@tonic-gate 
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	minor_nm = di_minor_name(minor);
5180Sstevel@tonic-gate 	drvr_nm = di_driver_name(node);
5190Sstevel@tonic-gate 	if ((minor_nm == NULL) || (drvr_nm == NULL)) {
5200Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
5210Sstevel@tonic-gate 	}
5220Sstevel@tonic-gate 
5230Sstevel@tonic-gate 	devfspath = di_devfs_path(node);
5240Sstevel@tonic-gate 
5250Sstevel@tonic-gate 	(void) strcpy(p_path, devfspath);
5260Sstevel@tonic-gate 	(void) strcat(p_path, ":");
5270Sstevel@tonic-gate 	(void) strcat(p_path, minor_nm);
5280Sstevel@tonic-gate 	di_devfs_path_free(devfspath);
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	/* build the physical path from the components */
5310Sstevel@tonic-gate 	if (devfsadm_enumerate_int(p_path, 0, &buf, gpio_rules, 1)) {
5320Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
5330Sstevel@tonic-gate 	}
5340Sstevel@tonic-gate 
5350Sstevel@tonic-gate 	(void) snprintf(l_path, sizeof (l_path), "%s%s", "gpio", buf);
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 	free(buf);
5380Sstevel@tonic-gate 
5390Sstevel@tonic-gate 	(void) devfsadm_mklink(l_path, node, minor, 0);
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
5420Sstevel@tonic-gate }
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate /*
5450Sstevel@tonic-gate  * Creates /dev/ppm nodes for Platform Specific PM module
5460Sstevel@tonic-gate  */
5470Sstevel@tonic-gate static int
5480Sstevel@tonic-gate ppm(di_minor_t minor, di_node_t node)
5490Sstevel@tonic-gate {
5500Sstevel@tonic-gate 	(void) devfsadm_mklink("ppm", node, minor, 0);
5510Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
5520Sstevel@tonic-gate }
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate /*
5550Sstevel@tonic-gate  * Handles:
5560Sstevel@tonic-gate  *	/dev/av/[0-9]+/(async|isoch)
5570Sstevel@tonic-gate  */
5580Sstevel@tonic-gate static int
5590Sstevel@tonic-gate av_create(di_minor_t minor, di_node_t node)
5600Sstevel@tonic-gate {
5610Sstevel@tonic-gate 	devfsadm_enumerate_t rules[1] = {"^av$/^([0-9]+)$", 1, MATCH_ADDR};
5620Sstevel@tonic-gate 	char	*minor_str;
5630Sstevel@tonic-gate 	char	path[PATH_MAX + 1];
5640Sstevel@tonic-gate 	char	*buf;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	if ((buf = di_devfs_path(node)) == NULL) {
5670Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
5680Sstevel@tonic-gate 	}
5690Sstevel@tonic-gate 
5700Sstevel@tonic-gate 	minor_str = di_minor_name(minor);
5710Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "%s:%s", buf, minor_str);
5720Sstevel@tonic-gate 	di_devfs_path_free(buf);
5730Sstevel@tonic-gate 
5740Sstevel@tonic-gate 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
5750Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
5760Sstevel@tonic-gate 	}
5770Sstevel@tonic-gate 
5780Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "av/%s/%s", buf, minor_str);
5790Sstevel@tonic-gate 	free(buf);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
5840Sstevel@tonic-gate }
5850Sstevel@tonic-gate 
5860Sstevel@tonic-gate /*
5870Sstevel@tonic-gate  * Creates /dev/lom and /dev/tsalarm:ctl for tsalarm node
5880Sstevel@tonic-gate  */
5890Sstevel@tonic-gate static int
5900Sstevel@tonic-gate tsalarm_create(di_minor_t minor, di_node_t node)
5910Sstevel@tonic-gate {
5920Sstevel@tonic-gate 	char buf[PATH_MAX + 1];
5930Sstevel@tonic-gate 	char *mn = di_minor_name(minor);
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	(void) snprintf(buf, sizeof (buf), "%s%s", di_node_name(node), ":ctl");
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	(void) devfsadm_mklink(mn, node, minor, 0);
5980Sstevel@tonic-gate 	(void) devfsadm_mklink(buf, node, minor, 0);
5990Sstevel@tonic-gate 
6000Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
6010Sstevel@tonic-gate }
6020Sstevel@tonic-gate 
603467Ssc121708 /*
604467Ssc121708  * Creates /dev/ntwdt for ntwdt node
605467Ssc121708  */
606467Ssc121708 static int
607467Ssc121708 ntwdt_create(di_minor_t minor, di_node_t node)
608467Ssc121708 {
609467Ssc121708 	(void) devfsadm_mklink("ntwdt", node, minor, 0);
610467Ssc121708 	return (DEVFSADM_CONTINUE);
611467Ssc121708 }
612467Ssc121708 
6130Sstevel@tonic-gate static int
6140Sstevel@tonic-gate zcons_create(di_minor_t minor, di_node_t node)
6150Sstevel@tonic-gate {
6160Sstevel@tonic-gate 	char	*minor_str;
6170Sstevel@tonic-gate 	char	*zonename;
6180Sstevel@tonic-gate 	char	path[MAXPATHLEN];
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	minor_str = di_minor_name(minor);
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename",
6230Sstevel@tonic-gate 	    &zonename) == -1) {
6240Sstevel@tonic-gate 		return (DEVFSADM_CONTINUE);
6250Sstevel@tonic-gate 	}
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	(void) snprintf(path, sizeof (path), "zcons/%s/%s", zonename,
6280Sstevel@tonic-gate 	    minor_str);
6290Sstevel@tonic-gate 	(void) devfsadm_mklink(path, node, minor, 0);
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
6320Sstevel@tonic-gate }
6330Sstevel@tonic-gate 
6340Sstevel@tonic-gate /*
6350Sstevel@tonic-gate  *	/dev/cpu/self/cpuid 	->	/devices/pseudo/cpuid@0:self
6360Sstevel@tonic-gate  */
6370Sstevel@tonic-gate static int
6380Sstevel@tonic-gate cpuid(di_minor_t minor, di_node_t node)
6390Sstevel@tonic-gate {
6400Sstevel@tonic-gate 	(void) devfsadm_mklink(CPUID_SELF_NAME, node, minor, 0);
6410Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
6420Sstevel@tonic-gate }
6430Sstevel@tonic-gate 
6440Sstevel@tonic-gate /*
6450Sstevel@tonic-gate  * For device
6460Sstevel@tonic-gate  *      /dev/spfma -> /devices/virtual-devices/fma@5:glvc
6470Sstevel@tonic-gate  */
6480Sstevel@tonic-gate static int
6490Sstevel@tonic-gate glvc(di_minor_t minor, di_node_t node)
6500Sstevel@tonic-gate {
6510Sstevel@tonic-gate 	char node_name[MAXNAMELEN + 1];
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 	(void) strcpy(node_name, di_node_name(node));
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 	if (strncmp(node_name, "fma", 3) == 0) {
6560Sstevel@tonic-gate 		/* Only one fma channel */
6570Sstevel@tonic-gate 		(void) devfsadm_mklink("spfma", node, minor, 0);
6580Sstevel@tonic-gate 	}
6590Sstevel@tonic-gate 	return (DEVFSADM_CONTINUE);
6600Sstevel@tonic-gate }
661