xref: /freebsd/sys/amd64/amd64/mem.c (revision efeaf95a41820e4eb661a90cfb59a26e36575784)
15b81b6b3SRodney W. Grimes /*-
25b81b6b3SRodney W. Grimes  * Copyright (c) 1988 University of Utah.
35b81b6b3SRodney W. Grimes  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
45b81b6b3SRodney W. Grimes  * All rights reserved.
55b81b6b3SRodney W. Grimes  *
65b81b6b3SRodney W. Grimes  * This code is derived from software contributed to Berkeley by
75b81b6b3SRodney W. Grimes  * the Systems Programming Group of the University of Utah Computer
85b81b6b3SRodney W. Grimes  * Science Department, and code derived from software contributed to
95b81b6b3SRodney W. Grimes  * Berkeley by William Jolitz.
105b81b6b3SRodney W. Grimes  *
115b81b6b3SRodney W. Grimes  * Redistribution and use in source and binary forms, with or without
125b81b6b3SRodney W. Grimes  * modification, are permitted provided that the following conditions
135b81b6b3SRodney W. Grimes  * are met:
145b81b6b3SRodney W. Grimes  * 1. Redistributions of source code must retain the above copyright
155b81b6b3SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer.
165b81b6b3SRodney W. Grimes  * 2. Redistributions in binary form must reproduce the above copyright
175b81b6b3SRodney W. Grimes  *    notice, this list of conditions and the following disclaimer in the
185b81b6b3SRodney W. Grimes  *    documentation and/or other materials provided with the distribution.
195b81b6b3SRodney W. Grimes  * 3. All advertising materials mentioning features or use of this software
205b81b6b3SRodney W. Grimes  *    must display the following acknowledgement:
215b81b6b3SRodney W. Grimes  *	This product includes software developed by the University of
225b81b6b3SRodney W. Grimes  *	California, Berkeley and its contributors.
235b81b6b3SRodney W. Grimes  * 4. Neither the name of the University nor the names of its contributors
245b81b6b3SRodney W. Grimes  *    may be used to endorse or promote products derived from this software
255b81b6b3SRodney W. Grimes  *    without specific prior written permission.
265b81b6b3SRodney W. Grimes  *
275b81b6b3SRodney W. Grimes  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
285b81b6b3SRodney W. Grimes  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
295b81b6b3SRodney W. Grimes  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
305b81b6b3SRodney W. Grimes  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
315b81b6b3SRodney W. Grimes  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
325b81b6b3SRodney W. Grimes  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
335b81b6b3SRodney W. Grimes  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
345b81b6b3SRodney W. Grimes  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
355b81b6b3SRodney W. Grimes  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
365b81b6b3SRodney W. Grimes  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
375b81b6b3SRodney W. Grimes  * SUCH DAMAGE.
385b81b6b3SRodney W. Grimes  *
395b81b6b3SRodney W. Grimes  *	from: Utah $Hdr: mem.c 1.13 89/10/08$
4047cacd38SRodney W. Grimes  *	from: @(#)mem.c	7.2 (Berkeley) 5/9/91
41efeaf95aSDavid Greenman  *	$Id: mem.c,v 1.21 1995/11/29 14:39:26 julian Exp $
425b81b6b3SRodney W. Grimes  */
435b81b6b3SRodney W. Grimes 
445b81b6b3SRodney W. Grimes /*
455b81b6b3SRodney W. Grimes  * Memory special file
465b81b6b3SRodney W. Grimes  */
475b81b6b3SRodney W. Grimes 
4826f9a767SRodney W. Grimes #include <sys/param.h>
4926f9a767SRodney W. Grimes #include <sys/conf.h>
5026f9a767SRodney W. Grimes #include <sys/buf.h>
5126f9a767SRodney W. Grimes #include <sys/systm.h>
5226f9a767SRodney W. Grimes #include <sys/uio.h>
5326f9a767SRodney W. Grimes #include <sys/malloc.h>
5426f9a767SRodney W. Grimes #include <sys/proc.h>
555b81b6b3SRodney W. Grimes 
5626f9a767SRodney W. Grimes #include <machine/cpu.h>
5700f7f6beSBruce Evans #include <machine/random.h>
5826f9a767SRodney W. Grimes #include <machine/psl.h>
595b81b6b3SRodney W. Grimes 
60c87801feSDavid Greenman #include <vm/vm.h>
6126f9a767SRodney W. Grimes #include <vm/vm_param.h>
6226f9a767SRodney W. Grimes #include <vm/lock.h>
6326f9a767SRodney W. Grimes #include <vm/vm_prot.h>
6426f9a767SRodney W. Grimes #include <vm/pmap.h>
65efeaf95aSDavid Greenman #include <vm/vm_extern.h>
665b81b6b3SRodney W. Grimes 
6753ac6efbSJulian Elischer #ifdef JREMOD
6853ac6efbSJulian Elischer #include <sys/kernel.h>
6953ac6efbSJulian Elischer #define CDEV_MAJOR 2
7053ac6efbSJulian Elischer #endif /*JREMOD*/
7153ac6efbSJulian Elischer 
728af5d536SJulian Elischer #ifdef DEVFS
738af5d536SJulian Elischer #include <sys/devfsext.h>
7433f538b9SBruce Evans 
7533f538b9SBruce Evans static void
7653ac6efbSJulian Elischer memdevfs_init(dev_t dev)
778af5d536SJulian Elischer {
788af5d536SJulian Elischer   void * x;
7953ac6efbSJulian Elischer   int maj = major(dev);
8053ac6efbSJulian Elischer /*            path	name		major   minor	type   uid gid perm*/
8153ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"mem",	maj,    0,	DV_CHR, 0,  2, 0640);
8253ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"kmem",	maj,    1,	DV_CHR, 0,  2, 0640);
8353ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"null",	maj,    2,	DV_CHR, 0,  0, 0666);
8453ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"random", maj,  3,	DV_CHR, 0,  0, 0666);
8553ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"urandom", maj, 4,	DV_CHR, 0,  0, 0666);
8653ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"zero",	maj,    12,	DV_CHR, 0,  0, 0666);
8753ac6efbSJulian Elischer    x=devfs_add_devsw("/misc",	"io",	maj,    14,	DV_CHR, 0,  2, 0640);
888af5d536SJulian Elischer }
898af5d536SJulian Elischer #endif /* DEVFS */
908af5d536SJulian Elischer 
9126f9a767SRodney W. Grimes extern        char *ptvmmap;            /* poor name! */
9233f538b9SBruce Evans 
93381fe1aaSGarrett Wollman int
9460039670SBruce Evans mmclose(dev, flags, fmt, p)
9578d172caSRodney W. Grimes 	dev_t dev;
9678d172caSRodney W. Grimes 	int flags;
9760039670SBruce Evans 	int fmt;
9860039670SBruce Evans 	struct proc *p;
9978d172caSRodney W. Grimes {
100c8a13ecdSDavid Greenman 	struct trapframe *fp;
10178d172caSRodney W. Grimes 
10278d172caSRodney W. Grimes 	switch (minor(dev)) {
10378d172caSRodney W. Grimes 	case 14:
10426f9a767SRodney W. Grimes 		fp = (struct trapframe *)curproc->p_md.md_regs;
105c8a13ecdSDavid Greenman 		fp->tf_eflags &= ~PSL_IOPL;
10678d172caSRodney W. Grimes 		break;
10778d172caSRodney W. Grimes 	default:
10878d172caSRodney W. Grimes 		break;
10978d172caSRodney W. Grimes 	}
11078d172caSRodney W. Grimes 	return(0);
11178d172caSRodney W. Grimes }
11233f538b9SBruce Evans 
113381fe1aaSGarrett Wollman int
11460039670SBruce Evans mmopen(dev, flags, fmt, p)
11578d172caSRodney W. Grimes 	dev_t dev;
11678d172caSRodney W. Grimes 	int flags;
11760039670SBruce Evans 	int fmt;
11860039670SBruce Evans 	struct proc *p;
11978d172caSRodney W. Grimes {
120c8a13ecdSDavid Greenman 	struct trapframe *fp;
12178d172caSRodney W. Grimes 
12278d172caSRodney W. Grimes 	switch (minor(dev)) {
12378d172caSRodney W. Grimes 	case 14:
12426f9a767SRodney W. Grimes 		fp = (struct trapframe *)curproc->p_md.md_regs;
125c8a13ecdSDavid Greenman 		fp->tf_eflags |= PSL_IOPL;
12678d172caSRodney W. Grimes 		break;
12778d172caSRodney W. Grimes 	default:
12878d172caSRodney W. Grimes 		break;
12978d172caSRodney W. Grimes 	}
13078d172caSRodney W. Grimes 	return(0);
13178d172caSRodney W. Grimes }
13233f538b9SBruce Evans 
133381fe1aaSGarrett Wollman int
1345b81b6b3SRodney W. Grimes mmrw(dev, uio, flags)
1355b81b6b3SRodney W. Grimes 	dev_t dev;
1365b81b6b3SRodney W. Grimes 	struct uio *uio;
1375b81b6b3SRodney W. Grimes 	int flags;
1385b81b6b3SRodney W. Grimes {
1395b81b6b3SRodney W. Grimes 	register int o;
1405b81b6b3SRodney W. Grimes 	register u_int c, v;
1411bb2d314SMark Murray 	u_int poolsize;
1425b81b6b3SRodney W. Grimes 	register struct iovec *iov;
1435b81b6b3SRodney W. Grimes 	int error = 0;
1441bb2d314SMark Murray 	caddr_t buf = NULL;
1455b81b6b3SRodney W. Grimes 
1465b81b6b3SRodney W. Grimes 	while (uio->uio_resid > 0 && error == 0) {
1475b81b6b3SRodney W. Grimes 		iov = uio->uio_iov;
1485b81b6b3SRodney W. Grimes 		if (iov->iov_len == 0) {
1495b81b6b3SRodney W. Grimes 			uio->uio_iov++;
1505b81b6b3SRodney W. Grimes 			uio->uio_iovcnt--;
1515b81b6b3SRodney W. Grimes 			if (uio->uio_iovcnt < 0)
1525b81b6b3SRodney W. Grimes 				panic("mmrw");
1535b81b6b3SRodney W. Grimes 			continue;
1545b81b6b3SRodney W. Grimes 		}
1555b81b6b3SRodney W. Grimes 		switch (minor(dev)) {
1565b81b6b3SRodney W. Grimes 
1575b81b6b3SRodney W. Grimes /* minor device 0 is physical memory */
1585b81b6b3SRodney W. Grimes 		case 0:
1595b81b6b3SRodney W. Grimes 			v = uio->uio_offset;
16026f9a767SRodney W. Grimes 			pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v,
1615b81b6b3SRodney W. Grimes 				uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE,
1625b81b6b3SRodney W. Grimes 				TRUE);
1635b81b6b3SRodney W. Grimes 			o = (int)uio->uio_offset & PGOFSET;
1645b81b6b3SRodney W. Grimes 			c = (u_int)(NBPG - ((int)iov->iov_base & PGOFSET));
16526f9a767SRodney W. Grimes 			c = min(c, (u_int)(NBPG - o));
16626f9a767SRodney W. Grimes 			c = min(c, (u_int)iov->iov_len);
16726f9a767SRodney W. Grimes 			error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio);
16826f9a767SRodney W. Grimes 			pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap,
16926f9a767SRodney W. Grimes 				    (vm_offset_t)&ptvmmap[NBPG]);
1705b81b6b3SRodney W. Grimes 			continue;
1715b81b6b3SRodney W. Grimes 
1725b81b6b3SRodney W. Grimes /* minor device 1 is kernel memory */
17397e11262SDavid Greenman 		case 1: {
17497e11262SDavid Greenman 			vm_offset_t addr, eaddr;
1755b81b6b3SRodney W. Grimes 			c = iov->iov_len;
17697e11262SDavid Greenman 
17797e11262SDavid Greenman 			/*
17897e11262SDavid Greenman 			 * Make sure that all of the pages are currently resident so
17997e11262SDavid Greenman 			 * that we don't create any zero-fill pages.
18097e11262SDavid Greenman 			 */
18197e11262SDavid Greenman 			addr = trunc_page(uio->uio_offset);
1820704324aSDavid Greenman 			eaddr = round_page(uio->uio_offset + c);
18397e11262SDavid Greenman 			for (; addr < eaddr; addr += PAGE_SIZE)
18497e11262SDavid Greenman 				if (pmap_extract(kernel_pmap, addr) == 0)
18597e11262SDavid Greenman 					return EFAULT;
18697e11262SDavid Greenman 
18726f9a767SRodney W. Grimes 			if (!kernacc((caddr_t)(int)uio->uio_offset, c,
1885b81b6b3SRodney W. Grimes 			    uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
1895b81b6b3SRodney W. Grimes 				return(EFAULT);
19026f9a767SRodney W. Grimes 			error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
1915b81b6b3SRodney W. Grimes 			continue;
19297e11262SDavid Greenman 		}
1935b81b6b3SRodney W. Grimes 
1945b81b6b3SRodney W. Grimes /* minor device 2 is EOF/RATHOLE */
1955b81b6b3SRodney W. Grimes 		case 2:
1965b81b6b3SRodney W. Grimes 			if (uio->uio_rw == UIO_READ)
1975b81b6b3SRodney W. Grimes 				return (0);
1985b81b6b3SRodney W. Grimes 			c = iov->iov_len;
1995b81b6b3SRodney W. Grimes 			break;
2005b81b6b3SRodney W. Grimes 
2011bb2d314SMark Murray /* minor device 3 (/dev/random) is source of filth on read, rathole on write */
2021bb2d314SMark Murray 		case 3:
2031bb2d314SMark Murray 			if (uio->uio_rw == UIO_WRITE) {
2041bb2d314SMark Murray 				c = iov->iov_len;
2051bb2d314SMark Murray 				break;
2061bb2d314SMark Murray 			}
2071bb2d314SMark Murray 			if (buf == NULL)
2081bb2d314SMark Murray 				buf = (caddr_t)
2091bb2d314SMark Murray 				    malloc(CLBYTES, M_TEMP, M_WAITOK);
2101bb2d314SMark Murray 			c = min(iov->iov_len, CLBYTES);
2111bb2d314SMark Murray 			poolsize = read_random(buf, c);
2121bb2d314SMark Murray 			if (poolsize == 0) {
2131bb2d314SMark Murray 				if (buf)
2141bb2d314SMark Murray 					free(buf, M_TEMP);
2151bb2d314SMark Murray 				return (0);
2161bb2d314SMark Murray 			}
2171bb2d314SMark Murray 			c = min(c, poolsize);
2181bb2d314SMark Murray 			error = uiomove(buf, (int)c, uio);
2191bb2d314SMark Murray 			continue;
2201bb2d314SMark Murray 
2211bb2d314SMark Murray /* minor device 4 (/dev/urandom) is source of muck on read, rathole on write */
2221bb2d314SMark Murray 		case 4:
2231bb2d314SMark Murray 			if (uio->uio_rw == UIO_WRITE) {
2241bb2d314SMark Murray 				c = iov->iov_len;
2251bb2d314SMark Murray 				break;
2261bb2d314SMark Murray 			}
2271bb2d314SMark Murray 			if (buf == NULL)
2281bb2d314SMark Murray 				buf = (caddr_t)
2291bb2d314SMark Murray 				    malloc(CLBYTES, M_TEMP, M_WAITOK);
2301bb2d314SMark Murray 			c = min(iov->iov_len, CLBYTES);
2311bb2d314SMark Murray 			poolsize = read_random_unlimited(buf, c);
2321bb2d314SMark Murray 			c = min(c, poolsize);
2331bb2d314SMark Murray 			error = uiomove(buf, (int)c, uio);
2341bb2d314SMark Murray 			continue;
2351bb2d314SMark Murray 
2365b81b6b3SRodney W. Grimes /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
2375b81b6b3SRodney W. Grimes 		case 12:
2385b81b6b3SRodney W. Grimes 			if (uio->uio_rw == UIO_WRITE) {
2395b81b6b3SRodney W. Grimes 				c = iov->iov_len;
2405b81b6b3SRodney W. Grimes 				break;
2415b81b6b3SRodney W. Grimes 			}
2421bb2d314SMark Murray 			if (buf == NULL) {
2431bb2d314SMark Murray 				buf = (caddr_t)
2445b81b6b3SRodney W. Grimes 				    malloc(CLBYTES, M_TEMP, M_WAITOK);
2451bb2d314SMark Murray 				bzero(buf, CLBYTES);
2465b81b6b3SRodney W. Grimes 			}
24726f9a767SRodney W. Grimes 			c = min(iov->iov_len, CLBYTES);
2481bb2d314SMark Murray 			error = uiomove(buf, (int)c, uio);
2495b81b6b3SRodney W. Grimes 			continue;
2505b81b6b3SRodney W. Grimes 
2515b81b6b3SRodney W. Grimes #ifdef notyet
2525b81b6b3SRodney W. Grimes /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate
2535b81b6b3SRodney W. Grimes    i/o device address bus, different than memory bus. Semantics here are
2545b81b6b3SRodney W. Grimes    very different than ordinary read/write, as if iov_len is a multiple
2555b81b6b3SRodney W. Grimes    an implied string move from a single port will be done. Note that lseek
2565b81b6b3SRodney W. Grimes    must be used to set the port number reliably. */
2575b81b6b3SRodney W. Grimes 		case 14:
2585b81b6b3SRodney W. Grimes 			if (iov->iov_len == 1) {
2595b81b6b3SRodney W. Grimes 				u_char tmp;
2605b81b6b3SRodney W. Grimes 				tmp = inb(uio->uio_offset);
2615b81b6b3SRodney W. Grimes 				error = uiomove (&tmp, iov->iov_len, uio);
2625b81b6b3SRodney W. Grimes 			} else {
2635b81b6b3SRodney W. Grimes 				if (!useracc((caddr_t)iov->iov_base,
2645b81b6b3SRodney W. Grimes 					iov->iov_len, uio->uio_rw))
2655b81b6b3SRodney W. Grimes 					return (EFAULT);
2665b81b6b3SRodney W. Grimes 				insb(uio->uio_offset, iov->iov_base,
2675b81b6b3SRodney W. Grimes 					iov->iov_len);
2685b81b6b3SRodney W. Grimes 			}
2695b81b6b3SRodney W. Grimes 			break;
2705b81b6b3SRodney W. Grimes 		case 15:
2715b81b6b3SRodney W. Grimes 			if (iov->iov_len == sizeof (short)) {
2725b81b6b3SRodney W. Grimes 				u_short tmp;
2735b81b6b3SRodney W. Grimes 				tmp = inw(uio->uio_offset);
2745b81b6b3SRodney W. Grimes 				error = uiomove (&tmp, iov->iov_len, uio);
2755b81b6b3SRodney W. Grimes 			} else {
2765b81b6b3SRodney W. Grimes 				if (!useracc((caddr_t)iov->iov_base,
2775b81b6b3SRodney W. Grimes 					iov->iov_len, uio->uio_rw))
2785b81b6b3SRodney W. Grimes 					return (EFAULT);
2795b81b6b3SRodney W. Grimes 				insw(uio->uio_offset, iov->iov_base,
2805b81b6b3SRodney W. Grimes 					iov->iov_len/ sizeof (short));
2815b81b6b3SRodney W. Grimes 			}
2825b81b6b3SRodney W. Grimes 			break;
2835b81b6b3SRodney W. Grimes 		case 16:
2845b81b6b3SRodney W. Grimes 			if (iov->iov_len == sizeof (long)) {
2855b81b6b3SRodney W. Grimes 				u_long tmp;
2865b81b6b3SRodney W. Grimes 				tmp = inl(uio->uio_offset);
2875b81b6b3SRodney W. Grimes 				error = uiomove (&tmp, iov->iov_len, uio);
2885b81b6b3SRodney W. Grimes 			} else {
2895b81b6b3SRodney W. Grimes 				if (!useracc((caddr_t)iov->iov_base,
2905b81b6b3SRodney W. Grimes 					iov->iov_len, uio->uio_rw))
2915b81b6b3SRodney W. Grimes 					return (EFAULT);
2925b81b6b3SRodney W. Grimes 				insl(uio->uio_offset, iov->iov_base,
2935b81b6b3SRodney W. Grimes 					iov->iov_len/ sizeof (long));
2945b81b6b3SRodney W. Grimes 			}
2955b81b6b3SRodney W. Grimes 			break;
2965b81b6b3SRodney W. Grimes #endif
2975b81b6b3SRodney W. Grimes 
2985b81b6b3SRodney W. Grimes 		default:
2995b81b6b3SRodney W. Grimes 			return (ENXIO);
3005b81b6b3SRodney W. Grimes 		}
3015b81b6b3SRodney W. Grimes 		if (error)
3025b81b6b3SRodney W. Grimes 			break;
3035b81b6b3SRodney W. Grimes 		iov->iov_base += c;
3045b81b6b3SRodney W. Grimes 		iov->iov_len -= c;
3055b81b6b3SRodney W. Grimes 		uio->uio_offset += c;
3065b81b6b3SRodney W. Grimes 		uio->uio_resid -= c;
3075b81b6b3SRodney W. Grimes 	}
3081bb2d314SMark Murray 	if (buf)
3091bb2d314SMark Murray 		free(buf, M_TEMP);
3105b81b6b3SRodney W. Grimes 	return (error);
3115b81b6b3SRodney W. Grimes }
312b513c262SDavid Greenman 
313b513c262SDavid Greenman 
314b513c262SDavid Greenman 
315b513c262SDavid Greenman 
316b513c262SDavid Greenman /*******************************************************\
317b513c262SDavid Greenman * allow user processes to MMAP some memory sections	*
318b513c262SDavid Greenman * instead of going through read/write			*
319b513c262SDavid Greenman \*******************************************************/
320b513c262SDavid Greenman int memmmap(dev_t dev, int offset, int nprot)
321b513c262SDavid Greenman {
322b513c262SDavid Greenman 	switch (minor(dev))
323b513c262SDavid Greenman 	{
324b513c262SDavid Greenman 
325b513c262SDavid Greenman /* minor device 0 is physical memory */
326b513c262SDavid Greenman 	case 0:
327b513c262SDavid Greenman         	return i386_btop(offset);
328b513c262SDavid Greenman 
329b513c262SDavid Greenman /* minor device 1 is kernel memory */
330b513c262SDavid Greenman 	case 1:
331b513c262SDavid Greenman         	return i386_btop(vtophys(offset));
332b513c262SDavid Greenman 
333b513c262SDavid Greenman 	default:
334b513c262SDavid Greenman 		return -1;
335b513c262SDavid Greenman 	}
336b513c262SDavid Greenman }
337b513c262SDavid Greenman 
3381bb2d314SMark Murray /*
3391bb2d314SMark Murray  * Allow userland to select which interrupts will be used in the muck
3401bb2d314SMark Murray  * gathering business.
3411bb2d314SMark Murray  */
3421bb2d314SMark Murray int
34300f7f6beSBruce Evans mmioctl(dev, cmd, cmdarg, flags, p)
34400f7f6beSBruce Evans 	dev_t dev;
34500f7f6beSBruce Evans 	int cmd;
34600f7f6beSBruce Evans 	caddr_t cmdarg;
34700f7f6beSBruce Evans 	int flags;
34800f7f6beSBruce Evans 	struct proc *p;
3491bb2d314SMark Murray {
350a0135d7eSMark Murray 	int error;
351a0135d7eSMark Murray 
3521bb2d314SMark Murray 	if (minor(dev) != 3 && minor(dev) != 4)
3531bb2d314SMark Murray 		return (ENODEV);
3541bb2d314SMark Murray 
3551bb2d314SMark Murray 	if (*(u_int16_t *)cmdarg >= 16)
3561bb2d314SMark Murray 		return (EINVAL);
3571bb2d314SMark Murray 
358a0135d7eSMark Murray 	/* Only root can do this */
359a0135d7eSMark Murray 	error = suser(p->p_ucred, &p->p_acflag);
360a0135d7eSMark Murray 	if (error != 0) {
361a0135d7eSMark Murray 		return (error);
362a0135d7eSMark Murray 	}
363a0135d7eSMark Murray 
3641bb2d314SMark Murray 	switch (cmd){
3651bb2d314SMark Murray 
3661bb2d314SMark Murray 		case MEM_SETIRQ:
3671bb2d314SMark Murray 			interrupt_allowed |= 1 << *(u_int16_t *)cmdarg;
3681bb2d314SMark Murray 			break;
3691bb2d314SMark Murray 
3701bb2d314SMark Murray 		case MEM_CLEARIRQ:
3711bb2d314SMark Murray 			interrupt_allowed &= ~(1 << *(u_int16_t *)cmdarg);
3721bb2d314SMark Murray 			break;
3731bb2d314SMark Murray 
3741bb2d314SMark Murray 		case MEM_RETURNIRQ:
3751bb2d314SMark Murray 			*(u_int16_t *)cmdarg = interrupt_allowed;
3761bb2d314SMark Murray 			break;
3771bb2d314SMark Murray 
3781bb2d314SMark Murray 		default:
3791bb2d314SMark Murray 			return (ENOTTY);
3801bb2d314SMark Murray 	}
3811bb2d314SMark Murray 	return (0);
38200f7f6beSBruce Evans }
38353ac6efbSJulian Elischer 
38453ac6efbSJulian Elischer 
38553ac6efbSJulian Elischer 
38653ac6efbSJulian Elischer #ifdef JREMOD
38753ac6efbSJulian Elischer struct cdevsw mem_cdevsw =
38853ac6efbSJulian Elischer 	{ mmopen,	mmclose,	mmrw,		mmrw,		/*2*/
38953ac6efbSJulian Elischer 	  mmioctl,	nullstop,	nullreset,	nodevtotty,/* memory */
39053ac6efbSJulian Elischer 	  seltrue,	memmmap,	NULL };
39153ac6efbSJulian Elischer 
39253ac6efbSJulian Elischer static mem_devsw_installed = 0;
39353ac6efbSJulian Elischer 
39453ac6efbSJulian Elischer static void 	mem_drvinit(void *unused)
39553ac6efbSJulian Elischer {
39653ac6efbSJulian Elischer 	dev_t dev;
39753ac6efbSJulian Elischer 
39853ac6efbSJulian Elischer 	if( ! mem_devsw_installed ) {
39953ac6efbSJulian Elischer 		dev = makedev(CDEV_MAJOR,0);
40053ac6efbSJulian Elischer 		cdevsw_add(&dev,&mem_cdevsw,NULL);
40153ac6efbSJulian Elischer 		mem_devsw_installed = 1;
40253ac6efbSJulian Elischer #ifdef DEVFS
40353ac6efbSJulian Elischer 		memdevfs_init(dev);
40453ac6efbSJulian Elischer #endif
40553ac6efbSJulian Elischer 	}
4067198bf47SJulian Elischer }
40753ac6efbSJulian Elischer 
40853ac6efbSJulian Elischer SYSINIT(memdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mem_drvinit,NULL)
40953ac6efbSJulian Elischer 
41053ac6efbSJulian Elischer #endif /* JREMOD */
41153ac6efbSJulian Elischer 
412