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/kernel/system/do_vdevio.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 /* The kernel call implemented in this file:
    2  *   m_type:    SYS_VDEVIO
    3  *
    4  * The parameters for this kernel call are:
    5  *    m2_i3:    DIO_REQUEST     (request input or output)       
    6  *    m2_i1:    DIO_TYPE        (flag indicating byte, word, or long)
    7  *    m2_p1:    DIO_VEC_ADDR    (pointer to port/ value pairs)  
    8  *    m2_i2:    DIO_VEC_SIZE    (number of ports to read or write) 
    9  */
   10 
   11 #include "../system.h"
   12 #include <minix/devio.h>
   13 
   14 #if USE_VDEVIO
   15 
   16 /* Buffer for SYS_VDEVIO to copy (port,value)-pairs from/ to user. */
   17 PRIVATE char vdevio_buf[VDEVIO_BUF_SIZE];      
   18 PRIVATE pvb_pair_t *pvb = (pvb_pair_t *) vdevio_buf;           
   19 PRIVATE pvw_pair_t *pvw = (pvw_pair_t *) vdevio_buf;      
   20 PRIVATE pvl_pair_t *pvl = (pvl_pair_t *) vdevio_buf;     
   21 
   22 /*===========================================================================*
   23  *                              do_vdevio                                    *
   24  *===========================================================================*/
   25 PUBLIC int do_vdevio(m_ptr)
   26 register message *m_ptr;        /* pointer to request message */
   27 {
   28 /* Perform a series of device I/O on behalf of a non-kernel process. The 
   29  * I/O addresses and I/O values are fetched from and returned to some buffer
   30  * in user space. The actual I/O is wrapped by lock() and unlock() to prevent
   31  * that I/O batch from being interrrupted.
   32  * This is the counterpart of do_devio, which performs a single device I/O. 
   33  */ 
   34   int vec_size;               /* size of vector */
   35   int io_in;                  /* true if input */
   36   size_t bytes;               /* # bytes to be copied */
   37   int caller_proc;            /* process number of caller */
   38   vir_bytes caller_vir;       /* virtual address at caller */
   39   phys_bytes caller_phys;     /* physical address at caller */
   40   int i;
   41     
   42   /* Get the request, size of the request vector, and check the values. */
   43   if (m_ptr->DIO_REQUEST == DIO_INPUT) io_in = TRUE;
   44   else if (m_ptr->DIO_REQUEST == DIO_OUTPUT) io_in = FALSE;
   45   else return(EINVAL);
   46   if ((vec_size = m_ptr->DIO_VEC_SIZE) <= 0) return(EINVAL);
   47   switch (m_ptr->DIO_TYPE) {
   48       case DIO_BYTE: bytes = vec_size * sizeof(pvb_pair_t); break;
   49       case DIO_WORD: bytes = vec_size * sizeof(pvw_pair_t); break;
   50       case DIO_LONG: bytes = vec_size * sizeof(pvl_pair_t); break;
   51       default:  return(EINVAL);   /* check type once and for all */
   52   }
   53   if (bytes > sizeof(vdevio_buf))  return(E2BIG);
   54 
   55   /* Calculate physical addresses and copy (port,value)-pairs from user. */
   56   caller_proc = m_ptr->m_source; 
   57   caller_vir = (vir_bytes) m_ptr->DIO_VEC_ADDR;
   58   caller_phys = umap_local(proc_addr(caller_proc), D, caller_vir, bytes);
   59   if (0 == caller_phys) return(EFAULT);
   60   phys_copy(caller_phys, vir2phys(vdevio_buf), (phys_bytes) bytes);
   61 
   62   /* Perform actual device I/O for byte, word, and long values. Note that 
   63    * the entire switch is wrapped in lock() and unlock() to prevent the I/O
   64    * batch from being interrupted. 
   65    */  
   66   lock(13, "do_vdevio");
   67   switch (m_ptr->DIO_TYPE) {
   68   case DIO_BYTE:                                         /* byte values */
   69       if (io_in) for (i=0; i<vec_size; i++)  pvb[i].value = inb(pvb[i].port); 
   70       else       for (i=0; i<vec_size; i++)  outb(pvb[i].port, pvb[i].value); 
   71       break; 
   72   case DIO_WORD:                                          /* word values */
   73       if (io_in) for (i=0; i<vec_size; i++)  pvw[i].value = inw(pvw[i].port);  
   74       else       for (i=0; i<vec_size; i++)  outw(pvw[i].port, pvw[i].value); 
   75       break; 
   76   default:                                                /* long values */
   77       if (io_in) for (i=0; i<vec_size; i++) pvl[i].value = inl(pvl[i].port);  
   78       else       for (i=0; i<vec_size; i++) outl(pvb[i].port, pvl[i].value); 
   79   }
   80   unlock(13);
   81     
   82   /* Almost done, copy back results for input requests. */
   83   if (io_in) phys_copy(vir2phys(vdevio_buf), caller_phys, (phys_bytes) bytes);
   84   return(OK);
   85 }
   86 
   87 #endif /* USE_VDEVIO */
   88 

Cache object: 17d6fa0bef509a78c73292d67d1580bb


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