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 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <regex.h> 29 #include <devfsadm.h> 30 #include <stdio.h> 31 #include <strings.h> 32 #include <stdlib.h> 33 #include <limits.h> 34 #include <sys/zone.h> 35 #include <sys/zcons.h> 36 #include <sys/cpuid_drv.h> 37 38 static int display(di_minor_t minor, di_node_t node); 39 static int parallel(di_minor_t minor, di_node_t node); 40 static int node_slash_minor(di_minor_t minor, di_node_t node); 41 static int driver_minor(di_minor_t minor, di_node_t node); 42 static int node_name(di_minor_t minor, di_node_t node); 43 static int minor_name(di_minor_t minor, di_node_t node); 44 static int wifi_minor_name(di_minor_t minor, di_node_t node); 45 static int conskbd(di_minor_t minor, di_node_t node); 46 static int consms(di_minor_t minor, di_node_t node); 47 static int power_button(di_minor_t minor, di_node_t node); 48 static int fc_port(di_minor_t minor, di_node_t node); 49 static int printer_create(di_minor_t minor, di_node_t node); 50 static int se_hdlc_create(di_minor_t minor, di_node_t node); 51 static int ppm(di_minor_t minor, di_node_t node); 52 static int gpio(di_minor_t minor, di_node_t node); 53 static int av_create(di_minor_t minor, di_node_t node); 54 static int tsalarm_create(di_minor_t minor, di_node_t node); 55 static int ntwdt_create(di_minor_t minor, di_node_t node); 56 static int zcons_create(di_minor_t minor, di_node_t node); 57 static int cpuid(di_minor_t minor, di_node_t node); 58 static int glvc(di_minor_t minor, di_node_t node); 59 static int ses_callback(di_minor_t minor, di_node_t node); 60 static int kmdrv_create(di_minor_t minor, di_node_t node); 61 62 static devfsadm_create_t misc_cbt[] = { 63 { "pseudo", "ddi_pseudo", "(^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$)|(^physmem$)", 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 "(^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, kmdrv_create, 150 }, 151 { "pseudo", "ddi_pseudo", "oplkmdrv", 152 TYPE_EXACT | DRV_RE, ILEVEL_0, kmdrv_create, 153 }, 154 { "av", "^ddi_av:(isoch|async)$", NULL, 155 TYPE_RE, ILEVEL_0, av_create, 156 }, 157 { "pseudo", "ddi_pseudo", "tsalarm", 158 TYPE_EXACT | DRV_RE, ILEVEL_0, tsalarm_create, 159 }, 160 { "pseudo", "ddi_pseudo", "ntwdt", 161 TYPE_EXACT | DRV_RE, ILEVEL_0, ntwdt_create, 162 }, 163 { "pseudo", "ddi_pseudo", "daplt", 164 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name 165 }, 166 { "pseudo", "ddi_pseudo", "zcons", 167 TYPE_EXACT | DRV_EXACT, ILEVEL_0, zcons_create, 168 }, 169 { "pseudo", "ddi_pseudo", CPUID_DRIVER_NAME, 170 TYPE_EXACT | DRV_EXACT, ILEVEL_0, cpuid, 171 }, 172 { "pseudo", "ddi_pseudo", "glvc", 173 TYPE_EXACT | DRV_EXACT, ILEVEL_0, glvc, 174 }, 175 { "pseudo", "ddi_pseudo", "dm2s", 176 TYPE_EXACT | DRV_EXACT, ILEVEL_0, minor_name, 177 }, 178 }; 179 180 DEVFSADM_CREATE_INIT_V0(misc_cbt); 181 182 static devfsadm_remove_t misc_remove_cbt[] = { 183 { "pseudo", "^profile$", 184 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 185 }, 186 { "pseudo", "^rsm$", 187 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 188 }, 189 { "printer", "^printers/[0-9]+$", 190 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 191 }, 192 { "av", "^av/[0-9]+/(async|isoch)$", 193 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 194 }, 195 { "pseudo", "^daplt$", 196 RM_PRE | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 197 }, 198 { "pseudo", "^zcons/" ZONENAME_REGEXP "/(" ZCONS_MASTER_NAME "|" 199 ZCONS_SLAVE_NAME ")$", 200 RM_PRE | RM_HOT | RM_ALWAYS, ILEVEL_0, devfsadm_rm_all 201 }, 202 { "pseudo", "^cpu/self/cpuid$", RM_ALWAYS | RM_PRE | RM_HOT, 203 ILEVEL_0, devfsadm_rm_all 204 }, 205 { "enclosure", "^es/ses[0-9]+$", RM_POST, 206 ILEVEL_0, devfsadm_rm_all 207 } 208 }; 209 210 /* Rules for gpio devices */ 211 static devfsadm_enumerate_t gpio_rules[1] = 212 {"^gpio([0-9]+)$", 1, MATCH_ALL}; 213 214 DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt); 215 216 /* 217 * Handles minor node type "ddi_display". 218 * 219 * type=ddi_display fbs/\M0 fb\N0 220 */ 221 static int 222 display(di_minor_t minor, di_node_t node) 223 { 224 char l_path[PATH_MAX + 1], contents[PATH_MAX + 1], *buf; 225 devfsadm_enumerate_t rules[1] = {"^fb([0-9]+)$", 1, MATCH_ALL}; 226 char *mn = di_minor_name(minor); 227 228 /* create fbs/\M0 primary link */ 229 (void) strcpy(l_path, "fbs/"); 230 (void) strcat(l_path, mn); 231 (void) devfsadm_mklink(l_path, node, minor, 0); 232 233 /* create fb\N0 which links to fbs/\M0 */ 234 if (devfsadm_enumerate_int(l_path, 0, &buf, rules, 1)) { 235 return (DEVFSADM_CONTINUE); 236 } 237 (void) strcpy(contents, l_path); 238 (void) strcpy(l_path, "fb"); 239 (void) strcat(l_path, buf); 240 free(buf); 241 (void) devfsadm_secondary_link(l_path, contents, 0); 242 return (DEVFSADM_CONTINUE); 243 } 244 245 /* 246 * Handles minor node type "ddi_parallel". 247 * type=ddi_parallel;name=mcpp mcpp\N0 248 */ 249 static int 250 parallel(di_minor_t minor, di_node_t node) 251 { 252 char path[PATH_MAX + 1], *buf; 253 devfsadm_enumerate_t rules[1] = {"mcpp([0-9]+)$", 1, MATCH_ALL}; 254 255 256 if (strcmp(di_node_name(node), "mcpp") != 0) { 257 return (DEVFSADM_CONTINUE); 258 } 259 260 if (NULL == (buf = di_devfs_path(node))) { 261 return (DEVFSADM_CONTINUE); 262 } 263 264 (void) snprintf(path, sizeof (path), "%s:%s", 265 buf, di_minor_name(minor)); 266 267 di_devfs_path_free(buf); 268 269 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) { 270 return (DEVFSADM_CONTINUE); 271 } 272 (void) snprintf(path, sizeof (path), "mcpp%s", buf); 273 free(buf); 274 275 (void) devfsadm_mklink(path, node, minor, 0); 276 return (DEVFSADM_CONTINUE); 277 } 278 279 static int 280 ses_callback(di_minor_t minor, di_node_t node) 281 { 282 char l_path[PATH_MAX]; 283 char *buf; 284 char *devfspath; 285 char p_path[PATH_MAX]; 286 devfsadm_enumerate_t re[] = {"^es$/^ses([0-9]+)$", 1, MATCH_ALL}; 287 288 /* find devices path -- need to free mem */ 289 if (NULL == (devfspath = di_devfs_path(node))) { 290 return (DEVFSADM_CONTINUE); 291 } 292 293 (void) snprintf(p_path, sizeof (p_path), "%s:%s", devfspath, 294 di_minor_name(minor)); 295 296 297 /* find next number to use; buf is an ascii number */ 298 if (devfsadm_enumerate_int(p_path, 0, &buf, re, 1)) { 299 /* free memory */ 300 di_devfs_path_free(devfspath); 301 return (DEVFSADM_CONTINUE); 302 } 303 304 (void) snprintf(l_path, sizeof (l_path), "es/ses%s", buf); 305 306 (void) devfsadm_mklink(l_path, node, minor, 0); 307 /* free memory */ 308 free(buf); 309 di_devfs_path_free(devfspath); 310 return (DEVFSADM_CONTINUE); 311 312 } 313 314 static int 315 node_slash_minor(di_minor_t minor, di_node_t node) 316 { 317 318 char path[PATH_MAX + 1]; 319 320 (void) strcpy(path, di_node_name(node)); 321 (void) strcat(path, "/"); 322 (void) strcat(path, di_minor_name(minor)); 323 (void) devfsadm_mklink(path, node, minor, 0); 324 return (DEVFSADM_CONTINUE); 325 } 326 327 static int 328 driver_minor(di_minor_t minor, di_node_t node) 329 { 330 char path[PATH_MAX + 1]; 331 332 (void) strcpy(path, di_driver_name(node)); 333 (void) strcat(path, di_minor_name(minor)); 334 (void) devfsadm_mklink(path, node, minor, 0); 335 return (DEVFSADM_CONTINUE); 336 } 337 338 /* 339 * Handles links of the form: 340 * type=ddi_pseudo;name=xyz \D 341 */ 342 static int 343 node_name(di_minor_t minor, di_node_t node) 344 { 345 (void) devfsadm_mklink(di_node_name(node), node, minor, 0); 346 return (DEVFSADM_CONTINUE); 347 } 348 349 /* 350 * Handles links of the form: 351 * type=ddi_pseudo;name=xyz \M0 352 */ 353 static int 354 minor_name(di_minor_t minor, di_node_t node) 355 { 356 char *mn = di_minor_name(minor); 357 358 (void) devfsadm_mklink(mn, node, minor, 0); 359 if (strcmp(mn, "icmp") == 0) { 360 (void) devfsadm_mklink("rawip", node, minor, 0); 361 } 362 if (strcmp(mn, "icmp6") == 0) { 363 (void) devfsadm_mklink("rawip6", node, minor, 0); 364 } 365 if (strcmp(mn, "ipf") == 0) { 366 (void) devfsadm_mklink("ipl", node, minor, 0); 367 } 368 return (DEVFSADM_CONTINUE); 369 } 370 371 /* 372 * create links at /dev/wifi for wifi minor node 373 */ 374 static int 375 wifi_minor_name(di_minor_t minor, di_node_t node) 376 { 377 char buf[256]; 378 char *mn = di_minor_name(minor); 379 380 (void) snprintf(buf, sizeof (buf), "%s%s", "wifi/", mn); 381 (void) devfsadm_mklink(buf, node, minor, 0); 382 383 return (DEVFSADM_CONTINUE); 384 } 385 386 static int 387 conskbd(di_minor_t minor, di_node_t node) 388 { 389 (void) devfsadm_mklink("kbd", node, minor, 0); 390 return (DEVFSADM_CONTINUE); 391 } 392 393 static int 394 consms(di_minor_t minor, di_node_t node) 395 { 396 (void) devfsadm_mklink("mouse", node, minor, 0); 397 return (DEVFSADM_CONTINUE); 398 } 399 400 static int 401 power_button(di_minor_t minor, di_node_t node) 402 { 403 (void) devfsadm_mklink("power_button", node, minor, 0); 404 return (DEVFSADM_CONTINUE); 405 } 406 407 static int 408 fc_port(di_minor_t minor, di_node_t node) 409 { 410 devfsadm_enumerate_t rules[1] = {"fc/fp([0-9]+)$", 1, MATCH_ALL}; 411 char *buf, path[PATH_MAX + 1]; 412 char *ptr; 413 414 if (NULL == (ptr = di_devfs_path(node))) { 415 return (DEVFSADM_CONTINUE); 416 } 417 418 (void) strcpy(path, ptr); 419 (void) strcat(path, ":"); 420 (void) strcat(path, di_minor_name(minor)); 421 422 di_devfs_path_free(ptr); 423 424 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) { 425 return (DEVFSADM_CONTINUE); 426 } 427 428 (void) strcpy(path, "fc/fp"); 429 (void) strcat(path, buf); 430 free(buf); 431 432 (void) devfsadm_mklink(path, node, minor, 0); 433 return (DEVFSADM_CONTINUE); 434 } 435 436 /* 437 * Handles: 438 * minor node type "ddi_printer". 439 * rules of the form: type=ddi_printer;name=bpp \M0 440 */ 441 static int 442 printer_create(di_minor_t minor, di_node_t node) 443 { 444 char *mn; 445 char path[PATH_MAX + 1], *buf; 446 devfsadm_enumerate_t rules[1] = {"^printers$/^([0-9]+)$", 1, MATCH_ALL}; 447 448 mn = di_minor_name(minor); 449 450 if (strcmp(di_driver_name(node), "bpp") == 0) { 451 (void) devfsadm_mklink(mn, node, minor, 0); 452 } 453 454 if (NULL == (buf = di_devfs_path(node))) { 455 return (DEVFSADM_CONTINUE); 456 } 457 458 (void) snprintf(path, sizeof (path), "%s:%s", buf, mn); 459 di_devfs_path_free(buf); 460 461 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) { 462 return (DEVFSADM_CONTINUE); 463 } 464 465 (void) snprintf(path, sizeof (path), "printers/%s", buf); 466 free(buf); 467 468 (void) devfsadm_mklink(path, node, minor, 0); 469 470 return (DEVFSADM_CONTINUE); 471 } 472 473 /* 474 * Handles links of the form: 475 * type=ddi_pseudo;name=se;minor2=hdlc se_hdlc\N0 476 * type=ddi_pseudo;name=serial;minor2=hdlc se_hdlc\N0 477 */ 478 static int 479 se_hdlc_create(di_minor_t minor, di_node_t node) 480 { 481 devfsadm_enumerate_t rules[1] = {"^se_hdlc([0-9]+)$", 1, MATCH_ALL}; 482 char *buf, path[PATH_MAX + 1]; 483 char *ptr; 484 char *mn; 485 486 mn = di_minor_name(minor); 487 488 /* minor node should be of the form: "?,hdlc" */ 489 if (strcmp(mn + 1, ",hdlc") != 0) { 490 return (DEVFSADM_CONTINUE); 491 } 492 493 if (NULL == (ptr = di_devfs_path(node))) { 494 return (DEVFSADM_CONTINUE); 495 } 496 497 (void) strcpy(path, ptr); 498 (void) strcat(path, ":"); 499 (void) strcat(path, mn); 500 501 di_devfs_path_free(ptr); 502 503 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1) != 0) { 504 return (DEVFSADM_CONTINUE); 505 } 506 507 (void) strcpy(path, "se_hdlc"); 508 (void) strcat(path, buf); 509 free(buf); 510 511 (void) devfsadm_mklink(path, node, minor, 0); 512 513 return (DEVFSADM_CONTINUE); 514 } 515 516 static int 517 gpio(di_minor_t minor, di_node_t node) 518 { 519 char l_path[PATH_MAX], p_path[PATH_MAX], *buf, *devfspath; 520 char *minor_nm, *drvr_nm; 521 522 523 minor_nm = di_minor_name(minor); 524 drvr_nm = di_driver_name(node); 525 if ((minor_nm == NULL) || (drvr_nm == NULL)) { 526 return (DEVFSADM_CONTINUE); 527 } 528 529 devfspath = di_devfs_path(node); 530 531 (void) strcpy(p_path, devfspath); 532 (void) strcat(p_path, ":"); 533 (void) strcat(p_path, minor_nm); 534 di_devfs_path_free(devfspath); 535 536 /* build the physical path from the components */ 537 if (devfsadm_enumerate_int(p_path, 0, &buf, gpio_rules, 1)) { 538 return (DEVFSADM_CONTINUE); 539 } 540 541 (void) snprintf(l_path, sizeof (l_path), "%s%s", "gpio", buf); 542 543 free(buf); 544 545 (void) devfsadm_mklink(l_path, node, minor, 0); 546 547 return (DEVFSADM_CONTINUE); 548 } 549 550 /* 551 * Creates /dev/ppm nodes for Platform Specific PM module 552 */ 553 static int 554 ppm(di_minor_t minor, di_node_t node) 555 { 556 (void) devfsadm_mklink("ppm", node, minor, 0); 557 return (DEVFSADM_CONTINUE); 558 } 559 560 /* 561 * Handles: 562 * /dev/av/[0-9]+/(async|isoch) 563 */ 564 static int 565 av_create(di_minor_t minor, di_node_t node) 566 { 567 devfsadm_enumerate_t rules[1] = {"^av$/^([0-9]+)$", 1, MATCH_ADDR}; 568 char *minor_str; 569 char path[PATH_MAX + 1]; 570 char *buf; 571 572 if ((buf = di_devfs_path(node)) == NULL) { 573 return (DEVFSADM_CONTINUE); 574 } 575 576 minor_str = di_minor_name(minor); 577 (void) snprintf(path, sizeof (path), "%s:%s", buf, minor_str); 578 di_devfs_path_free(buf); 579 580 if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) { 581 return (DEVFSADM_CONTINUE); 582 } 583 584 (void) snprintf(path, sizeof (path), "av/%s/%s", buf, minor_str); 585 free(buf); 586 587 (void) devfsadm_mklink(path, node, minor, 0); 588 589 return (DEVFSADM_CONTINUE); 590 } 591 592 /* 593 * Creates /dev/lom and /dev/tsalarm:ctl for tsalarm node 594 */ 595 static int 596 tsalarm_create(di_minor_t minor, di_node_t node) 597 { 598 char buf[PATH_MAX + 1]; 599 char *mn = di_minor_name(minor); 600 601 (void) snprintf(buf, sizeof (buf), "%s%s", di_node_name(node), ":ctl"); 602 603 (void) devfsadm_mklink(mn, node, minor, 0); 604 (void) devfsadm_mklink(buf, node, minor, 0); 605 606 return (DEVFSADM_CONTINUE); 607 } 608 609 /* 610 * Creates /dev/ntwdt for ntwdt node 611 */ 612 static int 613 ntwdt_create(di_minor_t minor, di_node_t node) 614 { 615 (void) devfsadm_mklink("ntwdt", node, minor, 0); 616 return (DEVFSADM_CONTINUE); 617 } 618 619 static int 620 zcons_create(di_minor_t minor, di_node_t node) 621 { 622 char *minor_str; 623 char *zonename; 624 char path[MAXPATHLEN]; 625 626 minor_str = di_minor_name(minor); 627 628 if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "zonename", 629 &zonename) == -1) { 630 return (DEVFSADM_CONTINUE); 631 } 632 633 (void) snprintf(path, sizeof (path), "zcons/%s/%s", zonename, 634 minor_str); 635 (void) devfsadm_mklink(path, node, minor, 0); 636 637 return (DEVFSADM_CONTINUE); 638 } 639 640 /* 641 * /dev/cpu/self/cpuid -> /devices/pseudo/cpuid@0:self 642 */ 643 static int 644 cpuid(di_minor_t minor, di_node_t node) 645 { 646 (void) devfsadm_mklink(CPUID_SELF_NAME, node, minor, 0); 647 return (DEVFSADM_CONTINUE); 648 } 649 650 /* 651 * For device 652 * /dev/spfma -> /devices/virtual-devices/fma@5:glvc 653 */ 654 static int 655 glvc(di_minor_t minor, di_node_t node) 656 { 657 char node_name[MAXNAMELEN + 1]; 658 659 (void) strcpy(node_name, di_node_name(node)); 660 661 if (strncmp(node_name, "fma", 3) == 0) { 662 /* Only one fma channel */ 663 (void) devfsadm_mklink("spfma", node, minor, 0); 664 } 665 return (DEVFSADM_CONTINUE); 666 } 667 668 /* 669 * Handles links of the form: 670 * type=ddi_pseudo;name=sckmdrv kmdrv\M0 671 * type=ddi_pseudo;name=oplkmdrv kmdrv\M0 672 */ 673 static int 674 kmdrv_create(di_minor_t minor, di_node_t node) 675 { 676 677 (void) devfsadm_mklink("kmdrv", node, minor, 0); 678 return (DEVFSADM_CONTINUE); 679 } 680