/* * Lights Out Management (LOM) serial ports * Creates links of the form "/dev/term/lom-console". */ static int lom_port_create(di_minor_t minor, di_node_t node) { char *devfspath; char *minor_name; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_CONTINUE); } if ((minor_name = di_minor_name(minor)) == NULL) { devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } /* * if this is the LOM console serial port (i.e. the minor * name == lom-console ), create /dev/term/lom-console link and * then we are done with this node. */ if (strcmp(minor_name, "lom-console") == 0) { (void) devfsadm_mklink("term/lom-console", node, minor, 0); di_devfs_path_free(devfspath); return (DEVFSADM_TERMINATE); } /* This is not a LOM node, continue... */ di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); }
/* * PCMCIA dialout serial ports * Creates links of the form "/dev/cua/pcN", where N is the PCMCIA * socket number the device is plugged into. */ static int pcmcia_dialout_create(di_minor_t minor, di_node_t node) { char l_path[MAXPATHLEN]; char *devfspath; int socket, *intp; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_TERMINATE); } if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, "socket", &intp) <= 0) { devfsadm_errprint("%s: failed socket lookup\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_TERMINATE); } socket = PCMCIA_SOCKETNO(*intp); di_devfs_path_free(devfspath); (void) sprintf(l_path, "cua/pc%d", socket); (void) devfsadm_mklink(l_path, node, minor, 0); return (DEVFSADM_TERMINATE); }
/* * Onboard dialout devices * Creates links of the form "/dev/cua/[a..z]" */ static int onbrd_dialout_create(di_minor_t minor, di_node_t node) { char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; char *devfspath, *buf, *mn; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_CONTINUE); } if ((mn = di_minor_name(minor)) == NULL) { devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } /* * verify this is a dialout port */ if (!is_dialout(mn)) { devfsadm_errprint("%s: not a dialout device\n\t%s:%s\n", modname, devfspath, mn); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, mn); di_devfs_path_free(devfspath); buf = NULL; #ifdef __i386 buf = check_compat_ports(p_path, mn); #endif /* * devfsadm_enumerate_char_start() is a private interface * for use by the ports module only. */ if (!buf && devfsadm_enumerate_char_start(p_path, 0, &buf, obport_rules, 1, start_id)) { devfsadm_errprint("%s: devfsadm_enumerate_char_start() failed" "\n\t%s\n", modname, p_path); return (DEVFSADM_CONTINUE); } /* * create the logical link */ (void) strcpy(l_path, "cua/"); (void) strcat(l_path, buf); (void) devfsadm_mklink(l_path, node, minor, 0); free(buf); return (DEVFSADM_CONTINUE); }
/* * Called for all dialout devices that are NOT onboard * Creates links of the form "/dev/cua/[0..n]" */ static int dialout_create(di_minor_t minor, di_node_t node) { char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; char *devfspath, *buf, *mn; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_CONTINUE); } if ((mn = di_minor_name(minor)) == NULL) { devfsadm_errprint("%s: NULL minorname\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } if (!is_dialout(mn)) { devfsadm_errprint("%s: invalid minor name\n\t%s:%s\n", modname, devfspath, mn); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, mn); di_devfs_path_free(devfspath); if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { devfsadm_errprint("%s:dialout_create:" " enumerate_int() failed\n\t%s\n", modname, p_path); return (DEVFSADM_CONTINUE); } (void) strcpy(l_path, "cua/"); (void) strcat(l_path, buf); /* * add the minor name to the physical path so we can create * the link. */ (void) devfsadm_mklink(l_path, node, minor, 0); free(buf); return (DEVFSADM_CONTINUE); }
/* * port monitor array mgmt */ static void * pma_alloc(void) { if (pma != NULL) { devfsadm_errprint("%s:pma_alloc:pma != NULL\n", modname); return (NULL); } if ((pma = calloc(maxports + 1, sizeof (*pma))) == NULL) { devfsadm_errprint("%s:pma_alloc:pma alloc failure\n", modname); return (NULL); } return ((void *)pma); }
/* * Remote System Controller (RSC) serial ports * Creates links of the form "/dev/rsc-control" | "/dev/term/rsc-console". */ static int rsc_port_create(di_minor_t minor, di_node_t node) { char *devfspath; char *minor_name; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_CONTINUE); } if ((minor_name = di_minor_name(minor)) == NULL) { devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } /* * if this is the RSC console serial port (i.e. the minor name == ssp), * create /dev/term/rsc-console link and then we are done with this * node. */ if (strcmp(minor_name, "ssp") == 0) { (void) devfsadm_mklink("term/rsc-console", node, minor, 0); di_devfs_path_free(devfspath); return (DEVFSADM_TERMINATE); /* * else if this is the RSC control serial port (i.e. the minor name == * sspctl), create /dev/rsc-control link and then we are done with this * node. */ } else if (strcmp(minor_name, "sspctl") == 0) { (void) devfsadm_mklink("rsc-control", node, minor, 0); di_devfs_path_free(devfspath); return (DEVFSADM_TERMINATE); } /* This is not an RSC node, continue... */ di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); }
static int disk_callback_fabric(di_minor_t minor, di_node_t node) { char disk[DISK_SUBPATH_MAX]; int lun; int count; int *intp; uchar_t *str; uchar_t *wwn; uchar_t ascii_wwn[ASCIIWWNSIZE]; if (di_prop_lookup_strings(DDI_DEV_T_ANY, node, "client-guid", (char **)&wwn) > 0) { if (strlcpy((char *)ascii_wwn, (char *)wwn, sizeof (ascii_wwn)) >= sizeof (ascii_wwn)) { devfsadm_errprint("SUNW_disk_link: GUID too long:%d", strlen((char *)wwn)); return (DEVFSADM_CONTINUE); } lun = 0; } else if (di_prop_lookup_bytes(DDI_DEV_T_ANY, node, "port-wwn", &wwn) > 0) { if (di_prop_lookup_ints(DDI_DEV_T_ANY, node, SCSI_ADDR_PROP_LUN, &intp) > 0) { lun = *intp; } else { lun = 0; } for (count = 0, str = ascii_wwn; count < 8; count++, str += 2) { (void) sprintf((caddr_t)str, "%02x", wwn[count]); } *str = '\0'; } else { return (DEVFSADM_CONTINUE); } for (str = ascii_wwn; *str != '\0'; str++) { *str = DISK_LINK_TO_UPPER(*str); } (void) snprintf(disk, DISK_SUBPATH_MAX, "t%sd%d", ascii_wwn, lun); disk_common(minor, node, disk, RM_STALE); return (DEVFSADM_CONTINUE); }
/* * Removes port entries that no longer have devices * backing them * Schedules an update the sacadm (portmon) database */ static void rm_dangling_port(char *devname) { char *portstr; int portnum; devfsadm_print(PORT_MID, "%s:rm_stale_port: %s\n", modname, devname); if ((portstr = strrchr(devname, (int)'/')) == NULL) { devfsadm_errprint("%s: invalid name: %s\n", modname, devname); return; } portstr++; /* * mark for removal from sacadm database */ if ((portnum = parse_portno(portstr)) != -1) pma[portnum].flags |= PORT_REMOVED; devfsadm_rm_all(devname); }
/* * Determine which port monitor entries already exist by invoking pmadm(1m) * to list all configured 'ttymon' port monitor entries. * Do not explicitly report errors from executing pmadm(1m) or sacadm(1m) * commands to remain compatible with the ports(1m) implementation. */ static int load_ttymondb(void) { char cmdline[CMDLEN]; char cmdbuf[PMTAB_MAXLINE+1]; int sac_exitval; FILE *fs_popen; char *portname; /* pointer to a tty name */ int portnum; char *ptr; char *error_msg = "%s: failed to load port monitor database\n"; (void) strcpy(cmdline, "/usr/sbin/pmadm -L -t ttymon"); fs_popen = popen(cmdline, "r"); if (fs_popen == NULL) { devfsadm_print(VERBOSE_MID, error_msg, modname); return (DEVFSADM_FAILURE); } while (fgets(cmdbuf, PMTAB_MAXLINE, fs_popen) != NULL) { if ((portname = pmtab_parse_portname(cmdbuf)) == NULL) { devfsadm_print(VERBOSE_MID, "load_ttymondb: failed to parse portname\n"); devfsadm_print(VERBOSE_MID, "load_ttymondb: buffer \"%s\"\n", cmdbuf); goto load_failed; } devfsadm_print(PORT_MID, "%s:load_ttymondb: port %s ", modname, portname); /* * skip onboard ports * There is no reliable way to determine if we * should start a port monitor on these lines. */ if ((portnum = parse_portno(portname)) == -1) { devfsadm_print(PORT_MID, "ignored\n"); continue; } /* * the first field of the pmadm output is * the port monitor name for this entry */ if ((ptr = strchr(cmdbuf, PMTAB_SEPR)) == NULL) { devfsadm_print(VERBOSE_MID, "load_ttymondb: no portmon tag\n"); goto load_failed; } *ptr = MN_NULLCHAR; if ((pma[portnum].pm_tag = strdup(cmdbuf)) == NULL) { devfsadm_errprint("load_ttymondb: failed strdup\n"); goto load_failed; } pma[portnum].flags |= PM_HAS_ENTRY; pma[PM_SLOT(portnum)].flags |= HAS_PORT_MON; devfsadm_print(PORT_MID, "present\n"); } (void) pclose(fs_popen); return (DEVFSADM_SUCCESS); load_failed: /* * failed to load the port monitor database */ devfsadm_print(VERBOSE_MID, error_msg, modname); sac_exitval = SAC_EXITVAL(pclose(fs_popen)); if (sac_exitval != 0) { devfsadm_print(VERBOSE_MID, "pmadm: (%s) %s\n", SAC_EID(sac_exitval), SAC_EMSG(sac_exitval)); } return (DEVFSADM_FAILURE); }
/* * Called for all serial devices that are NOT onboard * Creates links of the form "/dev/term/[0..n]" * Schedules an update the sacadm (portmon). */ static int serial_port_create(di_minor_t minor, di_node_t node) { char l_path[MAXPATHLEN], p_path[MAXPATHLEN]; char *devfspath, *buf, *minor_name; int port_num; devfspath = di_devfs_path(node); if (devfspath == NULL) { devfsadm_errprint("%s: di_devfs_path() failed\n", modname); return (DEVFSADM_CONTINUE); } if ((minor_name = di_minor_name(minor)) == NULL) { devfsadm_errprint("%s: NULL minor name\n\t%s\n", modname, devfspath); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } /* * verify dialout ports do not come in on this nodetype */ if (is_dialout(minor_name)) { devfsadm_errprint("%s: dialout device\n\t%s:%s\n", modname, devfspath, minor_name); di_devfs_path_free(devfspath); return (DEVFSADM_CONTINUE); } /* * add the minor name to the physical path so we can * enum the port# and create the the link. */ (void) strcpy(p_path, devfspath); (void) strcat(p_path, ":"); (void) strcat(p_path, minor_name); di_devfs_path_free(devfspath); if (devfsadm_enumerate_int(p_path, 0, &buf, port_rules, 1)) { devfsadm_errprint("%s:serial_port_create:" " enumerate_int() failed\n\t%s\n", modname, p_path); return (DEVFSADM_CONTINUE); } (void) strcpy(l_path, "term/"); (void) strcat(l_path, buf); (void) devfsadm_mklink(l_path, node, minor, 0); /* * update the portmon database if this port falls within * the valid range of ports. */ if ((port_num = parse_portno(buf)) != -1) { pma[port_num].flags |= HAS_PORT_DEVICE; } free(buf); return (DEVFSADM_CONTINUE); }