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