kernel: Sync ACPICA with Intel's version 20140424.
[dragonfly.git] / sys / netproto / atm / uni / unisig_sigmgr_state.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/unisig_sigmgr_state.c,v 1.6 2000/01/17 20:49:58 mks Exp $
27  */
28
29 /*
30  * ATM Forum UNI 3.0/3.1 Signalling Manager
31  * ----------------------------------------
32  *
33  * Signalling manager finite state machine
34  *
35  */
36
37 #include <netproto/atm/kern_include.h>
38
39 #include "uni.h"
40 #include "unisig.h"
41 #include "unisig_var.h"
42
43 /*
44  * Local functions
45  */
46 static int      unisig_sigmgr_invalid (struct unisig *, KBuffer *);
47 static int      unisig_sigmgr_act01 (struct unisig *, KBuffer *);
48 static int      unisig_sigmgr_act02 (struct unisig *, KBuffer *);
49 static int      unisig_sigmgr_act03 (struct unisig *, KBuffer *);
50 static int      unisig_sigmgr_act04 (struct unisig *, KBuffer *);
51 static int      unisig_sigmgr_act05 (struct unisig *, KBuffer *);
52 static int      unisig_sigmgr_act06 (struct unisig *, KBuffer *);
53 static int      unisig_sigmgr_act07 (struct unisig *, KBuffer *);
54 static int      unisig_sigmgr_act08 (struct unisig *, KBuffer *);
55 static int      unisig_sigmgr_act09 (struct unisig *, KBuffer *);
56 static int      unisig_sigmgr_act10 (struct unisig *, KBuffer *);
57 static int      unisig_sigmgr_act11 (struct unisig *, KBuffer *);
58 static int      unisig_sigmgr_act12 (struct unisig *, KBuffer *);
59 static int      unisig_sigmgr_act13 (struct unisig *, KBuffer *);
60 static int      unisig_sigmgr_act14 (struct unisig *, KBuffer *);
61
62
63 /*
64  * State table.
65  */
66 static int      sigmgr_state_table[10][7] = {
67     /*     0   1   2   3   4   5                                */
68         {  1,  0,  0,  0,  0 }, /* 0 - Time out         */
69         {  0,  0,  3,  5,  0 }, /* 1 - SSCF estab ind   */
70         {  0,  0,  3,  5,  0 }, /* 2 - SSCF estab cnf   */
71         {  0,  0,  4,  6,  0 }, /* 3 - SSCF release ind */
72         {  0,  0,  0,  6,  0 }, /* 4 - SSCF release cnf */
73         {  0,  0,  0,  7,  0 }, /* 5 - SSCF data ind    */
74         {  0,  0,  2,  2,  0 }, /* 6 - SSCF unit data ind */
75         {  0,  0,  8,  8,  8 }, /* 7 - Call cleared     */
76         { 14, 14, 14, 14,  0 }, /* 8 - Detach           */
77         { 13, 13,  0,  0,  0 }  /* 9 - Address set      */
78 };
79
80 /*
81  * Action vector
82  */
83 #define MAX_ACTION      15
84 static int (*unisig_sigmgr_act_vec[MAX_ACTION])
85                  (struct unisig *, KBuffer *) = {
86         unisig_sigmgr_invalid,
87         unisig_sigmgr_act01,
88         unisig_sigmgr_act02,
89         unisig_sigmgr_act03,
90         unisig_sigmgr_act04,
91         unisig_sigmgr_act05,
92         unisig_sigmgr_act06,
93         unisig_sigmgr_act07,
94         unisig_sigmgr_act08,
95         unisig_sigmgr_act09,
96         unisig_sigmgr_act10,
97         unisig_sigmgr_act11,
98         unisig_sigmgr_act12,
99         unisig_sigmgr_act13,
100         unisig_sigmgr_act14
101 };
102
103
104 /*
105  * ATM endpoint for UNI signalling channel
106  */
107 static Atm_endpoint     unisig_endpt = {
108         NULL,                   /* ep_next */
109         ENDPT_UNI_SIG,          /* ep_id */
110         NULL,                   /* ep_ioctl */
111         unisig_getname,         /* ep_getname */
112         unisig_connected,       /* ep_connected */
113         unisig_cleared,         /* ep_cleared */
114         NULL,                   /* ep_incoming */
115         NULL,                   /* ep_addparty */
116         NULL,                   /* ep_dropparty */
117         NULL,                   /* ep_cpcs_ctl */
118         NULL,                   /* ep_cpcs_data */
119         unisig_saal_ctl,        /* ep_saal_ctl */
120         unisig_saal_data,       /* ep_saal_data */
121         NULL,                   /* ep_sscop_ctl */
122         NULL                    /* ep_sscop_data */
123 };
124
125
126 /*
127  * ATM connection attributes for UNI signalling channel
128  */
129 static Atm_attributes   unisig_attr = {
130         NULL,                           /* nif */
131         CMAPI_SAAL,                     /* api */
132         UNI_VERS_3_0,                   /* api_init */
133         0,                              /* headin */
134         0,                              /* headout */
135         {                               /* aal */
136                 T_ATM_PRESENT,          /* aal.tag */
137                 ATM_AAL5                /* aal.aal_type */
138         },
139         {                               /* traffic */
140                 T_ATM_PRESENT,          /* traffic.tag */
141                 {                       /* traffic.v */
142                         {               /* traffic.v.forward */
143                                 T_ATM_ABSENT,   /* PCR_high */
144                                 0,              /* PCR_all */
145                                 T_ATM_ABSENT,   /* SCR_high */
146                                 T_ATM_ABSENT,   /* SCR_all */
147                                 T_ATM_ABSENT,   /* MBS_high */
148                                 T_ATM_ABSENT,   /* MBS_all */
149                                 T_NO,           /* tagging */
150                         },
151                         {               /* traffic.v.backward */
152                                 T_ATM_ABSENT,   /* PCR_high */
153                                 0,              /* PCR_all */
154                                 T_ATM_ABSENT,   /* SCR_high */
155                                 T_ATM_ABSENT,   /* SCR_all */
156                                 T_ATM_ABSENT,   /* MBS_high */
157                                 T_ATM_ABSENT,   /* MBS_all */
158                                 T_NO,           /* tagging */
159                         },
160                         T_YES,                  /* best_effort */
161                 }
162         },
163         {                               /* bearer */
164                 T_ATM_PRESENT,          /* bearer.tag */
165                 {                       /* bearer.v */
166                         T_ATM_CLASS_X,          /* class */
167                         T_ATM_NULL,             /* traffic_type */
168                         T_ATM_NO_END_TO_END,    /* timing_req */
169                         T_NO,                   /* clipping */
170                         T_ATM_1_TO_1,           /* conn_conf */
171                 }
172         },
173         {                               /* bhli */
174                 T_ATM_ABSENT,           /* bhli.tag */
175         },
176         {                               /* blli */
177                 T_ATM_ABSENT,           /* blli.tag_l2 */
178                 T_ATM_ABSENT,           /* blli.tag_l3 */
179         },
180         {                               /* llc */
181                 T_ATM_ABSENT,           /* llc.tag */
182         },
183         {                               /* called */
184                 T_ATM_PRESENT,          /* called.tag */
185         },
186         {                               /* calling */
187                 T_ATM_ABSENT,           /* calling.tag */
188         },
189         {                               /* qos */
190                 T_ATM_PRESENT,          /* qos.tag */
191                 {                       /* qos.v */
192                         T_ATM_NETWORK_CODING,   /* coding_standard */
193                         {                       /* qos.v.forward */
194                                 T_ATM_QOS_CLASS_0,      /* class */
195                         },
196                         {                       /* qos.v.backward */
197                                 T_ATM_QOS_CLASS_0,      /* class */
198                         }
199                 }
200         },
201         {                               /* transit */
202                 T_ATM_ABSENT,           /* transit.tag */
203         },
204         {                               /* cause */
205                 T_ATM_ABSENT,           /* cause.tag */
206         }
207 };
208
209
210 /*
211  * Finite state machine for the UNISIG signalling manager
212  *
213  * Arguments:
214  *      usp     pointer to the UNISIG protocol control block
215  *      event   indication of the event to be processed
216  *      m       pointer to a buffer with a message (optional)
217  *
218  * Returns:
219  *      0       success
220  *      errno   error encountered
221  *
222  */
223 int
224 unisig_sigmgr_state(struct unisig *usp, int event, KBuffer *m)
225 {
226         int             action, err = 0;
227
228         /*
229          * Cancel any signalling manager timer
230          */
231         UNISIG_CANCEL(usp);
232
233         /*
234          * Select an action based on the incoming event and
235          * the signalling manager's state
236          */
237         action = sigmgr_state_table[event][usp->us_state];
238         ATM_DEBUG4("unisig_sigmgr_state: usp=%p, state=%d, event=%d, action=%d\n",
239                         usp, usp->us_state, event, action);
240         if (action >= MAX_ACTION || action < 0) {
241                 panic("unisig_sigmgr_state: invalid action");
242         }
243
244         /*
245          * Perform the requested action
246          */
247         err = unisig_sigmgr_act_vec[action](usp, m);
248
249         return(err);
250 }
251
252
253 /*
254  * Signalling manager state machine action 0
255  *
256  * Invalid action
257  *
258  * Arguments:
259  *      usp     pointer to the UNISIG protocol control block
260  *      m       buffer pointer (may be NULL)
261  *
262  * Returns:
263  *      0       success
264  *      errno   error encountered
265  *
266  */
267 static int
268 unisig_sigmgr_invalid(struct unisig *usp, KBuffer *m)
269 {
270         log(LOG_ERR, "unisig_sigmgr_state: unexpected action\n");
271         if (m)
272                 KB_FREEALL(m);
273         return(0);
274 }
275
276
277 /*
278  * Signalling manager state machine action 1
279  *
280  * The kickoff timer has expired at attach time; go to
281  * UNISIG_ADDR_WAIT state.
282  *
283  * Arguments:
284  *      usp     pointer to the UNISIG protocol control block
285  *      m       buffer pointer (may be NULL)
286  *
287  * Returns:
288  *      0       success
289  *      errno   error encountered
290  *
291  */
292 static int
293 unisig_sigmgr_act01(struct unisig *usp, KBuffer *m)
294 {
295         /*
296          * Set the new state
297          */
298         usp->us_state = UNISIG_ADDR_WAIT;
299
300         return(0);
301 }
302
303
304 /*
305  * Signalling manager state machine action 2
306  *
307  * Ignore the event
308  *
309  * Arguments:
310  *      usp     pointer to the UNISIG protocol control block
311  *      m       buffer pointer (may be NULL)
312  *
313  * Returns:
314  *      0       success
315  *      errno   error encountered
316  *
317  */
318 static int
319 unisig_sigmgr_act02(struct unisig *usp, KBuffer *m)
320 {
321         /*
322          * Ignore event, discard message if present
323          */
324         if (m)
325                 KB_FREEALL(m);
326
327         return(0);
328 }
329
330
331 /*
332  * Signalling manager state machine action 3
333  *
334  * SSCF session on signalling channel has come up
335  *
336  * Arguments:
337  *      usp     pointer to the UNISIG protocol control block
338  *      m       buffer pointer (may be NULL)
339  *
340  * Returns:
341  *      0       success
342  *      errno   error encountered
343  *
344  */
345 static int
346 unisig_sigmgr_act03(struct unisig *usp, KBuffer *m)
347 {
348         struct unisig_vccb      *uvp, *vnext;
349
350         /*
351          * Log the activation
352          */
353         log(LOG_INFO, "unisig: signalling channel active\n");
354
355         /*
356          * Go to ACTIVE state
357          */
358         usp->us_state = UNISIG_ACTIVE;
359
360         /*
361          * Notify the VC state machine that the channel is up
362          */
363         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
364                         uvp; uvp = vnext) {
365                 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
366                 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
367                                 NULL);
368         }
369
370         return(0);
371 }
372
373
374 /*
375  * Signalling manager state machine action 4
376  *
377  * A SSCF release indication was received.  Try to establish an
378  * SSCF session on the signalling PVC.
379  *
380  * Arguments:
381  *      usp     pointer to the UNISIG protocol control block
382  *      m       buffer pointer (may be NULL)
383  *
384  * Returns:
385  *      0       success
386  *      errno   error encountered
387  *
388  */
389 static int
390 unisig_sigmgr_act04(struct unisig *usp, KBuffer *m)
391 {
392         int             err;
393
394         /*
395          * Try to establish an SSCF session.
396          */
397         err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
398         if (err)
399                 panic("unisig_sigmgr_act04: SSCF_UNI_ESTABLISH_REQ");
400
401         return(0);
402 }
403
404
405 /*
406  * Signalling manager state machine action 5
407  *
408  * SSCF session on signalling channel has been reset
409  *
410  * Arguments:
411  *      usp     pointer to the UNISIG protocol control block
412  *      m       buffer pointer (may be NULL)
413  *
414  * Returns:
415  *      0       success
416  *      errno   error encountered
417  *
418  */
419 static int
420 unisig_sigmgr_act05(struct unisig *usp, KBuffer *m)
421 {
422         struct unisig_vccb      *uvp, *vnext;
423
424         /*
425          * Log the reset
426          */
427         log(LOG_INFO, "unisig: signalling channel reset\n");
428
429         /*
430          * Notify the VC state machine of the reset
431          */
432         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
433                         uvp; uvp = vnext) {
434                 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
435                 unisig_vc_state(usp, uvp, UNI_VC_SAAL_ESTAB,
436                                 NULL);
437         }
438
439         return(0);
440 }
441
442
443 /*
444  * Signalling manager state machine action 6
445  *
446  * SSCF session on signalling channel has been lost
447  *
448  * Arguments:
449  *      usp     pointer to the UNISIG protocol control block
450  *      m       buffer pointer (may be NULL)
451  *
452  * Returns:
453  *      0       success
454  *      errno   error encountered
455  *
456  */
457 static int
458 unisig_sigmgr_act06(struct unisig *usp, KBuffer *m)
459 {
460         struct unisig_vccb      *uvp, *vnext;
461
462         /*
463          * Log the fact that the session has been lost
464          */
465         log(LOG_INFO, "unisig: signalling channel SSCF session lost\n");
466
467         /*
468          * Notify the VC state machine of the loss
469          */
470         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
471                         uvp; uvp = vnext) {
472                 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
473                 unisig_vc_state(usp, uvp, UNI_VC_SAAL_FAIL,
474                                 NULL);
475         }
476
477         /*
478          * Try to restart the SSCF session
479          */
480         unisig_sigmgr_act04(usp, NULL);
481
482         /*
483          * Go to INIT state
484          */
485         usp->us_state = UNISIG_INIT;
486
487         return(0);
488 }
489
490
491 /*
492  * Signalling manager state machine action 7
493  *
494  * A Q.2931 signalling message has been received
495  *
496  * Arguments:
497  *      usp     pointer to the UNISIG protocol control block
498  *      m       buffer pointer (may be NULL)
499  *
500  * Returns:
501  *      0       success
502  *      errno   error encountered
503  *
504  */
505 static int
506 unisig_sigmgr_act07(struct unisig *usp, KBuffer *m)
507 {
508         int     err;
509
510         /*
511          * Pass the Q.2931 signalling message on
512          * to the VC state machine
513          */
514         err = unisig_rcv_msg(usp, m);
515
516         return(err);
517 }
518
519
520 /*
521  * Signalling manager state machine action 8
522  *
523  * Process a CALL_CLOSED event for the signalling PVC
524  *
525  * Arguments:
526  *      usp     pointer to the UNISIG protocol control block
527  *      m       buffer pointer (may be NULL)
528  *
529  * Returns:
530  *      0       success
531  *      errno   error encountered
532  *
533  */
534 static int
535 unisig_sigmgr_act08(struct unisig *usp, KBuffer *m)
536 {
537
538         /*
539          * Signalling manager is now incommunicado
540          */
541         if (usp->us_state != UNISIG_DETACH) {
542                 /*
543                  * Log an error and set the state to NULL if
544                  * we're not detaching
545                  */
546                 log(LOG_ERR, "unisig: signalling channel closed\n");
547                 usp->us_state = UNISIG_NULL;
548         }
549         usp->us_conn = 0;
550
551         return(0);
552 }
553
554
555 /*
556  * Signalling manager state machine action 9
557  *
558  * Not used
559  *
560  * Arguments:
561  *      usp     pointer to the UNISIG protocol control block
562  *      m       buffer pointer (may be NULL)
563  *
564  * Returns:
565  *      0       success
566  *      errno   error encountered
567  *
568  */
569 static int
570 unisig_sigmgr_act09(struct unisig *usp, KBuffer *m)
571 {
572         log(LOG_ERR, "unisig_sigmgr_act09: unexpected action\n");
573         if (m)
574                 KB_FREEALL(m);
575         return (0);
576 }
577
578
579 /*
580  * Signalling manager state machine action 10
581  *
582  * Not used
583  *
584  * Arguments:
585  *      usp     pointer to the UNISIG protocol control block
586  *      m       buffer pointer (may be NULL)
587  *
588  * Returns:
589  *      0       success
590  *      errno   error encountered
591  *
592  */
593 static int
594 unisig_sigmgr_act10(struct unisig *usp, KBuffer *m)
595 {
596         return(0);
597 }
598
599
600 /*
601  * Signalling manager state machine action 11
602  *
603  * Not used
604  *
605  * Arguments:
606  *      usp     pointer to the UNISIG protocol control block
607  *      m       buffer pointer (may be NULL)
608  *
609  * Returns:
610  *      0       success
611  *      errno   error encountered
612  *
613  */
614 static int
615 unisig_sigmgr_act11(struct unisig *usp, KBuffer *m)
616 {
617         log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
618         if (m)
619                 KB_FREEALL(m);
620         return(0);
621 }
622
623
624 /*
625  * Signalling manager state machine action 12
626  *
627  * Not used
628  *
629  * Arguments:
630  *      usp     pointer to the UNISIG protocol control block
631  *      m       buffer pointer (may be NULL)
632  *
633  * Returns:
634  *      0       success
635  *      errno   error encountered
636  *
637  */
638 static int
639 unisig_sigmgr_act12(struct unisig *usp, KBuffer *m)
640 {
641         log(LOG_ERR, "unisig_sigmgr_act11: unexpected action\n");
642         if (m)
643                 KB_FREEALL(m);
644         return(0);
645 }
646
647
648 /*
649  * Signalling manager state machine action 13
650  *
651  * NSAP prefix has been set
652  *
653  * Arguments:
654  *      usp     pointer to the UNISIG protocol control block
655  *      m       buffer pointer (may be NULL)
656  *
657  * Returns:
658  *      0       success
659  *      errno   error encountered
660  *
661  */
662 static int
663 unisig_sigmgr_act13(struct unisig *usp, KBuffer *m)
664 {
665         int             err;
666         Atm_addr_pvc    *pvcp;
667
668         /*
669          * Set UNI signalling channel connection attributes
670          */
671         if (usp->us_proto == ATM_SIG_UNI30)
672                 unisig_attr.api_init = UNI_VERS_3_0;
673         else
674                 unisig_attr.api_init = UNI_VERS_3_1;
675
676         unisig_attr.nif = usp->us_pif->pif_nif;
677
678         unisig_attr.aal.v.aal5.forward_max_SDU_size = ATM_NIF_MTU;
679         unisig_attr.aal.v.aal5.backward_max_SDU_size = ATM_NIF_MTU;
680         unisig_attr.aal.v.aal5.SSCS_type = T_ATM_SSCS_SSCOP_REL;
681
682         unisig_attr.called.tag = T_ATM_PRESENT;
683         unisig_attr.called.addr.address_format = T_ATM_PVC_ADDR;
684         unisig_attr.called.addr.address_length = sizeof(Atm_addr_pvc);
685         pvcp = (Atm_addr_pvc *)unisig_attr.called.addr.address;
686         ATM_PVC_SET_VPI(pvcp, UNISIG_SIG_VPI);
687         ATM_PVC_SET_VCI(pvcp, UNISIG_SIG_VCI);
688         unisig_attr.called.subaddr.address_format = T_ATM_ABSENT;
689         unisig_attr.called.subaddr.address_length = 0;
690
691         unisig_attr.traffic.v.forward.PCR_all_traffic =
692                         usp->us_pif->pif_pcr;
693         unisig_attr.traffic.v.backward.PCR_all_traffic =
694                         usp->us_pif->pif_pcr;
695
696         /*
697          * Create UNISIG signalling channel
698          */
699         err = atm_cm_connect(&unisig_endpt, usp, &unisig_attr,
700                         &usp->us_conn);
701         if (err) {
702                 return(err);
703         }
704
705         /*
706          * Establish the SSCF session
707          */
708         err = atm_cm_saal_ctl(SSCF_UNI_ESTABLISH_REQ, usp->us_conn, NULL);
709         if (err)
710                 panic("unisig_sigmgr_act13: SSCF_UNI_ESTABLISH_REQ");
711
712         /*
713          * Set the new state
714          */
715         usp->us_state = UNISIG_INIT;
716
717         return(0);
718 }
719
720
721 /*
722  * Signalling manager state machine action 14
723  *
724  * Process a detach event
725  *
726  * Arguments:
727  *      usp     pointer to the UNISIG protocol control block
728  *      m       buffer pointer (may be NULL)
729  *
730  * Returns:
731  *      0       success
732  *      errno   error encountered
733  *
734  */
735 static int
736 unisig_sigmgr_act14(struct unisig *usp, KBuffer *m)
737 {
738         int                     err;
739         struct unisig_vccb      *sig_vccb, *uvp, *vnext;
740         struct atm_pif          *pip;
741         struct t_atm_cause      cause;
742
743         /*
744          * Locate the signalling channel's VCCB
745          */
746         sig_vccb = NULL;
747         if (usp->us_conn && usp->us_conn->co_connvc)
748                 sig_vccb = (struct unisig_vccb *)
749                                 usp->us_conn->co_connvc->cvc_vcc;
750
751         /*
752          * Terminate all of our VCCs
753          */
754         for (uvp = Q_HEAD(usp->us_vccq, struct unisig_vccb);
755                         uvp; uvp = vnext) {
756                 vnext = Q_NEXT(uvp, struct unisig_vccb, uv_sigelem);
757
758                 /*
759                  * Don't close the signalling VCC yet
760                  */
761                 if (uvp == sig_vccb)
762                         continue;
763
764                 /*
765                  * Close VCC and notify owner
766                  */
767                 err = unisig_clear_vcc(usp, uvp,
768                                 T_ATM_CAUSE_NORMAL_CALL_CLEARING);
769         }
770
771         /*
772          * Close the signalling channel
773          */
774         if (usp->us_conn) {
775                 cause.coding_standard = T_ATM_ITU_CODING;
776                 cause.coding_standard = T_ATM_LOC_USER;
777                 cause.coding_standard = T_ATM_CAUSE_UNSPECIFIED_NORMAL;
778                 err = atm_cm_release(usp->us_conn, &cause);
779                 if (err)
780                         panic("unisig_sigmgr_act14: close failed");
781         }
782
783         /*
784          * Get rid of protocol instance if there are no VCCs queued
785          */
786         pip = usp->us_pif;
787         if (Q_HEAD(usp->us_vccq, struct vccb) == NULL &&
788                         pip->pif_sigmgr) {
789                 struct sigmgr   *smp = pip->pif_sigmgr;
790
791                 crit_enter();
792                 pip->pif_sigmgr = NULL;
793                 pip->pif_siginst = NULL;
794                 crit_exit();
795
796                 UNLINK((struct siginst *)usp, struct siginst,
797                                 smp->sm_prinst, si_next);
798                 KM_FREE(usp, sizeof(struct unisig), M_DEVBUF);
799         } else {
800                 /*
801                  * Otherwise, set new signalling manager state and
802                  * wait for protocol instance to be freed during 
803                  * unisig_free processing for the last queued VCC
804                  */
805                 usp->us_state = UNISIG_DETACH;
806         }
807
808         return (0);
809 }