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/kern/kern_conf.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  * Parts Copyright (c) 1995 Terrence R. Lambert
    3  * Copyright (c) 1995 Julian R. Elischer
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 3. All advertising materials mentioning features or use of this software
   15  *    must display the following acknowledgement:
   16  *      This product includes software developed by Terrence R. Lambert.
   17  * 4. The name Terrence R. Lambert may not be used to endorse or promote
   18  *    products derived from this software without specific prior written
   19  *    permission.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY Julian R. Elischer ``AS IS'' AND ANY
   22  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE TERRENCE R. LAMBERT BE LIABLE
   25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   31  * SUCH DAMAGE.
   32  *
   33  * $FreeBSD$
   34  */
   35 
   36 #include <sys/param.h>
   37 #include <sys/kernel.h>
   38 #include <sys/sysctl.h>
   39 #include <sys/systm.h>
   40 #include <sys/module.h>
   41 #include <sys/malloc.h>
   42 #include <sys/conf.h>
   43 #include <sys/vnode.h>
   44 #include <sys/queue.h>
   45 #include <machine/stdarg.h>
   46 
   47 #define cdevsw_ALLOCSTART       (NUMCDEVSW/2)
   48 
   49 struct cdevsw   *cdevsw[NUMCDEVSW];
   50 
   51 static int      bmaj2cmaj[NUMCDEVSW];
   52 
   53 MALLOC_DEFINE(M_DEVT, "dev_t", "dev_t storage");
   54 
   55 /*
   56  * This is the number of hash-buckets.  Experiements with 'real-life'
   57  * udev_t's show that a prime halfway between two powers of two works
   58  * best.
   59  */
   60 #define DEVT_HASH 83
   61 
   62 /* The number of dev_t's we can create before malloc(9) kick in.  */
   63 #define DEVT_STASH 50
   64 
   65 static struct specinfo devt_stash[DEVT_STASH];
   66 
   67 static LIST_HEAD(, specinfo) dev_hash[DEVT_HASH];
   68 
   69 static LIST_HEAD(, specinfo) dev_free;
   70 
   71 static int free_devt;
   72 SYSCTL_INT(_debug, OID_AUTO, free_devt, CTLFLAG_RW, &free_devt, 0, "");
   73 
   74 struct cdevsw *
   75 devsw(dev_t dev)
   76 {
   77         if (dev->si_devsw)
   78                 return (dev->si_devsw);
   79         return(cdevsw[major(dev)]);
   80 }
   81 
   82 static void
   83 compile_devsw(struct cdevsw *devsw)
   84 {
   85         if (devsw->d_open == NULL)
   86                 devsw->d_open = noopen;
   87         if (devsw->d_close == NULL)
   88                 devsw->d_close = noclose;
   89         if (devsw->d_read == NULL)
   90                 devsw->d_read = noread;
   91         if (devsw->d_write == NULL)
   92                 devsw->d_write = nowrite;
   93         if (devsw->d_ioctl == NULL)
   94                 devsw->d_ioctl = noioctl;
   95         if (devsw->d_poll == NULL)
   96                 devsw->d_poll = nopoll;
   97         if (devsw->d_mmap == NULL)
   98                 devsw->d_mmap = nommap;
   99         if (devsw->d_strategy == NULL)
  100                 devsw->d_strategy = nostrategy;
  101         if (devsw->d_dump == NULL)
  102                 devsw->d_dump = nodump;
  103         if (devsw->d_psize == NULL)
  104                 devsw->d_psize = nopsize;
  105         if (devsw->d_kqfilter == NULL)
  106                 devsw->d_kqfilter = nokqfilter;
  107 }
  108 
  109 /*
  110  *  Add a cdevsw entry
  111  */
  112 
  113 int
  114 cdevsw_add(struct cdevsw *newentry)
  115 {
  116         int i;
  117         static int setup;
  118 
  119         if (!setup) {
  120                 for (i = 0; i < NUMCDEVSW; i++)
  121                         if (!bmaj2cmaj[i])
  122                                 bmaj2cmaj[i] = 254;
  123                 setup++;
  124         }
  125 
  126         compile_devsw(newentry);
  127         if (newentry->d_maj < 0 || newentry->d_maj >= NUMCDEVSW) {
  128                 printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
  129                     newentry->d_name, newentry->d_maj);
  130                 return (EINVAL);
  131         }
  132         if (newentry->d_bmaj >= NUMCDEVSW) {
  133                 printf("%s: ERROR: driver has bogus cdevsw->d_bmaj = %d\n",
  134                     newentry->d_name, newentry->d_bmaj);
  135                 return (EINVAL);
  136         }
  137         if (newentry->d_bmaj >= 0 && (newentry->d_flags & D_DISK) == 0) {
  138                 printf("ERROR: \"%s\" bmaj but is not a disk\n",
  139                     newentry->d_name);
  140                 return (EINVAL);
  141         }
  142 
  143         if (cdevsw[newentry->d_maj]) {
  144                 printf("WARNING: \"%s\" is usurping \"%s\"'s cdevsw[]\n",
  145                     newentry->d_name, cdevsw[newentry->d_maj]->d_name);
  146         }
  147 
  148         cdevsw[newentry->d_maj] = newentry;
  149 
  150         if (newentry->d_bmaj < 0)
  151                 return (0);
  152 
  153         if (bmaj2cmaj[newentry->d_bmaj] != 254) {
  154                 printf("WARNING: \"%s\" is usurping \"%s\"'s bmaj\n",
  155                     newentry->d_name,
  156                     cdevsw[bmaj2cmaj[newentry->d_bmaj]]->d_name);
  157         }
  158         bmaj2cmaj[newentry->d_bmaj] = newentry->d_maj;
  159         return (0);
  160 }
  161 
  162 /*
  163  *  Remove a cdevsw entry
  164  */
  165 
  166 int
  167 cdevsw_remove(struct cdevsw *oldentry)
  168 {
  169         if (oldentry->d_maj < 0 || oldentry->d_maj >= NUMCDEVSW) {
  170                 printf("%s: ERROR: driver has bogus cdevsw->d_maj = %d\n",
  171                     oldentry->d_name, oldentry->d_maj);
  172                 return EINVAL;
  173         }
  174 
  175         cdevsw[oldentry->d_maj] = NULL;
  176 
  177         if (oldentry->d_bmaj >= 0 && oldentry->d_bmaj < NUMCDEVSW)
  178                 bmaj2cmaj[oldentry->d_bmaj] = 254;
  179 
  180         return 0;
  181 }
  182 
  183 /*
  184  * dev_t and u_dev_t primitives
  185  */
  186 
  187 int
  188 major(dev_t x)
  189 {
  190         if (x == NODEV)
  191                 return NOUDEV;
  192         return((x->si_udev >> 8) & 0xff);
  193 }
  194 
  195 int
  196 minor(dev_t x)
  197 {
  198         if (x == NODEV)
  199                 return NOUDEV;
  200         return(x->si_udev & 0xffff00ff);
  201 }
  202 
  203 int
  204 lminor(dev_t x)
  205 {
  206         int i;
  207 
  208         if (x == NODEV)
  209                 return NOUDEV;
  210         i = minor(x);
  211         return ((i & 0xff) | (i >> 8));
  212 }
  213 
  214 dev_t
  215 makebdev(int x, int y)
  216 {
  217         
  218         if (x == umajor(NOUDEV) && y == uminor(NOUDEV))
  219                 Debugger("makebdev of NOUDEV");
  220         return (makedev(bmaj2cmaj[x], y));
  221 }
  222 
  223 dev_t
  224 makedev(int x, int y)
  225 {
  226         struct specinfo *si;
  227         udev_t  udev;
  228         int hash;
  229         static int stashed;
  230 
  231         if (x == umajor(NOUDEV) && y == uminor(NOUDEV))
  232                 Debugger("makedev of NOUDEV");
  233         udev = (x << 8) | y;
  234         hash = udev % DEVT_HASH;
  235         LIST_FOREACH(si, &dev_hash[hash], si_hash) {
  236                 if (si->si_udev == udev)
  237                         return (si);
  238         }
  239         if (stashed >= DEVT_STASH) {
  240                 MALLOC(si, struct specinfo *, sizeof(*si), M_DEVT,
  241                     M_USE_RESERVE);
  242                 bzero(si, sizeof(*si));
  243         } else if (LIST_FIRST(&dev_free)) {
  244                 si = LIST_FIRST(&dev_free);
  245                 LIST_REMOVE(si, si_hash);
  246         } else {
  247                 si = devt_stash + stashed++;
  248                 si->si_flags |= SI_STASHED;
  249         }
  250         si->si_udev = udev;
  251         LIST_INSERT_HEAD(&dev_hash[hash], si, si_hash);
  252         return (si);
  253 }
  254 
  255 void
  256 freedev(dev_t dev)
  257 {
  258         int hash;
  259 
  260         if (!free_devt)
  261                 return;
  262         if (SLIST_FIRST(&dev->si_hlist))
  263                 return;
  264         if (dev->si_devsw || dev->si_drv1 || dev->si_drv2)
  265                 return;
  266         hash = dev->si_udev % DEVT_HASH;
  267         LIST_REMOVE(dev, si_hash);
  268         if (dev->si_flags & SI_STASHED) {
  269                 bzero(dev, sizeof(*dev));
  270                 LIST_INSERT_HEAD(&dev_free, dev, si_hash);
  271         } else {
  272                 FREE(dev, M_DEVT);
  273         }
  274 }
  275 
  276 udev_t
  277 dev2udev(dev_t x)
  278 {
  279         if (x == NODEV)
  280                 return NOUDEV;
  281         return (x->si_udev);
  282 }
  283 
  284 dev_t
  285 udev2dev(udev_t x, int b)
  286 {
  287 
  288         if (x == NOUDEV)
  289                 return (NODEV);
  290         switch (b) {
  291                 case 0:
  292                         return makedev(umajor(x), uminor(x));
  293                 case 1:
  294                         return makebdev(umajor(x), uminor(x));
  295                 default:
  296                         Debugger("udev2dev(...,X)");
  297                         return NODEV;
  298         }
  299 }
  300 
  301 int
  302 uminor(udev_t dev)
  303 {
  304         return(dev & 0xffff00ff);
  305 }
  306 
  307 int
  308 umajor(udev_t dev)
  309 {
  310         return((dev & 0xff00) >> 8);
  311 }
  312 
  313 udev_t
  314 makeudev(int x, int y)
  315 {
  316         return ((x << 8) | y);
  317 }
  318 
  319 dev_t
  320 make_dev(struct cdevsw *devsw, int minor, uid_t uid, gid_t gid, int perms, const char *fmt, ...)
  321 {
  322         dev_t   dev;
  323         va_list ap;
  324         int i;
  325 
  326         compile_devsw(devsw);
  327         dev = makedev(devsw->d_maj, minor);
  328         va_start(ap, fmt);
  329         i = kvprintf(fmt, NULL, dev->si_name, 32, ap);
  330         dev->si_name[i] = '\0';
  331         va_end(ap);
  332         dev->si_devsw = devsw;
  333 
  334         return (dev);
  335 }
  336 
  337 void
  338 destroy_dev(dev_t dev)
  339 {
  340         dev->si_drv1 = 0;
  341         dev->si_drv2 = 0;
  342         dev->si_devsw = 0;
  343         freedev(dev);
  344 }
  345 
  346 const char *
  347 devtoname(dev_t dev)
  348 {
  349         char *p;
  350         int mynor;
  351 
  352         if (dev->si_name[0] == '#' || dev->si_name[0] == '\0') {
  353                 p = dev->si_name;
  354                 if (devsw(dev))
  355                         sprintf(p, "#%s/", devsw(dev)->d_name);
  356                 else
  357                         sprintf(p, "#%d/", major(dev));
  358                 p += strlen(p);
  359                 mynor = minor(dev);
  360                 if (mynor < 0 || mynor > 255)
  361                         sprintf(p, "%#x", (u_int)mynor);
  362                 else
  363                         sprintf(p, "%d", mynor);
  364         }
  365         return (dev->si_name);
  366 }

Cache object: f9d23f0183ae3bb4bc17d168d421b689


[ 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.