Home | History | Annotate | Line # | Download | only in atari
      1 /*	$NetBSD: bus.c,v 1.69 2023/12/07 16:56:09 thorpej Exp $	*/
      2 
      3 /*-
      4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
      5  * All rights reserved.
      6  *
      7  * This code is derived from software contributed to The NetBSD Foundation
      8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
      9  * NASA Ames Research Center and by Chris G. Demetriou.
     10  *
     11  * Redistribution and use in source and binary forms, with or without
     12  * modification, are permitted provided that the following conditions
     13  * are met:
     14  * 1. Redistributions of source code must retain the above copyright
     15  *    notice, this list of conditions and the following disclaimer.
     16  * 2. Redistributions in binary form must reproduce the above copyright
     17  *    notice, this list of conditions and the following disclaimer in the
     18  *    documentation and/or other materials provided with the distribution.
     19  *
     20  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
     21  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
     22  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     23  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
     24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
     26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
     27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
     28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
     29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
     30  * POSSIBILITY OF SUCH DAMAGE.
     31  */
     32 
     33 #include "opt_m68k_arch.h"
     34 
     35 #include <sys/cdefs.h>
     36 __KERNEL_RCSID(0, "$NetBSD: bus.c,v 1.69 2023/12/07 16:56:09 thorpej Exp $");
     37 
     38 #include <sys/param.h>
     39 #include <sys/systm.h>
     40 #include <sys/extent.h>
     41 #include <sys/kmem.h>
     42 #include <sys/mbuf.h>
     43 #include <sys/proc.h>
     44 #include <sys/vmem_impl.h>
     45 
     46 #include <uvm/uvm.h>
     47 
     48 #include <machine/cpu.h>
     49 #include <m68k/cacheops.h>
     50 #define	_ATARI_BUS_DMA_PRIVATE
     51 #include <sys/bus.h>
     52 
     53 /*
     54  * Vmem arena to manage all memory space, including I/O ranges.  Allocate
     55  * storage for 16 regions in each, initially.
     56  *
     57  * This means that the fixed static storage is only used for registrating
     58  * the found memory regions and the bus-mapping of the console.
     59  */
     60 #define	IOMEM_BTAG_COUNT	VMEM_EST_BTCOUNT(1, 16)
     61 static struct vmem iomem_arena_store;
     62 static struct vmem_btag iomem_btag_store[IOMEM_BTAG_COUNT];
     63 static vmem_t *iomem_arena;
     64 
     65 static int  _bus_dmamap_load_buffer(bus_dma_tag_t tag, bus_dmamap_t,
     66 		void *, bus_size_t, struct vmspace *, int, paddr_t *,
     67 		int *, int);
     68 static int  bus_mem_add_mapping(bus_space_tag_t t, bus_addr_t bpa,
     69 		bus_size_t size, int flags, bus_space_handle_t *bsph);
     70 
     71 extern paddr_t avail_end;
     72 
     73 /*
     74  * We need these for the early memory allocator. The idea is this:
     75  * Allocate VA-space through ptextra (atari_init.c:startc()). When
     76  * The VA & size of this space are known, call bootm_init().
     77  * Until the VM-system is up, bus_mem_add_mapping() allocates its virtual
     78  * addresses from this extent-map.
     79  *
     80  * This allows for the console code to use the bus_space interface at a
     81  * very early stage of the system configuration.
     82  */
     83 static pt_entry_t	*bootm_ptep;
     84 static vaddr_t		 bootm_start;
     85 static vaddr_t		 bootm_end;		/* inclusive */
     86 #define	BOOTM_BTAG_COUNT	VMEM_EST_BTCOUNT(1, 32)
     87 static struct vmem	 bootm_arena_store;
     88 static struct vmem_btag	 bootm_btag_store[BOOTM_BTAG_COUNT];
     89 static vmem_t *		 bootm_arena;
     90 
     91 static vaddr_t	bootm_alloc(paddr_t pa, u_long size, int flags);
     92 static int	bootm_free(vaddr_t va, u_long size);
     93 
     94 void
     95 bootm_init(vaddr_t va, void *ptep, vsize_t size)
     96 {
     97 
     98 	bootm_start = va;
     99 	bootm_end = va + size - 1;
    100 	bootm_ptep = (pt_entry_t *)ptep;
    101 
    102 	bootm_arena = vmem_init(&bootm_arena_store,
    103 				"bootmem",		/* name */
    104 				0,			/* addr */
    105 				0,			/* size */
    106 				PAGE_SIZE,		/* quantum */
    107 				NULL,			/* importfn */
    108 				NULL,			/* releasefn */
    109 				NULL,			/* source */
    110 				0,			/* qcache_max */
    111 				VM_NOSLEEP | VM_PRIVTAGS,
    112 				IPL_NONE);
    113 
    114 	vmem_add_bts(bootm_arena, bootm_btag_store, BOOTM_BTAG_COUNT);
    115 	vmem_add(bootm_arena, va, size, VM_NOSLEEP);
    116 }
    117 
    118 vaddr_t
    119 bootm_alloc(paddr_t pa, u_long size, int flags)
    120 {
    121 	pt_entry_t	*pg, *epg;
    122 	pt_entry_t	pg_proto;
    123 	vmem_addr_t	rva;
    124 	vaddr_t		va;
    125 
    126 	if (vmem_alloc(bootm_arena, size, VM_NOSLEEP, &rva) != 0) {
    127 		printf("bootm_alloc fails! Not enough fixed boundary tags?\n");
    128 		printf("Requested extent: pa=%lx, size=%lx\n",
    129 						(u_long)pa, size);
    130 		return 0;
    131 	}
    132 
    133 	pg  = &bootm_ptep[btoc(rva - bootm_start)];
    134 	epg = &pg[btoc(size)];
    135 	va  = rva;
    136 	pg_proto = pa | PG_RW | PG_V;
    137 	if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0)
    138 		pg_proto |= PG_CI;
    139 	while (pg < epg) {
    140 		*pg++     = pg_proto;
    141 		pg_proto += PAGE_SIZE;
    142 #if defined(M68040) || defined(M68060)
    143 		if (mmutype == MMU_68040) {
    144 			DCFP(pa);
    145 			pa += PAGE_SIZE;
    146 		}
    147 #endif
    148 		TBIS(va);
    149 		va += PAGE_SIZE;
    150 	}
    151 	return rva;
    152 }
    153 
    154 int
    155 bootm_free(vaddr_t va, u_long size)
    156 {
    157 
    158 	if ((va < bootm_start) || ((va + size - 1) > bootm_end))
    159 		return 0; /* Not for us! */
    160 	vmem_free(bootm_arena, va, size);
    161 	return 1;
    162 }
    163 
    164 void
    165 atari_bus_space_arena_init(paddr_t startpa, paddr_t endpa)
    166 {
    167 	vmem_size_t size;
    168 
    169 	/*
    170 	 * Initialize the I/O mem vmem arena.
    171 	 *
    172 	 * Note: we don't have to check the return value since
    173 	 * creation of a fixed extent map will never fail (since
    174 	 * descriptor storage has already been allocated).
    175 	 *
    176 	 * N.B. The iomem arena manages _all_ physical addresses
    177 	 * on the machine.  When the amount of RAM is found, all
    178 	 * extents of RAM are allocated from the map.
    179 	 */
    180 
    181 	iomem_arena = vmem_init(&iomem_arena_store,
    182 				"iomem",		/* name */
    183 				0,			/* addr */
    184 				0,			/* size */
    185 				1,			/* quantum */
    186 				NULL,			/* importfn */
    187 				NULL,			/* releasefn */
    188 				NULL,			/* source */
    189 				0,			/* qcache_max */
    190 				VM_NOSLEEP | VM_PRIVTAGS,
    191 				IPL_NONE);
    192 
    193 	vmem_add_bts(iomem_arena, iomem_btag_store, IOMEM_BTAG_COUNT);
    194 
    195 	/* XXX kern/57748 */
    196 	size = (vmem_size_t)(endpa - startpa) + 1;
    197 	if (size == 0) {
    198 		size--;
    199 	}
    200 	vmem_add(iomem_arena, startpa, size, VM_NOSLEEP);
    201 }
    202 
    203 int
    204 atari_bus_space_alloc_physmem(paddr_t startpa, paddr_t endpa)
    205 {
    206 
    207 	return vmem_xalloc_addr(iomem_arena, startpa, endpa - startpa,
    208 	    VM_NOSLEEP);
    209 }
    210 
    211 int
    212 bus_space_map(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size, int flags,
    213     bus_space_handle_t *mhp)
    214 {
    215 	int	error;
    216 
    217 	/*
    218 	 * Before we go any further, let's make sure that this
    219 	 * region is available.
    220 	 */
    221 	error = vmem_xalloc_addr(iomem_arena, bpa + t->base, size,
    222 	    VM_NOSLEEP);
    223 	if (error != 0)
    224 		return error;
    225 
    226 	error = bus_mem_add_mapping(t, bpa, size, flags, mhp);
    227 	if (error != 0) {
    228 		vmem_xfree(iomem_arena, bpa + t->base, size);
    229 	}
    230 	return error;
    231 }
    232 
    233 int
    234 bus_space_alloc(bus_space_tag_t t, bus_addr_t rstart, bus_addr_t rend,
    235     bus_size_t size, bus_size_t alignment, bus_size_t boundary, int flags,
    236     bus_addr_t *bpap, bus_space_handle_t *bshp)
    237 {
    238 	vmem_addr_t bpa;
    239 	int error;
    240 
    241 	/*
    242 	 * Do the requested allocation.
    243 	 */
    244 	error = vmem_xalloc(iomem_arena, size,
    245 			    alignment,		/* align */
    246 			    0,			/* phase */
    247 			    boundary,		/* boundary */
    248 			    rstart + t->base,	/* minaddr */
    249 			    rend + t->base,	/* maxaddr */
    250 			    VM_BESTFIT | VM_NOSLEEP,
    251 			    &bpa);
    252 	if (error != 0)
    253 		return error;
    254 
    255 	/*
    256 	 * Map the bus physical address to a kernel virtual address.
    257 	 */
    258 	error = bus_mem_add_mapping(t, bpa, size, flags, bshp);
    259 	if (error != 0) {
    260 		vmem_xfree(iomem_arena, bpa, size);
    261 	}
    262 
    263 	*bpap = bpa;
    264 
    265 	return error;
    266 }
    267 
    268 static int
    269 bus_mem_add_mapping(bus_space_tag_t t, bus_addr_t bpa, bus_size_t size,
    270     int flags, bus_space_handle_t *bshp)
    271 {
    272 	vaddr_t	va;
    273 	paddr_t	pa, endpa;
    274 
    275 	pa    = m68k_trunc_page(bpa + t->base);
    276 	endpa = m68k_round_page((bpa + t->base + size) - 1);
    277 
    278 #ifdef DIAGNOSTIC
    279 	if (endpa <= pa)
    280 		panic("%s: overflow", __func__);
    281 #endif
    282 
    283 	if (kernel_map == NULL) {
    284 		/*
    285 		 * The VM-system is not yet operational, allocate from
    286 		 * a special pool.
    287 		 */
    288 		va = bootm_alloc(pa, endpa - pa, flags);
    289 		if (va == 0)
    290 			return ENOMEM;
    291 		*bshp = va + (bpa & PGOFSET);
    292 		return 0;
    293 	}
    294 
    295 	va = uvm_km_alloc(kernel_map, endpa - pa, 0,
    296 	    UVM_KMF_VAONLY | UVM_KMF_NOWAIT);
    297 	if (va == 0)
    298 		return ENOMEM;
    299 
    300 	*bshp = va + (bpa & PGOFSET);
    301 
    302 	for (; pa < endpa; pa += PAGE_SIZE, va += PAGE_SIZE) {
    303 		pt_entry_t *ptep, npte;
    304 
    305 		pmap_enter(pmap_kernel(), (vaddr_t)va, pa,
    306 		    VM_PROT_READ|VM_PROT_WRITE, VM_PROT_READ|VM_PROT_WRITE);
    307 
    308 		ptep = kvtopte(va);
    309 		npte = *ptep & ~PG_CMASK;
    310 
    311 		if ((flags & BUS_SPACE_MAP_CACHEABLE) == 0)
    312 			npte |= PG_CI;
    313 		else if (mmutype == MMU_68040)
    314 			npte |= PG_CCB;
    315 
    316 		*ptep = npte;
    317 	}
    318 	pmap_update(pmap_kernel());
    319 	TBIAS();
    320 	return 0;
    321 }
    322 
    323 void
    324 bus_space_unmap(bus_space_tag_t t, bus_space_handle_t bsh, bus_size_t size)
    325 {
    326 	vaddr_t	va, endva;
    327 	paddr_t bpa;
    328 
    329 	va = m68k_trunc_page(bsh);
    330 	endva = m68k_round_page(((char *)bsh + size) - 1);
    331 #ifdef DIAGNOSTIC
    332 	if (endva < va)
    333 		panic("%s: overflow", __func__);
    334 #endif
    335 
    336 	(void)pmap_extract(pmap_kernel(), va, &bpa);
    337 	bpa += ((paddr_t)bsh & PGOFSET);
    338 
    339 	/*
    340 	 * Free the kernel virtual mapping.
    341 	 */
    342 	if (!bootm_free(va, endva - va)) {
    343 		pmap_remove(pmap_kernel(), va, endva);
    344 		pmap_update(pmap_kernel());
    345 		uvm_km_free(kernel_map, va, endva - va, UVM_KMF_VAONLY);
    346 	}
    347 
    348 	/*
    349 	 * Mark as free in the extent map.
    350 	 */
    351 	vmem_xfree(iomem_arena, bpa, size);
    352 }
    353 
    354 /*
    355  * Get a new handle for a subregion of an already-mapped area of bus space.
    356  */
    357 int
    358 bus_space_subregion(bus_space_tag_t t, bus_space_handle_t memh,
    359     bus_size_t off, bus_size_t sz, bus_space_handle_t *mhp)
    360 {
    361 
    362 	*mhp = memh + off;
    363 	return 0;
    364 }
    365 
    366 paddr_t
    367 bus_space_mmap(bus_space_tag_t t, bus_addr_t addr, off_t off, int prot,
    368     int flags)
    369 {
    370 
    371 	/*
    372 	 * "addr" is the base address of the device we're mapping.
    373 	 * "off" is the offset into that device.
    374 	 *
    375 	 * Note we are called for each "page" in the device that
    376 	 * the upper layers want to map.
    377 	 */
    378 	return m68k_btop(addr + off);
    379 }
    380 
    381 static size_t
    382 _bus_dmamap_mapsize(int const nsegments)
    383 {
    384 
    385 	KASSERT(nsegments > 0);
    386 	return sizeof(struct atari_bus_dmamap) +
    387 	    (sizeof(bus_dma_segment_t) * (nsegments - 1));
    388 }
    389 
    390 /*
    391  * Common function for DMA map creation.  May be called by bus-specific
    392  * DMA map creation functions.
    393  */
    394 int
    395 _bus_dmamap_create(bus_dma_tag_t t, bus_size_t size, int nsegments,
    396     bus_size_t maxsegsz, bus_size_t boundary, int flags, bus_dmamap_t *dmamp)
    397 {
    398 	struct atari_bus_dmamap *map;
    399 	void *mapstore;
    400 
    401 	/*
    402 	 * Allocate and initialize the DMA map.  The end of the map
    403 	 * is a variable-sized array of segments, so we allocate enough
    404 	 * room for them in one shot.
    405 	 *
    406 	 * Note we don't preserve the WAITOK or NOWAIT flags.  Preservation
    407 	 * of ALLOCNOW notifies others that we've reserved these resources,
    408 	 * and they are not to be freed.
    409 	 *
    410 	 * The bus_dmamap_t includes one bus_dma_segment_t, hence
    411 	 * the (nsegments - 1).
    412 	 */
    413 	if ((mapstore = kmem_zalloc(_bus_dmamap_mapsize(nsegments),
    414 	    (flags & BUS_DMA_NOWAIT) != 0 ? KM_NOSLEEP : KM_SLEEP)) == NULL)
    415 		return ENOMEM;
    416 
    417 	map = (struct atari_bus_dmamap *)mapstore;
    418 	map->_dm_size = size;
    419 	map->_dm_segcnt = nsegments;
    420 	map->_dm_maxmaxsegsz = maxsegsz;
    421 	map->_dm_boundary = boundary;
    422 	map->_dm_flags = flags & ~(BUS_DMA_WAITOK|BUS_DMA_NOWAIT);
    423 	map->dm_maxsegsz = maxsegsz;
    424 	map->dm_mapsize = 0;		/* no valid mappings */
    425 	map->dm_nsegs = 0;
    426 
    427 	*dmamp = map;
    428 	return 0;
    429 }
    430 
    431 /*
    432  * Common function for DMA map destruction.  May be called by bus-specific
    433  * DMA map destruction functions.
    434  */
    435 void
    436 _bus_dmamap_destroy(bus_dma_tag_t t, bus_dmamap_t map)
    437 {
    438 
    439 	kmem_free(map, _bus_dmamap_mapsize(map->_dm_segcnt));
    440 }
    441 
    442 /*
    443  * Common function for loading a DMA map with a linear buffer.  May
    444  * be called by bus-specific DMA map load functions.
    445  */
    446 int
    447 _bus_dmamap_load(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    448     bus_size_t buflen, struct proc *p, int flags)
    449 {
    450 	paddr_t lastaddr;
    451 	int seg, error;
    452 	struct vmspace *vm;
    453 
    454 	/*
    455 	 * Make sure that on error condition we return "no valid mappings".
    456 	 */
    457 	map->dm_mapsize = 0;
    458 	map->dm_nsegs = 0;
    459 	KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
    460 
    461 	if (buflen > map->_dm_size)
    462 		return EINVAL;
    463 
    464 	if (p != NULL) {
    465 		vm = p->p_vmspace;
    466 	} else {
    467 		vm = vmspace_kernel();
    468 	}
    469 
    470 	seg = 0;
    471 	error = _bus_dmamap_load_buffer(t, map, buf, buflen, vm, flags,
    472 	    &lastaddr, &seg, 1);
    473 	if (error == 0) {
    474 		map->dm_mapsize = buflen;
    475 		map->dm_nsegs = seg + 1;
    476 	}
    477 	return error;
    478 }
    479 
    480 /*
    481  * Like _bus_dmamap_load(), but for mbufs.
    482  */
    483 int
    484 _bus_dmamap_load_mbuf(bus_dma_tag_t t, bus_dmamap_t map, struct mbuf *m0,
    485     int flags)
    486 {
    487 	paddr_t lastaddr;
    488 	int seg, error, first;
    489 	struct mbuf *m;
    490 
    491 	/*
    492 	 * Make sure that on error condition we return "no valid mappings."
    493 	 */
    494 	map->dm_mapsize = 0;
    495 	map->dm_nsegs = 0;
    496 	KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
    497 
    498 #ifdef DIAGNOSTIC
    499 	if ((m0->m_flags & M_PKTHDR) == 0)
    500 		panic("%s: no packet header", __func__);
    501 #endif
    502 
    503 	if (m0->m_pkthdr.len > map->_dm_size)
    504 		return EINVAL;
    505 
    506 	first = 1;
    507 	seg = 0;
    508 	error = 0;
    509 	for (m = m0; m != NULL && error == 0; m = m->m_next) {
    510 		if (m->m_len == 0)
    511 			continue;
    512 		error = _bus_dmamap_load_buffer(t, map, m->m_data, m->m_len,
    513 		    vmspace_kernel(), flags, &lastaddr, &seg, first);
    514 		first = 0;
    515 	}
    516 	if (error == 0) {
    517 		map->dm_mapsize = m0->m_pkthdr.len;
    518 		map->dm_nsegs = seg + 1;
    519 	}
    520 	return error;
    521 }
    522 
    523 /*
    524  * Like _bus_dmamap_load(), but for uios.
    525  */
    526 int
    527 _bus_dmamap_load_uio(bus_dma_tag_t t, bus_dmamap_t map, struct uio *uio,
    528     int flags)
    529 {
    530 	paddr_t lastaddr;
    531 	int seg, i, error, first;
    532 	bus_size_t minlen, resid;
    533 	struct iovec *iov;
    534 	void *addr;
    535 
    536 	/*
    537 	 * Make sure that on error condition we return "no valid mappings."
    538 	 */
    539 	map->dm_mapsize = 0;
    540 	map->dm_nsegs = 0;
    541 	KASSERT(map->dm_maxsegsz <= map->_dm_maxmaxsegsz);
    542 
    543 	resid = uio->uio_resid;
    544 	iov = uio->uio_iov;
    545 
    546 	first = 1;
    547 	seg = 0;
    548 	error = 0;
    549 	for (i = 0; i < uio->uio_iovcnt && resid != 0 && error == 0; i++) {
    550 		/*
    551 		 * Now at the first iovec to load.  Load each iovec
    552 		 * until we have exhausted the residual count.
    553 		 */
    554 		minlen = resid < iov[i].iov_len ? resid : iov[i].iov_len;
    555 		addr = (void *)iov[i].iov_base;
    556 
    557 		error = _bus_dmamap_load_buffer(t, map, addr, minlen,
    558 		    uio->uio_vmspace, flags, &lastaddr, &seg, first);
    559 		first = 0;
    560 
    561 		resid -= minlen;
    562 	}
    563 	if (error == 0) {
    564 		map->dm_mapsize = uio->uio_resid;
    565 		map->dm_nsegs = seg + 1;
    566 	}
    567 	return error;
    568 }
    569 
    570 /*
    571  * Like _bus_dmamap_load(), but for raw memory allocated with
    572  * bus_dmamem_alloc().
    573  */
    574 int
    575 _bus_dmamap_load_raw(bus_dma_tag_t t, bus_dmamap_t map,
    576     bus_dma_segment_t *segs, int nsegs, bus_size_t size, int flags)
    577 {
    578 
    579 	panic("%s: not implemented", __func__);
    580 }
    581 
    582 /*
    583  * Common function for unloading a DMA map.  May be called by
    584  * bus-specific DMA map unload functions.
    585  */
    586 void
    587 _bus_dmamap_unload(bus_dma_tag_t t, bus_dmamap_t map)
    588 {
    589 
    590 	/*
    591 	 * No resources to free; just mark the mappings as
    592 	 * invalid.
    593 	 */
    594 	map->dm_maxsegsz = map->_dm_maxmaxsegsz;
    595 	map->dm_mapsize = 0;
    596 	map->dm_nsegs = 0;
    597 }
    598 
    599 /*
    600  * Common function for DMA map synchronization.  May be called
    601  * by bus-specific DMA map synchronization functions.
    602  */
    603 void
    604 _bus_dmamap_sync(bus_dma_tag_t t, bus_dmamap_t map, bus_addr_t offset,
    605     bus_size_t len, int ops)
    606 {
    607 #if defined(M68040) || defined(M68060)
    608 	bus_addr_t p, e, ps, pe;
    609 	bus_size_t seglen;
    610 	bus_dma_segment_t *seg;
    611 	int i;
    612 #endif
    613 
    614 #if defined(M68020) || defined(M68030)
    615 #if defined(M68040) || defined(M68060)
    616 	if (cputype == CPU_68020 || cputype == CPU_68030)
    617 #endif
    618 		/* assume no L2 physical cache */
    619 		return;
    620 #endif
    621 
    622 #if defined(M68040) || defined(M68060)
    623 	/* If the whole DMA map is uncached, do nothing. */
    624 	if ((map->_dm_flags & BUS_DMA_COHERENT) != 0)
    625 		return;
    626 
    627 	/* Short-circuit for unsupported `ops' */
    628 	if ((ops & (BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE)) == 0)
    629 		return;
    630 
    631 	/*
    632 	 * flush/purge the cache.
    633 	 */
    634 	for (i = 0; i < map->dm_nsegs && len != 0; i++) {
    635 		seg = &map->dm_segs[i];
    636 		if (seg->ds_len <= offset) {
    637 			/* Segment irrelevant - before requested offset */
    638 			offset -= seg->ds_len;
    639 			continue;
    640 		}
    641 
    642 		/*
    643 		 * Now at the first segment to sync; nail
    644 		 * each segment until we have exhausted the
    645 		 * length.
    646 		 */
    647 		seglen = seg->ds_len - offset;
    648 		if (seglen > len)
    649 			seglen = len;
    650 
    651 		ps = seg->ds_addr + offset;
    652 		pe = ps + seglen;
    653 
    654 		if ((ops & BUS_DMASYNC_PREWRITE) != 0) {
    655 			p = ps & ~CACHELINE_MASK;
    656 			e = (pe + CACHELINE_MASK) & ~CACHELINE_MASK;
    657 
    658 			/* flush cacheline */
    659 			while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) {
    660 				DCFL(p);
    661 				p += CACHELINE_SIZE;
    662 			}
    663 
    664 			/* flush cachelines per 128bytes */
    665 			while ((p < e) && (p & PAGE_MASK) != 0) {
    666 				DCFL(p);
    667 				p += CACHELINE_SIZE;
    668 				DCFL(p);
    669 				p += CACHELINE_SIZE;
    670 				DCFL(p);
    671 				p += CACHELINE_SIZE;
    672 				DCFL(p);
    673 				p += CACHELINE_SIZE;
    674 				DCFL(p);
    675 				p += CACHELINE_SIZE;
    676 				DCFL(p);
    677 				p += CACHELINE_SIZE;
    678 				DCFL(p);
    679 				p += CACHELINE_SIZE;
    680 				DCFL(p);
    681 				p += CACHELINE_SIZE;
    682 			}
    683 
    684 			/* flush page */
    685 			while (p + PAGE_SIZE <= e) {
    686 				DCFP(p);
    687 				p += PAGE_SIZE;
    688 			}
    689 
    690 			/* flush cachelines per 128bytes */
    691 			while (p + CACHELINE_SIZE * 8 <= e) {
    692 				DCFL(p);
    693 				p += CACHELINE_SIZE;
    694 				DCFL(p);
    695 				p += CACHELINE_SIZE;
    696 				DCFL(p);
    697 				p += CACHELINE_SIZE;
    698 				DCFL(p);
    699 				p += CACHELINE_SIZE;
    700 				DCFL(p);
    701 				p += CACHELINE_SIZE;
    702 				DCFL(p);
    703 				p += CACHELINE_SIZE;
    704 				DCFL(p);
    705 				p += CACHELINE_SIZE;
    706 				DCFL(p);
    707 				p += CACHELINE_SIZE;
    708 			}
    709 
    710 			/* flush cacheline */
    711 			while (p < e) {
    712 				DCFL(p);
    713 				p += CACHELINE_SIZE;
    714 			}
    715 		}
    716 
    717 		/*
    718 		 * Normally, the `PREREAD' flag instructs us to purge the
    719 		 * cache for the specified offset and length. However, if
    720 		 * the offset/length is not aligned to a cacheline boundary,
    721 		 * we may end up purging some legitimate data from the
    722 		 * start/end of the cache. In such a case, *flush* the
    723 		 * cachelines at the start and end of the required region.
    724 		 */
    725 		else if ((ops & BUS_DMASYNC_PREREAD) != 0) {
    726 			/* flush cacheline on start boundary */
    727 			if ((ps & CACHELINE_MASK) != 0) {
    728 				DCFL(ps & ~CACHELINE_MASK);
    729 			}
    730 
    731 			p = (ps + CACHELINE_MASK) & ~CACHELINE_MASK;
    732 			e = pe & ~CACHELINE_MASK;
    733 
    734 			/* purge cacheline */
    735 			while ((p < e) && (p & (CACHELINE_SIZE * 8 - 1)) != 0) {
    736 				DCPL(p);
    737 				p += CACHELINE_SIZE;
    738 			}
    739 
    740 			/* purge cachelines per 128bytes */
    741 			while ((p < e) && (p & PAGE_MASK) != 0) {
    742 				DCPL(p);
    743 				p += CACHELINE_SIZE;
    744 				DCPL(p);
    745 				p += CACHELINE_SIZE;
    746 				DCPL(p);
    747 				p += CACHELINE_SIZE;
    748 				DCPL(p);
    749 				p += CACHELINE_SIZE;
    750 				DCPL(p);
    751 				p += CACHELINE_SIZE;
    752 				DCPL(p);
    753 				p += CACHELINE_SIZE;
    754 				DCPL(p);
    755 				p += CACHELINE_SIZE;
    756 				DCPL(p);
    757 				p += CACHELINE_SIZE;
    758 			}
    759 
    760 			/* purge page */
    761 			while (p + PAGE_SIZE <= e) {
    762 				DCPP(p);
    763 				p += PAGE_SIZE;
    764 			}
    765 
    766 			/* purge cachelines per 128bytes */
    767 			while (p + CACHELINE_SIZE * 8 <= e) {
    768 				DCPL(p);
    769 				p += CACHELINE_SIZE;
    770 				DCPL(p);
    771 				p += CACHELINE_SIZE;
    772 				DCPL(p);
    773 				p += CACHELINE_SIZE;
    774 				DCPL(p);
    775 				p += CACHELINE_SIZE;
    776 				DCPL(p);
    777 				p += CACHELINE_SIZE;
    778 				DCPL(p);
    779 				p += CACHELINE_SIZE;
    780 				DCPL(p);
    781 				p += CACHELINE_SIZE;
    782 				DCPL(p);
    783 				p += CACHELINE_SIZE;
    784 			}
    785 
    786 			/* purge cacheline */
    787 			while (p < e) {
    788 				DCPL(p);
    789 				p += CACHELINE_SIZE;
    790 			}
    791 
    792 			/* flush cacheline on end boundary */
    793 			if (p < pe) {
    794 				DCFL(p);
    795 			}
    796 		}
    797 		offset = 0;
    798 		len -= seglen;
    799 	}
    800 #endif	/* defined(M68040) || defined(M68060) */
    801 }
    802 
    803 /*
    804  * Common function for DMA-safe memory allocation.  May be called
    805  * by bus-specific DMA memory allocation functions.
    806  */
    807 int
    808 bus_dmamem_alloc(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
    809     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
    810     int flags)
    811 {
    812 
    813 	return bus_dmamem_alloc_range(t, size, alignment, boundary,
    814 	    segs, nsegs, rsegs, flags, 0, trunc_page(avail_end));
    815 }
    816 
    817 /*
    818  * Common function for freeing DMA-safe memory.  May be called by
    819  * bus-specific DMA memory free functions.
    820  */
    821 void
    822 bus_dmamem_free(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs)
    823 {
    824 	struct vm_page *m;
    825 	bus_addr_t addr, offset;
    826 	struct pglist mlist;
    827 	int curseg;
    828 
    829 	offset = t->_displacement;
    830 
    831 	/*
    832 	 * Build a list of pages to free back to the VM system.
    833 	 */
    834 	TAILQ_INIT(&mlist);
    835 	for (curseg = 0; curseg < nsegs; curseg++) {
    836 		for (addr = segs[curseg].ds_addr;
    837 		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
    838 		    addr += PAGE_SIZE) {
    839 			m = PHYS_TO_VM_PAGE(addr - offset);
    840 			TAILQ_INSERT_TAIL(&mlist, m, pageq.queue);
    841 		}
    842 	}
    843 
    844 	uvm_pglistfree(&mlist);
    845 }
    846 
    847 /*
    848  * Common function for mapping DMA-safe memory.  May be called by
    849  * bus-specific DMA memory map functions.
    850  */
    851 int
    852 bus_dmamem_map(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs,
    853     size_t size, void **kvap, int flags)
    854 {
    855 	vaddr_t va;
    856 	bus_addr_t addr, offset;
    857 	int curseg;
    858 	const uvm_flag_t kmflags =
    859 	    (flags & BUS_DMA_NOWAIT) != 0 ? UVM_KMF_NOWAIT : 0;
    860 
    861 	offset = t->_displacement;
    862 
    863 	size = round_page(size);
    864 
    865 	va = uvm_km_alloc(kernel_map, size, 0, UVM_KMF_VAONLY | kmflags);
    866 
    867 	if (va == 0)
    868 		return ENOMEM;
    869 
    870 	*kvap = (void *)va;
    871 
    872 	for (curseg = 0; curseg < nsegs; curseg++) {
    873 		for (addr = segs[curseg].ds_addr;
    874 		    addr < (segs[curseg].ds_addr + segs[curseg].ds_len);
    875 		    addr += PAGE_SIZE, va += PAGE_SIZE, size -= PAGE_SIZE) {
    876 			if (size == 0)
    877 				panic("%s: size botch", __func__);
    878 			pmap_enter(pmap_kernel(), va, addr - offset,
    879 			    VM_PROT_READ | VM_PROT_WRITE,
    880 			    VM_PROT_READ | VM_PROT_WRITE);
    881 		}
    882 	}
    883 	pmap_update(pmap_kernel());
    884 
    885 	return 0;
    886 }
    887 
    888 /*
    889  * Common function for unmapping DMA-safe memory.  May be called by
    890  * bus-specific DMA memory unmapping functions.
    891  */
    892 void
    893 bus_dmamem_unmap(bus_dma_tag_t t, void *kva, size_t size)
    894 {
    895 
    896 #ifdef DIAGNOSTIC
    897 	if ((vaddr_t)kva & PGOFSET)
    898 		panic("%s", __func__);
    899 #endif
    900 
    901 	size = round_page(size);
    902 
    903 	pmap_remove(pmap_kernel(), (vaddr_t)kva, (vaddr_t)kva + size);
    904 	pmap_update(pmap_kernel());
    905 	uvm_km_free(kernel_map, (vaddr_t)kva, size, UVM_KMF_VAONLY);
    906 }
    907 
    908 /*
    909  * Common function for mmap(2)'ing DMA-safe memory.  May be called by
    910  * bus-specific DMA mmap(2)'ing functions.
    911  */
    912 paddr_t
    913 bus_dmamem_mmap(bus_dma_tag_t t, bus_dma_segment_t *segs, int nsegs, off_t off,
    914     int prot, int flags)
    915 {
    916 	int i, offset;
    917 
    918 	offset = t->_displacement;
    919 
    920 	for (i = 0; i < nsegs; i++) {
    921 #ifdef DIAGNOSTIC
    922 		if ((off & PGOFSET) != 0)
    923 			panic("%s: offset unaligned", __func__);
    924 		if ((segs[i].ds_addr & PGOFSET) != 0)
    925 			panic("%s: segment unaligned", __func__);
    926 		if ((segs[i].ds_len & PGOFSET) != 0)
    927 			panic("%s: segment size not multiple of page size",
    928 			    __func__);
    929 #endif
    930 		if (off >= segs[i].ds_len) {
    931 			off -= segs[i].ds_len;
    932 			continue;
    933 		}
    934 
    935 		return m68k_btop((char *)segs[i].ds_addr - offset + off);
    936 	}
    937 
    938 	/* Page not found. */
    939 	return -1;
    940 }
    941 
    942 /**********************************************************************
    943  * DMA utility functions
    944  **********************************************************************/
    945 
    946 /*
    947  * Utility function to load a linear buffer.  lastaddrp holds state
    948  * between invocations (for multiple-buffer loads).  segp contains
    949  * the starting segment on entrance, and the ending segment on exit.
    950  * first indicates if this is the first invocation of this function.
    951  */
    952 static int
    953 _bus_dmamap_load_buffer(bus_dma_tag_t t, bus_dmamap_t map, void *buf,
    954     bus_size_t buflen, struct vmspace *vm, int flags, paddr_t *lastaddrp,
    955     int *segp, int first)
    956 {
    957 	bus_size_t sgsize;
    958 	bus_addr_t curaddr, lastaddr, offset, baddr, bmask;
    959 	vaddr_t vaddr = (vaddr_t)buf;
    960 	int seg;
    961 	pmap_t pmap;
    962 
    963 	offset = t->_displacement;
    964 
    965 	pmap = vm_map_pmap(&vm->vm_map);
    966 
    967 	lastaddr = *lastaddrp;
    968 	bmask = ~(map->_dm_boundary - 1);
    969 
    970 	for (seg = *segp; buflen > 0 ; ) {
    971 		/*
    972 		 * Get the physical address for this segment.
    973 		 */
    974 		(void)pmap_extract(pmap, vaddr, &curaddr);
    975 
    976 		/*
    977 		 * Compute the segment size, and adjust counts.
    978 		 */
    979 		sgsize = PAGE_SIZE - ((vaddr_t)vaddr & PGOFSET);
    980 		if (buflen < sgsize)
    981 			sgsize = buflen;
    982 
    983 		/*
    984 		 * Make sure we don't cross any boundaries.
    985 		 */
    986 		if (map->_dm_boundary > 0) {
    987 			baddr = (curaddr + map->_dm_boundary) & bmask;
    988 			if (sgsize > (baddr - curaddr))
    989 				sgsize = (baddr - curaddr);
    990 		}
    991 
    992 		/*
    993 		 * Insert chunk into a segment, coalescing with
    994 		 * previous segment if possible.
    995 		 */
    996 		if (first) {
    997 			map->dm_segs[seg].ds_addr = curaddr + offset;
    998 			map->dm_segs[seg].ds_len = sgsize;
    999 			first = 0;
   1000 		} else {
   1001 			if (curaddr == lastaddr &&
   1002 			    (map->dm_segs[seg].ds_len + sgsize) <=
   1003 			     map->dm_maxsegsz &&
   1004 			    (map->_dm_boundary == 0 ||
   1005 			     (map->dm_segs[seg].ds_addr & bmask) ==
   1006 			     (curaddr & bmask)))
   1007 				map->dm_segs[seg].ds_len += sgsize;
   1008 			else {
   1009 				if (++seg >= map->_dm_segcnt)
   1010 					break;
   1011 				map->dm_segs[seg].ds_addr = curaddr + offset;
   1012 				map->dm_segs[seg].ds_len = sgsize;
   1013 			}
   1014 		}
   1015 
   1016 		lastaddr = curaddr + sgsize;
   1017 		vaddr += sgsize;
   1018 		buflen -= sgsize;
   1019 	}
   1020 
   1021 	*segp = seg;
   1022 	*lastaddrp = lastaddr;
   1023 
   1024 	/*
   1025 	 * Did we fit?
   1026 	 */
   1027 	if (buflen != 0)
   1028 		return EFBIG;		/* XXX better return value here? */
   1029 	return 0;
   1030 }
   1031 
   1032 /*
   1033  * Allocate physical memory from the given physical address range.
   1034  * Called by DMA-safe memory allocation methods.
   1035  */
   1036 int
   1037 bus_dmamem_alloc_range(bus_dma_tag_t t, bus_size_t size, bus_size_t alignment,
   1038     bus_size_t boundary, bus_dma_segment_t *segs, int nsegs, int *rsegs,
   1039     int flags, paddr_t low, paddr_t high)
   1040 {
   1041 	paddr_t curaddr, lastaddr;
   1042 	bus_addr_t offset;
   1043 	struct vm_page *m;
   1044 	struct pglist mlist;
   1045 	int curseg, error;
   1046 
   1047 	offset = t->_displacement;
   1048 
   1049 	/* Always round the size. */
   1050 	size = round_page(size);
   1051 
   1052 	/*
   1053 	 * Allocate pages from the VM system.
   1054 	 */
   1055 	error = uvm_pglistalloc(size, low, high, alignment, boundary,
   1056 	    &mlist, nsegs, (flags & BUS_DMA_NOWAIT) == 0);
   1057 	if (error != 0)
   1058 		return error;
   1059 
   1060 	/*
   1061 	 * Compute the location, size, and number of segments actually
   1062 	 * returned by the VM code.
   1063 	 */
   1064 	m = TAILQ_FIRST(&mlist);
   1065 	curseg = 0;
   1066 	lastaddr = VM_PAGE_TO_PHYS(m);
   1067 	segs[curseg].ds_addr = lastaddr + offset;
   1068 	segs[curseg].ds_len = PAGE_SIZE;
   1069 	m = TAILQ_NEXT(m, pageq.queue);
   1070 
   1071 	for (; m != NULL; m = TAILQ_NEXT(m, pageq.queue)) {
   1072 		curaddr = VM_PAGE_TO_PHYS(m);
   1073 #ifdef DIAGNOSTIC
   1074 		if (curaddr < low || curaddr >= high) {
   1075 			printf("uvm_pglistalloc returned non-sensical"
   1076 			    " address 0x%lx\n", curaddr);
   1077 			panic("%s", __func__);
   1078 		}
   1079 #endif
   1080 		if (curaddr == (lastaddr + PAGE_SIZE))
   1081 			segs[curseg].ds_len += PAGE_SIZE;
   1082 		else {
   1083 			curseg++;
   1084 			segs[curseg].ds_addr = curaddr + offset;
   1085 			segs[curseg].ds_len = PAGE_SIZE;
   1086 		}
   1087 		lastaddr = curaddr;
   1088 	}
   1089 
   1090 	*rsegs = curseg + 1;
   1091 
   1092 	return 0;
   1093 }
   1094