2005-04-16 15:20:36 -07:00
/* $Id: mntfunc.c,v 1.19.6.4 2005/01/31 12:22:20 armin Exp $
*
* Driver for Eicon DIVA Server ISDN cards .
* Maint module
*
* Copyright 2000 - 2003 by Armin Schindler ( mac @ melware . de )
* Copyright 2000 - 2003 Cytronics & Melware ( info @ melware . de )
*
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*/
# include "platform.h"
# include "di_defs.h"
# include "divasync.h"
# include "debug_if.h"
extern char * DRIVERRELEASE_MNT ;
# define DBG_MINIMUM (DL_LOG + DL_FTL + DL_ERR)
# define DBG_DEFAULT (DBG_MINIMUM + DL_XLOG + DL_REG)
extern void DIVA_DIDD_Read ( void * , int ) ;
static dword notify_handle ;
static DESCRIPTOR DAdapter ;
static DESCRIPTOR MAdapter ;
static DESCRIPTOR MaintDescriptor =
2012-02-19 19:52:38 -08:00
{ IDI_DIMAINT , 0 , 0 , ( IDI_CALL ) diva_maint_prtComp } ;
2005-04-16 15:20:36 -07:00
extern int diva_os_copy_to_user ( void * os_handle , void __user * dst ,
const void * src , int length ) ;
extern int diva_os_copy_from_user ( void * os_handle , void * dst ,
const void __user * src , int length ) ;
static void no_printf ( unsigned char * x , . . . )
{
/* dummy debug function */
}
# include "debuglib.c"
/*
* DIDD callback function
*/
2012-02-19 19:52:38 -08:00
static void * didd_callback ( void * context , DESCRIPTOR * adapter ,
2005-04-16 15:20:36 -07:00
int removal )
{
if ( adapter - > type = = IDI_DADAPTER ) {
DBG_ERR ( ( " cb: Change in DAdapter ? Oops ?. " ) ) ;
} else if ( adapter - > type = = IDI_DIMAINT ) {
if ( removal ) {
DbgDeregister ( ) ;
memset ( & MAdapter , 0 , sizeof ( MAdapter ) ) ;
dprintf = no_printf ;
} else {
memcpy ( & MAdapter , adapter , sizeof ( MAdapter ) ) ;
dprintf = ( DIVA_DI_PRINTF ) MAdapter . request ;
DbgRegister ( " MAINT " , DRIVERRELEASE_MNT , DBG_DEFAULT ) ;
}
} else if ( ( adapter - > type > 0 ) & & ( adapter - > type < 16 ) ) {
if ( removal ) {
diva_mnt_remove_xdi_adapter ( adapter ) ;
} else {
diva_mnt_add_xdi_adapter ( adapter ) ;
}
}
return ( NULL ) ;
}
/*
* connect to didd
*/
2012-04-24 12:56:03 +00:00
static int __init connect_didd ( void )
2005-04-16 15:20:36 -07:00
{
int x = 0 ;
int dadapter = 0 ;
IDI_SYNC_REQ req ;
DESCRIPTOR DIDD_Table [ MAX_DESCRIPTORS ] ;
DIVA_DIDD_Read ( DIDD_Table , sizeof ( DIDD_Table ) ) ;
for ( x = 0 ; x < MAX_DESCRIPTORS ; x + + ) {
if ( DIDD_Table [ x ] . type = = IDI_DADAPTER ) { /* DADAPTER found */
dadapter = 1 ;
memcpy ( & DAdapter , & DIDD_Table [ x ] , sizeof ( DAdapter ) ) ;
req . didd_notify . e . Req = 0 ;
req . didd_notify . e . Rc =
2012-02-19 19:52:38 -08:00
IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY ;
2005-04-16 15:20:36 -07:00
req . didd_notify . info . callback = ( void * ) didd_callback ;
req . didd_notify . info . context = NULL ;
2012-02-19 19:52:38 -08:00
DAdapter . request ( ( ENTITY * ) & req ) ;
2005-04-16 15:20:36 -07:00
if ( req . didd_notify . e . Rc ! = 0xff )
return ( 0 ) ;
notify_handle = req . didd_notify . info . handle ;
/* Register MAINT (me) */
req . didd_add_adapter . e . Req = 0 ;
req . didd_add_adapter . e . Rc =
2012-02-19 19:52:38 -08:00
IDI_SYNC_REQ_DIDD_ADD_ADAPTER ;
2005-04-16 15:20:36 -07:00
req . didd_add_adapter . info . descriptor =
2012-02-19 19:52:38 -08:00
( void * ) & MaintDescriptor ;
DAdapter . request ( ( ENTITY * ) & req ) ;
2005-04-16 15:20:36 -07:00
if ( req . didd_add_adapter . e . Rc ! = 0xff )
return ( 0 ) ;
} else if ( ( DIDD_Table [ x ] . type > 0 )
& & ( DIDD_Table [ x ] . type < 16 ) ) {
diva_mnt_add_xdi_adapter ( & DIDD_Table [ x ] ) ;
}
}
return ( dadapter ) ;
}
/*
* disconnect from didd
*/
2012-04-24 12:56:03 +00:00
static void __exit disconnect_didd ( void )
2005-04-16 15:20:36 -07:00
{
IDI_SYNC_REQ req ;
req . didd_notify . e . Req = 0 ;
req . didd_notify . e . Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY ;
req . didd_notify . info . handle = notify_handle ;
2012-02-19 19:52:38 -08:00
DAdapter . request ( ( ENTITY * ) & req ) ;
2005-04-16 15:20:36 -07:00
req . didd_remove_adapter . e . Req = 0 ;
req . didd_remove_adapter . e . Rc = IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER ;
req . didd_remove_adapter . info . p_request =
2012-02-19 19:52:38 -08:00
( IDI_CALL ) MaintDescriptor . request ;
DAdapter . request ( ( ENTITY * ) & req ) ;
2005-04-16 15:20:36 -07:00
}
/*
* read / write maint
*/
int maint_read_write ( void __user * buf , int count )
{
byte data [ 128 ] ;
dword cmd , id , mask ;
int ret = 0 ;
if ( count < ( 3 * sizeof ( dword ) ) )
return ( - EFAULT ) ;
if ( diva_os_copy_from_user ( NULL , ( void * ) & data [ 0 ] ,
buf , 3 * sizeof ( dword ) ) ) {
return ( - EFAULT ) ;
}
2012-02-19 19:52:38 -08:00
cmd = * ( dword * ) & data [ 0 ] ; /* command */
id = * ( dword * ) & data [ 4 ] ; /* driver id */
mask = * ( dword * ) & data [ 8 ] ; /* mask or size */
2005-04-16 15:20:36 -07:00
switch ( cmd ) {
case DITRACE_CMD_GET_DRIVER_INFO :
if ( ( ret = diva_get_driver_info ( id , data , sizeof ( data ) ) ) > 0 ) {
if ( ( count < ret ) | | diva_os_copy_to_user
( NULL , buf , ( void * ) & data [ 0 ] , ret ) )
ret = - EFAULT ;
} else {
ret = - EINVAL ;
}
break ;
case DITRACE_READ_DRIVER_DBG_MASK :
if ( ( ret = diva_get_driver_dbg_mask ( id , ( byte * ) data ) ) > 0 ) {
if ( ( count < ret ) | | diva_os_copy_to_user
( NULL , buf , ( void * ) & data [ 0 ] , ret ) )
ret = - EFAULT ;
} else {
ret = - ENODEV ;
}
break ;
case DITRACE_WRITE_DRIVER_DBG_MASK :
if ( ( ret = diva_set_driver_dbg_mask ( id , mask ) ) < = 0 ) {
ret = - ENODEV ;
}
break ;
2012-02-19 19:52:38 -08:00
/*
Filter commands will ignore the ID due to fact that filtering affects
the B - channel and Audio Tap trace levels only . Also MAINT driver will
select the right trace ID by itself
*/
2005-04-16 15:20:36 -07:00
case DITRACE_WRITE_SELECTIVE_TRACE_FILTER :
if ( ! mask ) {
2012-02-19 19:52:38 -08:00
ret = diva_set_trace_filter ( 1 , " * " ) ;
2005-04-16 15:20:36 -07:00
} else if ( mask < sizeof ( data ) ) {
2012-02-19 19:52:38 -08:00
if ( diva_os_copy_from_user ( NULL , data , ( char __user * ) buf + 12 , mask ) ) {
2005-04-16 15:20:36 -07:00
ret = - EFAULT ;
} else {
2012-02-19 19:52:38 -08:00
ret = diva_set_trace_filter ( ( int ) mask , data ) ;
2005-04-16 15:20:36 -07:00
}
} else {
ret = - EINVAL ;
}
break ;
case DITRACE_READ_SELECTIVE_TRACE_FILTER :
2012-02-19 19:52:38 -08:00
if ( ( ret = diva_get_trace_filter ( sizeof ( data ) , data ) ) > 0 ) {
if ( diva_os_copy_to_user ( NULL , buf , data , ret ) )
2005-04-16 15:20:36 -07:00
ret = - EFAULT ;
} else {
ret = - ENODEV ;
}
break ;
case DITRACE_READ_TRACE_ENTRY : {
2012-02-19 19:52:38 -08:00
diva_os_spin_lock_magic_t old_irql ;
word size ;
diva_dbg_entry_head_t * pmsg ;
byte * pbuf ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ! ( pbuf = diva_os_malloc ( 0 , mask ) ) ) {
return ( - ENOMEM ) ;
}
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
for ( ; ; ) {
if ( ! ( pmsg =
diva_maint_get_message ( & size , & old_irql ) ) ) {
break ;
}
if ( size > mask ) {
diva_maint_ack_message ( 0 , & old_irql ) ;
ret = - EINVAL ;
2005-04-16 15:20:36 -07:00
break ;
}
2012-02-19 19:52:38 -08:00
ret = size ;
memcpy ( pbuf , pmsg , size ) ;
diva_maint_ack_message ( 1 , & old_irql ) ;
if ( ( count < size ) | |
diva_os_copy_to_user ( NULL , buf , ( void * ) pbuf , size ) )
ret = - EFAULT ;
break ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
diva_os_free ( 0 , pbuf ) ;
}
2005-04-16 15:20:36 -07:00
break ;
case DITRACE_READ_TRACE_ENTRYS : {
2012-02-19 19:52:38 -08:00
diva_os_spin_lock_magic_t old_irql ;
word size ;
diva_dbg_entry_head_t * pmsg ;
byte * pbuf = NULL ;
int written = 0 ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( mask < 4096 ) {
ret = - EINVAL ;
break ;
}
if ( ! ( pbuf = diva_os_malloc ( 0 , mask ) ) ) {
return ( - ENOMEM ) ;
}
for ( ; ; ) {
if ( ! ( pmsg =
diva_maint_get_message ( & size , & old_irql ) ) ) {
2005-04-16 15:20:36 -07:00
break ;
}
2012-02-19 19:52:38 -08:00
if ( ( size + 8 ) > mask ) {
diva_maint_ack_message ( 0 , & old_irql ) ;
break ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
/*
Write entry length
*/
pbuf [ written + + ] = ( byte ) size ;
pbuf [ written + + ] = ( byte ) ( size > > 8 ) ;
2005-04-16 15:20:36 -07:00
pbuf [ written + + ] = 0 ;
pbuf [ written + + ] = 0 ;
2012-02-19 19:52:38 -08:00
/*
Write message
*/
memcpy ( & pbuf [ written ] , pmsg , size ) ;
diva_maint_ack_message ( 1 , & old_irql ) ;
written + = size ;
mask - = ( size + 4 ) ;
}
pbuf [ written + + ] = 0 ;
pbuf [ written + + ] = 0 ;
pbuf [ written + + ] = 0 ;
pbuf [ written + + ] = 0 ;
2005-04-16 15:20:36 -07:00
2012-02-19 19:52:38 -08:00
if ( ( count < written ) | | diva_os_copy_to_user ( NULL , buf , ( void * ) pbuf , written ) ) {
ret = - EFAULT ;
} else {
ret = written ;
2005-04-16 15:20:36 -07:00
}
2012-02-19 19:52:38 -08:00
diva_os_free ( 0 , pbuf ) ;
}
2005-04-16 15:20:36 -07:00
break ;
default :
ret = - EINVAL ;
}
return ( ret ) ;
}
/*
* init
*/
2012-04-24 12:56:03 +00:00
int __init mntfunc_init ( int * buffer_length , void * * buffer ,
2005-04-16 15:20:36 -07:00
unsigned long diva_dbg_mem )
{
if ( * buffer_length < 64 ) {
* buffer_length = 64 ;
}
if ( * buffer_length > 512 ) {
* buffer_length = 512 ;
}
* buffer_length * = 1024 ;
if ( diva_dbg_mem ) {
* buffer = ( void * ) diva_dbg_mem ;
} else {
while ( ( * buffer_length > = ( 64 * 1024 ) )
& &
2012-02-19 19:52:38 -08:00
( ! ( * buffer = diva_os_malloc ( 0 , * buffer_length ) ) ) ) {
2005-04-16 15:20:36 -07:00
* buffer_length - = 1024 ;
}
if ( ! * buffer ) {
DBG_ERR ( ( " init: Can not alloc trace buffer " ) ) ;
return ( 0 ) ;
}
}
if ( diva_maint_init ( * buffer , * buffer_length , ( diva_dbg_mem = = 0 ) ) ) {
if ( ! diva_dbg_mem ) {
2012-02-19 19:52:38 -08:00
diva_os_free ( 0 , * buffer ) ;
2005-04-16 15:20:36 -07:00
}
DBG_ERR ( ( " init: maint init failed " ) ) ;
return ( 0 ) ;
}
if ( ! connect_didd ( ) ) {
DBG_ERR ( ( " init: failed to connect to DIDD. " ) ) ;
diva_maint_finit ( ) ;
if ( ! diva_dbg_mem ) {
2012-02-19 19:52:38 -08:00
diva_os_free ( 0 , * buffer ) ;
2005-04-16 15:20:36 -07:00
}
return ( 0 ) ;
}
return ( 1 ) ;
}
/*
* exit
*/
2012-04-24 12:56:03 +00:00
void __exit mntfunc_finit ( void )
2005-04-16 15:20:36 -07:00
{
void * buffer ;
int i = 100 ;
DbgDeregister ( ) ;
while ( diva_mnt_shutdown_xdi_adapters ( ) & & i - - ) {
diva_os_sleep ( 10 ) ;
}
disconnect_didd ( ) ;
if ( ( buffer = diva_maint_finit ( ) ) ) {
2012-02-19 19:52:38 -08:00
diva_os_free ( 0 , buffer ) ;
2005-04-16 15:20:36 -07:00
}
memset ( & MAdapter , 0 , sizeof ( MAdapter ) ) ;
dprintf = no_printf ;
}