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 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 * 25 * FCIP mdb module 26 */ 27 28 29 #include <sys/mdb_modapi.h> 30 #include <sys/mutex.h> 31 #include <sys/modctl.h> 32 #include <sys/ethernet.h> 33 #include <sys/fibre-channel/fc.h> 34 #include <sys/fibre-channel/impl/fc_ulpif.h> 35 #include <sys/fibre-channel/impl/fctl_private.h> 36 #include <sys/fibre-channel/ulp/fcip.h> 37 38 /* 39 * Leadville fcip walker/dcmd code 40 */ 41 42 static int 43 fcip_walk_i(mdb_walk_state_t *wsp) 44 { 45 if (wsp->walk_addr == NULL && 46 mdb_readvar(&wsp->walk_addr, "fcip_port_head") == -1) { 47 mdb_warn("failed to read 'fcip_port_head'"); 48 return (WALK_ERR); 49 } 50 51 wsp->walk_data = mdb_alloc(sizeof (fcip_port_info_t), UM_SLEEP); 52 return (WALK_NEXT); 53 } 54 55 static int 56 fcip_walk_s(mdb_walk_state_t *wsp) 57 { 58 int status; 59 60 if (wsp->walk_addr == NULL) 61 return (WALK_DONE); 62 63 if (mdb_vread(wsp->walk_data, sizeof (fcip_port_info_t), 64 wsp->walk_addr) == -1) { 65 mdb_warn("failed to read fcip_port_info at %p", wsp->walk_addr); 66 return (WALK_DONE); 67 } 68 69 status = wsp->walk_callback(wsp->walk_addr, wsp->walk_data, 70 wsp->walk_cbdata); 71 72 wsp->walk_addr = 73 (uintptr_t)(((fcip_port_info_t *)wsp->walk_data)->fcipp_next); 74 75 return (status); 76 } 77 78 /* 79 * The walker's fini function is invoked at the end of each walk. Since we 80 * dynamically allocated a fc_fca_port_t in port_walk_i, we must free it now. 81 */ 82 static void 83 fcip_walk_f(mdb_walk_state_t *wsp) 84 { 85 mdb_free(wsp->walk_data, sizeof (fc_fca_port_t)); 86 } 87 88 89 static int 90 fcip(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv) 91 { 92 fcip_port_info_t pinfo; 93 94 if (argc != 0) { 95 return (DCMD_USAGE); 96 } 97 98 if (!(flags & DCMD_ADDRSPEC)) { 99 if (mdb_walk_dcmd("fcip", "fcip", 100 argc, argv) == -1) { 101 mdb_warn("failed to walk 'fcip_port_head'"); 102 return (DCMD_ERR); 103 } 104 return (DCMD_OK); 105 } 106 107 if (DCMD_HDRSPEC(flags)) 108 mdb_printf("%12s %12s %12s %16s %16s\n", 109 "FCIP Struct", "Handle", "DIP", "Port WWN", "Node WWN"); 110 111 /* 112 * For each port, we just need to read the fc_fca_port_t struct, read 113 * the port_handle 114 */ 115 if (mdb_vread(&pinfo, sizeof (fcip_port_info_t), addr) == 116 sizeof (fcip_port_info_t)) { 117 mdb_printf("%12p %12p %12p %02x%02x%02x%02x%02x%02x%02x%02x " 118 "%02x%02x%02x%02x%02x%02x%02x%02x\n", 119 pinfo.fcipp_fcip, pinfo.fcipp_handle, pinfo.fcipp_dip, 120 pinfo.fcipp_pwwn.raw_wwn[0], pinfo.fcipp_pwwn.raw_wwn[1], 121 pinfo.fcipp_pwwn.raw_wwn[2], pinfo.fcipp_pwwn.raw_wwn[3], 122 pinfo.fcipp_pwwn.raw_wwn[4], pinfo.fcipp_pwwn.raw_wwn[5], 123 pinfo.fcipp_pwwn.raw_wwn[6], pinfo.fcipp_pwwn.raw_wwn[7], 124 pinfo.fcipp_nwwn.raw_wwn[0], pinfo.fcipp_nwwn.raw_wwn[1], 125 pinfo.fcipp_nwwn.raw_wwn[2], pinfo.fcipp_nwwn.raw_wwn[3], 126 pinfo.fcipp_nwwn.raw_wwn[4], pinfo.fcipp_nwwn.raw_wwn[5], 127 pinfo.fcipp_nwwn.raw_wwn[6], pinfo.fcipp_nwwn.raw_wwn[7]); 128 129 } else 130 mdb_warn("failed to read port info at %p", addr); 131 132 return (DCMD_OK); 133 } 134 135 136 /* 137 * MDB module linkage information: 138 * 139 * We declare a list of structures describing our dcmds, a list of structures 140 * describing our walkers, and a function named _mdb_init to return a pointer 141 * to our module information. 142 */ 143 144 static const mdb_dcmd_t dcmds[] = { 145 { "fcip", NULL, "Leadville fcip instances", fcip }, 146 { NULL } 147 }; 148 149 static const mdb_walker_t walkers[] = { 150 { "fcip", "walk list of Leadville fcip instances", 151 fcip_walk_i, fcip_walk_s, fcip_walk_f }, 152 { NULL } 153 }; 154 155 static const mdb_modinfo_t modinfo = { 156 MDB_API_VERSION, dcmds, walkers 157 }; 158 159 const mdb_modinfo_t * 160 _mdb_init(void) 161 { 162 return (&modinfo); 163 } 164