sys_machdep.c revision 1.10
1/*	$NetBSD: sys_machdep.c,v 1.10 2007/02/22 17:09:44 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. 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 <sys/cdefs.h>
35__KERNEL_RCSID(0, "$NetBSD");
36
37#include "opt_compat_hpux.h"
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#ifdef COMPAT_HPUX
80		extern struct emul emul_hpux;
81
82		if ((p->p_emul == &emul_hpux) &&
83		    len != 16 && len != PAGE_SIZE)
84			doall = 1;
85#endif
86
87		if (addr == 0 ||
88#if defined(M68060)
89		    (cputype == CPU_68040 && req & CC_IPURGE) ||
90#else
91		    (req & CC_IPURGE) ||
92#endif
93		    ((req & ~CC_EXTPURGE) != CC_PURGE && len > 2 * PAGE_SIZE))
94			doall = 1;
95
96		if (!doall) {
97			end = addr + len;
98			if (len <= 1024) {
99				addr = addr & ~0xf;
100				inc = 16;
101			} else {
102				addr = addr & ~PGOFSET;
103				inc = PAGE_SIZE;
104			}
105		}
106		do {
107			/*
108			 * Convert to physical address if needed.
109			 * If translation fails, we perform operation on
110			 * entire cache.
111			 */
112			if (!doall &&
113			    (pa == 0 || m68k_page_offset(addr) == 0)) {
114				if (pmap_extract(p->p_vmspace->vm_map.pmap,
115				    addr, &pa) == false)
116					doall = 1;
117			}
118			switch (req) {
119			case CC_EXTPURGE|CC_IPURGE:
120			case CC_IPURGE:
121				if (doall) {
122					DCFA();
123					ICPA();
124				} else if (inc == 16) {
125					DCFL(pa);
126					ICPL(pa);
127				} else if (inc == PAGE_SIZE) {
128					DCFP(pa);
129					ICPP(pa);
130				}
131				break;
132
133			case CC_EXTPURGE|CC_PURGE:
134			case CC_PURGE:
135				if (doall)
136					DCFA();	/* note: flush not purge */
137				else if (inc == 16)
138					DCPL(pa);
139				else if (inc == PAGE_SIZE)
140					DCPP(pa);
141				break;
142
143			case CC_EXTPURGE|CC_FLUSH:
144			case CC_FLUSH:
145				if (doall)
146					DCFA();
147				else if (inc == 16)
148					DCFL(pa);
149				else if (inc == PAGE_SIZE)
150					DCFP(pa);
151				break;
152
153			default:
154				error = EINVAL;
155				break;
156			}
157			if (doall)
158				break;
159			pa += inc;
160			addr += inc;
161		} while (addr < end);
162		return (error);
163	}
164#endif
165	switch (req) {
166	case CC_EXTPURGE|CC_PURGE:
167	case CC_EXTPURGE|CC_FLUSH:
168#if defined(CACHE_HAVE_PAC)
169		if (ectype == EC_PHYS)
170			PCIA();
171		/* fall into... */
172#endif
173	case CC_PURGE:
174	case CC_FLUSH:
175		DCIU();
176		break;
177	case CC_EXTPURGE|CC_IPURGE:
178#if defined(CACHE_HAVE_PAC)
179		if (ectype == EC_PHYS)
180			PCIA();
181		else
182#endif
183		DCIU();
184		/* fall into... */
185	case CC_IPURGE:
186		ICIA();
187		break;
188	default:
189		error = EINVAL;
190		break;
191	}
192	return error;
193}
194
195int
196sys_sysarch(struct lwp *l, void *v, register_t *retval)
197{
198
199	return ENOSYS;
200}
201
202#if defined(amiga) || defined(x68k)
203
204/*
205 * DMA cache control
206 */
207
208/*ARGSUSED1*/
209int
210dma_cachectl(caddr_t addr, int len)
211{
212#if defined(M68040) || defined(M68060)
213	int inc = 0;
214	int pa = 0;
215	caddr_t end;
216
217	if (mmutype != MMU_68040) {
218		return 0;
219	}
220
221	end = addr + len;
222	if (len <= 1024) {
223		addr = (caddr_t)((vaddr_t)addr & ~0xf);
224		inc = 16;
225	} else {
226		addr = (caddr_t)((vaddr_t)addr & ~PGOFSET);
227		inc = PAGE_SIZE;
228	}
229	do {
230		/*
231		 * Convert to physical address.
232		 */
233		if (pa == 0 || ((vaddr_t)addr & PGOFSET) == 0) {
234			pa = kvtop(addr);
235		}
236		if (inc == 16) {
237			DCFL(pa);
238			ICPL(pa);
239		} else {
240			DCFP(pa);
241			ICPP(pa);
242		}
243		pa += inc;
244		addr += inc;
245	} while (addr < end);
246#endif	/* defined(M68040) || defined(M68060) */
247	return 0;
248}
249#endif	/* defined(amiga) || defined(x68k) */
250