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