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