15ba21ff1SScott Long /*- 2*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3*718cf2ccSPedro F. Giffuni * 45ba21ff1SScott Long * Copyright (c) 2006 IronPort Systems 55ba21ff1SScott Long * All rights reserved. 65ba21ff1SScott Long * 75ba21ff1SScott Long * Redistribution and use in source and binary forms, with or without 85ba21ff1SScott Long * modification, are permitted provided that the following conditions 95ba21ff1SScott Long * are met: 105ba21ff1SScott Long * 1. Redistributions of source code must retain the above copyright 115ba21ff1SScott Long * notice, this list of conditions and the following disclaimer. 125ba21ff1SScott Long * 2. Redistributions in binary form must reproduce the above copyright 135ba21ff1SScott Long * notice, this list of conditions and the following disclaimer in the 145ba21ff1SScott Long * documentation and/or other materials provided with the distribution. 155ba21ff1SScott Long * 165ba21ff1SScott Long * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 175ba21ff1SScott Long * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 185ba21ff1SScott Long * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 195ba21ff1SScott Long * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 205ba21ff1SScott Long * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 215ba21ff1SScott Long * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 225ba21ff1SScott Long * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 235ba21ff1SScott Long * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 245ba21ff1SScott Long * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 255ba21ff1SScott Long * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 265ba21ff1SScott Long * SUCH DAMAGE. 275ba21ff1SScott Long */ 285ba21ff1SScott Long 295ba21ff1SScott Long #include <sys/cdefs.h> 305ba21ff1SScott Long __FBSDID("$FreeBSD$"); 315ba21ff1SScott Long 32420a5a0eSScott Long #include "opt_mfi.h" 335ba21ff1SScott Long 345ba21ff1SScott Long #ifdef MFI_DEBUG 355ba21ff1SScott Long 365ba21ff1SScott Long #include <sys/param.h> 375ba21ff1SScott Long #include <sys/systm.h> 385ba21ff1SScott Long #include <sys/kernel.h> 395ba21ff1SScott Long #include <sys/conf.h> 405ba21ff1SScott Long #include <sys/bus.h> 415ba21ff1SScott Long #include <sys/bio.h> 425ba21ff1SScott Long #include <sys/lock.h> 435ba21ff1SScott Long #include <sys/mutex.h> 445ba21ff1SScott Long #include <sys/malloc.h> 455ba21ff1SScott Long #include <sys/selinfo.h> 46d185f187SKonstantin Belousov #include <sys/sysctl.h> 475ba21ff1SScott Long #include <sys/taskqueue.h> 485ba21ff1SScott Long #include <sys/uio.h> 495ba21ff1SScott Long #include <machine/resource.h> 505ba21ff1SScott Long #include <machine/bus.h> 515ba21ff1SScott Long 52441f6d5dSScott Long #include <vm/vm.h> 53441f6d5dSScott Long #include <vm/pmap.h> 54441f6d5dSScott Long 555ba21ff1SScott Long #include <dev/mfi/mfireg.h> 565ba21ff1SScott Long #include <dev/mfi/mfi_ioctl.h> 575ba21ff1SScott Long #include <dev/mfi/mfivar.h> 585ba21ff1SScott Long 595ba21ff1SScott Long static void 605ba21ff1SScott Long mfi_print_frame_flags(device_t dev, uint32_t flags) 615ba21ff1SScott Long { 6208c89430SSteven Hartland device_printf(dev, "flags=%b\n", flags, MFI_FRAME_FMT); 635ba21ff1SScott Long } 645ba21ff1SScott Long 655ba21ff1SScott Long static void 665ba21ff1SScott Long mfi_print_sgl(struct mfi_frame_header *hdr, union mfi_sgl *sgl, int count) 675ba21ff1SScott Long { 685ba21ff1SScott Long int i, columns = 0; 695ba21ff1SScott Long 705ba21ff1SScott Long printf("SG List:\n"); 715ba21ff1SScott Long for (i = 0; i < count; i++) { 72a6ba0fd6SDoug Ambrisko if (hdr->flags & MFI_FRAME_IEEE_SGL) { 73a6ba0fd6SDoug Ambrisko printf("0x%lx:%06d ", (u_long)sgl->sg_skinny[i].addr, 74a6ba0fd6SDoug Ambrisko sgl->sg_skinny[i].len); 75a6ba0fd6SDoug Ambrisko columns += 26; 76a6ba0fd6SDoug Ambrisko if (columns > 77) { 77a6ba0fd6SDoug Ambrisko printf("\n"); 78a6ba0fd6SDoug Ambrisko columns = 0; 79a6ba0fd6SDoug Ambrisko } 80a6ba0fd6SDoug Ambrisko } else if (hdr->flags & MFI_FRAME_SGL64) { 815ba21ff1SScott Long printf("0x%lx:%06d ", (u_long)sgl->sg64[i].addr, 825ba21ff1SScott Long sgl->sg64[i].len); 835ba21ff1SScott Long columns += 26; 845ba21ff1SScott Long if (columns > 77) { 855ba21ff1SScott Long printf("\n"); 865ba21ff1SScott Long columns = 0; 875ba21ff1SScott Long } 885ba21ff1SScott Long } else { 895ba21ff1SScott Long printf("0x%x:%06d ", sgl->sg32[i].addr, 905ba21ff1SScott Long sgl->sg32[i].len); 915ba21ff1SScott Long columns += 18; 925ba21ff1SScott Long if (columns > 71) { 935ba21ff1SScott Long printf("\n"); 945ba21ff1SScott Long columns = 0; 955ba21ff1SScott Long } 965ba21ff1SScott Long } 975ba21ff1SScott Long } 985ba21ff1SScott Long if (columns != 0) 995ba21ff1SScott Long printf("\n"); 1005ba21ff1SScott Long 1015ba21ff1SScott Long } 1025ba21ff1SScott Long 1035ba21ff1SScott Long static void 1045ba21ff1SScott Long mfi_print_ldio(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 1055ba21ff1SScott Long { 1065ba21ff1SScott Long struct mfi_io_frame *io; 1075ba21ff1SScott Long struct mfi_frame_header *hdr; 1085ba21ff1SScott Long 1095ba21ff1SScott Long io = &cm->cm_frame->io; 1105ba21ff1SScott Long hdr = &io->header; 1115ba21ff1SScott Long 1125ba21ff1SScott Long device_printf(dev, "cmd=%s target_id=%d sg_count=%d data_len=%d " 1135ba21ff1SScott Long "lba=%d\n", (hdr->cmd == MFI_CMD_LD_READ) ? "LD_READ":"LD_WRITE", 1145ba21ff1SScott Long hdr->target_id, hdr->sg_count, hdr->data_len, io->lba_lo); 1155ba21ff1SScott Long mfi_print_frame_flags(dev, hdr->flags); 1165ba21ff1SScott Long mfi_print_sgl(hdr, &io->sgl, hdr->sg_count); 1175ba21ff1SScott Long 1185ba21ff1SScott Long } 1195ba21ff1SScott Long 1205ba21ff1SScott Long static void 1215ba21ff1SScott Long mfi_print_dcmd(struct mfi_softc *sc, device_t dev, struct mfi_command *cm) 1225ba21ff1SScott Long { 1235ba21ff1SScott Long struct mfi_dcmd_frame *dcmd; 1245ba21ff1SScott Long struct mfi_frame_header *hdr; 1255ba21ff1SScott Long const char *opcode; 1265ba21ff1SScott Long 1275ba21ff1SScott Long dcmd = &cm->cm_frame->dcmd; 1285ba21ff1SScott Long hdr = &dcmd->header; 1295ba21ff1SScott Long 1305ba21ff1SScott Long switch (dcmd->opcode) { 1315ba21ff1SScott Long case MFI_DCMD_CTRL_GETINFO: 1325ba21ff1SScott Long opcode = "CTRL_GETINFO"; 1335ba21ff1SScott Long break; 1345ba21ff1SScott Long case MFI_DCMD_CTRL_FLUSHCACHE: 1355ba21ff1SScott Long opcode = "CTRL_FLUSHCACHE"; 1365ba21ff1SScott Long break; 1375ba21ff1SScott Long case MFI_DCMD_CTRL_SHUTDOWN: 1385ba21ff1SScott Long opcode = "CTRL_SHUTDOWN"; 1395ba21ff1SScott Long break; 1405ba21ff1SScott Long case MFI_DCMD_CTRL_EVENT_GETINFO: 1415ba21ff1SScott Long opcode = "EVENT_GETINFO"; 1425ba21ff1SScott Long break; 1435ba21ff1SScott Long case MFI_DCMD_CTRL_EVENT_GET: 1445ba21ff1SScott Long opcode = "EVENT_GET"; 1455ba21ff1SScott Long break; 1465ba21ff1SScott Long case MFI_DCMD_CTRL_EVENT_WAIT: 1475ba21ff1SScott Long opcode = "EVENT_WAIT"; 1485ba21ff1SScott Long break; 1495ba21ff1SScott Long case MFI_DCMD_LD_GET_LIST: 1505ba21ff1SScott Long opcode = "LD_GET_LIST"; 1515ba21ff1SScott Long break; 1525ba21ff1SScott Long case MFI_DCMD_LD_GET_INFO: 1535ba21ff1SScott Long opcode = "LD_GET_INFO"; 1545ba21ff1SScott Long break; 1555ba21ff1SScott Long case MFI_DCMD_LD_GET_PROP: 1565ba21ff1SScott Long opcode = "LD_GET_PROP"; 1575ba21ff1SScott Long break; 1585ba21ff1SScott Long case MFI_DCMD_LD_SET_PROP: 1595ba21ff1SScott Long opcode = "LD_SET_PROP"; 1605ba21ff1SScott Long break; 1615ba21ff1SScott Long case MFI_DCMD_CLUSTER: 1625ba21ff1SScott Long opcode = "CLUSTER"; 1635ba21ff1SScott Long break; 1645ba21ff1SScott Long case MFI_DCMD_CLUSTER_RESET_ALL: 1655ba21ff1SScott Long opcode = "CLUSTER_RESET_ALL"; 1665ba21ff1SScott Long break; 1675ba21ff1SScott Long case MFI_DCMD_CLUSTER_RESET_LD: 1685ba21ff1SScott Long opcode = "CLUSTER_RESET_LD"; 1695ba21ff1SScott Long break; 170ddbffe7fSDoug Ambrisko case MFI_DCMD_LD_MAP_GET_INFO: 171ddbffe7fSDoug Ambrisko opcode = "LD_MAP_GET_INFO"; 172ddbffe7fSDoug Ambrisko break; 173dee3e845SMark Johnston case MFI_DCMD_BBU_START_LEARN: 174dee3e845SMark Johnston opcode = "BBU_START_LEARN"; 175dee3e845SMark Johnston break; 176dee3e845SMark Johnston case MFI_DCMD_BBU_GET_PROP: 177dee3e845SMark Johnston opcode = "BBU_GET_PROP"; 178dee3e845SMark Johnston break; 179dee3e845SMark Johnston case MFI_DCMD_BBU_SET_PROP: 180dee3e845SMark Johnston opcode = "BBU_SET_PROP"; 181dee3e845SMark Johnston break; 1825ba21ff1SScott Long default: 1835ba21ff1SScott Long opcode = "UNKNOWN"; 1845ba21ff1SScott Long break; 1855ba21ff1SScott Long } 1865ba21ff1SScott Long 1875ba21ff1SScott Long device_printf(dev, "cmd=MFI_CMD_DCMD opcode=%s data_len=%d\n", 1885ba21ff1SScott Long opcode, hdr->data_len); 1895ba21ff1SScott Long mfi_print_frame_flags(dev, hdr->flags); 1905ba21ff1SScott Long mfi_print_sgl(hdr, &dcmd->sgl, hdr->sg_count); 1915ba21ff1SScott Long 1925ba21ff1SScott Long } 1935ba21ff1SScott Long 1945ba21ff1SScott Long static void 1955ba21ff1SScott Long mfi_print_generic_frame(struct mfi_softc *sc, struct mfi_command *cm) 1965ba21ff1SScott Long { 1975ba21ff1SScott Long hexdump(cm->cm_frame, cm->cm_total_frame_size, NULL, HD_OMIT_CHARS); 1985ba21ff1SScott Long } 1995ba21ff1SScott Long 2005ba21ff1SScott Long void 2015ba21ff1SScott Long mfi_print_cmd(struct mfi_command *cm) 2025ba21ff1SScott Long { 2035ba21ff1SScott Long device_t dev; 2045ba21ff1SScott Long struct mfi_softc *sc; 2055ba21ff1SScott Long 2065ba21ff1SScott Long sc = cm->cm_sc; 2075ba21ff1SScott Long dev = sc->mfi_dev; 2085ba21ff1SScott Long 2095ba21ff1SScott Long device_printf(dev, "cm=%p index=%d total_frame_size=%d " 2105ba21ff1SScott Long "extra_frames=%d\n", cm, cm->cm_index, cm->cm_total_frame_size, 2115ba21ff1SScott Long cm->cm_extra_frames); 21208c89430SSteven Hartland device_printf(dev, "flags=%b\n", cm->cm_flags, MFI_CMD_FLAGS_FMT); 2135ba21ff1SScott Long 2145ba21ff1SScott Long switch (cm->cm_frame->header.cmd) { 2155ba21ff1SScott Long case MFI_CMD_DCMD: 2165ba21ff1SScott Long mfi_print_dcmd(sc, dev, cm); 2175ba21ff1SScott Long break; 2185ba21ff1SScott Long case MFI_CMD_LD_READ: 2195ba21ff1SScott Long case MFI_CMD_LD_WRITE: 2205ba21ff1SScott Long mfi_print_ldio(sc, dev, cm); 2215ba21ff1SScott Long break; 2225ba21ff1SScott Long default: 2235ba21ff1SScott Long mfi_print_generic_frame(sc, cm); 2245ba21ff1SScott Long break; 2255ba21ff1SScott Long } 2265ba21ff1SScott Long 2275ba21ff1SScott Long return; 2285ba21ff1SScott Long } 2295ba21ff1SScott Long 2305ba21ff1SScott Long void 2315ba21ff1SScott Long mfi_dump_cmds(struct mfi_softc *sc) 2325ba21ff1SScott Long { 2335ba21ff1SScott Long int i; 2345ba21ff1SScott Long 23508c89430SSteven Hartland for (i = 0; i < sc->mfi_max_fw_cmds; i++) 2365ba21ff1SScott Long mfi_print_generic_frame(sc, &sc->mfi_commands[i]); 2375ba21ff1SScott Long } 2385ba21ff1SScott Long 239441f6d5dSScott Long void 240441f6d5dSScott Long mfi_validate_sg(struct mfi_softc *sc, struct mfi_command *cm, 241441f6d5dSScott Long const char *function, int line) 242441f6d5dSScott Long { 243441f6d5dSScott Long struct mfi_frame_header *hdr; 244441f6d5dSScott Long int i; 245441f6d5dSScott Long uint32_t count = 0, data_len; 246441f6d5dSScott Long 247441f6d5dSScott Long hdr = &cm->cm_frame->header; 248441f6d5dSScott Long count = 0; 249441f6d5dSScott Long for (i = 0; i < hdr->sg_count; i++) { 250a6ba0fd6SDoug Ambrisko if (hdr->flags & MFI_FRAME_IEEE_SGL) 251a6ba0fd6SDoug Ambrisko count += cm->cm_sg->sg_skinny[i].len; 252a6ba0fd6SDoug Ambrisko else if (hdr->flags & MFI_FRAME_SGL64) 253a6ba0fd6SDoug Ambrisko count += cm->cm_sg->sg64[i].len; 254a6ba0fd6SDoug Ambrisko else 255441f6d5dSScott Long count += cm->cm_sg->sg32[i].len; 256441f6d5dSScott Long } 257441f6d5dSScott Long /* 258441f6d5dSScott Long count++; 259441f6d5dSScott Long */ 260441f6d5dSScott Long data_len = hdr->data_len; 261441f6d5dSScott Long switch (hdr->cmd) { 262441f6d5dSScott Long case MFI_CMD_LD_READ: 263441f6d5dSScott Long case MFI_CMD_LD_WRITE: 264441f6d5dSScott Long data_len = data_len * 512; 265441f6d5dSScott Long case MFI_CMD_DCMD: 266441f6d5dSScott Long if (count != data_len) { 267441f6d5dSScott Long device_printf(sc->mfi_dev, 268441f6d5dSScott Long "%s %d COMMAND %p S/G count bad %d %d %d 0x%jx\n", 269441f6d5dSScott Long function, line, cm, count, data_len, cm->cm_len, 270441f6d5dSScott Long (intmax_t)pmap_kextract((vm_offset_t)cm->cm_data)); 271441f6d5dSScott Long MFI_PRINT_CMD(cm); 272441f6d5dSScott Long } 273441f6d5dSScott Long } 274441f6d5dSScott Long } 275441f6d5dSScott Long 2765ba21ff1SScott Long #endif 277