Home | History | Annotate | Download | only in i386
      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 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <regex.h>
     27 #include <devfsadm.h>
     28 #include <stdio.h>
     29 #include <strings.h>
     30 #include <stdlib.h>
     31 #include <limits.h>
     32 #include <ctype.h>
     33 #include <sys/mc_amd.h>
     34 #include <bsm/devalloc.h>
     35 
     36 extern int system_labeled;
     37 
     38 static int lp(di_minor_t minor, di_node_t node);
     39 static int serial_dialout(di_minor_t minor, di_node_t node);
     40 static int serial(di_minor_t minor, di_node_t node);
     41 static int diskette(di_minor_t minor, di_node_t node);
     42 static int vt00(di_minor_t minor, di_node_t node);
     43 static int kdmouse(di_minor_t minor, di_node_t node);
     44 static int bmc(di_minor_t minor, di_node_t node);
     45 static int smbios(di_minor_t minor, di_node_t node);
     46 static int agp_process(di_minor_t minor, di_node_t node);
     47 static int drm_node(di_minor_t minor, di_node_t node);
     48 static int mc_node(di_minor_t minor, di_node_t node);
     49 static int xsvc(di_minor_t minor, di_node_t node);
     50 static int srn(di_minor_t minor, di_node_t node);
     51 static int ucode(di_minor_t minor, di_node_t node);
     52 static int heci(di_minor_t minor, di_node_t node);
     53 
     54 
     55 static devfsadm_create_t misc_cbt[] = {
     56 	{ "vt00", "ddi_display", NULL,
     57 	    TYPE_EXACT, ILEVEL_0,	vt00
     58 	},
     59 	{ "drm", "ddi_display:drm", NULL,
     60 	    TYPE_EXACT, ILEVEL_0,	drm_node
     61 	},
     62 	{ "mouse", "ddi_mouse", "mouse8042",
     63 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, kdmouse
     64 	},
     65 	{ "pseudo", "ddi_pseudo", "bmc",
     66 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, bmc,
     67 	},
     68 	{ "pseudo", "ddi_pseudo", "smbios",
     69 	    TYPE_EXACT | DRV_EXACT, ILEVEL_1, smbios,
     70 	},
     71 	{ "disk",  "ddi_block:diskette", NULL,
     72 	    TYPE_EXACT, ILEVEL_1, diskette
     73 	},
     74 	{ "parallel",  "ddi_printer", NULL,
     75 	    TYPE_EXACT, ILEVEL_1, lp
     76 	},
     77 	{ "serial", "ddi_serial:mb", NULL,
     78 	    TYPE_EXACT, ILEVEL_1, serial
     79 	},
     80 	{ "serial",  "ddi_serial:dialout,mb", NULL,
     81 	    TYPE_EXACT, ILEVEL_1, serial_dialout
     82 	},
     83 	{ "agp", "ddi_agp:pseudo", NULL,
     84 	    TYPE_EXACT, ILEVEL_0, agp_process
     85 	},
     86 	{ "agp", "ddi_agp:target", NULL,
     87 	    TYPE_EXACT, ILEVEL_0, agp_process
     88 	},
     89 	{ "agp", "ddi_agp:cpugart", NULL,
     90 	    TYPE_EXACT, ILEVEL_0, agp_process
     91 	},
     92 	{ "agp", "ddi_agp:master", NULL,
     93 	    TYPE_EXACT, ILEVEL_0, agp_process
     94 	},
     95 	{ "pseudo", "ddi_pseudo", NULL,
     96 	    TYPE_EXACT, ILEVEL_0, xsvc
     97 	},
     98 	{ "pseudo", "ddi_pseudo", NULL,
     99 	    TYPE_EXACT, ILEVEL_0, srn
    100 	},
    101 	{ "memory-controller", "ddi_mem_ctrl", NULL,
    102 	    TYPE_EXACT, ILEVEL_0, mc_node
    103 	},
    104 	{ "pseudo", "ddi_pseudo", "ucode",
    105 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, ucode,
    106 	},
    107 	{ "pseudo", "ddi_pseudo", "heci",
    108 	    TYPE_EXACT | DRV_EXACT, ILEVEL_0, heci,
    109 	}
    110 };
    111 
    112 DEVFSADM_CREATE_INIT_V0(misc_cbt);
    113 
    114 static char *debug_mid = "misc_mid";
    115 
    116 typedef enum {
    117 	DRIVER_AGPPSEUDO = 0,
    118 	DRIVER_AGPTARGET,
    119 	DRIVER_CPUGART,
    120 	DRIVER_AGPMASTER_DRM_I915,
    121 	DRIVER_AGPMASTER_DRM_RADEON,
    122 	DRIVER_AGPMASTER_VGATEXT,
    123 	DRIVER_UNKNOWN
    124 } driver_defs_t;
    125 
    126 typedef struct {
    127 	char	*driver_name;
    128 	int	index;
    129 } driver_name_table_entry_t;
    130 
    131 static driver_name_table_entry_t driver_name_table[] = {
    132 	{ "agpgart",		DRIVER_AGPPSEUDO },
    133 	{ "agptarget",		DRIVER_AGPTARGET },
    134 	{ "amd64_gart",		DRIVER_CPUGART },
    135 	/* AGP master device managed by drm driver */
    136 	{ "i915",		DRIVER_AGPMASTER_DRM_I915 },
    137 	{ "radeon",		DRIVER_AGPMASTER_DRM_RADEON },
    138 	{ "vgatext",		DRIVER_AGPMASTER_VGATEXT },
    139 	{ NULL,			DRIVER_UNKNOWN }
    140 };
    141 
    142 static devfsadm_enumerate_t agptarget_rules[1] =
    143 	{ "^agp$/^agptarget([0-9]+)$", 1, MATCH_ALL };
    144 static devfsadm_enumerate_t cpugart_rules[1] =
    145 	{ "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
    146 static devfsadm_enumerate_t agpmaster_rules[1] =
    147 	{  "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
    148 
    149 static devfsadm_remove_t misc_remove_cbt[] = {
    150 	{ "vt", "vt[0-9][0-9]", RM_PRE|RM_ALWAYS,
    151 		ILEVEL_0, devfsadm_rm_all
    152 	},
    153 	{ "pseudo", "^ucode$", RM_ALWAYS | RM_PRE | RM_HOT,
    154 		ILEVEL_0, devfsadm_rm_all
    155 	}
    156 };
    157 
    158 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
    159 
    160 /*
    161  * Handles minor node type "ddi_display", in addition to generic processing
    162  * done by display().
    163  *
    164  * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
    165  */
    166 /* ARGSUSED */
    167 int
    168 vt00(di_minor_t minor, di_node_t node)
    169 {
    170 	(void) devfsadm_secondary_link("vt00", "fb", 0);
    171 	return (DEVFSADM_CONTINUE);
    172 }
    173 
    174 /*
    175  * type=ddi_block:diskette;addr=0,0;minor=c        diskette
    176  * type=ddi_block:diskette;addr=0,0;minor=c,raw    rdiskette
    177  * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
    178  * type=ddi_block:diskette;addr1=0;minor=c,raw     rdiskette\A2
    179  */
    180 static int
    181 diskette(di_minor_t minor, di_node_t node)
    182 {
    183 	int flags = 0;
    184 	char *a2;
    185 	char link[PATH_MAX];
    186 	char *addr = di_bus_addr(node);
    187 	char *mn = di_minor_name(minor);
    188 
    189 	if (system_labeled)
    190 		flags = DA_ADD|DA_FLOPPY;
    191 
    192 	if (strcmp(addr, "0,0") == 0) {
    193 		if (strcmp(mn, "c") == 0) {
    194 			(void) devfsadm_mklink("diskette", node, minor, flags);
    195 		} else if (strcmp(mn, "c,raw") == 0) {
    196 			(void) devfsadm_mklink("rdiskette", node, minor, flags);
    197 		}
    198 
    199 	}
    200 
    201 	if (addr[0] == '0') {
    202 		if ((a2 = strchr(addr, ',')) != NULL) {
    203 			a2++;
    204 			if (strcmp(mn, "c") == 0) {
    205 				(void) strcpy(link, "diskette");
    206 				(void) strcat(link, a2);
    207 				(void) devfsadm_mklink(link, node, minor,
    208 				    flags);
    209 			} else if (strcmp(mn, "c,raw") == 0) {
    210 				(void) strcpy(link, "rdiskette");
    211 				(void) strcat(link, a2);
    212 				(void) devfsadm_mklink(link, node, minor,
    213 				    flags);
    214 			}
    215 		}
    216 	}
    217 
    218 	return (DEVFSADM_CONTINUE);
    219 }
    220 
    221 /*
    222  * type=ddi_printer;name=lp;addr=1,3bc      lp0
    223  * type=ddi_printer;name=lp;addr=1,378      lp1
    224  * type=ddi_printer;name=lp;addr=1,278      lp2
    225  */
    226 static int
    227 lp(di_minor_t minor, di_node_t node)
    228 {
    229 	char *addr = di_bus_addr(node);
    230 	char *buf;
    231 	char path[PATH_MAX + 1];
    232 	devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
    233 
    234 	if (strcmp(addr, "1,3bc") == 0) {
    235 		(void) devfsadm_mklink("lp0", node, minor, 0);
    236 
    237 	} else if (strcmp(addr, "1,378") == 0) {
    238 		(void) devfsadm_mklink("lp1", node, minor, 0);
    239 
    240 	} else if (strcmp(addr, "1,278") == 0) {
    241 		(void) devfsadm_mklink("lp2", node, minor, 0);
    242 	}
    243 
    244 	if (strcmp(di_driver_name(node), "ecpp") != 0) {
    245 		return (DEVFSADM_CONTINUE);
    246 	}
    247 
    248 	if ((buf = di_devfs_path(node)) == NULL) {
    249 		return (DEVFSADM_CONTINUE);
    250 	}
    251 
    252 	(void) snprintf(path, sizeof (path), "%s:%s",
    253 	    buf, di_minor_name(minor));
    254 
    255 	di_devfs_path_free(buf);
    256 
    257 	if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
    258 		return (DEVFSADM_CONTINUE);
    259 	}
    260 
    261 	(void) snprintf(path, sizeof (path), "ecpp%s", buf);
    262 	free(buf);
    263 	(void) devfsadm_mklink(path, node, minor, 0);
    264 	return (DEVFSADM_CONTINUE);
    265 }
    266 
    267 /*
    268  * type=ddi_serial:mb;minor=a      tty00
    269  * type=ddi_serial:mb;minor=b      tty01
    270  * type=ddi_serial:mb;minor=c      tty02
    271  * type=ddi_serial:mb;minor=d      tty03
    272  */
    273 static int
    274 serial(di_minor_t minor, di_node_t node)
    275 {
    276 
    277 	char *mn = di_minor_name(minor);
    278 	char link[PATH_MAX];
    279 
    280 	(void) strcpy(link, "tty");
    281 	(void) strcat(link, mn);
    282 	(void) devfsadm_mklink(link, node, minor, 0);
    283 
    284 	if (strcmp(mn, "a") == 0) {
    285 		(void) devfsadm_mklink("tty00", node, minor, 0);
    286 
    287 	} else if (strcmp(mn, "b") == 0) {
    288 		(void) devfsadm_mklink("tty01", node, minor, 0);
    289 
    290 	} else if (strcmp(mn, "c") == 0) {
    291 		(void) devfsadm_mklink("tty02", node, minor, 0);
    292 
    293 	} else if (strcmp(mn, "d") == 0) {
    294 		(void) devfsadm_mklink("tty03", node, minor, 0);
    295 	}
    296 	return (DEVFSADM_CONTINUE);
    297 }
    298 
    299 /*
    300  * type=ddi_serial:dialout,mb;minor=a,cu   ttyd0
    301  * type=ddi_serial:dialout,mb;minor=b,cu   ttyd1
    302  * type=ddi_serial:dialout,mb;minor=c,cu   ttyd2
    303  * type=ddi_serial:dialout,mb;minor=d,cu   ttyd3
    304  */
    305 static int
    306 serial_dialout(di_minor_t minor, di_node_t node)
    307 {
    308 	char *mn = di_minor_name(minor);
    309 
    310 	if (strcmp(mn, "a,cu") == 0) {
    311 		(void) devfsadm_mklink("ttyd0", node, minor, 0);
    312 		(void) devfsadm_mklink("cua0", node, minor, 0);
    313 
    314 	} else if (strcmp(mn, "b,cu") == 0) {
    315 		(void) devfsadm_mklink("ttyd1", node, minor, 0);
    316 		(void) devfsadm_mklink("cua1", node, minor, 0);
    317 
    318 	} else if (strcmp(mn, "c,cu") == 0) {
    319 		(void) devfsadm_mklink("ttyd2", node, minor, 0);
    320 		(void) devfsadm_mklink("cua2", node, minor, 0);
    321 
    322 	} else if (strcmp(mn, "d,cu") == 0) {
    323 		(void) devfsadm_mklink("ttyd3", node, minor, 0);
    324 		(void) devfsadm_mklink("cua3", node, minor, 0);
    325 	}
    326 	return (DEVFSADM_CONTINUE);
    327 }
    328 
    329 static int
    330 kdmouse(di_minor_t minor, di_node_t node)
    331 {
    332 	(void) devfsadm_mklink("kdmouse", node, minor, 0);
    333 	return (DEVFSADM_CONTINUE);
    334 }
    335 
    336 static int
    337 bmc(di_minor_t minor, di_node_t node)
    338 {
    339 	(void) devfsadm_mklink("bmc", node, minor, 0);
    340 	return (DEVFSADM_CONTINUE);
    341 }
    342 
    343 static int
    344 smbios(di_minor_t minor, di_node_t node)
    345 {
    346 	(void) devfsadm_mklink("smbios", node, minor, 0);
    347 	return (DEVFSADM_CONTINUE);
    348 }
    349 
    350 static int
    351 agp_process(di_minor_t minor, di_node_t node)
    352 {
    353 	char *minor_nm, *drv_nm;
    354 	char *devfspath;
    355 	char *I_path, *p_path, *buf;
    356 	char *name = (char *)NULL;
    357 	int i, index;
    358 	devfsadm_enumerate_t rules[1];
    359 
    360 	minor_nm = di_minor_name(minor);
    361 	drv_nm = di_driver_name(node);
    362 
    363 	if ((minor_nm == NULL) || (drv_nm == NULL)) {
    364 		return (DEVFSADM_CONTINUE);
    365 	}
    366 
    367 	devfsadm_print(debug_mid, "agp_process: minor=%s node=%s\n",
    368 	    minor_nm, di_node_name(node));
    369 
    370 	devfspath = di_devfs_path(node);
    371 	if (devfspath == NULL) {
    372 		devfsadm_print(debug_mid, "agp_process: devfspath is NULL\n");
    373 		return (DEVFSADM_CONTINUE);
    374 	}
    375 
    376 	I_path = (char *)malloc(PATH_MAX);
    377 
    378 	if (I_path == NULL) {
    379 		di_devfs_path_free(devfspath);
    380 		devfsadm_print(debug_mid,  "agp_process: malloc failed\n");
    381 		return (DEVFSADM_CONTINUE);
    382 	}
    383 
    384 	p_path = (char *)malloc(PATH_MAX);
    385 
    386 	if (p_path == NULL) {
    387 		devfsadm_print(debug_mid,  "agp_process: malloc failed\n");
    388 		di_devfs_path_free(devfspath);
    389 		free(I_path);
    390 		return (DEVFSADM_CONTINUE);
    391 	}
    392 
    393 	(void) strlcpy(p_path, devfspath, PATH_MAX);
    394 	(void) strlcat(p_path, ":", PATH_MAX);
    395 	(void) strlcat(p_path, minor_nm, PATH_MAX);
    396 	di_devfs_path_free(devfspath);
    397 
    398 	devfsadm_print(debug_mid, "agp_process: path %s\n", p_path);
    399 
    400 	for (i = 0; ; i++) {
    401 		if ((driver_name_table[i].driver_name == NULL) ||
    402 		    (strcmp(drv_nm, driver_name_table[i].driver_name) == 0)) {
    403 			index = driver_name_table[i].index;
    404 			break;
    405 		}
    406 	}
    407 	switch (index) {
    408 	case DRIVER_AGPPSEUDO:
    409 		devfsadm_print(debug_mid,
    410 		    "agp_process: psdeudo driver name\n");
    411 		name = "agpgart";
    412 		(void) snprintf(I_path, PATH_MAX, "%s", name);
    413 		devfsadm_print(debug_mid,
    414 		    "mklink %s -> %s\n", I_path, p_path);
    415 
    416 		(void) devfsadm_mklink(I_path, node, minor, 0);
    417 
    418 		free(I_path);
    419 		free(p_path);
    420 		return (DEVFSADM_CONTINUE);
    421 	case DRIVER_AGPTARGET:
    422 		devfsadm_print(debug_mid,
    423 		    "agp_process: target driver name\n");
    424 		rules[0] = agptarget_rules[0];
    425 		name = "agptarget";
    426 		break;
    427 	case DRIVER_CPUGART:
    428 		devfsadm_print(debug_mid,
    429 		    "agp_process: cpugart driver name\n");
    430 		rules[0] = cpugart_rules[0];
    431 		name = "cpugart";
    432 		break;
    433 	case DRIVER_AGPMASTER_DRM_I915:
    434 	case DRIVER_AGPMASTER_DRM_RADEON:
    435 	case DRIVER_AGPMASTER_VGATEXT:
    436 		devfsadm_print(debug_mid,
    437 		    "agp_process: agpmaster driver name\n");
    438 		rules[0] = agpmaster_rules[0];
    439 		name = "agpmaster";
    440 		break;
    441 	case DRIVER_UNKNOWN:
    442 		devfsadm_print(debug_mid,
    443 		    "agp_process: unknown driver name=%s\n", drv_nm);
    444 		free(I_path);
    445 		free(p_path);
    446 		return (DEVFSADM_CONTINUE);
    447 	}
    448 
    449 	if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
    450 		devfsadm_print(debug_mid, "agp_process: exit/coninue\n");
    451 		free(I_path);
    452 		free(p_path);
    453 		return (DEVFSADM_CONTINUE);
    454 	}
    455 
    456 
    457 	(void) snprintf(I_path, PATH_MAX, "agp/%s%s", name, buf);
    458 
    459 	devfsadm_print(debug_mid, "agp_process: p_path=%s buf=%s\n",
    460 	    p_path, buf);
    461 
    462 	free(buf);
    463 
    464 	devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
    465 
    466 	(void) devfsadm_mklink(I_path, node, minor, 0);
    467 
    468 	free(p_path);
    469 	free(I_path);
    470 
    471 	return (DEVFSADM_CONTINUE);
    472 }
    473 
    474 static int
    475 drm_node(di_minor_t minor, di_node_t node)
    476 {
    477 	char *minor_nm, *drv_nm;
    478 	char *devfspath;
    479 	char *I_path, *p_path, *buf;
    480 	char *name = "card";
    481 
    482 	devfsadm_enumerate_t drm_rules[1] = {"^dri$/^card([0-9]+)$", 1,
    483 		MATCH_ALL };
    484 
    485 
    486 	minor_nm = di_minor_name(minor);
    487 	drv_nm = di_driver_name(node);
    488 	if ((minor_nm == NULL) || (drv_nm == NULL)) {
    489 		return (DEVFSADM_CONTINUE);
    490 	}
    491 
    492 	devfsadm_print(debug_mid, "drm_node: minor=%s node=%s type=%s\n",
    493 	    minor_nm, di_node_name(node), di_minor_nodetype(minor));
    494 
    495 	devfspath = di_devfs_path(node);
    496 	if (devfspath == NULL) {
    497 		devfsadm_print(debug_mid, "drm_node: devfspath is NULL\n");
    498 		return (DEVFSADM_CONTINUE);
    499 	}
    500 
    501 	I_path = (char *)malloc(PATH_MAX);
    502 
    503 	if (I_path == NULL) {
    504 		di_devfs_path_free(devfspath);
    505 		devfsadm_print(debug_mid,  "drm_node: malloc failed\n");
    506 		return (DEVFSADM_CONTINUE);
    507 	}
    508 
    509 	p_path = (char *)malloc(PATH_MAX);
    510 
    511 	if (p_path == NULL) {
    512 		devfsadm_print(debug_mid,  "drm_node: malloc failed\n");
    513 		di_devfs_path_free(devfspath);
    514 		free(I_path);
    515 		return (DEVFSADM_CONTINUE);
    516 	}
    517 
    518 	(void) strlcpy(p_path, devfspath, PATH_MAX);
    519 	(void) strlcat(p_path, ":", PATH_MAX);
    520 	(void) strlcat(p_path, minor_nm, PATH_MAX);
    521 	di_devfs_path_free(devfspath);
    522 
    523 	devfsadm_print(debug_mid, "drm_node: p_path %s\n", p_path);
    524 
    525 	if (devfsadm_enumerate_int(p_path, 0, &buf, drm_rules, 1)) {
    526 		free(p_path);
    527 		devfsadm_print(debug_mid, "drm_node: exit/coninue\n");
    528 		return (DEVFSADM_CONTINUE);
    529 	}
    530 	(void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, buf);
    531 
    532 	devfsadm_print(debug_mid, "drm_node: p_path=%s buf=%s\n",
    533 	    p_path, buf);
    534 
    535 	free(buf);
    536 
    537 	devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
    538 	(void) devfsadm_mklink(I_path, node, minor, 0);
    539 
    540 	free(p_path);
    541 	free(I_path);
    542 
    543 	return (0);
    544 }
    545 
    546 /*
    547  * /dev/mc/mc<chipid> -> /devices/.../pci1022,1102@<chipid+24>,2:mc-amd
    548  */
    549 static int
    550 mc_node(di_minor_t minor, di_node_t node)
    551 {
    552 	const char *minorname = di_minor_name(minor);
    553 	const char *busaddr = di_bus_addr(node);
    554 	char linkpath[PATH_MAX];
    555 	int unitaddr;
    556 	char *c;
    557 
    558 	if (minorname == NULL || busaddr == NULL)
    559 		return (DEVFSADM_CONTINUE);
    560 
    561 	errno = 0;
    562 	unitaddr = strtol(busaddr, &c, 16);
    563 
    564 	if (errno != 0)
    565 		return (DEVFSADM_CONTINUE);
    566 
    567 	if (unitaddr == 0) {
    568 		(void) snprintf(linkpath, sizeof (linkpath), "mc/mc");
    569 	} else if (unitaddr >= MC_AMD_DEV_OFFSET) {
    570 		(void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
    571 		    unitaddr - MC_AMD_DEV_OFFSET);
    572 	} else {
    573 		(void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
    574 		    minor->dev_minor);
    575 	}
    576 	(void) devfsadm_mklink(linkpath, node, minor, 0);
    577 	return (DEVFSADM_CONTINUE);
    578 }
    579 
    580 /*
    581  * Creates \M0 devlink for xsvc node
    582  */
    583 static int
    584 xsvc(di_minor_t minor, di_node_t node)
    585 {
    586 	char *mn;
    587 
    588 	if (strcmp(di_node_name(node), "xsvc") != 0)
    589 		return (DEVFSADM_CONTINUE);
    590 
    591 	mn = di_minor_name(minor);
    592 	if (mn == NULL)
    593 		return (DEVFSADM_CONTINUE);
    594 
    595 	(void) devfsadm_mklink(mn, node, minor, 0);
    596 	return (DEVFSADM_CONTINUE);
    597 }
    598 
    599 /*
    600  * Creates \M0 devlink for srn device
    601  */
    602 static int
    603 srn(di_minor_t minor, di_node_t node)
    604 {
    605 	char *mn;
    606 
    607 	if (strcmp(di_node_name(node), "srn") != 0)
    608 		return (DEVFSADM_CONTINUE);
    609 
    610 	mn = di_minor_name(minor);
    611 	if (mn == NULL)
    612 		return (DEVFSADM_CONTINUE);
    613 
    614 	(void) devfsadm_mklink(mn, node, minor, 0);
    615 	return (DEVFSADM_CONTINUE);
    616 }
    617 
    618 /*
    619  *	/dev/ucode	->	/devices/pseudo/ucode@0:ucode
    620  */
    621 static int
    622 ucode(di_minor_t minor, di_node_t node)
    623 {
    624 	(void) devfsadm_mklink("ucode", node, minor, 0);
    625 	return (DEVFSADM_CONTINUE);
    626 }
    627 
    628 static int
    629 heci(di_minor_t minor, di_node_t node)
    630 {
    631 	if (strcmp(di_minor_name(minor), "AMT") == 0) {
    632 		(void) devfsadm_mklink("heci", node, minor, 0);
    633 	}
    634 	return (DEVFSADM_CONTINUE);
    635 }
    636