2005-04-16 15:20:36 -07:00
/*
*
2012-02-19 19:52:38 -08:00
Copyright ( c ) Eicon Networks , 2002.
2005-04-16 15:20:36 -07:00
*
2012-02-19 19:52:38 -08:00
This source file is supplied for the use with
Eicon Networks range of DIVA Server Adapters .
2005-04-16 15:20:36 -07:00
*
2012-02-19 19:52:38 -08:00
Eicon File Revision : 2.1
2005-04-16 15:20:36 -07:00
*
2012-02-19 19:52:38 -08:00
This program is free software ; you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation ; either version 2 , or ( at your option )
any later version .
2005-04-16 15:20:36 -07:00
*
2012-02-19 19:52:38 -08:00
This program is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY OF ANY KIND WHATSOEVER INCLUDING ANY
implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE .
See the GNU General Public License for more details .
2005-04-16 15:20:36 -07:00
*
2012-02-19 19:52:38 -08:00
You should have received a copy of the GNU General Public License
along with this program ; if not , write to the Free Software
Foundation , Inc . , 675 Mass Ave , Cambridge , MA 0213 9 , USA .
2005-04-16 15:20:36 -07:00
*
*/
# include "platform.h"
# include "pc.h"
# include "debuglib.h"
# include "di_defs.h"
# include "divasync.h"
# include "dadapter.h"
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Adapter array change notification framework
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
typedef struct _didd_adapter_change_notification {
2012-02-19 19:52:38 -08:00
didd_adapter_change_callback_t callback ;
void IDI_CALL_ENTITY_T * context ;
} didd_adapter_change_notification_t , \
* IDI_CALL_ENTITY_T pdidd_adapter_change_notification_t ;
2005-04-16 15:20:36 -07:00
# define DIVA_DIDD_MAX_NOTIFICATIONS 256
2012-02-19 19:52:38 -08:00
static didd_adapter_change_notification_t \
NotificationTable [ DIVA_DIDD_MAX_NOTIFICATIONS ] ;
2005-04-16 15:20:36 -07:00
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Array to held adapter information
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static DESCRIPTOR HandleTable [ NEW_MAX_DESCRIPTORS ] ;
2005-06-28 20:44:56 -07:00
static dword Adapters = 0 ; /* Number of adapters */
2005-04-16 15:20:36 -07:00
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Shadow IDI_DIMAINT
and ' shadow ' debug stuff
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-02-19 19:52:38 -08:00
static void no_printf ( unsigned char * format , . . . )
2005-04-16 15:20:36 -07:00
{
# ifdef EBUG
va_list ap ;
2012-02-19 19:52:38 -08:00
va_start ( ap , format ) ;
2005-04-16 15:20:36 -07:00
debug ( ( format , ap ) ) ;
2012-02-19 19:52:38 -08:00
va_end ( ap ) ;
2005-04-16 15:20:36 -07:00
# endif
}
/* -------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Portable debug Library
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2005-04-16 15:20:36 -07:00
# include "debuglib.c"
2012-02-19 19:52:38 -08:00
2005-04-16 15:20:36 -07:00
static DESCRIPTOR MAdapter = { IDI_DIMAINT , /* Adapter Type */
2012-02-19 19:52:38 -08:00
0x00 , /* Channels */
0x0000 , /* Features */
( IDI_CALL ) no_printf } ;
2005-04-16 15:20:36 -07:00
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
DAdapter . Only IDI clients with buffer , that is huge enough to
get all descriptors will receive information about DAdapter
{ byte type , byte channels , word features , IDI_CALL request }
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-02-19 19:52:38 -08:00
static void IDI_CALL_LINK_T diva_dadapter_request ( ENTITY IDI_CALL_ENTITY_T * ) ;
2005-04-16 15:20:36 -07:00
static DESCRIPTOR DAdapter = { IDI_DADAPTER , /* Adapter Type */
2012-02-19 19:52:38 -08:00
0x00 , /* Channels */
0x0000 , /* Features */
diva_dadapter_request } ;
2005-04-16 15:20:36 -07:00
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
LOCALS
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-02-19 19:52:38 -08:00
static dword diva_register_adapter_callback ( \
didd_adapter_change_callback_t callback ,
void IDI_CALL_ENTITY_T * context ) ;
static void diva_remove_adapter_callback ( dword handle ) ;
static void diva_notify_adapter_change ( DESCRIPTOR * d , int removal ) ;
2005-04-16 15:20:36 -07:00
static diva_os_spin_lock_t didd_spin ;
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Should be called as first step , after driver init
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void diva_didd_load_time_init ( void ) {
memset ( & HandleTable [ 0 ] , 0x00 , sizeof ( HandleTable ) ) ;
memset ( & NotificationTable [ 0 ] , 0x00 , sizeof ( NotificationTable ) ) ;
diva_os_initialize_spin_lock ( & didd_spin , " didd " ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Should be called as last step , if driver does unload
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void diva_didd_load_time_finit ( void ) {
diva_os_destroy_spin_lock ( & didd_spin , " didd " ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Called in order to register new adapter in adapter array
return adapter handle ( > 0 ) on success
return - 1 adapter array overflow
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static int diva_didd_add_descriptor ( DESCRIPTOR * d ) {
diva_os_spin_lock_magic_t irql ;
int i ;
if ( d - > type = = IDI_DIMAINT ) {
if ( d - > request ) {
MAdapter . request = d - > request ;
dprintf = ( DIVA_DI_PRINTF ) d - > request ;
diva_notify_adapter_change ( & MAdapter , 0 ) ; /* Inserted */
DBG_TRC ( ( " DIMAINT registered, dprintf=%08x " , d - > request ) )
} else {
DBG_TRC ( ( " DIMAINT removed " ) )
diva_notify_adapter_change ( & MAdapter , 1 ) ; /* About to remove */
MAdapter . request = ( IDI_CALL ) no_printf ;
dprintf = no_printf ;
}
return ( NEW_MAX_DESCRIPTORS ) ;
}
for ( i = 0 ; i < NEW_MAX_DESCRIPTORS ; i + + ) {
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_add " ) ;
if ( HandleTable [ i ] . type = = 0 ) {
memcpy ( & HandleTable [ i ] , d , sizeof ( * d ) ) ;
Adapters + + ;
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_add " ) ;
diva_notify_adapter_change ( d , 0 ) ; /* we have new adapter */
DBG_TRC ( ( " Add adapter[%d], request=%08x " , ( i + 1 ) , d - > request ) )
return ( i + 1 ) ;
}
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_add " ) ;
}
DBG_ERR ( ( " Can't add adapter, out of resources " ) )
return ( - 1 ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Called in order to remove one registered adapter from array
return adapter handle ( > 0 ) on success
return 0 on success
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static int diva_didd_remove_descriptor ( IDI_CALL request ) {
diva_os_spin_lock_magic_t irql ;
int i ;
if ( request = = MAdapter . request ) {
DBG_TRC ( ( " DIMAINT removed " ) )
dprintf = no_printf ;
diva_notify_adapter_change ( & MAdapter , 1 ) ; /* About to remove */
MAdapter . request = ( IDI_CALL ) no_printf ;
return ( 0 ) ;
}
for ( i = 0 ; ( Adapters & & ( i < NEW_MAX_DESCRIPTORS ) ) ; i + + ) {
if ( HandleTable [ i ] . request = = request ) {
diva_notify_adapter_change ( & HandleTable [ i ] , 1 ) ; /* About to remove */
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_rm " ) ;
memset ( & HandleTable [ i ] , 0x00 , sizeof ( HandleTable [ 0 ] ) ) ;
Adapters - - ;
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_rm " ) ;
DBG_TRC ( ( " Remove adapter[%d], request=%08x " , ( i + 1 ) , request ) )
return ( 0 ) ;
}
}
DBG_ERR ( ( " Invalid request=%08x, can't remove adapter " , request ) )
return ( - 1 ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Read adapter array
return 1 if not enough space to save all available adapters
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-02-19 19:52:38 -08:00
static int diva_didd_read_adapter_array ( DESCRIPTOR * buffer , int length ) {
diva_os_spin_lock_magic_t irql ;
int src , dst ;
memset ( buffer , 0x00 , length ) ;
length / = sizeof ( DESCRIPTOR ) ;
DBG_TRC ( ( " DIDD_Read, space = %d, Adapters = %d " , length , Adapters + 2 ) )
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_read " ) ;
for ( src = 0 , dst = 0 ;
( Adapters & & ( src < NEW_MAX_DESCRIPTORS ) & & ( dst < length ) ) ;
src + + ) {
if ( HandleTable [ src ] . type ) {
memcpy ( & buffer [ dst ] , & HandleTable [ src ] , sizeof ( DESCRIPTOR ) ) ;
dst + + ;
}
}
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_read " ) ;
if ( dst < length ) {
memcpy ( & buffer [ dst ] , & MAdapter , sizeof ( DESCRIPTOR ) ) ;
dst + + ;
} else {
DBG_ERR ( ( " Can't write DIMAINT. Array too small " ) )
}
if ( dst < length ) {
memcpy ( & buffer [ dst ] , & DAdapter , sizeof ( DESCRIPTOR ) ) ;
dst + + ;
} else {
DBG_ERR ( ( " Can't write DADAPTER. Array too small " ) )
}
DBG_TRC ( ( " Read %d adapters " , dst ) )
return ( dst = = length ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
DAdapter request function .
This function does process only synchronous requests , and is used
for reception / registration of new interfaces
2005-04-16 15:20:36 -07:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
2012-02-19 19:52:38 -08:00
static void IDI_CALL_LINK_T diva_dadapter_request ( \
ENTITY IDI_CALL_ENTITY_T * e ) {
IDI_SYNC_REQ * syncReq = ( IDI_SYNC_REQ * ) e ;
if ( e - > Req ) { /* We do not process it, also return error */
e - > Rc = OUT_OF_RESOURCES ;
DBG_ERR ( ( " Can't process async request, Req=%02x " , e - > Req ) )
return ;
}
/*
So , we process sync request
*/
switch ( e - > Rc ) {
case IDI_SYNC_REQ_DIDD_REGISTER_ADAPTER_NOTIFY : {
diva_didd_adapter_notify_t * pinfo = & syncReq - > didd_notify . info ;
pinfo - > handle = diva_register_adapter_callback ( \
( didd_adapter_change_callback_t ) pinfo - > callback ,
( void IDI_CALL_ENTITY_T * ) pinfo - > context ) ;
e - > Rc = 0xff ;
} break ;
case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER_NOTIFY : {
diva_didd_adapter_notify_t * pinfo = & syncReq - > didd_notify . info ;
diva_remove_adapter_callback ( pinfo - > handle ) ;
e - > Rc = 0xff ;
} break ;
case IDI_SYNC_REQ_DIDD_ADD_ADAPTER : {
diva_didd_add_adapter_t * pinfo = & syncReq - > didd_add_adapter . info ;
if ( diva_didd_add_descriptor ( ( DESCRIPTOR * ) pinfo - > descriptor ) < 0 ) {
e - > Rc = OUT_OF_RESOURCES ;
} else {
e - > Rc = 0xff ;
}
} break ;
case IDI_SYNC_REQ_DIDD_REMOVE_ADAPTER : {
diva_didd_remove_adapter_t * pinfo = & syncReq - > didd_remove_adapter . info ;
if ( diva_didd_remove_descriptor ( ( IDI_CALL ) pinfo - > p_request ) < 0 ) {
e - > Rc = OUT_OF_RESOURCES ;
} else {
e - > Rc = 0xff ;
}
} break ;
case IDI_SYNC_REQ_DIDD_READ_ADAPTER_ARRAY : {
diva_didd_read_adapter_array_t * pinfo = \
& syncReq - > didd_read_adapter_array . info ;
if ( diva_didd_read_adapter_array ( ( DESCRIPTOR * ) pinfo - > buffer ,
( int ) pinfo - > length ) ) {
e - > Rc = OUT_OF_RESOURCES ;
} else {
e - > Rc = 0xff ;
}
} break ;
default :
DBG_ERR ( ( " Can't process sync request, Req=%02x " , e - > Rc ) )
e - > Rc = OUT_OF_RESOURCES ;
}
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
IDI client does register his notification function
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static dword diva_register_adapter_callback ( \
didd_adapter_change_callback_t callback ,
void IDI_CALL_ENTITY_T * context ) {
diva_os_spin_lock_magic_t irql ;
dword i ;
for ( i = 0 ; i < DIVA_DIDD_MAX_NOTIFICATIONS ; i + + ) {
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_nfy_add " ) ;
if ( ! NotificationTable [ i ] . callback ) {
NotificationTable [ i ] . callback = callback ;
NotificationTable [ i ] . context = context ;
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_nfy_add " ) ;
DBG_TRC ( ( " Register adapter notification[%d]=%08x " , i + 1 , callback ) )
return ( i + 1 ) ;
}
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_nfy_add " ) ;
}
DBG_ERR ( ( " Can't register adapter notification, overflow " ) )
return ( 0 ) ;
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
IDI client does register his notification function
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static void diva_remove_adapter_callback ( dword handle ) {
diva_os_spin_lock_magic_t irql ;
if ( handle & & ( ( - - handle ) < DIVA_DIDD_MAX_NOTIFICATIONS ) ) {
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_nfy_rm " ) ;
NotificationTable [ handle ] . callback = NULL ;
NotificationTable [ handle ] . context = NULL ;
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_nfy_rm " ) ;
DBG_TRC ( ( " Remove adapter notification[%d] " , ( int ) ( handle + 1 ) ) )
return ;
}
DBG_ERR ( ( " Can't remove adapter notification, handle=%d " , handle ) )
}
2005-04-16 15:20:36 -07:00
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
Notify all client about adapter array change
Does suppose following behavior in the client side :
Step 1 : Redister Notification
Step 2 : Read Adapter Array
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
static void diva_notify_adapter_change ( DESCRIPTOR * d , int removal ) {
int i , do_notify ;
didd_adapter_change_notification_t nfy ;
diva_os_spin_lock_magic_t irql ;
for ( i = 0 ; i < DIVA_DIDD_MAX_NOTIFICATIONS ; i + + ) {
do_notify = 0 ;
diva_os_enter_spin_lock ( & didd_spin , & irql , " didd_nfy " ) ;
if ( NotificationTable [ i ] . callback ) {
memcpy ( & nfy , & NotificationTable [ i ] , sizeof ( nfy ) ) ;
do_notify = 1 ;
}
diva_os_leave_spin_lock ( & didd_spin , & irql , " didd_nfy " ) ;
if ( do_notify ) {
( * ( nfy . callback ) ) ( nfy . context , d , removal ) ;
}
}
2005-04-16 15:20:36 -07:00
}
/* --------------------------------------------------------------------------
2012-02-19 19:52:38 -08:00
For all systems , that are linked by Kernel Mode Linker this is ONLY one
function thet should be exported by this device driver
IDI clients should look for IDI_DADAPTER , and use request function
of this adapter ( sync request ) in order to receive appropriate services :
- add new adapter
- remove existing adapter
- add adapter array notification
- remove adapter array notification
( read adapter is redundant in this case )
INPUT :
2005-04-16 15:20:36 -07:00
buffer - pointer to buffer that will receive adapter array
length - length ( in bytes ) of space in buffer
2012-02-19 19:52:38 -08:00
OUTPUT :
2005-04-16 15:20:36 -07:00
Adapter array will be written to memory described by ' buffer '
If the last adapter seen in the returned adapter array is
IDI_DADAPTER or if last adapter in array does have type ' 0 ' , then
it was enougth space in buffer to accommodate all available
adapter descriptors
2012-02-19 19:52:38 -08:00
* NOTE 1 ( debug interface ) :
2005-04-16 15:20:36 -07:00
The IDI adapter of type ' IDI_DIMAINT ' does register as ' request '
famous ' dprintf ' function ( of type DI_PRINTF , please look
include / debuglib . c and include / debuglib . h ) for details .
So dprintf is not exported from module debug module directly ,
instead of this IDI_DIMAINT is registered .
Module load order will receive in this case :
2012-02-19 19:52:38 -08:00
1. DIDD ( this file )
2. DIMAINT does load and register ' IDI_DIMAINT ' , at this step
DIDD should be able to get ' dprintf ' , save it , and
register with DIDD by means of ' dprintf ' function .
3. any other driver is loaded and is able to access adapter array
and debug interface
2005-04-16 15:20:36 -07:00
This approach does allow to load / unload debug interface on demand ,
and save memory , it it is necessary .
2012-02-19 19:52:38 -08:00
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
void IDI_CALL_LINK_T DIVA_DIDD_Read ( void IDI_CALL_ENTITY_T * buffer ,
int length ) {
diva_didd_read_adapter_array ( buffer , length ) ;
2005-04-16 15:20:36 -07:00
}