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