56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This file and its contents are supplied under the terms of the
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Common Development and Distribution License ("CDDL"), version 1.0.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * You may only use this file in accordance with the terms of version
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * 1.0 of the CDDL.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * A full copy of the text of the CDDL should have accompanied this
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * source. A copy of the CDDL is also available via the Internet at
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This file is part of the Chelsio T4 support code.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Copyright (C) 2011-2013 Chelsio Communications. All rights reserved.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * This program is distributed in the hope that it will be useful, but WITHOUT
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * FITNESS FOR A PARTICULAR PURPOSE. See the LICENSE file included in this
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * release for licensing terms and conditions.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int pci_rw(struct adapter *sc, void *data, int flags, int write);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int reg_rw(struct adapter *sc, void *data, int flags, int write);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic void reg_block_dump(struct adapter *sc, uint8_t *buf, unsigned int start,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana unsigned int end);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int regdump(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int get_sge_context(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int get_devlog(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_card_mem(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_tid_tab(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_mbox(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_cim_la(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_cim_qcfg(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_cim_ibq(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanastatic int read_edc(struct adapter *sc, void *data, int flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanat4_ioctl(struct adapter *sc, int cmd, void *data, int mode)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = pci_rw(sc, data, mode, cmd == T4_IOCTL_PCIPUT32);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = reg_rw(sc, data, mode, cmd == T4_IOCTL_PUT32);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanapci_rw(struct adapter *sc, void *data, int flags, int write)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &r, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* address must be 32 bit aligned */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana t4_os_pci_write_cfg4(sc, r.reg, r.value);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana t4_os_pci_read_cfg4(sc, r.reg, &r.value);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(&r, data, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanareg_rw(struct adapter *sc, void *data, int flags, int write)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &r, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* Register address must be 32 bit aligned */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(&r, data, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanareg_block_dump(struct adapter *sc, uint8_t *buf, unsigned int start,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* LINTED: E_BAD_PTR_CAST_ALIGN */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana uint32_t *p = (uint32_t *)(buf + start);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana for (/* */; start <= end; start += sizeof (uint32_t))
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaregdump(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana static const unsigned int reg_ranges[] = {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &r, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = kmem_zalloc(T4_REGDUMP_SIZE, KM_SLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana r.version = 4 | (sc->params.rev << 10);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana for (i = 0; i < ARRAY_SIZE(reg_ranges); i += 2)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana reg_block_dump(sc, buf, reg_ranges[i], reg_ranges[i + 1]);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, r.data, r.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (rc == 0 && ddi_copyout(&r, data, sizeof (r), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaget_sge_context(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &sgec, sizeof (sgec), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (sgec.len < SGE_CTXT_SIZE || sgec.addr > M_CTXTQID) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if ((sgec.mem_id != T4_CTXT_EGRESS) && (sgec.mem_id != T4_CTXT_FLM) &&
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana -t4_sge_ctxt_rd(sc, sc->mbox, sgec.addr, sgec.mem_id, buff) :
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana -t4_sge_ctxt_rd_bd(sc, sgec.addr, sgec.mem_id, buff);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana sgec.version = 4 | (sc->params.rev << 10);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* copyout data and then t4_sge_context */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_copyout(buff, sgec.data, sgec.len, flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_copyout(&sgec, data, sizeof (sgec), flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* if ddi_copyout fails, return EFAULT - for either of the two */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_tid_tab(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4tid, sizeof (t4tid), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = b = kmem_zalloc(t4tid.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, t4tid.data, t4tid.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_card_mem(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana uint32_t base, size, lo, hi, win, off, remaining, i, n;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &mr, sizeof (mr), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* reads are in multiples of 32 bits */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (mr.addr & 3 || mr.len & 3 || mr.len == 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * We don't want to deal with potential holes so we mandate that the
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * requested region must lie entirely within one of the 3 memories.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana lo = t4_read_reg(sc, A_MA_TARGET_MEM_ENABLE);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana mr.addr >= base && mr.addr < base + size &&
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana mr.addr >= base && mr.addr < base + size &&
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana hi = t4_read_reg(sc, A_MA_EXT_MEMORY_BAR);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana mr.addr >= base && mr.addr < base + size &&
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = b = kmem_zalloc(mr.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Position the PCIe window (we use memwin2) to the 16B aligned area
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * just at/before the requested region.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana off = mr.addr - win; /* offset of the requested region in the win */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2), win);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2));
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* number of bytes that we'll copy in the inner loop */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana n = min(remaining, MEMWIN2_APERTURE - off);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana for (i = 0; i < n; i += 4, remaining -= 4)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana *b++ = t4_read_reg(sc, MEMWIN2_BASE + off + i);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, mr.data, mr.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaget_devlog(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana struct devlog_params *dparams = &sc->params.devlog;
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &dl, sizeof (dl), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = ddi_copyout(&dl, data, sizeof (dl), flags);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * rc = 0 indicates copyout was successful, then return ENOBUFS
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * to indicate that the buffer size was not enough. Return of
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * EFAULT indicates that the copyout was not successful.
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = kmem_zalloc(dparams->size, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = -t4_mem_read(sc, dparams->memtype, dparams->start, dparams->size,
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana /* Copyout device log buffer and then carrier buffer */
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, dl.data, dl.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana else if (ddi_copyout(&dl, data, sizeof (dl), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_cim_qcfg(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4cimqcfg, sizeof (t4cimqcfg), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = t4_cim_read(sc, A_UP_IBQ_0_RDADDR, ARRAY_SIZE(t4cimqcfg.stat),
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana t4_read_cimq_cfg(sc, t4cimqcfg.base, t4cimqcfg.size, t4cimqcfg.thres);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(&t4cimqcfg, data, sizeof (t4cimqcfg), flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_edc(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4edc, sizeof (t4edc), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana edc = kmem_zalloc(t4edc.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * Offset into the region of memory which is being accessed
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * MEM_EDC0 = 0
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana * MEM_EDC1 = 1
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana memoffset = (t4edc.mem * (5 * 1024 * 1024));
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = t4_mem_win_read(sc, (pos + memoffset), edc);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(edc, t4edc.data, t4edc.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_cim_ibq(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4ibq, sizeof (t4ibq), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = kmem_zalloc(t4ibq.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = t4_read_cim_ibq(sc, 3, (u32 *)buf, CIM_IBQ_SIZE * 4);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, t4ibq.data, t4ibq.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_cim_la(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4cimla, sizeof (t4cimla), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = kmem_zalloc(t4cimla.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana rc = t4_cim_read_la(sc, (u32 *)buf, NULL);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyout(buf, t4cimla.data, t4cimla.len, flags) < 0)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushanaread_mbox(struct adapter *sc, void *data, int flags)
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana u32 data_reg = PF_REG(4, A_CIM_PF_MAILBOX_DATA);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana if (ddi_copyin(data, &t4mbox, sizeof (t4mbox), flags) < 0) {
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana buf = p = kmem_zalloc(t4mbox.len, KM_NOSLEEP);
56b2bdd1f04d465cfe4a95b88ae5cba5884154e4Gireesh Nagabhushana for (i = 0; i < t4mbox.len; i += 8, p++)