2 * Copyright (c) 2000 Hans Petter Selasky. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 *---------------------------------------------------------------------------
27 * i4b_hdlc.h - software-HDLC header file
28 * --------------------------------------
30 * $Id: i4b_hdlc.h,v 1.5 2000/08/28 07:41:19 hm Exp $
32 * $FreeBSD: src/sys/i4b/layer1/i4b_hdlc.h,v 1.4.2.1 2001/08/10 14:08:36 obrien Exp $
34 * last edit-date: [Wed Jul 19 09:41:13 2000]
36 *---------------------------------------------------------------------------*/
41 /*---------------------------------------------------------------------------*
45 * crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
47 * For more information see RFC 1662 (p. 10)
48 *---------------------------------------------------------------------------*/
49 const u_short HDLC_FCS_TAB[256] = { 0x0000,
50 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
51 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081,
52 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9,
53 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102,
54 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a,
55 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183,
56 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb,
57 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204,
58 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c,
59 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
60 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd,
61 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306,
62 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e,
63 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387,
64 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf,
65 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408,
66 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840,
67 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489,
68 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
69 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a,
70 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942,
71 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b,
72 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3,
73 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c,
74 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44,
75 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d,
76 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5,
77 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
78 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46,
79 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f,
80 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7,
81 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
84 /*---------------------------------------------------------------------------*
88 * bits[0..3]: A value which tells how many set bits there are at the
89 * beginning of the byte.
91 * bits[4..7]: Special bytes like 0x7e, 0x7d, 0xfd ... are flagged here
92 * NOTE: Special bytes also means 'abort' bytes (7 or more
93 * continuous set bits)
95 * bits[8..11]: A copy of bits[0..3] but only incremented by one.
96 * NOTE: 0x7e has value '8' instead of '0'. Internal reasons.
98 * bits[12..15]: A value which tells how many set bits there are at the
100 * NOTE: 0xff has both '8' incoming and '8' outgoing bits.
102 *---------------------------------------------------------------------------*/
103 const u_short HDLC_BIT_TAB[256] = { 0x0100,
104 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
105 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
106 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
107 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
108 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
109 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
110 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
111 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0160, 0x0706, 0x0100,
112 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
113 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
114 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
115 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
116 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
117 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
118 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
119 0x0201, 0x0100, 0x0302, 0x01a0, 0x02a1, 0x0860, 0x0807, 0x1100,
120 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
121 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
122 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
123 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1605, 0x1100,
124 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
125 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
126 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
127 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1160, 0x1706, 0x2100,
128 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
129 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2504, 0x2100,
130 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
131 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2605, 0x3100,
132 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3403, 0x3100,
133 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3504, 0x4100,
134 0x4201, 0x4100, 0x4302, 0x4100, 0x4201, 0x4100, 0x4403, 0x5100,
135 0x5201, 0x5100, 0x5302, 0x6180, 0x6281, 0x7150, 0x8908
138 /*---------------------------------------------------------------------------*
142 * u_char: flag, blevel
143 * u_short: crc, ib, tmp, tmp2, len
145 * next: 'continue' or 'goto xxx'
147 * cfr: complete frame
149 * NOTE: must setup 'len' and 'dst', so that 'dst' may be written
150 * at most 'len' times.
153 * rdd: read data (read byte is stored in 'tmp2')
158 * NOTE: setting flag to '0' and len to '0' => recover from rdu
159 * NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
160 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
161 * flag, blevel, crc, ib, tmp, len
162 * NOTE: zero is default value for all variables.
163 * NOTE: each time 'dst' is written, 'len' is decreased by one.
164 *---------------------------------------------------------------------------*/
166 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
167 cfrcmd, rabcmd, rdocmd, nextcmd, d) \
171 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
173 if ((u_char)ib >= 5) \
175 if (ib & 0x20) /* de-stuff (msb) */ \
177 if ((u_char)tmp2 == 0x7e) goto j0##d; \
178 tmp2 += tmp2 & 0x7f; \
181 if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */ \
186 if ((u_char)ib == 6) /* flag seq (lsb) */ \
188 j0##d: if (flag >= 2) \
190 len += (4 - flag) & 3; /* remove CRC bytes */ \
198 blevel = (ib >> 8) & 0xf; \
199 tmp = ((u_char)tmp2) >> blevel; \
200 blevel = 8 - blevel; \
206 if ((u_char)ib >= 7) /* abort (msb & lsb) */ \
220 if ((u_char)ib == 5) /* de-stuff (lsb) */ \
222 tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1; \
225 if (blevel > 7) /* EO - bits */ \
227 tmp |= (u_char)tmp2 >> (8 - (blevel &= 7)); \
235 tmp |= (u_char)tmp2 << blevel; \
241 if (!flag++) { flag--; goto j5##d;} /* hunt mode */ \
244 { case 2: /* new frame */ \
247 if (!len--) { len++; flag++; goto j4##d; } \
249 case 3: /* CRC (lsb's) */ \
250 case 4: /* CRC (msb's) */ \
260 j3##d: dst = (u_char)tmp; \
261 j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
267 /*------ end of HDLC_DECODE -------------------------------------------------*/
270 /*---------------------------------------------------------------------------*
275 * u_short: tmp2, blevel, ib, crc, len
278 * gfr: This is the place where you free the last [mbuf] chain, and get
279 * the next one. If a mbuf is available the code should setup 'len'
280 * and 'src' so that 'src' may be read 'len' times. If no mbuf is
281 * available leave 'len' and 'src' untouched.
283 * wrd: write data (output = (u_char)tmp)
287 * NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
288 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
289 * flag, blevel, crc, ib, tmp, len
290 * NOTE: zero is default value for all variables.
291 * NOTE: each time 'src' is read, 'len' is decreased by one.
292 * NOTE: neither cmd's should exit through 'goto' or 'break' statements.
293 *---------------------------------------------------------------------------*/
295 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, wrdcmd, d) \
297 if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; } \
304 { default: /* abort */ \
305 tmp = blevel = 0; /* zero is default */ \
308 case 1: /* 1st time FS */ \
309 case 2: /* 2nd time FS */ \
313 gfrcmd; /* get new frame */ \
317 flag--; /* don't proceed */ \
319 goto j3##d; /* final FS */ \
325 goto j1##d; /* first byte */ \
329 tmp2 = (u_char)crc; \
330 goto j2##d; /* CRC (lsb's) */ \
332 tmp2 = (u_char)(crc >> 8); \
334 goto j2##d; /* CRC (msb's) */ \
339 tmp2 = (u_char)src; \
340 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
344 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
346 if ((u_char)ib >= 5) /* stuffing */ \
350 if (ib & 0xc0) /* bit stuff (msb) */ \
352 tmp2 += tmp2 & (0xff * (ib & 0xc0)); \
359 if ((u_char)ib >= 5) /* bit stuff (lsb) */ \
361 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1) \
365 if ((u_char)ib >= 10) /* bit stuff (msb) */ \
367 tmp2 += tmp2 & ~0x7ff >> ((ib - \
368 (ib >> 8) + 1) & 7); \
371 if (ib & 0x8000) /* bit walk */ \
373 ib = ((u_char)ib % 5) << 12; \
377 tmp |= tmp2 << (u_char)(blevel >> 8); \
378 blevel += (u_char)blevel << 8; \
380 else /* no stuffing */ \
382 j3##d:tmp |= tmp2 << (u_char)(blevel >> 8); \
389 /*------ end of HDLC_ENCODE -------------------------------------------------*/
392 #endif /* _I4B_HDLC_H_ */