1 /*
2 * Copyright (c) 1988 University of Utah.
3 * Copyright (c) 1992, 1993
4 * The Regents of the University of California. All rights reserved.
5 *
6 * This code is derived from software contributed to Berkeley by
7 * the Systems Programming Group of the University of Utah Computer
8 * Science Department and Ralph Campbell.
9 *
10 * %sccs.include.redist.c%
11 *
12 * from: Utah $Hdr: mem.c 1.14 90/10/12$
13 *
14 * @(#)mem.c 8.3 (Berkeley) 06/02/95
15 */
16
17 /*
18 * Memory special file
19 */
20
21 #include <sys/param.h>
22 #include <sys/conf.h>
23 #include <sys/buf.h>
24 #include <sys/systm.h>
25 #include <sys/malloc.h>
26
27 #include <machine/cpu.h>
28
29 #include <vm/vm.h>
30
31 /*ARGSUSED*/
mmrw(dev,uio,flags)32 mmrw(dev, uio, flags)
33 dev_t dev;
34 struct uio *uio;
35 int flags;
36 {
37 register u_long v;
38 register u_int c;
39 register struct iovec *iov;
40 int error = 0;
41 caddr_t zbuf = NULL;
42 extern vm_offset_t avail_end;
43
44 while (uio->uio_resid > 0 && error == 0) {
45 iov = uio->uio_iov;
46 if (iov->iov_len == 0) {
47 uio->uio_iov++;
48 uio->uio_iovcnt--;
49 if (uio->uio_iovcnt < 0)
50 panic("mmrw");
51 continue;
52 }
53 switch (minor(dev)) {
54
55 /* minor device 0 is physical memory */
56 case 0:
57 v = (u_long)uio->uio_offset;
58 c = iov->iov_len;
59 if (v + c <= btoc(physmem))
60 v += MACH_CACHED_MEMORY_ADDR;
61 else
62 return (EFAULT);
63 error = uiomove((caddr_t)v, (int)c, uio);
64 continue;
65
66 /* minor device 1 is kernel memory */
67 case 1:
68 v = (u_long)uio->uio_offset;
69 if (v < MACH_CACHED_MEMORY_ADDR)
70 return (EFAULT);
71 c = iov->iov_len;
72 if (v + c <= MACH_PHYS_TO_CACHED(avail_end) ||
73 v >= MACH_KSEG2_ADDR && kernacc((caddr_t)v, c,
74 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) {
75 error = uiomove((caddr_t)v, (int)c, uio);
76 continue;
77 }
78 return (EFAULT);
79
80 /* minor device 2 is EOF/RATHOLE */
81 case 2:
82 if (uio->uio_rw == UIO_WRITE)
83 uio->uio_resid = 0;
84 return (0);
85
86 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
87 case 12:
88 if (uio->uio_rw == UIO_WRITE) {
89 c = iov->iov_len;
90 break;
91 }
92 if (zbuf == NULL) {
93 zbuf = (caddr_t)
94 malloc(CLBYTES, M_TEMP, M_WAITOK);
95 bzero(zbuf, CLBYTES);
96 }
97 c = min(iov->iov_len, CLBYTES);
98 error = uiomove(zbuf, (int)c, uio);
99 continue;
100
101 default:
102 return (ENXIO);
103 }
104 if (error)
105 break;
106 iov->iov_base += c;
107 iov->iov_len -= c;
108 uio->uio_offset += c;
109 uio->uio_resid -= c;
110 }
111 if (zbuf)
112 free(zbuf, M_TEMP);
113 return (error);
114 }
115