2014-09-26 22:21:21 +00:00
/*
* Copyright ( c ) 2011 , 2012 , Atheros Communications Inc .
* Copyright ( c ) 2014 , I2SE GmbH
*
* Permission to use , copy , modify , and / or distribute this software
* for any purpose with or without fee is hereby granted , provided
* that the above copyright notice and this permission notice appear
* in all copies .
*
* THE SOFTWARE IS PROVIDED " AS IS " AND THE AUTHOR DISCLAIMS ALL
* WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS . IN NO EVENT SHALL
* THE AUTHOR BE LIABLE FOR ANY SPECIAL , DIRECT , INDIRECT , OR
* CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
* LOSS OF USE , DATA OR PROFITS , WHETHER IN AN ACTION OF CONTRACT ,
* NEGLIGENCE OR OTHER TORTIOUS ACTION , ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE .
*/
/* Atheros ethernet framing. Every Ethernet frame is surrounded
* by an atheros frame while transmitted over a serial channel ;
*/
2017-05-29 13:57:20 +02:00
# include <linux/init.h>
2014-09-26 22:21:21 +00:00
# include <linux/kernel.h>
2017-05-29 13:57:20 +02:00
# include <linux/module.h>
2014-09-26 22:21:21 +00:00
2017-05-29 13:57:18 +02:00
# include "qca_7k_common.h"
2014-09-26 22:21:21 +00:00
u16
qcafrm_create_header ( u8 * buf , u16 length )
{
__le16 len ;
if ( ! buf )
return 0 ;
len = cpu_to_le16 ( length ) ;
buf [ 0 ] = 0xAA ;
buf [ 1 ] = 0xAA ;
buf [ 2 ] = 0xAA ;
buf [ 3 ] = 0xAA ;
buf [ 4 ] = len & 0xff ;
buf [ 5 ] = ( len > > 8 ) & 0xff ;
buf [ 6 ] = 0 ;
buf [ 7 ] = 0 ;
return QCAFRM_HEADER_LEN ;
}
2017-05-29 13:57:20 +02:00
EXPORT_SYMBOL_GPL ( qcafrm_create_header ) ;
2014-09-26 22:21:21 +00:00
u16
qcafrm_create_footer ( u8 * buf )
{
if ( ! buf )
return 0 ;
buf [ 0 ] = 0x55 ;
buf [ 1 ] = 0x55 ;
return QCAFRM_FOOTER_LEN ;
}
2017-05-29 13:57:20 +02:00
EXPORT_SYMBOL_GPL ( qcafrm_create_footer ) ;
2014-09-26 22:21:21 +00:00
/* Gather received bytes and try to extract a full ethernet frame by
* following a simple state machine .
*
* Return : QCAFRM_GATHER No ethernet frame fully received yet .
* QCAFRM_NOHEAD Header expected but not found .
* QCAFRM_INVLEN Atheros frame length is invalid
* QCAFRM_NOTAIL Footer expected but not found .
* > 0 Number of byte in the fully received
* Ethernet frame
*/
s32
qcafrm_fsm_decode ( struct qcafrm_handle * handle , u8 * buf , u16 buf_len , u8 recv_byte )
{
s32 ret = QCAFRM_GATHER ;
u16 len ;
switch ( handle - > state ) {
case QCAFRM_HW_LEN0 :
case QCAFRM_HW_LEN1 :
/* by default, just go to next state */
handle - > state - - ;
if ( recv_byte ! = 0x00 ) {
/* first two bytes of length must be 0 */
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
}
break ;
case QCAFRM_HW_LEN2 :
case QCAFRM_HW_LEN3 :
handle - > state - - ;
break ;
/* 4 bytes header pattern */
case QCAFRM_WAIT_AA1 :
case QCAFRM_WAIT_AA2 :
case QCAFRM_WAIT_AA3 :
case QCAFRM_WAIT_AA4 :
if ( recv_byte ! = 0xAA ) {
ret = QCAFRM_NOHEAD ;
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
} else {
handle - > state - - ;
}
break ;
/* 2 bytes length. */
/* Borrow offset field to hold length for now. */
case QCAFRM_WAIT_LEN_BYTE0 :
handle - > offset = recv_byte ;
handle - > state = QCAFRM_WAIT_LEN_BYTE1 ;
break ;
case QCAFRM_WAIT_LEN_BYTE1 :
handle - > offset = handle - > offset | ( recv_byte < < 8 ) ;
handle - > state = QCAFRM_WAIT_RSVD_BYTE1 ;
break ;
case QCAFRM_WAIT_RSVD_BYTE1 :
handle - > state = QCAFRM_WAIT_RSVD_BYTE2 ;
break ;
case QCAFRM_WAIT_RSVD_BYTE2 :
len = handle - > offset ;
2017-05-29 13:57:14 +02:00
if ( len > buf_len | | len < QCAFRM_MIN_LEN ) {
2014-09-26 22:21:21 +00:00
ret = QCAFRM_INVLEN ;
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
} else {
handle - > state = ( enum qcafrm_state ) ( len + 1 ) ;
/* Remaining number of bytes. */
handle - > offset = 0 ;
}
break ;
default :
/* Receiving Ethernet frame itself. */
buf [ handle - > offset ] = recv_byte ;
handle - > offset + + ;
handle - > state - - ;
break ;
case QCAFRM_WAIT_551 :
if ( recv_byte ! = 0x55 ) {
ret = QCAFRM_NOTAIL ;
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
} else {
handle - > state = QCAFRM_WAIT_552 ;
}
break ;
case QCAFRM_WAIT_552 :
if ( recv_byte ! = 0x55 ) {
ret = QCAFRM_NOTAIL ;
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
} else {
ret = handle - > offset ;
/* Frame is fully received. */
2017-05-29 13:57:19 +02:00
handle - > state = handle - > init ;
2014-09-26 22:21:21 +00:00
}
break ;
}
return ret ;
}
2017-05-29 13:57:20 +02:00
EXPORT_SYMBOL_GPL ( qcafrm_fsm_decode ) ;
MODULE_DESCRIPTION ( " Qualcomm Atheros QCA7000 common " ) ;
MODULE_AUTHOR ( " Qualcomm Atheros Communications " ) ;
MODULE_AUTHOR ( " Stefan Wahren <stefan.wahren@i2se.com> " ) ;
MODULE_LICENSE ( " Dual BSD/GPL " ) ;