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