Merge from vendor branch OPENSSH:
[dragonfly.git] / sys / net / i4b / layer1 / 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/i4b_hdlc.h,v 1.4.2.1 2001/08/10 14:08:36 obrien Exp $
33  * $DragonFly: src/sys/net/i4b/layer1/i4b_hdlc.h,v 1.2 2003/06/17 04:28:39 dillon Exp $
34  *
35  *      last edit-date: [Wed Jul 19 09:41:13 2000]
36  *
37  *---------------------------------------------------------------------------*/
38
39 #ifndef _I4B_HDLC_H_
40 #define _I4B_HDLC_H_
41
42 /*---------------------------------------------------------------------------*
43  *      HDLC CRC table
44  *
45  * Usage:
46  *      crc = (HDLC_FCS_TAB[(u_char)(crc ^ byte of data)] ^ (u_char)(crc >> 8));
47  *
48  *      For more information see RFC 1662 (p. 10)
49  *---------------------------------------------------------------------------*/
50 const u_short HDLC_FCS_TAB[256] = { 0x0000, 
51         0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf, 0x8c48, 
52         0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7, 0x1081, 
53         0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e, 0x9cc9, 
54         0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876, 0x2102, 
55         0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd, 0xad4a, 
56         0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5, 0x3183, 
57         0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c, 0xbdcb, 
58         0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974, 0x4204, 
59         0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb, 0xce4c, 
60         0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3, 0x5285, 
61         0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a, 0xdecd, 
62         0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72, 0x6306, 
63         0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9, 0xef4e, 
64         0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1, 0x7387, 
65         0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738, 0xffcf, 
66         0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70, 0x8408, 
67         0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7, 0x0840, 
68         0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff, 0x9489, 
69         0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036, 0x18c1, 
70         0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e, 0xa50a, 
71         0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5, 0x2942, 
72         0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd, 0xb58b, 
73         0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134, 0x39c3, 
74         0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c, 0xc60c, 
75         0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3, 0x4a44, 
76         0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb, 0xd68d, 
77         0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232, 0x5ac5, 
78         0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a, 0xe70e, 
79         0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1, 0x6b46, 
80         0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9, 0xf78f, 
81         0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330, 0x7bc7, 
82         0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78 
83 };
84
85 /*---------------------------------------------------------------------------*
86  *      HDLC bit table
87  *      ==============  
88  *
89  *      bits[0..3]:     A value which tells how many set bits there are at the
90  *                      beginning of the byte.
91  *
92  *      bits[4..7]:     Special bytes like 0x7e, 0x7d, 0xfd ... are flagged here
93  *                      NOTE: Special bytes also means 'abort' bytes (7 or more
94  *                            continuous set bits)
95  *
96  *      bits[8..11]:    A copy of bits[0..3] but only incremented by one.
97  *                      NOTE: 0x7e has value '8' instead of '0'. Internal reasons.
98  *
99  *      bits[12..15]:   A value which tells how many set bits there are at the
100  *                      end of the byte.
101  *                      NOTE: 0xff has both '8' incoming and '8' outgoing bits.
102  *
103  *---------------------------------------------------------------------------*/
104 const u_short HDLC_BIT_TAB[256] = { 0x0100, 
105         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
106         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100, 
107         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
108         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100, 
109         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
110         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100, 
111         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
112         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0160, 0x0706, 0x0100, 
113         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
114         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100, 
115         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
116         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0605, 0x0100, 
117         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
118         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0504, 0x0100, 
119         0x0201, 0x0100, 0x0302, 0x0100, 0x0201, 0x0100, 0x0403, 0x0100, 
120         0x0201, 0x0100, 0x0302, 0x01a0, 0x02a1, 0x0860, 0x0807, 0x1100, 
121         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100, 
122         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100, 
123         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100, 
124         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1605, 0x1100, 
125         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100, 
126         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1504, 0x1100, 
127         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1100, 0x1403, 0x1100, 
128         0x1201, 0x1100, 0x1302, 0x1100, 0x1201, 0x1160, 0x1706, 0x2100, 
129         0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100, 
130         0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2504, 0x2100, 
131         0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2403, 0x2100, 
132         0x2201, 0x2100, 0x2302, 0x2100, 0x2201, 0x2100, 0x2605, 0x3100, 
133         0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3403, 0x3100, 
134         0x3201, 0x3100, 0x3302, 0x3100, 0x3201, 0x3100, 0x3504, 0x4100, 
135         0x4201, 0x4100, 0x4302, 0x4100, 0x4201, 0x4100, 0x4403, 0x5100, 
136         0x5201, 0x5100, 0x5302, 0x6180, 0x6281, 0x7150, 0x8908 
137 };
138
139 /*---------------------------------------------------------------------------*
140  *      HDLC_DECODE
141  *      ===========
142  *
143  *      u_char:  flag, blevel
144  *      u_short: crc, ib, tmp, tmp2, len
145  *
146  *      next: 'continue' or 'goto xxx'
147  *
148  *      cfr: complete frame
149  *      nfr: new frame
150  *           NOTE: must setup 'len' and 'dst', so that 'dst' may be written
151  *                 at most 'len' times.
152  *
153  *      rab: abort
154  *      rdd: read data (read byte is stored in 'tmp2')
155  *      rdo: overflow
156  *
157  *      d: dummy
158  *
159  *      NOTE: setting flag to '0' and len to '0' => recover from rdu
160  *      NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
161  *      NOTE: these variables have to be 'suspended' / 'resumed' somehow:
162  *              flag, blevel, crc, ib, tmp, len
163  *      NOTE: zero is default value for all variables.
164  *      NOTE: each time 'dst' is written, 'len' is decreased by one.
165  *---------------------------------------------------------------------------*/
166
167 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
168                  cfrcmd, rabcmd, rdocmd, nextcmd, d)                            \
169                                                                                 \
170         rddcmd;                                                                 \
171                                                                                 \
172         ib  += HDLC_BIT_TAB[(u_char)tmp2];                                      \
173                                                                                 \
174         if ((u_char)ib >= 5)                                                    \
175         {                                                                       \
176                 if (ib & 0x20)          /* de-stuff (msb) */                    \
177                 {                                                               \
178                         if ((u_char)tmp2 == 0x7e) goto j0##d;                   \
179                         tmp2 += tmp2 & 0x7f;                                    \
180                         blevel--;                                               \
181                                                                                 \
182                         if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */               \
183                 }                                                               \
184                                                                                 \
185                 ib &= ~0xe0;                                                    \
186                                                                                 \
187                 if ((u_char)ib == 6)    /* flag seq (lsb) */                    \
188                 {                                                               \
189                  j0##d: if (flag >= 2)                                          \
190                         {                                                       \
191                                 len += (4 - flag) & 3;  /* remove CRC bytes */  \
192                                 crc ^= 0xf0b8;                                  \
193                                 cfrcmd;                                         \
194                                 len = 0;                                        \
195                         }                                                       \
196                                                                                 \
197                         flag   = 1;                                             \
198                                                                                 \
199                         blevel = (ib >> 8) & 0xf;                               \
200                         tmp    = ((u_char)tmp2) >> blevel;                      \
201                         blevel = 8 - blevel;                                    \
202                                                                                 \
203                         ib >>= 12;                                              \
204                                                                                 \
205                         nextcmd;                                                \
206                 }                                                               \
207                 if ((u_char)ib >= 7)    /* abort (msb & lsb) */                 \
208                 {                                                               \
209                         if (flag >= 2)                                          \
210                         {                                                       \
211                                 rabcmd;                                         \
212                                 len = 0;                                        \
213                         }                                                       \
214                                                                                 \
215                         flag = 0;                                               \
216                                                                                 \
217                         ib >>= 12;                                              \
218                                                                                 \
219                         nextcmd;                                                \
220                 }                                                               \
221                 if ((u_char)ib == 5)    /* de-stuff (lsb) */                    \
222                 {                                                               \
223                         tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1;                      \
224                         blevel--;                                               \
225                 }                                                               \
226                 if (blevel > 7)         /* EO - bits */                         \
227                 {                                                               \
228                         tmp |= (u_char)tmp2 >> (8 - (blevel &= 7));             \
229                                                                                 \
230                         ib >>= 12;                                              \
231                                                                                 \
232                         nextcmd;                                                \
233                 }                                                               \
234         }                                                                       \
235                                                                                 \
236         tmp |= (u_char)tmp2 << blevel;                                          \
237                                                                                 \
238         if (!len--)                                                             \
239         {                                                                       \
240                 len++;                                                          \
241                                                                                 \
242                 if (!flag++) { flag--; goto j5##d;} /* hunt mode */             \
243                                                                                 \
244                 switch (flag)                                                   \
245                 {   case 2:             /* new frame */                         \
246                         nfrcmd;                                                 \
247                         crc = -1;                                               \
248                         if (!len--) { len++; flag++; goto j4##d; }              \
249                         goto j3##d;                                             \
250                     case 3:             /* CRC (lsb's) */                       \
251                     case 4:             /* CRC (msb's) */                       \
252                         goto j4##d;                                             \
253                     case 5:             /* RDO */                               \
254                         rdocmd;                                                 \
255                         flag = 0;                                               \
256                         break;                                                  \
257                 }                                                               \
258         }                                                                       \
259         else                                                                    \
260         {                                                                       \
261          j3##d: dst = (u_char)tmp;                                              \
262          j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
263         }                                                                       \
264                                                                                 \
265  j5##d: ib >>= 12;                                                              \
266         tmp >>= 8;                                                              \
267
268 /*------ end of HDLC_DECODE -------------------------------------------------*/
269
270
271 /*---------------------------------------------------------------------------*
272  *      HDLC_ENCODE
273  *      ===========
274  *
275  *      u_char:  flag, src
276  *      u_short: tmp2, blevel, ib, crc, len
277  *      u_int:   tmp
278  *
279  *      gfr: This is the place where you free the last [mbuf] chain, and get
280  *           the next one. If a mbuf is available the code should setup 'len'
281  *           and 'src' so that 'src' may be read 'len' times. If no mbuf is
282  *           available leave 'len' and 'src' untouched.
283  *
284  *      wrd: write data (output = (u_char)tmp)
285  *
286  *      d: dummy
287  *
288  *      NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
289  *      NOTE: these variables have to be 'suspended' / 'resumed' somehow:
290  *              flag, blevel, crc, ib, tmp, len
291  *      NOTE: zero is default value for all variables.
292  *      NOTE: each time 'src' is read, 'len' is decreased by one.
293  *      NOTE: neither cmd's should exit through 'goto' or 'break' statements.
294  *---------------------------------------------------------------------------*/
295
296 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, wrdcmd, d) \
297                                                                                 \
298         if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; }                   \
299                                                                                 \
300         if (!len--)                                                             \
301         {                                                                       \
302                 len++;                                                          \
303                                                                                 \
304                 switch(++flag)                                                  \
305                 { default:                      /* abort */                     \
306                         tmp  = blevel = 0;      /* zero is default */           \
307                         tmp2 = 0xff;                                            \
308                         goto j3##d;                                             \
309                   case 1:                       /* 1st time FS */               \
310                   case 2:                       /* 2nd time FS */               \
311                         tmp2 = 0x7e;                                            \
312                         goto j3##d;                                             \
313                   case 3:                                                       \
314                         gfrcmd;                 /* get new frame */             \
315                         if (!len--)                                             \
316                         {                                                       \
317                                 len++;                                          \
318                                 flag--;         /* don't proceed */             \
319                                 tmp2 = 0x7e;                                    \
320                                 goto j3##d;     /* final FS */                  \
321                         }                                                       \
322                         else                                                    \
323                         {                                                       \
324                                 crc = -1;                                       \
325                                 ib  = 0;                                        \
326                                 goto j1##d;     /* first byte */                \
327                         }                                                       \
328                   case 4:                                                       \
329                         crc ^= -1;                                              \
330                         tmp2 = (u_char)crc;                                     \
331                         goto j2##d;             /* CRC (lsb's) */               \
332                   case 5:                                                       \
333                         tmp2  = (u_char)(crc >> 8);                             \
334                         flag  = 1;                                              \
335                         goto j2##d;             /* CRC (msb's) */               \
336                 }                                                               \
337         }                                                                       \
338         else                                                                    \
339         { j1##d :                                                               \
340                 tmp2 = (u_char)src;                                             \
341                 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
342           j2##d:                                                                \
343                                                                                 \
344                 ib >>= 12;                                                      \
345                 ib  += HDLC_BIT_TAB[(u_char)tmp2];                              \
346                                                                                 \
347                 if ((u_char)ib >= 5)    /* stuffing */                          \
348                 {                                                               \
349                         blevel &= ~0xff;                                        \
350                                                                                 \
351                         if (ib & 0xc0)          /* bit stuff (msb) */           \
352                         {                                                       \
353                                 tmp2 += tmp2 & (0xff * (ib & 0xc0));            \
354                                 ib %= 0x5000;                                   \
355                                 blevel++;                                       \
356                         }                                                       \
357                                                                                 \
358                         ib &= ~0xf0;                                            \
359                                                                                 \
360                         if ((u_char)ib >= 5)    /* bit stuff (lsb) */           \
361                         {                                                       \
362                                 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1)   \
363                                                                 & 7);           \
364                                 blevel++;                                       \
365                                                                                 \
366                                 if ((u_char)ib >= 10)   /* bit stuff (msb) */   \
367                                 {                                               \
368                                         tmp2 += tmp2 & ~0x7ff >> ((ib -         \
369                                                         (ib >> 8) + 1) & 7);    \
370                                         blevel++;                               \
371                                 }                                               \
372                                 if (ib & 0x8000)        /* bit walk */          \
373                                 {                                               \
374                                         ib = ((u_char)ib % 5) << 12;            \
375                                 }                                               \
376                         }                                                       \
377                                                                                 \
378                         tmp    |= tmp2 << (u_char)(blevel >> 8);                \
379                         blevel += (u_char)blevel << 8;                          \
380                 }                                                               \
381                 else            /* no stuffing */                               \
382                 {                                                               \
383                   j3##d:tmp    |= tmp2 << (u_char)(blevel >> 8);                \
384                 }                                                               \
385         }                                                                       \
386                                                                                 \
387  j4##d: wrdcmd;                                                                 \
388         tmp >>= 8;                                                              \
389
390 /*------ end of HDLC_ENCODE -------------------------------------------------*/
391
392
393 #endif /* _I4B_HDLC_H_ */
394