#include <sys/cdefs.h>
__KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.70 2023/12/20 15:29:07 thorpej Exp $");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/endian.h>
#include <sys/bswap.h>
#include <sys/kernel.h>
#include <sys/device.h>
#include <sys/proc.h>
#include <sys/mbuf.h>
#define _MIPS_BUS_DMA_PRIVATE
#include <sys/bus.h>
#include <machine/cpu.h>
#include <machine/machtype.h>
#include <uvm/uvm_extern.h>
#include <mips/cpuregs.h>
#include <mips/locore.h>
#include <mips/cache.h>
#include <sgimips/mace/macereg.h>
#include "opt_sgimace.h"
struct mips_bus_dma_tag sgimips_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 *);
static struct mips_bus_space normal_mbst;
bus_space_tag_t normal_memt = NULL;
void
sgimips_bus_dma_init(void)
{
normal_bus_mem_init(&normal_mbst, NULL);
normal_memt = &normal_mbst;
#ifdef MIPS1
switch (mach_type) {
case MACH_SGI_IP6 | MACH_SGI_IP10:
case MACH_SGI_IP12:
sgimips_default_bus_dma_tag._dmamap_ops.dmamap_sync =
_bus_dmamap_sync_mips1;
break;
}
#endif
}
#if 0
u_int8_t
bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t o)
{
wbflush();
switch (t) {
case SGIMIPS_BUS_SPACE_NORMAL:
return *(volatile u_int8_t *)(vaddr_t)(h + o);
case SGIMIPS_BUS_SPACE_IP6_DPCLOCK:
return *(volatile u_int8_t *)(vaddr_t)(h + (o << 2));
case SGIMIPS_BUS_SPACE_HPC:
return *(volatile u_int8_t *)(vaddr_t)(h + (o << 2) + 3);
case SGIMIPS_BUS_SPACE_MEM:
case SGIMIPS_BUS_SPACE_IO:
return *(volatile u_int8_t *)(vaddr_t)(h + (o | 3) - (o & 3));
case SGIMIPS_BUS_SPACE_MACE:
return *(volatile u_int8_t *)(vaddr_t)(h + (o << 8) + 7);
default:
panic("no bus tag");
}
}
#endif
#ifdef MIPS1
void
_bus_dmamap_sync_mips1(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_mips1: mix PRE and POST");
#ifdef DIAGNOSTIC
if (offset >= map->dm_mapsize)
panic("_bus_dmamap_sync_mips1: bad offset %"PRIxPSIZE
" (map size is %"PRIxPSIZE")"
, offset, map->dm_mapsize);
if (len == 0 || (offset + len) > map->dm_mapsize)
panic("_bus_dmamap_sync_mips1: bad length");
#endif
if (ops & BUS_DMASYNC_PREWRITE) {
wbflush();
}
if ((ops & BUS_DMASYNC_PREREAD) == 0)
return;
if (map->_dm_flags & SGIMIPS_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("bus_dmamap_sync_mips1: flushing segment %d "
"(0x%"PRIxBUSADDR"..0x%"PRIxBUSADDR") ...", i,
addr + offset, 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
#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>