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 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. All advertising materials mentioning features or use of this software 20 * must display the following acknowledgement: 21 * This product includes software developed by the University of 22 * California, Berkeley and its contributors. 23 * 4. Neither the name of the University nor the names of its contributors 24 * may be used to endorse or promote products derived from this software 25 * without specific prior written permission. 26 * 27 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 28 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 29 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 30 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 31 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 32 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 33 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 34 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 35 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 36 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 37 * SUCH DAMAGE. 38 * 39 * from: Utah $Hdr: mem.c 1.13 89/10/08$ 40 * from: @(#)mem.c 7.2 (Berkeley) 5/9/91 41 * $Id: mem.c,v 1.6 1993/12/19 00:50:06 wollman Exp $ 42 */ 43 44 /* 45 * Memory special file 46 */ 47 48 #include <sys/param.h> 49 #include <sys/conf.h> 50 #include <sys/buf.h> 51 #include <sys/systm.h> 52 #include <sys/uio.h> 53 #include <sys/malloc.h> 54 #include <sys/proc.h> 55 56 #include <machine/cpu.h> 57 #include <machine/psl.h> 58 59 #include <vm/vm_param.h> 60 #include <vm/lock.h> 61 #include <vm/vm_prot.h> 62 #include <vm/pmap.h> 63 64 extern char *ptvmmap; /* poor name! */ 65 /*ARGSUSED*/ 66 int 67 mmclose(dev, uio, flags) 68 dev_t dev; 69 struct uio *uio; 70 int flags; 71 { 72 struct trapframe *fp; 73 74 switch (minor(dev)) { 75 case 14: 76 fp = (struct trapframe *)curproc->p_md.md_regs; 77 fp->tf_eflags &= ~PSL_IOPL; 78 break; 79 default: 80 break; 81 } 82 return(0); 83 } 84 /*ARGSUSED*/ 85 int 86 mmopen(dev, uio, flags) 87 dev_t dev; 88 struct uio *uio; 89 int flags; 90 { 91 struct trapframe *fp; 92 93 switch (minor(dev)) { 94 case 14: 95 fp = (struct trapframe *)curproc->p_md.md_regs; 96 fp->tf_eflags |= PSL_IOPL; 97 break; 98 default: 99 break; 100 } 101 return(0); 102 } 103 /*ARGSUSED*/ 104 int 105 mmrw(dev, uio, flags) 106 dev_t dev; 107 struct uio *uio; 108 int flags; 109 { 110 register int o; 111 register u_int c, v; 112 register struct iovec *iov; 113 int error = 0; 114 caddr_t zbuf = NULL; 115 116 while (uio->uio_resid > 0 && error == 0) { 117 iov = uio->uio_iov; 118 if (iov->iov_len == 0) { 119 uio->uio_iov++; 120 uio->uio_iovcnt--; 121 if (uio->uio_iovcnt < 0) 122 panic("mmrw"); 123 continue; 124 } 125 switch (minor(dev)) { 126 127 /* minor device 0 is physical memory */ 128 case 0: 129 v = uio->uio_offset; 130 pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v, 131 uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE, 132 TRUE); 133 o = (int)uio->uio_offset & PGOFSET; 134 c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET)); 135 c = min(c, (u_int)(NBPG - o)); 136 c = min(c, (u_int)iov->iov_len); 137 error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio); 138 pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap, 139 (vm_offset_t)&ptvmmap[NBPG]); 140 continue; 141 142 /* minor device 1 is kernel memory */ 143 case 1: 144 c = iov->iov_len; 145 if (!kernacc((caddr_t)(int)uio->uio_offset, c, 146 uio->uio_rw == UIO_READ ? B_READ : B_WRITE)) 147 return(EFAULT); 148 error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio); 149 continue; 150 151 /* minor device 2 is EOF/RATHOLE */ 152 case 2: 153 if (uio->uio_rw == UIO_READ) 154 return (0); 155 c = iov->iov_len; 156 break; 157 158 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */ 159 case 12: 160 if (uio->uio_rw == UIO_WRITE) { 161 c = iov->iov_len; 162 break; 163 } 164 if (zbuf == NULL) { 165 zbuf = (caddr_t) 166 malloc(CLBYTES, M_TEMP, M_WAITOK); 167 bzero(zbuf, CLBYTES); 168 } 169 c = min(iov->iov_len, CLBYTES); 170 error = uiomove(zbuf, (int)c, uio); 171 continue; 172 173 #ifdef notyet 174 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate 175 i/o device address bus, different than memory bus. Semantics here are 176 very different than ordinary read/write, as if iov_len is a multiple 177 an implied string move from a single port will be done. Note that lseek 178 must be used to set the port number reliably. */ 179 case 14: 180 if (iov->iov_len == 1) { 181 u_char tmp; 182 tmp = inb(uio->uio_offset); 183 error = uiomove (&tmp, iov->iov_len, uio); 184 } else { 185 if (!useracc((caddr_t)iov->iov_base, 186 iov->iov_len, uio->uio_rw)) 187 return (EFAULT); 188 insb(uio->uio_offset, iov->iov_base, 189 iov->iov_len); 190 } 191 break; 192 case 15: 193 if (iov->iov_len == sizeof (short)) { 194 u_short tmp; 195 tmp = inw(uio->uio_offset); 196 error = uiomove (&tmp, iov->iov_len, uio); 197 } else { 198 if (!useracc((caddr_t)iov->iov_base, 199 iov->iov_len, uio->uio_rw)) 200 return (EFAULT); 201 insw(uio->uio_offset, iov->iov_base, 202 iov->iov_len/ sizeof (short)); 203 } 204 break; 205 case 16: 206 if (iov->iov_len == sizeof (long)) { 207 u_long tmp; 208 tmp = inl(uio->uio_offset); 209 error = uiomove (&tmp, iov->iov_len, uio); 210 } else { 211 if (!useracc((caddr_t)iov->iov_base, 212 iov->iov_len, uio->uio_rw)) 213 return (EFAULT); 214 insl(uio->uio_offset, iov->iov_base, 215 iov->iov_len/ sizeof (long)); 216 } 217 break; 218 #endif 219 220 default: 221 return (ENXIO); 222 } 223 if (error) 224 break; 225 iov->iov_base += c; 226 iov->iov_len -= c; 227 uio->uio_offset += c; 228 uio->uio_resid -= c; 229 } 230 if (zbuf) 231 free(zbuf, M_TEMP); 232 return (error); 233 } 234 235 236 237 238 /*******************************************************\ 239 * allow user processes to MMAP some memory sections * 240 * instead of going through read/write * 241 \*******************************************************/ 242 int memmmap(dev_t dev, int offset, int nprot) 243 { 244 switch (minor(dev)) 245 { 246 247 /* minor device 0 is physical memory */ 248 case 0: 249 return i386_btop(offset); 250 251 /* minor device 1 is kernel memory */ 252 case 1: 253 return i386_btop(vtophys(offset)); 254 255 default: 256 return -1; 257 } 258 } 259 260