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 42static int 43fcip_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 55static int 56fcip_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 */ 82static void 83fcip_walk_f(mdb_walk_state_t *wsp) 84{ 85 mdb_free(wsp->walk_data, sizeof (fc_fca_port_t)); 86} 87 88 89static int 90fcip(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 144static const mdb_dcmd_t dcmds[] = { 145 { "fcip", NULL, "Leadville fcip instances", fcip }, 146 { NULL } 147}; 148 149static 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 155static const mdb_modinfo_t modinfo = { 156 MDB_API_VERSION, dcmds, walkers 157}; 158 159const mdb_modinfo_t * 160_mdb_init(void) 161{ 162 return (&modinfo); 163} 164