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