#include "lio_bsd.h"
#include "lio_common.h"
#include "lio_droq.h"
#include "lio_iq.h"
#include "lio_response_manager.h"
#include "lio_device.h"
#include "lio_mem_ops.h"
#define MEMOPS_IDX LIO_MAX_BAR1_MAP_INDEX
#if BYTE_ORDER == BIG_ENDIAN
static inline void
lio_toggle_bar1_swapmode(struct octeon_device *oct, uint32_t idx)
{
uint32_t mask;
mask = oct->fn_list.bar1_idx_read(oct, idx);
mask = (mask & 0x2) ? (mask & ~2) : (mask | 2);
oct->fn_list.bar1_idx_write(oct, idx, mask);
}
#else
#define lio_toggle_bar1_swapmode(oct, idx)
#endif
static inline void
lio_write_bar1_mem8(struct octeon_device *oct, uint32_t reg, uint64_t val)
{
bus_space_write_1(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg, val);
}
#ifdef __i386__
static inline uint32_t
lio_read_bar1_mem32(struct octeon_device *oct, uint32_t reg)
{
return (bus_space_read_4(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg));
}
static inline void
lio_write_bar1_mem32(struct octeon_device *oct, uint32_t reg, uint32_t val)
{
bus_space_write_4(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg, val);
}
#endif
static inline uint64_t
lio_read_bar1_mem64(struct octeon_device *oct, uint32_t reg)
{
#ifdef __i386__
return (lio_read_bar1_mem32(oct, reg) |
((uint64_t)lio_read_bar1_mem32(oct, reg + 4) << 32));
#else
return (bus_space_read_8(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg));
#endif
}
static inline void
lio_write_bar1_mem64(struct octeon_device *oct, uint32_t reg, uint64_t val)
{
#ifdef __i386__
lio_write_bar1_mem32(oct, reg, (uint32_t)val);
lio_write_bar1_mem32(oct, reg + 4, val >> 32);
#else
bus_space_write_8(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg, val);
#endif
}
static void
lio_pci_fastwrite(struct octeon_device *oct, uint32_t offset,
uint8_t *hostbuf, uint32_t len)
{
while ((len) && ((unsigned long)offset) & 7) {
lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
len--;
}
lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
while (len >= 8) {
lio_write_bar1_mem64(oct, offset, *((uint64_t *)hostbuf));
offset += 8;
hostbuf += 8;
len -= 8;
}
lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
while (len--)
lio_write_bar1_mem8(oct, offset++, *(hostbuf++));
}
static inline uint64_t
lio_read_bar1_mem8(struct octeon_device *oct, uint32_t reg)
{
return (bus_space_read_1(oct->mem_bus_space[1].tag,
oct->mem_bus_space[1].handle, reg));
}
static void
lio_pci_fastread(struct octeon_device *oct, uint32_t offset,
uint8_t *hostbuf, uint32_t len)
{
while ((len) && ((unsigned long)offset) & 7) {
*(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
len--;
}
lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
while (len >= 8) {
*((uint64_t *)hostbuf) = lio_read_bar1_mem64(oct, offset);
offset += 8;
hostbuf += 8;
len -= 8;
}
lio_toggle_bar1_swapmode(oct, MEMOPS_IDX);
while (len--)
*(hostbuf++) = lio_read_bar1_mem8(oct, offset++);
}
static void
lio_pci_rw_core_mem(struct octeon_device *oct, uint64_t addr,
uint8_t *hostbuf, uint32_t len, uint32_t op)
{
uint64_t static_mapping_base;
uint32_t copy_len = 0, index_reg_val = 0;
uint32_t offset;
static_mapping_base = oct->console_nb_info.dram_region_base;
if (static_mapping_base && static_mapping_base ==
(addr & 0xFFFFFFFFFFC00000ULL)) {
int bar1_index = oct->console_nb_info.bar1_index;
offset = (bar1_index << 22) + (addr & 0x3fffff);
if (op)
lio_pci_fastread(oct, offset, hostbuf, len);
else
lio_pci_fastwrite(oct, offset, hostbuf, len);
return;
}
mtx_lock(&oct->mem_access_lock);
index_reg_val = oct->fn_list.bar1_idx_read(oct, MEMOPS_IDX);
do {
oct->fn_list.bar1_idx_setup(oct, addr, MEMOPS_IDX, 1);
offset = (MEMOPS_IDX << 22) + (addr & 0x3fffff);
if (((addr + len - 1) & ~(0x3fffff)) != (addr & ~(0x3fffff))) {
copy_len = (uint32_t)(((addr & ~(0x3fffff)) +
(MEMOPS_IDX << 22)) - addr);
} else {
copy_len = len;
}
if (op) {
lio_pci_fastread(oct, offset, hostbuf,
copy_len);
} else {
lio_pci_fastwrite(oct, offset, hostbuf,
copy_len);
}
len -= copy_len;
addr += copy_len;
hostbuf += copy_len;
} while (len);
oct->fn_list.bar1_idx_write(oct, MEMOPS_IDX, index_reg_val);
mtx_unlock(&oct->mem_access_lock);
}
void
lio_pci_read_core_mem(struct octeon_device *oct, uint64_t coreaddr,
uint8_t *buf, uint32_t len)
{
lio_pci_rw_core_mem(oct, coreaddr, buf, len, 1);
}
void
lio_pci_write_core_mem(struct octeon_device *oct, uint64_t coreaddr,
uint8_t *buf, uint32_t len)
{
lio_pci_rw_core_mem(oct, coreaddr, buf, len, 0);
}
uint64_t
lio_read_device_mem64(struct octeon_device *oct, uint64_t coreaddr)
{
__be64 ret;
lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 8, 1);
return (be64toh(ret));
}
uint32_t
lio_read_device_mem32(struct octeon_device *oct, uint64_t coreaddr)
{
__be32 ret;
lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&ret, 4, 1);
return (be32toh(ret));
}
void
lio_write_device_mem32(struct octeon_device *oct, uint64_t coreaddr,
uint32_t val)
{
__be32 t = htobe32(val);
lio_pci_rw_core_mem(oct, coreaddr, (uint8_t *)&t, 4, 0);
}