1 /* $NetBSD: sys_machdep.c,v 1.16 2019/04/11 14:38:06 kamil 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: sys_machdep.c,v 1.16 2019/04/11 14:38:06 kamil Exp $");
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
cachectl1(u_long req,vaddr_t addr,size_t len,struct proc * p)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
sys_sysarch(struct lwp * l,const struct sys_sysarch_args * uap,register_t * retval)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
dma_cachectl(void * addr,int len)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