1 /* $NetBSD: mem.c,v 1.32 2007/03/04 06:00:55 christos Exp $ */
4 * Copyright (c) 1982, 1986, 1990, 1993
5 * The Regents of the University of California. All rights reserved.
7 * This code is derived from software contributed to Berkeley by
8 * the Systems Programming Group of the University of Utah Computer
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions and the following disclaimer.
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in the
18 * documentation and/or other materials provided with the distribution.
19 * 3. 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.
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
35 * from: @(#)mem.c 8.3 (Berkeley) 1/12/94
38 * Copyright (c) 1988 University of Utah.
40 * This code is derived from software contributed to Berkeley by
41 * the Systems Programming Group of the University of Utah Computer
44 * Redistribution and use in source and binary forms, with or without
45 * modification, are permitted provided that the following conditions
47 * 1. Redistributions of source code must retain the above copyright
48 * notice, this list of conditions and the following disclaimer.
49 * 2. Redistributions in binary form must reproduce the above copyright
50 * notice, this list of conditions and the following disclaimer in the
51 * documentation and/or other materials provided with the distribution.
52 * 3. All advertising materials mentioning features or use of this software
53 * must display the following acknowledgement:
54 * This product includes software developed by the University of
55 * California, Berkeley and its contributors.
56 * 4. Neither the name of the University nor the names of its contributors
57 * may be used to endorse or promote products derived from this software
58 * without specific prior written permission.
60 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
61 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
62 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
63 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
64 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
65 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
66 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
67 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
68 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
69 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
72 * from: @(#)mem.c 8.3 (Berkeley) 1/12/94
79 #include <sys/cdefs.h>
80 __KERNEL_RCSID(0, "$NetBSD: mem.c,v 1.32 2007/03/04 06:00:55 christos Exp $");
82 #include <sys/param.h>
83 #include <sys/systm.h>
86 #include <sys/malloc.h>
90 #include <uvm/uvm_extern.h>
92 #include <machine/cpu.h>
93 #include <machine/eeprom.h>
94 #include <machine/leds.h>
95 #include <machine/mon.h>
96 #include <machine/pmap.h>
97 #include <machine/pte.h>
99 #include <sun3/sun3/machdep.h>
101 #define DEV_VME16D16 5 /* minor device 5 is /dev/vme16d16 */
102 #define DEV_VME24D16 6 /* minor device 6 is /dev/vme24d16 */
103 #define DEV_VME32D16 7 /* minor device 7 is /dev/vme32d16 */
104 #define DEV_VME16D32 8 /* minor device 8 is /dev/vme16d32 */
105 #define DEV_VME24D32 9 /* minor device 9 is /dev/vme24d32 */
106 #define DEV_VME32D32 10 /* minor device 10 is /dev/vme32d32 */
107 #define DEV_EEPROM 11 /* minor device 11 is eeprom */
108 #define DEV_LEDS 13 /* minor device 13 is leds */
110 /* XXX - Put this in pmap_pvt.h or something? */
111 extern paddr_t avail_start
;
113 static int promacc(void *, int, int);
114 static void *devzeropage
;
117 dev_type_ioctl(mmioctl
);
118 dev_type_mmap(mmmmap
);
120 const struct cdevsw mem_cdevsw
= {
121 nullopen
, nullclose
, mmrw
, mmrw
, mmioctl
,
122 nostop
, notty
, nopoll
, mmmmap
, nokqfilter
,
127 mmrw(dev_t dev
, struct uio
*uio
, int flags
)
136 if (minor(dev
) == DEV_MEM
) {
139 /* lock against other uses of shared vmmap */
140 while (physlock
> 0) {
142 error
= tsleep((void *)&physlock
, PZERO
| PCATCH
,
149 while (uio
->uio_resid
> 0 && error
== 0) {
151 if (iov
->iov_len
== 0) {
154 if (uio
->uio_iovcnt
< 0)
158 switch (minor(dev
)) {
162 /* allow reads only in RAM */
163 if (!pmap_pa_exists(v
)) {
168 * If the offset (physical address) is within the
169 * linearly mapped range (0 .. avail_start) then
170 * we can save some hair by using the /dev/kmem
171 * alias mapping known to exist for this range.
173 if (v
< avail_start
) {
177 /* Temporarily map the memory at vmmap. */
178 prot
= uio
->uio_rw
== UIO_READ
? VM_PROT_READ
:
180 pmap_enter(pmap_kernel(), (vaddr_t
)vmmap
,
181 trunc_page(v
), prot
, prot
|PMAP_WIRED
);
182 pmap_update(pmap_kernel());
184 c
= min(uio
->uio_resid
, (int)(PAGE_SIZE
- o
));
185 error
= uiomove((char *)vmmap
+ o
, c
, uio
);
186 pmap_remove(pmap_kernel(), (vaddr_t
)vmmap
,
187 (vaddr_t
)vmmap
+ PAGE_SIZE
);
188 pmap_update(pmap_kernel());
195 * One page at a time to simplify access checks.
196 * Note that we can get here from case 0 above!
199 c
= min(uio
->uio_resid
, (int)(PAGE_SIZE
- o
));
200 rw
= (uio
->uio_rw
== UIO_READ
) ? B_READ
: B_WRITE
;
201 if (!(uvm_kernacc((void *)v
, c
, rw
) ||
202 promacc((void *)v
, c
, rw
)))
205 /* Note: case 0 can get here, so must unlock! */
208 error
= uiomove((void *)v
, c
, uio
);
212 if (uio
->uio_rw
== UIO_WRITE
)
217 error
= eeprom_uio(uio
);
218 /* Yes, return (not break) so EOF works. */
222 /* Write to /dev/zero is ignored. */
223 if (uio
->uio_rw
== UIO_WRITE
) {
228 * On the first call, allocate and zero a page
229 * of memory for use with /dev/zero.
231 if (devzeropage
== NULL
) {
232 devzeropage
= (void *)
233 malloc(PAGE_SIZE
, M_TEMP
, M_WAITOK
);
234 memset(devzeropage
, 0, PAGE_SIZE
);
236 c
= min(iov
->iov_len
, PAGE_SIZE
);
237 error
= uiomove(devzeropage
, c
, uio
);
241 error
= leds_uio(uio
);
242 /* Yes, return (not break) so EOF works. */
251 * Note the different location of this label, compared with
252 * other ports. This is because the /dev/mem to /dev/kmem
253 * redirection above jumps here on error to do its unlock.
256 if (minor(dev
) == DEV_MEM
) {
258 wakeup((void *)&physlock
);
265 mmmmap(dev_t dev
, off_t off
, int prot
)
268 * Check address validity.
273 switch (minor(dev
)) {
275 case DEV_MEM
: /* dev/mem */
276 /* Allow access only in valid memory. */
277 if (!pmap_pa_exists(off
))
281 #if 0 /* XXX - NOTYET */
282 /* XXX - Move this to bus_subr.c? */
284 if (off
& 0xffff0000)
289 if (off
& 0xff000000)
294 return (off
| PMAP_VME16
);
297 if (off
& 0xffff0000)
302 if (off
& 0xff000000)
307 return (off
| PMAP_VME32
);
316 * Just like uvm_kernacc(), but for the PROM mappings.
317 * Return non-zero if access at VA is allowed.
320 promacc(void *va
, int len
, int rw
)
325 eva
= (vaddr_t
)va
+ len
;
327 /* Test for the most common case first. */
328 if (sva
< SUN3X_PROM_BASE
)
331 /* Read in the PROM itself is OK. */
332 if ((rw
== B_READ
) && (eva
<= SUN3X_MONEND
))
335 /* PROM data page is OK for read/write. */
336 if ((sva
>= SUN3X_MONDATA
) &&
337 (eva
<= (SUN3X_MONDATA
+ PAGE_SIZE
)))
340 /* otherwise, not OK to touch */