1 /*- 2 * Copyright (c) 2006 IronPort Systems 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 */ 26 27 #include <sys/cdefs.h> 28 __FBSDID("$FreeBSD$"); 29 30 #include "opt_mfi.h" 31 32 #ifdef MFI_DEBUG 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/kernel.h> 37 #include <sys/conf.h> 38 #include <sys/bus.h> 39 #include <sys/bio.h> 40 #include <sys/lock.h> 41 #include <sys/mutex.h> 42 #include <sys/malloc.h> 43 #include <sys/selinfo.h> 44 #include <sys/sysctl.h> 45 #include <sys/taskqueue.h> 46 #include <sys/uio.h> 47 #include <machine/resource.h> 48 #include <machine/bus.h> 49 50 #include <vm/vm.h> 51 #include <vm/pmap.h> 52 53 #include <dev/mfi/mfireg.h> 54 #include <dev/mfi/mfi_ioctl.h> 55 #include <dev/mfi/mfivar.h> 56 57 static void 58 mfi_print_frame_flags(device_t dev, uint32_t flags) 59 { 60 device_printf(dev, "flags=%b\n", flags, 61 "\20" 62 "\1NOPOST" 63 "\2SGL64" 64 "\3SENSE64" 65 "\4WRITE" 66 "\5READ" 67 "\6IEEESGL"); 68 } 69 70 static void 71 mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count) 72 { 73 int i, columns = 0; 74 75 printf("SG List:\n"); 76 for (i = 0; i < count; i++) { 77 if (hdr->flags & MFI_FRAME_IEEE_SGL) { 78 printf("0x%lx:%06d ", (u_long)sgl->sg_skinny[i].addr, 79 sgl->sg_skinny[i].len); 80 columns += 26; 81 if (columns > 77) { 82 printf("\n"); 83 columns = 0; 84 } 85 } else if (hdr->flags & MFI_FRAME_SGL64) { 86 printf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr, 87 sgl->sg64[i].len); 88 columns += 26; 89 if (columns > 77) { 90 printf("\n"); 91 columns = 0; 92 } 93 } else { 94 printf("0x%x:%06d ", sgl->sg32[i].addr, 95 sgl->sg32[i].len); 96 columns += 18; 97 if (columns > 71) { 98 printf("\n"); 99 columns = 0; 100 } 101 } 102 } 103 if (columns != 0) 104 printf("\n"); 105 106 } 107 108 static void 109 mfi_print_ldio(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 110 { 111 struct mfi_io_frame *io; 112 struct mfi_frame_header *hdr; 113 114 io = &cm->cm_frame->io; 115 hdr = &io->header; 116 117 device_printf(dev, "cmd=%s target_id=%d sg_count=%d data_len=%d " 118 "lba=%d\n", (hdr->cmd == MFI_CMD_LD_READ) ? "LD_READ":"LD_WRITE", 119 hdr->target_id, hdr->sg_count, hdr->data_len, io->lba_lo); 120 mfi_print_frame_flags(dev, hdr->flags); 121 mfi_print_sgl(hdr, &io->sgl, hdr->sg_count); 122 123 } 124 125 static void 126 mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 127 { 128 struct mfi_dcmd_frame *dcmd; 129 struct mfi_frame_header *hdr; 130 const char *opcode; 131 132 dcmd = &cm->cm_frame->dcmd; 133 hdr = &dcmd->header; 134 135 switch (dcmd->opcode) { 136 case MFI_DCMD_CTRL_GETINFO: 137 opcode = "CTRL_GETINFO"; 138 break; 139 case MFI_DCMD_CTRL_FLUSHCACHE: 140 opcode = "CTRL_FLUSHCACHE"; 141 break; 142 case MFI_DCMD_CTRL_SHUTDOWN: 143 opcode = "CTRL_SHUTDOWN"; 144 break; 145 case MFI_DCMD_CTRL_EVENT_GETINFO: 146 opcode = "EVENT_GETINFO"; 147 break; 148 case MFI_DCMD_CTRL_EVENT_GET: 149 opcode = "EVENT_GET"; 150 break; 151 case MFI_DCMD_CTRL_EVENT_WAIT: 152 opcode = "EVENT_WAIT"; 153 break; 154 case MFI_DCMD_LD_GET_LIST: 155 opcode = "LD_GET_LIST"; 156 break; 157 case MFI_DCMD_LD_GET_INFO: 158 opcode = "LD_GET_INFO"; 159 break; 160 case MFI_DCMD_LD_GET_PROP: 161 opcode = "LD_GET_PROP"; 162 break; 163 case MFI_DCMD_LD_SET_PROP: 164 opcode = "LD_SET_PROP"; 165 break; 166 case MFI_DCMD_CLUSTER: 167 opcode = "CLUSTER"; 168 break; 169 case MFI_DCMD_CLUSTER_RESET_ALL: 170 opcode = "CLUSTER_RESET_ALL"; 171 break; 172 case MFI_DCMD_CLUSTER_RESET_LD: 173 opcode = "CLUSTER_RESET_LD"; 174 break; 175 default: 176 opcode = "UNKNOWN"; 177 break; 178 } 179 180 device_printf(dev, "cmd=MFI_CMD_DCMD opcode=%s data_len=%d\n", 181 opcode, hdr->data_len); 182 mfi_print_frame_flags(dev, hdr->flags); 183 mfi_print_sgl(hdr, &dcmd->sgl, hdr->sg_count); 184 185 } 186 187 static void 188 mfi_print_generic_frame(struct mfi_softc *sc, struct mfi_command *cm) 189 { 190 hexdump(cm->cm_frame, cm->cm_total_frame_size, NULL, HD_OMIT_CHARS); 191 } 192 193 void 194 mfi_print_cmd(struct mfi_command *cm) 195 { 196 device_t dev; 197 struct mfi_softc *sc; 198 199 sc = cm->cm_sc; 200 dev = sc->mfi_dev; 201 202 device_printf(dev, "cm=%p index=%d total_frame_size=%d " 203 "extra_frames=%d\n", cm, cm->cm_index, cm->cm_total_frame_size, 204 cm->cm_extra_frames); 205 device_printf(dev, "flags=%b\n", cm->cm_flags, 206 "\20" 207 "\1MAPPED" 208 "\2DATAIN" 209 "\3DATAOUT" 210 "\4COMPLETED" 211 "\5POLLED" 212 "\6Q_FREE" 213 "\7Q_READY" 214 "\10Q_BUSY"); 215 216 switch (cm->cm_frame->header.cmd) { 217 case MFI_CMD_DCMD: 218 mfi_print_dcmd(sc, dev, cm); 219 break; 220 case MFI_CMD_LD_READ: 221 case MFI_CMD_LD_WRITE: 222 mfi_print_ldio(sc, dev, cm); 223 break; 224 default: 225 mfi_print_generic_frame(sc, cm); 226 break; 227 } 228 229 return; 230 } 231 232 void 233 mfi_dump_cmds(struct mfi_softc *sc) 234 { 235 int i; 236 237 for (i = 0; i < sc->mfi_total_cmds; i++) 238 mfi_print_generic_frame(sc, &sc->mfi_commands[i]); 239 } 240 241 void 242 mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm, 243 const char *function, int line) 244 { 245 struct mfi_frame_header *hdr; 246 int i; 247 uint32_t count = 0, data_len; 248 249 hdr = &cm->cm_frame->header; 250 count = 0; 251 for (i = 0; i < hdr->sg_count; i++) { 252 if (hdr->flags & MFI_FRAME_IEEE_SGL) 253 count += cm->cm_sg->sg_skinny[i].len; 254 else if (hdr->flags & MFI_FRAME_SGL64) 255 count += cm->cm_sg->sg64[i].len; 256 else 257 count += cm->cm_sg->sg32[i].len; 258 } 259 /* 260 count++; 261 */ 262 data_len = hdr->data_len; 263 switch (hdr->cmd) { 264 case MFI_CMD_LD_READ: 265 case MFI_CMD_LD_WRITE: 266 data_len = data_len * 512; 267 case MFI_CMD_DCMD: 268 if (count != data_len) { 269 device_printf(sc->mfi_dev, 270 "%s %d COMMAND %p S/G count bad %d %d %d 0x%jx\n", 271 function, line, cm, count, data_len, cm->cm_len, 272 (intmax_t)pmap_kextract((vm_offset_t)cm->cm_data)); 273 MFI_PRINT_CMD(cm); 274 } 275 } 276 } 277 278 #endif 279