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 $
33 * $DragonFly: src/sys/net/i4b/layer1/itjc/i4b_hdlc.h,v 1.2 2003/06/17 04:28:40 dillon Exp $
35 * last edit-date: [Thu Jan 11 11:31:01 2001]
37 * Please conform "ihfc/i4b_ihfc_drv.c" (ihfc_hdlc_Bxxxx)
38 * for correct usage! (-hp)
40 *---------------------------------------------------------------------------*/
45 /*---------------------------------------------------------------------------*
49 * crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
51 * For more information see RFC 1662 (p. 10)
52 *---------------------------------------------------------------------------*/
53 static const u_short HDLC_FCS_TAB[256] = { 0x0000,
54 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48,
55 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081,
56 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9,
57 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102,
58 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a,
59 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183,
60 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb,
61 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204,
62 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c,
63 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285,
64 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd,
65 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306,
66 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e,
67 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387,
68 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf,
69 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408,
70 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840,
71 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489,
72 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1,
73 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a,
74 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942,
75 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b,
76 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3,
77 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c,
78 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44,
79 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d,
80 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5,
81 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e,
82 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46,
83 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f,
84 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7,
85 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
88 /*---------------------------------------------------------------------------*
92 * bits[0..3]: A value which tells how many set bits there are at the
93 * beginning of the byte.
95 * bits[4..7]: Special bytes like 0x7e, 0x7d, 0xfd ... are flagged here
96 * NOTE: Special bytes also means 'abort' bytes (7 or more
97 * continuous set bits)
99 * bits[8..11]: A copy of bits[0..3] but only incremented by one.
100 * NOTE: 0x7e has value '8' instead of '0'. Internal reasons.
102 * bits[12..15]: A value which tells how many set bits there are at the
104 * NOTE: 0xff has both '8' incoming and '8' outgoing bits.
106 *---------------------------------------------------------------------------*/
107 static const u_short HDLC_BIT_TAB[256] = { 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, 0x0100, 0x0605, 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, 0x0160, 0x0706, 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, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100,
120 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
121 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100,
122 0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100,
123 0x0201, 0x0100, 0x0302, 0x01a0, 0x02a1, 0x0860, 0x0807, 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, 0x1100, 0x1605, 0x1100,
128 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
129 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100,
130 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100,
131 0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1160, 0x1706, 0x2100,
132 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
133 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2504, 0x2100,
134 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100,
135 0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2605, 0x3100,
136 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3403, 0x3100,
137 0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3504, 0x4100,
138 0x4201, 0x4100, 0x4302, 0x4100, 0x4201, 0x4100, 0x4403, 0x5100,
139 0x5201, 0x5100, 0x5302, 0x6180, 0x6281, 0x7150, 0x8908
142 /*---------------------------------------------------------------------------*
146 * u_char: flag, blevel
147 * u_short: crc, ib, tmp, tmp2, len
149 * next: 'continue' or 'goto xxx'
151 * cfr: complete frame
153 * NOTE: must setup 'len' and 'dst', so that 'dst' may be written
154 * at most 'len' times.
157 * rdd: read data (read byte is stored in 'tmp2')
162 * NOTE: setting flag to '0' and len to '0' => recover from rdu
163 * NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
164 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
165 * flag, blevel, crc, ib, tmp, len
166 * NOTE: zero is default value for all variables.
167 * NOTE: each time 'dst' is written, 'len' is decreased by one.
168 *---------------------------------------------------------------------------*/
170 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
171 cfrcmd, rabcmd, rdocmd, nextcmd, d) \
175 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
177 if ((u_char)ib >= 5) \
179 if (ib & 0x20) /* de-stuff (msb) */ \
181 if ((u_char)tmp2 == 0x7e) goto j0##d; \
182 tmp2 += tmp2 & 0x7f; \
185 if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */ \
190 if ((u_char)ib == 6) /* flag seq (lsb) */ \
192 j0##d: if (flag >= 2) \
194 len += (4 - flag) & 3; /* remove CRC bytes */ \
202 blevel = (ib >> 8) & 0xf; \
203 tmp = ((u_char)tmp2) >> blevel; \
204 blevel = 8 - blevel; \
210 if ((u_char)ib >= 7) /* abort (msb & lsb) */ \
224 if ((u_char)ib == 5) /* de-stuff (lsb) */ \
226 tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1; \
229 if (blevel > 7) /* EO - bits */ \
231 tmp |= (u_char)tmp2 >> (8 - (blevel &= 7)); \
239 tmp |= (u_char)tmp2 << blevel; \
245 if (!flag++) { flag--; goto j5##d;} /* hunt mode */ \
248 { case 2: /* new frame */ \
251 if (!len--) { len++; flag++; goto j4##d; } \
253 case 3: /* CRC (lsb's) */ \
254 case 4: /* CRC (msb's) */ \
264 j3##d: dst = (u_char)tmp; \
265 j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
271 /*------ end of HDLC_DECODE -------------------------------------------------*/
274 /*---------------------------------------------------------------------------*
279 * u_short: tmp2, blevel, ib, crc, len
282 * gfr: This is the place where you free the last [mbuf] chain, and get
283 * the next one. If a mbuf is available the code should setup 'len'
284 * and 'src' so that 'src' may be read 'len' times. If no mbuf is
285 * available leave 'len' and 'src' untouched.
287 * nmb: If your implementation accept/use chained mbufs, this is the
288 * place where you update 'len' and 'src' to the next mbuf of
289 * the chain that makes up a frame. If no further mbuf is
290 * available leave 'len' and 'src' untouched. This is not the
291 * place where you free the mbuf. Leave the block empty if your
292 * implementation does not accept/use chained mbufs.
294 * wrd: write data (output = (u_char)tmp)
298 * NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
299 * NOTE: these variables have to be 'suspended' / 'resumed' somehow:
300 * flag, blevel, crc, ib, tmp, len
301 * NOTE: zero is default value for all variables.
302 * NOTE: each time 'src' is read, 'len' is decreased by one.
303 * NOTE: neither cmd's should exit through 'goto' or 'break' statements.
304 *---------------------------------------------------------------------------*/
306 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, nmbcmd, wrdcmd, d) \
308 if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; } \
315 { default: /* abort */ \
316 tmp = blevel = 0; /* zero is default */ \
319 case 1: /* 1st time FS */ \
320 case 2: /* 2nd time FS */ \
324 gfrcmd; /* get new frame */ \
328 flag--; /* don't proceed */ \
330 goto j3##d; /* final FS */ \
336 goto j1##d; /* first byte */ \
339 nmbcmd; /* get next mbuf in chain */ \
344 tmp2 = (u_char)crc; \
345 goto j2##d; /* CRC (lsb's) */ \
350 goto j1##d; /* proceed with the frame */ \
353 tmp2 = (u_char)(crc >> 8); \
355 goto j2##d; /* CRC (msb's) */ \
360 tmp2 = (u_char)src; \
361 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
365 ib += HDLC_BIT_TAB[(u_char)tmp2]; \
367 if ((u_char)ib >= 5) /* stuffing */ \
371 if (ib & 0xc0) /* bit stuff (msb) */ \
373 tmp2 += tmp2 & (0xff * (ib & 0xc0)); \
380 if ((u_char)ib >= 5) /* bit stuff (lsb) */ \
382 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1) \
386 if ((u_char)ib >= 10) /* bit stuff (msb) */ \
388 tmp2 += tmp2 & ~0x7ff >> ((ib - \
389 (ib >> 8) + 1) & 7); \
392 if (ib & 0x8000) /* bit walk */ \
394 ib = ((u_char)ib % 5) << 12; \
398 tmp |= tmp2 << (u_char)(blevel >> 8); \
399 blevel += (u_char)blevel << 8; \
401 else /* no stuffing */ \
403 j3##d:tmp |= tmp2 << (u_char)(blevel >> 8); \
410 /*------ end of HDLC_ENCODE -------------------------------------------------*/
413 #endif /* _I4B_HDLC_H_ */