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