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