Initial import from FreeBSD RELENG_4:
[games.git] / sys / net / i4b / layer1 / itjc / i4b_hdlc.h
1 /*
2  * Copyright (c) 2000 Hans Petter Selasky. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions
6  * are met:
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.
12  *
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
23  * SUCH DAMAGE.
24  *
25  *---------------------------------------------------------------------------
26  *
27  *      i4b_hdlc.h - software-HDLC header file
28  *      --------------------------------------
29  *
30  *      $Id: i4b_hdlc.h,v 1.5 2000/08/28 07:41:19 hm Exp $
31  *
32  * $FreeBSD: src/sys/i4b/layer1/itjc/i4b_hdlc.h,v 1.1.2.1 2001/08/10 14:08:39 obrien Exp $
33  *
34  *      last edit-date: [Thu Jan 11 11:31:01 2001]
35  *
36  *      Please conform "ihfc/i4b_ihfc_drv.c" (ihfc_hdlc_Bxxxx)
37  *      for correct usage! (-hp)
38  *
39  *---------------------------------------------------------------------------*/
40
41 #ifndef _I4B_HDLC_H_
42 #define _I4B_HDLC_H_
43
44 /*---------------------------------------------------------------------------*
45  *      HDLC CRC table
46  *
47  * Usage:
48  *      crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
49  *
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 
85 };
86
87 /*---------------------------------------------------------------------------*
88  *      HDLC bit table
89  *      ==============  
90  *
91  *      bits[0..3]:     A value which tells how many set bits there are at the
92  *                      beginning of the byte.
93  *
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)
97  *
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.
100  *
101  *      bits[12..15]:   A value which tells how many set bits there are at the
102  *                      end of the byte.
103  *                      NOTE: 0xff has both '8' incoming and '8' outgoing bits.
104  *
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 
139 };
140
141 /*---------------------------------------------------------------------------*
142  *      HDLC_DECODE
143  *      ===========
144  *
145  *      u_char:  flag, blevel
146  *      u_short: crc, ib, tmp, tmp2, len
147  *
148  *      next: 'continue' or 'goto xxx'
149  *
150  *      cfr: complete frame
151  *      nfr: new frame
152  *           NOTE: must setup 'len' and 'dst', so that 'dst' may be written
153  *                 at most 'len' times.
154  *
155  *      rab: abort
156  *      rdd: read data (read byte is stored in 'tmp2')
157  *      rdo: overflow
158  *
159  *      d: dummy
160  *
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  *---------------------------------------------------------------------------*/
168
169 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
170                  cfrcmd, rabcmd, rdocmd, nextcmd, d)                            \
171                                                                                 \
172         rddcmd;                                                                 \
173                                                                                 \
174         ib  += HDLC_BIT_TAB[(u_char)tmp2];                                      \
175                                                                                 \
176         if ((u_char)ib >= 5)                                                    \
177         {                                                                       \
178                 if (ib & 0x20)          /* de-stuff (msb) */                    \
179                 {                                                               \
180                         if ((u_char)tmp2 == 0x7e) goto j0##d;                   \
181                         tmp2 += tmp2 & 0x7f;                                    \
182                         blevel--;                                               \
183                                                                                 \
184                         if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */               \
185                 }                                                               \
186                                                                                 \
187                 ib &= ~0xe0;                                                    \
188                                                                                 \
189                 if ((u_char)ib == 6)    /* flag seq (lsb) */                    \
190                 {                                                               \
191                  j0##d: if (flag >= 2)                                          \
192                         {                                                       \
193                                 len += (4 - flag) & 3;  /* remove CRC bytes */  \
194                                 crc ^= 0xf0b8;                                  \
195                                 cfrcmd;                                         \
196                                 len = 0;                                        \
197                         }                                                       \
198                                                                                 \
199                         flag   = 1;                                             \
200                                                                                 \
201                         blevel = (ib >> 8) & 0xf;                               \
202                         tmp    = ((u_char)tmp2) >> blevel;                      \
203                         blevel = 8 - blevel;                                    \
204                                                                                 \
205                         ib >>= 12;                                              \
206                                                                                 \
207                         nextcmd;                                                \
208                 }                                                               \
209                 if ((u_char)ib >= 7)    /* abort (msb & lsb) */                 \
210                 {                                                               \
211                         if (flag >= 2)                                          \
212                         {                                                       \
213                                 rabcmd;                                         \
214                                 len = 0;                                        \
215                         }                                                       \
216                                                                                 \
217                         flag = 0;                                               \
218                                                                                 \
219                         ib >>= 12;                                              \
220                                                                                 \
221                         nextcmd;                                                \
222                 }                                                               \
223                 if ((u_char)ib == 5)    /* de-stuff (lsb) */                    \
224                 {                                                               \
225                         tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1;                      \
226                         blevel--;                                               \
227                 }                                                               \
228                 if (blevel > 7)         /* EO - bits */                         \
229                 {                                                               \
230                         tmp |= (u_char)tmp2 >> (8 - (blevel &= 7));             \
231                                                                                 \
232                         ib >>= 12;                                              \
233                                                                                 \
234                         nextcmd;                                                \
235                 }                                                               \
236         }                                                                       \
237                                                                                 \
238         tmp |= (u_char)tmp2 << blevel;                                          \
239                                                                                 \
240         if (!len--)                                                             \
241         {                                                                       \
242                 len++;                                                          \
243                                                                                 \
244                 if (!flag++) { flag--; goto j5##d;} /* hunt mode */             \
245                                                                                 \
246                 switch (flag)                                                   \
247                 {   case 2:             /* new frame */                         \
248                         nfrcmd;                                                 \
249                         crc = -1;                                               \
250                         if (!len--) { len++; flag++; goto j4##d; }              \
251                         goto j3##d;                                             \
252                     case 3:             /* CRC (lsb's) */                       \
253                     case 4:             /* CRC (msb's) */                       \
254                         goto j4##d;                                             \
255                     case 5:             /* RDO */                               \
256                         rdocmd;                                                 \
257                         flag = 0;                                               \
258                         break;                                                  \
259                 }                                                               \
260         }                                                                       \
261         else                                                                    \
262         {                                                                       \
263          j3##d: dst = (u_char)tmp;                                              \
264          j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
265         }                                                                       \
266                                                                                 \
267  j5##d: ib >>= 12;                                                              \
268         tmp >>= 8;                                                              \
269
270 /*------ end of HDLC_DECODE -------------------------------------------------*/
271
272
273 /*---------------------------------------------------------------------------*
274  *      HDLC_ENCODE
275  *      ===========
276  *
277  *      u_char:  flag, src
278  *      u_short: tmp2, blevel, ib, crc, len
279  *      u_int:   tmp
280  *
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.
285  *
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.
292  *
293  *      wrd: write data (output = (u_char)tmp)
294  *
295  *      d: dummy
296  *
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  *---------------------------------------------------------------------------*/
304
305 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, nmbcmd, wrdcmd, d) \
306                                                                                 \
307         if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; }                   \
308                                                                                 \
309         if (!len--)                                                             \
310         {                                                                       \
311                 len++;                                                          \
312                                                                                 \
313                 switch(++flag)                                                  \
314                 { default:                      /* abort */                     \
315                         tmp  = blevel = 0;      /* zero is default */           \
316                         tmp2 = 0xff;                                            \
317                         goto j3##d;                                             \
318                   case 1:                       /* 1st time FS */               \
319                   case 2:                       /* 2nd time FS */               \
320                         tmp2 = 0x7e;                                            \
321                         goto j3##d;                                             \
322                   case 3:                                                       \
323                         gfrcmd;                 /* get new frame */             \
324                         if (!len--)                                             \
325                         {                                                       \
326                                 len++;                                          \
327                                 flag--;         /* don't proceed */             \
328                                 tmp2 = 0x7e;                                    \
329                                 goto j3##d;     /* final FS */                  \
330                         }                                                       \
331                         else                                                    \
332                         {                                                       \
333                                 crc = -1;                                       \
334                                 ib  = 0;                                        \
335                                 goto j1##d;     /* first byte */                \
336                         }                                                       \
337                   case 4:                                                       \
338                         nmbcmd;                 /* get next mbuf in chain */    \
339                         if (!len--)                                             \
340                         {                                                       \
341                                 len++;                                          \
342                                 crc ^= -1;                                      \
343                                 tmp2 = (u_char)crc;                             \
344                                 goto j2##d;     /* CRC (lsb's) */               \
345                         }                                                       \
346                         else                                                    \
347                         {                                                       \
348                                 flag--;                                         \
349                                 goto j1##d;     /* proceed with the frame */    \
350                         }                                                       \
351                   case 5:                                                       \
352                         tmp2  = (u_char)(crc >> 8);                             \
353                         flag  = 1;                                              \
354                         goto j2##d;             /* CRC (msb's) */               \
355                 }                                                               \
356         }                                                                       \
357         else                                                                    \
358         { j1##d :                                                               \
359                 tmp2 = (u_char)src;                                             \
360                 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
361           j2##d:                                                                \
362                                                                                 \
363                 ib >>= 12;                                                      \
364                 ib  += HDLC_BIT_TAB[(u_char)tmp2];                              \
365                                                                                 \
366                 if ((u_char)ib >= 5)    /* stuffing */                          \
367                 {                                                               \
368                         blevel &= ~0xff;                                        \
369                                                                                 \
370                         if (ib & 0xc0)          /* bit stuff (msb) */           \
371                         {                                                       \
372                                 tmp2 += tmp2 & (0xff * (ib & 0xc0));            \
373                                 ib %= 0x5000;                                   \
374                                 blevel++;                                       \
375                         }                                                       \
376                                                                                 \
377                         ib &= ~0xf0;                                            \
378                                                                                 \
379                         if ((u_char)ib >= 5)    /* bit stuff (lsb) */           \
380                         {                                                       \
381                                 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1)   \
382                                                                 & 7);           \
383                                 blevel++;                                       \
384                                                                                 \
385                                 if ((u_char)ib >= 10)   /* bit stuff (msb) */   \
386                                 {                                               \
387                                         tmp2 += tmp2 & ~0x7ff >> ((ib -         \
388                                                         (ib >> 8) + 1) & 7);    \
389                                         blevel++;                               \
390                                 }                                               \
391                                 if (ib & 0x8000)        /* bit walk */          \
392                                 {                                               \
393                                         ib = ((u_char)ib % 5) << 12;            \
394                                 }                                               \
395                         }                                                       \
396                                                                                 \
397                         tmp    |= tmp2 << (u_char)(blevel >> 8);                \
398                         blevel += (u_char)blevel << 8;                          \
399                 }                                                               \
400                 else            /* no stuffing */                               \
401                 {                                                               \
402                   j3##d:tmp    |= tmp2 << (u_char)(blevel >> 8);                \
403                 }                                                               \
404         }                                                                       \
405                                                                                 \
406  j4##d: wrdcmd;                                                                 \
407         tmp >>= 8;                                                              \
408
409 /*------ end of HDLC_ENCODE -------------------------------------------------*/
410
411
412 #endif /* _I4B_HDLC_H_ */