sys_machdep.c revision 1.4
1/*	$NetBSD: sys_machdep.c,v 1.4 2003/08/07 16:28:19 agc 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/sa.h>
46#include <sys/syscallargs.h>
47
48#include <machine/cpu.h>
49#include <m68k/cacheops.h>
50
51/* XXX should be in an include file somewhere */
52#define CC_PURGE	1
53#define CC_FLUSH	2
54#define CC_IPURGE	4
55#define CC_EXTPURGE	0x80000000
56/* XXX end should be */
57
58/*
59 * Note that what we do here on 040/060 for BSD is different than for HP-UX.
60 *
61 * In 'pux they either act on a line (len == 16), a page (len == PAGE_SIZE)
62 * or the whole cache (len == anything else).
63 *
64 * In BSD we attempt to be more optimal when acting on "odd" sizes.
65 * For lengths up to 1024 we do all affected lines, up to 2*PAGE_SIZE we
66 * do pages, above that we do the entire cache.
67 */
68/*ARGSUSED1*/
69int
70cachectl1(req, addr, len, p)
71	unsigned long req;
72	vaddr_t	addr;
73	size_t len;
74	struct proc *p;
75{
76	int error = 0;
77
78#if defined(M68040) || defined(M68060)
79	if (mmutype == MMU_68040) {
80		int inc = 0;
81		boolean_t doall = FALSE;
82		paddr_t pa = 0;
83		vaddr_t end = 0;
84#ifdef COMPAT_HPUX
85		extern struct emul emul_hpux;
86
87		if ((p->p_emul == &emul_hpux) &&
88		    len != 16 && len != PAGE_SIZE)
89			doall = 1;
90#endif
91
92		if (addr == 0 ||
93#if defined(M68060)
94		    (cputype == CPU_68040 && req & CC_IPURGE) ||
95#else
96		    (req & CC_IPURGE) ||
97#endif
98		    ((req & ~CC_EXTPURGE) != CC_PURGE && len > 2 * PAGE_SIZE))
99			doall = 1;
100
101		if (!doall) {
102			end = addr + len;
103			if (len <= 1024) {
104				addr = addr & ~0xf;
105				inc = 16;
106			} else {
107				addr = addr & ~PGOFSET;
108				inc = PAGE_SIZE;
109			}
110		}
111		do {
112			/*
113			 * Convert to physical address if needed.
114			 * If translation fails, we perform operation on
115			 * entire cache.
116			 */
117			if (!doall &&
118			    (pa == 0 || m68k_page_offset(addr) == 0)) {
119				if (pmap_extract(p->p_vmspace->vm_map.pmap,
120				    addr, &pa) == FALSE)
121					doall = 1;
122			}
123			switch (req) {
124			case CC_EXTPURGE|CC_IPURGE:
125			case CC_IPURGE:
126				if (doall) {
127					DCFA();
128					ICPA();
129				} else if (inc == 16) {
130					DCFL(pa);
131					ICPL(pa);
132				} else if (inc == PAGE_SIZE) {
133					DCFP(pa);
134					ICPP(pa);
135				}
136				break;
137
138			case CC_EXTPURGE|CC_PURGE:
139			case CC_PURGE:
140				if (doall)
141					DCFA();	/* note: flush not purge */
142				else if (inc == 16)
143					DCPL(pa);
144				else if (inc == PAGE_SIZE)
145					DCPP(pa);
146				break;
147
148			case CC_EXTPURGE|CC_FLUSH:
149			case CC_FLUSH:
150				if (doall)
151					DCFA();
152				else if (inc == 16)
153					DCFL(pa);
154				else if (inc == PAGE_SIZE)
155					DCFP(pa);
156				break;
157
158			default:
159				error = EINVAL;
160				break;
161			}
162			if (doall)
163				break;
164			pa += inc;
165			addr += inc;
166		} while (addr < end);
167		return (error);
168	}
169#endif
170	switch (req) {
171	case CC_EXTPURGE|CC_PURGE:
172	case CC_EXTPURGE|CC_FLUSH:
173#if defined(CACHE_HAVE_PAC)
174		if (ectype == EC_PHYS)
175			PCIA();
176		/* fall into... */
177#endif
178	case CC_PURGE:
179	case CC_FLUSH:
180		DCIU();
181		break;
182	case CC_EXTPURGE|CC_IPURGE:
183#if defined(CACHE_HAVE_PAC)
184		if (ectype == EC_PHYS)
185			PCIA();
186		else
187#endif
188		DCIU();
189		/* fall into... */
190	case CC_IPURGE:
191		ICIA();
192		break;
193	default:
194		error = EINVAL;
195		break;
196	}
197	return (error);
198}
199
200int
201sys_sysarch(l, v, retval)
202	struct lwp *l;
203	void *v;
204	register_t *retval;
205{
206
207	return (ENOSYS);
208}
209
210#if defined(amiga) || defined(x68k)
211
212/*
213 * DMA cache control
214 */
215
216/*ARGSUSED1*/
217int
218dma_cachectl(addr, len)
219	caddr_t	addr;
220	int len;
221{
222#if defined(M68040) || defined(M68060)
223	int inc = 0;
224	int pa = 0;
225	caddr_t end;
226
227	if (mmutype != MMU_68040) {
228		return (0);
229	}
230
231	end = addr + len;
232	if (len <= 1024) {
233		addr = (caddr_t)((vaddr_t)addr & ~0xf);
234		inc = 16;
235	} else {
236		addr = (caddr_t)((vaddr_t)addr & ~PGOFSET);
237		inc = PAGE_SIZE;
238	}
239	do {
240		/*
241		 * Convert to physical address.
242		 */
243		if (pa == 0 || ((vaddr_t)addr & PGOFSET) == 0) {
244			pa = kvtop(addr);
245		}
246		if (inc == 16) {
247			DCFL(pa);
248			ICPL(pa);
249		} else {
250			DCFP(pa);
251			ICPP(pa);
252		}
253		pa += inc;
254		addr += inc;
255	} while (addr < end);
256#endif	/* defined(M68040) || defined(M68060) */
257	return (0);
258}
259#endif	/* defined(amiga) || defined(x68k) */
260