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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 #include <sys/param.h>
28 #include <sys/stat.h>
29 #include <errno.h>
30 #include <string.h>
31 #include <dirent.h>
32 #include "cfga_sata.h"
33
34 /*
35 * This file contains the entry points to the plug-in as defined in the
36 * config_admin(3X) man page.
37 */
38
39 /*
40 * Set the version number for the cfgadm library's use.
41 */
42 int cfga_version = CFGA_HSL_V2;
43
697
698 len = strlen(SATA_CONFIRM_DEVICE) +
699 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
700 strlen("Unconfigure") + strlen(ap_id);
701 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
702 (void) snprintf(msg, len + 3, "Unconfigure"
703 " %s%s\n%s",
704 SATA_CONFIRM_DEVICE, ap_id,
705 SATA_CONFIRM_DEVICE_SUSPEND);
706 }
707
708 if (!sata_confirm(confp, msg)) {
709 free(msg);
710 rv = CFGA_SATA_NACK;
711 break;
712 }
713 free(msg);
714
715 devpath = sata_get_devicepath(ap_id);
716 if (devpath == NULL) {
717 (void) printf(
718 "cfga_change_state: get device path failed\n");
719 rv = CFGA_SATA_DEV_UNCONFIGURE;
720 break;
721 }
722
723 if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
724 != CFGA_SATA_OK) {
725 break;
726 }
727
728 ret = devctl_ap_unconfigure(hdl, nvl);
729
730 if (ret != 0) {
731 rv = CFGA_SATA_DEV_UNCONFIGURE;
732 if (errno == EBUSY) {
733 rv = CFGA_SATA_BUSY;
734 }
735 (void) sata_rcm_online(ap_id, errstring, devpath,
736 flags);
737 } else {
754 }
755
756 /* Strip off AP name dynamic component, if present */
757 if ((pdyn = GET_DYN(ap_id)) != NULL) {
758 *pdyn = '\0';
759 }
760
761
762 rv = CFGA_SATA_OK; /* other statuses don't matter */
763
764 /*
765 * If the port originally with device attached and was
766 * unconfigured already, the devicepath for the sd will be
767 * removed. sata_get_devicepath in this case is not necessary.
768 */
769 /* only call rcm_offline if the state was CONFIGURED */
770 if (ostate == AP_OSTATE_CONFIGURED &&
771 pmult == B_FALSE) {
772 devpath = sata_get_devicepath(ap_id);
773 if (devpath == NULL) {
774 (void) printf(
775 "cfga_change_state: get path failed\n");
776 rv = CFGA_SATA_DEV_UNCONFIGURE;
777 break;
778 }
779
780 len = strlen(SATA_CONFIRM_DEVICE) +
781 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
782 strlen("Disconnect") + strlen(ap_id);
783 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
784 (void) snprintf(msg, len + 3,
785 "Disconnect"
786 " %s%s\n%s",
787 SATA_CONFIRM_DEVICE, ap_id,
788 SATA_CONFIRM_DEVICE_SUSPEND);
789 }
790 if (!sata_confirm(confp, msg)) {
791 free(msg);
792 rv = CFGA_SATA_NACK;
793 break;
794 }
929 devctl_hdl_t hdl = NULL;
930 cfga_sata_ret_t rv;
931 char *str_p;
932 size_t size;
933
934 if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
935 (void) cfga_help(msgp, options, flags);
936 return (sata_err_msg(errstring, rv, ap_id, errno));
937 }
938
939 /*
940 * All subcommands which can change state of device require
941 * root privileges.
942 */
943 if (geteuid() != 0) {
944 rv = CFGA_SATA_PRIV;
945 goto bailout;
946 }
947
948 if (func == NULL) {
949 (void) printf("No valid option specified\n");
950 rv = CFGA_SATA_OPTIONS;
951 goto bailout;
952 }
953
954 if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
955 CFGA_SATA_OK) {
956 goto bailout;
957 }
958
959 /* We do not care here about dynamic AP name component */
960 if ((str_p = GET_DYN(ap_id)) != NULL) {
961 *str_p = '\0';
962 }
963
964 rv = CFGA_SATA_OK;
965
966 if (strcmp(func, SATA_RESET_PORT) == 0) {
967 len = strlen(SATA_CONFIRM_PORT) +
968 strlen(SATA_CONFIRM_DEVICE_ABORT) +
969 strlen("Reset Port") + strlen(ap_id);
1240 char minor_path[MAXPATHLEN];
1241 char name_part[MAXNAMELEN];
1242 char *devlink = NULL;
1243 char *minor_portion = NULL;
1244 int deplen;
1245 int err;
1246 DIR *dp = NULL;
1247 struct stat sb;
1248 struct dirent *dep = NULL;
1249 struct dirent *newdep = NULL;
1250 char *p;
1251
1252 assert(dyncomp != NULL);
1253
1254 /*
1255 * Get target node path
1256 */
1257 devpath = sata_get_devicepath(ap_id);
1258 if (devpath == NULL) {
1259
1260 (void) printf("cfga_list_ext: cannot locate target device\n");
1261 return (CFGA_SATA_DYNAMIC_AP);
1262
1263 } else {
1264
1265 cp = strrchr(devpath, *PATH_SEP);
1266 assert(cp != NULL);
1267 *cp = 0; /* terminate path for opendir() */
1268
1269 (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1270
1271 /*
1272 * Using libdevinfo for this is overkill and kills
1273 * performance when many consumers are using libcfgadm
1274 * concurrently.
1275 */
1276 if ((dp = opendir(devpath)) == NULL) {
1277 goto bailout;
1278 }
1279
1280 /*
1556 default:
1557 rv = CFGA_SATA_STATE;
1558 goto bailout;
1559 }
1560
1561 (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */
1562 (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1563 (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1564 (*ap_id_list)->ap_info[0] = NULL;
1565
1566 if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1567 char *str_p;
1568 int skip, i;
1569
1570 /*
1571 * Fill in the 'Information' field for the -v option
1572 * Model (MOD:)
1573 */
1574 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1575 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1576 (void) printf(
1577 "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1578 goto bailout;
1579 }
1580 /* drop leading and trailing spaces */
1581 skip = strspn(str_p, " ");
1582 for (i = size - 1; i >= 0; i--) {
1583 if (str_p[i] == '\040')
1584 str_p[i] = '\0';
1585 else if (str_p[i] != '\0')
1586 break;
1587 }
1588
1589 (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1590 sizeof ((*ap_id_list)->ap_info));
1591 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1592 sizeof ((*ap_id_list)->ap_info));
1593
1594 free(str_p);
1595
1596 /*
1597 * Fill in the 'Information' field for the -v option
1598 * Firmware revision (FREV:)
1599 */
1600 if ((rv = do_control_ioctl(ap_id,
1601 SATA_CFGA_GET_REVFIRMWARE_INFO,
1602 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1603 (void) printf(
1604 "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1605 goto bailout;
1606 }
1607 /* drop leading and trailing spaces */
1608 skip = strspn(str_p, " ");
1609 for (i = size - 1; i >= 0; i--) {
1610 if (str_p[i] == '\040')
1611 str_p[i] = '\0';
1612 else if (str_p[i] != '\0')
1613 break;
1614 }
1615 (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1616 sizeof ((*ap_id_list)->ap_info));
1617 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1618 sizeof ((*ap_id_list)->ap_info));
1619
1620 free(str_p);
1621
1622
1623 /*
1624 * Fill in the 'Information' field for the -v option
1625 * Serial Number (SN:)
1626 */
1627 if ((rv = do_control_ioctl(ap_id,
1628 SATA_CFGA_GET_SERIALNUMBER_INFO,
1629 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1630 (void) printf(
1631 "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1632 goto bailout;
1633 }
1634 /* drop leading and trailing spaces */
1635 skip = strspn(str_p, " ");
1636 for (i = size - 1; i >= 0; i--) {
1637 if (str_p[i] == '\040')
1638 str_p[i] = '\0';
1639 else if (str_p[i] != '\0')
1640 break;
1641 }
1642 (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1643 sizeof ((*ap_id_list)->ap_info));
1644 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1645 sizeof ((*ap_id_list)->ap_info));
1646
1647 free(str_p);
1648
1649
1650
1651 /* Fill in ap_type which is collected from HBA driver */
1652 /* call do_control_ioctl TBD */
1653 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1654 (void **)&str_p, &size)) != CFGA_SATA_OK) {
1655 (void) printf(
1656 "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1657 goto bailout;
1658 }
1659
1660 (void) strlcpy((*ap_id_list)->ap_type, str_p,
1661 sizeof ((*ap_id_list)->ap_type));
1662
1663 free(str_p);
1664
1665 /*
1666 * Checking device type. Port multiplier has no dynamic
1667 * suffix.
1668 */
1669 if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1670 sizeof ("sata-pmult")) == 0)
1671 pmult = B_TRUE;
1672
1673 if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1674 pmult == B_FALSE) {
1675
1714 if (*ap_id_list != NULL) {
1715 free(*ap_id_list);
1716 }
1717 if (ap_id_log != NULL) {
1718 free(ap_id_log);
1719 }
1720
1721 return (sata_err_msg(errstring, rv, ap_id, errno));
1722 }
1723 /*
1724 * This routine accepts a string adn prints it using
1725 * the message print routine argument.
1726 */
1727 static void
1728 cfga_msg(struct cfga_msg *msgp, const char *str)
1729 {
1730 int len;
1731 char *q;
1732
1733 if (msgp == NULL || msgp->message_routine == NULL) {
1734 (void) printf("cfga_msg: NULL msgp\n");
1735 return;
1736 }
1737
1738 if ((len = strlen(str)) == 0) {
1739 (void) printf("cfga_msg: null str\n");
1740 return;
1741 }
1742
1743 if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1744 perror("cfga_msg");
1745 return;
1746 }
1747
1748 (void) strcpy(q, str);
1749 (*msgp->message_routine)(msgp->appdata_ptr, q);
1750
1751 free(q);
1752 }
1753
1754 /* cfgadm entry point */
1755 /* ARGSUSED */
1756 cfga_err_t
1757 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1758 {
1759 if (options != NULL) {
1760 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1761 cfga_msg(msgp, options);
1762 }
1763 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1764 cfga_msg(msgp, sata_help[HELP_CONFIG]);
1807
1808
1809
1810 /*
1811 * Verify the params passed in are valid.
1812 */
1813 static cfga_sata_ret_t
1814 verify_params(
1815 const char *ap_id,
1816 const char *options,
1817 char **errstring)
1818 {
1819 char *pdyn, *lap_id;
1820 int rv;
1821
1822 if (errstring != NULL) {
1823 *errstring = NULL;
1824 }
1825
1826 if (options != NULL) {
1827 return (CFGA_SATA_OPTIONS);
1828 }
1829
1830 /* Strip dynamic AP name component if it is present. */
1831 lap_id = strdup(ap_id);
1832 if (lap_id == NULL) {
1833 return (CFGA_SATA_ALLOC_FAIL);
1834 }
1835 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1836 *pdyn = '\0';
1837 }
1838
1839 if (verify_valid_apid(lap_id) != 0) {
1840 rv = CFGA_SATA_AP;
1841 } else {
1842 rv = CFGA_SATA_OK;
1843 }
1844 free(lap_id);
1845
1846 return (rv);
1847 }
1848
1849 /*
1850 * Takes a validated ap_id and extracts the port number.
1851 * Port multiplier is supported now.
1852 */
1853 static cfga_sata_ret_t
1854 get_port_num(const char *ap_id, uint32_t *port)
1855 {
1856 uint32_t cport, pmport = 0, qual = 0;
1857 char *cport_str, *pmport_str;
1858
1859 /* Get the cport number */
1909 lap_id = strdup(ap_id);
1910 if (lap_id == NULL)
1911 return (CFGA_SATA_ALLOC_FAIL);
1912 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1913 *pdyn = '\0';
1914 }
1915
1916 /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1917 if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1918 (void) fprintf(stderr, "[libcfgadm:sata] "
1919 "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1920 strerror(errno));
1921 rv = CFGA_SATA_DEVCTL;
1922 goto bailout;
1923 }
1924
1925 /* Set up nvlist to pass the port number down to the driver */
1926 if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1927 *user_nvlistp = NULL;
1928 rv = CFGA_SATA_NVLIST;
1929 (void) printf("nvlist_alloc failed\n");
1930 goto bailout;
1931 }
1932
1933 /*
1934 * Get port id, for Port Multiplier port, things could be a little bit
1935 * complicated because of "port.port" format in ap_id, thus for
1936 * port multiplier port, port number should be coded as 32bit int
1937 * with the sig 16 bit as sata channel number, least 16 bit as
1938 * the port number of sata port multiplier port.
1939 */
1940 if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1941 (void) printf(
1942 "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1943 errno);
1944 goto bailout;
1945 }
1946
1947 /* Creates an int32_t entry */
1948 if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1949 (void) printf("nvlist_add_int32 failed\n");
1950 rv = CFGA_SATA_NVLIST;
1951 goto bailout;
1952 }
1953
1954 free(lap_id);
1955 return (rv);
1956
1957 bailout:
1958 free(lap_id);
1959 (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1960
1961 return (rv);
1962 }
1963
1964
1965 static cfga_sata_ret_t
1966 port_state(devctl_hdl_t hdl, nvlist_t *list,
1967 ap_rstate_t *rstate, ap_ostate_t *ostate)
1968 {
1969 devctl_ap_state_t devctl_ap_state;
1970
1971 if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1972 (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
1973 return (CFGA_SATA_IOCTL);
1974 }
1975 *rstate = devctl_ap_state.ap_rstate;
1976 *ostate = devctl_ap_state.ap_ostate;
1977 return (CFGA_SATA_OK);
1978 }
1979
1980
1981 /*
1982 * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1983 * the data to be returned, allocate a buffer, then get the data.
1984 * Returns *descrp (which must be freed) and size.
1985 *
1986 * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1987 * not a string descr.
1988 */
1989 cfga_sata_ret_t
1990 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1991 void **descrp, size_t *sizep)
1992 {
1993 int fd = -1;
1994 uint_t port;
1995 uint32_t local_size;
1996 cfga_sata_ret_t rv = CFGA_SATA_OK;
1997 struct sata_ioctl_data ioctl_data;
1998
1999 assert(descrp != NULL);
2000 *descrp = NULL;
2001 assert(sizep != NULL);
2002
2003 if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2004 goto bailout;
2005 }
2006
2007 if ((fd = open(ap_id, O_RDONLY)) == -1) {
2008 (void) printf("do_control_ioctl: open failed: errno:%d\n",
2009 errno);
2010 rv = CFGA_SATA_OPEN;
2011 if (errno == EBUSY) {
2012 rv = CFGA_SATA_BUSY;
2013 }
2014 goto bailout;
2015 }
2016
2017 ioctl_data.cmd = subcommand;
2018 ioctl_data.port = port;
2019 ioctl_data.misc_arg = (uint_t)arg;
2020
2021 /*
2022 * Find out how large a buf we need to get the data.
2023 * Note the ioctls only accept/return a 32-bit int for a get_size
2024 * to avoid 32/64 and BE/LE issues.
2025 */
2026 if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2027 (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2028 (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2029 (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2030 (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2031 ioctl_data.get_size = B_TRUE;
2032 ioctl_data.buf = (caddr_t)&local_size;
2033 ioctl_data.bufsiz = sizeof (local_size);
2034
2035 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2036 perror("ioctl failed (size)");
2037 rv = CFGA_SATA_IOCTL;
2038 goto bailout;
2039 }
2040 *sizep = local_size;
2041
2042 if (local_size == 0) {
2043 (void) printf("zero length data\n");
2044 rv = CFGA_SATA_ZEROLEN;
2045 goto bailout;
2046 }
2047 if ((*descrp = malloc(*sizep)) == NULL) {
2048 (void) printf("do_control_ioctl: malloc failed\n");
2049 rv = CFGA_SATA_ALLOC_FAIL;
2050 goto bailout;
2051 }
2052 } else {
2053 *sizep = 0;
2054 }
2055 ioctl_data.get_size = B_FALSE;
2056 ioctl_data.buf = *descrp;
2057 ioctl_data.bufsiz = *sizep;
2058
2059 /* Execute IOCTL */
2060
2061 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2062 rv = CFGA_SATA_IOCTL;
2063 goto bailout;
2064 }
2065
2066 (void) close(fd);
2067
2068 return (rv);
|
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 /*
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
25 * Use is subject to license terms.
26 */
27
28 #include <sys/param.h>
29 #include <sys/stat.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <dirent.h>
33 #include "cfga_sata.h"
34
35 /*
36 * This file contains the entry points to the plug-in as defined in the
37 * config_admin(3X) man page.
38 */
39
40 /*
41 * Set the version number for the cfgadm library's use.
42 */
43 int cfga_version = CFGA_HSL_V2;
44
698
699 len = strlen(SATA_CONFIRM_DEVICE) +
700 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
701 strlen("Unconfigure") + strlen(ap_id);
702 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
703 (void) snprintf(msg, len + 3, "Unconfigure"
704 " %s%s\n%s",
705 SATA_CONFIRM_DEVICE, ap_id,
706 SATA_CONFIRM_DEVICE_SUSPEND);
707 }
708
709 if (!sata_confirm(confp, msg)) {
710 free(msg);
711 rv = CFGA_SATA_NACK;
712 break;
713 }
714 free(msg);
715
716 devpath = sata_get_devicepath(ap_id);
717 if (devpath == NULL) {
718 DPRINTF(
719 "cfga_change_state: get device path failed\n");
720 rv = CFGA_SATA_DEV_UNCONFIGURE;
721 break;
722 }
723
724 if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
725 != CFGA_SATA_OK) {
726 break;
727 }
728
729 ret = devctl_ap_unconfigure(hdl, nvl);
730
731 if (ret != 0) {
732 rv = CFGA_SATA_DEV_UNCONFIGURE;
733 if (errno == EBUSY) {
734 rv = CFGA_SATA_BUSY;
735 }
736 (void) sata_rcm_online(ap_id, errstring, devpath,
737 flags);
738 } else {
755 }
756
757 /* Strip off AP name dynamic component, if present */
758 if ((pdyn = GET_DYN(ap_id)) != NULL) {
759 *pdyn = '\0';
760 }
761
762
763 rv = CFGA_SATA_OK; /* other statuses don't matter */
764
765 /*
766 * If the port originally with device attached and was
767 * unconfigured already, the devicepath for the sd will be
768 * removed. sata_get_devicepath in this case is not necessary.
769 */
770 /* only call rcm_offline if the state was CONFIGURED */
771 if (ostate == AP_OSTATE_CONFIGURED &&
772 pmult == B_FALSE) {
773 devpath = sata_get_devicepath(ap_id);
774 if (devpath == NULL) {
775 DPRINTF(
776 "cfga_change_state: get path failed\n");
777 rv = CFGA_SATA_DEV_UNCONFIGURE;
778 break;
779 }
780
781 len = strlen(SATA_CONFIRM_DEVICE) +
782 strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
783 strlen("Disconnect") + strlen(ap_id);
784 if ((msg = (char *)calloc(len +3, 1)) != NULL) {
785 (void) snprintf(msg, len + 3,
786 "Disconnect"
787 " %s%s\n%s",
788 SATA_CONFIRM_DEVICE, ap_id,
789 SATA_CONFIRM_DEVICE_SUSPEND);
790 }
791 if (!sata_confirm(confp, msg)) {
792 free(msg);
793 rv = CFGA_SATA_NACK;
794 break;
795 }
930 devctl_hdl_t hdl = NULL;
931 cfga_sata_ret_t rv;
932 char *str_p;
933 size_t size;
934
935 if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
936 (void) cfga_help(msgp, options, flags);
937 return (sata_err_msg(errstring, rv, ap_id, errno));
938 }
939
940 /*
941 * All subcommands which can change state of device require
942 * root privileges.
943 */
944 if (geteuid() != 0) {
945 rv = CFGA_SATA_PRIV;
946 goto bailout;
947 }
948
949 if (func == NULL) {
950 DPRINTF("No valid option specified\n");
951 rv = CFGA_SATA_OPTIONS;
952 goto bailout;
953 }
954
955 if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
956 CFGA_SATA_OK) {
957 goto bailout;
958 }
959
960 /* We do not care here about dynamic AP name component */
961 if ((str_p = GET_DYN(ap_id)) != NULL) {
962 *str_p = '\0';
963 }
964
965 rv = CFGA_SATA_OK;
966
967 if (strcmp(func, SATA_RESET_PORT) == 0) {
968 len = strlen(SATA_CONFIRM_PORT) +
969 strlen(SATA_CONFIRM_DEVICE_ABORT) +
970 strlen("Reset Port") + strlen(ap_id);
1241 char minor_path[MAXPATHLEN];
1242 char name_part[MAXNAMELEN];
1243 char *devlink = NULL;
1244 char *minor_portion = NULL;
1245 int deplen;
1246 int err;
1247 DIR *dp = NULL;
1248 struct stat sb;
1249 struct dirent *dep = NULL;
1250 struct dirent *newdep = NULL;
1251 char *p;
1252
1253 assert(dyncomp != NULL);
1254
1255 /*
1256 * Get target node path
1257 */
1258 devpath = sata_get_devicepath(ap_id);
1259 if (devpath == NULL) {
1260
1261 DPRINTF("cfga_list_ext: cannot locate target device\n");
1262 return (CFGA_SATA_DYNAMIC_AP);
1263
1264 } else {
1265
1266 cp = strrchr(devpath, *PATH_SEP);
1267 assert(cp != NULL);
1268 *cp = 0; /* terminate path for opendir() */
1269
1270 (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1271
1272 /*
1273 * Using libdevinfo for this is overkill and kills
1274 * performance when many consumers are using libcfgadm
1275 * concurrently.
1276 */
1277 if ((dp = opendir(devpath)) == NULL) {
1278 goto bailout;
1279 }
1280
1281 /*
1557 default:
1558 rv = CFGA_SATA_STATE;
1559 goto bailout;
1560 }
1561
1562 (*ap_id_list)->ap_class[0] = '\0'; /* Filled by libcfgadm */
1563 (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1564 (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1565 (*ap_id_list)->ap_info[0] = NULL;
1566
1567 if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1568 char *str_p;
1569 int skip, i;
1570
1571 /*
1572 * Fill in the 'Information' field for the -v option
1573 * Model (MOD:)
1574 */
1575 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1576 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1577 DPRINTF(
1578 "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1579 goto bailout;
1580 }
1581 /* drop leading and trailing spaces */
1582 skip = strspn(str_p, " ");
1583 for (i = size - 1; i >= 0; i--) {
1584 if (str_p[i] == '\040')
1585 str_p[i] = '\0';
1586 else if (str_p[i] != '\0')
1587 break;
1588 }
1589
1590 (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1591 sizeof ((*ap_id_list)->ap_info));
1592 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1593 sizeof ((*ap_id_list)->ap_info));
1594
1595 free(str_p);
1596
1597 /*
1598 * Fill in the 'Information' field for the -v option
1599 * Firmware revision (FREV:)
1600 */
1601 if ((rv = do_control_ioctl(ap_id,
1602 SATA_CFGA_GET_REVFIRMWARE_INFO,
1603 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1604 DPRINTF(
1605 "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1606 goto bailout;
1607 }
1608 /* drop leading and trailing spaces */
1609 skip = strspn(str_p, " ");
1610 for (i = size - 1; i >= 0; i--) {
1611 if (str_p[i] == '\040')
1612 str_p[i] = '\0';
1613 else if (str_p[i] != '\0')
1614 break;
1615 }
1616 (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1617 sizeof ((*ap_id_list)->ap_info));
1618 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1619 sizeof ((*ap_id_list)->ap_info));
1620
1621 free(str_p);
1622
1623
1624 /*
1625 * Fill in the 'Information' field for the -v option
1626 * Serial Number (SN:)
1627 */
1628 if ((rv = do_control_ioctl(ap_id,
1629 SATA_CFGA_GET_SERIALNUMBER_INFO,
1630 NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1631 DPRINTF(
1632 "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1633 goto bailout;
1634 }
1635 /* drop leading and trailing spaces */
1636 skip = strspn(str_p, " ");
1637 for (i = size - 1; i >= 0; i--) {
1638 if (str_p[i] == '\040')
1639 str_p[i] = '\0';
1640 else if (str_p[i] != '\0')
1641 break;
1642 }
1643 (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1644 sizeof ((*ap_id_list)->ap_info));
1645 (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1646 sizeof ((*ap_id_list)->ap_info));
1647
1648 free(str_p);
1649
1650
1651
1652 /* Fill in ap_type which is collected from HBA driver */
1653 /* call do_control_ioctl TBD */
1654 if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1655 (void **)&str_p, &size)) != CFGA_SATA_OK) {
1656 DPRINTF(
1657 "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1658 goto bailout;
1659 }
1660
1661 (void) strlcpy((*ap_id_list)->ap_type, str_p,
1662 sizeof ((*ap_id_list)->ap_type));
1663
1664 free(str_p);
1665
1666 /*
1667 * Checking device type. Port multiplier has no dynamic
1668 * suffix.
1669 */
1670 if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1671 sizeof ("sata-pmult")) == 0)
1672 pmult = B_TRUE;
1673
1674 if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1675 pmult == B_FALSE) {
1676
1715 if (*ap_id_list != NULL) {
1716 free(*ap_id_list);
1717 }
1718 if (ap_id_log != NULL) {
1719 free(ap_id_log);
1720 }
1721
1722 return (sata_err_msg(errstring, rv, ap_id, errno));
1723 }
1724 /*
1725 * This routine accepts a string adn prints it using
1726 * the message print routine argument.
1727 */
1728 static void
1729 cfga_msg(struct cfga_msg *msgp, const char *str)
1730 {
1731 int len;
1732 char *q;
1733
1734 if (msgp == NULL || msgp->message_routine == NULL) {
1735 DPRINTF("cfga_msg: msg\n");
1736 return;
1737 }
1738
1739 if ((len = strlen(str)) == 0) {
1740 DPRINTF("cfga_msg: null str\n");
1741 return;
1742 }
1743
1744 if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1745 DPRINTF("cfga_msg: null q\n");
1746 return;
1747 }
1748
1749 (void) strcpy(q, str);
1750 (*msgp->message_routine)(msgp->appdata_ptr, q);
1751
1752 free(q);
1753 }
1754
1755 /* cfgadm entry point */
1756 /* ARGSUSED */
1757 cfga_err_t
1758 cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1759 {
1760 if (options != NULL) {
1761 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1762 cfga_msg(msgp, options);
1763 }
1764 cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1765 cfga_msg(msgp, sata_help[HELP_CONFIG]);
1808
1809
1810
1811 /*
1812 * Verify the params passed in are valid.
1813 */
1814 static cfga_sata_ret_t
1815 verify_params(
1816 const char *ap_id,
1817 const char *options,
1818 char **errstring)
1819 {
1820 char *pdyn, *lap_id;
1821 int rv;
1822
1823 if (errstring != NULL) {
1824 *errstring = NULL;
1825 }
1826
1827 if (options != NULL) {
1828 DPRINTF("verify_params: hardware-specific options not "
1829 "supported.\n");
1830 return (CFGA_SATA_OPTIONS);
1831 }
1832
1833 /* Strip dynamic AP name component if it is present. */
1834 lap_id = strdup(ap_id);
1835 if (lap_id == NULL) {
1836 return (CFGA_SATA_ALLOC_FAIL);
1837 }
1838 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1839 *pdyn = '\0';
1840 }
1841
1842 if (verify_valid_apid(lap_id) != 0) {
1843 DPRINTF("verify_params: not a SATA ap_id.\n");
1844 rv = CFGA_SATA_AP;
1845 } else {
1846 rv = CFGA_SATA_OK;
1847 }
1848 free(lap_id);
1849
1850 return (rv);
1851 }
1852
1853 /*
1854 * Takes a validated ap_id and extracts the port number.
1855 * Port multiplier is supported now.
1856 */
1857 static cfga_sata_ret_t
1858 get_port_num(const char *ap_id, uint32_t *port)
1859 {
1860 uint32_t cport, pmport = 0, qual = 0;
1861 char *cport_str, *pmport_str;
1862
1863 /* Get the cport number */
1913 lap_id = strdup(ap_id);
1914 if (lap_id == NULL)
1915 return (CFGA_SATA_ALLOC_FAIL);
1916 if ((pdyn = GET_DYN(lap_id)) != NULL) {
1917 *pdyn = '\0';
1918 }
1919
1920 /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1921 if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1922 (void) fprintf(stderr, "[libcfgadm:sata] "
1923 "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1924 strerror(errno));
1925 rv = CFGA_SATA_DEVCTL;
1926 goto bailout;
1927 }
1928
1929 /* Set up nvlist to pass the port number down to the driver */
1930 if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1931 *user_nvlistp = NULL;
1932 rv = CFGA_SATA_NVLIST;
1933 DPRINTF("nvlist_alloc failed\n");
1934 goto bailout;
1935 }
1936
1937 /*
1938 * Get port id, for Port Multiplier port, things could be a little bit
1939 * complicated because of "port.port" format in ap_id, thus for
1940 * port multiplier port, port number should be coded as 32bit int
1941 * with the sig 16 bit as sata channel number, least 16 bit as
1942 * the port number of sata port multiplier port.
1943 */
1944 if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1945 DPRINTF(
1946 "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1947 errno);
1948 goto bailout;
1949 }
1950
1951 /* Creates an int32_t entry */
1952 if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1953 DPRINTF("nvlist_add_int32 failed\n");
1954 rv = CFGA_SATA_NVLIST;
1955 goto bailout;
1956 }
1957
1958 free(lap_id);
1959 return (rv);
1960
1961 bailout:
1962 free(lap_id);
1963 (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1964
1965 return (rv);
1966 }
1967
1968
1969 static cfga_sata_ret_t
1970 port_state(devctl_hdl_t hdl, nvlist_t *list,
1971 ap_rstate_t *rstate, ap_ostate_t *ostate)
1972 {
1973 devctl_ap_state_t devctl_ap_state;
1974
1975 if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1976 DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno);
1977 return (CFGA_SATA_IOCTL);
1978 }
1979 *rstate = devctl_ap_state.ap_rstate;
1980 *ostate = devctl_ap_state.ap_ostate;
1981 return (CFGA_SATA_OK);
1982 }
1983
1984
1985 /*
1986 * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1987 * the data to be returned, allocate a buffer, then get the data.
1988 * Returns *descrp (which must be freed) and size.
1989 *
1990 * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1991 * not a string descr.
1992 */
1993 cfga_sata_ret_t
1994 do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1995 void **descrp, size_t *sizep)
1996 {
1997 int fd = -1;
1998 uint_t port;
1999 uint32_t local_size;
2000 cfga_sata_ret_t rv = CFGA_SATA_OK;
2001 struct sata_ioctl_data ioctl_data;
2002
2003 assert(descrp != NULL);
2004 *descrp = NULL;
2005 assert(sizep != NULL);
2006
2007 if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2008 goto bailout;
2009 }
2010
2011 if ((fd = open(ap_id, O_RDONLY)) == -1) {
2012 DPRINTF("do_control_ioctl: open failed: errno:%d\n",
2013 errno);
2014 rv = CFGA_SATA_OPEN;
2015 if (errno == EBUSY) {
2016 rv = CFGA_SATA_BUSY;
2017 }
2018 goto bailout;
2019 }
2020
2021 ioctl_data.cmd = subcommand;
2022 ioctl_data.port = port;
2023 ioctl_data.misc_arg = (uint_t)arg;
2024
2025 /*
2026 * Find out how large a buf we need to get the data.
2027 * Note the ioctls only accept/return a 32-bit int for a get_size
2028 * to avoid 32/64 and BE/LE issues.
2029 */
2030 if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2031 (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2032 (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2033 (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2034 (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2035 ioctl_data.get_size = B_TRUE;
2036 ioctl_data.buf = (caddr_t)&local_size;
2037 ioctl_data.bufsiz = sizeof (local_size);
2038
2039 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2040 perror("ioctl failed (size)");
2041 rv = CFGA_SATA_IOCTL;
2042 goto bailout;
2043 }
2044 *sizep = local_size;
2045
2046 if (local_size == 0) {
2047 DPRINTF("zero length data\n");
2048 rv = CFGA_SATA_ZEROLEN;
2049 goto bailout;
2050 }
2051 if ((*descrp = malloc(*sizep)) == NULL) {
2052 DPRINTF("do_control_ioctl: malloc failed\n");
2053 rv = CFGA_SATA_ALLOC_FAIL;
2054 goto bailout;
2055 }
2056 } else {
2057 *sizep = 0;
2058 }
2059 ioctl_data.get_size = B_FALSE;
2060 ioctl_data.buf = *descrp;
2061 ioctl_data.bufsiz = *sizep;
2062
2063 /* Execute IOCTL */
2064
2065 if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2066 rv = CFGA_SATA_IOCTL;
2067 goto bailout;
2068 }
2069
2070 (void) close(fd);
2071
2072 return (rv);
|