xref: /minix/minix/kernel/system/do_devio.c (revision 9f81acbc)
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  *===========================================================================*/
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