Print this page
    
NEX-14898 Null message (cfga_msg: NULL msgp) printed for sata devices with cfgadm
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Sanjay Nadkarni <sanjay.nadkarni@nexenta.com>
Reviewed by: Cynthia Eastham <cynthia.eastham@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
    
      
        | Split | 
	Close | 
      
      | Expand all | 
      | Collapse all | 
    
    
          --- old/usr/src/lib/cfgadm_plugins/sata/common/cfga_sata.c
          +++ new/usr/src/lib/cfgadm_plugins/sata/common/cfga_sata.c
   1    1  /*
   2    2   * CDDL HEADER START
   3    3   *
   4    4   * The contents of this file are subject to the terms of the
   5    5   * Common Development and Distribution License (the "License").
   6    6   * You may not use this file except in compliance with the License.
   7    7   *
   8    8   * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9    9   * or http://www.opensolaris.org/os/licensing.
  10   10   * See the License for the specific language governing permissions
  11   11   * and limitations under the License.
  12   12   *
  13   13   * When distributing Covered Code, include this CDDL HEADER in each
  
    | 
      ↓ open down ↓ | 
    13 lines elided | 
    
      ↑ open up ↑ | 
  
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
       24 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
  24   25   * Use is subject to license terms.
  25   26   */
  26   27  
  27   28  #include <sys/param.h>
  28   29  #include <sys/stat.h>
  29   30  #include <errno.h>
  30   31  #include <string.h>
  31   32  #include <dirent.h>
  32   33  #include "cfga_sata.h"
  33   34  
  34   35  /*
  35   36   * This file contains the entry points to the plug-in as defined in the
  36   37   * config_admin(3X) man page.
  37   38   */
  38   39  
  39   40  /*
  40   41   * Set the version number for the cfgadm library's use.
  41   42   */
  42   43  int cfga_version = CFGA_HSL_V2;
  43   44  
  44   45  enum {
  45   46          HELP_HEADER = 1,
  46   47          HELP_CONFIG,
  47   48          HELP_RESET_PORT,
  48   49          HELP_RESET_DEVICE,
  49   50          HELP_RESET_ALL,
  50   51          HELP_PORT_DEACTIVATE,
  51   52          HELP_PORT_ACTIVATE,
  52   53          HELP_PORT_SELF_TEST,
  53   54          HELP_CNTRL_SELF_TEST,
  54   55          HELP_UNKNOWN
  55   56  };
  56   57  
  57   58  /* SATA specific help messages */
  58   59  static char *sata_help[] = {
  59   60          NULL,
  60   61          "SATA specific commands:\n",
  61   62          " cfgadm -c [configure|unconfigure|disconnect|connect] ap_id "
  62   63              "[ap_id...]\n",
  63   64          " cfgadm -x sata_reset_port ap_id  [ap_id...]\n",
  64   65          " cfgadm -x sata_reset_device ap_id [ap_id...]\n",
  65   66          " cfgadm -x sata_reset_all ap_id\n",
  66   67          " cfgadm -x sata_port_deactivate ap_id [ap_id...]\n",
  67   68          " cfgadm -x sata_port_activate ap_id [ap_id...]\n",
  68   69          " cfgadm -x sata_port_self_test ap_id [ap_id...]\n",
  69   70          " cfgadm -t ap_id\n",
  70   71          "\tunknown command or option:\n",
  71   72          NULL
  72   73  };      /* End help messages */
  73   74  
  74   75  
  75   76  /*
  76   77   * Messages.
  77   78   */
  78   79  static msgcvt_t sata_msgs[] = {
  79   80          /* CFGA_SATA_OK */
  80   81          { CVT, CFGA_OK, "" },
  81   82  
  82   83          /* CFGA_SATA_NACK */
  83   84          { CVT, CFGA_NACK, "" },
  84   85  
  85   86          /* CFGA_SATA_DEVICE_UNCONFIGURED */
  86   87          { CVT, CFGA_OK, "Device unconfigured prior to disconnect" },
  87   88  
  88   89          /* CFGA_SATA_UNKNOWN / CFGA_LIB_ERROR -> "Library error" */
  89   90          { CVT, CFGA_LIB_ERROR, "Unknown message; internal error" },
  90   91  
  91   92          /* CFGA_SATA_INTERNAL_ERROR / CFGA_LIB_ERROR -> "Library error" */
  92   93          { CVT, CFGA_LIB_ERROR, "Internal error" },
  93   94  
  94   95          /* CFGA_SATA_DATA_ERROR / CFGA_DATA_ERROR -> "Data error" */
  95   96          { CVT, CFGA_DATA_ERROR, "cfgadm data error" },
  96   97  
  97   98          /* CFGA_SATA_OPTIONS / CFGA_ERROR -> "Hardware specific failure" */
  98   99          { CVT, CFGA_ERROR, "Hardware specific option not supported" },
  99  100  
 100  101          /* CFGA_SATA_HWOPNOTSUPP / CFGA_ERROR -> "Hardware specific failure" */
 101  102          { CVT, CFGA_ERROR, "Hardware specific operation not supported" },
 102  103  
 103  104          /*
 104  105           * CFGA_SATA_DYNAMIC_AP /
 105  106           * CFGA_LIB_ERROR -> "Configuration operation invalid"
 106  107           */
 107  108          { CVT, CFGA_INVAL, "Cannot identify attached device" },
 108  109  
 109  110          /* CFGA_SATA_AP / CFGA_APID_NOEXIST -> "Attachment point not found" */
 110  111          { CVT, CFGA_APID_NOEXIST, "" },
 111  112  
 112  113          /* CFGA_SATA_PORT / CFGA_LIB_ERROR -> "Library error" */
 113  114          { CVT, CFGA_LIB_ERROR, "Cannot determine sata port number for " },
 114  115  
 115  116          /* CFGA_SATA_DEVCTL / CFGA_LIB_ERROR -> "Library error" */
 116  117          { CVT, CFGA_LIB_ERROR, "Internal error: "
 117  118                  "Cannot allocate devctl handle " },
 118  119  
 119  120          /*
 120  121           * CFGA_SATA_DEV_CONFIGURE /
 121  122           * CFGA_ERROR -> "Hardware specific failure"
 122  123           */
 123  124          { CVT, CFGA_ERROR, "Failed to config device at " },
 124  125  
 125  126          /*
 126  127           * CFGA_SATA_DEV_UNCONFIGURE /
 127  128           * CFGA_ERROR -> "Hardware specific failure"
 128  129           */
 129  130          { CVT, CFGA_ERROR, "Failed to unconfig device at " },
 130  131  
 131  132          /*
 132  133           * CFGA_SATA_DISCONNECTED
 133  134           * CFGA_INVAL -> "Configuration operation invalid"
 134  135           */
 135  136          { CVT, CFGA_INVAL, "Port already disconnected " },
 136  137  
 137  138          /*
 138  139           * CFGA_SATA_NOT_CONNECTED
 139  140           * CFGA_INVAL -> "Configuration operation invalid"
 140  141           */
 141  142          { CVT, CFGA_INVAL, "No device connected to " },
 142  143  
 143  144          /*
 144  145           * CFGA_SATA_NOT_CONFIGURED /
 145  146           * CFGA_INVAL -> "Configuration operation invalid"
 146  147           */
 147  148          { CVT, CFGA_INVAL, "No device configured at " },
 148  149  
 149  150          /*
 150  151           * CFGA_SATA_ALREADY_CONNECTED /
 151  152           * CFGA_INVAL -> "Configuration operation invalid"
 152  153           */
 153  154          { CVT, CFGA_INVAL, "Device already connected to " },
 154  155  
 155  156          /*
 156  157           * CFGA_SATA_ALREADY_CONFIGURED /
 157  158           * CFGA_INVAL -> "Configuration operation invalid"
 158  159           */
 159  160          { CVT, CFGA_INVAL, "Device already configured at " },
 160  161  
 161  162          /*
 162  163           * CFGA_SATA_INVALID_DEVNAME /
 163  164           * CFGA_INVAL -> "Configuration operation invalid"
 164  165           */
 165  166          { CVT, CFGA_INVAL, "Cannot specify device name" },
 166  167  
 167  168          /* CFGA_SATA_OPEN / CFGA_LIB_ERROR -> "Library error" */
 168  169          { CVT, CFGA_LIB_ERROR, "Cannot open " },
 169  170  
 170  171          /* CFGA_SATA_IOCTL / CFGA_ERROR -> "Hardware specific failure"  */
 171  172          { CVT, CFGA_ERROR, "Driver ioctl failed " },
 172  173  
 173  174          /*
 174  175           * CFGA_SATA_BUSY /
 175  176           * CFGA_SYSTEM_BUSY -> "System is busy, try again"
 176  177           */
 177  178          { CVT, CFGA_SYSTEM_BUSY, "" },
 178  179  
 179  180          /* CFGA_SATA_ALLOC_FAIL / CFGA_LIB_ERROR -> "Library error" */
 180  181          { CVT, CFGA_LIB_ERROR, "Memory allocation failure" },
 181  182  
 182  183          /*
 183  184           * CFGA_SATA_OPNOTSUPP /
 184  185           * CFGA_OPNOTSUPP -> "Configuration operation not supported"
 185  186           */
 186  187          { CVT, CFGA_OPNOTSUPP, "Operation not supported" },
 187  188  
 188  189          /* CFGA_SATA_DEVLINK / CFGA_LIB_ERROR -> "Library error" */
 189  190          { CVT, CFGA_LIB_ERROR, "Could not find /dev/cfg link for " },
 190  191  
 191  192          /* CFGA_SATA_STATE / CFGA_LIB_ERROR -> "Library error" */
 192  193          { CVT, CFGA_LIB_ERROR, "Internal error: Unrecognized ap state" },
 193  194  
 194  195          /* CFGA_SATA_PRIV / CFGA_PRIV -> "Insufficient privileges" */
 195  196          { CVT, CFGA_PRIV, "" },
 196  197  
 197  198          /* CFGA_SATA_NVLIST / CFGA_ERROR -> "Hardware specific failure" */
 198  199          { CVT, CFGA_ERROR, "Internal error (nvlist)" },
 199  200  
 200  201          /* CFGA_SATA_ZEROLEN / CFGA_ERROR -> "Hardware specific failure" */
 201  202          { CVT, CFGA_ERROR, "Internal error (zerolength string)" },
 202  203  
 203  204          /* CFGA_SATA_RCM_HANDLE / CFGA_ERROR -> "Hardware specific failure" */
 204  205          { CVT, CFGA_ERROR, "cannot get RCM handle"},
 205  206  
 206  207          /*
 207  208           * CFGA_SATA_RCM_ONLINE /
 208  209           * CFGA_SYSTEM_BUSY -> "System is busy, try again"
 209  210           */
 210  211          { CVT, CFGA_SYSTEM_BUSY, "failed to online: "},
 211  212  
 212  213          /*
 213  214           * CFGA_SATA_RCM_OFFLINE /
 214  215           * CFGA_SYSTEM_BUSY -> "System is busy, try again"
 215  216           */
 216  217          { CVT, CFGA_SYSTEM_BUSY, "failed to offline: "},
 217  218  
 218  219          /* CFGA_SATA_RCM_INFO / CFGA_ERROR -> "Hardware specific failure" */
 219  220          { CVT, CFGA_ERROR, "failed to query: "}
 220  221  
 221  222  };      /* End error messages */
 222  223  
 223  224  static cfga_sata_ret_t
 224  225  verify_params(const char *ap_id, const char *options, char **errstring);
 225  226  
 226  227  
 227  228  static cfga_sata_ret_t
 228  229  setup_for_devctl_cmd(const char *ap_id, devctl_hdl_t *devctl_hdl,
 229  230      nvlist_t **user_nvlistp, uint_t oflag);
 230  231  
 231  232  static cfga_sata_ret_t
 232  233  port_state(devctl_hdl_t hdl, nvlist_t *list,
 233  234      ap_rstate_t *rstate, ap_ostate_t *ostate);
 234  235  
 235  236  static cfga_sata_ret_t
 236  237  do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
 237  238      void **descrp, size_t *sizep);
 238  239  
 239  240  static void
 240  241  cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist);
 241  242  
 242  243  static char *
 243  244  sata_get_devicepath(const char *ap_id);
 244  245  
 245  246  static int
 246  247  sata_confirm(struct cfga_confirm *confp, char *msg);
 247  248  
 248  249  static cfga_sata_ret_t
 249  250  get_port_num(const char *ap_id, uint32_t *port);
 250  251  
 251  252  /* Utilities */
 252  253  
 253  254  static cfga_sata_ret_t
 254  255  physpath_to_devlink(const char *basedir, const char *node_path,
 255  256      char **logpp, int *l_errnop)
 256  257  {
 257  258          char *linkpath;
 258  259          char *buf;
 259  260          char *real_path;
 260  261          DIR *dp;
 261  262          struct dirent *dep, *newdep;
 262  263          int deplen;
 263  264          boolean_t found = B_FALSE;
 264  265          int err = 0;
 265  266          struct stat sb;
 266  267          char *p;
 267  268          cfga_sata_ret_t rv = CFGA_SATA_INTERNAL_ERROR;
 268  269  
 269  270          /*
 270  271           * Using libdevinfo for this is overkill and kills performance
 271  272           * when multiple consumers of libcfgadm are executing
 272  273           * concurrently.
 273  274           */
 274  275          if ((dp = opendir(basedir)) == NULL) {
 275  276                  *l_errnop = errno;
 276  277                  return (CFGA_SATA_INTERNAL_ERROR);
 277  278          }
 278  279  
 279  280          linkpath = malloc(PATH_MAX);
 280  281          buf = malloc(PATH_MAX);
 281  282          real_path = malloc(PATH_MAX);
 282  283  
 283  284          deplen = pathconf(basedir, _PC_NAME_MAX);
 284  285          deplen = (deplen <= 0 ? MAXNAMELEN : deplen) +
 285  286              sizeof (struct dirent);
 286  287          dep = (struct dirent *)malloc(deplen);
 287  288  
 288  289          if (dep == NULL || linkpath == NULL || buf == NULL ||
 289  290              real_path == NULL) {
 290  291                  *l_errnop = ENOMEM;
 291  292                  rv = CFGA_SATA_ALLOC_FAIL;
 292  293                  goto pp_cleanup;
 293  294          }
 294  295  
 295  296          *logpp = NULL;
 296  297  
 297  298          while (!found && (err = readdir_r(dp, dep, &newdep)) == 0 &&
 298  299              newdep != NULL) {
 299  300  
 300  301                  assert(newdep == dep);
 301  302  
 302  303                  if (strcmp(dep->d_name, ".") == 0 ||
 303  304                      strcmp(dep->d_name, "..") == 0)
 304  305                          continue;
 305  306  
 306  307                  (void) snprintf(linkpath, MAXPATHLEN,
 307  308                      "%s/%s", basedir, dep->d_name);
 308  309  
 309  310                  if (lstat(linkpath, &sb) < 0)
 310  311                          continue;
 311  312  
 312  313                  if (S_ISDIR(sb.st_mode)) {
 313  314  
 314  315                          if ((rv = physpath_to_devlink(linkpath, node_path,
 315  316                              logpp, l_errnop)) != CFGA_SATA_OK) {
 316  317  
 317  318                                  goto pp_cleanup;
 318  319                          }
 319  320  
 320  321                          if (*logpp != NULL)
 321  322                                  found = B_TRUE;
 322  323  
 323  324                  } else if (S_ISLNK(sb.st_mode)) {
 324  325  
 325  326                          bzero(buf, PATH_MAX);
 326  327                          if (readlink(linkpath, buf, PATH_MAX) < 0)
 327  328                                  continue;
 328  329  
 329  330  
 330  331                          /*
 331  332                           * realpath() is too darn slow, so fake
 332  333                           * it, by using what we know about /dev
 333  334                           * links: they are always of the form:
 334  335                           * <"../">+/devices/<path>
 335  336                           */
 336  337                          p = buf;
 337  338                          while (strncmp(p, "../", 3) == 0)
 338  339                                  p += 3;
 339  340  
 340  341                          if (p != buf)
 341  342                                  p--;    /* back up to get a slash */
 342  343  
 343  344                          assert (*p == '/');
 344  345  
 345  346                          if (strcmp(p, node_path) == 0) {
 346  347                                  *logpp = strdup(linkpath);
 347  348                                  if (*logpp == NULL) {
 348  349  
 349  350                                          rv = CFGA_SATA_ALLOC_FAIL;
 350  351                                          goto pp_cleanup;
 351  352                                  }
 352  353  
 353  354                                  found = B_TRUE;
 354  355                          }
 355  356                  }
 356  357          }
 357  358  
 358  359          free(linkpath);
 359  360          free(buf);
 360  361          free(real_path);
 361  362          free(dep);
 362  363          (void) closedir(dp);
 363  364  
 364  365          if (err != 0) {
 365  366                  *l_errnop = err;
 366  367                  return (CFGA_SATA_INTERNAL_ERROR);
 367  368          }
 368  369  
 369  370          return (CFGA_SATA_OK);
 370  371  
 371  372  pp_cleanup:
 372  373  
 373  374          if (dp)
 374  375                  (void) closedir(dp);
 375  376          if (dep)
 376  377                  free(dep);
 377  378          if (linkpath)
 378  379                  free(linkpath);
 379  380          if (buf)
 380  381                  free(buf);
 381  382          if (real_path)
 382  383                  free(real_path);
 383  384          if (*logpp) {
 384  385                  free(*logpp);
 385  386                  *logpp = NULL;
 386  387          }
 387  388          return (rv);
 388  389  }
 389  390  
 390  391  
 391  392  /*
 392  393   * Given the index into a table (msgcvt_t) of messages, get the message
 393  394   * string, converting it to the proper locale if necessary.
 394  395   * NOTE: Indexes are defined in cfga_sata.h
 395  396   */
 396  397  static const char *
 397  398  get_msg(uint_t msg_index, msgcvt_t *msg_tbl, uint_t tbl_size)
 398  399  {
 399  400          if (msg_index >= tbl_size) {
 400  401                  msg_index = CFGA_SATA_UNKNOWN;
 401  402          }
 402  403  
 403  404          return ((msg_tbl[msg_index].intl) ?
 404  405              dgettext(TEXT_DOMAIN, msg_tbl[msg_index].msgstr) :
 405  406              msg_tbl[msg_index].msgstr);
 406  407  }
 407  408  
 408  409  /*
 409  410   * Allocates and creates a message string (in *ret_str),
 410  411   * by concatenating all the (char *) args together, in order.
 411  412   * Last arg MUST be NULL.
 412  413   */
 413  414  static void
 414  415  set_msg(char **ret_str, ...)
 415  416  {
 416  417          char    *str;
 417  418          size_t  total_len;
 418  419          va_list valist;
 419  420  
 420  421          va_start(valist, ret_str);
 421  422  
 422  423          total_len = (*ret_str == NULL) ? 0 : strlen(*ret_str);
 423  424  
 424  425          while ((str = va_arg(valist, char *)) != NULL) {
 425  426                  size_t  len = strlen(str);
 426  427                  char    *old_str = *ret_str;
 427  428  
 428  429                  *ret_str = (char *)realloc(*ret_str, total_len + len + 1);
 429  430                  if (*ret_str == NULL) {
 430  431                          /* We're screwed */
 431  432                          free(old_str);
 432  433                          va_end(valist);
 433  434                          return;
 434  435                  }
 435  436  
 436  437                  (void) strcpy(*ret_str + total_len, str);
 437  438                  total_len += len;
 438  439          }
 439  440  
 440  441          va_end(valist);
 441  442  }
 442  443  
 443  444  /*
 444  445   * Error message handling.
 445  446   * For the rv passed in, looks up the corresponding error message string(s),
 446  447   * internationalized if necessary, and concatenates it into a new
 447  448   * memory buffer, and points *errstring to it.
 448  449   * Note not all rvs will result in an error message return, as not all
 449  450   * error conditions warrant a SATA-specific error message - for those
 450  451   * conditions the cfgadm generic messages are sufficient.
 451  452   *
 452  453   * Some messages may display ap_id or errno, which is why they are passed
 453  454   * in.
 454  455   */
 455  456  
 456  457  cfga_err_t
 457  458  sata_err_msg(
 458  459      char **errstring,
 459  460      cfga_sata_ret_t rv,
 460  461      const char *ap_id,
 461  462      int l_errno)
 462  463  {
 463  464          if (errstring == NULL) {
 464  465                  return (sata_msgs[rv].cfga_err);
 465  466          }
 466  467  
 467  468          /*
 468  469           * Generate the appropriate SATA-specific error message(s) (if any).
 469  470           */
 470  471          switch (rv) {
 471  472          case CFGA_SATA_OK:
 472  473          case CFGA_NACK:
 473  474                  /* Special case - do nothing.  */
 474  475                  break;
 475  476  
 476  477          case CFGA_SATA_UNKNOWN:
 477  478          case CFGA_SATA_DYNAMIC_AP:
 478  479          case CFGA_SATA_INTERNAL_ERROR:
 479  480          case CFGA_SATA_OPTIONS:
 480  481          case CFGA_SATA_ALLOC_FAIL:
 481  482          case CFGA_SATA_STATE:
 482  483          case CFGA_SATA_PRIV:
 483  484          case CFGA_SATA_OPNOTSUPP:
 484  485          case CFGA_SATA_DATA_ERROR:
 485  486                  /* These messages require no additional strings passed. */
 486  487                  set_msg(errstring, ERR_STR(rv), NULL);
 487  488                  break;
 488  489  
 489  490          case CFGA_SATA_HWOPNOTSUPP:
 490  491                  /* hardware-specific help needed */
 491  492                  set_msg(errstring, ERR_STR(rv), NULL);
 492  493                  set_msg(errstring, "\n",
 493  494                      dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]), NULL);
 494  495                  set_msg(errstring, sata_help[HELP_RESET_PORT], NULL);
 495  496                  set_msg(errstring, sata_help[HELP_RESET_DEVICE], NULL);
 496  497                  set_msg(errstring, sata_help[HELP_RESET_ALL],  NULL);
 497  498                  set_msg(errstring, sata_help[HELP_PORT_ACTIVATE], NULL);
 498  499                  set_msg(errstring, sata_help[HELP_PORT_DEACTIVATE], NULL);
 499  500                  set_msg(errstring, sata_help[HELP_PORT_SELF_TEST], NULL);
 500  501                  set_msg(errstring, sata_help[HELP_CNTRL_SELF_TEST], NULL);
 501  502                  break;
 502  503  
 503  504          case CFGA_SATA_AP:
 504  505          case CFGA_SATA_PORT:
 505  506          case CFGA_SATA_NOT_CONNECTED:
 506  507          case CFGA_SATA_NOT_CONFIGURED:
 507  508          case CFGA_SATA_ALREADY_CONNECTED:
 508  509          case CFGA_SATA_ALREADY_CONFIGURED:
 509  510          case CFGA_SATA_BUSY:
 510  511          case CFGA_SATA_DEVLINK:
 511  512          case CFGA_SATA_RCM_HANDLE:
 512  513          case CFGA_SATA_RCM_ONLINE:
 513  514          case CFGA_SATA_RCM_OFFLINE:
 514  515          case CFGA_SATA_RCM_INFO:
 515  516          case CFGA_SATA_DEV_CONFIGURE:
 516  517          case CFGA_SATA_DEV_UNCONFIGURE:
 517  518          case CFGA_SATA_DISCONNECTED:
 518  519                  /* These messages also print ap_id.  */
 519  520                  set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "", NULL);
 520  521                  break;
 521  522  
 522  523  
 523  524          case CFGA_SATA_IOCTL:
 524  525          case CFGA_SATA_NVLIST:
 525  526                  /* These messages also print errno.  */
 526  527                  {
 527  528                          char *errno_str = l_errno ? strerror(l_errno) : "";
 528  529  
 529  530                          set_msg(errstring, ERR_STR(rv), errno_str,
 530  531                              l_errno ? "\n" : "", NULL);
 531  532                          break;
 532  533                  }
 533  534  
 534  535          case CFGA_SATA_OPEN:
 535  536                  /* These messages also apid and errno.  */
 536  537                  {
 537  538                          char *errno_str = l_errno ? strerror(l_errno) : "";
 538  539  
 539  540                          set_msg(errstring, ERR_STR(rv), "ap_id: ", ap_id, "\n",
 540  541                              errno_str, l_errno ? "\n" : "", NULL);
 541  542                          break;
 542  543                  }
 543  544  
 544  545          default:
 545  546                  set_msg(errstring, ERR_STR(CFGA_SATA_INTERNAL_ERROR), NULL);
 546  547  
 547  548          } /* end switch */
 548  549  
 549  550  
 550  551          /*
 551  552           * Determine the proper error code to send back to the cfgadm library.
 552  553           */
 553  554          return (sata_msgs[rv].cfga_err);
 554  555  }
 555  556  
 556  557  
 557  558  /*
 558  559   * Entry points
 559  560   */
 560  561  /* cfgadm entry point */
 561  562  /*ARGSUSED*/
 562  563  cfga_err_t
 563  564  cfga_change_state(
 564  565      cfga_cmd_t state_change_cmd,
 565  566      const char *ap_id,
 566  567      const char *options,
 567  568      struct cfga_confirm *confp,
 568  569      struct cfga_msg *msgp,
 569  570      char **errstring,
 570  571      cfga_flags_t flags)
 571  572  {
 572  573          int             ret;
 573  574          int             len;
 574  575          char            *msg;
 575  576          char            *devpath;
 576  577          nvlist_t        *nvl = NULL;
 577  578          ap_rstate_t     rstate;
 578  579          ap_ostate_t     ostate;
 579  580          devctl_hdl_t    hdl = NULL;
 580  581          cfga_sata_ret_t rv = CFGA_SATA_OK;
 581  582          char            *pdyn;
 582  583          char            *str_type;
 583  584          size_t          size;
 584  585          boolean_t       pmult = B_FALSE;
 585  586  
 586  587          /*
 587  588           * All sub-commands which can change state of device require
 588  589           * root privileges.
 589  590           */
 590  591          if (geteuid() != 0) {
 591  592                  rv = CFGA_SATA_PRIV;
 592  593                  goto bailout;
 593  594          }
 594  595  
 595  596          if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
 596  597                  (void) cfga_help(msgp, options, flags);
 597  598                  goto bailout;
 598  599          }
 599  600  
 600  601          if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &nvl,
 601  602              DC_RDONLY)) != CFGA_SATA_OK) {
 602  603                  goto bailout;
 603  604          }
 604  605  
 605  606          /*
 606  607           * Checking device type. A port multiplier is not configurable - it is
 607  608           * already configured as soon as it is connected.
 608  609           */
 609  610          if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
 610  611              (void **)&str_type, &size)) != CFGA_SATA_OK) {
 611  612                  /* no such deivce */
 612  613                  goto bailout;
 613  614          }
 614  615          if (strncmp(str_type, "sata-pmult", sizeof ("sata-pmult")) == 0) {
 615  616                  pmult = B_TRUE;
 616  617          }
 617  618  
 618  619          switch (state_change_cmd) {
 619  620          case CFGA_CMD_CONFIGURE:
 620  621                  if (pmult == B_TRUE) {
 621  622                          rv = CFGA_SATA_HWOPNOTSUPP;
 622  623                          goto bailout;
 623  624                  }
 624  625  
 625  626                  if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
 626  627                      CFGA_SATA_OK)
 627  628                          goto bailout;
 628  629  
 629  630                  if (ostate == AP_OSTATE_CONFIGURED) {
 630  631                          rv = CFGA_SATA_ALREADY_CONFIGURED;
 631  632                          goto bailout;
 632  633                  }
 633  634                  /* Disallow dynamic AP name component */
 634  635                  if (GET_DYN(ap_id) != NULL) {
 635  636                          rv = CFGA_SATA_INVALID_DEVNAME;
 636  637                          goto bailout;
 637  638                  }
 638  639  
 639  640                  if (rstate == AP_RSTATE_EMPTY) {
 640  641                          rv = CFGA_SATA_NOT_CONNECTED;
 641  642                          goto bailout;
 642  643                  }
 643  644                  rv = CFGA_SATA_OK;
 644  645  
 645  646                  if (devctl_ap_configure(hdl, nvl) != 0) {
 646  647                          rv = CFGA_SATA_DEV_CONFIGURE;
 647  648                          goto bailout;
 648  649                  }
 649  650  
 650  651                  devpath = sata_get_devicepath(ap_id);
 651  652                  if (devpath == NULL) {
 652  653                          int i;
 653  654                          /*
 654  655                           * Try for some time as SATA hotplug thread
 655  656                           * takes a while to create the path then
 656  657                           * eventually give up.
 657  658                           */
 658  659                          for (i = 0; i < 12 && (devpath == NULL); i++) {
 659  660                                  (void) sleep(6);
 660  661                                  devpath = sata_get_devicepath(ap_id);
 661  662                          }
 662  663  
 663  664                          if (devpath == NULL) {
 664  665                                  rv = CFGA_SATA_DEV_CONFIGURE;
 665  666                                  break;
 666  667                          }
 667  668                  }
 668  669  
 669  670                  S_FREE(devpath);
 670  671                  break;
 671  672  
 672  673          case CFGA_CMD_UNCONFIGURE:
 673  674                  if (pmult == B_TRUE) {
 674  675                          rv = CFGA_SATA_HWOPNOTSUPP;
 675  676                          goto bailout;
 676  677                  }
 677  678  
 678  679                  if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
 679  680                      CFGA_SATA_OK)
 680  681                          goto bailout;
 681  682  
 682  683                  if (rstate != AP_RSTATE_CONNECTED) {
 683  684                          rv = CFGA_SATA_NOT_CONNECTED;
 684  685                          goto bailout;
 685  686                  }
 686  687  
 687  688                  if (ostate != AP_OSTATE_CONFIGURED) {
 688  689                          rv = CFGA_SATA_NOT_CONFIGURED;
 689  690                          goto bailout;
 690  691                  }
 691  692                  /* Strip off AP name dynamic component, if present */
 692  693                  if ((pdyn = GET_DYN(ap_id)) != NULL) {
 693  694                          *pdyn = '\0';
 694  695                  }
 695  696  
 696  697                  rv = CFGA_SATA_OK;
 697  698  
 698  699                  len = strlen(SATA_CONFIRM_DEVICE) +
 699  700                      strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 700  701                      strlen("Unconfigure") + strlen(ap_id);
 701  702                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 702  703                          (void) snprintf(msg, len + 3, "Unconfigure"
 703  704                              " %s%s\n%s",
 704  705                              SATA_CONFIRM_DEVICE, ap_id,
 705  706                              SATA_CONFIRM_DEVICE_SUSPEND);
 706  707                  }
  
    | 
      ↓ open down ↓ | 
    673 lines elided | 
    
      ↑ open up ↑ | 
  
 707  708  
 708  709                  if (!sata_confirm(confp, msg)) {
 709  710                          free(msg);
 710  711                          rv = CFGA_SATA_NACK;
 711  712                          break;
 712  713                  }
 713  714                  free(msg);
 714  715  
 715  716                  devpath = sata_get_devicepath(ap_id);
 716  717                  if (devpath == NULL) {
 717      -                        (void) printf(
      718 +                        DPRINTF(
 718  719                              "cfga_change_state: get device path failed\n");
 719  720                          rv = CFGA_SATA_DEV_UNCONFIGURE;
 720  721                          break;
 721  722                  }
 722  723  
 723  724                  if ((rv = sata_rcm_offline(ap_id, errstring, devpath, flags))
 724  725                      != CFGA_SATA_OK) {
 725  726                          break;
 726  727                  }
 727  728  
 728  729                  ret = devctl_ap_unconfigure(hdl, nvl);
 729  730  
 730  731                  if (ret != 0) {
 731  732                          rv = CFGA_SATA_DEV_UNCONFIGURE;
 732  733                          if (errno == EBUSY) {
 733  734                                  rv = CFGA_SATA_BUSY;
 734  735                          }
 735  736                          (void) sata_rcm_online(ap_id, errstring, devpath,
 736  737                              flags);
 737  738                  } else {
 738  739                          (void) sata_rcm_remove(ap_id, errstring, devpath,
 739  740                              flags);
 740  741  
 741  742                  }
 742  743                  S_FREE(devpath);
 743  744  
 744  745                  break;
 745  746  
 746  747          case CFGA_CMD_DISCONNECT:
 747  748                  if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
 748  749                      CFGA_SATA_OK)
 749  750                          goto bailout;
 750  751  
 751  752                  if (rstate == AP_RSTATE_DISCONNECTED) {
 752  753                          rv = CFGA_SATA_DISCONNECTED;
 753  754                          goto bailout;
 754  755                  }
 755  756  
 756  757                  /* Strip off AP name dynamic component, if present */
 757  758                  if ((pdyn = GET_DYN(ap_id)) != NULL) {
 758  759                          *pdyn = '\0';
 759  760                  }
 760  761  
 761  762  
 762  763                  rv = CFGA_SATA_OK; /* other statuses don't matter */
 763  764  
  
    | 
      ↓ open down ↓ | 
    36 lines elided | 
    
      ↑ open up ↑ | 
  
 764  765                  /*
 765  766                   * If the port originally with device attached and was
 766  767                   * unconfigured already, the devicepath for the sd will be
 767  768                   * removed. sata_get_devicepath in this case is not necessary.
 768  769                   */
 769  770                  /* only call rcm_offline if the state was CONFIGURED */
 770  771                  if (ostate == AP_OSTATE_CONFIGURED &&
 771  772                      pmult == B_FALSE) {
 772  773                          devpath = sata_get_devicepath(ap_id);
 773  774                          if (devpath == NULL) {
 774      -                                (void) printf(
      775 +                                DPRINTF(
 775  776                                      "cfga_change_state: get path failed\n");
 776  777                                  rv = CFGA_SATA_DEV_UNCONFIGURE;
 777  778                                  break;
 778  779                          }
 779  780  
 780  781                          len = strlen(SATA_CONFIRM_DEVICE) +
 781  782                              strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
 782  783                              strlen("Disconnect") + strlen(ap_id);
 783  784                          if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 784  785                                  (void) snprintf(msg, len + 3,
 785  786                                      "Disconnect"
 786  787                                      " %s%s\n%s",
 787  788                                      SATA_CONFIRM_DEVICE, ap_id,
 788  789                                      SATA_CONFIRM_DEVICE_SUSPEND);
 789  790                          }
 790  791                          if (!sata_confirm(confp, msg)) {
 791  792                                  free(msg);
 792  793                                  rv = CFGA_SATA_NACK;
 793  794                                  break;
 794  795                          }
 795  796                          free(msg);
 796  797  
 797  798                          if ((rv = sata_rcm_offline(ap_id, errstring,
 798  799                              devpath, flags)) != CFGA_SATA_OK) {
 799  800                                  break;
 800  801                          }
 801  802  
 802  803                          ret = devctl_ap_unconfigure(hdl, nvl);
 803  804                          if (ret != 0) {
 804  805                                  (void) printf(
 805  806                                      "devctl_ap_unconfigure failed\n");
 806  807                                  rv = CFGA_SATA_DEV_UNCONFIGURE;
 807  808                                  if (errno == EBUSY)
 808  809                                          rv = CFGA_SATA_BUSY;
 809  810                                  (void) sata_rcm_online(ap_id, errstring,
 810  811                                      devpath, flags);
 811  812                                  S_FREE(devpath);
 812  813  
 813  814                                  /*
 814  815                                   * The current policy is that if unconfigure
 815  816                                   * failed, do not continue with disconnect.
 816  817                                   * If the port needs to be forced into the
 817  818                                   * disconnect (shutdown) state,
 818  819                                   * the -x sata_port_poweroff command should be
 819  820                                   * used instead of -c disconnect
 820  821                                   */
 821  822                                  break;
 822  823                          } else {
 823  824                                  (void) printf("%s\n",
 824  825                                      ERR_STR(CFGA_SATA_DEVICE_UNCONFIGURED));
 825  826                                  (void) sata_rcm_remove(ap_id, errstring,
 826  827                                      devpath, flags);
 827  828                          }
 828  829                          S_FREE(devpath);
 829  830                  } else if (rstate == AP_RSTATE_CONNECTED ||
 830  831                      rstate == AP_RSTATE_EMPTY) {
 831  832                          len = strlen(SATA_CONFIRM_PORT) +
 832  833                              strlen(SATA_CONFIRM_PORT_DISABLE) +
 833  834                              strlen("Deactivate Port") + strlen(ap_id);
 834  835                          if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 835  836                                  (void) snprintf(msg, len +3,
 836  837                                      "Disconnect"
 837  838                                      " %s%s\n%s",
 838  839                                      SATA_CONFIRM_PORT, ap_id,
 839  840                                      SATA_CONFIRM_PORT_DISABLE);
 840  841                          }
 841  842                          if (!sata_confirm(confp, msg)) {
 842  843                                  free(msg);
 843  844                                  rv = CFGA_SATA_NACK;
 844  845                                  break;
 845  846                          }
 846  847                  }
 847  848                  ret = devctl_ap_disconnect(hdl, nvl);
 848  849                  if (ret != 0) {
 849  850                          rv = CFGA_SATA_IOCTL;
 850  851                          if (errno == EBUSY) {
 851  852                                  rv = CFGA_SATA_BUSY;
 852  853                          }
 853  854                  }
 854  855                  break;
 855  856  
 856  857          case CFGA_CMD_CONNECT:
 857  858                  if ((rv = port_state(hdl, nvl, &rstate, &ostate)) !=
 858  859                      CFGA_SATA_OK)
 859  860                          goto bailout;
 860  861  
 861  862                  if (rstate == AP_RSTATE_CONNECTED) {
 862  863                          rv = CFGA_SATA_ALREADY_CONNECTED;
 863  864                          goto bailout;
 864  865                  }
 865  866  
 866  867                  len = strlen(SATA_CONFIRM_PORT) +
 867  868                      strlen(SATA_CONFIRM_PORT_ENABLE) +
 868  869                      strlen("Activate Port") + strlen(ap_id);
 869  870                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 870  871                          (void) snprintf(msg, len +3, "Activate"
 871  872                              " %s%s\n%s",
 872  873                              SATA_CONFIRM_PORT, ap_id,
 873  874                              SATA_CONFIRM_PORT_ENABLE);
 874  875                  }
 875  876                  if (!sata_confirm(confp, msg)) {
 876  877                          rv = CFGA_SATA_NACK;
 877  878                          break;
 878  879                  }
 879  880  
 880  881                  /* Disallow dynamic AP name component */
 881  882                  if (GET_DYN(ap_id) != NULL) {
 882  883                          rv = CFGA_SATA_INVALID_DEVNAME;
 883  884                          goto bailout;
 884  885                  }
 885  886  
 886  887                  ret = devctl_ap_connect(hdl, nvl);
 887  888                  if (ret != 0) {
 888  889                          rv = CFGA_SATA_IOCTL;
 889  890                  } else {
 890  891                          rv = CFGA_SATA_OK;
 891  892                  }
 892  893  
 893  894                  break;
 894  895  
 895  896          case CFGA_CMD_LOAD:
 896  897          case CFGA_CMD_UNLOAD:
 897  898                  (void) cfga_help(msgp, options, flags);
 898  899                  rv = CFGA_SATA_OPNOTSUPP;
 899  900                  break;
 900  901  
 901  902          case CFGA_CMD_NONE:
 902  903          default:
 903  904                  (void) cfga_help(msgp, options, flags);
 904  905                  rv = CFGA_SATA_INTERNAL_ERROR;
 905  906          }
 906  907  
 907  908  bailout:
 908  909          cleanup_after_devctl_cmd(hdl, nvl);
 909  910  
 910  911          return (sata_err_msg(errstring, rv, ap_id, errno));
 911  912  }
 912  913  
 913  914  /* cfgadm entry point */
 914  915  cfga_err_t
 915  916  cfga_private_func(
 916  917      const char *func,
 917  918      const char *ap_id,
 918  919      const char *options,
 919  920      struct cfga_confirm *confp,
 920  921      struct cfga_msg *msgp,
 921  922      char **errstring,
 922  923      cfga_flags_t flags)
 923  924  {
 924  925          int                     len;
 925  926          char                    *msg;
 926  927          nvlist_t                *list = NULL;
 927  928          ap_ostate_t             ostate;
 928  929          ap_rstate_t             rstate;
 929  930          devctl_hdl_t            hdl = NULL;
 930  931          cfga_sata_ret_t         rv;
 931  932          char                    *str_p;
 932  933          size_t                  size;
 933  934  
 934  935          if ((rv = verify_params(ap_id, NULL, errstring)) != CFGA_SATA_OK) {
 935  936                  (void) cfga_help(msgp, options, flags);
 936  937                  return (sata_err_msg(errstring, rv, ap_id, errno));
 937  938          }
 938  939  
  
    | 
      ↓ open down ↓ | 
    154 lines elided | 
    
      ↑ open up ↑ | 
  
 939  940          /*
 940  941           * All subcommands which can change state of device require
 941  942           * root privileges.
 942  943           */
 943  944          if (geteuid() != 0) {
 944  945                  rv = CFGA_SATA_PRIV;
 945  946                  goto bailout;
 946  947          }
 947  948  
 948  949          if (func == NULL) {
 949      -                (void) printf("No valid option specified\n");
      950 +                DPRINTF("No valid option specified\n");
 950  951                  rv = CFGA_SATA_OPTIONS;
 951  952                  goto bailout;
 952  953          }
 953  954  
 954  955          if ((rv = setup_for_devctl_cmd(ap_id, &hdl, &list, 0)) !=
 955  956              CFGA_SATA_OK) {
 956  957                  goto bailout;
 957  958          }
 958  959  
 959  960          /* We do not care here about dynamic AP name component */
 960  961          if ((str_p = GET_DYN(ap_id)) != NULL) {
 961  962                  *str_p = '\0';
 962  963          }
 963  964  
 964  965          rv = CFGA_SATA_OK;
 965  966  
 966  967          if (strcmp(func, SATA_RESET_PORT) == 0) {
 967  968                  len = strlen(SATA_CONFIRM_PORT) +
 968  969                      strlen(SATA_CONFIRM_DEVICE_ABORT) +
 969  970                      strlen("Reset Port") + strlen(ap_id);
 970  971  
 971  972                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
 972  973                          (void) snprintf(msg, len +3, "Reset"
 973  974                              " %s%s\n%s",
 974  975                              SATA_CONFIRM_PORT, ap_id,
 975  976                              SATA_CONFIRM_DEVICE_ABORT);
 976  977                  } else {
 977  978                          rv = CFGA_SATA_NACK;
 978  979                          goto bailout;
 979  980                  }
 980  981  
 981  982                  if (!sata_confirm(confp, msg)) {
 982  983                          rv = CFGA_SATA_NACK;
 983  984                          goto bailout;
 984  985                  }
 985  986  
 986  987                  rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_PORT, NULL,
 987  988                      (void **)&str_p, &size);
 988  989  
 989  990          } else if (strcmp(func, SATA_RESET_DEVICE) == 0) {
 990  991                  if ((rv = port_state(hdl, list, &rstate, &ostate)) !=
 991  992                      CFGA_SATA_OK)
 992  993                          goto bailout;
 993  994                  /*
 994  995                   * Reset device function requires device to be connected
 995  996                   */
 996  997                  if (rstate != AP_RSTATE_CONNECTED) {
 997  998                          rv = CFGA_SATA_NOT_CONNECTED;
 998  999                          goto bailout;
 999 1000                  }
1000 1001  
1001 1002                  len = strlen(SATA_CONFIRM_DEVICE) +
1002 1003                      strlen(SATA_CONFIRM_DEVICE_ABORT) +
1003 1004                      strlen("Reset Device") + strlen(ap_id);
1004 1005  
1005 1006                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1006 1007                          (void) snprintf(msg, len +3, "Reset"
1007 1008                              " %s%s\n%s",
1008 1009                              SATA_CONFIRM_DEVICE, ap_id,
1009 1010                              SATA_CONFIRM_DEVICE_ABORT);
1010 1011                  } else {
1011 1012                          rv = CFGA_SATA_NACK;
1012 1013                          goto bailout;
1013 1014                  }
1014 1015  
1015 1016                  if (!sata_confirm(confp, msg)) {
1016 1017                          rv = CFGA_SATA_NACK;
1017 1018                          goto bailout;
1018 1019                  }
1019 1020  
1020 1021                  rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_DEVICE, NULL,
1021 1022                      (void **)&str_p, &size);
1022 1023  
1023 1024          } else if (strcmp(func, SATA_RESET_ALL) == 0) {
1024 1025                  len = strlen(SATA_CONFIRM_CONTROLLER) +
1025 1026                      strlen(SATA_CONFIRM_CONTROLLER_ABORT) +
1026 1027                      strlen("Reset All") + strlen(ap_id);
1027 1028  
1028 1029                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1029 1030                          (void) snprintf(msg, len +3, "Reset"
1030 1031                              " %s%s\n%s",
1031 1032                              SATA_CONFIRM_CONTROLLER, ap_id,
1032 1033                              SATA_CONFIRM_CONTROLLER_ABORT);
1033 1034                  } else {
1034 1035                          rv = CFGA_SATA_NACK;
1035 1036                          goto bailout;
1036 1037                  }
1037 1038  
1038 1039                  if (!sata_confirm(confp, msg)) {
1039 1040                          rv = CFGA_SATA_NACK;
1040 1041                          goto bailout;
1041 1042                  }
1042 1043                  rv = do_control_ioctl(ap_id, SATA_CFGA_RESET_ALL, NULL,
1043 1044                      (void **)&str_p, &size);
1044 1045  
1045 1046          } else if (strcmp(func, SATA_PORT_DEACTIVATE) == 0) {
1046 1047                  len = strlen(SATA_CONFIRM_PORT) +
1047 1048                      strlen(SATA_CONFIRM_PORT_DISABLE) +
1048 1049                      strlen("Deactivate Port") + strlen(ap_id);
1049 1050  
1050 1051                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1051 1052                          (void) snprintf(msg, len +3, "Deactivate"
1052 1053                              " %s%s\n%s",
1053 1054                              SATA_CONFIRM_PORT, ap_id,
1054 1055                              SATA_CONFIRM_PORT_DISABLE);
1055 1056                  } else {
1056 1057                          rv = CFGA_SATA_NACK;
1057 1058                          goto bailout;
1058 1059                  }
1059 1060                  if (!sata_confirm(confp, msg)) {
1060 1061                          rv = CFGA_SATA_NACK;
1061 1062                          goto bailout;
1062 1063                  }
1063 1064  
1064 1065                  rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_DEACTIVATE, NULL,
1065 1066                      (void **)&str_p, &size);
1066 1067  
1067 1068          } else if (strcmp(func, SATA_PORT_ACTIVATE) == 0) {
1068 1069                  len = strlen(SATA_CONFIRM_PORT) +
1069 1070                      strlen(SATA_CONFIRM_PORT_ENABLE) +
1070 1071                      strlen("Activate Port") + strlen(ap_id);
1071 1072  
1072 1073                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1073 1074                          (void) snprintf(msg, len +3, "Activate"
1074 1075                              " %s%s\n%s",
1075 1076                              SATA_CONFIRM_PORT, ap_id,
1076 1077                              SATA_CONFIRM_PORT_ENABLE);
1077 1078                  } else {
1078 1079                          rv = CFGA_SATA_NACK;
1079 1080                          goto bailout;
1080 1081                  }
1081 1082                  if (!sata_confirm(confp, msg)) {
1082 1083                          rv = CFGA_SATA_NACK;
1083 1084                          goto bailout;
1084 1085                  }
1085 1086  
1086 1087                  rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_ACTIVATE,
1087 1088                      NULL, (void **)&str_p, &size);
1088 1089                  goto bailout;
1089 1090  
1090 1091          } else if (strcmp(func, SATA_PORT_SELF_TEST) == 0) {
1091 1092                  len = strlen(SATA_CONFIRM_PORT) +
1092 1093                      strlen(SATA_CONFIRM_DEVICE_SUSPEND) +
1093 1094                      strlen("Self Test Port") + strlen(ap_id);
1094 1095  
1095 1096                  if ((msg = (char *)calloc(len +3, 1)) != NULL) {
1096 1097                          (void) snprintf(msg, len +3, "Self Test"
1097 1098                              " %s%s\n%s",
1098 1099                              SATA_CONFIRM_PORT, ap_id,
1099 1100                              SATA_CONFIRM_DEVICE_SUSPEND);
1100 1101                  } else {
1101 1102                          rv = CFGA_SATA_NACK;
1102 1103                          goto bailout;
1103 1104                  }
1104 1105                  if (!sata_confirm(confp, msg)) {
1105 1106                          rv = CFGA_SATA_NACK;
1106 1107                          goto bailout;
1107 1108                  }
1108 1109  
1109 1110                  rv = do_control_ioctl(ap_id, SATA_CFGA_PORT_SELF_TEST,
1110 1111                      NULL, (void **)&str_p, &size);
1111 1112          } else {
1112 1113                  /* Unrecognized operation request */
1113 1114                  rv = CFGA_SATA_HWOPNOTSUPP;
1114 1115          }
1115 1116  
1116 1117  bailout:
1117 1118          cleanup_after_devctl_cmd(hdl, list);
1118 1119  
1119 1120          return (sata_err_msg(errstring, rv, ap_id, errno));
1120 1121  
1121 1122  }
1122 1123  
1123 1124  /* cfgadm entry point */
1124 1125  /*ARGSUSED*/
1125 1126  cfga_err_t
1126 1127  cfga_test(
1127 1128      const char *ap_id,
1128 1129      const char *options,
1129 1130      struct cfga_msg *msgp,
1130 1131      char **errstring,
1131 1132      cfga_flags_t flags)
1132 1133  {
1133 1134          /* Should call ioctl for self test - phase 2 */
1134 1135          return (CFGA_OPNOTSUPP);
1135 1136  }
1136 1137  
1137 1138  
1138 1139  int
1139 1140  sata_check_target_node(di_node_t node, void *arg)
1140 1141  {
1141 1142          char *minorpath;
1142 1143          char *cp;
1143 1144  
1144 1145          minorpath = di_devfs_minor_path(di_minor_next(node, DI_MINOR_NIL));
1145 1146          if (minorpath != NULL) {
1146 1147                  if (strstr(minorpath, arg) != NULL) {
1147 1148                          cp = strrchr(minorpath, (int)*MINOR_SEP);
1148 1149                          if (cp != NULL) {
1149 1150                                  (void) strcpy(arg, cp);
1150 1151                          }
1151 1152                          free(minorpath);
1152 1153                          return (DI_WALK_TERMINATE);
1153 1154                  }
1154 1155                  free(minorpath);
1155 1156          }
1156 1157          return (DI_WALK_CONTINUE);
1157 1158  }
1158 1159  
1159 1160  struct chk_dev {
1160 1161          int c_isblk;
1161 1162          char *c_minor;
1162 1163  };
1163 1164  
1164 1165  /*ARGSUSED*/
1165 1166  static int
1166 1167  chk_dev_fcn(di_node_t node, di_minor_t minor, void *arg)
1167 1168  {
1168 1169          char    *mn;
1169 1170          struct chk_dev *chkp = (struct chk_dev *)arg;
1170 1171  
1171 1172          mn = di_minor_name(minor);
1172 1173          if (mn == NULL)
1173 1174                  return (DI_WALK_CONTINUE);
1174 1175  
1175 1176          if (strcmp(mn, chkp->c_minor) != 0)
1176 1177                  return (DI_WALK_CONTINUE);
1177 1178  
1178 1179          chkp->c_isblk = di_minor_spectype(minor) == S_IFBLK ? 1 : 0;
1179 1180  
1180 1181          return (DI_WALK_TERMINATE);
1181 1182  }
1182 1183  
1183 1184  /*
1184 1185   * Don't use devfs if stat() in /devices fails. Use libdevinfo instead.
1185 1186   * Retired devices don't show up in devfs.
1186 1187   *
1187 1188   *      Returns:
1188 1189   *              1 - minor exists and is of type BLK
1189 1190   *              0 - minor does not exist or is not of type BLK.
1190 1191   */
1191 1192  static int
1192 1193  is_devinfo_blk(char *minor_path)
1193 1194  {
1194 1195          char    *minor_portion;
1195 1196          struct chk_dev chk_dev;
1196 1197          di_node_t node;
1197 1198          int     rv;
1198 1199  
1199 1200          /*
1200 1201           * prune minor path for di_init() - no /devices prefix and no minor name
1201 1202           */
1202 1203          if (strncmp(minor_path, "/devices/", strlen("/devices/")) != 0)
1203 1204                  return (0);
1204 1205  
1205 1206          minor_portion = strrchr(minor_path, *MINOR_SEP);
1206 1207          if (minor_portion == NULL)
1207 1208                  return (0);
1208 1209  
1209 1210          *minor_portion = 0;
1210 1211  
1211 1212          node = di_init(minor_path + strlen("/devices"), DINFOMINOR);
1212 1213  
1213 1214          *minor_portion = *MINOR_SEP;
1214 1215  
1215 1216          if (node == DI_NODE_NIL)
1216 1217                  return (0);
1217 1218  
1218 1219          chk_dev.c_isblk = 0;
1219 1220          chk_dev.c_minor = minor_portion + 1;
1220 1221  
1221 1222          rv = di_walk_minor(node, NULL, 0, &chk_dev, chk_dev_fcn);
1222 1223  
1223 1224          di_fini(node);
1224 1225  
1225 1226          if (rv == 0 && chk_dev.c_isblk)
1226 1227                  return (1);
1227 1228          else
1228 1229                  return (0);
1229 1230  }
1230 1231  
1231 1232  /*
1232 1233   * The dynamic component buffer returned by this function has to be freed!
1233 1234   */
1234 1235  int
1235 1236  sata_make_dyncomp(const char *ap_id, char **dyncomp, const char *type)
1236 1237  {
1237 1238          char    *devpath = NULL;
1238 1239          char    *cp = NULL;
1239 1240          int     l_errno;
1240 1241          char    minor_path[MAXPATHLEN];
1241 1242          char    name_part[MAXNAMELEN];
1242 1243          char    *devlink = NULL;
1243 1244          char    *minor_portion = NULL;
1244 1245          int     deplen;
1245 1246          int     err;
1246 1247          DIR     *dp = NULL;
1247 1248          struct stat sb;
1248 1249          struct dirent *dep = NULL;
1249 1250          struct dirent *newdep = NULL;
  
    | 
      ↓ open down ↓ | 
    290 lines elided | 
    
      ↑ open up ↑ | 
  
1250 1251          char    *p;
1251 1252  
1252 1253          assert(dyncomp != NULL);
1253 1254  
1254 1255          /*
1255 1256           * Get target node path
1256 1257           */
1257 1258          devpath = sata_get_devicepath(ap_id);
1258 1259          if (devpath == NULL) {
1259 1260  
1260      -                (void) printf("cfga_list_ext: cannot locate target device\n");
     1261 +                DPRINTF("cfga_list_ext: cannot locate target device\n");
1261 1262                  return (CFGA_SATA_DYNAMIC_AP);
1262 1263  
1263 1264          } else {
1264 1265  
1265 1266                  cp = strrchr(devpath, *PATH_SEP);
1266 1267                  assert(cp != NULL);
1267 1268                  *cp = 0;        /* terminate path for opendir() */
1268 1269  
1269 1270                  (void) strncpy(name_part, cp + 1, MAXNAMELEN);
1270 1271  
1271 1272                  /*
1272 1273                   * Using libdevinfo for this is overkill and kills
1273 1274                   * performance when many consumers are using libcfgadm
1274 1275                   * concurrently.
1275 1276                   */
1276 1277                  if ((dp = opendir(devpath)) == NULL) {
1277 1278                          goto bailout;
1278 1279                  }
1279 1280  
1280 1281                  /*
1281 1282                   * deplen is large enough to fit the largest path-
1282 1283                   * struct dirent includes one byte (the terminator)
1283 1284                   * so we don't add 1 to the calculation here.
1284 1285                   */
1285 1286                  deplen = pathconf(devpath, _PC_NAME_MAX);
1286 1287                  deplen = ((deplen <= 0) ? MAXNAMELEN : deplen) +
1287 1288                      sizeof (struct dirent);
1288 1289                  dep = (struct dirent *)malloc(deplen);
1289 1290                  if (dep == NULL)
1290 1291                          goto bailout;
1291 1292  
1292 1293                  while ((err = readdir_r(dp, dep, &newdep)) == 0 &&
1293 1294                      newdep != NULL) {
1294 1295  
1295 1296                          assert(newdep == dep);
1296 1297  
1297 1298                          if (strcmp(dep->d_name, ".") == 0 ||
1298 1299                              strcmp(dep->d_name, "..") == 0 ||
1299 1300                              (minor_portion = strchr(dep->d_name,
1300 1301                              *MINOR_SEP)) == NULL)
1301 1302                                  continue;
1302 1303  
1303 1304                          *minor_portion = 0;
1304 1305                          if (strcmp(dep->d_name, name_part) != 0)
1305 1306                                  continue;
1306 1307                          *minor_portion = *MINOR_SEP;
1307 1308  
1308 1309                          (void) snprintf(minor_path, MAXPATHLEN,
1309 1310                              "%s/%s", devpath, dep->d_name);
1310 1311  
1311 1312                          /*
1312 1313                           * Break directly for tape device
1313 1314                           */
1314 1315                          if (strcmp(type, "tape") == 0)
1315 1316                                  break;
1316 1317  
1317 1318                          /*
1318 1319                           * If stat() fails, the device *may* be retired.
1319 1320                           * Check via libdevinfo if the device has a BLK minor.
1320 1321                           * We don't use libdevinfo all the time, since taking
1321 1322                           * a snapshot is slower than a stat().
1322 1323                           */
1323 1324                          if (stat(minor_path, &sb) < 0) {
1324 1325                                  if (is_devinfo_blk(minor_path)) {
1325 1326                                          break;
1326 1327                                  } else {
1327 1328                                          continue;
1328 1329                                  }
1329 1330                          }
1330 1331  
1331 1332                          if (S_ISBLK(sb.st_mode))
1332 1333                                  break;
1333 1334  
1334 1335                  }
1335 1336  
1336 1337                  (void) closedir(dp);
1337 1338                  free(dep);
1338 1339                  free(devpath);
1339 1340  
1340 1341                  dp = NULL;
1341 1342                  dep = NULL;
1342 1343                  devpath = NULL;
1343 1344  
1344 1345                  /*
1345 1346                   * If there was an error, or we didn't exit the loop
1346 1347                   * by finding a block or character device, bail out.
1347 1348                   */
1348 1349                  if (err != 0 || newdep == NULL)
1349 1350                          goto bailout;
1350 1351  
1351 1352                  /*
1352 1353                   * Look for links to the physical path in /dev/dsk
1353 1354                   * and /dev/rmt. So far, sata modue supports disk,
1354 1355                   * dvd and tape devices, so we will first look for
1355 1356                   * BLOCK devices, and then look for tape devices.
1356 1357                   */
1357 1358                  (void) physpath_to_devlink("/dev/dsk",
1358 1359                      minor_path, &devlink, &l_errno);
1359 1360  
1360 1361                  /* postprocess and copy logical name here */
1361 1362                  if (devlink != NULL) {
1362 1363                          /*
1363 1364                           * For disks, remove partition/slice info
1364 1365                           */
1365 1366                          if ((cp = strstr(devlink, "dsk/")) != NULL) {
1366 1367                                  /* cXtYdZ[(s[0..15])|(p[0..X])] */
1367 1368                                  if ((p = strchr(cp + 4, 'd')) != NULL) {
1368 1369                                          p++;    /* Skip the 'd' */
1369 1370                                          while (*p != 0 && isdigit(*p))
1370 1371                                                  p++;
1371 1372                                          *p = 0;
1372 1373                                  }
1373 1374                                  *dyncomp = strdup(cp);
1374 1375                          }
1375 1376  
1376 1377                          free(devlink);
1377 1378                  } else if (strcmp(type, "tape") == 0) {
1378 1379  
1379 1380                          /*
1380 1381                           * For tape device, logical name looks like
1381 1382                           * rmt/X
1382 1383                           */
1383 1384                          (void) physpath_to_devlink("/dev/rmt",
1384 1385                              minor_path, &devlink, &l_errno);
1385 1386  
1386 1387                          if (devlink != NULL) {
1387 1388                                  if ((cp = strstr(devlink, "rmt/")) != NULL) {
1388 1389                                          *dyncomp = strdup(cp);
1389 1390                                  }
1390 1391  
1391 1392                                  free(devlink);
1392 1393                          }
1393 1394                  }
1394 1395  
1395 1396                  return (SATA_CFGA_OK);
1396 1397          }
1397 1398  
1398 1399  bailout:
1399 1400          if (dp)
1400 1401                  (void) closedir(dp);
1401 1402          if (devpath)
1402 1403                  free(devpath);
1403 1404          if (dep)
1404 1405                  free(dep);
1405 1406          return (CFGA_SATA_DYNAMIC_AP);
1406 1407  }
1407 1408  
1408 1409  /* cfgadm entry point */
1409 1410  /*ARGSUSED*/
1410 1411  cfga_err_t
1411 1412  cfga_list_ext(
1412 1413      const char *ap_id,
1413 1414      cfga_list_data_t **ap_id_list,
1414 1415      int *nlistp,
1415 1416      const char *options,
1416 1417      const char *listopts,
1417 1418      char **errstring,
1418 1419      cfga_flags_t flags)
1419 1420  {
1420 1421          int                     l_errno;
1421 1422          char                    *ap_id_log = NULL;
1422 1423          size_t                  size;
1423 1424          nvlist_t                *user_nvlist = NULL;
1424 1425          devctl_hdl_t            devctl_hdl = NULL;
1425 1426          cfga_sata_ret_t         rv = CFGA_SATA_OK;
1426 1427          devctl_ap_state_t       devctl_ap_state;
1427 1428          char                    *pdyn;
1428 1429          boolean_t               pmult = B_FALSE;
1429 1430          uint32_t                port;
1430 1431  
1431 1432  
1432 1433          if ((rv = verify_params(ap_id, options, errstring)) != CFGA_SATA_OK) {
1433 1434                  (void) cfga_help(NULL, options, flags);
1434 1435                  goto bailout;
1435 1436          }
1436 1437          /* We do not care here about dynamic AP name component */
1437 1438          if ((pdyn = GET_DYN(ap_id)) != NULL) {
1438 1439                  *pdyn = '\0';
1439 1440          }
1440 1441  
1441 1442          if (ap_id_list == NULL || nlistp == NULL) {
1442 1443                  rv = CFGA_SATA_DATA_ERROR;
1443 1444                  (void) cfga_help(NULL, options, flags);
1444 1445                  goto bailout;
1445 1446          }
1446 1447  
1447 1448          /* Get ap status */
1448 1449          if ((rv = setup_for_devctl_cmd(ap_id, &devctl_hdl, &user_nvlist,
1449 1450              DC_RDONLY)) != CFGA_SATA_OK) {
1450 1451                  goto bailout;
1451 1452          }
1452 1453  
1453 1454          /* will call dc_cmd to send IOCTL to kernel */
1454 1455          if (devctl_ap_getstate(devctl_hdl, user_nvlist,
1455 1456              &devctl_ap_state) == -1) {
1456 1457                  cleanup_after_devctl_cmd(devctl_hdl, user_nvlist);
1457 1458                  rv = CFGA_SATA_IOCTL;
1458 1459                  goto bailout;
1459 1460          }
1460 1461  
1461 1462          cleanup_after_devctl_cmd(devctl_hdl, user_nvlist);
1462 1463  
1463 1464          /*
1464 1465           * Create cfga_list_data_t struct.
1465 1466           */
1466 1467          if ((*ap_id_list =
1467 1468              (cfga_list_data_t *)malloc(sizeof (**ap_id_list))) == NULL) {
1468 1469                  rv = CFGA_SATA_ALLOC_FAIL;
1469 1470                  goto bailout;
1470 1471          }
1471 1472          *nlistp = 1;
1472 1473  
1473 1474          /*
1474 1475           * Rest of the code fills in the cfga_list_data_t struct.
1475 1476           */
1476 1477  
1477 1478          /* Get /dev/cfg path to corresponding to the physical ap_id */
1478 1479          /* Remember ap_id_log must be freed */
1479 1480          rv = physpath_to_devlink(CFGA_DEV_DIR, (char *)ap_id,
1480 1481              &ap_id_log, &l_errno);
1481 1482  
1482 1483          if (rv != 0) {
1483 1484                  rv = CFGA_SATA_DEVLINK;
1484 1485                  goto bailout;
1485 1486          }
1486 1487  
1487 1488          /* Get logical ap_id corresponding to the physical */
1488 1489          if (ap_id_log == NULL || strstr(ap_id_log, CFGA_DEV_DIR) == NULL) {
1489 1490                  rv = CFGA_SATA_DEVLINK;
1490 1491                  goto bailout;
1491 1492          }
1492 1493  
1493 1494          (void) strlcpy((*ap_id_list)->ap_log_id,
1494 1495              /* Strip off /dev/cfg/ */ ap_id_log + strlen(CFGA_DEV_DIR)+ 1,
1495 1496              sizeof ((*ap_id_list)->ap_log_id));
1496 1497  
1497 1498          free(ap_id_log);
1498 1499          ap_id_log = NULL;
1499 1500  
1500 1501          (void) strlcpy((*ap_id_list)->ap_phys_id, ap_id,
1501 1502              sizeof ((*ap_id_list)->ap_phys_id));
1502 1503  
1503 1504          switch (devctl_ap_state.ap_rstate) {
1504 1505          case AP_RSTATE_EMPTY:
1505 1506                  (*ap_id_list)->ap_r_state = CFGA_STAT_EMPTY;
1506 1507                  break;
1507 1508  
1508 1509          case AP_RSTATE_DISCONNECTED:
1509 1510                  (*ap_id_list)->ap_r_state = CFGA_STAT_DISCONNECTED;
1510 1511                  break;
1511 1512  
1512 1513          case AP_RSTATE_CONNECTED:
1513 1514                  (*ap_id_list)->ap_r_state = CFGA_STAT_CONNECTED;
1514 1515                  break;
1515 1516  
1516 1517          default:
1517 1518                  rv = CFGA_SATA_STATE;
1518 1519                  goto bailout;
1519 1520          }
1520 1521  
1521 1522          switch (devctl_ap_state.ap_ostate) {
1522 1523          case AP_OSTATE_CONFIGURED:
1523 1524                  (*ap_id_list)->ap_o_state = CFGA_STAT_CONFIGURED;
1524 1525                  break;
1525 1526  
1526 1527          case AP_OSTATE_UNCONFIGURED:
1527 1528                  (*ap_id_list)->ap_o_state = CFGA_STAT_UNCONFIGURED;
1528 1529                  break;
1529 1530  
1530 1531          default:
1531 1532                  rv = CFGA_SATA_STATE;
1532 1533                  goto bailout;
1533 1534          }
1534 1535  
1535 1536          switch (devctl_ap_state.ap_condition) {
1536 1537          case AP_COND_OK:
1537 1538                  (*ap_id_list)->ap_cond = CFGA_COND_OK;
1538 1539                  break;
1539 1540  
1540 1541          case AP_COND_FAILING:
1541 1542                  (*ap_id_list)->ap_cond = CFGA_COND_FAILING;
1542 1543                  break;
1543 1544  
1544 1545          case AP_COND_FAILED:
1545 1546                  (*ap_id_list)->ap_cond = CFGA_COND_FAILED;
1546 1547                  break;
1547 1548  
1548 1549          case AP_COND_UNUSABLE:
1549 1550                  (*ap_id_list)->ap_cond = CFGA_COND_UNUSABLE;
1550 1551                  break;
1551 1552  
1552 1553          case AP_COND_UNKNOWN:
1553 1554                  (*ap_id_list)->ap_cond = CFGA_COND_UNKNOWN;
1554 1555                  break;
1555 1556  
1556 1557          default:
1557 1558                  rv = CFGA_SATA_STATE;
1558 1559                  goto bailout;
1559 1560          }
1560 1561  
1561 1562          (*ap_id_list)->ap_class[0] = '\0';      /* Filled by libcfgadm */
1562 1563          (*ap_id_list)->ap_busy = devctl_ap_state.ap_in_transition;
1563 1564          (*ap_id_list)->ap_status_time = devctl_ap_state.ap_last_change;
1564 1565          (*ap_id_list)->ap_info[0] = NULL;
1565 1566  
  
    | 
      ↓ open down ↓ | 
    295 lines elided | 
    
      ↑ open up ↑ | 
  
1566 1567          if ((*ap_id_list)->ap_r_state == CFGA_STAT_CONNECTED) {
1567 1568                  char *str_p;
1568 1569                  int skip, i;
1569 1570  
1570 1571                  /*
1571 1572                   * Fill in the 'Information' field for the -v option
1572 1573                   * Model (MOD:)
1573 1574                   */
1574 1575                  if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_MODEL_INFO,
1575 1576                      NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1576      -                        (void) printf(
     1577 +                        DPRINTF(
1577 1578                              "SATA_CFGA_GET_MODULE_INFO ioctl failed\n");
1578 1579                          goto bailout;
1579 1580                  }
1580 1581                  /* drop leading and trailing spaces */
1581 1582                  skip = strspn(str_p, " ");
1582 1583                  for (i = size - 1; i >= 0; i--) {
1583 1584                          if (str_p[i] == '\040')
1584 1585                                  str_p[i] = '\0';
1585 1586                          else if (str_p[i] != '\0')
1586 1587                                  break;
1587 1588                  }
1588 1589  
1589 1590                  (void) strlcpy((*ap_id_list)->ap_info, "Mod: ",
1590 1591                      sizeof ((*ap_id_list)->ap_info));
1591 1592                  (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1592 1593                      sizeof ((*ap_id_list)->ap_info));
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
1593 1594  
1594 1595                  free(str_p);
1595 1596  
1596 1597                  /*
1597 1598                   * Fill in the 'Information' field for the -v option
1598 1599                   * Firmware revision (FREV:)
1599 1600                   */
1600 1601                  if ((rv = do_control_ioctl(ap_id,
1601 1602                      SATA_CFGA_GET_REVFIRMWARE_INFO,
1602 1603                      NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1603      -                        (void) printf(
     1604 +                        DPRINTF(
1604 1605                              "SATA_CFGA_GET_REVFIRMWARE_INFO ioctl failed\n");
1605 1606                          goto bailout;
1606 1607                  }
1607 1608                  /* drop leading and trailing spaces */
1608 1609                  skip = strspn(str_p, " ");
1609 1610                  for (i = size - 1; i >= 0; i--) {
1610 1611                          if (str_p[i] == '\040')
1611 1612                                  str_p[i] = '\0';
1612 1613                          else if (str_p[i] != '\0')
1613 1614                                  break;
1614 1615                  }
1615 1616                  (void) strlcat((*ap_id_list)->ap_info, " FRev: ",
1616 1617                      sizeof ((*ap_id_list)->ap_info));
1617 1618                  (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
1618 1619                      sizeof ((*ap_id_list)->ap_info));
1619 1620  
  
    | 
      ↓ open down ↓ | 
    6 lines elided | 
    
      ↑ open up ↑ | 
  
1620 1621                  free(str_p);
1621 1622  
1622 1623  
1623 1624                  /*
1624 1625                   * Fill in the 'Information' field for the -v option
1625 1626                   * Serial Number (SN:)
1626 1627                   */
1627 1628                  if ((rv = do_control_ioctl(ap_id,
1628 1629                      SATA_CFGA_GET_SERIALNUMBER_INFO,
1629 1630                      NULL, (void **)&str_p, &size)) != CFGA_SATA_OK) {
1630      -                        (void) printf(
     1631 +                        DPRINTF(
1631 1632                              "SATA_CFGA_GET_SERIALNUMBER_INFO ioctl failed\n");
1632 1633                          goto bailout;
1633 1634                  }
1634 1635                  /* drop leading and trailing spaces */
1635 1636                  skip = strspn(str_p, " ");
1636 1637                  for (i = size - 1; i >= 0; i--) {
1637 1638                          if (str_p[i] == '\040')
1638 1639                                  str_p[i] = '\0';
1639 1640                          else if (str_p[i] != '\0')
1640 1641                                  break;
1641 1642                  }
1642 1643                  (void) strlcat((*ap_id_list)->ap_info, " SN: ",
1643 1644                      sizeof ((*ap_id_list)->ap_info));
1644 1645                  (void) strlcat((*ap_id_list)->ap_info, str_p + skip,
  
    | 
      ↓ open down ↓ | 
    4 lines elided | 
    
      ↑ open up ↑ | 
  
1645 1646                      sizeof ((*ap_id_list)->ap_info));
1646 1647  
1647 1648                  free(str_p);
1648 1649  
1649 1650  
1650 1651  
1651 1652                  /* Fill in ap_type which is collected from HBA driver */
1652 1653                  /* call do_control_ioctl TBD */
1653 1654                  if ((rv = do_control_ioctl(ap_id, SATA_CFGA_GET_AP_TYPE, NULL,
1654 1655                      (void **)&str_p, &size)) != CFGA_SATA_OK) {
1655      -                        (void) printf(
     1656 +                        DPRINTF(
1656 1657                              "SATA_CFGA_GET_AP_TYPE ioctl failed\n");
1657 1658                          goto bailout;
1658 1659                  }
1659 1660  
1660 1661                  (void) strlcpy((*ap_id_list)->ap_type, str_p,
1661 1662                      sizeof ((*ap_id_list)->ap_type));
1662 1663  
1663 1664                  free(str_p);
1664 1665  
1665 1666                  /*
1666 1667                   * Checking device type. Port multiplier has no dynamic
1667 1668                   * suffix.
1668 1669                   */
1669 1670                  if (strncmp((*ap_id_list)->ap_type, "sata-pmult",
1670 1671                      sizeof ("sata-pmult")) == 0)
1671 1672                          pmult = B_TRUE;
1672 1673  
1673 1674                  if ((*ap_id_list)->ap_o_state == CFGA_STAT_CONFIGURED &&
1674 1675                      pmult == B_FALSE) {
1675 1676  
1676 1677                          char *dyncomp = NULL;
1677 1678  
1678 1679                          /*
1679 1680                           * This is the case where we need to generate
1680 1681                           * a dynamic component of the ap_id, i.e. device.
1681 1682                           */
1682 1683                          rv = sata_make_dyncomp(ap_id, &dyncomp,
1683 1684                              (*ap_id_list)->ap_type);
1684 1685                          if (rv != CFGA_SATA_OK)
1685 1686                                  goto bailout;
1686 1687                          if (dyncomp != NULL) {
1687 1688                                  (void) strcat((*ap_id_list)->ap_log_id,
1688 1689                                      DYN_SEP);
1689 1690                                  (void) strlcat((*ap_id_list)->ap_log_id,
1690 1691                                      dyncomp,
1691 1692                                      sizeof ((*ap_id_list)->ap_log_id));
1692 1693                                  free(dyncomp);
1693 1694                          }
1694 1695                  }
1695 1696  
1696 1697          } else {
1697 1698                  /* This is an empty port */
1698 1699                  if (get_port_num(ap_id, &port) != CFGA_SATA_OK) {
1699 1700                          goto bailout;
1700 1701                  }
1701 1702  
1702 1703                  if (port & SATA_CFGA_PMPORT_QUAL) {
1703 1704                          (void) strlcpy((*ap_id_list)->ap_type, "pmult-port",
1704 1705                              sizeof ((*ap_id_list)->ap_type));
1705 1706                  } else {
1706 1707                          (void) strlcpy((*ap_id_list)->ap_type, "sata-port",
1707 1708                              sizeof ((*ap_id_list)->ap_type));
1708 1709                  }
1709 1710          }
1710 1711  
1711 1712          return (sata_err_msg(errstring, rv, ap_id, errno));
1712 1713  
1713 1714  bailout:
1714 1715          if (*ap_id_list != NULL) {
1715 1716                  free(*ap_id_list);
1716 1717          }
1717 1718          if (ap_id_log != NULL) {
1718 1719                  free(ap_id_log);
1719 1720          }
1720 1721  
1721 1722          return (sata_err_msg(errstring, rv, ap_id, errno));
1722 1723  }
1723 1724  /*
  
    | 
      ↓ open down ↓ | 
    58 lines elided | 
    
      ↑ open up ↑ | 
  
1724 1725   * This routine accepts a string adn prints it using
1725 1726   * the message print routine argument.
1726 1727   */
1727 1728  static void
1728 1729  cfga_msg(struct cfga_msg *msgp, const char *str)
1729 1730  {
1730 1731          int len;
1731 1732          char *q;
1732 1733  
1733 1734          if (msgp == NULL || msgp->message_routine == NULL) {
1734      -                (void) printf("cfga_msg: NULL msgp\n");
     1735 +                DPRINTF("cfga_msg: msg\n");
1735 1736                  return;
1736 1737          }
1737 1738  
1738 1739          if ((len = strlen(str)) == 0) {
1739      -                (void) printf("cfga_msg: null str\n");
     1740 +                DPRINTF("cfga_msg: null str\n");
1740 1741                  return;
1741 1742          }
1742 1743  
1743 1744          if ((q = (char *)calloc(len + 1, 1)) == NULL) {
1744      -                perror("cfga_msg");
     1745 +                DPRINTF("cfga_msg: null q\n");
1745 1746                  return;
1746 1747          }
1747 1748  
1748 1749          (void) strcpy(q, str);
1749 1750          (*msgp->message_routine)(msgp->appdata_ptr, q);
1750 1751  
1751 1752          free(q);
1752 1753  }
1753 1754  
1754 1755  /* cfgadm entry point */
1755 1756  /* ARGSUSED */
1756 1757  cfga_err_t
1757 1758  cfga_help(struct cfga_msg *msgp, const char *options, cfga_flags_t flags)
1758 1759  {
1759 1760          if (options != NULL) {
1760 1761                  cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_UNKNOWN]));
1761 1762                  cfga_msg(msgp, options);
1762 1763          }
1763 1764          cfga_msg(msgp, dgettext(TEXT_DOMAIN, sata_help[HELP_HEADER]));
1764 1765          cfga_msg(msgp, sata_help[HELP_CONFIG]);
1765 1766          cfga_msg(msgp, sata_help[HELP_RESET_PORT]);
1766 1767          cfga_msg(msgp, sata_help[HELP_RESET_DEVICE]);
1767 1768          cfga_msg(msgp, sata_help[HELP_RESET_ALL]);
1768 1769          cfga_msg(msgp, sata_help[HELP_PORT_ACTIVATE]);
1769 1770          cfga_msg(msgp, sata_help[HELP_PORT_DEACTIVATE]);
1770 1771          cfga_msg(msgp, sata_help[HELP_PORT_SELF_TEST]);
1771 1772          cfga_msg(msgp, sata_help[HELP_CNTRL_SELF_TEST]);
1772 1773  
1773 1774          return (CFGA_OK);
1774 1775  }
1775 1776  
1776 1777  
1777 1778  /*
1778 1779   * Ensure the ap_id passed is in the correct (physical ap_id) form:
1779 1780   *     path/device:xx[.xx]
1780 1781   * where xx is a one or two-digit number.
1781 1782   *
1782 1783   * Note the library always calls the plugin with a physical ap_id.
1783 1784   */
1784 1785  static int
1785 1786  verify_valid_apid(const char *ap_id)
1786 1787  {
1787 1788          char    *l_ap_id;
1788 1789  
1789 1790          if (ap_id == NULL)
1790 1791                  return (-1);
1791 1792  
1792 1793          l_ap_id = strrchr(ap_id, (int)*MINOR_SEP);
1793 1794          l_ap_id++;
1794 1795  
1795 1796          if (strspn(l_ap_id, "0123456789.") != strlen(l_ap_id)) {
1796 1797                  /* Bad characters in the ap_id */
1797 1798                  return (-1);
1798 1799          }
1799 1800  
1800 1801          if (strstr(l_ap_id, "..") != NULL) {
1801 1802                  /* ap_id has 1..2 or more than 2 dots */
1802 1803                  return (-1);
1803 1804          }
1804 1805  
1805 1806          return (0);
1806 1807  }
1807 1808  
1808 1809  
1809 1810  
1810 1811  /*
1811 1812   * Verify the params passed in are valid.
1812 1813   */
1813 1814  static cfga_sata_ret_t
1814 1815  verify_params(
1815 1816      const char *ap_id,
1816 1817      const char *options,
  
    | 
      ↓ open down ↓ | 
    62 lines elided | 
    
      ↑ open up ↑ | 
  
1817 1818      char **errstring)
1818 1819  {
1819 1820          char *pdyn, *lap_id;
1820 1821          int rv;
1821 1822  
1822 1823          if (errstring != NULL) {
1823 1824                  *errstring = NULL;
1824 1825          }
1825 1826  
1826 1827          if (options != NULL) {
     1828 +                DPRINTF("verify_params: hardware-specific options not "
     1829 +                    "supported.\n");
1827 1830                  return (CFGA_SATA_OPTIONS);
1828 1831          }
1829 1832  
1830 1833          /* Strip dynamic AP name component if it is present. */
1831 1834          lap_id = strdup(ap_id);
1832 1835          if (lap_id == NULL) {
1833 1836                  return (CFGA_SATA_ALLOC_FAIL);
1834 1837          }
1835 1838          if ((pdyn = GET_DYN(lap_id)) != NULL) {
1836 1839                  *pdyn = '\0';
1837 1840          }
1838 1841  
1839 1842          if (verify_valid_apid(lap_id) != 0) {
     1843 +                DPRINTF("verify_params: not a SATA ap_id.\n");
1840 1844                  rv = CFGA_SATA_AP;
1841 1845          } else {
1842 1846                  rv = CFGA_SATA_OK;
1843 1847          }
1844 1848          free(lap_id);
1845 1849  
1846 1850          return (rv);
1847 1851  }
1848 1852  
1849 1853  /*
1850 1854   * Takes a validated ap_id and extracts the port number.
1851 1855   * Port multiplier is supported now.
1852 1856   */
1853 1857  static cfga_sata_ret_t
1854 1858  get_port_num(const char *ap_id, uint32_t *port)
1855 1859  {
1856 1860          uint32_t        cport, pmport = 0, qual = 0;
1857 1861          char            *cport_str, *pmport_str;
1858 1862  
1859 1863          /* Get the cport number */
1860 1864          cport_str = strrchr(ap_id, (int)*MINOR_SEP) + strlen(MINOR_SEP);
1861 1865  
1862 1866          errno = 0;
1863 1867          cport = strtol(cport_str, NULL, 10);
1864 1868          if ((cport & ~SATA_CFGA_CPORT_MASK) != 0 || errno != 0) {
1865 1869                  return (CFGA_SATA_PORT);
1866 1870          }
1867 1871  
1868 1872          /* Get pmport number if there is a PORT_SEPARATOR */
1869 1873          errno = 0;
1870 1874          if ((pmport_str = strrchr(ap_id, (int)*PORT_SEPARATOR)) != 0) {
1871 1875                  pmport_str += strlen(PORT_SEPARATOR);
1872 1876                  pmport = strtol(pmport_str, NULL, 10);
1873 1877                  qual = SATA_CFGA_PMPORT_QUAL;
1874 1878                  if ((pmport & ~SATA_CFGA_PMPORT_MASK) != 0 || errno != 0) {
1875 1879                          return (CFGA_SATA_PORT);
1876 1880                  }
1877 1881          }
1878 1882  
1879 1883          *port = cport | (pmport << SATA_CFGA_PMPORT_SHIFT) | qual;
1880 1884          return (CFGA_SATA_OK);
1881 1885  }
1882 1886  
1883 1887  /*
1884 1888   * Pair of routines to set up for/clean up after a devctl_ap_* lib call.
1885 1889   */
1886 1890  static void
1887 1891  cleanup_after_devctl_cmd(devctl_hdl_t devctl_hdl, nvlist_t *user_nvlist)
1888 1892  {
1889 1893          if (user_nvlist != NULL) {
1890 1894                  nvlist_free(user_nvlist);
1891 1895          }
1892 1896          if (devctl_hdl != NULL) {
1893 1897                  devctl_release(devctl_hdl);
1894 1898          }
1895 1899  }
1896 1900  
1897 1901  static cfga_sata_ret_t
1898 1902  setup_for_devctl_cmd(
1899 1903      const char *ap_id,
1900 1904      devctl_hdl_t *devctl_hdl,
1901 1905      nvlist_t **user_nvlistp,
1902 1906      uint_t oflag)
1903 1907  {
1904 1908  
1905 1909          uint_t  port;
1906 1910          cfga_sata_ret_t rv = CFGA_SATA_OK;
1907 1911          char *lap_id, *pdyn;
1908 1912  
1909 1913          lap_id = strdup(ap_id);
1910 1914          if (lap_id == NULL)
1911 1915                  return (CFGA_SATA_ALLOC_FAIL);
1912 1916          if ((pdyn = GET_DYN(lap_id)) != NULL) {
1913 1917                  *pdyn = '\0';
1914 1918          }
1915 1919  
1916 1920          /* Get a devctl handle to pass to the devctl_ap_XXX functions */
1917 1921          if ((*devctl_hdl = devctl_ap_acquire((char *)lap_id, oflag)) == NULL) {
1918 1922                  (void) fprintf(stderr, "[libcfgadm:sata] "
  
    | 
      ↓ open down ↓ | 
    69 lines elided | 
    
      ↑ open up ↑ | 
  
1919 1923                      "setup_for_devctl_cmd: devctl_ap_acquire failed: %s\n",
1920 1924                      strerror(errno));
1921 1925                  rv = CFGA_SATA_DEVCTL;
1922 1926                  goto bailout;
1923 1927          }
1924 1928  
1925 1929          /* Set up nvlist to pass the port number down to the driver */
1926 1930          if (nvlist_alloc(user_nvlistp, NV_UNIQUE_NAME_TYPE, NULL) != 0) {
1927 1931                  *user_nvlistp = NULL;
1928 1932                  rv = CFGA_SATA_NVLIST;
1929      -                (void) printf("nvlist_alloc failed\n");
     1933 +                DPRINTF("nvlist_alloc failed\n");
1930 1934                  goto bailout;
1931 1935          }
1932 1936  
1933 1937          /*
1934 1938           * Get port id, for Port Multiplier port, things could be a little bit
1935 1939           * complicated because of "port.port" format in ap_id, thus for
1936 1940           * port multiplier port, port number should be coded as 32bit int
1937 1941           * with the sig 16 bit as sata channel number, least 16 bit as
1938 1942           * the port number of sata port multiplier port.
1939 1943           */
1940 1944          if ((rv = get_port_num(lap_id, &port)) != CFGA_SATA_OK) {
1941      -                (void) printf(
     1945 +                DPRINTF(
1942 1946                      "setup_for_devctl_cmd: get_port_num, errno: %d\n",
1943 1947                      errno);
1944 1948                  goto bailout;
1945 1949          }
1946 1950  
1947 1951          /* Creates an int32_t entry */
1948 1952          if (nvlist_add_int32(*user_nvlistp, PORT, port) == -1) {
1949      -                (void) printf("nvlist_add_int32 failed\n");
     1953 +                DPRINTF("nvlist_add_int32 failed\n");
1950 1954                  rv = CFGA_SATA_NVLIST;
1951 1955                  goto bailout;
1952 1956          }
1953 1957  
1954 1958          free(lap_id);
1955 1959          return (rv);
1956 1960  
1957 1961  bailout:
1958 1962          free(lap_id);
1959 1963          (void) cleanup_after_devctl_cmd(*devctl_hdl, *user_nvlistp);
1960 1964  
1961 1965          return (rv);
  
    | 
      ↓ open down ↓ | 
    2 lines elided | 
    
      ↑ open up ↑ | 
  
1962 1966  }
1963 1967  
1964 1968  
1965 1969  static cfga_sata_ret_t
1966 1970  port_state(devctl_hdl_t hdl, nvlist_t *list,
1967 1971      ap_rstate_t *rstate, ap_ostate_t *ostate)
1968 1972  {
1969 1973          devctl_ap_state_t       devctl_ap_state;
1970 1974  
1971 1975          if (devctl_ap_getstate(hdl, list, &devctl_ap_state) == -1) {
1972      -                (void) printf("devctl_ap_getstate failed, errno: %d\n", errno);
     1976 +                DPRINTF("devctl_ap_getstate failed, errno: %d\n", errno);
1973 1977                  return (CFGA_SATA_IOCTL);
1974 1978          }
1975 1979          *rstate = devctl_ap_state.ap_rstate;
1976 1980          *ostate =  devctl_ap_state.ap_ostate;
1977 1981          return (CFGA_SATA_OK);
1978 1982  }
1979 1983  
1980 1984  
1981 1985  /*
1982 1986   * Given a subcommand to the DEVCTL_AP_CONTROL ioctl, rquest the size of
1983 1987   * the data to be returned, allocate a buffer, then get the data.
1984 1988   * Returns *descrp (which must be freed) and size.
1985 1989   *
1986 1990   * Note SATA_DESCR_TYPE_STRING returns an ASCII NULL-terminated string,
1987 1991   * not a string descr.
1988 1992   */
1989 1993  cfga_sata_ret_t
1990 1994  do_control_ioctl(const char *ap_id, sata_cfga_apctl_t subcommand, uint_t arg,
1991 1995      void **descrp, size_t *sizep)
1992 1996  {
1993 1997          int                     fd = -1;
1994 1998          uint_t                  port;
1995 1999          uint32_t                local_size;
1996 2000          cfga_sata_ret_t         rv = CFGA_SATA_OK;
1997 2001          struct sata_ioctl_data  ioctl_data;
  
    | 
      ↓ open down ↓ | 
    15 lines elided | 
    
      ↑ open up ↑ | 
  
1998 2002  
1999 2003          assert(descrp != NULL);
2000 2004          *descrp = NULL;
2001 2005          assert(sizep != NULL);
2002 2006  
2003 2007          if ((rv = get_port_num(ap_id, &port)) != CFGA_SATA_OK) {
2004 2008                  goto bailout;
2005 2009          }
2006 2010  
2007 2011          if ((fd = open(ap_id, O_RDONLY)) == -1) {
2008      -                (void) printf("do_control_ioctl: open failed: errno:%d\n",
     2012 +                DPRINTF("do_control_ioctl: open failed: errno:%d\n",
2009 2013                      errno);
2010 2014                  rv = CFGA_SATA_OPEN;
2011 2015                  if (errno == EBUSY) {
2012 2016                          rv = CFGA_SATA_BUSY;
2013 2017                  }
2014 2018                  goto bailout;
2015 2019          }
2016 2020  
2017 2021          ioctl_data.cmd = subcommand;
2018 2022          ioctl_data.port = port;
2019 2023          ioctl_data.misc_arg = (uint_t)arg;
2020 2024  
2021 2025          /*
2022 2026           * Find out how large a buf we need to get the data.
2023 2027           * Note the ioctls only accept/return a 32-bit int for a get_size
2024 2028           * to avoid 32/64 and BE/LE issues.
2025 2029           */
2026 2030          if ((subcommand == SATA_CFGA_GET_AP_TYPE) ||
2027 2031              (subcommand == SATA_CFGA_GET_DEVICE_PATH) ||
2028 2032              (subcommand == SATA_CFGA_GET_MODEL_INFO) ||
2029 2033              (subcommand == SATA_CFGA_GET_REVFIRMWARE_INFO) ||
2030 2034              (subcommand == SATA_CFGA_GET_SERIALNUMBER_INFO)) {
2031 2035                  ioctl_data.get_size = B_TRUE;
2032 2036                  ioctl_data.buf = (caddr_t)&local_size;
  
    | 
      ↓ open down ↓ | 
    14 lines elided | 
    
      ↑ open up ↑ | 
  
2033 2037                  ioctl_data.bufsiz = sizeof (local_size);
2034 2038  
2035 2039                  if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2036 2040                          perror("ioctl failed (size)");
2037 2041                          rv = CFGA_SATA_IOCTL;
2038 2042                          goto bailout;
2039 2043                  }
2040 2044                  *sizep = local_size;
2041 2045  
2042 2046                  if (local_size == 0) {
2043      -                        (void) printf("zero length data\n");
     2047 +                        DPRINTF("zero length data\n");
2044 2048                          rv = CFGA_SATA_ZEROLEN;
2045 2049                          goto bailout;
2046 2050                  }
2047 2051                  if ((*descrp = malloc(*sizep)) == NULL) {
2048      -                        (void) printf("do_control_ioctl: malloc failed\n");
     2052 +                        DPRINTF("do_control_ioctl: malloc failed\n");
2049 2053                          rv = CFGA_SATA_ALLOC_FAIL;
2050 2054                          goto bailout;
2051 2055                  }
2052 2056          } else {
2053 2057                  *sizep = 0;
2054 2058          }
2055 2059          ioctl_data.get_size = B_FALSE;
2056 2060          ioctl_data.buf = *descrp;
2057 2061          ioctl_data.bufsiz = *sizep;
2058 2062  
2059 2063          /* Execute IOCTL */
2060 2064  
2061 2065          if (ioctl(fd, DEVCTL_AP_CONTROL, &ioctl_data) != 0) {
2062 2066                  rv = CFGA_SATA_IOCTL;
2063 2067                  goto bailout;
2064 2068          }
2065 2069  
2066 2070          (void) close(fd);
2067 2071  
2068 2072          return (rv);
2069 2073  
2070 2074  bailout:
2071 2075          if (fd != -1) {
2072 2076                  (void) close(fd);
2073 2077          }
2074 2078          if (*descrp != NULL) {
2075 2079                  free(*descrp);
2076 2080                  *descrp = NULL;
2077 2081          }
2078 2082  
2079 2083          if (rv == CFGA_SATA_IOCTL && errno == EBUSY) {
2080 2084                  rv = CFGA_SATA_BUSY;
2081 2085          }
2082 2086  
2083 2087          return (rv);
2084 2088  }
2085 2089  
2086 2090  
2087 2091  static int
2088 2092  sata_confirm(struct cfga_confirm *confp, char *msg)
2089 2093  {
2090 2094          int rval;
2091 2095  
2092 2096          if (confp == NULL || confp->confirm == NULL) {
2093 2097                  return (0);
2094 2098          }
2095 2099          rval = (*confp->confirm)(confp->appdata_ptr, msg);
2096 2100  
2097 2101          return (rval);
2098 2102  }
2099 2103  
2100 2104  
2101 2105  static char *
2102 2106  sata_get_devicepath(const char *ap_id)
2103 2107  {
2104 2108          char            *devpath = NULL;
2105 2109          size_t          size;
2106 2110          cfga_sata_ret_t rv;
2107 2111  
2108 2112          rv = do_control_ioctl(ap_id, SATA_CFGA_GET_DEVICE_PATH, NULL,
2109 2113              (void **)&devpath, &size);
2110 2114  
2111 2115          if (rv == CFGA_SATA_OK) {
2112 2116                  return (devpath);
2113 2117          } else {
2114 2118                  return ((char *)NULL);
2115 2119          }
2116 2120  
2117 2121  }
  
    | 
      ↓ open down ↓ | 
    59 lines elided | 
    
      ↑ open up ↑ | 
  
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX