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/servers/fs/dmap.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 /* This file contains the table with device <-> driver mappings. It also
    2  * contains some routines to dynamically add and/ or remove device drivers
    3  * or change mappings.  
    4  */
    5 
    6 #include "fs.h"
    7 #include "fproc.h"
    8 #include <string.h>
    9 #include <stdlib.h>
   10 #include <ctype.h>
   11 #include <unistd.h>
   12 #include <minix/com.h>
   13 #include "param.h"
   14 
   15 /* Some devices may or may not be there in the next table. */
   16 #define DT(enable, opcl, io, driver, flags) \
   17   { (enable?(opcl):no_dev), (enable?(io):0), \
   18         (enable?(driver):0), (flags) },
   19 #define NC(x) (NR_CTRLRS >= (x))
   20 
   21 /* The order of the entries here determines the mapping between major device
   22  * numbers and tasks.  The first entry (major device 0) is not used.  The
   23  * next entry is major device 1, etc.  Character and block devices can be
   24  * intermixed at random.  The ordering determines the device numbers in /dev/.
   25  * Note that FS knows the device number of /dev/ram/ to load the RAM disk.
   26  * Also note that the major device numbers used in /dev/ are NOT the same as 
   27  * the process numbers of the device drivers. 
   28  */
   29 /*
   30   Driver enabled     Open/Cls  I/O     Driver #     Flags Device  File
   31   --------------     --------  ------  -----------  ----- ------  ----       
   32  */
   33 struct dmap dmap[NR_DEVICES];                           /* actual map */ 
   34 PRIVATE struct dmap init_dmap[] = {
   35   DT(1, no_dev,   0,       0,           0)              /* 0 = not used   */
   36   DT(1, gen_opcl, gen_io,  MEM_PROC_NR, 0)              /* 1 = /dev/mem   */
   37   DT(0, no_dev,   0,       0,           DMAP_MUTABLE)   /* 2 = /dev/fd0   */
   38   DT(0, no_dev,   0,       0,           DMAP_MUTABLE)   /* 3 = /dev/c0    */
   39   DT(1, tty_opcl, gen_io,  TTY_PROC_NR, 0)              /* 4 = /dev/tty00 */
   40   DT(1, ctty_opcl,ctty_io, TTY_PROC_NR, 0)              /* 5 = /dev/tty   */
   41   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /* 6 = /dev/lp    */
   42 
   43 #if (MACHINE == IBM_PC)
   44   DT(1, no_dev,   0,       0,           DMAP_MUTABLE)   /* 7 = /dev/ip    */
   45   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /* 8 = /dev/c1    */
   46   DT(0, 0,        0,       0,           DMAP_MUTABLE)   /* 9 = not used   */
   47   DT(0, no_dev,   0,       0,           DMAP_MUTABLE)   /*10 = /dev/c2    */
   48   DT(0, 0,        0,       0,           DMAP_MUTABLE)   /*11 = not used   */
   49   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /*12 = /dev/c3    */
   50   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /*13 = /dev/audio */
   51   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /*14 = /dev/mixer */
   52   DT(1, gen_opcl, gen_io,  LOG_PROC_NR, 0)              /*15 = /dev/klog  */
   53   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /*16 = /dev/random*/
   54   DT(0, no_dev,   0,       NONE,        DMAP_MUTABLE)   /*17 = /dev/cmos  */
   55 #endif /* IBM_PC */
   56 };
   57 
   58 /*===========================================================================*
   59  *                              do_devctl                                    *
   60  *===========================================================================*/
   61 PUBLIC int do_devctl()
   62 {
   63   int result;
   64 
   65   switch(m_in.ctl_req) {
   66   case DEV_MAP:
   67       /* Try to update device mapping. */
   68       result = map_driver(m_in.dev_nr, m_in.driver_nr, m_in.dev_style);
   69       break;
   70   case DEV_UNMAP:
   71       result = map_driver(m_in.dev_nr, NONE, 0);
   72       break;
   73   default:
   74       result = EINVAL;
   75   }
   76   return(result);
   77 }
   78 
   79 /*===========================================================================*
   80  *                              map_driver                                   *
   81  *===========================================================================*/
   82 PUBLIC int map_driver(major, proc_nr, style)
   83 int major;                      /* major number of the device */
   84 int proc_nr;                    /* process number of the driver */
   85 int style;                      /* style of the device */
   86 {
   87 /* Set a new device driver mapping in the dmap table. Given that correct 
   88  * arguments are given, this only works if the entry is mutable and the 
   89  * current driver is not busy.  If the proc_nr is set to NONE, we're supposed
   90  * to unmap it.
   91  *
   92  * Normal error codes are returned so that this function can be used from
   93  * a system call that tries to dynamically install a new driver.
   94  */
   95   struct dmap *dp;
   96 
   97   /* Get pointer to device entry in the dmap table. */
   98   if (major < 0 || major >= NR_DEVICES) return(ENODEV);
   99   dp = &dmap[major];            
  100 
  101   /* Check if we're supposed to unmap it. If so, do it even
  102    * if busy or unmutable, as unmap is called when driver has
  103    * exited.
  104    */
  105  if(proc_nr == NONE) {
  106         dp->dmap_opcl = no_dev;
  107         dp->dmap_io = no_dev_io;
  108         dp->dmap_driver = NONE;
  109         dp->dmap_flags = DMAP_MUTABLE;  /* When gone, not busy or reserved. */
  110         return(OK);
  111   }
  112         
  113   /* See if updating the entry is allowed. */
  114   if (! (dp->dmap_flags & DMAP_MUTABLE))  return(EPERM);
  115   if (dp->dmap_flags & DMAP_BUSY)  return(EBUSY);
  116 
  117   /* Check process number of new driver. */
  118   if (! isokprocnr(proc_nr))  return(EINVAL);
  119 
  120   /* Try to update the entry. */
  121   switch (style) {
  122   case STYLE_DEV:       dp->dmap_opcl = gen_opcl;       break;
  123   case STYLE_TTY:       dp->dmap_opcl = tty_opcl;       break;
  124   case STYLE_CLONE:     dp->dmap_opcl = clone_opcl;     break;
  125   default:              return(EINVAL);
  126   }
  127   dp->dmap_io = gen_io;
  128   dp->dmap_driver = proc_nr;
  129 
  130   /* If a driver has completed its exec(), it can be announced to be up. */
  131   if(fproc[proc_nr].fp_execced) {
  132         dev_up(major);
  133   } else {
  134         dp->dmap_flags |= DMAP_BABY;
  135   }
  136 
  137   return(OK); 
  138 }
  139 
  140 /*===========================================================================*
  141  *                              dmap_unmap_by_proc                           *
  142  *===========================================================================*/
  143 PUBLIC void dmap_unmap_by_proc(int proc_nr)
  144 {
  145         int i, r;
  146         for (i=0; i<NR_DEVICES; i++)
  147           if(dmap[i].dmap_driver && dmap[i].dmap_driver == proc_nr)
  148             if((r=map_driver(i, NONE, 0)) != OK)
  149                 printf("FS: unmap of p %d / d %d failed: %d\n", proc_nr, i, r);
  150 
  151         return;
  152 
  153 }
  154 
  155 /*===========================================================================*
  156  *                              build_dmap                                   *
  157  *===========================================================================*/
  158 PUBLIC void build_dmap()
  159 {
  160 /* Initialize the table with all device <-> driver mappings. Then, map  
  161  * the boot driver to a controller and update the dmap table to that
  162  * selection. The boot driver and the controller it handles are set at 
  163  * the boot monitor.  
  164  */
  165   char driver[16];
  166   char *controller = "c##";
  167   int nr, major = -1;
  168   int i,s;
  169   struct dmap *dp;
  170 
  171   /* Build table with device <-> driver mappings. */
  172   for (i=0; i<NR_DEVICES; i++) {
  173       dp = &dmap[i];            
  174       if (i < sizeof(init_dmap)/sizeof(struct dmap) && 
  175               init_dmap[i].dmap_opcl != no_dev) {       /* a preset driver */
  176           dp->dmap_opcl = init_dmap[i].dmap_opcl;
  177           dp->dmap_io = init_dmap[i].dmap_io;
  178           dp->dmap_driver = init_dmap[i].dmap_driver;
  179           dp->dmap_flags = init_dmap[i].dmap_flags;
  180       } else {                                          /* no default */
  181           dp->dmap_opcl = no_dev;
  182           dp->dmap_io = no_dev_io;
  183           dp->dmap_driver = NONE;
  184           dp->dmap_flags = DMAP_MUTABLE;
  185       }
  186   }
  187 
  188   /* Get settings of 'controller' and 'driver' at the boot monitor. */
  189   if ((s = env_get_param("label", driver, sizeof(driver))) != OK) 
  190       panic(__FILE__,"couldn't get boot monitor parameter 'driver'", s);
  191   if ((s = env_get_param("controller", controller, sizeof(controller))) != OK) 
  192       panic(__FILE__,"couldn't get boot monitor parameter 'controller'", s);
  193 
  194   /* Determine major number to map driver onto. */
  195   if (controller[0] == 'f' && controller[1] == 'd') {
  196       major = FLOPPY_MAJOR;
  197   } 
  198   else if (controller[0] == 'c' && isdigit(controller[1])) {
  199       if ((nr = (unsigned) atoi(&controller[1])) > NR_CTRLRS)
  200           panic(__FILE__,"monitor 'controller' maximum 'c#' is", NR_CTRLRS);
  201       major = CTRLR(nr);
  202   } 
  203   else {
  204       panic(__FILE__,"monitor 'controller' syntax is 'c#' of 'fd'", NO_NUM); 
  205   }
  206   
  207   /* Now try to set the actual mapping and report to the user. */
  208   if ((s=map_driver(major, DRVR_PROC_NR, STYLE_DEV)) != OK)
  209       panic(__FILE__,"map_driver failed",s);
  210   printf("Boot medium driver: %s driver mapped onto controller %s.\n",
  211       driver, controller);
  212 }
  213 
  214 /*===========================================================================*
  215  *                              dmap_driver_match                            *
  216  *===========================================================================*/ 
  217 PUBLIC int dmap_driver_match(int proc, int major)
  218 {
  219         if (major < 0 || major >= NR_DEVICES) return(0);
  220         if(dmap[major].dmap_driver != NONE && dmap[major].dmap_driver == proc)
  221                 return 1;
  222         return 0;
  223 }
  224 
  225 /*===========================================================================*
  226  *                              dmap_proc_up                                 *
  227  *===========================================================================*/ 
  228 PUBLIC void dmap_proc_up(int proc)
  229 {
  230         int i;
  231         for (i=0; i<NR_DEVICES; i++) {
  232                 if(dmap[i].dmap_driver != NONE
  233                         && dmap[i].dmap_driver == proc
  234                         && (dmap[i].dmap_flags & DMAP_BABY)) {
  235                         dmap[i].dmap_flags &= ~DMAP_BABY;
  236                         dev_up(i);
  237                 }
  238         }
  239         return;
  240 }

Cache object: 513139308e084c639c9094d4542bf47d


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