1 /* 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990, 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. 9 * 10 * %sccs.include.redist.c% 11 * 12 * from: Utah $Hdr: mem.c 1.14 90/10/12$ 13 * 14 * @(#)mem.c 8.4 (Berkeley) 04/12/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 extern u_int lowram; 32 caddr_t zeropage; 33 34 /*ARGSUSED*/ 35 mmrw(dev, uio, flags) 36 dev_t dev; 37 struct uio *uio; 38 int flags; 39 { 40 register int o; 41 register u_int c, v; 42 register struct iovec *iov; 43 int error = 0; 44 int kernloc; 45 46 while (uio->uio_resid > 0 && error == 0) { 47 iov = uio->uio_iov; 48 if (iov->iov_len == 0) { 49 uio->uio_iov++; 50 uio->uio_iovcnt--; 51 if (uio->uio_iovcnt < 0) 52 panic("mmrw"); 53 continue; 54 } 55 switch (minor(dev)) { 56 57 /* minor device 0 is physical memory */ 58 case 0: 59 v = uio->uio_offset; 60 #ifndef DEBUG 61 /* allow reads only in RAM (except for DEBUG) */ 62 if (v >= 0xFFFFFFFC || v < lowram) 63 return (EFAULT); 64 #endif 65 pmap_enter(kernel_pmap, (vm_offset_t)vmmap, 66 trunc_page(v), uio->uio_rw == UIO_READ ? 67 VM_PROT_READ : VM_PROT_WRITE, TRUE); 68 o = (int)uio->uio_offset & PGOFSET; 69 c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET)); 70 c = min(c, (u_int)(NBPG - o)); 71 c = min(c, (u_int)iov->iov_len); 72 error = uiomove((caddr_t)&vmmap[o], (int)c, uio); 73 pmap_remove(kernel_pmap, (vm_offset_t)vmmap, 74 (vm_offset_t)&vmmap[NBPG]); 75 continue; 76 77 /* minor device 1 is kernel memory */ 78 case 1: 79 kernloc = uio->uio_offset; 80 c = min(iov->iov_len, MAXPHYS); 81 if (!kernacc((caddr_t)kernloc, c, 82 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 83 return (EFAULT); 84 error = uiomove((caddr_t)kernloc, (int)c, uio); 85 continue; 86 87 /* minor device 2 is EOF/RATHOLE */ 88 case 2: 89 if (uio->uio_rw == UIO_WRITE) 90 uio->uio_resid = 0; 91 return (0); 92 93 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 94 case 12: 95 if (uio->uio_rw == UIO_WRITE) { 96 c = iov->iov_len; 97 break; 98 } 99 /* 100 * On the first call, allocate and zero a page 101 * of memory for use with /dev/zero. 102 * 103 * XXX on the hp300 we already know where there 104 * is a global zeroed page, the null segment table. 105 */ 106 if (zeropage == NULL) { 107 #if CLBYTES == NBPG 108 extern caddr_t Segtabzero; 109 zeropage = Segtabzero; 110 #else 111 zeropage = (caddr_t) 112 malloc(CLBYTES, M_TEMP, M_WAITOK); 113 bzero(zeropage, CLBYTES); 114 #endif 115 } 116 c = min(iov->iov_len, CLBYTES); 117 error = uiomove(zeropage, (int)c, uio); 118 continue; 119 120 default: 121 return (ENXIO); 122 } 123 if (error) 124 break; 125 iov->iov_base += c; 126 iov->iov_len -= c; 127 uio->uio_offset += c; 128 uio->uio_resid -= c; 129 } 130 return (error); 131 } 132 133 mmmap(dev, off, prot) 134 dev_t dev; 135 int off, prot; 136 { 137 /* 138 * /dev/mem is the only one that makes sense through this 139 * interface. For /dev/kmem any physaddr we return here 140 * could be transient and hence incorrect or invalid at 141 * a later time. /dev/null just doesn't make any sense 142 * and /dev/zero is a hack that is handled via the default 143 * pager in mmap(). 144 */ 145 if (minor(dev) != 0) 146 return (-1); 147 /* 148 * Allow access only in RAM. 149 * 150 * XXX could be extended to allow access to IO space but must 151 * be very careful. 152 */ 153 if ((unsigned)off < lowram || (unsigned)off >= 0xFFFFFFFC) 154 return (-1); 155 return (hp300_btop(off)); 156 } 157