1 /*- 2 * Copyright (c) 1988 University of Utah. 3 * Copyright (c) 1982, 1986, 1990 The Regents of the University of California. 4 * 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 code derived from software contributed to 9 * Berkeley by William Jolitz. 10 * 11 * %sccs.include.redist.c% 12 * 13 * from: Utah $Hdr: mem.c 1.13 89/10/08$ 14 * @(#)mem.c 7.5 (Berkeley) 02/19/92 15 */ 16 17 /* 18 * Memory special file 19 */ 20 21 #include "param.h" 22 #include "conf.h" 23 #include "buf.h" 24 #include "systm.h" 25 #include "uio.h" 26 #include "malloc.h" 27 28 #include "machine/cpu.h" 29 30 #include "vm/vm_param.h" 31 #include "vm/lock.h" 32 #include "vm/vm_prot.h" 33 #include "vm/pmap.h" 34 35 extern char *vmmap; /* poor name! */ 36 /*ARGSUSED*/ 37 mmrw(dev, uio, flags) 38 dev_t dev; 39 struct uio *uio; 40 int flags; 41 { 42 register int o; 43 register u_int c, v; 44 register struct iovec *iov; 45 int error = 0; 46 caddr_t zbuf = NULL; 47 48 while (uio->uio_resid > 0 && error == 0) { 49 iov = uio->uio_iov; 50 if (iov->iov_len == 0) { 51 uio->uio_iov++; 52 uio->uio_iovcnt--; 53 if (uio->uio_iovcnt < 0) 54 panic("mmrw"); 55 continue; 56 } 57 switch (minor(dev)) { 58 59 /* minor device 0 is physical memory */ 60 case 0: 61 v = uio->uio_offset; 62 pmap_enter(kernel_pmap, vmmap, v, 63 uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE, 64 TRUE); 65 o = (int)uio->uio_offset & PGOFSET; 66 c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET)); 67 c = MIN(c, (u_int)(NBPG - o)); 68 c = MIN(c, (u_int)iov->iov_len); 69 error = uiomove((caddr_t)&vmmap[o], (int)c, uio); 70 pmap_remove(kernel_pmap, vmmap, &vmmap[NBPG]); 71 continue; 72 73 /* minor device 1 is kernel memory */ 74 case 1: 75 c = iov->iov_len; 76 if (!kernacc((caddr_t)uio->uio_offset, c, 77 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 78 return(EFAULT); 79 error = uiomove((caddr_t)uio->uio_offset, (int)c, uio); 80 continue; 81 82 /* minor device 2 is EOF/RATHOLE */ 83 case 2: 84 if (uio->uio_rw == UIO_READ) 85 return (0); 86 c = iov->iov_len; 87 break; 88 89 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 90 case 12: 91 if (uio->uio_rw == UIO_WRITE) { 92 c = iov->iov_len; 93 break; 94 } 95 if (zbuf == NULL) { 96 zbuf = (caddr_t) 97 malloc(CLBYTES, M_TEMP, M_WAITOK); 98 bzero(zbuf, CLBYTES); 99 } 100 c = MIN(iov->iov_len, CLBYTES); 101 error = uiomove(zbuf, (int)c, uio); 102 continue; 103 104 #ifdef notyet 105 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate 106 i/o device address bus, different than memory bus. Semantics here are 107 very different than ordinary read/write, as if iov_len is a multiple 108 an implied string move from a single port will be done. Note that lseek 109 must be used to set the port number reliably. */ 110 case 14: 111 if (iov->iov_len == 1) { 112 u_char tmp; 113 tmp = inb(uio->uio_offset); 114 error = uiomove (&tmp, iov->iov_len, uio); 115 } else { 116 if (!useracc((caddr_t)iov->iov_base, 117 iov->iov_len, uio->uio_rw)) 118 return (EFAULT); 119 insb(uio->uio_offset, iov->iov_base, 120 iov->iov_len); 121 } 122 break; 123 case 15: 124 if (iov->iov_len == sizeof (short)) { 125 u_short tmp; 126 tmp = inw(uio->uio_offset); 127 error = uiomove (&tmp, iov->iov_len, uio); 128 } else { 129 if (!useracc((caddr_t)iov->iov_base, 130 iov->iov_len, uio->uio_rw)) 131 return (EFAULT); 132 insw(uio->uio_offset, iov->iov_base, 133 iov->iov_len/ sizeof (short)); 134 } 135 break; 136 case 16: 137 if (iov->iov_len == sizeof (long)) { 138 u_long tmp; 139 tmp = inl(uio->uio_offset); 140 error = uiomove (&tmp, iov->iov_len, uio); 141 } else { 142 if (!useracc((caddr_t)iov->iov_base, 143 iov->iov_len, uio->uio_rw)) 144 return (EFAULT); 145 insl(uio->uio_offset, iov->iov_base, 146 iov->iov_len/ sizeof (long)); 147 } 148 break; 149 #endif 150 151 default: 152 return (ENXIO); 153 } 154 if (error) 155 break; 156 iov->iov_base += c; 157 iov->iov_len -= c; 158 uio->uio_offset += c; 159 uio->uio_resid -= c; 160 } 161 if (zbuf) 162 free(zbuf, M_TEMP); 163 return (error); 164 } 165