1 /* The kernel call implemented in this file:
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_l1: DIO_PORT (port to read/ write)
8 * m2_p1: DIO_VEC_ADDR (virtual address of buffer)
9 * m2_l2: DIO_VEC_SIZE (number of elements)
10 * m2_i2: DIO_VEC_PROC (process where buffer is)
13 #include "../../system.h"
14 #include <minix/devio.h>
15 #include <minix/endpoint.h>
21 /*===========================================================================*
23 *===========================================================================*/
24 PUBLIC
int do_sdevio(m_ptr
)
25 register message
*m_ptr
; /* pointer to request message */
29 int proc_nr
, proc_nr_e
= m_ptr
->DIO_VEC_ENDPT
;
30 int count
= m_ptr
->DIO_VEC_SIZE
;
31 long port
= m_ptr
->DIO_PORT
;
33 int i
, req_type
, req_dir
, io_type
, size
, nr_io_range
;
36 struct io_range
*iorp
;
39 struct proc
*destproc
;
41 /* Allow safe copies and accesses to SELF */
42 if ((m_ptr
->DIO_REQUEST
& _DIO_SAFEMASK
) != _DIO_SAFE
&&
49 kprintf("do_sdevio: for %d, req %d\n",
50 m_ptr
->m_source
, m_ptr
->DIO_REQUEST
);
54 /* Check if process endpoint is OK.
55 * A driver may directly provide a pointer to a buffer at the user-process
56 * that initiated the device I/O. Kernel processes, of course, are denied.
58 if (proc_nr_e
== SELF
)
61 if(!isokendpt(proc_nr_e
, &proc_nr
))
63 if (iskerneln(proc_nr
)) return(EPERM
);
65 /* Extract direction (in or out) and type (size). */
66 req_dir
= m_ptr
->DIO_REQUEST
& _DIO_DIRMASK
;
67 req_type
= m_ptr
->DIO_REQUEST
& _DIO_TYPEMASK
;
69 /* Check for 'safe' variants. */
70 if((m_ptr
->DIO_REQUEST
& _DIO_SAFEMASK
) == _DIO_SAFE
) {
71 /* Map grant address to physical address. */
72 if(verify_grant(proc_nr_e
, who_e
,
73 (vir_bytes
) m_ptr
->DIO_VEC_ADDR
,
75 req_dir
== _DIO_INPUT
? CPF_WRITE
: CPF_READ
,
76 (vir_bytes
) m_ptr
->DIO_OFFSET
,
77 &newoffset
, &newep
) != OK
) {
78 printf("do_sdevio: verify_grant failed\n");
81 if(!isokendpt(newep
, &proc_nr
))
83 destproc
= proc_addr(proc_nr
);
84 if ((phys_buf
= umap_local(destproc
, D
,
85 (vir_bytes
) newoffset
, count
)) == 0) {
86 printf("do_sdevio: umap_local failed\n");
92 kprintf("do_sdevio: unsafe sdevio by %d in %d denied\n",
96 /* Get and check physical address. */
97 if ((phys_buf
= umap_local(proc_addr(proc_nr
), D
,
98 (vir_bytes
) m_ptr
->DIO_VEC_ADDR
, count
)) == 0)
100 destproc
= proc_addr(proc_nr
);
102 /* current process must be target for phys_* to be OK */
104 vm_set_cr3(destproc
);
108 case _DIO_BYTE
: size
= 1; break;
109 case _DIO_WORD
: size
= 2; break;
110 case _DIO_LONG
: size
= 4; break;
111 default: size
= 4; break; /* Be conservative */
114 rp
= proc_addr(who_p
);
116 if (privp
&& privp
->s_flags
& CHECK_IO_PORT
)
120 case _DIO_BYTE
: size
= 1; break;
121 case _DIO_WORD
: size
= 2; break;
122 case _DIO_LONG
: size
= 4; break;
123 default: size
= 4; break; /* Be conservative */
125 port
= m_ptr
->DIO_PORT
;
126 nr_io_range
= privp
->s_nr_io_range
;
127 for (i
= 0, iorp
= privp
->s_io_tab
; i
<nr_io_range
; i
++, iorp
++)
129 if (port
>= iorp
->ior_base
&& port
+size
-1 <= iorp
->ior_limit
)
132 if (i
>= nr_io_range
)
135 "do_sdevio: I/O port check failed for proc %d, port 0x%x\n",
136 m_ptr
->m_source
, port
);
143 kprintf("do_devio: unaligned port 0x%x (size %d)\n", port
, size
);
147 /* Perform device I/O for bytes and words. Longs are not supported. */
148 if (req_dir
== _DIO_INPUT
) {
150 case _DIO_BYTE
: phys_insb(port
, phys_buf
, count
); break;
151 case _DIO_WORD
: phys_insw(port
, phys_buf
, count
); break;
152 default: return(EINVAL
);
154 } else if (req_dir
== _DIO_OUTPUT
) {
156 case _DIO_BYTE
: phys_outsb(port
, phys_buf
, count
); break;
157 case _DIO_WORD
: phys_outsw(port
, phys_buf
, count
); break;
158 default: return(EINVAL
);
167 #endif /* USE_SDEVIO */