xref: /netbsd/sys/arch/m68k/m68k/sys_machdep.c (revision 6550d01e)
1 /*	$NetBSD: sys_machdep.c,v 1.15 2010/06/06 04:50:07 mrg 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*/
68 int
69 cachectl1(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 
188 int
189 sys_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*/
202 int
203 dma_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