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*/ 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