The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/mem.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    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  * $FreeBSD$
   42  */
   43 
   44 /*
   45  * Memory special file
   46  */
   47 
   48 #include "opt_devfs.h"
   49 #include "opt_perfmon.h"
   50 
   51 #include <sys/param.h>
   52 #include <sys/conf.h>
   53 #include <sys/buf.h>
   54 #ifdef DEVFS
   55 #include <sys/devfsext.h>
   56 #endif /* DEVFS */
   57 #include <sys/kernel.h>
   58 #include <sys/systm.h>
   59 #include <sys/uio.h>
   60 #include <sys/malloc.h>
   61 #include <sys/memrange.h>
   62 #include <sys/proc.h>
   63 #include <sys/signalvar.h>
   64 
   65 #include <machine/frame.h>
   66 #include <machine/random.h>
   67 #include <machine/psl.h>
   68 #ifdef PERFMON
   69 #include <machine/perfmon.h>
   70 #endif
   71 #include <i386/isa/intr_machdep.h>
   72 
   73 #include <vm/vm.h>
   74 #include <vm/vm_prot.h>
   75 #include <vm/pmap.h>
   76 #include <vm/vm_extern.h>
   77 
   78 
   79 
   80 static  d_open_t        mmopen;
   81 static  d_close_t       mmclose;
   82 static  d_read_t        mmrw;
   83 static  d_ioctl_t       mmioctl;
   84 static  d_mmap_t        memmmap;
   85 static  d_poll_t        mmpoll;
   86 
   87 #define CDEV_MAJOR 2
   88 static struct cdevsw mem_cdevsw = 
   89         { mmopen,       mmclose,        mmrw,           mmrw,           /*2*/
   90           mmioctl,      nullstop,       nullreset,      nodevtotty,/* memory */
   91           mmpoll,       memmmap,        NULL,   "mem",  NULL, -1 };
   92 
   93 static struct random_softc random_softc[16];
   94 static caddr_t  zbuf;
   95 
   96 MALLOC_DEFINE(M_MEMDESC, "memdesc", "memory range descriptors");
   97 static int mem_ioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
   98 static int random_ioctl __P((dev_t, u_long, caddr_t, int, struct proc *));
   99 
  100 struct mem_range_softc mem_range_softc;
  101 
  102 #ifdef DEVFS
  103 static void *mem_devfs_token;
  104 static void *kmem_devfs_token;
  105 static void *null_devfs_token;
  106 static void *random_devfs_token;
  107 static void *urandom_devfs_token;
  108 static void *zero_devfs_token;
  109 static void *io_devfs_token;
  110 #ifdef PERFMON
  111 static void *perfmon_devfs_token;
  112 #endif
  113 
  114 static void memdevfs_init __P((void));
  115 
  116 static void 
  117 memdevfs_init()
  118 {
  119     mem_devfs_token = 
  120         devfs_add_devswf(&mem_cdevsw, 0, DV_CHR, 
  121                          UID_ROOT, GID_KMEM, 0640, "mem");
  122     kmem_devfs_token = 
  123         devfs_add_devswf(&mem_cdevsw, 1, DV_CHR,
  124                          UID_ROOT, GID_KMEM, 0640, "kmem");
  125     null_devfs_token = 
  126         devfs_add_devswf(&mem_cdevsw, 2, DV_CHR, 
  127                          UID_ROOT, GID_WHEEL, 0666, "null");
  128     random_devfs_token = 
  129         devfs_add_devswf(&mem_cdevsw, 3, DV_CHR, 
  130                          UID_ROOT, GID_WHEEL, 0644, "random");
  131     urandom_devfs_token = 
  132         devfs_add_devswf(&mem_cdevsw, 4, DV_CHR, 
  133                          UID_ROOT, GID_WHEEL, 0644, "urandom");
  134     zero_devfs_token = 
  135         devfs_add_devswf(&mem_cdevsw, 12, DV_CHR, 
  136                          UID_ROOT, GID_WHEEL, 0666, "zero");
  137     io_devfs_token = 
  138         devfs_add_devswf(&mem_cdevsw, 14, DV_CHR, 
  139                          UID_ROOT, GID_WHEEL, 0600, "io");
  140 #ifdef PERFMON
  141     perfmon_devfs_token = 
  142         devfs_add_devswf(&mem_cdevsw, 32, DV_CHR, 
  143                          UID_ROOT, GID_KMEM, 0640, "perfmon");
  144 #endif /* PERFMON */
  145 }
  146 #endif /* DEVFS */
  147 
  148 static int
  149 mmclose(dev, flags, fmt, p)
  150         dev_t dev;
  151         int flags;
  152         int fmt;
  153         struct proc *p;
  154 {
  155         switch (minor(dev)) {
  156 #ifdef PERFMON
  157         case 32:
  158                 return perfmon_close(dev, flags, fmt, p);
  159 #endif
  160         case 14:
  161                 curproc->p_md.md_regs->tf_eflags &= ~PSL_IOPL;
  162                 break;
  163         default:
  164                 break;
  165         }
  166         return(0);
  167 }
  168 
  169 static int
  170 mmopen(dev, flags, fmt, p)
  171         dev_t dev;
  172         int flags;
  173         int fmt;
  174         struct proc *p;
  175 {
  176         int error;
  177 
  178         switch (minor(dev)) {
  179         case 32:
  180 #ifdef PERFMON
  181                 return perfmon_open(dev, flags, fmt, p);
  182 #else
  183                 return ENODEV;
  184 #endif
  185         case 14:
  186                 error = suser(p->p_ucred, &p->p_acflag);
  187                 if (error != 0)
  188                         return (error);
  189                 if (securelevel > 0)
  190                         return (EPERM);
  191                 curproc->p_md.md_regs->tf_eflags |= PSL_IOPL;
  192                 break;
  193         default:
  194                 break;
  195         }
  196         return(0);
  197 }
  198 
  199 static int
  200 mmrw(dev, uio, flags)
  201         dev_t dev;
  202         struct uio *uio;
  203         int flags;
  204 {
  205         register int o;
  206         register u_int c, v;
  207         u_int poolsize;
  208         register struct iovec *iov;
  209         int error = 0;
  210         caddr_t buf = NULL;
  211 
  212         while (uio->uio_resid > 0 && error == 0) {
  213                 iov = uio->uio_iov;
  214                 if (iov->iov_len == 0) {
  215                         uio->uio_iov++;
  216                         uio->uio_iovcnt--;
  217                         if (uio->uio_iovcnt < 0)
  218                                 panic("mmrw");
  219                         continue;
  220                 }
  221                 switch (minor(dev)) {
  222 
  223 /* minor device 0 is physical memory */
  224                 case 0:
  225                         v = uio->uio_offset;
  226                         pmap_enter(kernel_pmap, (vm_offset_t)ptvmmap, v,
  227                                 uio->uio_rw == UIO_READ ? VM_PROT_READ : VM_PROT_WRITE,
  228                                 TRUE);
  229                         o = (int)uio->uio_offset & PAGE_MASK;
  230                         c = (u_int)(PAGE_SIZE - ((int)iov->iov_base & PAGE_MASK));
  231                         c = min(c, (u_int)(PAGE_SIZE - o));
  232                         c = min(c, (u_int)iov->iov_len);
  233                         error = uiomove((caddr_t)&ptvmmap[o], (int)c, uio);
  234                         pmap_remove(kernel_pmap, (vm_offset_t)ptvmmap,
  235                                     (vm_offset_t)&ptvmmap[PAGE_SIZE]);
  236                         continue;
  237 
  238 /* minor device 1 is kernel memory */
  239                 case 1: {
  240                         vm_offset_t addr, eaddr;
  241                         c = iov->iov_len;
  242 
  243                         /*
  244                          * Make sure that all of the pages are currently resident so
  245                          * that we don't create any zero-fill pages.
  246                          */
  247                         addr = trunc_page(uio->uio_offset);
  248                         eaddr = round_page(uio->uio_offset + c);
  249 
  250                         if (addr < (vm_offset_t)VADDR(PTDPTDI, 0))
  251                                 return EFAULT;
  252                         if (eaddr >= (vm_offset_t)VADDR(APTDPTDI, 0))
  253                                 return EFAULT;
  254                         for (; addr < eaddr; addr += PAGE_SIZE) 
  255                                 if (pmap_extract(kernel_pmap, addr) == 0)
  256                                         return EFAULT;
  257                         
  258                         if (!kernacc((caddr_t)(int)uio->uio_offset, c,
  259                             uio->uio_rw == UIO_READ ? B_READ : B_WRITE))
  260                                 return(EFAULT);
  261                         error = uiomove((caddr_t)(int)uio->uio_offset, (int)c, uio);
  262                         continue;
  263                 }
  264 
  265 /* minor device 2 is EOF/RATHOLE */
  266                 case 2:
  267                         if (uio->uio_rw == UIO_READ)
  268                                 return (0);
  269                         c = iov->iov_len;
  270                         break;
  271 
  272 /* minor device 3 (/dev/random) is source of filth on read, rathole on write */
  273                 case 3:
  274                         if (uio->uio_rw == UIO_WRITE) {
  275                                 c = iov->iov_len;
  276                                 break;
  277                         }
  278                         if (buf == NULL)
  279                                 buf = (caddr_t)
  280                                     malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  281                         c = min(iov->iov_len, PAGE_SIZE);
  282                         poolsize = read_random(buf, c);
  283                         if (poolsize == 0) {
  284                                 if (buf)
  285                                         free(buf, M_TEMP);
  286                                 return (0);
  287                         }
  288                         c = min(c, poolsize);
  289                         error = uiomove(buf, (int)c, uio);
  290                         continue;
  291 
  292 /* minor device 4 (/dev/urandom) is source of muck on read, rathole on write */
  293                 case 4:
  294                         if (uio->uio_rw == UIO_WRITE) {
  295                                 c = iov->iov_len;
  296                                 break;
  297                         }
  298                         if (CURSIG(curproc) != 0) {
  299                                 /*
  300                                  * Use tsleep() to get the error code right.
  301                                  * It should return immediately.
  302                                  */
  303                                 error = tsleep(&random_softc[0],
  304                                     PZERO | PCATCH, "urand", 1);
  305                                 if (error != 0 && error != EWOULDBLOCK)
  306                                         continue;
  307                         }
  308                         if (buf == NULL)
  309                                 buf = (caddr_t)
  310                                     malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  311                         c = min(iov->iov_len, PAGE_SIZE);
  312                         poolsize = read_random_unlimited(buf, c);
  313                         c = min(c, poolsize);
  314                         error = uiomove(buf, (int)c, uio);
  315                         continue;
  316 
  317 /* minor device 12 (/dev/zero) is source of nulls on read, rathole on write */
  318                 case 12:
  319                         if (uio->uio_rw == UIO_WRITE) {
  320                                 c = iov->iov_len;
  321                                 break;
  322                         }
  323                         if (zbuf == NULL) {
  324                                 zbuf = (caddr_t)
  325                                     malloc(PAGE_SIZE, M_TEMP, M_WAITOK);
  326                                 bzero(zbuf, PAGE_SIZE);
  327                         }
  328                         c = min(iov->iov_len, PAGE_SIZE);
  329                         error = uiomove(zbuf, (int)c, uio);
  330                         continue;
  331 
  332 #ifdef notyet
  333 /* 386 I/O address space (/dev/ioport[bwl]) is a read/write access to seperate
  334    i/o device address bus, different than memory bus. Semantics here are
  335    very different than ordinary read/write, as if iov_len is a multiple
  336    an implied string move from a single port will be done. Note that lseek
  337    must be used to set the port number reliably. */
  338                 case 14:
  339                         if (iov->iov_len == 1) {
  340                                 u_char tmp;
  341                                 tmp = inb(uio->uio_offset);
  342                                 error = uiomove (&tmp, iov->iov_len, uio);
  343                         } else {
  344                                 if (!useracc((caddr_t)iov->iov_base,
  345                                         iov->iov_len, uio->uio_rw))
  346                                         return (EFAULT);
  347                                 insb(uio->uio_offset, iov->iov_base,
  348                                         iov->iov_len);
  349                         }
  350                         break;
  351                 case 15:
  352                         if (iov->iov_len == sizeof (short)) {
  353                                 u_short tmp;
  354                                 tmp = inw(uio->uio_offset);
  355                                 error = uiomove (&tmp, iov->iov_len, uio);
  356                         } else {
  357                                 if (!useracc((caddr_t)iov->iov_base,
  358                                         iov->iov_len, uio->uio_rw))
  359                                         return (EFAULT);
  360                                 insw(uio->uio_offset, iov->iov_base,
  361                                         iov->iov_len/ sizeof (short));
  362                         }
  363                         break;
  364                 case 16:
  365                         if (iov->iov_len == sizeof (long)) {
  366                                 u_long tmp;
  367                                 tmp = inl(uio->uio_offset);
  368                                 error = uiomove (&tmp, iov->iov_len, uio);
  369                         } else {
  370                                 if (!useracc((caddr_t)iov->iov_base,
  371                                         iov->iov_len, uio->uio_rw))
  372                                         return (EFAULT);
  373                                 insl(uio->uio_offset, iov->iov_base,
  374                                         iov->iov_len/ sizeof (long));
  375                         }
  376                         break;
  377 #endif
  378 
  379                 default:
  380                         return (ENXIO);
  381                 }
  382                 if (error)
  383                         break;
  384                 iov->iov_base += c;
  385                 iov->iov_len -= c;
  386                 uio->uio_offset += c;
  387                 uio->uio_resid -= c;
  388         }
  389         if (buf)
  390                 free(buf, M_TEMP);
  391         return (error);
  392 }
  393 
  394 
  395 
  396 
  397 /*******************************************************\
  398 * allow user processes to MMAP some memory sections     *
  399 * instead of going through read/write                   *
  400 \*******************************************************/
  401 static int
  402 memmmap(dev_t dev, vm_offset_t offset, int nprot)
  403 {
  404         switch (minor(dev))
  405         {
  406 
  407 /* minor device 0 is physical memory */
  408         case 0:
  409                 return i386_btop(offset);
  410 
  411 /* minor device 1 is kernel memory */
  412         case 1:
  413                 return i386_btop(vtophys(offset));
  414 
  415         default:
  416                 return -1;
  417         }
  418 }
  419 
  420 static int
  421 mmioctl(dev, cmd, data, flags, p)
  422         dev_t dev;
  423         u_long cmd;
  424         caddr_t data;
  425         int flags;
  426         struct proc *p;
  427 {
  428         switch (minor(dev)) {
  429         case 0:
  430                 return mem_ioctl(dev, cmd, data, flags, p);
  431         case 3:
  432         case 4:
  433                 return random_ioctl(dev, cmd, data, flags, p);
  434 #ifdef PERFMON
  435         case 32:
  436                 return perfmon_ioctl(dev, cmd, data, flags, p);
  437 #endif
  438         }
  439         return (ENODEV);
  440 }
  441 
  442 /*
  443  * Operations for changing memory attributes.
  444  *
  445  * This is basically just an ioctl shim for mem_range_attr_get
  446  * and mem_range_attr_set.
  447  */
  448 static int 
  449 mem_ioctl(dev, cmd, data, flags, p)
  450         dev_t dev;
  451         u_long cmd;
  452         caddr_t data;
  453         int flags;
  454         struct proc *p;
  455 {
  456         int nd, error = 0;
  457         struct mem_range_op *mo = (struct mem_range_op *)data;
  458         struct mem_range_desc *md;
  459         
  460         /* is this for us? */
  461         if ((cmd != MEMRANGE_GET) &&
  462             (cmd != MEMRANGE_SET))
  463                 return(ENODEV);
  464 
  465         /* any chance we can handle this? */
  466         if (mem_range_softc.mr_op == NULL)
  467                 return(EOPNOTSUPP);
  468 
  469         /* do we have any descriptors? */
  470         if (mem_range_softc.mr_ndesc == 0)
  471                 return(ENXIO);
  472 
  473         switch(cmd) {
  474         case MEMRANGE_GET:
  475                 nd = imin(mo->mo_arg[0], mem_range_softc.mr_ndesc);
  476                 if (nd > 0) {
  477                         md = (struct mem_range_desc *)
  478                                 malloc(nd * sizeof(struct mem_range_desc),
  479                                        M_MEMDESC, M_WAITOK);
  480                         error = mem_range_attr_get(md, &nd);
  481                         if (!error)
  482                                 error = copyout(md, mo->mo_desc, 
  483                                         nd * sizeof(struct mem_range_desc));
  484                         free(md, M_MEMDESC);
  485                 } else {
  486                         nd = mem_range_softc.mr_ndesc;
  487                 }
  488                 mo->mo_arg[0] = nd;
  489                 break;
  490                 
  491         case MEMRANGE_SET:
  492                 md = (struct mem_range_desc *)malloc(sizeof(struct mem_range_desc),
  493                                                     M_MEMDESC, M_WAITOK);
  494                 error = copyin(mo->mo_desc, md, sizeof(struct mem_range_desc));
  495                 /* clamp description string */
  496                 md->mr_owner[sizeof(md->mr_owner) - 1] = 0;
  497                 if (error == 0)
  498                         error = mem_range_attr_set(md, &mo->mo_arg[0]);
  499                 free(md, M_MEMDESC);
  500                 break;
  501             
  502         default:
  503                 error = EOPNOTSUPP;
  504         }
  505         return(error);
  506 }
  507 
  508 /*
  509  * Implementation-neutral, kernel-callable functions for manipulating
  510  * memory range attributes.
  511  */
  512 int
  513 mem_range_attr_get(mrd, arg)
  514         struct mem_range_desc *mrd;
  515         int *arg;
  516 {
  517         /* can we handle this? */
  518         if (mem_range_softc.mr_op == NULL)
  519                 return(EOPNOTSUPP);
  520 
  521         if (*arg == 0) {
  522                 *arg = mem_range_softc.mr_ndesc;
  523         } else {
  524                 bcopy(mem_range_softc.mr_desc, mrd, (*arg) * sizeof(struct mem_range_desc));
  525         }
  526         return(0);
  527 }
  528 
  529 int
  530 mem_range_attr_set(mrd, arg)
  531         struct mem_range_desc *mrd; 
  532         int *arg;
  533 {
  534         /* can we handle this? */
  535         if (mem_range_softc.mr_op == NULL)
  536                 return(EOPNOTSUPP);
  537 
  538         return(mem_range_softc.mr_op->set(&mem_range_softc, mrd, arg));
  539 }
  540 
  541 #ifdef SMP
  542 void
  543 mem_range_AP_init(void)
  544 {
  545         if (mem_range_softc.mr_op && mem_range_softc.mr_op->initAP)
  546                 return(mem_range_softc.mr_op->initAP(&mem_range_softc));
  547 }
  548 #endif
  549 
  550 static int 
  551 random_ioctl(dev, cmd, data, flags, p)
  552         dev_t dev;
  553         u_long cmd;
  554         caddr_t data;
  555         int flags;
  556         struct proc *p;
  557 {
  558         static intrmask_t interrupt_allowed;
  559         intrmask_t interrupt_mask;
  560         int error, intr;
  561         struct random_softc *sc;
  562 
  563         /*
  564          * We're the random or urandom device.  The only ioctls are for
  565          * selecting and inspecting which interrupts are used in the muck
  566          * gathering business.
  567          */
  568         if (cmd != MEM_SETIRQ && cmd != MEM_CLEARIRQ && cmd != MEM_RETURNIRQ)
  569                 return (ENOTTY);
  570 
  571         /*
  572          * Even inspecting the state is privileged, since it gives a hint
  573          * about how easily the randomness might be guessed.
  574          */
  575         error = suser(p->p_ucred, &p->p_acflag);
  576         if (error != 0)
  577                 return (error);
  578 
  579         /*
  580          * XXX the data is 16-bit due to a historical botch, so we use
  581          * magic 16's instead of ICU_LEN and can't support 24 interrupts
  582          * under SMP.
  583          */
  584         intr = *(int16_t *)data;
  585         if (cmd != MEM_RETURNIRQ && (intr < 0 || intr >= 16))
  586                 return (EINVAL);
  587 
  588         interrupt_mask = 1 << intr;
  589         sc = &random_softc[intr];
  590         switch (cmd) {
  591         case MEM_SETIRQ:
  592                 if (interrupt_allowed & interrupt_mask)
  593                         break;
  594                 interrupt_allowed |= interrupt_mask;
  595                 sc->sc_intr = intr;
  596                 disable_intr();
  597                 sc->sc_handler = intr_handler[intr];
  598                 intr_handler[intr] = add_interrupt_randomness;
  599                 sc->sc_arg = intr_unit[intr];
  600                 intr_unit[intr] = sc;
  601                 enable_intr();
  602                 break;
  603         case MEM_CLEARIRQ:
  604                 if (!(interrupt_allowed & interrupt_mask))
  605                         break;
  606                 interrupt_allowed &= ~interrupt_mask;
  607                 disable_intr();
  608                 intr_handler[intr] = sc->sc_handler;
  609                 intr_unit[intr] = sc->sc_arg;
  610                 enable_intr();
  611                 break;
  612         case MEM_RETURNIRQ:
  613                 *(u_int16_t *)data = interrupt_allowed;
  614                 break;
  615         default:
  616                 return (ENOTTY);
  617         }
  618         return (0);
  619 }
  620 
  621 int
  622 mmpoll(dev, events, p)
  623         dev_t dev;
  624         int events;
  625         struct proc *p;
  626 {
  627         switch (minor(dev)) {
  628         case 3:         /* /dev/random */
  629                 return random_poll(dev, events, p);
  630         case 4:         /* /dev/urandom */
  631         default:
  632                 return seltrue(dev, events, p);
  633         }
  634 }
  635 
  636 /*
  637  * Routine that identifies /dev/mem and /dev/kmem.
  638  *
  639  * A minimal stub routine can always return 0.
  640  */
  641 int
  642 iskmemdev(dev)
  643         dev_t dev;
  644 {
  645 
  646         return ((major(dev) == mem_cdevsw.d_maj)
  647               && (minor(dev) == 0 || minor(dev) == 1));
  648 }
  649 
  650 int
  651 iszerodev(dev)
  652         dev_t dev;
  653 {
  654         return ((major(dev) == mem_cdevsw.d_maj)
  655           && minor(dev) == 12);
  656 }
  657 
  658 
  659 
  660 static int mem_devsw_installed;
  661 
  662 static void
  663 mem_drvinit(void *unused)
  664 {
  665         dev_t dev;
  666 
  667         /* Initialise memory range handling */
  668         if (mem_range_softc.mr_op != NULL)
  669                 mem_range_softc.mr_op->init(&mem_range_softc);
  670 
  671         if( ! mem_devsw_installed ) {
  672                 dev = makedev(CDEV_MAJOR, 0);
  673                 cdevsw_add(&dev,&mem_cdevsw, NULL);
  674                 mem_devsw_installed = 1;
  675 #ifdef DEVFS
  676                 memdevfs_init();
  677 #endif
  678         }
  679 }
  680 
  681 SYSINIT(memdev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,mem_drvinit,NULL)
  682 

Cache object: df74b6826aab2ac4ce9b904904292d7a


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.