#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.6 2026/05/19 21:41:21 andvar Exp $");
#include "opt_cputype.h"
#define _MIPS_BUS_DMA_PRIVATE
#include <sys/param.h>
#include <sys/bus.h>
#include <sys/mbuf.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <machine/cpu.h>
#include <uvm/uvm_extern.h>
#include <mips/cpuregs.h>
#include <mips/locore.h>
#include <mips/cache.h>
struct mips_bus_dma_tag pmax_default_bus_dma_tag = {
._dmamap_ops = _BUS_DMAMAP_OPS_INITIALIZER,
._dmamem_ops = _BUS_DMAMEM_OPS_INITIALIZER,
._dmatag_ops = _BUS_DMATAG_OPS_INITIALIZER,
};
static void normal_bus_mem_init(bus_space_tag_t, void *);
#ifdef MIPS1
static void _bus_dmamap_sync_r3k(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
bus_size_t, int);
#endif
#if 0
static void _bus_dmamap_sync_r4k(bus_dma_tag_t, bus_dmamap_t, bus_addr_t,
bus_size_t, int);
#endif
static struct mips_bus_space normal_mbst;
bus_space_tag_t normal_memt = NULL;
void
pmax_bus_dma_init(void)
{
normal_bus_mem_init(&normal_mbst, NULL);
normal_memt = &normal_mbst;
#ifdef MIPS1
if (CPUISMIPS3 == 0)
pmax_default_bus_dma_tag._dmamap_ops.dmamap_sync = _bus_dmamap_sync_r3k;
#endif
#if 0
#ifdef MIPS3
if (CPUISMIPS3)
pmax_default_bus_dma_tag._dmamap_ops.dmamap_sync = _bus_dmamap_sync_r4k;
#endif
#endif
}
#ifdef MIPS1
static void
_bus_dmamap_sync_r3k(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
bus_size_t len, int ops)
{
bus_size_t minlen;
bus_addr_t addr;
int i;
if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
(ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
panic("_bus_dmamap_sync_r3k: mix PRE and POST");
#ifdef DIAGNOSTIC
if (offset >= map->dm_mapsize)
panic("%s: bad offset %ju (map size is %ju)", __func__,
(uintmax_t)offset, (uintmax_t)map->dm_mapsize);
if (len == 0 || (offset + len) > map->dm_mapsize)
panic("%s: bad length", __func__);
#endif
if (ops & BUS_DMASYNC_PREWRITE) {
wbflush();
}
if ((ops & BUS_DMASYNC_PREREAD) == 0)
return;
if (map->_dm_flags & _BUS_DMAMAP_COHERENT)
return;
if (len >= mips_cache_info.mci_pdcache_size) {
mips_dcache_wbinv_all();
return;
}
for (i = 0; i < map->dm_nsegs && len != 0; i++) {
if (offset >= map->dm_segs[i].ds_len) {
offset -= map->dm_segs[i].ds_len;
continue;
}
minlen = len < map->dm_segs[i].ds_len - offset ?
len : map->dm_segs[i].ds_len - offset;
addr = map->dm_segs[i].ds_addr;
#ifdef BUS_DMA_DEBUG
printf("%s: flushing segment %d (%#jx..%#jx) ...", __func__, i,
(intmax_t)addr + offset,
(intmax_t)addr + offset + minlen - 1);
#endif
mips_dcache_inv_range(
MIPS_PHYS_TO_KSEG0(addr + offset), minlen);
#ifdef BUS_DMA_DEBUG
printf("\n");
#endif
offset = 0;
len -= minlen;
}
}
#endif
#if 0
#ifdef MIPS3
static void
_bus_dmamap_sync_r4k(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
bus_size_t len, int ops)
{
bus_size_t minlen;
bus_addr_t addr;
int i, useindex;
if ((ops & (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE)) != 0 &&
(ops & (BUS_DMASYNC_POSTREAD|BUS_DMASYNC_POSTWRITE)) != 0)
panic("_bus_dmamap_sync_r4k: mix PRE and POST");
#ifdef DIAGNOSTIC
if (offset >= map->dm_mapsize)
panic("%s: bad offset %ju (map size is %ju)", __func__,
(uintmax_t)offset, (uintmax_t)map->dm_mapsize);
if (len == 0 || (offset + len) > map->dm_mapsize)
panic("%s: bad length", __func__);
#endif
wbflush();
ops &= (BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE);
if (ops == 0)
return;
if (map->_dm_flags & _BUS_DMAMAP_COHERENT)
return;
if (__predict_true(VMSPACE_IS_KERNEL_P(map->_dm_vmspace) ||
map->_dm_vmspace == curproc->p_vmspace))
useindex = 0;
else
useindex = 1;
for (i = 0; i < map->dm_nsegs && len != 0; i++) {
if (offset >= map->dm_segs[i].ds_len) {
offset -= map->dm_segs[i].ds_len;
continue;
}
minlen = len < map->dm_segs[i].ds_len - offset ?
len : map->dm_segs[i].ds_len - offset;
addr = map->dm_segs[i]._ds_vaddr;
#ifdef BUS_DMA_DEBUG
printf("%s: flushing segment %d (%#jx..%#jx) ...",
__func__, i, (intmax_t)addr + offset,
(intmax_t)ddr + offset + minlen - 1);
#endif
if (__predict_false(useindex)) {
mips_dcache_wbinv_range_index(addr + offset, minlen);
#ifdef BUS_DMA_DEBUG
printf("\n");
#endif
offset = 0;
len -= minlen;
continue;
}
switch (ops) {
case BUS_DMASYNC_PREREAD|BUS_DMASYNC_PREWRITE:
mips_dcache_wbinv_range(addr + offset, minlen);
break;
case BUS_DMASYNC_PREREAD:
#if 1
mips_dcache_wbinv_range(addr + offset, minlen);
#else
mips_dcache_inv_range(addr + offset, minlen);
#endif
break;
case BUS_DMASYNC_PREWRITE:
mips_dcache_wb_range(addr + offset, minlen);
break;
}
#ifdef BUS_DMA_DEBUG
printf("\n");
#endif
offset = 0;
len -= minlen;
}
}
#endif
#endif
#define CHIP normal
#define CHIP_MEM
#define CHIP_W1_BUS_START(v) 0x00000000UL
#define CHIP_W1_BUS_END(v) 0xffffffffUL
#define CHIP_W1_SYS_START(v) 0x00000000UL
#define CHIP_W1_SYS_END(v) 0xffffffffUL
#include <mips/mips/bus_space_alignstride_chipdep.c>