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/taskqueue.h> 45 #include <sys/uio.h> 46 #include <machine/resource.h> 47 #include <machine/bus.h> 48 49 #include <vm/vm.h> 50 #include <vm/pmap.h> 51 52 #include <dev/mfi/mfireg.h> 53 #include <dev/mfi/mfi_ioctl.h> 54 #include <dev/mfi/mfivar.h> 55 56 static void 57 mfi_print_frame_flags(device_t dev, uint32_t flags) 58 { 59 device_printf(dev, "flags=%b\n", flags, 60 "\20" 61 "\1NOPOST" 62 "\2SGL64" 63 "\3SENSE64" 64 "\4WRITE" 65 "\5READ"); 66 } 67 68 static void 69 mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count) 70 { 71 int i, columns = 0; 72 73 printf("SG List:\n"); 74 for (i = 0; i < count; i++) { 75 if (hdr->flags & MFI_FRAME_SGL64) { 76 printf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr, 77 sgl->sg64[i].len); 78 columns += 26; 79 if (columns > 77) { 80 printf("\n"); 81 columns = 0; 82 } 83 } else { 84 printf("0x%x:%06d ", sgl->sg32[i].addr, 85 sgl->sg32[i].len); 86 columns += 18; 87 if (columns > 71) { 88 printf("\n"); 89 columns = 0; 90 } 91 } 92 } 93 if (columns != 0) 94 printf("\n"); 95 96 } 97 98 static void 99 mfi_print_ldio(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 100 { 101 struct mfi_io_frame *io; 102 struct mfi_frame_header *hdr; 103 104 io = &cm->cm_frame->io; 105 hdr = &io->header; 106 107 device_printf(dev, "cmd=%s target_id=%d sg_count=%d data_len=%d " 108 "lba=%d\n", (hdr->cmd == MFI_CMD_LD_READ) ? "LD_READ":"LD_WRITE", 109 hdr->target_id, hdr->sg_count, hdr->data_len, io->lba_lo); 110 mfi_print_frame_flags(dev, hdr->flags); 111 mfi_print_sgl(hdr, &io->sgl, hdr->sg_count); 112 113 } 114 115 static void 116 mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 117 { 118 struct mfi_dcmd_frame *dcmd; 119 struct mfi_frame_header *hdr; 120 const char *opcode; 121 122 dcmd = &cm->cm_frame->dcmd; 123 hdr = &dcmd->header; 124 125 switch (dcmd->opcode) { 126 case MFI_DCMD_CTRL_GETINFO: 127 opcode = "CTRL_GETINFO"; 128 break; 129 case MFI_DCMD_CTRL_FLUSHCACHE: 130 opcode = "CTRL_FLUSHCACHE"; 131 break; 132 case MFI_DCMD_CTRL_SHUTDOWN: 133 opcode = "CTRL_SHUTDOWN"; 134 break; 135 case MFI_DCMD_CTRL_EVENT_GETINFO: 136 opcode = "EVENT_GETINFO"; 137 break; 138 case MFI_DCMD_CTRL_EVENT_GET: 139 opcode = "EVENT_GET"; 140 break; 141 case MFI_DCMD_CTRL_EVENT_WAIT: 142 opcode = "EVENT_WAIT"; 143 break; 144 case MFI_DCMD_LD_GET_LIST: 145 opcode = "LD_GET_LIST"; 146 break; 147 case MFI_DCMD_LD_GET_INFO: 148 opcode = "LD_GET_INFO"; 149 break; 150 case MFI_DCMD_LD_GET_PROP: 151 opcode = "LD_GET_PROP"; 152 break; 153 case MFI_DCMD_LD_SET_PROP: 154 opcode = "LD_SET_PROP"; 155 break; 156 case MFI_DCMD_CLUSTER: 157 opcode = "CLUSTER"; 158 break; 159 case MFI_DCMD_CLUSTER_RESET_ALL: 160 opcode = "CLUSTER_RESET_ALL"; 161 break; 162 case MFI_DCMD_CLUSTER_RESET_LD: 163 opcode = "CLUSTER_RESET_LD"; 164 break; 165 default: 166 opcode = "UNKNOWN"; 167 break; 168 } 169 170 device_printf(dev, "cmd=MFI_CMD_DCMD opcode=%s data_len=%d\n", 171 opcode, hdr->data_len); 172 mfi_print_frame_flags(dev, hdr->flags); 173 mfi_print_sgl(hdr, &dcmd->sgl, hdr->sg_count); 174 175 } 176 177 static void 178 mfi_print_generic_frame(struct mfi_softc *sc, struct mfi_command *cm) 179 { 180 hexdump(cm->cm_frame, cm->cm_total_frame_size, NULL, HD_OMIT_CHARS); 181 } 182 183 void 184 mfi_print_cmd(struct mfi_command *cm) 185 { 186 device_t dev; 187 struct mfi_softc *sc; 188 189 sc = cm->cm_sc; 190 dev = sc->mfi_dev; 191 192 device_printf(dev, "cm=%p index=%d total_frame_size=%d " 193 "extra_frames=%d\n", cm, cm->cm_index, cm->cm_total_frame_size, 194 cm->cm_extra_frames); 195 device_printf(dev, "flags=%b\n", cm->cm_flags, 196 "\20" 197 "\1MAPPED" 198 "\2DATAIN" 199 "\3DATAOUT" 200 "\4COMPLETED" 201 "\5POLLED" 202 "\6Q_FREE" 203 "\7Q_READY" 204 "\10Q_BUSY"); 205 206 switch (cm->cm_frame->header.cmd) { 207 case MFI_CMD_DCMD: 208 mfi_print_dcmd(sc, dev, cm); 209 break; 210 case MFI_CMD_LD_READ: 211 case MFI_CMD_LD_WRITE: 212 mfi_print_ldio(sc, dev, cm); 213 break; 214 default: 215 mfi_print_generic_frame(sc, cm); 216 break; 217 } 218 219 return; 220 } 221 222 void 223 mfi_dump_cmds(struct mfi_softc *sc) 224 { 225 int i; 226 227 for (i = 0; i < sc->mfi_total_cmds; i++) 228 mfi_print_generic_frame(sc, &sc->mfi_commands[i]); 229 } 230 231 void 232 mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm, 233 const char *function, int line) 234 { 235 struct mfi_frame_header *hdr; 236 int i; 237 uint32_t count = 0, data_len; 238 239 hdr = &cm->cm_frame->header; 240 count = 0; 241 for (i = 0; i < hdr->sg_count; i++) { 242 count += cm->cm_sg->sg32[i].len; 243 } 244 /* 245 count++; 246 */ 247 data_len = hdr->data_len; 248 switch (hdr->cmd) { 249 case MFI_CMD_LD_READ: 250 case MFI_CMD_LD_WRITE: 251 data_len = data_len * 512; 252 case MFI_CMD_DCMD: 253 if (count != data_len) { 254 device_printf(sc->mfi_dev, 255 "%s %d COMMAND %p S/G count bad %d %d %d 0x%jx\n", 256 function, line, cm, count, data_len, cm->cm_len, 257 (intmax_t)pmap_kextract((vm_offset_t)cm->cm_data)); 258 MFI_PRINT_CMD(cm); 259 } 260 } 261 } 262 263 #endif 264