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 #include <limits.h>
  27 #include <sys/mdb_modapi.h>
  28 #include <sys/sysinfo.h>
  29 #include <sys/sunmdi.h>
  30 #include <sys/scsi/scsi.h>
  31 #include "mr_sas.h"
  32 
  33 int
  34 construct_path(uintptr_t addr, char *result)
  35 {
  36         struct  dev_info        d;
  37         char    devi_node[PATH_MAX];
  38         char    devi_addr[PATH_MAX];
  39 
  40         if (mdb_vread(&d, sizeof (d), addr) == -1) {
  41                 mdb_warn("couldn't read dev_info");
  42                 return (DCMD_ERR);
  43         }
  44 
  45         if (d.devi_parent) {
  46                 construct_path((uintptr_t)d.devi_parent, result);
  47                 mdb_readstr(devi_node, sizeof (devi_node),
  48                     (uintptr_t)d.devi_node_name);
  49                 mdb_readstr(devi_addr, sizeof (devi_addr),
  50                     (uintptr_t)d.devi_addr);
  51                 mdb_snprintf(result+strlen(result),
  52                     PATH_MAX-strlen(result),
  53                     "/%s%s%s", devi_node, (*devi_addr ? "@" : ""),
  54                     devi_addr);
  55         }
  56         return (DCMD_OK);
  57 }
  58 
  59 void
  60 display_targets(struct mrsas_instance m, int verbose)
  61 {
  62         int     tgt;
  63         struct mrsas_ld *mr_ldp;
  64         char    device_path[PATH_MAX];
  65 
  66         if (verbose) {
  67                 *device_path = 0;
  68                 if (construct_path((uintptr_t)m.dip, device_path) != DCMD_OK) {
  69                         strcpy(device_path, "couldn't determine device path");
  70                 }
  71         }
  72 
  73         mdb_printf("\n");
  74         if (verbose)
  75                 mdb_printf("%s\n", device_path);
  76         mdb_printf("dev_type target\n");
  77         mdb_printf("----------");
  78         mdb_printf("\n");
  79         for (tgt = 0; tgt < MRDRV_MAX_LD; tgt++) {
  80                 mr_ldp = (struct mrsas_ld *)&m.mr_ld_list[tgt];
  81                 if ((mr_ldp != NULL) && (mr_ldp->dip != NULL) &&
  82                     (mr_ldp->lun_type == MRSAS_LD_LUN)) {
  83                         mdb_printf("sd %d", tgt);
  84                         mdb_printf("\n");
  85                 }
  86         }
  87         mdb_printf("\n");
  88 }
  89 
  90 void
  91 display_deviceinfo(struct mrsas_instance m)
  92 {
  93         uint16_t vid, did, svid, sid;
  94 
  95         vid = m.vendor_id;
  96         did = m.device_id;
  97         svid = m.subsysvid;
  98         sid = m.subsysid;
  99 
 100         mdb_printf("\n");
 101         mdb_printf("vendor_id device_id subsysvid subsysid");
 102         mdb_printf("\n");
 103         mdb_printf("--------------------------------------");
 104         mdb_printf("\n");
 105         mdb_printf("    0x%x   0x%x    0x%x    0x%x",
 106             vid, did, svid, sid);
 107         mdb_printf("\n");
 108 }
 109 
 110 static int
 111 mr_sas_dcmd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
 112 {
 113         struct mrsas_instance m;
 114 
 115         int     instance;
 116         uint16_t ncmds;
 117         uint_t  verbose = FALSE;
 118         uint_t  device_info = FALSE;
 119         uint_t  target_info = FALSE;
 120         int     rv = DCMD_OK;
 121         void    *mrsas_state;
 122 
 123         if (!(flags & DCMD_ADDRSPEC)) {
 124                 mrsas_state = NULL;
 125                 if (mdb_readvar(&mrsas_state, "mrsas_state") == -1) {
 126                         mdb_warn("can't read mrsas_state");
 127                         return (DCMD_ERR);
 128                 }
 129                 if (mdb_pwalk_dcmd("genunix`softstate", "mr_sas`mr_sas",
 130                     argc, argv, (uintptr_t)mrsas_state) == -1) {
 131                         mdb_warn("mdb_pwalk_dcmd failed");
 132                         return (DCMD_ERR);
 133                 }
 134                 return (DCMD_OK);
 135         }
 136 
 137         if (mdb_getopts(argc, argv,
 138             'd', MDB_OPT_SETBITS, TRUE, &device_info,
 139             't', MDB_OPT_SETBITS, TRUE, &target_info,
 140             'v', MDB_OPT_SETBITS, TRUE, &verbose,
 141             NULL) != argc)
 142                 return (DCMD_USAGE);
 143 
 144         if (mdb_vread(&m, sizeof (m), addr) == -1) {
 145                 mdb_warn("couldn't read mrsas_instance struct at 0x%p", addr);
 146                 return (DCMD_ERR);
 147         }
 148         instance = m.instance;
 149 
 150         /* cmd slot info */
 151         ncmds = m.max_fw_cmds;
 152 
 153         /* processing completed */
 154         if (((flags & DCMD_ADDRSPEC) && !(flags & DCMD_LOOP)) ||
 155             (flags & DCMD_LOOPFIRST)) {
 156                 if ((flags & DCMD_LOOP) && !(flags & DCMD_LOOPFIRST))
 157                         mdb_printf("\n");
 158                 mdb_printf("         mrsas_t inst max_fw_cmds intr_type");
 159                 mdb_printf("\n");
 160                 mdb_printf("===========================================");
 161                 mdb_printf("\n");
 162         }
 163 
 164         mdb_printf("%16p %4d      %4d    ", addr, instance, ncmds);
 165         switch (m.intr_type) {
 166                 case DDI_INTR_TYPE_MSIX:
 167                         mdb_printf("MSI-X");
 168                         break;
 169                 case DDI_INTR_TYPE_MSI:
 170                         mdb_printf("MSI");
 171                         break;
 172                 case DDI_INTR_TYPE_FIXED:
 173                         mdb_printf("FIXED");
 174                         break;
 175                 default:
 176                         mdb_printf("INVALD");
 177         }
 178         mdb_printf("\n");
 179 
 180         if (target_info)
 181                 display_targets(m, verbose);
 182 
 183         if (device_info)
 184                 display_deviceinfo(m);
 185 
 186         return (rv);
 187 }
 188 
 189 void
 190 mr_sas_help(void)
 191 {
 192         mdb_printf("Prints summary information about each mr_sas instance, "
 193             "Without the address of a \"struct mrsas_instance\", prints every "
 194             "instance.\n\n"
 195             "Switches:\n"
 196             "  -t   includes information about targets\n"
 197             "  -d   includes information about the hardware\n"
 198             "  -v   displays extra information for some options\n");
 199 }
 200 
 201 static const mdb_dcmd_t dcmds[] = {
 202         { "mr_sas", "?[-tdv]", "print mr_sas information", mr_sas_dcmd,
 203             mr_sas_help },
 204         { NULL }
 205 };
 206 
 207 static const mdb_modinfo_t modinfo = {
 208         MDB_API_VERSION, dcmds, NULL
 209 };
 210 
 211 const mdb_modinfo_t *
 212 _mdb_init(void)
 213 {
 214         return (&modinfo);
 215 }