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 /* 23 * Copyright 2008 Emulex. All rights reserved. 24 * Use is subject to License terms. 25 */ 26 27 #include "emlxs_mdb.h" 28 #include "emlxs_msg.h" 29 #include "emlxs_device.h" 30 31 /* 32 * MDB module linkage information: 33 */ 34 35 static const mdb_dcmd_t dcmds[] = 36 { 37 { "emlxs_msgbuf", "<instance>", 38 "dumps the emlxs driver internal message buffer", 39 emlxs_msgbuf, emlxs_msgbuf_help}, 40 { NULL } 41 }; 42 43 static const mdb_modinfo_t modinfo = 44 { 45 MDB_API_VERSION, 46 dcmds, 47 NULL 48 }; 49 50 const mdb_modinfo_t * 51 _mdb_init(void) 52 { 53 return (&modinfo); 54 } 55 56 57 /* 58 * emlxs_msgbuf library 59 */ 60 void 61 emlxs_msgbuf_help() 62 { 63 64 mdb_printf("Usage: ::%s_msgbuf <instance (in hex)>\n\n", DRIVER_NAME); 65 mdb_printf( 66 " <instance> This is the %s driver instance number in hex.\n", 67 DRIVER_NAME); 68 mdb_printf(" (e.g. 0, 1,..., e, f, etc.)\n"); 69 70 } /* emlxs_msgbuf_help() */ 71 72 73 /*ARGSUSED*/ 74 int emlxs_msgbuf(uintptr_t base_addr, uint_t flags, int argc, 75 const mdb_arg_t *argv) 76 { 77 uintptr_t addr; 78 emlxs_device_t device; 79 uint32_t brd_no; 80 emlxs_msg_log_t log; 81 uint32_t count; 82 uint32_t first; 83 uint32_t last; 84 uint32_t idx; 85 uint32_t i; 86 char *level; 87 emlxs_msg_t msg; 88 uint32_t secs; 89 uint32_t hsecs; 90 emlxs_msg_entry_t entry; 91 char buffer[256]; 92 char buffer2[256]; 93 int32_t instance[MAX_FC_BRDS]; 94 char driver[32]; 95 int32_t instance_count; 96 uint32_t ddiinst; 97 98 99 if (argc != 1) { 100 mdb_printf("Usage: ::%s_msgbuf <instance (in hex)>\n", 101 DRIVER_NAME); 102 mdb_printf("mdb: try \"::help %s_msgbuf\" for more information", 103 DRIVER_NAME); 104 105 return (DCMD_ERR); 106 } 107 108 /* Get the device address */ 109 mdb_snprintf(buffer, sizeof (buffer), "%s_device", DRIVER_NAME); 110 if (mdb_readvar(&device, buffer) == -1) { 111 mdb_snprintf(buffer2, sizeof (buffer2), 112 "%s not found.\n", buffer); 113 mdb_warn(buffer2); 114 115 mdb_snprintf(buffer2, sizeof (buffer2), 116 "Is the %s driver loaded ?\n", DRIVER_NAME); 117 mdb_warn(buffer2); 118 return (DCMD_ERR); 119 } 120 121 /* Get the device instance table */ 122 mdb_snprintf(buffer, sizeof (buffer), "%s_instance", DRIVER_NAME); 123 if (mdb_readvar(&instance, buffer) == -1) { 124 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 125 buffer); 126 mdb_warn(buffer2); 127 128 mdb_snprintf(buffer2, sizeof (buffer2), 129 "Is the %s driver loaded ?\n", DRIVER_NAME); 130 mdb_warn(buffer2); 131 return (DCMD_ERR); 132 } 133 134 /* Get the device instance count */ 135 mdb_snprintf(buffer, sizeof (buffer), "%s_instance_count", DRIVER_NAME); 136 if (mdb_readvar(&instance_count, buffer) == -1) { 137 mdb_snprintf(buffer2, sizeof (buffer2), "%s not found.\n", 138 buffer); 139 mdb_warn(buffer2); 140 141 mdb_snprintf(buffer2, sizeof (buffer2), 142 "Is the %s driver loaded ?\n", DRIVER_NAME); 143 mdb_warn(buffer2); 144 return (DCMD_ERR); 145 } 146 147 ddiinst = (uint32_t)mdb_strtoull(argv[0].a_un.a_str); 148 149 for (brd_no = 0; brd_no < instance_count; brd_no++) { 150 if (instance[brd_no] == ddiinst) { 151 break; 152 } 153 } 154 155 if (brd_no == instance_count) { 156 mdb_warn("Device instance not found. ddinst=%d\n", ddiinst); 157 return (DCMD_ERR); 158 } 159 160 /* Check if buffer is null */ 161 addr = (uintptr_t)device.log[brd_no]; 162 if (addr == 0) { 163 mdb_warn("Device instance not found. ddinst=%d\n", ddiinst); 164 return (0); 165 } 166 167 if (mdb_vread(&log, sizeof (emlxs_msg_log_t), addr) != 168 sizeof (emlxs_msg_log_t)) { 169 mdb_warn("\nUnable to read %d bytes @ %llx.\n", 170 sizeof (emlxs_msg_log_t), addr); 171 return (0); 172 } 173 174 /* Check if buffer is empty */ 175 if (log.count == 0) { 176 mdb_warn("Log buffer empty.\n"); 177 return (0); 178 } 179 180 /* Get last entry id saved */ 181 last = log.count - 1; 182 183 /* Check if buffer has already been filled once */ 184 if (log.count >= log.size) { 185 first = log.count - log.size; 186 idx = log.next; 187 } else { 188 /* Buffer not yet filled */ 189 first = 0; 190 idx = 0; 191 } 192 193 /* Get the total number of messages available for return */ 194 count = last - first + 1; 195 196 mdb_printf("\n"); 197 198 /* Print the messages */ 199 for (i = 0; i < count; i++) { 200 if (mdb_vread(&entry, sizeof (emlxs_msg_entry_t), 201 (uintptr_t)&log.entry[idx]) != sizeof (emlxs_msg_entry_t)) { 202 mdb_warn("Cannot read log entry. index=%d count=%d\n", 203 idx, count); 204 return (DCMD_ERR); 205 } 206 207 if (mdb_vread(&msg, sizeof (emlxs_msg_t), 208 (uintptr_t)entry.msg) != sizeof (emlxs_msg_t)) { 209 mdb_warn("Cannot read msg. index=%d count=%d\n", 210 idx, count); 211 return (DCMD_ERR); 212 } 213 214 hsecs = (entry.time%100); 215 secs = entry.time/100; 216 217 switch (msg.level) { 218 case EMLXS_DEBUG: 219 level = " DEBUG"; 220 break; 221 222 case EMLXS_NOTICE: 223 level = " NOTICE"; 224 break; 225 226 case EMLXS_WARNING: 227 level = "WARNING"; 228 break; 229 230 case EMLXS_ERROR: 231 level = " ERROR"; 232 break; 233 234 case EMLXS_PANIC: 235 level = " PANIC"; 236 break; 237 238 case EMLXS_EVENT: 239 level = " EVENT"; 240 break; 241 242 default: 243 level = "UNKNOWN"; 244 break; 245 } 246 247 if (entry.vpi == 0) { 248 mdb_snprintf(driver, sizeof (driver), "%s%d", 249 DRIVER_NAME, entry.instance); 250 } else { 251 mdb_snprintf(driver, sizeof (driver), "%s%d.%d", 252 DRIVER_NAME, entry.instance, entry.vpi); 253 } 254 255 /* Generate the message string */ 256 if (msg.buffer[0] != 0) { 257 if (entry.buffer[0] != 0) { 258 mdb_snprintf(buffer, sizeof (buffer), 259 "%8d.%02d: " 260 "%6d:[%1X.%04X]%s:%7s:%4d: %s\n(%s)\n", 261 secs, hsecs, entry.id, entry.fileno, 262 entry.line, driver, level, msg.id, 263 msg.buffer, entry.buffer); 264 265 } else { 266 mdb_snprintf(buffer, sizeof (buffer), 267 "%8d.%02d: %6d:[%1X.%04X]%s:%7s:%4d: %s\n", 268 secs, hsecs, entry.id, entry.fileno, 269 entry.line, driver, level, msg.id, 270 msg.buffer); 271 } 272 } else { 273 if (entry.buffer[0] != 0) { 274 mdb_snprintf(buffer, sizeof (buffer), 275 "%8d.%02d: " 276 "%6d:[%1X.%04X]%s:%7s:%4d:\n(%s)\n", 277 secs, hsecs, entry.id, entry.fileno, 278 entry.line, driver, level, msg.id, 279 entry.buffer); 280 } else { 281 mdb_snprintf(buffer, sizeof (buffer), 282 "%8d.%02d: %6d:[%1X.%04X]%s:%7s:%4d:\n", 283 secs, hsecs, entry.id, entry.fileno, 284 entry.line, driver, level, msg.id); 285 } 286 } 287 288 mdb_printf("%s", buffer); 289 290 /* Increment index */ 291 if (++idx >= log.size) { 292 idx = 0; 293 } 294 } 295 296 mdb_printf("\n"); 297 298 return (0); 299 300 } /* emlxs_msgbuf() */ 301