kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / netproto / atm / uni / qsaal1_sigcpcs.c
1 /*
2  *
3  * ===================================
4  * HARP  |  Host ATM Research Platform
5  * ===================================
6  *
7  *
8  * This Host ATM Research Platform ("HARP") file (the "Software") is
9  * made available by Network Computing Services, Inc. ("NetworkCS")
10  * "AS IS".  NetworkCS does not provide maintenance, improvements or
11  * support of any kind.
12  *
13  * NETWORKCS MAKES NO WARRANTIES OR REPRESENTATIONS, EXPRESS OR IMPLIED,
14  * INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY
15  * AND FITNESS FOR A PARTICULAR PURPOSE, AS TO ANY ELEMENT OF THE
16  * SOFTWARE OR ANY SUPPORT PROVIDED IN CONNECTION WITH THIS SOFTWARE.
17  * In no event shall NetworkCS be responsible for any damages, including
18  * but not limited to consequential damages, arising from or relating to
19  * any use of the Software or related support.
20  *
21  * Copyright 1994-1998 Network Computing Services, Inc.
22  *
23  * Copies of this Software may be made, however, the above copyright
24  * notice must be reproduced on all copies.
25  *
26  *      @(#) $FreeBSD: src/sys/netatm/uni/qsaal1_sigcpcs.c,v 1.4 2000/01/17 20:49:49 mks Exp $
27  *      @(#) $DragonFly: src/sys/netproto/atm/uni/qsaal1_sigcpcs.c,v 1.7 2006/01/14 13:36:39 swildner Exp $
28  */
29
30 /*
31  * ATM Forum UNI Support
32  * ---------------------
33  *
34  * ITU-T Q.SAAL1 - Process CPCS-signals (SSCOP PDUs)
35  *
36  */
37
38 #include <netproto/atm/kern_include.h>
39
40 #include "sscop.h"
41 #include "sscop_misc.h"
42 #include "sscop_pdu.h"
43 #include "sscop_var.h"
44
45 /*
46  * Local functions
47  */
48 static void     sscop_bgn_outconn (struct sscop *, KBuffer *, caddr_t);
49 static void     sscop_end_outresyn (struct sscop *, KBuffer *, caddr_t);
50 static void     sscop_end_conresyn (struct sscop *, KBuffer *, caddr_t);
51 static void     sscop_end_ready (struct sscop *, KBuffer *, caddr_t);
52 static void     sscop_endak_outresyn (struct sscop *, KBuffer *, caddr_t);
53 static void     sscop_rs_outresyn (struct sscop *, KBuffer *, caddr_t);
54 static void     sscop_rs_ready (struct sscop *, KBuffer *, caddr_t);
55 static void     sscop_rsak_conresyn (struct sscop *, KBuffer *, caddr_t);
56 static void     sscop_sd_inresyn (struct sscop *, KBuffer *, caddr_t);
57 static void     sscop_sd_conresyn (struct sscop *, KBuffer *, caddr_t);
58 static void     sscop_sd_process (struct sscop *, KBuffer *, caddr_t, int);
59 static void     sscop_sd_ready (struct sscop *, KBuffer *, caddr_t);
60 static void     sscop_sdp_ready (struct sscop *, KBuffer *, caddr_t);
61 static void     sscop_poll_inresyn (struct sscop *, KBuffer *, caddr_t);
62 static void     sscop_poll_conresyn (struct sscop *, KBuffer *, caddr_t);
63 static void     sscop_poll_ready (struct sscop *, KBuffer *, caddr_t);
64 static void     sscop_stat_conresyn (struct sscop *, KBuffer *, caddr_t);
65 static void     sscop_ustat_conresyn (struct sscop *, KBuffer *, caddr_t);
66
67
68 /*
69  * PDU type state lookup tables
70  */
71 /* BGN PDU */
72 static void     (*sscop_bgn_tab[SOS_NUMSTATES])
73                                 (struct sscop *, KBuffer *, caddr_t) = {
74                         NULL,                   /* SOS_INST */
75                         sscop_bgn_idle,         /* SOS_IDLE */
76                         sscop_bgn_outconn,      /* SOS_OUTCONN */
77                         sscop_noop,             /* SOS_INCONN */
78                         sscop_bgn_outdisc,      /* SOS_OUTDISC */
79                         sscop_bgn_outresyn,     /* SOS_OUTRESYN */
80                         sscop_bgn_inresyn,      /* SOS_INRESYN */
81                         sscop_bgn_outresyn,     /* SOS_CONRESYN */
82                         NULL,                   /* invalid */
83                         NULL,                   /* invalid */
84                         sscop_bgn_inresyn,      /* SOS_READY */
85                         sscop_noop              /* SOS_TERM */
86 };
87
88 /* BGAK PDU */
89 static void     (*sscop_bgak_tab[SOS_NUMSTATES])
90                                 (struct sscop *, KBuffer *, caddr_t) = {
91                         NULL,                   /* SOS_INST */
92                         sscop_bgak_idle,        /* SOS_IDLE */
93                         sscop_bgak_outconn,     /* SOS_OUTCONN */
94                         sscop_bgak_error,       /* SOS_INCONN */
95                         sscop_noop,             /* SOS_OUTDISC */
96                         sscop_bgak_error,       /* SOS_OUTRESYN */
97                         sscop_bgak_error,       /* SOS_INRESYN */
98                         sscop_bgak_error,       /* SOS_CONRESYN */
99                         NULL,                   /* invalid */
100                         NULL,                   /* invalid */
101                         sscop_noop,             /* SOS_READY */
102                         sscop_noop              /* SOS_TERM */
103 };
104
105 /* BGREJ PDU */
106 static void     (*sscop_bgrej_tab[SOS_NUMSTATES])
107                                 (struct sscop *, KBuffer *, caddr_t) = {
108                         NULL,                   /* SOS_INST */
109                         sscop_bgrej_error,      /* SOS_IDLE */
110                         sscop_bgrej_outconn,    /* SOS_OUTCONN */
111                         sscop_bgrej_inconn,     /* SOS_INCONN */
112                         sscop_noop,             /* SOS_OUTDISC */
113                         sscop_bgrej_outresyn,   /* SOS_OUTRESYN */
114                         sscop_bgrej_ready,      /* SOS_INRESYN */
115                         sscop_bgrej_outresyn,   /* SOS_CONRESYN */
116                         NULL,                   /* invalid */
117                         NULL,                   /* invalid */
118                         sscop_bgrej_ready,      /* SOS_READY */
119                         sscop_noop              /* SOS_TERM */
120 };
121
122 /* END PDU */
123 static void     (*sscop_end_tab[SOS_NUMSTATES])
124                                 (struct sscop *, KBuffer *, caddr_t) = {
125                         NULL,                   /* SOS_INST */
126                         sscop_end_idle,         /* SOS_IDLE */
127                         sscop_noop,             /* SOS_OUTCONN */
128                         sscop_end_inconn,       /* SOS_INCONN */
129                         sscop_end_outdisc,      /* SOS_OUTDISC */
130                         sscop_end_outresyn,     /* SOS_OUTRESYN */
131                         sscop_end_ready,        /* SOS_INRESYN */
132                         sscop_end_conresyn,     /* SOS_CONRESYN */
133                         NULL,                   /* invalid */
134                         NULL,                   /* invalid */
135                         sscop_end_ready,        /* SOS_READY */
136                         sscop_noop              /* SOS_TERM */
137 };
138
139 /* ENDAK PDU */
140 static void     (*sscop_endak_tab[SOS_NUMSTATES])
141                                 (struct sscop *, KBuffer *, caddr_t) = {
142                         NULL,                   /* SOS_INST */
143                         sscop_noop,             /* SOS_IDLE */
144                         sscop_noop,             /* SOS_OUTCONN */
145                         sscop_endak_inconn,     /* SOS_INCONN */
146                         sscop_endak_outdisc,    /* SOS_OUTDISC */
147                         sscop_endak_outresyn,   /* SOS_OUTRESYN */
148                         sscop_endak_ready,      /* SOS_INRESYN */
149                         sscop_endak_outresyn,   /* SOS_CONRESYN */
150                         NULL,                   /* invalid */
151                         NULL,                   /* invalid */
152                         sscop_endak_ready,      /* SOS_READY */
153                         sscop_noop              /* SOS_TERM */
154 };
155
156 /* RS PDU */
157 static void     (*sscop_rs_tab[SOS_NUMSTATES])
158                                 (struct sscop *, KBuffer *, caddr_t) = {
159                         NULL,                   /* SOS_INST */
160                         sscop_rs_idle,          /* SOS_IDLE */
161                         sscop_noop,             /* SOS_OUTCONN */
162                         sscop_rs_error,         /* SOS_INCONN */
163                         sscop_noop,             /* SOS_OUTDISC */
164                         sscop_rs_outresyn,      /* SOS_OUTRESYN */
165                         sscop_noop,             /* SOS_INRESYN */
166                         sscop_noop,             /* SOS_CONRESYN */
167                         NULL,                   /* invalid */
168                         NULL,                   /* invalid */
169                         sscop_rs_ready,         /* SOS_READY */
170                         sscop_noop              /* SOS_TERM */
171 };
172
173 /* RSAK PDU */
174 static void     (*sscop_rsak_tab[SOS_NUMSTATES])
175                                 (struct sscop *, KBuffer *, caddr_t) = {
176                         NULL,                   /* SOS_INST */
177                         sscop_rsak_idle,        /* SOS_IDLE */
178                         sscop_noop,             /* SOS_OUTCONN */
179                         sscop_rsak_error,       /* SOS_INCONN */
180                         sscop_noop,             /* SOS_OUTDISC */
181                         sscop_rsak_outresyn,    /* SOS_OUTRESYN */
182                         sscop_rsak_error,       /* SOS_INRESYN */
183                         sscop_rsak_conresyn,    /* SOS_CONRESYN */
184                         NULL,                   /* invalid */
185                         NULL,                   /* invalid */
186                         sscop_rsak_error,       /* SOS_READY */
187                         sscop_noop              /* SOS_TERM */
188 };
189
190 /* SD PDU */
191 static void     (*sscop_sd_tab[SOS_NUMSTATES])
192                                 (struct sscop *, KBuffer *, caddr_t) = {
193                         NULL,                   /* SOS_INST */
194                         sscop_sd_idle,          /* SOS_IDLE */
195                         sscop_noop,             /* SOS_OUTCONN */
196                         sscop_sd_inconn,        /* SOS_INCONN */
197                         sscop_noop,             /* SOS_OUTDISC */
198                         sscop_sd_ready,         /* SOS_OUTRESYN */
199                         sscop_sd_inresyn,       /* SOS_INRESYN */
200                         sscop_sd_conresyn,      /* SOS_CONRESYN */
201                         NULL,                   /* invalid */
202                         NULL,                   /* invalid */
203                         sscop_sd_ready,         /* SOS_READY */
204                         sscop_noop              /* SOS_TERM */
205 };
206
207 /* SDP PDU */
208 static void     (*sscop_sdp_tab[SOS_NUMSTATES])
209                                 (struct sscop *, KBuffer *, caddr_t) = {
210                         NULL,                   /* SOS_INST */
211                         sscop_sd_idle,          /* SOS_IDLE */
212                         sscop_noop,             /* SOS_OUTCONN */
213                         sscop_sd_inconn,        /* SOS_INCONN */
214                         sscop_noop,             /* SOS_OUTDISC */
215                         sscop_sdp_ready,        /* SOS_OUTRESYN */
216                         sscop_sd_inresyn,       /* SOS_INRESYN */
217                         sscop_sd_conresyn,      /* SOS_CONRESYN */
218                         NULL,                   /* invalid */
219                         NULL,                   /* invalid */
220                         sscop_sdp_ready,        /* SOS_READY */
221                         sscop_noop              /* SOS_TERM */
222 };
223
224 /* POLL PDU */
225 static void     (*sscop_poll_tab[SOS_NUMSTATES])
226                                 (struct sscop *, KBuffer *, caddr_t) = {
227                         NULL,                   /* SOS_INST */
228                         sscop_poll_idle,        /* SOS_IDLE */
229                         sscop_noop,             /* SOS_OUTCONN */
230                         sscop_poll_inconn,      /* SOS_INCONN */
231                         sscop_noop,             /* SOS_OUTDISC */
232                         sscop_poll_ready,       /* SOS_OUTRESYN */
233                         sscop_poll_inresyn,     /* SOS_INRESYN */
234                         sscop_poll_conresyn,    /* SOS_CONRESYN */
235                         NULL,                   /* invalid */
236                         NULL,                   /* invalid */
237                         sscop_poll_ready,       /* SOS_READY */
238                         sscop_noop              /* SOS_TERM */
239 };
240
241 /* STAT PDU */
242 static void     (*sscop_stat_tab[SOS_NUMSTATES])
243                                 (struct sscop *, KBuffer *, caddr_t) = {
244                         NULL,                   /* SOS_INST */
245                         sscop_stat_idle,        /* SOS_IDLE */
246                         sscop_noop,             /* SOS_OUTCONN */
247                         sscop_stat_inconn,      /* SOS_INCONN */
248                         sscop_noop,             /* SOS_OUTDISC */
249                         sscop_noop,             /* SOS_OUTRESYN */
250                         sscop_stat_ready,       /* SOS_INRESYN */
251                         sscop_stat_conresyn,    /* SOS_CONRESYN */
252                         NULL,                   /* invalid */
253                         NULL,                   /* invalid */
254                         sscop_stat_ready,       /* SOS_READY */
255                         sscop_noop              /* SOS_TERM */
256 };
257
258 /* USTAT PDU */
259 static void     (*sscop_ustat_tab[SOS_NUMSTATES])
260                                 (struct sscop *, KBuffer *, caddr_t) = {
261                         NULL,                   /* SOS_INST */
262                         sscop_ustat_idle,       /* SOS_IDLE */
263                         sscop_noop,             /* SOS_OUTCONN */
264                         sscop_ustat_inconn,     /* SOS_INCONN */
265                         sscop_noop,             /* SOS_OUTDISC */
266                         sscop_noop,             /* SOS_OUTRESYN */
267                         sscop_ustat_ready,      /* SOS_INRESYN */
268                         sscop_ustat_conresyn,   /* SOS_CONRESYN */
269                         NULL,                   /* invalid */
270                         NULL,                   /* invalid */
271                         sscop_ustat_ready,      /* SOS_READY */
272                         sscop_noop              /* SOS_TERM */
273 };
274
275 /* UD PDU */
276 static void     (*sscop_ud_tab[SOS_NUMSTATES])
277                                 (struct sscop *, KBuffer *, caddr_t) = {
278                         NULL,                   /* SOS_INST */
279                         sscop_ud_all,           /* SOS_IDLE */
280                         sscop_ud_all,           /* SOS_OUTCONN */
281                         sscop_ud_all,           /* SOS_INCONN */
282                         sscop_ud_all,           /* SOS_OUTDISC */
283                         sscop_ud_all,           /* SOS_OUTRESYN */
284                         sscop_ud_all,           /* SOS_INRESYN */
285                         sscop_ud_all,           /* SOS_CONRESYN */
286                         NULL,                   /* invalid */
287                         NULL,                   /* invalid */
288                         sscop_ud_all,           /* SOS_READY */
289                         sscop_noop              /* SOS_TERM */
290 };
291
292 /* MD PDU */
293 static void     (*sscop_md_tab[SOS_NUMSTATES])
294                                 (struct sscop *, KBuffer *, caddr_t) = {
295                         NULL,                   /* SOS_INST */
296                         sscop_md_all,           /* SOS_IDLE */
297                         sscop_md_all,           /* SOS_OUTCONN */
298                         sscop_md_all,           /* SOS_INCONN */
299                         sscop_md_all,           /* SOS_OUTDISC */
300                         sscop_md_all,           /* SOS_OUTRESYN */
301                         sscop_md_all,           /* SOS_INRESYN */
302                         sscop_md_all,           /* SOS_CONRESYN */
303                         NULL,                   /* invalid */
304                         NULL,                   /* invalid */
305                         sscop_md_all,           /* SOS_READY */
306                         sscop_noop              /* SOS_TERM */
307 };
308
309
310 /*
311  * PDU type lookup table
312  */
313 void    (*(*sscop_qsaal_pdutab[]))
314                                 (struct sscop *, KBuffer *, caddr_t) = {
315                 NULL,
316                 sscop_bgn_tab,
317                 sscop_bgak_tab,
318                 sscop_end_tab,
319                 sscop_endak_tab,
320                 sscop_rs_tab,
321                 sscop_rsak_tab,
322                 sscop_bgrej_tab,
323                 sscop_sd_tab,
324                 sscop_sdp_tab,
325                 sscop_poll_tab,
326                 sscop_stat_tab,
327                 sscop_ustat_tab,
328                 sscop_ud_tab,
329                 sscop_md_tab,
330                 NULL
331 };
332
333
334 /*
335  * BGN PDU / SOS_OUTCONN Processor
336  * 
337  * Arguments:
338  *      sop     pointer to sscop connection block
339  *      m       pointer to PDU buffer (without trailer)
340  *      trlr    pointer to PDU trailer
341  *
342  * Returns:
343  *      none
344  *
345  */
346 static void
347 sscop_bgn_outconn(struct sscop *sop, KBuffer *m, caddr_t trlr)
348 {
349         struct bgn_pdu  *bp = (struct bgn_pdu *)trlr;
350         int             err;
351
352         /*
353          * Initialize transmit window
354          */
355         SEQ_SET(sop->so_sendmax, ntohl(bp->bgn_nmr));
356
357         /*
358          * Notify user of connection establishment
359          */
360         if (sop->so_flags & SOF_REESTAB) {
361                 KB_FREEALL(m);
362                 STACK_CALL(SSCOP_ESTABLISH_IND, sop->so_upper, sop->so_toku, 
363                         sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
364                 if (err) {
365                         sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
366                         return;
367                 }
368                 sop->so_flags &= ~SOF_REESTAB;
369         } else {
370                 STACK_CALL(SSCOP_ESTABLISH_CNF, sop->so_upper, sop->so_toku, 
371                         sop->so_connvc, (int)m, 0, err);
372                 if (err) {
373                         KB_FREEALL(m);
374                         sscop_abort(sop, "sscop_bgn_outconn: stack memory\n");
375                         return;
376                 }
377         }
378
379         /*
380          * Return an ACK to peer
381          */
382         sscop_send_bgak(sop);
383
384         /*
385          * Stop retransmit timer
386          */
387         sop->so_timer[SSCOP_T_CC] = 0;
388
389         /*
390          * Reset receiver variables
391          */
392         qsaal1_reset_rcvr(sop);
393         
394         /*
395          * Start polling timer
396          */
397         sscop_set_poll(sop);
398
399         /*
400          * Start lost poll/stat timer
401          */
402         sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
403
404         /*
405          * OK, we're ready for data
406          */
407         sop->so_state = SOS_READY;
408
409         /*
410          * See if transmit queues need servicing
411          */
412         if (sop->so_flags & SOF_XMITSRVC)
413                 sscop_service_xmit(sop);
414
415         return;
416 }
417
418
419 /*
420  * END PDU / SOS_OUTRESYN Processor
421  * 
422  * Arguments:
423  *      sop     pointer to sscop connection block
424  *      m       pointer to PDU buffer (without trailer)
425  *      trlr    pointer to PDU trailer
426  *
427  * Returns:
428  *      none
429  *
430  */
431 static void
432 sscop_end_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
433 {
434         struct end_pdu  *ep = (struct end_pdu *)trlr;
435         int             err, source;
436
437         /*
438          * Stop retransmit timer
439          */
440         sop->so_timer[SSCOP_T_CC] = 0;
441
442         /*
443          * Acknowledge END
444          */
445         sscop_send_endak(sop);
446
447         /*
448          * Get Source value
449          */
450         if (ep->end_type & PT_SOURCE_SSCOP)
451                 source = SSCOP_SOURCE_SSCOP;
452         else
453                 source = SSCOP_SOURCE_USER;
454
455         /*
456          * Notify user of connection termination
457          */
458         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
459                 sop->so_connvc, (int)m, source, err);
460         if (err) {
461                 KB_FREEALL(m);
462                 sscop_abort(sop, "sscop_end_outresyn: stack memory\n");
463                 return;
464         }
465
466         /*
467          * Clear connection data
468          */
469         qsaal1_clear_connection(sop);
470
471         /*
472          * Back to idle state
473          */
474         sop->so_state = SOS_IDLE;
475
476         return;
477 }
478
479
480 /*
481  * END PDU / SOS_CONRESYN Processor
482  * 
483  * Arguments:
484  *      sop     pointer to sscop connection block
485  *      m       pointer to PDU buffer (without trailer)
486  *      trlr    pointer to PDU trailer
487  *
488  * Returns:
489  *      none
490  *
491  */
492 static void
493 sscop_end_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
494 {
495         int             err;
496
497         /*
498          * Stop retransmit timer
499          */
500         sop->so_timer[SSCOP_T_CC] = 0;
501
502         /*
503          * Free up buffers
504          */
505         KB_FREEALL(m);
506
507         /*
508          * Acknowledge END
509          */
510         sscop_send_endak(sop);
511
512         /*
513          * Notify user of connection termination
514          */
515         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
516                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
517         if (err) {
518                 sscop_abort(sop, "sscop_end_conresyn: stack memory\n");
519                 return;
520         }
521
522         /*
523          * Clear connection data
524          */
525         qsaal1_clear_connection(sop);
526
527         /*
528          * Back to idle state
529          */
530         sop->so_state = SOS_IDLE;
531
532         return;
533 }
534
535
536 /*
537  * END PDU / SOS_READY Processor
538  * 
539  * Arguments:
540  *      sop     pointer to sscop connection block
541  *      m       pointer to PDU buffer (without trailer)
542  *      trlr    pointer to PDU trailer
543  *
544  * Returns:
545  *      none
546  *
547  */
548 static void
549 sscop_end_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
550 {
551         struct end_pdu  *ep = (struct end_pdu *)trlr;
552         int             err, source;
553
554         /*
555          * Stop poll timer
556          */
557         sop->so_timer[SSCOP_T_POLL] = 0;
558         sop->so_flags &= ~SOF_KEEPALIVE;
559
560         /*
561          * Stop lost poll/stat timer
562          */
563         sop->so_timer[SSCOP_T_NORESP] = 0;
564
565         /*
566          * Acknowledge END
567          */
568         sscop_send_endak(sop);
569
570         /*
571          * Get Source value
572          */
573         if (ep->end_type & PT_SOURCE_SSCOP)
574                 source = SSCOP_SOURCE_SSCOP;
575         else
576                 source = SSCOP_SOURCE_USER;
577
578         /*
579          * Notify user of connection termination
580          */
581         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
582                 sop->so_connvc, (int)m, source, err);
583         if (err) {
584                 KB_FREEALL(m);
585                 sscop_abort(sop, "sscop_end_ready: stack memory\n");
586                 return;
587         }
588
589         /*
590          * Clear connection data
591          */
592         qsaal1_clear_connection(sop);
593
594         /*
595          * Back to idle state
596          */
597         sop->so_state = SOS_IDLE;
598
599         return;
600 }
601
602
603 /*
604  * ENDAK PDU / SOS_OUTRESYN Processor
605  * 
606  * Arguments:
607  *      sop     pointer to sscop connection block
608  *      m       pointer to PDU buffer (without trailer)
609  *      trlr    pointer to PDU trailer
610  *
611  * Returns:
612  *      none
613  *
614  */
615 static void
616 sscop_endak_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
617 {
618         int             err;
619
620         /*
621          * Stop retransmit timer
622          */
623         sop->so_timer[SSCOP_T_CC] = 0;
624
625         /*
626          * Report protocol error
627          */
628         sscop_endak_error(sop, m, trlr);
629
630         /*
631          * Notify user of connection failure
632          */
633         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
634                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
635         if (err) {
636                 sscop_abort(sop, "sscop_endak_outresyn: stack memory\n");
637                 return;
638         }
639
640         /*
641          * Clear connection data
642          */
643         qsaal1_clear_connection(sop);
644
645         /*
646          * Back to idle state
647          */
648         sop->so_state = SOS_IDLE;
649
650         return;
651 }
652
653
654 /*
655  * RS PDU / SOS_OUTRESYN Processor
656  * 
657  * Arguments:
658  *      sop     pointer to sscop connection block
659  *      m       pointer to PDU buffer (without trailer)
660  *      trlr    pointer to PDU trailer
661  *
662  * Returns:
663  *      none
664  *
665  */
666 static void
667 sscop_rs_outresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
668 {
669         int             err;
670
671         /*
672          * Notify user of resynchronization
673          */
674         STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku, 
675                 sop->so_connvc, (int)m, 0, err);
676         if (err) {
677                 KB_FREEALL(m);
678                 sscop_abort(sop, "sscop_rs_outresyn: stack memory\n");
679                 return;
680         }
681
682         /*
683          * Reset receiver state variables
684          */
685         qsaal1_reset_rcvr(sop);
686
687         /*
688          * Wait for both peer and user responses
689          */
690         sop->so_state = SOS_CONRESYN;
691
692         return;
693 }
694
695
696 /*
697  * RS PDU / SOS_READY Processor
698  * 
699  * Arguments:
700  *      sop     pointer to sscop connection block
701  *      m       pointer to PDU buffer (without trailer)
702  *      trlr    pointer to PDU trailer
703  *
704  * Returns:
705  *      none
706  *
707  */
708 static void
709 sscop_rs_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
710 {
711         int             err;
712
713         /*
714          * Notify user of resynchronization
715          */
716         STACK_CALL(SSCOP_RESYNC_IND, sop->so_upper, sop->so_toku, 
717                 sop->so_connvc, (int)m, 0, err);
718         if (err) {
719                 KB_FREEALL(m);
720                 sscop_abort(sop, "sscop_rs_ready: stack memory\n");
721                 return;
722         }
723
724         /*
725          * Reset receiver state variables
726          */
727         qsaal1_reset_rcvr(sop);
728
729         /*
730          * Wait for user response
731          */
732         sop->so_state = SOS_INRESYN;
733
734         return;
735 }
736
737
738 /*
739  * RSAK PDU / SOS_CONRESYN Processor
740  * 
741  * Arguments:
742  *      sop     pointer to sscop connection block
743  *      m       pointer to PDU buffer (without trailer)
744  *      trlr    pointer to PDU trailer
745  *
746  * Returns:
747  *      none
748  *
749  */
750 static void
751 sscop_rsak_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
752 {
753         int             err;
754
755         /*
756          * Stop retransmit timer
757          */
758         sop->so_timer[SSCOP_T_CC] = 0;
759
760         /*
761          * Free buffers
762          */
763         KB_FREEALL(m);
764
765         /*
766          * Notify user of resynchronization completion
767          */
768         STACK_CALL(SSCOP_RESYNC_CNF, sop->so_upper, sop->so_toku, 
769                 sop->so_connvc, 0, 0, err);
770         if (err) {
771                 sscop_abort(sop, "sscop_rsak_conresyn: stack memory\n");
772                 return;
773         }
774
775         /*
776          * Start the polling timer
777          */
778         sscop_set_poll(sop);
779
780         /*
781          * Start lost poll/stat timer
782          */
783         sop->so_timer[SSCOP_T_NORESP] = sop->so_parm.sp_timeresp;
784
785         /*
786          * Continue waiting for user response
787          */
788         sop->so_state = SOS_INRESYN;
789
790         /*
791          * See if transmit queues need servicing
792          */
793         if (sop->so_flags & SOF_XMITSRVC)
794                 sscop_service_xmit(sop);
795
796         return;
797 }
798
799
800 /*
801  * SD PDU / SOS_INRESYN Processor
802  * 
803  * Arguments:
804  *      sop     pointer to sscop connection block
805  *      m       pointer to PDU buffer (without trailer)
806  *      trlr    pointer to PDU trailer
807  *
808  * Returns:
809  *      none
810  *
811  */
812 static void
813 sscop_sd_inresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
814 {
815         int             err;
816
817         /*
818          * Stop poll timer
819          */
820         sop->so_timer[SSCOP_T_POLL] = 0;
821         sop->so_flags &= ~SOF_KEEPALIVE;
822
823         /*
824          * Stop lost poll/stat timer
825          */
826         sop->so_timer[SSCOP_T_NORESP] = 0;
827
828         /*
829          * Record error condition
830          */
831         sscop_sd_error(sop, m, trlr);
832
833         /*
834          * Return an END to peer
835          */
836         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
837
838         /*
839          * Notify user of connection failure
840          */
841         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
842                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
843         if (err) {
844                 sscop_abort(sop, "sscop_sd_inresyn: stack memory\n");
845                 return;
846         }
847
848         /*
849          * Clear connection data
850          */
851         qsaal1_clear_connection(sop);
852
853         /*
854          * Go back to idle state
855          */
856         sop->so_state = SOS_IDLE;
857
858         return;
859 }
860
861
862 /*
863  * SD PDU / SOS_CONRESYN Processor
864  * 
865  * Arguments:
866  *      sop     pointer to sscop connection block
867  *      m       pointer to PDU buffer (without trailer)
868  *      trlr    pointer to PDU trailer
869  *
870  * Returns:
871  *      none
872  *
873  */
874 static void
875 sscop_sd_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
876 {
877         int             err;
878
879         /*
880          * Stop retransmit timer
881          */
882         sop->so_timer[SSCOP_T_CC] = 0;
883
884         /*
885          * Record error condition
886          */
887         sscop_sd_error(sop, m, trlr);
888
889         /*
890          * Return an END to peer
891          */
892         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
893
894         /*
895          * Notify user of connection failure
896          */
897         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
898                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
899         if (err) {
900                 sscop_abort(sop, "sscop_sd_conresyn: stack memory\n");
901                 return;
902         }
903
904         /*
905          * Clear connection data
906          */
907         qsaal1_clear_connection(sop);
908
909         /*
910          * Go back to idle state
911          */
912         sop->so_state = SOS_IDLE;
913
914         return;
915 }
916
917
918 /*
919  * SD/SDP PDU Common Processor
920  * 
921  * Arguments:
922  *      sop     pointer to sscop connection block
923  *      m       pointer to PDU user data buffer chain
924  *      trlr    pointer to PDU trailer
925  *      type    PDU type (SD or SDP)
926  *
927  * Returns:
928  *      none
929  *
930  */
931 static void
932 sscop_sd_process(struct sscop *sop, KBuffer *m, caddr_t trlr, int type)
933 {
934         struct sd_pdu   *sp;
935         struct sdp_pdu  *spp;
936         struct poll_pdu poll;
937         struct pdu_hdr  *php;
938         KBuffer         *n;
939         sscop_seq       ns, nps;
940         int             err, space;
941
942         /*
943          * Get PDU sequence number(s)
944          */
945         if (type == PT_SD) {
946                 sp = (struct sd_pdu *)trlr;
947                 SEQ_SET(ns, ntohl(sp->sd_ns));
948                 SEQ_SET(nps, 0);
949         } else {
950                 spp = (struct sdp_pdu *)trlr;
951                 SEQ_SET(ns, ntohl(spp->sdp_ns));
952                 SEQ_SET(nps, ntohl(spp->sdp_nps));
953         }
954
955         /*
956          * Ensure that the sequence number fits within the window
957          */
958         if (SEQ_GEQ(ns, sop->so_rcvmax, sop->so_rcvnext)) {
959                 KB_FREEALL(m);
960                 return;
961         }
962
963         /*
964          * If this is the next in-sequence PDU, hand it to user
965          */
966         if (ns == sop->so_rcvnext) {
967                 STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku, 
968                         sop->so_connvc, (int)m, ns, err);
969                 if (err) {
970                         KB_FREEALL(m);
971                         return;
972                 }
973
974                 /*
975                  * Bump next expected sequence number
976                  */
977                 SEQ_INCR(sop->so_rcvnext, 1);
978
979                 /*
980                  * Slide receive window down
981                  */
982                 SEQ_INCR(sop->so_rcvmax, 1);
983
984                 /*
985                  * Is this the highest sequence PDU we've received??
986                  */
987                 if (ns == sop->so_rcvhigh) {
988                         /*
989                          * Yes, bump the limit and exit
990                          */
991                         sop->so_rcvhigh = sop->so_rcvnext;
992                         if (type == PT_SDP)
993                                 goto dopoll;
994                         return;
995                 }
996
997                 /*
998                  * This is a retransmitted PDU, so see if we have
999                  * more in-sequence PDUs already queued up
1000                  */
1001                 while ((php = sop->so_recv_hd) && 
1002                        (php->ph_ns == sop->so_rcvnext)) {
1003
1004                         /*
1005                          * Yup we do, so remove next PDU from queue and
1006                          * pass it up to the user as well
1007                          */
1008                         sop->so_recv_hd = php->ph_recv_lk;
1009                         if (sop->so_recv_hd == NULL)
1010                                 sop->so_recv_tl = NULL;
1011                         STACK_CALL(SSCOP_DATA_IND, sop->so_upper, sop->so_toku,
1012                                 sop->so_connvc, (int)php->ph_buf, php->ph_ns,
1013                                 err);
1014                         if (err) {
1015                                 /*
1016                                  * Should never happen, but...
1017                                  */
1018                                 KB_FREEALL(php->ph_buf);
1019                                 sscop_abort(sop,
1020                                         "sscop_sd_process: stack memory\n");
1021                                 return;
1022                         }
1023
1024                         /*
1025                          * Bump next expected sequence number
1026                          */
1027                         SEQ_INCR(sop->so_rcvnext, 1);
1028
1029                         /*
1030                          * Slide receive window down
1031                          */
1032                         SEQ_INCR(sop->so_rcvmax, 1);
1033                 }
1034
1035                 /*
1036                  * Finished with data...see if we need to poll
1037                  */
1038                 if (type == PT_SDP)
1039                         goto dopoll;
1040                 return;
1041         }
1042
1043         /*
1044          * We're gonna have to queue this PDU, so find space 
1045          * for the PDU header
1046          */
1047         KB_HEADROOM(m, space);
1048
1049         /*
1050          * If there's not enough room in the received buffer,
1051          * allocate & link a new buffer for the header
1052          */
1053         if (space < sizeof(struct pdu_hdr)) {
1054
1055                 KB_ALLOC(n, sizeof(struct pdu_hdr), KB_F_NOWAIT, KB_T_HEADER);
1056                 if (n == NULL) {
1057                         KB_FREEALL(m);
1058                         return;
1059                 }
1060                 KB_HEADSET(n, sizeof(struct pdu_hdr));
1061                 KB_LEN(n) = 0;
1062                 KB_LINKHEAD(n, m);
1063                 m = n;
1064         }
1065
1066         /*
1067          * Build PDU header
1068          *
1069          * We can at least assume/require that the start of
1070          * the user data is aligned.  Also note that we don't
1071          * include this header in the buffer len/offset fields.
1072          */
1073         KB_DATASTART(m, php, struct pdu_hdr *);
1074         php--;
1075         php->ph_ns = ns;
1076         php->ph_buf = m;
1077
1078         /*
1079          * Insert PDU into the receive queue
1080          */
1081         if (sscop_recv_insert(sop, php)) {
1082                 /*
1083                  * Oops, a duplicate sequence number PDU is already on
1084                  * the queue, somethings wrong here.
1085                  */
1086                 sscop_maa_error(sop, 'Q');
1087
1088                 /*
1089                  * Free buffers
1090                  */
1091                 KB_FREEALL(m);
1092
1093                 /*
1094                  * Reestablish a new connection
1095                  */
1096                 qsaal1_reestablish(sop);
1097
1098                 return;
1099         }
1100
1101         /*
1102          * Are we at the high-water mark??
1103          */
1104         if (ns == sop->so_rcvhigh) {
1105                 /*
1106                  * Yes, just bump the mark
1107                  */
1108                 SEQ_INCR(sop->so_rcvhigh, 1);
1109
1110                 if (type == PT_SDP)
1111                         goto dopoll;
1112                 return;
1113         }
1114
1115         /*
1116          * Are we beyond the high-water mark??
1117          */
1118         if (SEQ_GT(ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1119                 /*
1120                  * Yes, then there's a missing PDU, so inform the transmitter
1121                  */
1122                 if (type == PT_SD)
1123                         sscop_send_ustat(sop, ns);
1124
1125                 /*
1126                  * Update high-water mark
1127                  */
1128                 sop->so_rcvhigh = SEQ_ADD(ns, 1);
1129         }
1130
1131         if (type == PT_SD)
1132                 return;
1133
1134 dopoll:
1135         /*
1136          * Do the "poll" part of an SDP PDU
1137          */
1138         poll.poll_nps = htonl(nps);
1139         poll.poll_ns = htonl((PT_POLL << PT_TYPE_SHIFT) | ns);
1140         sscop_poll_ready(sop, NULL, (caddr_t)&poll);
1141         return;
1142 }
1143
1144
1145 /*
1146  * SD PDU / SOS_READY Processor
1147  * 
1148  * Arguments:
1149  *      sop     pointer to sscop connection block
1150  *      m       pointer to PDU buffer (without trailer)
1151  *      trlr    pointer to PDU trailer
1152  *
1153  * Returns:
1154  *      none
1155  *
1156  */
1157 static void
1158 sscop_sd_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1159 {
1160         /*
1161          * Just call common SD/SDP processor
1162          */
1163         sscop_sd_process(sop, m, trlr, PT_SD);
1164
1165         return;
1166 }
1167
1168
1169 /*
1170  * SDP PDU / SOS_READY Processor
1171  * 
1172  * Arguments:
1173  *      sop     pointer to sscop connection block
1174  *      m       pointer to PDU buffer (without trailer)
1175  *      trlr    pointer to PDU trailer
1176  *
1177  * Returns:
1178  *      none
1179  *
1180  */
1181 static void
1182 sscop_sdp_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1183 {
1184         /*
1185          * Just call common SD/SDP processor
1186          */
1187         sscop_sd_process(sop, m, trlr, PT_SDP);
1188
1189         return;
1190 }
1191
1192
1193 /*
1194  * POLL PDU / SOS_INRESYN Processor
1195  * 
1196  * Arguments:
1197  *      sop     pointer to sscop connection block
1198  *      m       pointer to PDU buffer (without trailer)
1199  *      trlr    pointer to PDU trailer
1200  *
1201  * Returns:
1202  *      none
1203  *
1204  */
1205 static void
1206 sscop_poll_inresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1207 {
1208         int             err;
1209
1210         /*
1211          * Stop poll timer
1212          */
1213         sop->so_timer[SSCOP_T_POLL] = 0;
1214         sop->so_flags &= ~SOF_KEEPALIVE;
1215
1216         /*
1217          * Stop lost poll/stat timer
1218          */
1219         sop->so_timer[SSCOP_T_NORESP] = 0;
1220
1221         /*
1222          * Report protocol error
1223          */
1224         sscop_poll_error(sop, m, trlr);
1225
1226         /*
1227          * Return an END to peer
1228          */
1229         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1230
1231         /*
1232          * Notify user of connection failure
1233          */
1234         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
1235                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1236         if (err) {
1237                 sscop_abort(sop, "sscop_poll_inresyn: stack memory\n");
1238                 return;
1239         }
1240
1241         /*
1242          * Clear connection data
1243          */
1244         qsaal1_clear_connection(sop);
1245
1246         /*
1247          * Back to idle state
1248          */
1249         sop->so_state = SOS_IDLE;
1250
1251         return;
1252 }
1253
1254
1255 /*
1256  * POLL PDU / SOS_CONRESYN Processor
1257  * 
1258  * Arguments:
1259  *      sop     pointer to sscop connection block
1260  *      m       pointer to PDU buffer (without trailer)
1261  *      trlr    pointer to PDU trailer
1262  *
1263  * Returns:
1264  *      none
1265  *
1266  */
1267 static void
1268 sscop_poll_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1269 {
1270         int             err;
1271
1272         /*
1273          * Stop retransmit timer
1274          */
1275         sop->so_timer[SSCOP_T_CC] = 0;
1276
1277         /*
1278          * Record error condition
1279          */
1280         sscop_poll_error(sop, m, trlr);
1281
1282         /*
1283          * Return an END to peer
1284          */
1285         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1286
1287         /*
1288          * Notify user of connection failure
1289          */
1290         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
1291                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1292         if (err) {
1293                 sscop_abort(sop, "sscop_poll_conresyn: stack memory\n");
1294                 return;
1295         }
1296
1297         /*
1298          * Clear connection data
1299          */
1300         qsaal1_clear_connection(sop);
1301
1302         /*
1303          * Go back to idle state
1304          */
1305         sop->so_state = SOS_IDLE;
1306
1307         return;
1308 }
1309
1310
1311 /*
1312  * POLL PDU / SOS_READY Processor
1313  * 
1314  * Arguments:
1315  *      sop     pointer to sscop connection block
1316  *      m       pointer to PDU buffer (without trailer)
1317  *      trlr    pointer to PDU trailer
1318  *
1319  * Returns:
1320  *      none
1321  *
1322  */
1323 static void
1324 sscop_poll_ready(struct sscop *sop, KBuffer *m, caddr_t trlr)
1325 {
1326         struct poll_pdu *pp = (struct poll_pdu *)trlr;
1327         sscop_seq       nps;
1328
1329         pp->poll_ns = ntohl(pp->poll_ns);
1330
1331         /*
1332          * If the poll sequence number is less than highest number
1333          * we've already seen, something's wrong - so attempt to
1334          * reestablish a new connection.
1335          */
1336         if (SEQ_LT(pp->poll_ns, sop->so_rcvhigh, sop->so_rcvnext)) {
1337                 /*
1338                  * Record error condition
1339                  */
1340                 sscop_maa_error(sop, 'Q');
1341
1342                 /*
1343                  * Free buffers
1344                  */
1345                 KB_FREEALL(m);
1346
1347                 /*
1348                  * Reestablish a new connection
1349                  */
1350                 qsaal1_reestablish(sop);
1351
1352                 return;
1353         }
1354
1355         /*
1356          * Set a new "next highest" sequence number expected
1357          */
1358         if (SEQ_LT(pp->poll_ns, sop->so_rcvmax, sop->so_rcvnext))
1359                 SEQ_SET(sop->so_rcvhigh, pp->poll_ns);
1360         else
1361                 sop->so_rcvhigh = sop->so_rcvmax;
1362
1363         /*
1364          * Return a STAT PDU to peer
1365          */
1366         SEQ_SET(nps, ntohl(pp->poll_nps));
1367         KB_FREEALL(m);
1368         sscop_send_stat(sop, nps);
1369
1370         return;
1371 }
1372
1373
1374 /*
1375  * STAT PDU / SOS_CONRESYN Processor
1376  * 
1377  * Arguments:
1378  *      sop     pointer to sscop connection block
1379  *      m       pointer to PDU buffer (without trailer)
1380  *      trlr    pointer to PDU trailer
1381  *
1382  * Returns:
1383  *      none
1384  *
1385  */
1386 static void
1387 sscop_stat_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1388 {
1389         int             err;
1390
1391         /*
1392          * Stop retransmit timer
1393          */
1394         sop->so_timer[SSCOP_T_CC] = 0;
1395
1396         /*
1397          * Record error condition
1398          */
1399         sscop_stat_error(sop, m, trlr);
1400
1401         /*
1402          * Return an END to peer
1403          */
1404         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1405
1406         /*
1407          * Notify user of connection failure
1408          */
1409         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
1410                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1411         if (err) {
1412                 sscop_abort(sop, "sscop_stat_conresyn: stack memory\n");
1413                 return;
1414         }
1415
1416         /*
1417          * Clear connection data
1418          */
1419         qsaal1_clear_connection(sop);
1420
1421         /*
1422          * Go back to idle state
1423          */
1424         sop->so_state = SOS_IDLE;
1425
1426         return;
1427 }
1428
1429
1430 /*
1431  * USTAT PDU / SOS_CONRESYN Processor
1432  * 
1433  * Arguments:
1434  *      sop     pointer to sscop connection block
1435  *      m       pointer to PDU buffer (without trailer)
1436  *      trlr    pointer to PDU trailer
1437  *
1438  * Returns:
1439  *      none
1440  *
1441  */
1442 static void
1443 sscop_ustat_conresyn(struct sscop *sop, KBuffer *m, caddr_t trlr)
1444 {
1445         int             err;
1446
1447         /*
1448          * Stop retransmit timer
1449          */
1450         sop->so_timer[SSCOP_T_CC] = 0;
1451
1452         /*
1453          * Record error condition
1454          */
1455         sscop_ustat_error(sop, m, trlr);
1456
1457         /*
1458          * Return an END to peer
1459          */
1460         sscop_send_end(sop, SSCOP_SOURCE_SSCOP);
1461
1462         /*
1463          * Notify user of connection failure
1464          */
1465         STACK_CALL(SSCOP_RELEASE_IND, sop->so_upper, sop->so_toku, 
1466                 sop->so_connvc, SSCOP_UU_NULL, SSCOP_SOURCE_SSCOP, err);
1467         if (err) {
1468                 sscop_abort(sop, "sscop_ustat_conresyn: stack memory\n");
1469                 return;
1470         }
1471
1472         /*
1473          * Clear connection data
1474          */
1475         qsaal1_clear_connection(sop);
1476
1477         /*
1478          * Go back to idle state
1479          */
1480         sop->so_state = SOS_IDLE;
1481
1482         return;
1483 }
1484