2006-03-27 01:14:30 -08:00
/*
2008-02-04 22:31:02 -08:00
* Copyright ( C ) 2000 - 2007 Jeff Dike ( jdike @ { addtoit , linux . intel } . com )
2006-03-27 01:14:30 -08:00
* Licensed under the GPL
*/
# include <stdlib.h>
# include <errno.h>
2008-02-04 22:31:02 -08:00
# include <poll.h>
2006-03-27 01:14:30 -08:00
# include <signal.h>
# include <string.h>
# include "irq_user.h"
2008-02-04 22:31:02 -08:00
# include "kern_constants.h"
2006-03-27 01:14:30 -08:00
# include "os.h"
2008-02-04 22:31:02 -08:00
# include "process.h"
2006-10-19 23:28:20 -07:00
# include "um_malloc.h"
2008-02-04 22:31:02 -08:00
# include "user.h"
2006-03-27 01:14:30 -08:00
2007-02-10 01:44:23 -08:00
/*
* Locked by irq_lock in arch / um / kernel / irq . c . Changed by os_create_pollfd
* and os_free_irq_by_cb , which are called under irq_lock .
*/
2006-03-27 01:14:30 -08:00
static struct pollfd * pollfds = NULL ;
static int pollfds_num = 0 ;
static int pollfds_size = 0 ;
int os_waiting_for_events ( struct irq_fd * active_fds )
{
struct irq_fd * irq_fd ;
int i , n , err ;
n = poll ( pollfds , pollfds_num , 0 ) ;
2006-05-01 12:15:57 -07:00
if ( n < 0 ) {
2006-03-27 01:14:30 -08:00
err = - errno ;
2006-05-01 12:15:57 -07:00
if ( errno ! = EINTR )
2008-02-04 22:31:02 -08:00
printk ( UM_KERN_ERR " os_waiting_for_events: "
2006-03-27 01:14:30 -08:00
" poll returned %d, errno = %d \n " , n , errno ) ;
return err ;
}
2006-05-01 12:15:57 -07:00
if ( n = = 0 )
2006-03-27 01:14:30 -08:00
return 0 ;
irq_fd = active_fds ;
2006-05-01 12:15:57 -07:00
for ( i = 0 ; i < pollfds_num ; i + + ) {
if ( pollfds [ i ] . revents ! = 0 ) {
2006-03-27 01:14:30 -08:00
irq_fd - > current_events = pollfds [ i ] . revents ;
pollfds [ i ] . fd = - 1 ;
}
irq_fd = irq_fd - > next ;
}
return n ;
}
int os_create_pollfd ( int fd , int events , void * tmp_pfd , int size_tmpfds )
{
if ( pollfds_num = = pollfds_size ) {
if ( size_tmpfds < = pollfds_size * sizeof ( pollfds [ 0 ] ) ) {
/* return min size needed for new pollfds area */
2007-02-10 01:44:23 -08:00
return ( pollfds_size + 1 ) * sizeof ( pollfds [ 0 ] ) ;
2006-03-27 01:14:30 -08:00
}
2006-05-01 12:15:57 -07:00
if ( pollfds ! = NULL ) {
2006-03-27 01:14:30 -08:00
memcpy ( tmp_pfd , pollfds ,
sizeof ( pollfds [ 0 ] ) * pollfds_size ) ;
/* remove old pollfds */
kfree ( pollfds ) ;
}
pollfds = tmp_pfd ;
pollfds_size + + ;
2006-05-01 12:15:57 -07:00
} else
kfree ( tmp_pfd ) ; /* remove not used tmp_pfd */
2006-03-27 01:14:30 -08:00
2006-05-01 12:15:57 -07:00
pollfds [ pollfds_num ] = ( ( struct pollfd ) { . fd = fd ,
. events = events ,
. revents = 0 } ) ;
2006-03-27 01:14:30 -08:00
pollfds_num + + ;
2006-05-01 12:15:57 -07:00
return 0 ;
2006-03-27 01:14:30 -08:00
}
void os_free_irq_by_cb ( int ( * test ) ( struct irq_fd * , void * ) , void * arg ,
struct irq_fd * active_fds , struct irq_fd * * * last_irq_ptr2 )
{
struct irq_fd * * prev ;
int i = 0 ;
prev = & active_fds ;
2006-05-01 12:15:57 -07:00
while ( * prev ! = NULL ) {
if ( ( * test ) ( * prev , arg ) ) {
2006-03-27 01:14:30 -08:00
struct irq_fd * old_fd = * prev ;
2006-05-01 12:15:57 -07:00
if ( ( pollfds [ i ] . fd ! = - 1 ) & &
( pollfds [ i ] . fd ! = ( * prev ) - > fd ) ) {
2008-02-04 22:31:02 -08:00
printk ( UM_KERN_ERR " os_free_irq_by_cb - "
" mismatch between active_fds and "
" pollfds, fd %d vs %d \n " ,
2006-03-27 01:14:30 -08:00
( * prev ) - > fd , pollfds [ i ] . fd ) ;
goto out ;
}
pollfds_num - - ;
2008-02-04 22:31:02 -08:00
/*
* This moves the * whole * array after pollfds [ i ]
2006-03-27 01:14:30 -08:00
* ( though it doesn ' t spot as such ) !
*/
memmove ( & pollfds [ i ] , & pollfds [ i + 1 ] ,
( pollfds_num - i ) * sizeof ( pollfds [ 0 ] ) ) ;
2008-02-04 22:31:02 -08:00
if ( * last_irq_ptr2 = = & old_fd - > next )
2006-03-27 01:14:30 -08:00
* last_irq_ptr2 = prev ;
* prev = ( * prev ) - > next ;
2008-02-04 22:31:02 -08:00
if ( old_fd - > type = = IRQ_WRITE )
2006-03-27 01:14:30 -08:00
ignore_sigio_fd ( old_fd - > fd ) ;
kfree ( old_fd ) ;
continue ;
}
prev = & ( * prev ) - > next ;
i + + ;
}
out :
return ;
}
int os_get_pollfd ( int i )
{
2006-05-01 12:15:57 -07:00
return pollfds [ i ] . fd ;
2006-03-27 01:14:30 -08:00
}
void os_set_pollfd ( int i , int fd )
{
pollfds [ i ] . fd = fd ;
}
void os_set_ioignore ( void )
{
2006-09-25 23:33:04 -07:00
signal ( SIGIO , SIG_IGN ) ;
2006-03-27 01:14:30 -08:00
}