1 /*
   2  * CDDL HEADER START
   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
  28  */
  29 
  30 #include <limits.h>
  31 #include <sys/mdb_modapi.h>
  32 #include <sys/sysinfo.h>
  33 #include <sys/sunmdi.h>
  34 #include <sys/scsi/scsi.h>
  35 #include "mr_sas.h"
  36 
  37 int
  38 construct_path(uintptr_t addr, char *result)
  39 {
  40         struct  dev_info        d;
  41         char    devi_node[PATH_MAX];
  42         char    devi_addr[PATH_MAX];
  43 
  44         if (mdb_vread(&d, sizeof (d), addr) == -1) {
  45                 mdb_warn("couldn't read dev_info");
  46                 return (DCMD_ERR);
  47         }
  48 
  49         if (d.devi_parent) {
  50                 construct_path((uintptr_t)d.devi_parent, result);
  51                 mdb_readstr(devi_node, sizeof (devi_node),
  52                     (uintptr_t)d.devi_node_name);
  53                 mdb_readstr(devi_addr, sizeof (devi_addr),
  54                     (uintptr_t)d.devi_addr);
  55                 mdb_snprintf(result+strlen(result),
  56                     PATH_MAX-strlen(result),
  57                     "/%s%s%s", devi_node, (*devi_addr ? "@" : ""),
  58                     devi_addr);
  59         }
  60         return (DCMD_OK);
  61 }
  62 
  63 void
  64 display_targets(struct mrsas_instance *m, int verbose)
  65 {
  66         int     tgt;
  67         struct mrsas_ld mr_ldp[MRDRV_MAX_LD];
  68         struct mrsas_tbolt_pd mr_pdp[MRSAS_TBOLT_PD_TGT_MAX];
  69         char    device_path[PATH_MAX];
  70 
  71         if (verbose) {
  72                 *device_path = 0;
  73                 if (construct_path((uintptr_t)m->dip, device_path) != DCMD_OK) {
  74                         strcpy(device_path, "couldn't determine device path");
  75                 }
  76         }
  77 
  78         mdb_printf("\n");
  79         if (verbose)
  80                 mdb_printf("%s\n", device_path);
  81         mdb_printf("Physical/Logical Target\n");
  82         mdb_printf("-----------------------\n");
  83 
  84         if (mdb_vread(&mr_ldp, sizeof (mr_ldp), (uintptr_t)m->mr_ld_list)
  85             == -1 ||
  86             mdb_vread(&mr_pdp, sizeof (mr_pdp), (uintptr_t)m->mr_tbolt_pd_list)
  87             == -1) {
  88                 mdb_warn("can't read list of disks");
  89                 return;
  90         }
  91 
  92         for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) {
  93                 if (mr_ldp[tgt].dip != NULL &&
  94                     mr_ldp[tgt].lun_type == MRSAS_LD_LUN) {
  95                         mdb_printf("Logical          sd %d\n", tgt);
  96                 }
  97         }
  98         for (tgt = 0; tgt < MRSAS_TBOLT_PD_TGT_MAX; tgt++) {
  99                 if (mr_pdp[tgt].dip != NULL &&
 100                     mr_pdp[tgt].lun_type == MRSAS_TBOLT_PD_LUN) {
 101                         mdb_printf("Physical         sd %d\n", tgt);
 102                 }
 103         }
 104         mdb_printf("\n");
 105 }
 106 
 107 void
 108 display_deviceinfo(struct mrsas_instance *m)
 109 {
 110         uint16_t vid, did, svid, sid;
 111 
 112         vid = m->vendor_id;
 113         did = m->device_id;
 114         svid = m->subsysvid;
 115         sid = m->subsysid;
 116 
 117         mdb_printf("\n");
 118         mdb_printf("vendor_id device_id subsysvid subsysid");
 119         mdb_printf("\n");
 120         mdb_printf("--------------------------------------");
 121         mdb_printf("\n");
 122         mdb_printf("    0x%x   0x%x    0x%x    0x%x",
 123             vid, did, svid, sid);
 124         mdb_printf("\n");
 125 }
 126 
 127 static int
 128 mr_sas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 129 {
 130         struct mrsas_instance m;
 131 
 132         int     instance;
 133         uint16_t ncmds;
 134         uint_t  verbose = FALSE;
 135         uint_t  device_info = FALSE;
 136         uint_t  target_info = FALSE;
 137         int     rv = DCMD_OK;
 138         void    *mrsas_state;
 139 
 140         if (!(flags & DCMD_ADDRSPEC)) {
 141                 mrsas_state = NULL;
 142                 if (mdb_readvar(&mrsas_state, "mrsas_state") == -1) {
 143                         mdb_warn("can't read mrsas_state");
 144                         return (DCMD_ERR);
 145                 }
 146                 if (mdb_pwalk_dcmd("genunix`softstate", "mr_sas`mr_sas",
 147                     argc, argv, (uintptr_t)mrsas_state) == -1) {
 148                         mdb_warn("mdb_pwalk_dcmd failed");
 149                         return (DCMD_ERR);
 150                 }
 151                 return (DCMD_OK);
 152         }
 153 
 154         if (mdb_getopts(argc, argv,
 155             'd', MDB_OPT_SETBITS, TRUE, &device_info,
 156             't', MDB_OPT_SETBITS, TRUE, &target_info,
 157             'v', MDB_OPT_SETBITS, TRUE, &verbose,
 158             NULL) != argc)
 159                 return (DCMD_USAGE);
 160 
 161         if (mdb_vread(&m, sizeof (m), addr) == -1) {
 162                 mdb_warn("couldn't read mrsas_instance struct at 0x%p", addr);
 163                 return (DCMD_ERR);
 164         }
 165         instance = m.instance;
 166 
 167         /* cmd slot info */
 168         ncmds = m.max_fw_cmds;
 169 
 170         /* processing completed */
 171         if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
 172             (flags & DCMD_LOOPFIRST)) {
 173                 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
 174                         mdb_printf("\n");
 175                 mdb_printf("         mrsas_t inst max_fw_cmds intr_type");
 176                 mdb_printf("\n");
 177                 mdb_printf("===========================================");
 178                 mdb_printf("\n");
 179         }
 180 
 181         mdb_printf("%16p %4d      %4d    ", addr, instance, ncmds);
 182         switch (m.intr_type) {
 183                 case DDI_INTR_TYPE_MSIX:
 184                         mdb_printf("MSI-X");
 185                         break;
 186                 case DDI_INTR_TYPE_MSI:
 187                         mdb_printf("MSI");
 188                         break;
 189                 case DDI_INTR_TYPE_FIXED:
 190                         mdb_printf("FIXED");
 191                         break;
 192                 default:
 193                         mdb_printf("INVALD");
 194         }
 195         mdb_printf("\n");
 196 
 197         if (target_info)
 198                 display_targets(&m, verbose);
 199 
 200         if (device_info)
 201                 display_deviceinfo(&m);
 202 
 203         return (rv);
 204 }
 205 
 206 void
 207 mr_sas_help(void)
 208 {
 209         mdb_printf("Prints summary information about each mr_sas instance, "
 210             "Without the address of a \"struct mrsas_instance\", prints every "
 211             "instance.\n\n"
 212             "Switches:\n"
 213             "  -t   includes information about targets\n"
 214             "  -d   includes information about the hardware\n"
 215             "  -v   displays extra information for some options\n");
 216 }
 217 
 218 static const mdb_dcmd_t dcmds[] = {
 219         { "mr_sas", "?[-tdv]", "print mr_sas information", mr_sas_dcmd,
 220             mr_sas_help },
 221         { NULL }
 222 };
 223 
 224 static const mdb_modinfo_t modinfo = {
 225         MDB_API_VERSION, dcmds, NULL
 226 };
 227 
 228 const mdb_modinfo_t *
 229 _mdb_init(void)
 230 {
 231         return (&modinfo);
 232 }