Back to home page

OSCL-LXR

 
 

    


0001 /*
0002  *   Copyright (c) 2011, 2012, Atheros Communications Inc.
0003  *   Copyright (c) 2014, I2SE GmbH
0004  *
0005  *   Permission to use, copy, modify, and/or distribute this software
0006  *   for any purpose with or without fee is hereby granted, provided
0007  *   that the above copyright notice and this permission notice appear
0008  *   in all copies.
0009  *
0010  *   THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
0011  *   WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
0012  *   WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
0013  *   THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
0014  *   CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
0015  *   LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
0016  *   NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
0017  *   CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
0018  */
0019 
0020 /*   Atheros ethernet framing. Every Ethernet frame is surrounded
0021  *   by an atheros frame while transmitted over a serial channel;
0022  */
0023 
0024 #include <linux/init.h>
0025 #include <linux/kernel.h>
0026 #include <linux/module.h>
0027 
0028 #include "qca_7k_common.h"
0029 
0030 u16
0031 qcafrm_create_header(u8 *buf, u16 length)
0032 {
0033     __le16 len;
0034 
0035     if (!buf)
0036         return 0;
0037 
0038     len = cpu_to_le16(length);
0039 
0040     buf[0] = 0xAA;
0041     buf[1] = 0xAA;
0042     buf[2] = 0xAA;
0043     buf[3] = 0xAA;
0044     buf[4] = len & 0xff;
0045     buf[5] = (len >> 8) & 0xff;
0046     buf[6] = 0;
0047     buf[7] = 0;
0048 
0049     return QCAFRM_HEADER_LEN;
0050 }
0051 EXPORT_SYMBOL_GPL(qcafrm_create_header);
0052 
0053 u16
0054 qcafrm_create_footer(u8 *buf)
0055 {
0056     if (!buf)
0057         return 0;
0058 
0059     buf[0] = 0x55;
0060     buf[1] = 0x55;
0061     return QCAFRM_FOOTER_LEN;
0062 }
0063 EXPORT_SYMBOL_GPL(qcafrm_create_footer);
0064 
0065 /*   Gather received bytes and try to extract a full ethernet frame by
0066  *   following a simple state machine.
0067  *
0068  * Return:   QCAFRM_GATHER       No ethernet frame fully received yet.
0069  *           QCAFRM_NOHEAD       Header expected but not found.
0070  *           QCAFRM_INVLEN       Atheros frame length is invalid
0071  *           QCAFRM_NOTAIL       Footer expected but not found.
0072  *           > 0                 Number of byte in the fully received
0073  *                               Ethernet frame
0074  */
0075 
0076 s32
0077 qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte)
0078 {
0079     s32 ret = QCAFRM_GATHER;
0080     u16 len;
0081 
0082     switch (handle->state) {
0083     case QCAFRM_HW_LEN0:
0084     case QCAFRM_HW_LEN1:
0085         /* by default, just go to next state */
0086         handle->state--;
0087 
0088         if (recv_byte != 0x00) {
0089             /* first two bytes of length must be 0 */
0090             handle->state = handle->init;
0091         }
0092         break;
0093     case QCAFRM_HW_LEN2:
0094     case QCAFRM_HW_LEN3:
0095         handle->state--;
0096         break;
0097     /* 4 bytes header pattern */
0098     case QCAFRM_WAIT_AA1:
0099     case QCAFRM_WAIT_AA2:
0100     case QCAFRM_WAIT_AA3:
0101     case QCAFRM_WAIT_AA4:
0102         if (recv_byte != 0xAA) {
0103             ret = QCAFRM_NOHEAD;
0104             handle->state = handle->init;
0105         } else {
0106             handle->state--;
0107         }
0108         break;
0109         /* 2 bytes length. */
0110         /* Borrow offset field to hold length for now. */
0111     case QCAFRM_WAIT_LEN_BYTE0:
0112         handle->offset = recv_byte;
0113         handle->state = QCAFRM_WAIT_LEN_BYTE1;
0114         break;
0115     case QCAFRM_WAIT_LEN_BYTE1:
0116         handle->offset = handle->offset | (recv_byte << 8);
0117         handle->state = QCAFRM_WAIT_RSVD_BYTE1;
0118         break;
0119     case QCAFRM_WAIT_RSVD_BYTE1:
0120         handle->state = QCAFRM_WAIT_RSVD_BYTE2;
0121         break;
0122     case QCAFRM_WAIT_RSVD_BYTE2:
0123         len = handle->offset;
0124         if (len > buf_len || len < QCAFRM_MIN_LEN) {
0125             ret = QCAFRM_INVLEN;
0126             handle->state = handle->init;
0127         } else {
0128             handle->state = (enum qcafrm_state)(len + 1);
0129             /* Remaining number of bytes. */
0130             handle->offset = 0;
0131         }
0132         break;
0133     default:
0134         /* Receiving Ethernet frame itself. */
0135         buf[handle->offset] = recv_byte;
0136         handle->offset++;
0137         handle->state--;
0138         break;
0139     case QCAFRM_WAIT_551:
0140         if (recv_byte != 0x55) {
0141             ret = QCAFRM_NOTAIL;
0142             handle->state = handle->init;
0143         } else {
0144             handle->state = QCAFRM_WAIT_552;
0145         }
0146         break;
0147     case QCAFRM_WAIT_552:
0148         if (recv_byte != 0x55) {
0149             ret = QCAFRM_NOTAIL;
0150             handle->state = handle->init;
0151         } else {
0152             ret = handle->offset;
0153             /* Frame is fully received. */
0154             handle->state = handle->init;
0155         }
0156         break;
0157     }
0158 
0159     return ret;
0160 }
0161 EXPORT_SYMBOL_GPL(qcafrm_fsm_decode);
0162 
0163 MODULE_DESCRIPTION("Qualcomm Atheros QCA7000 common");
0164 MODULE_AUTHOR("Qualcomm Atheros Communications");
0165 MODULE_AUTHOR("Stefan Wahren <stefan.wahren@i2se.com>");
0166 MODULE_LICENSE("Dual BSD/GPL");