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