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