1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun * Copyright (c) 2011, 2012, Atheros Communications Inc.
3*4882a593Smuzhiyun * Copyright (c) 2014, I2SE GmbH
4*4882a593Smuzhiyun *
5*4882a593Smuzhiyun * Permission to use, copy, modify, and/or distribute this software
6*4882a593Smuzhiyun * for any purpose with or without fee is hereby granted, provided
7*4882a593Smuzhiyun * that the above copyright notice and this permission notice appear
8*4882a593Smuzhiyun * in all copies.
9*4882a593Smuzhiyun *
10*4882a593Smuzhiyun * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL
11*4882a593Smuzhiyun * WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED
12*4882a593Smuzhiyun * WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL
13*4882a593Smuzhiyun * THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR
14*4882a593Smuzhiyun * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
15*4882a593Smuzhiyun * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
16*4882a593Smuzhiyun * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
17*4882a593Smuzhiyun * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18*4882a593Smuzhiyun */
19*4882a593Smuzhiyun
20*4882a593Smuzhiyun /* Atheros Ethernet framing. Every Ethernet frame is surrounded by an atheros
21*4882a593Smuzhiyun * frame while transmitted over a serial channel.
22*4882a593Smuzhiyun */
23*4882a593Smuzhiyun
24*4882a593Smuzhiyun #ifndef _QCA_FRAMING_H
25*4882a593Smuzhiyun #define _QCA_FRAMING_H
26*4882a593Smuzhiyun
27*4882a593Smuzhiyun #include <linux/if_ether.h>
28*4882a593Smuzhiyun #include <linux/if_vlan.h>
29*4882a593Smuzhiyun #include <linux/types.h>
30*4882a593Smuzhiyun
31*4882a593Smuzhiyun /* Frame is currently being received */
32*4882a593Smuzhiyun #define QCAFRM_GATHER 0
33*4882a593Smuzhiyun
34*4882a593Smuzhiyun /* No header byte while expecting it */
35*4882a593Smuzhiyun #define QCAFRM_NOHEAD (QCAFRM_ERR_BASE - 1)
36*4882a593Smuzhiyun
37*4882a593Smuzhiyun /* No tailer byte while expecting it */
38*4882a593Smuzhiyun #define QCAFRM_NOTAIL (QCAFRM_ERR_BASE - 2)
39*4882a593Smuzhiyun
40*4882a593Smuzhiyun /* Frame length is invalid */
41*4882a593Smuzhiyun #define QCAFRM_INVLEN (QCAFRM_ERR_BASE - 3)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun /* Frame length is invalid */
44*4882a593Smuzhiyun #define QCAFRM_INVFRAME (QCAFRM_ERR_BASE - 4)
45*4882a593Smuzhiyun
46*4882a593Smuzhiyun /* Min/Max Ethernet MTU: 46/1500 */
47*4882a593Smuzhiyun #define QCAFRM_MIN_MTU (ETH_ZLEN - ETH_HLEN)
48*4882a593Smuzhiyun #define QCAFRM_MAX_MTU ETH_DATA_LEN
49*4882a593Smuzhiyun
50*4882a593Smuzhiyun /* Min/Max frame lengths */
51*4882a593Smuzhiyun #define QCAFRM_MIN_LEN (QCAFRM_MIN_MTU + ETH_HLEN)
52*4882a593Smuzhiyun #define QCAFRM_MAX_LEN (QCAFRM_MAX_MTU + VLAN_ETH_HLEN)
53*4882a593Smuzhiyun
54*4882a593Smuzhiyun /* QCA7K header len */
55*4882a593Smuzhiyun #define QCAFRM_HEADER_LEN 8
56*4882a593Smuzhiyun
57*4882a593Smuzhiyun /* QCA7K footer len */
58*4882a593Smuzhiyun #define QCAFRM_FOOTER_LEN 2
59*4882a593Smuzhiyun
60*4882a593Smuzhiyun /* QCA7K Framing. */
61*4882a593Smuzhiyun #define QCAFRM_ERR_BASE -1000
62*4882a593Smuzhiyun
63*4882a593Smuzhiyun enum qcafrm_state {
64*4882a593Smuzhiyun /* HW length is only available on SPI */
65*4882a593Smuzhiyun QCAFRM_HW_LEN0 = 0x8000,
66*4882a593Smuzhiyun QCAFRM_HW_LEN1 = QCAFRM_HW_LEN0 - 1,
67*4882a593Smuzhiyun QCAFRM_HW_LEN2 = QCAFRM_HW_LEN1 - 1,
68*4882a593Smuzhiyun QCAFRM_HW_LEN3 = QCAFRM_HW_LEN2 - 1,
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun /* Waiting first 0xAA of header */
71*4882a593Smuzhiyun QCAFRM_WAIT_AA1 = QCAFRM_HW_LEN3 - 1,
72*4882a593Smuzhiyun
73*4882a593Smuzhiyun /* Waiting second 0xAA of header */
74*4882a593Smuzhiyun QCAFRM_WAIT_AA2 = QCAFRM_WAIT_AA1 - 1,
75*4882a593Smuzhiyun
76*4882a593Smuzhiyun /* Waiting third 0xAA of header */
77*4882a593Smuzhiyun QCAFRM_WAIT_AA3 = QCAFRM_WAIT_AA2 - 1,
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun /* Waiting fourth 0xAA of header */
80*4882a593Smuzhiyun QCAFRM_WAIT_AA4 = QCAFRM_WAIT_AA3 - 1,
81*4882a593Smuzhiyun
82*4882a593Smuzhiyun /* Waiting Byte 0-1 of length (litte endian) */
83*4882a593Smuzhiyun QCAFRM_WAIT_LEN_BYTE0 = QCAFRM_WAIT_AA4 - 1,
84*4882a593Smuzhiyun QCAFRM_WAIT_LEN_BYTE1 = QCAFRM_WAIT_AA4 - 2,
85*4882a593Smuzhiyun
86*4882a593Smuzhiyun /* Reserved bytes */
87*4882a593Smuzhiyun QCAFRM_WAIT_RSVD_BYTE1 = QCAFRM_WAIT_AA4 - 3,
88*4882a593Smuzhiyun QCAFRM_WAIT_RSVD_BYTE2 = QCAFRM_WAIT_AA4 - 4,
89*4882a593Smuzhiyun
90*4882a593Smuzhiyun /* The frame length is used as the state until
91*4882a593Smuzhiyun * the end of the Ethernet frame
92*4882a593Smuzhiyun * Waiting for first 0x55 of footer
93*4882a593Smuzhiyun */
94*4882a593Smuzhiyun QCAFRM_WAIT_551 = 1,
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun /* Waiting for second 0x55 of footer */
97*4882a593Smuzhiyun QCAFRM_WAIT_552 = QCAFRM_WAIT_551 - 1
98*4882a593Smuzhiyun };
99*4882a593Smuzhiyun
100*4882a593Smuzhiyun /* Structure to maintain the frame decoding during reception. */
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun struct qcafrm_handle {
103*4882a593Smuzhiyun /* Current decoding state */
104*4882a593Smuzhiyun enum qcafrm_state state;
105*4882a593Smuzhiyun /* Initial state depends on connection type */
106*4882a593Smuzhiyun enum qcafrm_state init;
107*4882a593Smuzhiyun
108*4882a593Smuzhiyun /* Offset in buffer (borrowed for length too) */
109*4882a593Smuzhiyun u16 offset;
110*4882a593Smuzhiyun
111*4882a593Smuzhiyun /* Frame length as kept by this module */
112*4882a593Smuzhiyun u16 len;
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun u16 qcafrm_create_header(u8 *buf, u16 len);
116*4882a593Smuzhiyun
117*4882a593Smuzhiyun u16 qcafrm_create_footer(u8 *buf);
118*4882a593Smuzhiyun
qcafrm_fsm_init_spi(struct qcafrm_handle * handle)119*4882a593Smuzhiyun static inline void qcafrm_fsm_init_spi(struct qcafrm_handle *handle)
120*4882a593Smuzhiyun {
121*4882a593Smuzhiyun handle->init = QCAFRM_HW_LEN0;
122*4882a593Smuzhiyun handle->state = handle->init;
123*4882a593Smuzhiyun }
124*4882a593Smuzhiyun
qcafrm_fsm_init_uart(struct qcafrm_handle * handle)125*4882a593Smuzhiyun static inline void qcafrm_fsm_init_uart(struct qcafrm_handle *handle)
126*4882a593Smuzhiyun {
127*4882a593Smuzhiyun handle->init = QCAFRM_WAIT_AA1;
128*4882a593Smuzhiyun handle->state = handle->init;
129*4882a593Smuzhiyun }
130*4882a593Smuzhiyun
131*4882a593Smuzhiyun /* Gather received bytes and try to extract a full Ethernet frame
132*4882a593Smuzhiyun * by following a simple state machine.
133*4882a593Smuzhiyun *
134*4882a593Smuzhiyun * Return: QCAFRM_GATHER No Ethernet frame fully received yet.
135*4882a593Smuzhiyun * QCAFRM_NOHEAD Header expected but not found.
136*4882a593Smuzhiyun * QCAFRM_INVLEN QCA7K frame length is invalid
137*4882a593Smuzhiyun * QCAFRM_NOTAIL Footer expected but not found.
138*4882a593Smuzhiyun * > 0 Number of byte in the fully received
139*4882a593Smuzhiyun * Ethernet frame
140*4882a593Smuzhiyun */
141*4882a593Smuzhiyun
142*4882a593Smuzhiyun s32 qcafrm_fsm_decode(struct qcafrm_handle *handle, u8 *buf, u16 buf_len, u8 recv_byte);
143*4882a593Smuzhiyun
144*4882a593Smuzhiyun #endif /* _QCA_FRAMING_H */
145