]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/i4b/layer1/i4b_hdlc.h
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / 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  *
28  *      i4b_hdlc.h - software-HDLC header file
29  *      --------------------------------------
30  *
31  *      $Id: i4b_hdlc.h,v 1.5 2000/08/28 07:41:19 hm Exp $
32  *
33  * $FreeBSD$
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 extern const u_short HDLC_FCS_TAB[256];
43 extern const u_short HDLC_BIT_TAB[256];
44
45 /*---------------------------------------------------------------------------*
46  *      HDLC_DECODE
47  *      ===========
48  *
49  *      u_char:  flag, blevel
50  *      u_short: crc, ib, tmp, tmp2, len
51  *
52  *      next: 'continue' or 'goto xxx'
53  *
54  *      cfr: complete frame
55  *      nfr: new frame
56  *           NOTE: must setup 'len' and 'dst', so that 'dst' may be written
57  *                 at most 'len' times.
58  *
59  *      rab: abort
60  *      rdd: read data (read byte is stored in 'tmp2')
61  *      rdo: overflow
62  *
63  *      d: dummy
64  *
65  *      NOTE: setting flag to '0' and len to '0' => recover from rdu
66  *      NOTE: bits[8 .. ] of tmp2 may be used to store custom data/flags
67  *      NOTE: these variables have to be 'suspended' / 'resumed' somehow:
68  *              flag, blevel, crc, ib, tmp, len
69  *      NOTE: zero is default value for all variables.
70  *      NOTE: each time 'dst' is written, 'len' is decreased by one.
71  *---------------------------------------------------------------------------*/
72
73 #define HDLC_DECODE(dst, len, tmp, tmp2, blevel, ib, crc, flag, rddcmd, nfrcmd, \
74                  cfrcmd, rabcmd, rdocmd, nextcmd, d)                            \
75                                                                                 \
76         rddcmd;                                                                 \
77                                                                                 \
78         ib  += HDLC_BIT_TAB[(u_char)tmp2];                                      \
79                                                                                 \
80         if ((u_char)ib >= 5)                                                    \
81         {                                                                       \
82                 if (ib & 0x20)          /* de-stuff (msb) */                    \
83                 {                                                               \
84                         if ((u_char)tmp2 == 0x7e) goto j0##d;                   \
85                         tmp2 += tmp2 & 0x7f;                                    \
86                         blevel--;                                               \
87                                                                                 \
88                         if ((ib += 0x100) & 0xc) tmp2 |= 1; /* */               \
89                 }                                                               \
90                                                                                 \
91                 ib &= ~0xe0;                                                    \
92                                                                                 \
93                 if ((u_char)ib == 6)    /* flag seq (lsb) */                    \
94                 {                                                               \
95                  j0##d: if (flag >= 2)                                          \
96                         {                                                       \
97                                 len += (4 - flag) & 3;  /* remove CRC bytes */  \
98                                 crc ^= 0xf0b8;                                  \
99                                 cfrcmd;                                         \
100                                 len = 0;                                        \
101                         }                                                       \
102                                                                                 \
103                         flag   = 1;                                             \
104                                                                                 \
105                         blevel = (ib >> 8) & 0xf;                               \
106                         tmp    = ((u_char)tmp2) >> blevel;                      \
107                         blevel = 8 - blevel;                                    \
108                                                                                 \
109                         ib >>= 12;                                              \
110                                                                                 \
111                         nextcmd;                                                \
112                 }                                                               \
113                 if ((u_char)ib >= 7)    /* abort (msb & lsb) */                 \
114                 {                                                               \
115                         if (flag >= 2)                                          \
116                         {                                                       \
117                                 rabcmd;                                         \
118                                 len = 0;                                        \
119                         }                                                       \
120                                                                                 \
121                         flag = 0;                                               \
122                                                                                 \
123                         ib >>= 12;                                              \
124                                                                                 \
125                         nextcmd;                                                \
126                 }                                                               \
127                 if ((u_char)ib == 5)    /* de-stuff (lsb) */                    \
128                 {                                                               \
129                         tmp2 = (tmp2 | (tmp2 + 1)) & ~0x1;                      \
130                         blevel--;                                               \
131                 }                                                               \
132                 if (blevel > 7)         /* EO - bits */                         \
133                 {                                                               \
134                         tmp |= (u_char)tmp2 >> (8 - (blevel &= 7));             \
135                                                                                 \
136                         ib >>= 12;                                              \
137                                                                                 \
138                         nextcmd;                                                \
139                 }                                                               \
140         }                                                                       \
141                                                                                 \
142         tmp |= (u_char)tmp2 << blevel;                                          \
143                                                                                 \
144         if (!len--)                                                             \
145         {                                                                       \
146                 len++;                                                          \
147                                                                                 \
148                 if (!flag++) { flag--; goto j5##d;} /* hunt mode */             \
149                                                                                 \
150                 switch (flag)                                                   \
151                 {   case 2:             /* new frame */                         \
152                         nfrcmd;                                                 \
153                         crc = -1;                                               \
154                         if (!len--) { len++; flag++; goto j4##d; }              \
155                         goto j3##d;                                             \
156                     case 3:             /* CRC (lsb's) */                       \
157                     case 4:             /* CRC (msb's) */                       \
158                         goto j4##d;                                             \
159                     case 5:             /* RDO */                               \
160                         rdocmd;                                                 \
161                         flag = 0;                                               \
162                         break;                                                  \
163                 }                                                               \
164         }                                                                       \
165         else                                                                    \
166         {                                                                       \
167          j3##d: dst = (u_char)tmp;                                              \
168          j4##d: crc = (HDLC_FCS_TAB[(u_char)(tmp ^ crc)] ^ (u_char)(crc >> 8)); \
169         }                                                                       \
170                                                                                 \
171  j5##d: ib >>= 12;                                                              \
172         tmp >>= 8;                                                              \
173
174 /*------ end of HDLC_DECODE -------------------------------------------------*/
175
176
177 /*---------------------------------------------------------------------------*
178  *      HDLC_ENCODE
179  *      ===========
180  *
181  *      u_char:  flag, src
182  *      u_short: tmp2, blevel, ib, crc, len
183  *      u_int:   tmp
184  *
185  *      gfr: This is the place where you free the last [mbuf] chain, and get
186  *           the next one. If a mbuf is available the code should setup 'len'
187  *           and 'src' so that 'src' may be read 'len' times. If no mbuf is
188  *           available leave 'len' and 'src' untouched.
189  *
190  *      wrd: write data (output = (u_char)tmp)
191  *
192  *      d: dummy
193  *
194  *      NOTE: setting flag to '-2' and len to '0' => abort bytes will be sent
195  *      NOTE: these variables have to be 'suspended' / 'resumed' somehow:
196  *              flag, blevel, crc, ib, tmp, len
197  *      NOTE: zero is default value for all variables.
198  *      NOTE: each time 'src' is read, 'len' is decreased by one.
199  *      NOTE: neither cmd's should exit through 'goto' or 'break' statements.
200  *---------------------------------------------------------------------------*/
201
202 #define HDLC_ENCODE(src, len, tmp, tmp2, blevel, ib, crc, flag, gfrcmd, wrdcmd, d) \
203                                                                                 \
204         if (blevel >= 0x800) { blevel -= 0x800; goto j4##d; }                   \
205                                                                                 \
206         if (!len--)                                                             \
207         {                                                                       \
208                 len++;                                                          \
209                                                                                 \
210                 switch(++flag)                                                  \
211                 { default:                      /* abort */                     \
212                         tmp  = blevel = 0;      /* zero is default */           \
213                         tmp2 = 0xff;                                            \
214                         goto j3##d;                                             \
215                   case 1:                       /* 1st time FS */               \
216                   case 2:                       /* 2nd time FS */               \
217                         tmp2 = 0x7e;                                            \
218                         goto j3##d;                                             \
219                   case 3:                                                       \
220                         gfrcmd;                 /* get new frame */             \
221                         if (!len--)                                             \
222                         {                                                       \
223                                 len++;                                          \
224                                 flag--;         /* don't proceed */             \
225                                 tmp2 = 0x7e;                                    \
226                                 goto j3##d;     /* final FS */                  \
227                         }                                                       \
228                         else                                                    \
229                         {                                                       \
230                                 crc = -1;                                       \
231                                 ib  = 0;                                        \
232                                 goto j1##d;     /* first byte */                \
233                         }                                                       \
234                   case 4:                                                       \
235                         crc ^= -1;                                              \
236                         tmp2 = (u_char)crc;                                     \
237                         goto j2##d;             /* CRC (lsb's) */               \
238                   case 5:                                                       \
239                         tmp2  = (u_char)(crc >> 8);                             \
240                         flag  = 1;                                              \
241                         goto j2##d;             /* CRC (msb's) */               \
242                 }                                                               \
243         }                                                                       \
244         else                                                                    \
245         { j1##d :                                                               \
246                 tmp2 = (u_char)src;                                             \
247                 crc =(HDLC_FCS_TAB[(u_char)(crc ^ tmp2)] ^ (u_char)(crc >> 8)); \
248           j2##d:                                                                \
249                                                                                 \
250                 ib >>= 12;                                                      \
251                 ib  += HDLC_BIT_TAB[(u_char)tmp2];                              \
252                                                                                 \
253                 if ((u_char)ib >= 5)    /* stuffing */                          \
254                 {                                                               \
255                         blevel &= ~0xff;                                        \
256                                                                                 \
257                         if (ib & 0xc0)          /* bit stuff (msb) */           \
258                         {                                                       \
259                                 tmp2 += tmp2 & (0xff * (ib & 0xc0));            \
260                                 ib %= 0x5000;                                   \
261                                 blevel++;                                       \
262                         }                                                       \
263                                                                                 \
264                         ib &= ~0xf0;                                            \
265                                                                                 \
266                         if ((u_char)ib >= 5)    /* bit stuff (lsb) */           \
267                         {                                                       \
268                                 tmp2 += tmp2 & ~0x1f >> ((ib - (ib >> 8) + 1)   \
269                                                                 & 7);           \
270                                 blevel++;                                       \
271                                                                                 \
272                                 if ((u_char)ib >= 10)   /* bit stuff (msb) */   \
273                                 {                                               \
274                                         tmp2 += tmp2 & ~0x7ff >> ((ib -         \
275                                                         (ib >> 8) + 1) & 7);    \
276                                         blevel++;                               \
277                                 }                                               \
278                                 if (ib & 0x8000)        /* bit walk */          \
279                                 {                                               \
280                                         ib = ((u_char)ib % 5) << 12;            \
281                                 }                                               \
282                         }                                                       \
283                                                                                 \
284                         tmp    |= tmp2 << (u_char)(blevel >> 8);                \
285                         blevel += (u_char)blevel << 8;                          \
286                 }                                                               \
287                 else            /* no stuffing */                               \
288                 {                                                               \
289                   j3##d:tmp    |= tmp2 << (u_char)(blevel >> 8);                \
290                 }                                                               \
291         }                                                                       \
292                                                                                 \
293  j4##d: wrdcmd;                                                                 \
294         tmp >>= 8;                                                              \
295
296 /*------ end of HDLC_ENCODE -------------------------------------------------*/
297
298
299 #endif /* _I4B_HDLC_H_ */
300