xref: /original-bsd/sys/vax/vax/mem.c (revision a0a7d8f4)
1 /*	mem.c	6.2	84/08/28	*/
2 
3 /*
4  * Memory special file
5  */
6 
7 #include "pte.h"
8 
9 #include "param.h"
10 #include "dir.h"
11 #include "user.h"
12 #include "conf.h"
13 #include "buf.h"
14 #include "systm.h"
15 #include "vm.h"
16 #include "cmap.h"
17 #include "uio.h"
18 
19 #include "mtpr.h"
20 
21 mmread(dev, uio)
22 	dev_t dev;
23 	struct uio *uio;
24 {
25 
26 	return (mmrw(dev, uio, UIO_READ));
27 }
28 
29 mmwrite(dev, uio)
30 	dev_t dev;
31 	struct uio *uio;
32 {
33 
34 	return (mmrw(dev, uio, UIO_WRITE));
35 }
36 
37 mmrw(dev, uio, rw)
38 	dev_t dev;
39 	struct uio *uio;
40 	enum uio_rw rw;
41 {
42 	register int o;
43 	register u_int c, v;
44 	register struct iovec *iov;
45 	int error = 0;
46 	extern int umbabeg, umbaend;
47 
48 
49 	while (uio->uio_resid > 0 && error == 0) {
50 		iov = uio->uio_iov;
51 		if (iov->iov_len == 0) {
52 			uio->uio_iov++;
53 			uio->uio_iovcnt--;
54 			if (uio->uio_iovcnt < 0)
55 				panic("mmrw");
56 			continue;
57 		}
58 		switch (minor(dev)) {
59 
60 /* minor device 0 is physical memory */
61 		case 0:
62 			v = btop(uio->uio_offset);
63 			if (v >= physmem)
64 				goto fault;
65 			*(int *)mmap = v | PG_V |
66 				(rw == UIO_READ ? PG_KR : PG_KW);
67 			mtpr(TBIS, vmmap);
68 			o = (int)uio->uio_offset & PGOFSET;
69 			c = min((u_int)(NBPG - o), (u_int)iov->iov_len);
70 			c = min(c, (u_int)(NBPG - ((int)iov->iov_base&PGOFSET)));
71 			error = uiomove((caddr_t)&vmmap[o], (int)c, rw, uio);
72 			continue;
73 
74 /* minor device 1 is kernel memory */
75 		case 1:
76 			if ((caddr_t)uio->uio_offset < (caddr_t)&umbabeg &&
77 			    (caddr_t)uio->uio_offset + uio->uio_resid >= (caddr_t)&umbabeg)
78 				goto fault;
79 			if ((caddr_t)uio->uio_offset >= (caddr_t)&umbabeg &&
80 			    (caddr_t)uio->uio_offset < (caddr_t)&umbaend)
81 				goto fault;
82 			c = iov->iov_len;
83 			if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE))
84 				goto fault;
85 			error = uiomove((caddr_t)uio->uio_offset, (int)c, rw, uio);
86 			continue;
87 
88 /* minor device 2 is EOF/RATHOLE */
89 		case 2:
90 			if (rw == UIO_READ)
91 				return (0);
92 			c = iov->iov_len;
93 			break;
94 
95 /* minor device 3 is unibus memory (addressed by shorts) */
96 		case 3:
97 			c = iov->iov_len;
98 			if (!kernacc((caddr_t)uio->uio_offset, c, rw == UIO_READ ? B_READ : B_WRITE))
99 				goto fault;
100 			if (!useracc(iov->iov_base, c, rw == UIO_READ ? B_WRITE : B_READ))
101 				goto fault;
102 			error = UNIcpy((caddr_t)uio->uio_offset, iov->iov_base,
103 			    (int)c, rw);
104 			break;
105 		}
106 		if (error)
107 			break;
108 		iov->iov_base += c;
109 		iov->iov_len -= c;
110 		uio->uio_offset += c;
111 		uio->uio_resid -= c;
112 	}
113 	return (error);
114 fault:
115 	return (EFAULT);
116 }
117 
118 /*
119  * UNIBUS Address Space <--> User Space transfer
120  */
121 UNIcpy(uniadd, usradd, n, rw)
122 	caddr_t uniadd, usradd;
123 	register int n;
124 	enum uio_rw rw;
125 {
126 	register short *from, *to;
127 
128 	if (rw == UIO_READ) {
129 		from = (short *)uniadd;
130 		to = (short *)usradd;
131 	} else {
132 		from = (short *)usradd;
133 		to = (short *)uniadd;
134 	}
135 	for (n >>= 1; n > 0; n--)
136 		*to++ = *from++;
137 	return (0);
138 }
139