/usr/src/cmd/devfsadm/i386/misc_link_i386.c
C | 656 lines | 482 code | 101 blank | 73 comment | 100 complexity | 16cfe1a71aecc8288bcc1d79c9dc062e MD5 | raw file
Possible License(s): BSD-3-Clause-No-Nuclear-License-2014, AGPL-1.0, AGPL-3.0, GPL-2.0, GPL-3.0, BSD-2-Clause, MPL-2.0-no-copyleft-exception, BSD-3-Clause, LGPL-2.1, LGPL-3.0, LGPL-2.0, 0BSD
- /*
- * CDDL HEADER START
- *
- * The contents of this file are subject to the terms of the
- * Common Development and Distribution License (the "License").
- * You may not use this file except in compliance with the License.
- *
- * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
- * or http://www.opensolaris.org/os/licensing.
- * See the License for the specific language governing permissions
- * and limitations under the License.
- *
- * When distributing Covered Code, include this CDDL HEADER in each
- * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
- * If applicable, add the following below this CDDL HEADER, with the
- * fields enclosed by brackets "[]" replaced with your own identifying
- * information: Portions Copyright [yyyy] [name of copyright owner]
- *
- * CDDL HEADER END
- */
- /*
- * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
- * Use is subject to license terms.
- * Copyright 2012 Joyent, Inc. All rights reserved.
- */
- #include <regex.h>
- #include <devfsadm.h>
- #include <stdio.h>
- #include <strings.h>
- #include <stdlib.h>
- #include <limits.h>
- #include <ctype.h>
- #include <sys/mc_amd.h>
- #include <bsm/devalloc.h>
- extern int system_labeled;
- static int lp(di_minor_t minor, di_node_t node);
- static int serial_dialout(di_minor_t minor, di_node_t node);
- static int serial(di_minor_t minor, di_node_t node);
- static int diskette(di_minor_t minor, di_node_t node);
- static int vt00(di_minor_t minor, di_node_t node);
- static int kdmouse(di_minor_t minor, di_node_t node);
- static int ipmi(di_minor_t minor, di_node_t node);
- static int smbios(di_minor_t minor, di_node_t node);
- static int agp_process(di_minor_t minor, di_node_t node);
- static int drm_node(di_minor_t minor, di_node_t node);
- static int mc_node(di_minor_t minor, di_node_t node);
- static int xsvc(di_minor_t minor, di_node_t node);
- static int srn(di_minor_t minor, di_node_t node);
- static int ucode(di_minor_t minor, di_node_t node);
- static int heci(di_minor_t minor, di_node_t node);
- static devfsadm_create_t misc_cbt[] = {
- { "vt00", "ddi_display", NULL,
- TYPE_EXACT, ILEVEL_0, vt00
- },
- { "drm", "ddi_display:drm", NULL,
- TYPE_EXACT, ILEVEL_0, drm_node
- },
- { "mouse", "ddi_mouse", "mouse8042",
- TYPE_EXACT | DRV_EXACT, ILEVEL_0, kdmouse
- },
- { "pseudo", "ddi_pseudo", "ipmi",
- TYPE_EXACT | DRV_EXACT, ILEVEL_0, ipmi,
- },
- { "pseudo", "ddi_pseudo", "smbios",
- TYPE_EXACT | DRV_EXACT, ILEVEL_1, smbios,
- },
- /* floppies share the same class, but not link regex, as hard disks */
- { "disk", "ddi_block:diskette", NULL,
- TYPE_EXACT, ILEVEL_1, diskette
- },
- { "parallel", "ddi_printer", NULL,
- TYPE_EXACT, ILEVEL_1, lp
- },
- { "serial", "ddi_serial:mb", NULL,
- TYPE_EXACT, ILEVEL_1, serial
- },
- { "serial", "ddi_serial:dialout,mb", NULL,
- TYPE_EXACT, ILEVEL_1, serial_dialout
- },
- { "agp", "ddi_agp:pseudo", NULL,
- TYPE_EXACT, ILEVEL_0, agp_process
- },
- { "agp", "ddi_agp:target", NULL,
- TYPE_EXACT, ILEVEL_0, agp_process
- },
- { "agp", "ddi_agp:cpugart", NULL,
- TYPE_EXACT, ILEVEL_0, agp_process
- },
- { "agp", "ddi_agp:master", NULL,
- TYPE_EXACT, ILEVEL_0, agp_process
- },
- { "pseudo", "ddi_pseudo", NULL,
- TYPE_EXACT, ILEVEL_0, xsvc
- },
- { "pseudo", "ddi_pseudo", NULL,
- TYPE_EXACT, ILEVEL_0, srn
- },
- { "memory-controller", "ddi_mem_ctrl", NULL,
- TYPE_EXACT, ILEVEL_0, mc_node
- },
- { "pseudo", "ddi_pseudo", "ucode",
- TYPE_EXACT | DRV_EXACT, ILEVEL_0, ucode,
- },
- { "pseudo", "ddi_pseudo", "heci",
- TYPE_EXACT | DRV_EXACT, ILEVEL_0, heci,
- }
- };
- DEVFSADM_CREATE_INIT_V0(misc_cbt);
- static char *debug_mid = "misc_mid";
- typedef enum {
- DRIVER_AGPPSEUDO = 0,
- DRIVER_AGPTARGET,
- DRIVER_CPUGART,
- DRIVER_AGPMASTER_DRM_I915,
- DRIVER_AGPMASTER_DRM_RADEON,
- DRIVER_AGPMASTER_VGATEXT,
- DRIVER_UNKNOWN
- } driver_defs_t;
- typedef struct {
- char *driver_name;
- int index;
- } driver_name_table_entry_t;
- static driver_name_table_entry_t driver_name_table[] = {
- { "agpgart", DRIVER_AGPPSEUDO },
- { "agptarget", DRIVER_AGPTARGET },
- { "amd64_gart", DRIVER_CPUGART },
- /* AGP master device managed by drm driver */
- { "i915", DRIVER_AGPMASTER_DRM_I915 },
- { "radeon", DRIVER_AGPMASTER_DRM_RADEON },
- { "vgatext", DRIVER_AGPMASTER_VGATEXT },
- { NULL, DRIVER_UNKNOWN }
- };
- static devfsadm_enumerate_t agptarget_rules[1] =
- { "^agp$/^agptarget([0-9]+)$", 1, MATCH_ALL };
- static devfsadm_enumerate_t cpugart_rules[1] =
- { "^agp$/^cpugart([0-9]+)$", 1, MATCH_ALL };
- static devfsadm_enumerate_t agpmaster_rules[1] =
- { "^agp$/^agpmaster([0-9]+)$", 1, MATCH_ALL };
- static devfsadm_remove_t misc_remove_cbt[] = {
- { "vt", "vt[0-9][0-9]", RM_PRE|RM_ALWAYS,
- ILEVEL_0, devfsadm_rm_all
- },
- { "pseudo", "^ucode$", RM_ALWAYS | RM_PRE | RM_HOT,
- ILEVEL_0, devfsadm_rm_all
- },
- { "mouse", "^kdmouse$", RM_ALWAYS | RM_PRE,
- ILEVEL_0, devfsadm_rm_all
- },
- { "disk", "^(diskette|rdiskette)([0-9]*)$",
- RM_ALWAYS | RM_PRE, ILEVEL_1, devfsadm_rm_all
- },
- { "parallel", "^(lp|ecpp)([0-9]+)$", RM_ALWAYS | RM_PRE,
- ILEVEL_1, devfsadm_rm_all
- },
- { "serial", "^(tty|ttyd)([0-9]+)$", RM_ALWAYS | RM_PRE,
- ILEVEL_1, devfsadm_rm_all
- },
- { "serial", "^tty[a-z]$", RM_ALWAYS | RM_PRE,
- ILEVEL_1, devfsadm_rm_all
- }
- };
- DEVFSADM_REMOVE_INIT_V0(misc_remove_cbt);
- /*
- * Handles minor node type "ddi_display", in addition to generic processing
- * done by display().
- *
- * This creates a /dev/vt00 link to /dev/fb, for backwards compatibility.
- */
- /* ARGSUSED */
- int
- vt00(di_minor_t minor, di_node_t node)
- {
- (void) devfsadm_secondary_link("vt00", "fb", 0);
- return (DEVFSADM_CONTINUE);
- }
- /*
- * type=ddi_block:diskette;addr=0,0;minor=c diskette
- * type=ddi_block:diskette;addr=0,0;minor=c,raw rdiskette
- * type=ddi_block:diskette;addr1=0;minor=c diskette\A2
- * type=ddi_block:diskette;addr1=0;minor=c,raw rdiskette\A2
- */
- static int
- diskette(di_minor_t minor, di_node_t node)
- {
- int flags = 0;
- char *a2;
- char link[PATH_MAX];
- char *addr = di_bus_addr(node);
- char *mn = di_minor_name(minor);
- if (system_labeled)
- flags = DA_ADD|DA_FLOPPY;
- if (strcmp(addr, "0,0") == 0) {
- if (strcmp(mn, "c") == 0) {
- (void) devfsadm_mklink("diskette", node, minor, flags);
- } else if (strcmp(mn, "c,raw") == 0) {
- (void) devfsadm_mklink("rdiskette", node, minor, flags);
- }
- }
- if (addr[0] == '0') {
- if ((a2 = strchr(addr, ',')) != NULL) {
- a2++;
- if (strcmp(mn, "c") == 0) {
- (void) strcpy(link, "diskette");
- (void) strcat(link, a2);
- (void) devfsadm_mklink(link, node, minor,
- flags);
- } else if (strcmp(mn, "c,raw") == 0) {
- (void) strcpy(link, "rdiskette");
- (void) strcat(link, a2);
- (void) devfsadm_mklink(link, node, minor,
- flags);
- }
- }
- }
- return (DEVFSADM_CONTINUE);
- }
- /*
- * type=ddi_printer;name=lp;addr=1,3bc lp0
- * type=ddi_printer;name=lp;addr=1,378 lp1
- * type=ddi_printer;name=lp;addr=1,278 lp2
- */
- static int
- lp(di_minor_t minor, di_node_t node)
- {
- char *addr = di_bus_addr(node);
- char *buf;
- char path[PATH_MAX + 1];
- devfsadm_enumerate_t rules[1] = {"^ecpp([0-9]+)$", 1, MATCH_ALL};
- if (strcmp(addr, "1,3bc") == 0) {
- (void) devfsadm_mklink("lp0", node, minor, 0);
- } else if (strcmp(addr, "1,378") == 0) {
- (void) devfsadm_mklink("lp1", node, minor, 0);
- } else if (strcmp(addr, "1,278") == 0) {
- (void) devfsadm_mklink("lp2", node, minor, 0);
- }
- if (strcmp(di_driver_name(node), "ecpp") != 0) {
- return (DEVFSADM_CONTINUE);
- }
- if ((buf = di_devfs_path(node)) == NULL) {
- return (DEVFSADM_CONTINUE);
- }
- (void) snprintf(path, sizeof (path), "%s:%s",
- buf, di_minor_name(minor));
- di_devfs_path_free(buf);
- if (devfsadm_enumerate_int(path, 0, &buf, rules, 1)) {
- return (DEVFSADM_CONTINUE);
- }
- (void) snprintf(path, sizeof (path), "ecpp%s", buf);
- free(buf);
- (void) devfsadm_mklink(path, node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- /*
- * type=ddi_serial:mb;minor=a tty00
- * type=ddi_serial:mb;minor=b tty01
- * type=ddi_serial:mb;minor=c tty02
- * type=ddi_serial:mb;minor=d tty03
- */
- static int
- serial(di_minor_t minor, di_node_t node)
- {
- char *mn = di_minor_name(minor);
- char link[PATH_MAX];
- (void) strcpy(link, "tty");
- (void) strcat(link, mn);
- (void) devfsadm_mklink(link, node, minor, 0);
- if (strcmp(mn, "a") == 0) {
- (void) devfsadm_mklink("tty00", node, minor, 0);
- } else if (strcmp(mn, "b") == 0) {
- (void) devfsadm_mklink("tty01", node, minor, 0);
- } else if (strcmp(mn, "c") == 0) {
- (void) devfsadm_mklink("tty02", node, minor, 0);
- } else if (strcmp(mn, "d") == 0) {
- (void) devfsadm_mklink("tty03", node, minor, 0);
- }
- return (DEVFSADM_CONTINUE);
- }
- /*
- * type=ddi_serial:dialout,mb;minor=a,cu ttyd0
- * type=ddi_serial:dialout,mb;minor=b,cu ttyd1
- * type=ddi_serial:dialout,mb;minor=c,cu ttyd2
- * type=ddi_serial:dialout,mb;minor=d,cu ttyd3
- */
- static int
- serial_dialout(di_minor_t minor, di_node_t node)
- {
- char *mn = di_minor_name(minor);
- if (strcmp(mn, "a,cu") == 0) {
- (void) devfsadm_mklink("ttyd0", node, minor, 0);
- (void) devfsadm_mklink("cua0", node, minor, 0);
- } else if (strcmp(mn, "b,cu") == 0) {
- (void) devfsadm_mklink("ttyd1", node, minor, 0);
- (void) devfsadm_mklink("cua1", node, minor, 0);
- } else if (strcmp(mn, "c,cu") == 0) {
- (void) devfsadm_mklink("ttyd2", node, minor, 0);
- (void) devfsadm_mklink("cua2", node, minor, 0);
- } else if (strcmp(mn, "d,cu") == 0) {
- (void) devfsadm_mklink("ttyd3", node, minor, 0);
- (void) devfsadm_mklink("cua3", node, minor, 0);
- }
- return (DEVFSADM_CONTINUE);
- }
- static int
- kdmouse(di_minor_t minor, di_node_t node)
- {
- (void) devfsadm_mklink("kdmouse", node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- static int
- ipmi(di_minor_t minor, di_node_t node)
- {
- /*
- * Follow convention from other systems, and include an instance#,
- * even though there will only be one.
- */
- (void) devfsadm_mklink("ipmi0", node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- static int
- smbios(di_minor_t minor, di_node_t node)
- {
- (void) devfsadm_mklink("smbios", node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- static int
- agp_process(di_minor_t minor, di_node_t node)
- {
- char *minor_nm, *drv_nm;
- char *devfspath;
- char *I_path, *p_path, *buf;
- char *name = (char *)NULL;
- int i, index;
- devfsadm_enumerate_t rules[1];
- minor_nm = di_minor_name(minor);
- drv_nm = di_driver_name(node);
- if ((minor_nm == NULL) || (drv_nm == NULL)) {
- return (DEVFSADM_CONTINUE);
- }
- devfsadm_print(debug_mid, "agp_process: minor=%s node=%s\n",
- minor_nm, di_node_name(node));
- devfspath = di_devfs_path(node);
- if (devfspath == NULL) {
- devfsadm_print(debug_mid, "agp_process: devfspath is NULL\n");
- return (DEVFSADM_CONTINUE);
- }
- I_path = (char *)malloc(PATH_MAX);
- if (I_path == NULL) {
- di_devfs_path_free(devfspath);
- devfsadm_print(debug_mid, "agp_process: malloc failed\n");
- return (DEVFSADM_CONTINUE);
- }
- p_path = (char *)malloc(PATH_MAX);
- if (p_path == NULL) {
- devfsadm_print(debug_mid, "agp_process: malloc failed\n");
- di_devfs_path_free(devfspath);
- free(I_path);
- return (DEVFSADM_CONTINUE);
- }
- (void) strlcpy(p_path, devfspath, PATH_MAX);
- (void) strlcat(p_path, ":", PATH_MAX);
- (void) strlcat(p_path, minor_nm, PATH_MAX);
- di_devfs_path_free(devfspath);
- devfsadm_print(debug_mid, "agp_process: path %s\n", p_path);
- for (i = 0; ; i++) {
- if ((driver_name_table[i].driver_name == NULL) ||
- (strcmp(drv_nm, driver_name_table[i].driver_name) == 0)) {
- index = driver_name_table[i].index;
- break;
- }
- }
- switch (index) {
- case DRIVER_AGPPSEUDO:
- devfsadm_print(debug_mid,
- "agp_process: psdeudo driver name\n");
- name = "agpgart";
- (void) snprintf(I_path, PATH_MAX, "%s", name);
- devfsadm_print(debug_mid,
- "mklink %s -> %s\n", I_path, p_path);
- (void) devfsadm_mklink(I_path, node, minor, 0);
- free(I_path);
- free(p_path);
- return (DEVFSADM_CONTINUE);
- case DRIVER_AGPTARGET:
- devfsadm_print(debug_mid,
- "agp_process: target driver name\n");
- rules[0] = agptarget_rules[0];
- name = "agptarget";
- break;
- case DRIVER_CPUGART:
- devfsadm_print(debug_mid,
- "agp_process: cpugart driver name\n");
- rules[0] = cpugart_rules[0];
- name = "cpugart";
- break;
- case DRIVER_AGPMASTER_DRM_I915:
- case DRIVER_AGPMASTER_DRM_RADEON:
- case DRIVER_AGPMASTER_VGATEXT:
- devfsadm_print(debug_mid,
- "agp_process: agpmaster driver name\n");
- rules[0] = agpmaster_rules[0];
- name = "agpmaster";
- break;
- case DRIVER_UNKNOWN:
- devfsadm_print(debug_mid,
- "agp_process: unknown driver name=%s\n", drv_nm);
- free(I_path);
- free(p_path);
- return (DEVFSADM_CONTINUE);
- }
- if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) {
- devfsadm_print(debug_mid, "agp_process: exit/coninue\n");
- free(I_path);
- free(p_path);
- return (DEVFSADM_CONTINUE);
- }
- (void) snprintf(I_path, PATH_MAX, "agp/%s%s", name, buf);
- devfsadm_print(debug_mid, "agp_process: p_path=%s buf=%s\n",
- p_path, buf);
- free(buf);
- devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
- (void) devfsadm_mklink(I_path, node, minor, 0);
- free(p_path);
- free(I_path);
- return (DEVFSADM_CONTINUE);
- }
- static int
- drm_node(di_minor_t minor, di_node_t node)
- {
- char *minor_nm, *drv_nm;
- char *devfspath;
- char *I_path, *p_path, *buf;
- char *name = "card";
- devfsadm_enumerate_t drm_rules[1] = {"^dri$/^card([0-9]+)$", 1,
- MATCH_ALL };
- minor_nm = di_minor_name(minor);
- drv_nm = di_driver_name(node);
- if ((minor_nm == NULL) || (drv_nm == NULL)) {
- return (DEVFSADM_CONTINUE);
- }
- devfsadm_print(debug_mid, "drm_node: minor=%s node=%s type=%s\n",
- minor_nm, di_node_name(node), di_minor_nodetype(minor));
- devfspath = di_devfs_path(node);
- if (devfspath == NULL) {
- devfsadm_print(debug_mid, "drm_node: devfspath is NULL\n");
- return (DEVFSADM_CONTINUE);
- }
- I_path = (char *)malloc(PATH_MAX);
- if (I_path == NULL) {
- di_devfs_path_free(devfspath);
- devfsadm_print(debug_mid, "drm_node: malloc failed\n");
- return (DEVFSADM_CONTINUE);
- }
- p_path = (char *)malloc(PATH_MAX);
- if (p_path == NULL) {
- devfsadm_print(debug_mid, "drm_node: malloc failed\n");
- di_devfs_path_free(devfspath);
- free(I_path);
- return (DEVFSADM_CONTINUE);
- }
- (void) strlcpy(p_path, devfspath, PATH_MAX);
- (void) strlcat(p_path, ":", PATH_MAX);
- (void) strlcat(p_path, minor_nm, PATH_MAX);
- di_devfs_path_free(devfspath);
- devfsadm_print(debug_mid, "drm_node: p_path %s\n", p_path);
- if (devfsadm_enumerate_int(p_path, 0, &buf, drm_rules, 1)) {
- free(p_path);
- devfsadm_print(debug_mid, "drm_node: exit/coninue\n");
- return (DEVFSADM_CONTINUE);
- }
- (void) snprintf(I_path, PATH_MAX, "dri/%s%s", name, buf);
- devfsadm_print(debug_mid, "drm_node: p_path=%s buf=%s\n",
- p_path, buf);
- free(buf);
- devfsadm_print(debug_mid, "mklink %s -> %s\n", I_path, p_path);
- (void) devfsadm_mklink(I_path, node, minor, 0);
- free(p_path);
- free(I_path);
- return (0);
- }
- /*
- * /dev/mc/mc<chipid> -> /devices/.../pci1022,1102@<chipid+24>,2:mc-amd
- */
- static int
- mc_node(di_minor_t minor, di_node_t node)
- {
- const char *minorname = di_minor_name(minor);
- const char *busaddr = di_bus_addr(node);
- char linkpath[PATH_MAX];
- int unitaddr;
- char *c;
- if (minorname == NULL || busaddr == NULL)
- return (DEVFSADM_CONTINUE);
- errno = 0;
- unitaddr = strtol(busaddr, &c, 16);
- if (errno != 0)
- return (DEVFSADM_CONTINUE);
- if (unitaddr == 0) {
- (void) snprintf(linkpath, sizeof (linkpath), "mc/mc");
- } else if (unitaddr >= MC_AMD_DEV_OFFSET) {
- (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
- unitaddr - MC_AMD_DEV_OFFSET);
- } else {
- (void) snprintf(linkpath, sizeof (linkpath), "mc/mc%u",
- minor->dev_minor);
- }
- (void) devfsadm_mklink(linkpath, node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- /*
- * Creates \M0 devlink for xsvc node
- */
- static int
- xsvc(di_minor_t minor, di_node_t node)
- {
- char *mn;
- if (strcmp(di_node_name(node), "xsvc") != 0)
- return (DEVFSADM_CONTINUE);
- mn = di_minor_name(minor);
- if (mn == NULL)
- return (DEVFSADM_CONTINUE);
- (void) devfsadm_mklink(mn, node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- /*
- * Creates \M0 devlink for srn device
- */
- static int
- srn(di_minor_t minor, di_node_t node)
- {
- char *mn;
- if (strcmp(di_node_name(node), "srn") != 0)
- return (DEVFSADM_CONTINUE);
- mn = di_minor_name(minor);
- if (mn == NULL)
- return (DEVFSADM_CONTINUE);
- (void) devfsadm_mklink(mn, node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- /*
- * /dev/ucode -> /devices/pseudo/ucode@0:ucode
- */
- static int
- ucode(di_minor_t minor, di_node_t node)
- {
- (void) devfsadm_mklink("ucode", node, minor, 0);
- return (DEVFSADM_CONTINUE);
- }
- static int
- heci(di_minor_t minor, di_node_t node)
- {
- if (strcmp(di_minor_name(minor), "AMT") == 0) {
- (void) devfsadm_mklink("heci", node, minor, 0);
- }
- return (DEVFSADM_CONTINUE);
- }