2005-04-16 15:20:36 -07:00
/* $Id: packet.c,v 1.5.8.1 2001/09/23 22:24:59 kai Exp $
*
* Copyright ( C ) 1996 SpellCaster Telecommunications Inc .
*
* This software may be used and distributed according to the terms
* of the GNU General Public License , incorporated herein by reference .
*
* For more information , please contact gpl - info @ spellcast . com or write :
*
* SpellCaster Telecommunications Inc .
* 5621 Finch Avenue East , Unit # 3
* Scarborough , Ontario Canada
* M1B 2 T9
* + 1 ( 416 ) 297 - 8565
* + 1 ( 416 ) 297 - 6433 Facsimile
*/
# include "includes.h"
# include "hardware.h"
# include "message.h"
# include "card.h"
2007-11-14 15:57:38 -08:00
int sndpkt ( int devId , int channel , int ack , struct sk_buff * data )
2005-04-16 15:20:36 -07:00
{
LLData ReqLnkWrite ;
int status ;
int card ;
unsigned long len ;
card = get_card_from_id ( devId ) ;
if ( ! IS_VALID_CARD ( card ) ) {
pr_debug ( " invalid param: %d is not a valid card id \n " , card ) ;
return - ENODEV ;
}
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: sndpkt: frst = 0x%lx nxt = %d f = %d n = %d \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
sc_adapter [ card ] - > channel [ channel ] . first_sendbuf ,
sc_adapter [ card ] - > channel [ channel ] . next_sendbuf ,
sc_adapter [ card ] - > channel [ channel ] . free_sendbufs ,
sc_adapter [ card ] - > channel [ channel ] . num_sendbufs ) ;
if ( ! sc_adapter [ card ] - > channel [ channel ] . free_sendbufs ) {
pr_debug ( " %s: out of TX buffers \n " ,
sc_adapter [ card ] - > devicename ) ;
return - EINVAL ;
}
if ( data - > len > BUFFER_SIZE ) {
pr_debug ( " %s: data overflows buffer size (data > buffer) \n " ,
sc_adapter [ card ] - > devicename ) ;
return - EINVAL ;
}
ReqLnkWrite . buff_offset = sc_adapter [ card ] - > channel [ channel ] . next_sendbuf *
BUFFER_SIZE + sc_adapter [ card ] - > channel [ channel ] . first_sendbuf ;
ReqLnkWrite . msg_len = data - > len ; /* sk_buff size */
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: writing %d bytes to buffer offset 0x%lx \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
ReqLnkWrite . msg_len , ReqLnkWrite . buff_offset ) ;
memcpy_toshmem ( card , ( char * ) ReqLnkWrite . buff_offset , data - > data , ReqLnkWrite . msg_len ) ;
/*
* sendmessage
*/
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: sndpkt size=%d, buf_offset=0x%lx buf_indx=%d \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
ReqLnkWrite . msg_len , ReqLnkWrite . buff_offset ,
sc_adapter [ card ] - > channel [ channel ] . next_sendbuf ) ;
status = sendmessage ( card , CEPID , ceReqTypeLnk , ceReqClass1 , ceReqLnkWrite ,
channel + 1 , sizeof ( LLData ) , ( unsigned int * ) & ReqLnkWrite ) ;
len = data - > len ;
if ( status ) {
pr_debug ( " %s: failed to send packet, status = %d \n " ,
sc_adapter [ card ] - > devicename , status ) ;
return - 1 ;
}
else {
sc_adapter [ card ] - > channel [ channel ] . free_sendbufs - - ;
sc_adapter [ card ] - > channel [ channel ] . next_sendbuf =
+ + sc_adapter [ card ] - > channel [ channel ] . next_sendbuf = =
sc_adapter [ card ] - > channel [ channel ] . num_sendbufs ? 0 :
sc_adapter [ card ] - > channel [ channel ] . next_sendbuf ;
pr_debug ( " %s: packet sent successfully \n " , sc_adapter [ card ] - > devicename ) ;
dev_kfree_skb ( data ) ;
indicate_status ( card , ISDN_STAT_BSENT , channel , ( char * ) & len ) ;
}
return len ;
}
void rcvpkt ( int card , RspMessage * rcvmsg )
{
LLData newll ;
struct sk_buff * skb ;
if ( ! IS_VALID_CARD ( card ) ) {
pr_debug ( " invalid param: %d is not a valid card id \n " , card ) ;
return ;
}
switch ( rcvmsg - > rsp_status ) {
case 0x01 :
case 0x02 :
case 0x70 :
pr_debug ( " %s: error status code: 0x%x \n " ,
sc_adapter [ card ] - > devicename , rcvmsg - > rsp_status ) ;
return ;
case 0x00 :
if ( ! ( skb = dev_alloc_skb ( rcvmsg - > msg_data . response . msg_len ) ) ) {
printk ( KERN_WARNING " %s: rcvpkt out of memory, dropping packet \n " ,
sc_adapter [ card ] - > devicename ) ;
return ;
}
skb_put ( skb , rcvmsg - > msg_data . response . msg_len ) ;
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: getting data from offset: 0x%lx \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
rcvmsg - > msg_data . response . buff_offset ) ;
memcpy_fromshmem ( card ,
skb_put ( skb , rcvmsg - > msg_data . response . msg_len ) ,
( char * ) rcvmsg - > msg_data . response . buff_offset ,
rcvmsg - > msg_data . response . msg_len ) ;
sc_adapter [ card ] - > card - > rcvcallb_skb ( sc_adapter [ card ] - > driverId ,
rcvmsg - > phy_link_no - 1 , skb ) ;
case 0x03 :
/*
* Recycle the buffer
*/
pr_debug ( " %s: buffer size : %d \n " ,
sc_adapter [ card ] - > devicename , BUFFER_SIZE ) ;
/* memset_shmem(card, rcvmsg->msg_data.response.buff_offset, 0, BUFFER_SIZE); */
newll . buff_offset = rcvmsg - > msg_data . response . buff_offset ;
newll . msg_len = BUFFER_SIZE ;
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: recycled buffer at offset 0x%lx size %d \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
newll . buff_offset , newll . msg_len ) ;
sendmessage ( card , CEPID , ceReqTypeLnk , ceReqClass1 , ceReqLnkRead ,
rcvmsg - > phy_link_no , sizeof ( LLData ) , ( unsigned int * ) & newll ) ;
}
}
int setup_buffers ( int card , int c )
{
unsigned int nBuffers , i , cBase ;
unsigned int buffer_size ;
LLData RcvBuffOffset ;
if ( ! IS_VALID_CARD ( card ) ) {
pr_debug ( " invalid param: %d is not a valid card id \n " , card ) ;
return - ENODEV ;
}
/*
* Calculate the buffer offsets ( send / recv / send / recv )
*/
pr_debug ( " %s: setting up channel buffer space in shared RAM \n " ,
sc_adapter [ card ] - > devicename ) ;
buffer_size = BUFFER_SIZE ;
nBuffers = ( ( sc_adapter [ card ] - > ramsize - BUFFER_BASE ) / buffer_size ) / 2 ;
nBuffers = nBuffers > BUFFERS_MAX ? BUFFERS_MAX : nBuffers ;
pr_debug ( " %s: calculating buffer space: %d buffers, %d big \n " ,
sc_adapter [ card ] - > devicename ,
nBuffers , buffer_size ) ;
if ( nBuffers < 2 ) {
pr_debug ( " %s: not enough buffer space \n " ,
sc_adapter [ card ] - > devicename ) ;
return - 1 ;
}
cBase = ( nBuffers * buffer_size ) * ( c - 1 ) ;
pr_debug ( " %s: channel buffer offset from shared RAM: 0x%x \n " ,
sc_adapter [ card ] - > devicename , cBase ) ;
sc_adapter [ card ] - > channel [ c - 1 ] . first_sendbuf = BUFFER_BASE + cBase ;
sc_adapter [ card ] - > channel [ c - 1 ] . num_sendbufs = nBuffers / 2 ;
sc_adapter [ card ] - > channel [ c - 1 ] . free_sendbufs = nBuffers / 2 ;
sc_adapter [ card ] - > channel [ c - 1 ] . next_sendbuf = 0 ;
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: send buffer setup complete: first=0x%lx n=%d f=%d, nxt=%d \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
sc_adapter [ card ] - > channel [ c - 1 ] . first_sendbuf ,
sc_adapter [ card ] - > channel [ c - 1 ] . num_sendbufs ,
sc_adapter [ card ] - > channel [ c - 1 ] . free_sendbufs ,
sc_adapter [ card ] - > channel [ c - 1 ] . next_sendbuf ) ;
/*
* Prep the receive buffers
*/
pr_debug ( " %s: adding %d RecvBuffers: \n " ,
sc_adapter [ card ] - > devicename , nBuffers / 2 ) ;
for ( i = 0 ; i < nBuffers / 2 ; i + + ) {
RcvBuffOffset . buff_offset =
( ( sc_adapter [ card ] - > channel [ c - 1 ] . first_sendbuf +
( nBuffers / 2 ) * buffer_size ) + ( buffer_size * i ) ) ;
RcvBuffOffset . msg_len = buffer_size ;
2006-10-11 01:22:25 -07:00
pr_debug ( " %s: adding RcvBuffer #%d offset=0x%lx sz=%d bufsz:%d \n " ,
2005-04-16 15:20:36 -07:00
sc_adapter [ card ] - > devicename ,
i + 1 , RcvBuffOffset . buff_offset ,
RcvBuffOffset . msg_len , buffer_size ) ;
sendmessage ( card , CEPID , ceReqTypeLnk , ceReqClass1 , ceReqLnkRead ,
c , sizeof ( LLData ) , ( unsigned int * ) & RcvBuffOffset ) ;
}
return 0 ;
}