#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bus_space_alignstride_chipdep.c,v 1.32 2022/09/29 07:00:46 skrll Exp $");
#ifdef CHIP_EXTENT
#include <sys/extent.h>
#endif
#include <mips/locore.h>
#include <uvm/uvm_extern.h>
#if defined(__mips_o32) && defined(MIPS3)
#define NEED_64BIT_ASM
#endif
#define __C(A,B) __CONCAT(A,B)
#define __S(S) __STRING(S)
#ifdef CHIP_IO
#define __BS(A) __C(__C(CHIP,_bus_io_),A)
#endif
#ifdef CHIP_MEM
#define __BS(A) __C(__C(CHIP,_bus_mem_),A)
#endif
#if defined(CHIP_LITTLE_ENDIAN)
#define CHIP_SWAP16(x) le16toh(x)
#define CHIP_SWAP32(x) le32toh(x)
#define CHIP_SWAP64(x) le64toh(x)
#define CHIP_NEED_STREAM 1
#elif defined(CHIP_BIG_ENDIAN)
#define CHIP_SWAP16(x) be16toh(x)
#define CHIP_SWAP32(x) be32toh(x)
#define CHIP_SWAP64(x) be64toh(x)
#define CHIP_NEED_STREAM 1
#else
#define CHIP_SWAP16(x) (x)
#define CHIP_SWAP32(x) (x)
#define CHIP_SWAP64(x) (x)
#endif
#ifndef CHIP_ACCESS_SIZE
#define CHIP_ACCESS_SIZE 1
#endif
#if CHIP_ACCESS_SIZE==1
# define CHIP_SWAP_ACCESS(x) (x)
#elif CHIP_ACCESS_SIZE==2
# define CHIP_SWAP_ACCESS(x) CHIP_SWAP16(x)
#elif CHIP_ACCESS_SIZE==4
# define CHIP_SWAP_ACCESS(x) CHIP_SWAP32(x)
#elif CHIP_ACCESS_SIZE==8
# ifndef MIPS3_PLUS
# error 8 byte access size not available
# endif
# define CHIP_SWAP_ACCESS(x) CHIP_SWAP64(x)
#else
# error your access size not implemented
#endif
#if CHIP_ACCESS_SIZE == 1
#define CHIP_TYPE uint8_t
#endif
#if CHIP_ACCESS_SIZE == 2
#define CHIP_TYPE uint16_t
#endif
#if CHIP_ACCESS_SIZE == 4
#define CHIP_TYPE uint32_t
#endif
#if CHIP_ACCESS_SIZE == 8
#define CHIP_TYPE uint64_t
#endif
#ifndef CHIP_TYPE
#error "Invalid chip access size!"
#endif
#ifdef CHIP_EXTENT
#ifndef CHIP_EX_STORE
static long
__BS(ex_storage)[EXTENT_FIXED_STORAGE_SIZE(8) / sizeof(long)];
#define CHIP_EX_STORE(v) (__BS(ex_storage))
#define CHIP_EX_STORE_SIZE(v) (sizeof __BS(ex_storage))
#endif
#endif
#ifndef CHIP_ALIGN_STRIDE
#define CHIP_ALIGN_STRIDE 0
#endif
#ifdef CHIP_WRONG_ENDIAN
#define CHIP_OFF8(o) ((o) ^ 3)
#else
#if CHIP_ALIGN_STRIDE > 0
#define CHIP_OFF8(o) ((o) << (CHIP_ALIGN_STRIDE))
#else
#define CHIP_OFF8(o) (o)
#endif
#endif
#ifdef CHIP_WRONG_ENDIAN
#define CHIP_OFF16(o) ((o) ^ 2)
#else
#if CHIP_ALIGN_STRIDE > 1
#define CHIP_OFF16(o) ((o) << (CHIP_ALIGN_STRIDE - 1))
#else
#define CHIP_OFF16(o) (o)
#endif
#endif
#if CHIP_ALIGN_STRIDE > 2
#define CHIP_OFF32(o) ((o) << (CHIP_ALIGN_STRIDE - 2))
#else
#define CHIP_OFF32(o) (o)
#endif
#if CHIP_ALIGN_STRIDE > 3
#define CHIP_OFF64(o) ((o) << (CHIP_ALIGN_STRIDE - 3))
#else
#define CHIP_OFF64(o) (o)
#endif
static int
__BS(get_window)(void *v, int window, struct mips_bus_space_translation *mbst)
{
switch (window) {
#ifdef CHIP_W1_BUS_START
case 0:
mbst->mbst_bus_start = CHIP_W1_BUS_START(v);
mbst->mbst_bus_end = CHIP_W1_BUS_END(v);
mbst->mbst_sys_start = CHIP_W1_SYS_START(v);
mbst->mbst_sys_end = CHIP_W1_SYS_END(v);
mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
mbst->mbst_flags = 0;
break;
#endif
#ifdef CHIP_W2_BUS_START
case 1:
mbst->mbst_bus_start = CHIP_W2_BUS_START(v);
mbst->mbst_bus_end = CHIP_W2_BUS_END(v);
mbst->mbst_sys_start = CHIP_W2_SYS_START(v);
mbst->mbst_sys_end = CHIP_W2_SYS_END(v);
mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
mbst->mbst_flags = 0;
break;
#endif
#ifdef CHIP_W3_BUS_START
case 2:
mbst->mbst_bus_start = CHIP_W3_BUS_START(v);
mbst->mbst_bus_end = CHIP_W3_BUS_END(v);
mbst->mbst_sys_start = CHIP_W3_SYS_START(v);
mbst->mbst_sys_end = CHIP_W3_SYS_END(v);
mbst->mbst_align_stride = CHIP_ALIGN_STRIDE;
mbst->mbst_flags = 0;
break;
#endif
default:
panic(__S(__BS(get_window)) ": invalid window %d",
window);
}
return (0);
}
static int
__BS(translate)(void *v, bus_addr_t addr, bus_size_t len, int flags,
struct mips_bus_space_translation *mbst)
{
bus_addr_t end = addr + (len - 1);
#if CHIP_ALIGN_STRIDE != 0
int linear = flags & BUS_SPACE_MAP_LINEAR;
if (linear)
return (EOPNOTSUPP);
#endif
#ifdef CHIP_W1_BUS_START
if (addr >= CHIP_W1_BUS_START(v) && end <= CHIP_W1_BUS_END(v))
return (__BS(get_window)(v, 0, mbst));
#endif
#ifdef CHIP_W2_BUS_START
if (addr >= CHIP_W2_BUS_START(v) && end <= CHIP_W2_BUS_END(v))
return (__BS(get_window)(v, 1, mbst));
#endif
#ifdef CHIP_W3_BUS_START
if (addr >= CHIP_W3_BUS_START(v) && end <= CHIP_W3_BUS_END(v))
return (__BS(get_window)(v, 2, mbst));
#endif
#ifdef EXTENT_DEBUG
printf("\n");
#ifdef CHIP_W1_BUS_START
printf("%s: window[1]=0x%lx-0x%lx\n", __S(__BS(map)),
(u_long)CHIP_W1_BUS_START(v), (u_long)CHIP_W1_BUS_END(v));
#endif
#ifdef CHIP_W2_BUS_START
printf("%s: window[2]=0x%lx-0x%lx\n", __S(__BS(map)),
(u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
#ifdef CHIP_W3_BUS_START
printf("%s: window[3]=0x%lx-0x%lx\n", __S(__BS(map)),
(u_long)CHIP_W3_BUS_START(v), (u_long)CHIP_W3_BUS_END(v));
#endif
#endif
return (EINVAL);
}
static int
__BS(map)(void *v, bus_addr_t addr, bus_size_t size, int flags,
bus_space_handle_t *hp, int acct)
{
struct mips_bus_space_translation mbst;
int error;
error = __BS(translate)(v, addr, size, flags, &mbst);
if (error)
return (error);
#ifdef CHIP_EXTENT
if (acct == 0)
goto mapit;
#ifdef EXTENT_DEBUG
printf("%s: allocating %#"PRIxBUSADDR" to %#"PRIxBUSADDR"\n",
__S(__BS(map)), addr, addr + size - 1);
#endif
error = extent_alloc_region(CHIP_EXTENT(v), addr, size,
EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
if (error) {
#ifdef EXTENT_DEBUG
printf("%s: allocation failed (%d)\n", __S(__BS(map)), error);
extent_print(CHIP_EXTENT(v));
#endif
return (error);
}
mapit:
#endif
addr = mbst.mbst_sys_start + (addr - mbst.mbst_bus_start);
#if defined(__mips_n32) || defined(_LP64)
if (flags & BUS_SPACE_MAP_CACHEABLE) {
#ifdef __mips_n32
if (((addr + size) & ~MIPS_PHYS_MASK) == 0)
*hp = (intptr_t)MIPS_PHYS_TO_KSEG0(addr);
else
#endif
*hp = MIPS_PHYS_TO_XKPHYS_CACHED(addr);
} else if (flags & BUS_SPACE_MAP_PREFETCHABLE) {
*hp = MIPS_PHYS_TO_XKPHYS_ACC(addr);
} else {
#ifdef __mips_n32
if (((addr + size) & ~MIPS_PHYS_MASK) == 0)
*hp = (intptr_t)MIPS_PHYS_TO_KSEG1(addr);
else
#endif
*hp = MIPS_PHYS_TO_XKPHYS_UNCACHED(addr);
}
#else
if (((addr + size) & ~MIPS_PHYS_MASK) != 0) {
vaddr_t va;
paddr_t pa;
int s;
size = round_page((addr % PAGE_SIZE) + size);
va = uvm_km_alloc(kernel_map, size, PAGE_SIZE,
UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
if (va == 0)
return ENOMEM;
KASSERT(!(MIPS_KSEG0_P(va) || MIPS_KSEG1_P(va)));
*hp = va + (addr & PAGE_MASK);
pa = trunc_page(addr);
s = splhigh();
while (size != 0) {
pmap_kenter_pa(va, pa, VM_PROT_READ | VM_PROT_WRITE, 0);
pa += PAGE_SIZE;
va += PAGE_SIZE;
size -= PAGE_SIZE;
}
pmap_update(pmap_kernel());
splx(s);
} else {
if (flags & BUS_SPACE_MAP_CACHEABLE)
*hp = (intptr_t)MIPS_PHYS_TO_KSEG0(addr);
else
*hp = (intptr_t)MIPS_PHYS_TO_KSEG1(addr);
}
#endif
return (0);
}
static void
__BS(unmap)(void *v, bus_space_handle_t h, bus_size_t size, int acct)
{
#if !defined(_LP64) || defined(CHIP_EXTENT)
bus_addr_t addr = 0;
#endif
#ifndef _LP64
bool handle_is_km;
handle_is_km = !(MIPS_KSEG0_P(h) || MIPS_KSEG1_P(h));
#ifdef __mips_n32
if (handle_is_km == true)
handle_is_km = !MIPS_XKPHYS_P(h);
#endif
if (handle_is_km == true) {
paddr_t pa;
vaddr_t va = (vaddr_t)trunc_page(h);
vsize_t sz = (vsize_t)round_page((h % PAGE_SIZE) + size);
int s;
s = splhigh();
if (pmap_extract(pmap_kernel(), (vaddr_t)h, &pa) == false)
panic("%s: pmap_extract failed", __func__);
addr = (bus_addr_t)pa;
#if 0
printf("%s:%d: addr %#"PRIxBUSADDR", sz %#"PRIxVSIZE"\n",
__func__, __LINE__, addr, sz);
#endif
KASSERT (((addr + sz) & ~MIPS_PHYS_MASK) != 0);
pmap_kremove(va, sz);
pmap_update(pmap_kernel());
uvm_km_free(kernel_map, va, sz, UVM_KMF_VAONLY);
splx(s);
}
#endif
#ifdef CHIP_EXTENT
if (acct == 0)
return;
#ifdef EXTENT_DEBUG
printf("%s: freeing handle %#"PRIxBSH" for %#"PRIxBUSSIZE"\n",
__S(__BS(unmap)), h, size);
#endif
#ifdef _LP64
KASSERT(MIPS_XKPHYS_P(h));
addr = MIPS_XKPHYS_TO_PHYS(h);
#else
if (handle_is_km == false) {
if (MIPS_KSEG0_P(h))
addr = MIPS_KSEG0_TO_PHYS(h);
#ifdef __mips_n32
else if (MIPS_XKPHYS_P(h))
addr = MIPS_XKPHYS_TO_PHYS(h);
#endif
else
addr = MIPS_KSEG1_TO_PHYS(h);
}
#endif
#ifdef CHIP_W1_BUS_START
if (addr >= CHIP_W1_SYS_START(v) && addr <= CHIP_W1_SYS_END(v)) {
addr = CHIP_W1_BUS_START(v) + (addr - CHIP_W1_SYS_START(v));
} else
#endif
#ifdef CHIP_W2_BUS_START
if (addr >= CHIP_W2_SYS_START(v) && addr <= CHIP_W2_SYS_END(v)) {
addr = CHIP_W2_BUS_START(v) + (addr - CHIP_W2_SYS_START(v));
} else
#endif
#ifdef CHIP_W3_BUS_START
if (addr >= CHIP_W3_SYS_START(v) && addr <= CHIP_W3_SYS_END(v)) {
addr = CHIP_W3_BUS_START(v) + (addr - CHIP_W3_SYS_START(v));
} else
#endif
{
printf("\n");
#ifdef CHIP_W1_BUS_START
printf("%s: sys window[1]=0x%lx-0x%lx\n",
__S(__BS(unmap)), (u_long)CHIP_W1_SYS_START(v),
(u_long)CHIP_W1_SYS_END(v));
#endif
#ifdef CHIP_W2_BUS_START
printf("%s: sys window[2]=0x%lx-0x%lx\n",
__S(__BS(unmap)), (u_long)CHIP_W2_SYS_START(v),
(u_long)CHIP_W2_SYS_END(v));
#endif
#ifdef CHIP_W3_BUS_START
printf("%s: sys window[3]=0x%lx-0x%lx\n",
__S(__BS(unmap)), (u_long)CHIP_W3_SYS_START(v),
(u_long)CHIP_W3_SYS_END(v));
#endif
panic("%s: don't know how to unmap %#"PRIxBSH, __S(__BS(unmap)), h);
}
#ifdef EXTENT_DEBUG
printf("%s: freeing %#"PRIxBUSADDR" to %#"PRIxBUSADDR"\n",
__S(__BS(unmap)), addr, addr + size - 1);
#endif
int error = extent_free(CHIP_EXTENT(v), addr, size,
EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
if (error) {
printf("%s: WARNING: could not unmap"
" %#"PRIxBUSADDR"-%#"PRIxBUSADDR" (error %d)\n",
__S(__BS(unmap)), addr, addr + size - 1, error);
#ifdef EXTENT_DEBUG
extent_print(CHIP_EXTENT(v));
#endif
}
#endif
#if !defined(_LP64) || defined(CHIP_EXTENT)
__USE(addr);
#endif
}
static int
__BS(subregion)(void *v, bus_space_handle_t h, bus_size_t offset,
bus_size_t size, bus_space_handle_t *nh)
{
*nh = h + (offset << CHIP_ALIGN_STRIDE);
return (0);
}
static int
__BS(alloc)(void *v, bus_addr_t rstart, bus_addr_t rend, bus_size_t size,
bus_size_t align, bus_size_t boundary, int flags, bus_addr_t *addrp,
bus_space_handle_t *bshp)
{
#ifdef CHIP_EXTENT
struct mips_bus_space_translation mbst;
u_long addr;
int error;
#if CHIP_ALIGN_STRIDE != 0
int linear = flags & BUS_SPACE_MAP_LINEAR;
if (linear)
return (EOPNOTSUPP);
#endif
#ifdef EXTENT_DEBUG
printf("%s: allocating from %#"PRIxBUSADDR" to %#"PRIxBUSADDR"\n",
__S(__BS(alloc)), rstart, rend);
#endif
error = extent_alloc_subregion(CHIP_EXTENT(v), rstart, rend, size,
align, boundary,
EX_FAST | EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0),
&addr);
if (error) {
#ifdef EXTENT_DEBUG
printf("%s: allocation failed (%d)\n", __S(__BS(alloc)), error);
extent_print(CHIP_EXTENT(v));
#endif
return (error);
}
#ifdef EXTENT_DEBUG
printf("%s: allocated 0x%lx to %#"PRIxBUSSIZE"\n",
__S(__BS(alloc)), addr, addr + size - 1);
#endif
error = __BS(translate)(v, addr, size, flags, &mbst);
if (error) {
(void) extent_free(CHIP_EXTENT(v), addr, size,
EX_NOWAIT | (CHIP_EX_MALLOC_SAFE(v) ? EX_MALLOCOK : 0));
return (error);
}
*addrp = addr;
#if !defined(__mips_o32)
if (flags & BUS_SPACE_MAP_CACHEABLE) {
*bshp = MIPS_PHYS_TO_XKPHYS_CACHED(mbst.mbst_sys_start +
(addr - mbst.mbst_bus_start));
} else {
*bshp = MIPS_PHYS_TO_XKPHYS_UNCACHED(mbst.mbst_sys_start +
(addr - mbst.mbst_bus_start));
}
#else
if (flags & BUS_SPACE_MAP_CACHEABLE) {
*bshp = MIPS_PHYS_TO_KSEG0(mbst.mbst_sys_start +
(addr - mbst.mbst_bus_start));
} else
*bshp = MIPS_PHYS_TO_KSEG1(mbst.mbst_sys_start +
(addr - mbst.mbst_bus_start));
#endif
return (0);
#else
return (EOPNOTSUPP);
#endif
}
static void
__BS(free)(void *v, bus_space_handle_t bsh, bus_size_t size)
{
__BS(unmap)(v, bsh, size, 1);
}
static void *
__BS(vaddr)(void *v, bus_space_handle_t bsh)
{
#if (CHIP_ALIGN_STRIDE != 0)
return (NULL);
#elif defined(__mips_n32)
if (MIPS_KSEG0_P(bsh) || MIPS_KSEG1_P(bsh) || MIPS_KSEG2_P(bsh))
return ((void *)(intptr_t)bsh);
return NULL;
#else
return ((void *)bsh);
#endif
}
static paddr_t
__BS(mmap)(void *v, bus_addr_t addr, off_t off, int prot, int flags)
{
#ifdef CHIP_IO
return (-1);
#elif defined(CHIP_MEM)
paddr_t ret;
struct mips_bus_space_translation mbst;
int error;
error = __BS(translate)(v, addr, off + PAGE_SIZE, flags,
&mbst);
if (error)
return (-1);
ret = mbst.mbst_sys_start + (addr - mbst.mbst_bus_start) + off;
#if defined(_MIPS_PADDR_T_64BIT) || defined(_LP64)
if (flags & BUS_SPACE_MAP_PREFETCHABLE) {
ret |= PGC_PREFETCH;
}
#endif
return (mips_btop(ret));
#else
# error must define one of CHIP_IO or CHIP_MEM
#endif
}
static void
__BS(barrier)(void *v, bus_space_handle_t h, bus_size_t o, bus_size_t l, int f)
{
if ((f & BUS_SPACE_BARRIER_WRITE) != 0)
wbflush();
}
static uint8_t
__BS(read_1)(void *v, bus_space_handle_t h, bus_size_t off)
{
h += CHIP_OFF8(off);
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
#if CHIP_ACCESS_SIZE == 8
const CHIP_TYPE val = mips3_ld(h);
#elif CHIP_ACCESS_SIZE == 4
const CHIP_TYPE val = mips_lwu(h);
#elif CHIP_ACCESS_SIZE == 2
const CHIP_TYPE val = mips_lhu(h);
#else
const uint8_t val = mips_lbu(h);
#endif
const uint8_t r = (uint8_t)(CHIP_SWAP_ACCESS(val) >> shift);
return r;
}
static uint16_t
__BS(read_2)(void *v, bus_space_handle_t h, bus_size_t off)
{
KASSERT((off & 1) == 0);
h += CHIP_OFF16(off);
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
#if CHIP_ACCESS_SIZE == 8
const CHIP_TYPE val = mips3_ld(h);
#elif CHIP_ACCESS_SIZE == 4
const CHIP_TYPE val = mips_lwu(h);
#else
const uint16_t val = mips_lhu(h);
#endif
const uint16_t r = (uint16_t)CHIP_SWAP16(val >> shift);
return r;
}
static uint32_t
__BS(read_4)(void *v, bus_space_handle_t h, bus_size_t off)
{
KASSERT((off & 3) == 0);
h += CHIP_OFF32(off);
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
#if CHIP_ACCESS_SIZE > 4
const CHIP_TYPE val = mips3_ld(h);
#else
const uint32_t val = mips_lwu(h);
#endif
const uint32_t r = (uint32_t)CHIP_SWAP32(val >> shift);
return r;
}
static uint64_t
__BS(read_8)(void *v, bus_space_handle_t h, bus_size_t off)
{
#ifdef MIPS3_64BIT
KASSERT((off & 7) == 0);
h += CHIP_OFF64(off);
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
const uint64_t r = CHIP_SWAP64(mips3_ld(h) >> shift);
return r;
#else
panic("%s: not implemented!", __func__);
#endif
}
#define CHIP_read_multi_N(BYTES,TYPE) \
static void \
__C(__BS(read_multi_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__BS(barrier)(v, h, o, sizeof *a, \
BUS_SPACE_BARRIER_READ); \
*a++ = __C(__BS(read_),BYTES)(v, h, o); \
} \
}
CHIP_read_multi_N(1,uint8_t)
CHIP_read_multi_N(2,uint16_t)
CHIP_read_multi_N(4,uint32_t)
CHIP_read_multi_N(8,uint64_t)
#define CHIP_read_region_N(BYTES,TYPE) \
static void \
__C(__BS(read_region_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
*a++ = __C(__BS(read_),BYTES)(v, h, o); \
o += sizeof *a; \
} \
}
CHIP_read_region_N(1,uint8_t)
CHIP_read_region_N(2,uint16_t)
CHIP_read_region_N(4,uint32_t)
CHIP_read_region_N(8,uint64_t)
static void
__BS(write_1)(void *v, bus_space_handle_t h, bus_size_t off, uint8_t val)
{
h += CHIP_OFF8(off);
#if CHIP_ACCESS_SIZE == 1
mips_sb(h, val);
#else
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
CHIP_TYPE cval = CHIP_SWAP_ACCESS(((CHIP_TYPE)val) << shift);
# if CHIP_ACCESS_SIZE == 8
mips3_sd(h, cval);
# elif CHIP_ACCESS_SIZE == 4
mips_sw(h, cval);
# else
mips_sh(h, cval);
# endif
#endif
}
static void
__BS(write_2)(void *v, bus_space_handle_t h, bus_size_t off, uint16_t val)
{
KASSERT((h & 1) == 0);
KASSERT((off & 1) == 0);
h += CHIP_OFF16(off);
#if CHIP_ACCESS_SIZE <= 2
mips_sh(h, CHIP_SWAP16(val));
#else
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
CHIP_TYPE cval = ((CHIP_TYPE)CHIP_SWAP16(val)) << shift;
# if CHIP_ACCESS_SIZE == 8
mips3_sd(h, cval);
# else
mips_sw(h, cval);
# endif
#endif
}
static void
__BS(write_4)(void *v, bus_space_handle_t h, bus_size_t off, uint32_t val)
{
KASSERT((h & 3) == 0);
KASSERT((off & 3) == 0);
h += CHIP_OFF32(off);
#if CHIP_ACCESS_SIZE <= 4
mips_sw(h, CHIP_SWAP32(val));
#else
const int shift = (h & (CHIP_ACCESS_SIZE - 1)) * 8;
h &= ~((bus_space_handle_t)(CHIP_ACCESS_SIZE - 1));
mips3_sd(h, ((CHIP_TYPE)CHIP_SWAP32(val)) << shift);
#endif
}
static void
__BS(write_8)(void *v, bus_space_handle_t h, bus_size_t off, uint64_t val)
{
#ifdef MIPS3_64BIT
KASSERT((h & 7) == 0);
KASSERT((off & 7) == 0);
h += CHIP_OFF64(off);
mips3_sd(h, CHIP_SWAP64(val));
#else
panic("%s: not implemented!", __func__);
#endif
}
#define CHIP_write_multi_N(BYTES,TYPE) \
static void \
__C(__BS(write_multi_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, const TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_),BYTES)(v, h, o, *a++); \
__BS(barrier)(v, h, o, sizeof *a, \
BUS_SPACE_BARRIER_WRITE); \
} \
}
CHIP_write_multi_N(1,uint8_t)
CHIP_write_multi_N(2,uint16_t)
CHIP_write_multi_N(4,uint32_t)
CHIP_write_multi_N(8,uint64_t)
#define CHIP_write_region_N(BYTES,TYPE) \
static void \
__C(__BS(write_region_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, const TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_),BYTES)(v, h, o, *a++); \
o += sizeof *a; \
} \
}
CHIP_write_region_N(1,uint8_t)
CHIP_write_region_N(2,uint16_t)
CHIP_write_region_N(4,uint32_t)
CHIP_write_region_N(8,uint64_t)
#define CHIP_set_multi_N(BYTES,TYPE) \
static void \
__C(__BS(set_multi_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE val, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_),BYTES)(v, h, o, val); \
__BS(barrier)(v, h, o, sizeof val, \
BUS_SPACE_BARRIER_WRITE); \
} \
}
CHIP_set_multi_N(1,uint8_t)
CHIP_set_multi_N(2,uint16_t)
CHIP_set_multi_N(4,uint32_t)
CHIP_set_multi_N(8,uint64_t)
#define CHIP_set_region_N(BYTES,TYPE) \
static void \
__C(__BS(set_region_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE val, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_),BYTES)(v, h, o, val); \
o += sizeof val; \
} \
}
CHIP_set_region_N(1,uint8_t)
CHIP_set_region_N(2,uint16_t)
CHIP_set_region_N(4,uint32_t)
CHIP_set_region_N(8,uint64_t)
#define CHIP_copy_region_N(BYTES) \
static void \
__C(__BS(copy_region_),BYTES)(void *v, bus_space_handle_t h1, \
bus_size_t o1, bus_space_handle_t h2, bus_size_t o2, bus_size_t c) \
{ \
bus_size_t o; \
\
if ((h1 + o1) >= (h2 + o2)) { \
\
for (o = 0; c != 0; c--, o += BYTES) \
__C(__BS(write_),BYTES)(v, h2, o2 + o, \
__C(__BS(read_),BYTES)(v, h1, o1 + o)); \
} else { \
\
for (o = (c - 1) * BYTES; c != 0; c--, o -= BYTES) \
__C(__BS(write_),BYTES)(v, h2, o2 + o, \
__C(__BS(read_),BYTES)(v, h1, o1 + o)); \
} \
}
CHIP_copy_region_N(1)
CHIP_copy_region_N(2)
CHIP_copy_region_N(4)
CHIP_copy_region_N(8)
#ifdef CHIP_NEED_STREAM
static uint8_t
__BS(read_stream_1)(void *v, bus_space_handle_t h, bus_size_t off)
{
h += CHIP_OFF8(off);
#if CHIP_ACCESS_SIZE == 8
return (uint8_t)mips3_ld(h);
#elif CHIP_ACCESS_SIZE == 4
return (uint8_t)mips_lwu(h);
#elif CHIP_ACCESS_SIZE == 2
return (uint8_t)mips_lhu(h);
#else
return mips_lbu(h);
#endif
}
static uint16_t
__BS(read_stream_2)(void *v, bus_space_handle_t h, bus_size_t off)
{
h += CHIP_OFF16(off);
#if CHIP_ACCESS_SIZE == 8
return (uint16_t)mips3_ld(h);
#elif CHIP_ACCESS_SIZE == 4
return (uint16_t)mips_lwu(h);
#else
return (uint16_t)mips_lbu(h);
#endif
}
static uint32_t
__BS(read_stream_4)(void *v, bus_space_handle_t h, bus_size_t off)
{
h += CHIP_OFF32(off);
#if CHIP_ACCESS_SIZE == 8
return (uint32_t)mips3_ld(h);
#else
return (uint32_t)mips_lwu(h);
#endif
}
static uint64_t
__BS(read_stream_8)(void *v, bus_space_handle_t h, bus_size_t off)
{
#ifdef MIPS3_64BIT
h += CHIP_OFF64(off);
return mips3_ld(h);
#else
panic("%s: not implemented!", __func__);
#endif
}
#define CHIP_read_multi_stream_N(BYTES,TYPE) \
static void \
__C(__BS(read_multi_stream_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__BS(barrier)(v, h, o, sizeof *a, \
BUS_SPACE_BARRIER_READ); \
*a++ = __C(__BS(read_stream_),BYTES)(v, h, o); \
} \
}
CHIP_read_multi_stream_N(1,uint8_t)
CHIP_read_multi_stream_N(2,uint16_t)
CHIP_read_multi_stream_N(4,uint32_t)
CHIP_read_multi_stream_N(8,uint64_t)
#define CHIP_read_region_stream_N(BYTES,TYPE) \
static void \
__C(__BS(read_region_stream_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
*a++ = __C(__BS(read_stream_),BYTES)(v, h, o); \
o += sizeof *a; \
} \
}
CHIP_read_region_stream_N(1,uint8_t)
CHIP_read_region_stream_N(2,uint16_t)
CHIP_read_region_stream_N(4,uint32_t)
CHIP_read_region_stream_N(8,uint64_t)
static void
__BS(write_stream_1)(void *v, bus_space_handle_t h, bus_size_t off,
uint8_t val)
{
#if CHIP_ACCESS_SIZE == 8
mips3_sd(h, val);
#elif CHIP_ACCESS_SIZE == 4
mips_sw(h, val);
#elif CHIP_ACCESS_SIZE == 2
mips_sh(h, val);
#else
mips_sb(h, val);
#endif
}
static void
__BS(write_stream_2)(void *v, bus_space_handle_t h, bus_size_t off,
uint16_t val)
{
#if CHIP_ACCESS_SIZE == 8
mips3_sd(h, val);
#elif CHIP_ACCESS_SIZE == 4
mips_sw(h, val);
#else
mips_sh(h, val);
#endif
}
static void
__BS(write_stream_4)(void *v, bus_space_handle_t h, bus_size_t off,
uint32_t val)
{
h += CHIP_OFF32(off);
#if CHIP_ACCESS_SIZE == 8
mips3_sd(h, val);
#else
mips_sw(h, val);
#endif
}
static void
__BS(write_stream_8)(void *v, bus_space_handle_t h, bus_size_t off,
uint64_t val)
{
#ifdef MIPS3_64BIT
h += CHIP_OFF64(off);
mips3_sd(h, val);
#else
panic("%s: not implemented!", __func__);
#endif
}
#define CHIP_write_multi_stream_N(BYTES,TYPE) \
static void \
__C(__BS(write_multi_stream_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, const TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_stream_),BYTES)(v, h, o, *a++); \
__BS(barrier)(v, h, o, sizeof *a, \
BUS_SPACE_BARRIER_WRITE); \
} \
}
CHIP_write_multi_stream_N(1,uint8_t)
CHIP_write_multi_stream_N(2,uint16_t)
CHIP_write_multi_stream_N(4,uint32_t)
CHIP_write_multi_stream_N(8,uint64_t)
#define CHIP_write_region_stream_N(BYTES,TYPE) \
static void \
__C(__BS(write_region_stream_),BYTES)(void *v, bus_space_handle_t h, \
bus_size_t o, const TYPE *a, bus_size_t c) \
{ \
\
while (c-- > 0) { \
__C(__BS(write_stream_),BYTES)(v, h, o, *a++); \
o += sizeof *a; \
} \
}
CHIP_write_region_stream_N(1,uint8_t)
CHIP_write_region_stream_N(2,uint16_t)
CHIP_write_region_stream_N(4,uint32_t)
CHIP_write_region_stream_N(8,uint64_t)
#endif
void
__BS(init)(bus_space_tag_t t, void *v)
{
#ifdef CHIP_EXTENT
struct extent *ex;
#endif
t->bs_cookie = v;
t->bs_map = __BS(map);
t->bs_unmap = __BS(unmap);
t->bs_subregion = __BS(subregion);
t->bs_translate = __BS(translate);
t->bs_get_window = __BS(get_window);
t->bs_alloc = __BS(alloc);
t->bs_free = __BS(free);
t->bs_vaddr = __BS(vaddr);
t->bs_mmap = __BS(mmap);
t->bs_barrier = __BS(barrier);
t->bs_r_1 = __BS(read_1);
t->bs_r_2 = __BS(read_2);
t->bs_r_4 = __BS(read_4);
t->bs_r_8 = __BS(read_8);
t->bs_rm_1 = __BS(read_multi_1);
t->bs_rm_2 = __BS(read_multi_2);
t->bs_rm_4 = __BS(read_multi_4);
t->bs_rm_8 = __BS(read_multi_8);
t->bs_rr_1 = __BS(read_region_1);
t->bs_rr_2 = __BS(read_region_2);
t->bs_rr_4 = __BS(read_region_4);
t->bs_rr_8 = __BS(read_region_8);
t->bs_w_1 = __BS(write_1);
t->bs_w_2 = __BS(write_2);
t->bs_w_4 = __BS(write_4);
t->bs_w_8 = __BS(write_8);
t->bs_wm_1 = __BS(write_multi_1);
t->bs_wm_2 = __BS(write_multi_2);
t->bs_wm_4 = __BS(write_multi_4);
t->bs_wm_8 = __BS(write_multi_8);
t->bs_wr_1 = __BS(write_region_1);
t->bs_wr_2 = __BS(write_region_2);
t->bs_wr_4 = __BS(write_region_4);
t->bs_wr_8 = __BS(write_region_8);
t->bs_sm_1 = __BS(set_multi_1);
t->bs_sm_2 = __BS(set_multi_2);
t->bs_sm_4 = __BS(set_multi_4);
t->bs_sm_8 = __BS(set_multi_8);
t->bs_sr_1 = __BS(set_region_1);
t->bs_sr_2 = __BS(set_region_2);
t->bs_sr_4 = __BS(set_region_4);
t->bs_sr_8 = __BS(set_region_8);
t->bs_c_1 = __BS(copy_region_1);
t->bs_c_2 = __BS(copy_region_2);
t->bs_c_4 = __BS(copy_region_4);
t->bs_c_8 = __BS(copy_region_8);
#ifdef CHIP_NEED_STREAM
t->bs_rs_1 = __BS(read_stream_1);
t->bs_rs_2 = __BS(read_stream_2);
t->bs_rs_4 = __BS(read_stream_4);
t->bs_rs_8 = __BS(read_stream_8);
t->bs_rms_1 = __BS(read_multi_stream_1);
t->bs_rms_2 = __BS(read_multi_stream_2);
t->bs_rms_4 = __BS(read_multi_stream_4);
t->bs_rms_8 = __BS(read_multi_stream_8);
t->bs_rrs_1 = __BS(read_region_stream_1);
t->bs_rrs_2 = __BS(read_region_stream_2);
t->bs_rrs_4 = __BS(read_region_stream_4);
t->bs_rrs_8 = __BS(read_region_stream_8);
t->bs_ws_1 = __BS(write_stream_1);
t->bs_ws_2 = __BS(write_stream_2);
t->bs_ws_4 = __BS(write_stream_4);
t->bs_ws_8 = __BS(write_stream_8);
t->bs_wms_1 = __BS(write_multi_stream_1);
t->bs_wms_2 = __BS(write_multi_stream_2);
t->bs_wms_4 = __BS(write_multi_stream_4);
t->bs_wms_8 = __BS(write_multi_stream_8);
t->bs_wrs_1 = __BS(write_region_stream_1);
t->bs_wrs_2 = __BS(write_region_stream_2);
t->bs_wrs_4 = __BS(write_region_stream_4);
t->bs_wrs_8 = __BS(write_region_stream_8);
#else
t->bs_rs_1 = __BS(read_1);
t->bs_rs_2 = __BS(read_2);
t->bs_rs_4 = __BS(read_4);
t->bs_rs_8 = __BS(read_8);
t->bs_rms_1 = __BS(read_multi_1);
t->bs_rms_2 = __BS(read_multi_2);
t->bs_rms_4 = __BS(read_multi_4);
t->bs_rms_8 = __BS(read_multi_8);
t->bs_rrs_1 = __BS(read_region_1);
t->bs_rrs_2 = __BS(read_region_2);
t->bs_rrs_4 = __BS(read_region_4);
t->bs_rrs_8 = __BS(read_region_8);
t->bs_ws_1 = __BS(write_1);
t->bs_ws_2 = __BS(write_2);
t->bs_ws_4 = __BS(write_4);
t->bs_ws_8 = __BS(write_8);
t->bs_wms_1 = __BS(write_multi_1);
t->bs_wms_2 = __BS(write_multi_2);
t->bs_wms_4 = __BS(write_multi_4);
t->bs_wms_8 = __BS(write_multi_8);
t->bs_wrs_1 = __BS(write_region_1);
t->bs_wrs_2 = __BS(write_region_2);
t->bs_wrs_4 = __BS(write_region_4);
t->bs_wrs_8 = __BS(write_region_8);
#endif
#ifdef CHIP_EXTENT
ex = extent_create(__S(__BS(bus)), 0x0UL, ~0UL,
(void *)CHIP_EX_STORE(v), CHIP_EX_STORE_SIZE(v), EX_NOWAIT);
extent_alloc_region(ex, 0, ~0UL, EX_NOWAIT);
#ifdef CHIP_W1_BUS_START
if (CHIP_W1_BUS_START(v) == (bus_addr_t) -1) {
#ifdef EXTENT_DEBUG
printf("%s: this space is disabled\n", __S(__BS(init)));
#endif
return;
}
#ifdef EXTENT_DEBUG
printf("%s: freeing from %#"PRIxBUSADDR" to %#"PRIxBUSADDR"\n",
__S(__BS(init)), (bus_addr_t)CHIP_W1_BUS_START(v),
(bus_addr_t)CHIP_W1_BUS_END(v));
#endif
extent_free(ex, CHIP_W1_BUS_START(v),
CHIP_W1_BUS_END(v) - CHIP_W1_BUS_START(v) + 1, EX_NOWAIT);
#endif
#ifdef CHIP_W2_BUS_START
if (CHIP_W2_BUS_START(v) != CHIP_W1_BUS_START(v)) {
#ifdef EXTENT_DEBUG
printf("xxx: freeing from 0x%lx to 0x%lx\n",
(u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
extent_free(ex, CHIP_W2_BUS_START(v),
CHIP_W2_BUS_END(v) - CHIP_W2_BUS_START(v) + 1, EX_NOWAIT);
} else {
#ifdef EXTENT_DEBUG
printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
(u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
}
#endif
#ifdef CHIP_W3_BUS_START
if (CHIP_W3_BUS_START(v) != CHIP_W1_BUS_START(v) &&
CHIP_W3_BUS_START(v) != CHIP_W2_BUS_START(v)) {
#ifdef EXTENT_DEBUG
printf("xxx: freeing from 0x%lx to 0x%lx\n",
(u_long)CHIP_W3_BUS_START(v), (u_long)CHIP_W3_BUS_END(v));
#endif
extent_free(ex, CHIP_W3_BUS_START(v),
CHIP_W3_BUS_END(v) - CHIP_W3_BUS_START(v) + 1, EX_NOWAIT);
} else {
#ifdef EXTENT_DEBUG
printf("xxx: window 2 (0x%lx to 0x%lx) overlaps window 1\n",
(u_long)CHIP_W2_BUS_START(v), (u_long)CHIP_W2_BUS_END(v));
#endif
}
#endif
#ifdef EXTENT_DEBUG
extent_print(ex);
#endif
CHIP_EXTENT(v) = ex;
#endif
}