static int dm(di_minor_t minor, di_node_t node) { dev_t dev; minor_t minorno; char minorname[MAXNAMELEN + 1]; char dmname[MAXNAMELEN + 1]; char blkname[MAXNAMELEN + 1]; char rawname[MAXNAMELEN + 1]; char path[PATH_MAX + 1]; (void) strcpy(minorname, di_minor_name(minor)); dev = di_minor_devt(minor); minorno = minor(dev); /* Is it a control node ? */ if ((minorno == 0) && (strcmp(minorname, "ctl") == 0)) { (void) devfsadm_mklink(DM_CONTROL_NODE, node, minor, 0); (void) devfsadm_secondary_link(DM_CONTROL_LINUX, DM_CONTROL_NODE, 0); return (DEVFSADM_CONTINUE); } /* If we got here that is not a control node */ (void) strlcpy(dmname, sizeof (dmname), minorname); (void) snprintf(blkname, sizeof (blkname), "%s,blk", minorname); (void) snprintf(rawname, sizeof (rawname), "%s,raw", minorname); if (strcmp(mn, blkname) == 0) { (void) snprintf(path, sizeof (path), "%s/%s", DM_BLOCK_NAME, blkname); } else if (strcmp(mn, rawname) == 0) { (void) snprintf(path, sizeof (path), "%s/%s", DM_CHAR_NAME, blkname); } else { return (DEVFSADM_CONTINUE); } (void) devfsadm_mklink(path, node, minor, 0); return (DEVFSADM_CONTINUE); }
/* * Handles minor node type "ddi_display". * * type=ddi_display fbs/\M0 fb\N0 */ static int display(di_minor_t minor, di_node_t node) { char l_path[PATH_MAX + 1], contents[PATH_MAX + 1], *buf; devfsadm_enumerate_t rules[1] = {"^fb([0-9]+)$", 1, MATCH_ALL}; char *mn = di_minor_name(minor); /* create fbs/\M0 primary link */ (void) strcpy(l_path, "fbs/"); (void) strcat(l_path, mn); (void) devfsadm_mklink(l_path, node, minor, 0); /* create fb\N0 which links to fbs/\M0 */ if (devfsadm_enumerate_int(l_path, 0, &buf, rules, 1)) { return (DEVFSADM_CONTINUE); } (void) strcpy(contents, l_path); (void) strcpy(l_path, "fb"); (void) strcat(l_path, buf); free(buf); (void) devfsadm_secondary_link(l_path, contents, 0); return (DEVFSADM_CONTINUE); }
/* * This function is called for every usb minor node. * Calls enumerate to assign a logical usb id, and then * devfsadm_mklink to make the link. */ static int usb_process(di_minor_t minor, di_node_t node) { devfsadm_enumerate_t rules[1]; char *l_path, *p_path, *buf, *devfspath; char *minor_nm, *drvr_nm, *name = (char *)NULL; int i, index; int flags = 0; int create_secondary_link = 0; minor_nm = di_minor_name(minor); drvr_nm = di_driver_name(node); if ((minor_nm == NULL) || (drvr_nm == NULL)) { return (DEVFSADM_CONTINUE); } devfsadm_print(debug_mid, "usb_process: 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, "USB_process: devfspath is NULL\n"); return (DEVFSADM_CONTINUE); } l_path = (char *)malloc(PATH_MAX); if (l_path == NULL) { di_devfs_path_free(devfspath); devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); return (DEVFSADM_CONTINUE); } p_path = (char *)malloc(PATH_MAX); if (p_path == NULL) { devfsadm_print(debug_mid, "usb_process: malloc() failed\n"); di_devfs_path_free(devfspath); free(l_path); return (DEVFSADM_CONTINUE); } (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, minor_nm); di_devfs_path_free(devfspath); devfsadm_print(debug_mid, "usb_process: path %s\n", p_path); for (i = 0; ; i++) { if ((driver_name_table[i].driver_name == NULL) || (strcmp(drvr_nm, driver_name_table[i].driver_name) == 0)) { index = driver_name_table[i].index; break; } } if (strcmp(di_minor_nodetype(minor), DDI_NT_UGEN) == 0) { ugen_create_link(p_path, minor_nm, node, minor); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } /* Figure out which rules to apply */ switch (index) { case DRIVER_HUBD: case DRIVER_OHCI: case DRIVER_EHCI: case DRIVER_UHCI: rules[0] = hub_rules[0]; /* For HUBs */ name = "hub"; break; case DRIVER_USB_AC: if (strcmp(minor_nm, "sound,audio") == 0) { rules[0] = audio_rules[0]; name = "audio"; /* For audio */ create_secondary_link = 1; } else if (strcmp(minor_nm, "sound,audioctl") == 0) { rules[0] = audio_control_rules[0]; name = "audio-control"; /* For audio */ create_secondary_link = 1; } else if (strcmp(minor_nm, "mux") == 0) { rules[0] = audio_mux_rules[0]; name = "audio-mux"; /* For audio */ } else { free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } break; case DRIVER_USB_AS: rules[0] = audio_stream_rules[0]; name = "audio-stream"; /* For audio */ break; case DRIVER_VIDEO: rules[0] = video_rules[0]; name = "video"; /* For video */ create_secondary_link = 1; break; case DRIVER_HID: rules[0] = hid_rules[0]; name = "hid"; /* For HIDs */ break; case DRIVER_USB_MID: rules[0] = device_rules[0]; name = "device"; /* For other USB devices */ break; case DRIVER_DDIVS_USBC: rules[0] = ddivs_usbc_rules[0]; name = "device"; /* For other USB devices */ break; case DRIVER_SCSA2USB: rules[0] = mass_storage_rules[0]; name = "mass-storage"; /* For mass-storage devices */ break; case DRIVER_USBPRN: rules[0] = usbprn_rules[0]; name = "printer"; break; case DRIVER_HWAHC: if (strcmp(minor_nm, "hwahc") == 0) { rules[0] = whost_rules[0]; name = "whost"; /* For HWA HC */ } else if (strcmp(minor_nm, "hubd") == 0) { rules[0] = hub_rules[0]; name = "hub"; /* For HWA HC */ } else { free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } break; case DRIVER_HWARC: rules[0] = hwarc_rules[0]; name = "hwarc"; /* For UWB HWA Radio Controllers */ break; case DRIVER_WUSB_CA: rules[0] = wusb_ca_rules[0]; name = "wusb_ca"; /* for wusb cable association */ break; default: devfsadm_print(debug_mid, "usb_process: unknown driver=%s\n", drvr_nm); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } /* * build the physical path from the components. * find the logical usb id, and stuff it in buf */ if (devfsadm_enumerate_int(p_path, 0, &buf, rules, 1)) { devfsadm_print(debug_mid, "usb_process: exit/continue\n"); free(l_path); free(p_path); return (DEVFSADM_CONTINUE); } (void) snprintf(l_path, PATH_MAX, "usb/%s%s", name, buf); devfsadm_print(debug_mid, "usb_process: p_path=%s buf=%s\n", p_path, buf); free(buf); devfsadm_print(debug_mid, "mklink %s -> %s\n", l_path, p_path); (void) devfsadm_mklink(l_path, node, minor, flags); if (create_secondary_link) { /* * Create secondary links to make newly hotplugged * usb audio device the primary device. */ if (strcmp(name, "audio") == 0) { (void) devfsadm_secondary_link("audio", l_path, 0); } else if (strcmp(name, "audio-control") == 0) { (void) devfsadm_secondary_link("audioctl", l_path, 0); } else if (strcmp(name, "video") == 0) { (void) devfsadm_secondary_link(l_path + 4, l_path, 0); } } free(p_path); free(l_path); return (DEVFSADM_CONTINUE); }
/* * For the admin device: * /dev/md/admin -> /devices/pseudo/md@0:admin * * For metadevice: * /dev/md/dsk/foobar --> /devices/pseudo/md@0:0,100,blk * /dev/md/rdsk/foobar --> /devices/pseudo/md@0:0,100,raw * * Where 'foobar' is user specified arbitrary name and '100' * is the minor number returned by MD_IOCMAKE_DEV ioctl * */ static int md_create(di_minor_t minor, di_node_t node) { char mn[MAXNAMELEN + 1]; char path[PATH_MAX + 1]; char set_path[PATH_MAX +1]; char sym_path[PATH_MAX + 1]; int set = -1, ret; char *type, *dir; char *device_name; dev_t minor_devt = di_minor_devt(minor); int key; mdsetname_t *sp = NULL; md_error_t ep; /* * Initialize sdssc entry points. Don't worry about the return * value here since the interface functions will get initialized * correctly regardless. */ (void) sdssc_bind_library(); (void) strcpy(mn, di_minor_name(minor)); /* * Check whether we are being requested to setup the admin * device link or one of the metadevice links. They need * to be treated differently. */ if (strcmp(mn, "admin") == 0) { /* there is only one admin link and always in /dev/md/admin */ (void) devfsadm_mklink("md/admin", node, minor, 0); } else { /* * Extract out the minor components and create the * appropriate links. The node looks like: * md@<set>,<mdev>,<type> * where the <set> number is the named diskset, * <mdev> is the metadevice number, and <type> * is the trailing "blk" or "raw" indication. * * NOTE: when <set> is non-zero, we need to create * under the "shared" directory entry instead of linking * into the top level dsk/rdsk directories. */ ret = sscanf(mn, "%d,", &set); if (ret == 1 && (type = strrchr(mn, ',')) != NULL) { type++; if (strcmp(type, "blk") == 0) { dir = "dsk"; } else { dir = "rdsk"; } (void) memset(&ep, '\0', sizeof (ep)); if ((device_name = meta_getnmentbydev(set, MD_SIDEWILD, minor_devt, NULL, NULL, &key, &ep)) == NULL) { (void) close_admin(&ep); return (DEVFSADM_CONTINUE); } if (set == 0) { /* this is a simple md */ (void) snprintf(path, sizeof (path), "md/%s/%s", dir, basename(device_name)); } else { /* this is a shared md */ (void) snprintf(path, sizeof (path), "md/shared/%d/%s/%s", set, dir, basename(device_name)); /* * flush the caches so the next call to * metasetnosetname will get us the * updated cache. */ metaflushnames(0); if ((sp = metasetnosetname(set, &ep)) != NULL) { (void) snprintf(set_path, sizeof (set_path), "md/shared/%d", sp->setno); (void) snprintf(sym_path, sizeof (sym_path), "md/%s", sp->setname); } } (void) devfsadm_mklink(path, node, minor, 0); Free(device_name); if (sp != NULL) { (void) devfsadm_secondary_link(sym_path, set_path, 0); } } } (void) close_admin(&ep); return (DEVFSADM_CONTINUE); }