initial commit with v2.6.9
[linux-2.6.9-moxart.git] / drivers / isdn / tpam / tpam_crcpc.c
blobfae8df7ae1365207b3008aac4cceb212931e10f6
1 /* $Id: tpam_crcpc.c,v 1.1.2.2 2001/09/23 22:25:03 kai Exp $
3 * Turbo PAM ISDN driver for Linux. (Kernel Driver - CRC encoding)
5 * Copyright 1998-2000 AUVERTECH Télécom
6 * Copyright 2001 Stelian Pop <stelian.pop@fr.alcove.com>, Alcôve
8 * This software may be used and distributed according to the terms
9 * of the GNU General Public License, incorporated herein by reference.
11 * For all support questions please contact: <support@auvertech.fr>
15 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
17 Module Name:
19 crcpc.c
21 Abstract:
23 Modem HDLC coding
24 Software HDLC coding / decoding
26 Revision History:
28 ---------------------------------------------------------------------------*/
30 #include <linux/crc-ccitt.h>
31 #include "tpam.h"
33 #define HDLC_CTRL_CHAR_CMPL_MASK 0x20 /* HDLC control character complement mask */
34 #define HDLC_FLAG 0x7E /* HDLC flag */
35 #define HDLC_CTRL_ESC 0x7D /* HDLC control escapr character */
36 #define HDLC_LIKE_FCS_INIT_VAL 0xFFFF /* FCS initial value (0xFFFF for new equipment or 0) */
37 #define HDLC_FCS_OK 0xF0B8 /* This value is the only valid value of FCS */
39 #define TRUE 1
40 #define FALSE 0
42 static u8 ap_t_ctrl_char_complemented[256]; /* list of characters to complement */
44 static void ap_hdlc_like_ctrl_char_list (u32 ctrl_char) {
45 int i;
47 for (i = 0; i < 256; ++i)
48 ap_t_ctrl_char_complemented[i] = FALSE;
49 for (i = 0; i < 32; ++i)
50 if ((ctrl_char >> i) & 0x0001)
51 ap_t_ctrl_char_complemented [i] = TRUE;
52 ap_t_ctrl_char_complemented[HDLC_FLAG] = TRUE;
53 ap_t_ctrl_char_complemented[HDLC_CTRL_ESC] = TRUE;
57 void init_CRC(void) {
58 ap_hdlc_like_ctrl_char_list(0xffffffff);
61 void hdlc_encode_modem(u8 *buffer_in, u32 lng_in,
62 u8 *buffer_out, u32 *lng_out) {
63 u16 fcs;
64 register u8 data;
65 register u8 *p_data_out = buffer_out;
67 fcs = HDLC_LIKE_FCS_INIT_VAL;
70 * Insert HDLC flag at the beginning of the frame
72 *p_data_out++ = HDLC_FLAG;
74 #define ESCAPE_CHAR(data_out, data) \
75 if (ap_t_ctrl_char_complemented[data]) { \
76 *data_out++ = HDLC_CTRL_ESC; \
77 *data_out++ = data ^ 0x20; \
78 } \
79 else \
80 *data_out++ = data;
82 while (lng_in--) {
83 data = *buffer_in++;
86 * FCS calculation
88 fcs = crc_ccitt_byte(fcs, data);
90 ESCAPE_CHAR(p_data_out, data);
94 * Add FCS and closing flag
96 fcs ^= 0xFFFF; // Complement
98 data = (u8)(fcs & 0xff); /* LSB */
99 ESCAPE_CHAR(p_data_out, data);
101 data = (u8)((fcs >> 8)); /* MSB */
102 ESCAPE_CHAR(p_data_out, data);
103 #undef ESCAPE_CHAR
105 *p_data_out++ = HDLC_FLAG;
107 *lng_out = (u32)(p_data_out - buffer_out);
110 void hdlc_no_accm_encode(u8 *buffer_in, u32 lng_in,
111 u8 *buffer_out, u32 *lng_out) {
112 u16 fcs;
113 register u8 data;
114 register u8 *p_data_out = buffer_out;
117 * Insert HDLC flag at the beginning of the frame
119 fcs = HDLC_LIKE_FCS_INIT_VAL;
121 while (lng_in--) {
122 data = *buffer_in++;
123 /* calculate FCS */
124 fcs = crc_ccitt_byte(fcs, data);
125 *p_data_out++ = data;
129 * Add FCS and closing flag
131 fcs ^= 0xFFFF; // Complement
132 data = (u8)(fcs);
133 *p_data_out++ = data;
135 data =(u8)((fcs >> 8)); // revense MSB / LSB
136 *p_data_out++ = data;
138 *lng_out = (u32)(p_data_out - buffer_out);
141 u32 hdlc_no_accm_decode(u8 *buffer_in, u32 lng_in) {
142 u16 fcs;
143 u32 lng = lng_in;
144 register u8 data;
147 * Insert HDLC flag at the beginning of the frame
149 fcs = HDLC_LIKE_FCS_INIT_VAL;
151 while (lng_in--) {
152 data = *buffer_in++;
153 /* calculate FCS */
154 fcs = crc_ccitt_byte(fcs, data);
157 if (fcs == HDLC_FCS_OK)
158 return (lng-2);
159 else
160 return 0;