xref: /original-bsd/sys/sparc/sparc/mem.c (revision 3705696b)
1 /*
2  * Copyright (c) 1992, 1993
3  *	The Regents of the University of California.  All rights reserved.
4  *
5  * This software was developed by the Computer Systems Engineering group
6  * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and
7  * contributed to Berkeley.
8  *
9  * All advertising materials mentioning features or use of this software
10  * must display the following acknowledgement:
11  *	This product includes software developed by the University of
12  *	California, Lawrence Berkeley Laboratory.
13  *
14  * %sccs.include.redist.c%
15  *
16  *	@(#)mem.c	8.1 (Berkeley) 06/11/93
17  *
18  * from: $Header: mem.c,v 1.9 92/11/26 03:05:03 torek Exp $
19  */
20 
21 /*
22  * Memory special file
23  */
24 
25 #include <sys/param.h>
26 #include <sys/proc.h>
27 #include <sys/conf.h>
28 #include <sys/buf.h>
29 #include <sys/systm.h>
30 #include <sys/malloc.h>
31 
32 #include <vm/vm.h>
33 
34 /*ARGSUSED*/
35 mmrw(dev, uio, flags)
36 	dev_t dev;
37 	struct uio *uio;
38 	int flags;
39 {
40 	register struct iovec *iov;
41 	register caddr_t va;
42 	register int o;
43 	register u_int c;
44 	int error = 0;
45 	caddr_t zbuf = NULL;
46 	extern caddr_t vmempage;
47 	static struct {
48 		int	locked;
49 		int	wanted;
50 	} physlock;
51 
52 	if (minor(dev) == 0) {
53 		/* lock against other uses of shared vmempage */
54 		while (physlock.locked) {
55 			physlock.wanted = 1;
56 			(void)tsleep((caddr_t)&physlock, PZERO, "mmrw", 0);
57 		}
58 		physlock.locked = 1;
59 	}
60 	while (uio->uio_resid > 0 && error == 0) {
61 		iov = uio->uio_iov;
62 		if (iov->iov_len == 0) {
63 			uio->uio_iov++;
64 			uio->uio_iovcnt--;
65 			if (uio->uio_iovcnt < 0)
66 				panic("mmrw");
67 			continue;
68 		}
69 		switch (minor(dev)) {
70 
71 /* minor device 0 is physical memory */
72 		case 0:
73 			o = uio->uio_offset;
74 			va = vmempage;
75 			if (pmap_enter_hw(kernel_pmap, (vm_offset_t)va,
76 			    (vm_offset_t)trunc_page(o),
77 			    uio->uio_rw == UIO_READ ?
78 			    VM_PROT_READ : VM_PROT_WRITE, 1)) {
79 				error = EFAULT;
80 				goto unlock;
81 			}
82 			o = (int)uio->uio_offset & PGOFSET;
83 			c = min(uio->uio_resid, (u_int)(NBPG - o));
84 			error = uiomove(&va[o], (int)c, uio);
85 			pmap_remove(kernel_pmap,
86 			    (vm_offset_t)va, (vm_offset_t)va + PAGE_SIZE);
87 			continue;
88 
89 /* minor device 1 is kernel memory */
90 		case 1:
91 			va = (caddr_t)uio->uio_offset;
92 			c = min(iov->iov_len, MAXPHYS);
93 			if (!kernacc(va, c,
94 			    uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
95 				return (EFAULT);
96 			error = uiomove(va, (int)c, uio);
97 			continue;
98 
99 /* minor device 2 is EOF/RATHOLE */
100 		case 2:
101 			if (uio->uio_rw == UIO_WRITE)
102 				uio->uio_resid = 0;
103 			return (0);
104 
105 /* XXX should add sbus, `prom', etc */
106 
107 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
108 		case 12:
109 			if (uio->uio_rw == UIO_WRITE) {
110 				uio->uio_resid = 0;
111 				return (0);
112 			}
113 			if (zbuf == NULL) {	/* XXX grot */
114 				zbuf = (caddr_t)malloc(CLBYTES,
115 				    M_TEMP, M_WAITOK);
116 				bzero(zbuf, CLBYTES);
117 			}
118 			c = min(iov->iov_len, CLBYTES);
119 			error = uiomove(zbuf, (int)c, uio);
120 			continue;
121 
122 		default:
123 			return (ENXIO);
124 		}
125 		if (error)
126 			break;
127 		iov->iov_base += c;
128 		iov->iov_len -= c;
129 		uio->uio_offset += c;
130 		uio->uio_resid -= c;
131 	}
132 	if (zbuf)
133 		free(zbuf, M_TEMP);
134 	if (minor(dev) == 0) {
135 unlock:
136 		physlock.locked = 0;
137 		if (physlock.wanted)
138 			wakeup((caddr_t)&physlock);
139 	}
140 	return (error);
141 }
142