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/drivers/rescue/rescue.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 rescue device driver (/dev/rescue)
    2  *
    3  *  Changes:
    4  *      Oct 21, 1992    created  (Jorrit N. Herder)
    5  */
    6 
    7 #include "../drivers.h"
    8 #include "../libdriver/driver.h"
    9 #include "../../kernel/const.h"
   10 #include "../../kernel/config.h"
   11 #include "../../kernel/type.h"
   12 
   13 #define VERBOSE            0            /* enable/ disable messages */
   14 #define NR_DEVS            1            /* number of rescue devices */
   15 #define RESCUE_KBYTES    128            /* default size in kilobytes */
   16 
   17 PRIVATE struct device m_geom[NR_DEVS];  /* base and size of each device */
   18 PRIVATE int m_seg[NR_DEVS];             /* segment index of each device */
   19 PRIVATE int m_device;                   /* current device */
   20 
   21 extern int errno;                       /* error number for PM calls */
   22 
   23 FORWARD _PROTOTYPE( void m_init, (int argc, char **argv) );
   24 FORWARD _PROTOTYPE( char *m_name, (void)                                );
   25 FORWARD _PROTOTYPE( struct device *m_prepare, (int device)              );
   26 FORWARD _PROTOTYPE( int m_transfer, (int proc_nr, int opcode, off_t position,
   27                                         iovec_t *iov, unsigned nr_req)  );
   28 FORWARD _PROTOTYPE( int m_do_open, (struct driver *dp, message *m_ptr)  );
   29 FORWARD _PROTOTYPE( void m_geometry, (struct partition *entry)          );
   30 
   31 /* Entry points to this driver. */
   32 PRIVATE struct driver m_dtab = {
   33   m_name,       /* current device's name */
   34   m_do_open,    /* open or mount */
   35   do_nop,       /* nothing on a close */
   36   do_diocntl,   /* standard I/O controls */
   37   m_prepare,    /* prepare for I/O on a given minor device */
   38   m_transfer,   /* do the I/O */
   39   nop_cleanup,  /* no need to clean up */
   40   m_geometry,   /* memory device "geometry" */
   41   nop_signal,   /* system signals */
   42   nop_alarm,
   43   nop_cancel,
   44   nop_select,
   45   NULL,
   46   NULL
   47 };
   48 
   49 
   50 /*===========================================================================*
   51  *                                 main                                      *
   52  *===========================================================================*/
   53 PUBLIC int main(int argc, char **argv)
   54 {
   55 /* Main program. Initialize the rescue driver and start the main loop. */
   56   m_init(argc, argv);                   
   57   driver_task(&m_dtab);         
   58   return(OK);                           
   59 }
   60 
   61 /*===========================================================================*
   62  *                               m_name                                      *
   63  *===========================================================================*/
   64 PRIVATE char *m_name()
   65 {
   66 /* Return a name for the current device. */
   67   static char name[] = "rescue";
   68   return name;  
   69 }
   70 
   71 /*===========================================================================*
   72  *                              m_prepare                                    *
   73  *===========================================================================*/
   74 PRIVATE struct device *m_prepare(device)
   75 int device;
   76 {
   77 /* Prepare for I/O on a device: check if the minor device number is ok. */
   78   if (device < 0 || device >= NR_DEVS) return(NIL_DEV);
   79   m_device = device;
   80 
   81   return(&m_geom[device]);
   82 }
   83 
   84 /*===========================================================================*
   85  *                              m_transfer                                   *
   86  *===========================================================================*/
   87 PRIVATE int m_transfer(proc_nr, opcode, position, iov, nr_req)
   88 int proc_nr;                    /* process doing the request */
   89 int opcode;                     /* DEV_GATHER or DEV_SCATTER */
   90 off_t position;                 /* offset on device to read or write */
   91 iovec_t *iov;                   /* pointer to read or write request vector */
   92 unsigned nr_req;                /* length of request vector */
   93 {
   94 /* Read or write one the driver's minor devices. */
   95   int seg;
   96   unsigned count, left, chunk;
   97   vir_bytes user_vir;
   98   struct device *dv;
   99   unsigned long dv_size;
  100   int s;
  101 
  102   /* Get and check minor device number. */
  103   if ((unsigned) m_device > NR_DEVS - 1) return(ENXIO);
  104   dv = &m_geom[m_device];
  105   dv_size = cv64ul(dv->dv_size);
  106 
  107   while (nr_req > 0) {
  108 
  109         /* How much to transfer and where to / from. */
  110         count = iov->iov_size;
  111         user_vir = iov->iov_addr;
  112 
  113         /* Virtual copying. For rescue device. */
  114         if (position >= dv_size) return(OK);    /* check for EOF */
  115         if (position + count > dv_size) count = dv_size - position;
  116         seg = m_seg[m_device];
  117 
  118         if (opcode == DEV_GATHER) {                     /* copy actual data */
  119             sys_vircopy(SELF,seg,position, proc_nr,D,user_vir, count);
  120         } else {
  121             sys_vircopy(proc_nr,D,user_vir, SELF,seg,position, count);
  122         }
  123 
  124         /* Book the number of bytes transferred. */
  125         position += count;
  126         iov->iov_addr += count;
  127         if ((iov->iov_size -= count) == 0) { iov++; nr_req--; }
  128 
  129   }
  130   return(OK);
  131 }
  132 
  133 /*===========================================================================*
  134  *                              m_do_open                                    *
  135  *===========================================================================*/
  136 PRIVATE int m_do_open(dp, m_ptr)
  137 struct driver *dp;
  138 message *m_ptr;
  139 {
  140 /* Check device number on open. */
  141   if (m_prepare(m_ptr->DEVICE) == NIL_DEV) return(ENXIO);
  142   return(OK);
  143 }
  144 
  145 /*===========================================================================*
  146  *                              m_init                                       *
  147  *===========================================================================*/
  148 PRIVATE void m_init(argc,argv)
  149 int argc;
  150 char **argv;
  151 {
  152   /* Initialize this task. All minor devices are initialized one by one. */
  153   phys_bytes rescue_size;
  154   phys_bytes rescue_base;
  155   message m;
  156   int i, s;
  157 
  158   /* Initialize all rescue devices in a loop. */
  159   for (i=0; i< NR_DEVS; i++) {
  160 
  161       /* Determine size and base of rescue disks. See if rescue disk details 
  162        * exist in the data store. If no memory for the rescue disk was claimed 
  163        * yet, do it below. 
  164        */
  165       m.DS_KEY = (RESCUE_MAJOR << 8) + i;
  166       if (OK == (s = _taskcall(DS_PROC_NR, DS_RETRIEVE, &m))) {
  167           rescue_size = m.DS_VAL_L1;
  168           rescue_base = m.DS_VAL_L2;
  169       }
  170       else {                                    /* no details known */
  171           if (argc>i+1) rescue_size = atoi(argv[i+1]) * 1024;
  172           else          rescue_size = RESCUE_KBYTES * 1024;
  173 
  174           if (allocmem(rescue_size, &rescue_base) < 0) {
  175               report("RESCUE", "warning, allocmem failed", errno);
  176               rescue_size = 0;
  177           }
  178       }
  179 
  180       /* Now that we have the base and size of the rescue disk, set up all
  181        * data structures if the rescue has a positive (nonzero) size. 
  182        */
  183       if (rescue_size > 0) {
  184 
  185           /* Create a new remote segment to make virtual copies. */ 
  186           if (OK != (s=sys_segctl(&m_seg[i], (u16_t *) &s, 
  187                   (vir_bytes *) &s, rescue_base, rescue_size))) {
  188               panic("RESCUE","Couldn't install remote segment.",s);
  189           }
  190 
  191           /* Set the device geometry for the outside world. */
  192           m_geom[i].dv_base = cvul64(rescue_base);
  193           m_geom[i].dv_size = cvul64(rescue_size);
  194 
  195           /* Store the values in the data store for future retrieval. */
  196           m.DS_KEY = (RESCUE_MAJOR << 8) + i;
  197           m.DS_VAL_L1 = rescue_size;
  198           m.DS_VAL_L2 = rescue_base;
  199           if (OK != (s = _taskcall(DS_PROC_NR, DS_PUBLISH, &m))) {
  200               panic("RESCUE","Couldn't store rescue disk details at DS.",s);
  201           }
  202 
  203 #if VERBOSE
  204           printf("RESCUE disk %d (size %u/base %u) initialized\n",
  205               i, rescue_size, rescue_base);
  206 #endif
  207       }
  208   }
  209 }
  210 
  211 /*===========================================================================*
  212  *                              m_geometry                                   *
  213  *===========================================================================*/
  214 PRIVATE void m_geometry(entry)
  215 struct partition *entry;
  216 {
  217   /* Memory devices don't have a geometry, but the outside world insists. */
  218   entry->cylinders = div64u(m_geom[m_device].dv_size, SECTOR_SIZE) / (64 * 32);
  219   entry->heads = 64;
  220   entry->sectors = 32;
  221 }
  222 

Cache object: b1eaad0c870dfd911998d2b2e25dce5e


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