1/*	$NetBSD: sys_machdep.c,v 1.14 2007/12/31 13:38:51 ad Exp $	*/
2
3/*
4 * Copyright (c) 1982, 1986, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 * 3. Neither the name of the University nor the names of its contributors
16 *    may be used to endorse or promote products derived from this software
17 *    without specific prior written permission.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
20 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22 * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
23 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
25 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
27 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
28 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
29 * SUCH DAMAGE.
30 *
31 *	@(#)sys_machdep.c	8.2 (Berkeley) 1/13/94
32 */
33
34#include "opt_m68k_arch.h"
35
36#include <sys/cdefs.h>
37__KERNEL_RCSID(0, "$NetBSD");
38
39#include <sys/param.h>
40#include <sys/proc.h>
41#include <sys/mount.h>
42
43#include <uvm/uvm_extern.h>
44
45#include <sys/syscallargs.h>
46
47#include <machine/cpu.h>
48#include <m68k/cacheops.h>
49
50/* XXX should be in an include file somewhere */
51#define CC_PURGE	1
52#define CC_FLUSH	2
53#define CC_IPURGE	4
54#define CC_EXTPURGE	0x80000000
55/* XXX end should be */
56
57/*
58 * Note that what we do here on 040/060 for BSD is different than for HP-UX.
59 *
60 * In 'pux they either act on a line (len == 16), a page (len == PAGE_SIZE)
61 * or the whole cache (len == anything else).
62 *
63 * In BSD we attempt to be more optimal when acting on "odd" sizes.
64 * For lengths up to 1024 we do all affected lines, up to 2*PAGE_SIZE we
65 * do pages, above that we do the entire cache.
66 */
67/*ARGSUSED1*/
68int
69cachectl1(u_long req, vaddr_t addr, size_t len, struct proc *p)
70{
71	int error = 0;
72
73#if defined(M68040) || defined(M68060)
74	if (mmutype == MMU_68040) {
75		int inc = 0;
76		bool doall = false;
77		paddr_t pa = 0;
78		vaddr_t end = 0;
79
80		if (addr == 0 ||
81#if defined(M68060)
82		    (cputype == CPU_68040 && req & CC_IPURGE) ||
83#else
84		    (req & CC_IPURGE) ||
85#endif
86		    ((req & ~CC_EXTPURGE) != CC_PURGE && len > 2 * PAGE_SIZE))
87			doall = 1;
88
89		if (!doall) {
90			end = addr + len;
91			if (len <= 1024) {
92				addr = addr & ~0xf;
93				inc = 16;
94			} else {
95				addr = addr & ~PGOFSET;
96				inc = PAGE_SIZE;
97			}
98		}
99		do {
100			/*
101			 * Convert to physical address if needed.
102			 * If translation fails, we perform operation on
103			 * entire cache.
104			 */
105			if (!doall &&
106			    (pa == 0 || m68k_page_offset(addr) == 0)) {
107				if (pmap_extract(p->p_vmspace->vm_map.pmap,
108				    addr, &pa) == false)
109					doall = 1;
110			}
111			switch (req) {
112			case CC_EXTPURGE|CC_IPURGE:
113			case CC_IPURGE:
114				if (doall) {
115					DCFA();
116					ICPA();
117				} else if (inc == 16) {
118					DCFL(pa);
119					ICPL(pa);
120				} else if (inc == PAGE_SIZE) {
121					DCFP(pa);
122					ICPP(pa);
123				}
124				break;
125
126			case CC_EXTPURGE|CC_PURGE:
127			case CC_PURGE:
128				if (doall)
129					DCFA();	/* note: flush not purge */
130				else if (inc == 16)
131					DCPL(pa);
132				else if (inc == PAGE_SIZE)
133					DCPP(pa);
134				break;
135
136			case CC_EXTPURGE|CC_FLUSH:
137			case CC_FLUSH:
138				if (doall)
139					DCFA();
140				else if (inc == 16)
141					DCFL(pa);
142				else if (inc == PAGE_SIZE)
143					DCFP(pa);
144				break;
145
146			default:
147				error = EINVAL;
148				break;
149			}
150			if (doall)
151				break;
152			pa += inc;
153			addr += inc;
154		} while (addr < end);
155		return (error);
156	}
157#endif
158	switch (req) {
159	case CC_EXTPURGE|CC_PURGE:
160	case CC_EXTPURGE|CC_FLUSH:
161#if defined(CACHE_HAVE_PAC)
162		if (ectype == EC_PHYS)
163			PCIA();
164		/* fall into... */
165#endif
166	case CC_PURGE:
167	case CC_FLUSH:
168		DCIU();
169		break;
170	case CC_EXTPURGE|CC_IPURGE:
171#if defined(CACHE_HAVE_PAC)
172		if (ectype == EC_PHYS)
173			PCIA();
174		else
175#endif
176		DCIU();
177		/* fall into... */
178	case CC_IPURGE:
179		ICIA();
180		break;
181	default:
182		error = EINVAL;
183		break;
184	}
185	return error;
186}
187
188int
189sys_sysarch(struct lwp *l, const struct sys_sysarch_args *uap, register_t *retval)
190{
191
192	return ENOSYS;
193}
194
195#if defined(amiga) || defined(x68k)
196
197/*
198 * DMA cache control
199 */
200
201/*ARGSUSED1*/
202int
203dma_cachectl(void *addr, int len)
204{
205#if defined(M68040) || defined(M68060)
206	int inc = 0;
207	int pa = 0;
208	void *end;
209
210	if (mmutype != MMU_68040) {
211		return 0;
212	}
213
214	end = (char*)addr + len;
215	if (len <= 1024) {
216		addr = (void *)((vaddr_t)addr & ~0xf);
217		inc = 16;
218	} else {
219		addr = (void *)((vaddr_t)addr & ~PGOFSET);
220		inc = PAGE_SIZE;
221	}
222	do {
223		/*
224		 * Convert to physical address.
225		 */
226		if (pa == 0 || ((vaddr_t)addr & PGOFSET) == 0) {
227			pa = kvtop(addr);
228		}
229		if (inc == 16) {
230			DCFL(pa);
231			ICPL(pa);
232		} else {
233			DCFP(pa);
234			ICPP(pa);
235		}
236		pa += inc;
237		addr = (char*)addr + inc;
238	} while (addr < end);
239#endif	/* defined(M68040) || defined(M68060) */
240	return 0;
241}
242#endif	/* defined(amiga) || defined(x68k) */
243