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/itjc/i4b_hdlc.h,v 1.1.2.1 2001/08/10 14:08:39 obrien Exp $
34 * last edit-date: [Thu Jan 11 11:31:01 2001]
36 * Please conform "ihfc/i4b_ihfc_drv.c" (ihfc_hdlc_Bxxxx)
37 * for correct usage! (-hp)
39 *---------------------------------------------------------------------------*/
44 /*---------------------------------------------------------------------------*
48 * crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
50 * For more information see RFC 1662 (p. 10)
51 *---------------------------------------------------------------------------*/
52 static const u_short HDLC_FCS_TAB[256] = { 0x0000,
53 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
54 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081,
55 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9,
56 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102,
57 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a,
58 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183,
59 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb,
60 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204,
61 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c,
62 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
63 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd,
64 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306,
65 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e,
66 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387,
67 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf,
68 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408,
69 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840,
70 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489,
71 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
72 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a,
73 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942,
74 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b,
75 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3,
76 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c,
77 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44,
78 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d,
79 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5,
80 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
81 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46,
82 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f,
83 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7,
84 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
87 /*---------------------------------------------------------------------------*
91 * bits[0..3]: A value which tells how many set bits there are at the
92 * beginning of the byte.
94 * bits[4..7]: Special bytes like 0x7e, 0x7d, 0xfd ... are flagged here
95 * NOTE: Special bytes also means 'abort' bytes (7 or more
96 * continuous set bits)
98 * bits[8..11]: A copy of bits[0..3] but only incremented by one.
99 * NOTE: 0x7e has value '8' instead of '0'. Internal reasons.
101 * bits[12..15]: A value which tells how many set bits there are at the
103 * NOTE: 0xff has both '8' incoming and '8' outgoing bits.
105 *---------------------------------------------------------------------------*/
106 static const u_short HDLC_BIT_TAB[256] = { 0x0100,
107 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
108 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
109 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
110 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
111 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
112 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
113 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
114 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0160, 0x0706, 0x0100,
115 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
116 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
117 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
118 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
119 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
120 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
121 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
122 0x0201, 0x0100, 0x0302, 0x01a0, 0x02a1, 0x0860, 0x0807, 0x1100,
123 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
124 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
125 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
126 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1605, 0x1100,
127 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
128 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
129 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
130 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1160, 0x1706, 0x2100,
131 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
132 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2504, 0x2100,
133 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
134 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2605, 0x3100,
135 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3403, 0x3100,
136 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3504, 0x4100,
137 0x4201, 0x4100, 0x4302, 0x4100, 0x4201, 0x4100, 0x4403, 0x5100,
138 0x5201, 0x5100, 0x5302, 0x6180, 0x6281, 0x7150, 0x8908
141 /*---------------------------------------------------------------------------*
145 * u_char: flag, blevel
146 * u_short: crc, ib, tmp, tmp2, len
148 * next: 'continue' or 'goto xxx'
150 * cfr: complete frame
152 * NOTE: must setup 'len' and 'dst', so that 'dst' may be written
153 * at most 'len' times.
156 * rdd: read data (read byte is stored in 'tmp2')
161 * NOTE: setting flag to '0' and len to '0' => recover from rdu
162 * NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
163 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
164 * flag, blevel, crc, ib, tmp, len
165 * NOTE: zero is default value for all variables.
166 * NOTE: each time 'dst' is written, 'len' is decreased by one.
167 *---------------------------------------------------------------------------*/
169 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
170 cfrcmd, rabcmd, rdocmd, nextcmd, d) \
174 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
176 if ((u_char)ib >= 5) \
178 if (ib & 0x20) /* de-stuff (msb) */ \
180 if ((u_char)tmp2 == 0x7e) goto j0##d; \
181 tmp2 += tmp2 & 0x7f; \
184 if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */ \
189 if ((u_char)ib == 6) /* flag seq (lsb) */ \
191 j0##d: if (flag >= 2) \
193 len += (4 - flag) & 3; /* remove CRC bytes */ \
201 blevel = (ib >> 8) & 0xf; \
202 tmp = ((u_char)tmp2) >> blevel; \
203 blevel = 8 - blevel; \
209 if ((u_char)ib >= 7) /* abort (msb & lsb) */ \
223 if ((u_char)ib == 5) /* de-stuff (lsb) */ \
225 tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1; \
228 if (blevel > 7) /* EO - bits */ \
230 tmp |= (u_char)tmp2 >> (8 - (blevel &= 7)); \
238 tmp |= (u_char)tmp2 << blevel; \
244 if (!flag++) { flag--; goto j5##d;} /* hunt mode */ \
247 { case 2: /* new frame */ \
250 if (!len--) { len++; flag++; goto j4##d; } \
252 case 3: /* CRC (lsb's) */ \
253 case 4: /* CRC (msb's) */ \
263 j3##d: dst = (u_char)tmp; \
264 j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
270 /*------ end of HDLC_DECODE -------------------------------------------------*/
273 /*---------------------------------------------------------------------------*
278 * u_short: tmp2, blevel, ib, crc, len
281 * gfr: This is the place where you free the last [mbuf] chain, and get
282 * the next one. If a mbuf is available the code should setup 'len'
283 * and 'src' so that 'src' may be read 'len' times. If no mbuf is
284 * available leave 'len' and 'src' untouched.
286 * nmb: If your implementation accept/use chained mbufs, this is the
287 * place where you update 'len' and 'src' to the next mbuf of
288 * the chain that makes up a frame. If no further mbuf is
289 * available leave 'len' and 'src' untouched. This is not the
290 * place where you free the mbuf. Leave the block empty if your
291 * implementation does not accept/use chained mbufs.
293 * wrd: write data (output = (u_char)tmp)
297 * NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
298 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
299 * flag, blevel, crc, ib, tmp, len
300 * NOTE: zero is default value for all variables.
301 * NOTE: each time 'src' is read, 'len' is decreased by one.
302 * NOTE: neither cmd's should exit through 'goto' or 'break' statements.
303 *---------------------------------------------------------------------------*/
305 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, nmbcmd, wrdcmd, d) \
307 if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; } \
314 { default: /* abort */ \
315 tmp = blevel = 0; /* zero is default */ \
318 case 1: /* 1st time FS */ \
319 case 2: /* 2nd time FS */ \
323 gfrcmd; /* get new frame */ \
327 flag--; /* don't proceed */ \
329 goto j3##d; /* final FS */ \
335 goto j1##d; /* first byte */ \
338 nmbcmd; /* get next mbuf in chain */ \
343 tmp2 = (u_char)crc; \
344 goto j2##d; /* CRC (lsb's) */ \
349 goto j1##d; /* proceed with the frame */ \
352 tmp2 = (u_char)(crc >> 8); \
354 goto j2##d; /* CRC (msb's) */ \
359 tmp2 = (u_char)src; \
360 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
364 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
366 if ((u_char)ib >= 5) /* stuffing */ \
370 if (ib & 0xc0) /* bit stuff (msb) */ \
372 tmp2 += tmp2 & (0xff * (ib & 0xc0)); \
379 if ((u_char)ib >= 5) /* bit stuff (lsb) */ \
381 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1) \
385 if ((u_char)ib >= 10) /* bit stuff (msb) */ \
387 tmp2 += tmp2 & ~0x7ff >> ((ib - \
388 (ib >> 8) + 1) & 7); \
391 if (ib & 0x8000) /* bit walk */ \
393 ib = ((u_char)ib % 5) << 12; \
397 tmp |= tmp2 << (u_char)(blevel >> 8); \
398 blevel += (u_char)blevel << 8; \
400 else /* no stuffing */ \
402 j3##d:tmp |= tmp2 << (u_char)(blevel >> 8); \
409 /*------ end of HDLC_ENCODE -------------------------------------------------*/
412 #endif /* _I4B_HDLC_H_ */