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