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