static int csio_t5_set_mem_win(struct csio_hw *hw, uint32_t win) { u32 mem_win_base; /* * Truncation intentional: we only read the bottom 32-bits of the * 64-bit BAR0/BAR1 ... We use the hardware backdoor mechanism to * read BAR0 instead of using pci_resource_start() because we could be * operating from within a Virtual Machine which is trapping our * accesses to our Configuration Space and we need to set up the PCI-E * Memory Window decoders with the actual addresses which will be * coming across the PCI-E link. */ /* For T5, only relative offset inside the PCIe BAR is passed */ mem_win_base = MEMWIN_BASE; /* * Set up memory window for accessing adapter memory ranges. (Read * back MA register to ensure that changes propagate before we attempt * to use the new values.) */ csio_wr_reg32(hw, mem_win_base | BIR(0) | WINDOW(ilog2(MEMWIN_APERTURE) - 10), PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); return 0; }
static void t4_dump_tcb(struct adapter *sc, int tid) { uint32_t tcb_base, off, i, j; /* Dump TCB for the tid */ tcb_base = t4_read_reg(sc, A_TP_CMM_TCB_BASE); t4_write_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2), tcb_base + tid * TCB_SIZE); t4_read_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2)); off = 0; printf("\n"); for (i = 0; i < 4; i++) { uint32_t buf[8]; for (j = 0; j < 8; j++, off += 4) buf[j] = htonl(t4_read_reg(sc, MEMWIN2_BASE + off)); printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); } }
/* * csio_t5_memory_rw - read/write EDC 0, EDC 1 or MC via PCIE memory window * @hw: the csio_hw * @win: PCI-E memory Window to use * @mtype: memory type: MEM_EDC0, MEM_EDC1, MEM_MC0 (or MEM_MC) or MEM_MC1 * @addr: address within indicated memory type * @len: amount of memory to transfer * @buf: host memory buffer * @dir: direction of transfer 1 => read, 0 => write * * Reads/writes an [almost] arbitrary memory region in the firmware: the * firmware memory address, length and host buffer must be aligned on * 32-bit boudaries. The memory is transferred as a raw byte sequence * from/to the firmware's memory. If this memory contains data * structures which contain multi-byte integers, it's the callers * responsibility to perform appropriate byte order conversions. */ static int csio_t5_memory_rw(struct csio_hw *hw, u32 win, int mtype, u32 addr, u32 len, uint32_t *buf, int dir) { u32 pos, start, offset, memoffset; u32 edc_size, mc_size, win_pf, mem_reg, mem_aperture, mem_base; /* * Argument sanity checks ... */ if ((addr & 0x3) || (len & 0x3)) return -EINVAL; /* Offset into the region of memory which is being accessed * MEM_EDC0 = 0 * MEM_EDC1 = 1 * MEM_MC = 2 -- T4 * MEM_MC0 = 2 -- For T5 * MEM_MC1 = 3 -- For T5 */ edc_size = EDRAM_SIZE_GET(csio_rd_reg32(hw, MA_EDRAM0_BAR)); if (mtype != MEM_MC1) memoffset = (mtype * (edc_size * 1024 * 1024)); else { mc_size = EXT_MEM_SIZE_GET(csio_rd_reg32(hw, MA_EXT_MEMORY_BAR)); memoffset = (MEM_MC0 * edc_size + mc_size) * 1024 * 1024; } /* Determine the PCIE_MEM_ACCESS_OFFSET */ addr = addr + memoffset; /* * Each PCI-E Memory Window is programmed with a window size -- or * "aperture" -- which controls the granularity of its mapping onto * adapter memory. We need to grab that aperture in order to know * how to use the specified window. The window is also programmed * with the base address of the Memory Window in BAR0's address * space. For T4 this is an absolute PCI-E Bus Address. For T5 * the address is relative to BAR0. */ mem_reg = csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_BASE_WIN, win)); mem_aperture = 1 << (WINDOW(mem_reg) + 10); mem_base = GET_PCIEOFST(mem_reg) << 10; start = addr & ~(mem_aperture-1); offset = addr - start; win_pf = V_PFNUM(hw->pfn); csio_dbg(hw, "csio_t5_memory_rw: mem_reg: 0x%x, mem_aperture: 0x%x\n", mem_reg, mem_aperture); csio_dbg(hw, "csio_t5_memory_rw: mem_base: 0x%x, mem_offset: 0x%x\n", mem_base, memoffset); csio_dbg(hw, "csio_t5_memory_rw: start:0x%x, offset:0x%x, win_pf:%d\n", start, offset, win_pf); csio_dbg(hw, "csio_t5_memory_rw: mtype: %d, addr: 0x%x, len: %d\n", mtype, addr, len); for (pos = start; len > 0; pos += mem_aperture, offset = 0) { /* * Move PCI-E Memory Window to our current transfer * position. Read it back to ensure that changes propagate * before we attempt to use the new value. */ csio_wr_reg32(hw, pos | win_pf, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win)); csio_rd_reg32(hw, PCIE_MEM_ACCESS_REG(PCIE_MEM_ACCESS_OFFSET, win)); while (offset < mem_aperture && len > 0) { if (dir) *buf++ = csio_rd_reg32(hw, mem_base + offset); else csio_wr_reg32(hw, *buf++, mem_base + offset); offset += sizeof(__be32); len -= sizeof(__be32); } } return 0; }