1 /* The kernel call implemented in this file:
2 * m_type: SYS_DEVIO
3 *
4 * The parameters for this kernel call are:
5 * m_lsys_krn_sys_devio.request (request input or output)
6 * m_lsys_krn_sys_devio.port (port to read/ write)
7 * m_lsys_krn_sys_devio.value (value to write/ return value read)
8 */
9
10 #include "kernel/system.h"
11 #include <minix/devio.h>
12 #include <minix/endpoint.h>
13
14 #if USE_DEVIO
15
16 /*===========================================================================*
17 * do_devio *
18 *===========================================================================*/
do_devio(struct proc * caller,message * m_ptr)19 int do_devio(struct proc * caller, message * m_ptr)
20 {
21 struct priv *privp;
22 port_t port;
23 struct io_range *iorp;
24 int i, size, nr_io_range;
25 int io_type, io_dir;
26
27 io_type = m_ptr->m_lsys_krn_sys_devio.request & _DIO_TYPEMASK;
28 io_dir = m_ptr->m_lsys_krn_sys_devio.request & _DIO_DIRMASK;
29
30 switch (io_type)
31 {
32 case _DIO_BYTE: size= 1; break;
33 case _DIO_WORD: size= 2; break;
34 case _DIO_LONG: size= 4; break;
35 default: size= 4; break; /* Be conservative */
36 }
37
38 privp= priv(caller);
39 if (!privp)
40 {
41 printf("no priv structure!\n");
42 goto doit;
43 }
44 if (privp->s_flags & CHECK_IO_PORT)
45 {
46 port= m_ptr->m_lsys_krn_sys_devio.port;
47 nr_io_range= privp->s_nr_io_range;
48 for (i= 0, iorp= privp->s_io_tab; i<nr_io_range; i++, iorp++)
49 {
50 if (port >= iorp->ior_base && port+size-1 <= iorp->ior_limit)
51 break;
52 }
53 if (i >= nr_io_range)
54 {
55 printf("do_devio: port 0x%x (size %d) not allowed\n",
56 m_ptr->m_lsys_krn_sys_devio.port, size);
57 return EPERM;
58 }
59 }
60
61 doit:
62 if (m_ptr->m_lsys_krn_sys_devio.port & (size-1))
63 {
64 printf("do_devio: unaligned port 0x%x (size %d)\n",
65 m_ptr->m_lsys_krn_sys_devio.port, size);
66 return EPERM;
67 }
68
69 /* Process a single I/O request for byte, word, and long values. */
70 if (io_dir == _DIO_INPUT) {
71 switch (io_type) {
72 /* maybe "it" should not be called ports */
73 case _DIO_BYTE:
74 m_ptr->m_krn_lsys_sys_devio.value =
75 inb(m_ptr->m_lsys_krn_sys_devio.port);
76 break;
77 case _DIO_WORD:
78 m_ptr->m_krn_lsys_sys_devio.value =
79 inw(m_ptr->m_lsys_krn_sys_devio.port);
80 break;
81 case _DIO_LONG:
82 m_ptr->m_krn_lsys_sys_devio.value =
83 inl(m_ptr->m_lsys_krn_sys_devio.port);
84 break;
85 default: return(EINVAL);
86 }
87 } else {
88 switch (io_type) {
89 case _DIO_BYTE:
90 outb(m_ptr->m_lsys_krn_sys_devio.port,
91 m_ptr->m_lsys_krn_sys_devio.value);
92 break;
93 case _DIO_WORD:
94 outw(m_ptr->m_lsys_krn_sys_devio.port,
95 m_ptr->m_lsys_krn_sys_devio.value);
96 break;
97 case _DIO_LONG:
98 outl(m_ptr->m_lsys_krn_sys_devio.port,
99 m_ptr->m_lsys_krn_sys_devio.value);
100 break;
101 default: return(EINVAL);
102 }
103 }
104 return(OK);
105 }
106
107 #endif /* USE_DEVIO */
108