Replace the remaining NG_*LEN constants with NG_*SIZ constants for real.
[dragonfly/vkernel-mp.git] / sys / net / i4b / driver / i4b_ing.c
blobbeac90a45c90a3a3f47c026104a7e97b1bcf55fd
1 /*
2 * Copyright (c) 1999, 2001 Hellmuth Michaelis. All rights reserved.
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.
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.
25 *---------------------------------------------------------------------------
27 * i4b_ing.c - isdn4bsd B-channel to netgraph driver
28 * -------------------------------------------------
30 * $FreeBSD: src/sys/i4b/driver/i4b_ing.c,v 1.10.2.4 2002/07/02 23:44:02 archie Exp $
31 * $DragonFly: src/sys/net/i4b/driver/i4b_ing.c,v 1.11 2007/06/04 00:40:31 swildner Exp $
33 * last edit-date: [Tue Jan 1 10:43:58 2002]
35 *---------------------------------------------------------------------------*/
37 #include "use_i4bing.h"
39 #if NI4BING > 0
41 #include "opt_i4b.h"
43 #include <sys/param.h>
44 #include <sys/systm.h>
45 #include <sys/kernel.h>
46 #include <sys/mbuf.h>
47 #include <sys/socket.h>
48 #include <sys/errno.h>
49 #include <sys/ctype.h>
50 #include <sys/ioccom.h>
51 #include <sys/syslog.h>
52 #include <sys/malloc.h>
53 #include <sys/thread2.h>
55 #include <net/if.h>
57 #include <netgraph/ng_message.h>
58 #include <netgraph/ng_parse.h>
59 #include <netgraph/netgraph.h>
61 #include <net/i4b/include/machine/i4b_debug.h>
62 #include <net/i4b/include/machine/i4b_ioctl.h>
64 #include "../include/i4b_global.h"
65 #include "../include/i4b_mbuf.h"
66 #include "../include/i4b_l3l4.h"
67 #include "../layer4/i4b_l4.h"
69 #define I4BINGACCT 1 /* enable accounting messages */
70 #define I4BINGACCTINTVL 2 /* accounting msg interval in secs */
72 #define I4BINGMAXQLEN 50 /* max queue length */
74 /* initialized by L4 */
76 static drvr_link_t ing_drvr_linktab[NI4BING];
77 static isdn_link_t *isdn_linktab[NI4BING];
79 struct ing_softc {
80 int sc_unit; /* unit number */
81 int sc_state; /* state of the interface */
82 call_desc_t *sc_cdp; /* ptr to call descriptor */
83 int sc_updown; /* soft state of interface */
84 struct ifqueue sc_fastq; /* interactive traffic */
85 int sc_dialresp; /* dialresponse */
86 int sc_lastdialresp;/* last dialresponse */
88 #if I4BINGACCT
89 struct callout sc_timeout;
90 int sc_iinb; /* isdn driver # of inbytes */
91 int sc_ioutb; /* isdn driver # of outbytes */
92 int sc_inb; /* # of bytes rx'd */
93 int sc_outb; /* # of bytes tx'd */
94 int sc_linb; /* last # of bytes rx'd */
95 int sc_loutb; /* last # of bytes tx'd */
96 int sc_fn; /* flag, first null acct */
97 #endif
99 int sc_inpkt; /* incoming packets */
100 int sc_outpkt; /* outgoing packets */
102 struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
103 struct ifqueue xmitq; /* transmit queue */
105 node_p node; /* back pointer to node */
106 char nodename[NG_NODESIZ]; /* store our node name */
107 hook_p debughook;
108 hook_p hook;
110 u_int packets_in; /* packets in from downstream */
111 u_int packets_out; /* packets out towards downstream */
112 u_int32_t flags;
114 } ing_softc[NI4BING];
116 enum ing_states {
117 ST_IDLE, /* initialized, ready, idle */
118 ST_DIALING, /* dialling out to remote */
119 ST_CONNECTED /* connected to remote */
122 static void i4bingattach(void *);
124 PSEUDO_SET(i4bingattach, i4b_ing);
126 static void ing_init_linktab(int unit);
127 static void ing_tx_queue_empty(int unit);
129 /* ========= NETGRAPH ============= */
131 #define NG_ING_NODE_TYPE "i4bing" /* node type name */
132 #define NGM_ING_COOKIE 947513046 /* node type cookie */
134 /* Hook names */
135 #define NG_ING_HOOK_DEBUG "debug"
136 #define NG_ING_HOOK_RAW "rawdata"
138 /* Netgraph commands understood by this node type */
139 enum {
140 NGM_ING_SET_FLAG = 1,
141 NGM_ING_GET_STATUS,
144 /* This structure is returned by the NGM_ING_GET_STATUS command */
145 struct ngingstat {
146 u_int packets_in; /* packets in from downstream */
147 u_int packets_out; /* packets out towards downstream */
151 * This is used to define the 'parse type' for a struct ngingstat, which
152 * is bascially a description of how to convert a binary struct ngingstat
153 * to an ASCII string and back. See ng_parse.h for more info.
155 * This needs to be kept in sync with the above structure definition
157 #define NG_ING_STATS_TYPE_INFO { \
158 { "packets_in", &ng_parse_int32_type }, \
159 { "packets_out", &ng_parse_int32_type }, \
160 { NULL }, \
164 * This section contains the netgraph method declarations for the
165 * sample node. These methods define the netgraph 'type'.
168 static ng_constructor_t ng_ing_constructor;
169 static ng_rcvmsg_t ng_ing_rcvmsg;
170 static ng_shutdown_t ng_ing_rmnode;
171 static ng_newhook_t ng_ing_newhook;
172 static ng_connect_t ng_ing_connect;
173 static ng_rcvdata_t ng_ing_rcvdata;
174 static ng_disconnect_t ng_ing_disconnect;
176 /* Parse type for struct ngingstat */
177 static const struct
178 ng_parse_struct_field ng_ing_stat_type_fields[] =
179 NG_ING_STATS_TYPE_INFO;
181 static const struct ng_parse_type ng_ing_stat_type = {
182 &ng_parse_struct_type,
183 &ng_ing_stat_type_fields
186 /* List of commands and how to convert arguments to/from ASCII */
188 static const struct ng_cmdlist ng_ing_cmdlist[] = {
190 NGM_ING_COOKIE,
191 NGM_ING_GET_STATUS,
192 "getstatus",
193 NULL,
194 &ng_ing_stat_type,
197 NGM_ING_COOKIE,
198 NGM_ING_SET_FLAG,
199 "setflag",
200 &ng_parse_int32_type,
201 NULL
203 { 0 }
206 /* Netgraph node type descriptor */
207 static struct ng_type typestruct = {
208 NG_VERSION,
209 NG_ING_NODE_TYPE,
210 NULL,
211 ng_ing_constructor,
212 ng_ing_rcvmsg,
213 ng_ing_rmnode,
214 ng_ing_newhook,
215 NULL,
216 ng_ing_connect,
217 ng_ing_rcvdata,
218 ng_ing_rcvdata,
219 ng_ing_disconnect,
220 ng_ing_cmdlist
223 NETGRAPH_INIT_ORDERED(ing, &typestruct, SI_SUB_DRIVERS, SI_ORDER_ANY);
225 /*===========================================================================*
226 * DEVICE DRIVER ROUTINES
227 *===========================================================================*/
229 /*---------------------------------------------------------------------------*
230 * interface attach routine at kernel boot time
231 *---------------------------------------------------------------------------*/
232 static void
233 i4bingattach(void *dummy)
235 struct ing_softc *sc = ing_softc;
236 int i;
237 int ret;
239 kprintf("i4bing: %d i4b NetGraph ISDN B-channel device(s) attached\n", NI4BING);
241 for(i=0; i < NI4BING; sc++, i++)
243 sc->sc_unit = i;
245 ing_init_linktab(i);
247 NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
249 sc->sc_state = ST_IDLE;
251 sc->sc_fastq.ifq_maxlen = I4BINGMAXQLEN;
253 #if I4BINGACCT
254 callout_init(&sc->sc_timeout);
255 sc->sc_iinb = 0;
256 sc->sc_ioutb = 0;
257 sc->sc_inb = 0;
258 sc->sc_outb = 0;
259 sc->sc_linb = 0;
260 sc->sc_loutb = 0;
261 sc->sc_fn = 1;
262 #endif
264 sc->sc_inpkt = 0;
265 sc->sc_outpkt = 0;
267 sc->sc_updown = SOFT_ENA; /* soft enabled */
269 sc->sc_dialresp = DSTAT_NONE; /* no response */
270 sc->sc_lastdialresp = DSTAT_NONE;
272 /* setup a netgraph node */
274 if ((ret = ng_make_node_common(&typestruct, &sc->node)))
276 kprintf("ing: ng_make_node_common, ret = %d\n!", ret);
279 sc->node->private = sc;
281 sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
282 sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
284 /* name the netgraph node */
286 ksprintf(sc->nodename, "%s%d", NG_ING_NODE_TYPE, sc->sc_unit);
288 if(ng_name_node(sc->node, sc->nodename))
290 ng_rmnode(sc->node);
291 ng_unref(sc->node);
296 #ifdef I4BINGACCT
297 /*---------------------------------------------------------------------------*
298 * accounting timeout routine
299 *---------------------------------------------------------------------------*/
300 static void
301 ing_timeout(struct ing_softc *sc)
303 bchan_statistics_t bs;
304 int unit = sc->sc_unit;
306 /* get # of bytes in and out from the HSCX driver */
308 (*isdn_linktab[unit]->bch_stat)
309 (isdn_linktab[unit]->unit, isdn_linktab[unit]->channel, &bs);
311 sc->sc_ioutb += bs.outbytes;
312 sc->sc_iinb += bs.inbytes;
314 if((sc->sc_iinb != sc->sc_linb) || (sc->sc_ioutb != sc->sc_loutb) || sc->sc_fn)
316 int ri = (sc->sc_iinb - sc->sc_linb)/I4BINGACCTINTVL;
317 int ro = (sc->sc_ioutb - sc->sc_loutb)/I4BINGACCTINTVL;
319 if((sc->sc_iinb == sc->sc_linb) && (sc->sc_ioutb == sc->sc_loutb))
320 sc->sc_fn = 0;
321 else
322 sc->sc_fn = 1;
324 sc->sc_linb = sc->sc_iinb;
325 sc->sc_loutb = sc->sc_ioutb;
327 i4b_l4_accounting(BDRV_ING, unit, ACCT_DURING,
328 sc->sc_ioutb, sc->sc_iinb, ro, ri, sc->sc_ioutb, sc->sc_iinb);
331 callout_reset(&sc->sc_timeout, I4BINGACCTINTVL * hz,
332 (TIMEOUT_FUNC_T)ing_timeout, sc);
334 #endif /* I4BINGACCT */
336 #if 0
337 /*---------------------------------------------------------------------------*
338 * clear the interface's send queues
339 *---------------------------------------------------------------------------*/
340 static void
341 ingclearqueue(struct ifqueue *iq)
343 int x;
344 struct mbuf *m;
346 for(;;)
348 crit_enter();
349 IF_DEQUEUE(iq, m);
350 crit_exit();
352 if(m)
353 m_freem(m);
354 else
355 break;
358 #endif
360 /*===========================================================================*
361 * ISDN INTERFACE ROUTINES
362 *===========================================================================*/
364 /*---------------------------------------------------------------------------*
365 * this routine is called from L4 handler at connect time
366 *---------------------------------------------------------------------------*/
367 static void
368 ing_connect(int unit, void *cdp)
370 struct ing_softc *sc = &ing_softc[unit];
372 sc->sc_cdp = (call_desc_t *)cdp;
374 crit_enter();
376 NDBGL4(L4_DIALST, "ing%d: setting dial state to ST_CONNECTED", unit);
378 sc->sc_dialresp = DSTAT_NONE;
379 sc->sc_lastdialresp = DSTAT_NONE;
381 #if I4BINGACCT
382 sc->sc_iinb = 0;
383 sc->sc_ioutb = 0;
384 sc->sc_inb = 0;
385 sc->sc_outb = 0;
386 sc->sc_linb = 0;
387 sc->sc_loutb = 0;
388 callout_reset(&sc->sc_timeout, I4BINGACCTINTVL * hz,
389 (TIMEOUT_FUNC_T)ing_timeout, sc);
390 #endif
392 sc->sc_state = ST_CONNECTED;
394 crit_exit();
397 /*---------------------------------------------------------------------------*
398 * this routine is called from L4 handler at disconnect time
399 *---------------------------------------------------------------------------*/
400 static void
401 ing_disconnect(int unit, void *cdp)
403 call_desc_t *cd = (call_desc_t *)cdp;
404 struct ing_softc *sc = &ing_softc[unit];
406 /* new stuff to check that the active channel is being closed */
408 if (cd != sc->sc_cdp)
410 NDBGL4(L4_INGDBG, "ing%d: channel %d not active",
411 cd->driver_unit, cd->channelid);
412 return;
415 #if I4BINGACCT
416 callout_stop(&sc->sc_timeout);
417 #endif
419 i4b_l4_accounting(BDRV_ING, cd->driver_unit, ACCT_FINAL,
420 sc->sc_ioutb, sc->sc_iinb, 0, 0, sc->sc_outb, sc->sc_inb);
422 sc->sc_cdp = (call_desc_t *)0;
424 NDBGL4(L4_DIALST, "setting dial state to ST_IDLE");
426 sc->sc_dialresp = DSTAT_NONE;
427 sc->sc_lastdialresp = DSTAT_NONE;
429 sc->sc_state = ST_IDLE;
432 /*---------------------------------------------------------------------------*
433 * this routine is used to give a feedback from userland daemon
434 * in case of dial problems
435 *---------------------------------------------------------------------------*/
436 static void
437 ing_dialresponse(int unit, int status, cause_t cause)
439 struct ing_softc *sc = &ing_softc[unit];
440 sc->sc_dialresp = status;
442 NDBGL4(L4_INGDBG, "ing%d: last=%d, this=%d",
443 unit, sc->sc_lastdialresp, sc->sc_dialresp);
445 if(status != DSTAT_NONE)
447 NDBGL4(L4_INGDBG, "ing%d: clearing queues", unit);
448 /* ingclearqueues(sc); */
452 /*---------------------------------------------------------------------------*
453 * interface soft up/down
454 *---------------------------------------------------------------------------*/
455 static void
456 ing_updown(int unit, int updown)
458 struct ing_softc *sc = &ing_softc[unit];
459 sc->sc_updown = updown;
462 /*---------------------------------------------------------------------------*
463 * this routine is called from the HSCX interrupt handler
464 * when a new frame (mbuf) has been received and was put on
465 * the rx queue. It is assumed that this routines runs at
466 * pri level splimp() ! Keep it short !
467 *---------------------------------------------------------------------------*/
468 static void
469 ing_rx_data_rdy(int unit)
471 struct ing_softc *sc = &ing_softc[unit];
472 struct mbuf *m;
474 if((m = *isdn_linktab[unit]->rx_mbuf) == NULL)
475 return;
477 #if I4BINGACCT
478 sc->sc_inb += m->m_pkthdr.len;
479 #endif
481 m->m_pkthdr.rcvif = NULL;
483 sc->sc_inpkt++;
485 ng_queue_data(sc->hook, m, NULL);
488 /*---------------------------------------------------------------------------*
489 * this routine is called from the HSCX interrupt handler
490 * when the last frame has been sent out and there is no
491 * further frame (mbuf) in the tx queue.
492 *---------------------------------------------------------------------------*/
493 static void
494 ing_tx_queue_empty(int unit)
496 struct ing_softc *sc = &ing_softc[unit];
497 struct mbuf *m;
498 int x = 0;
500 if(sc->sc_state != ST_CONNECTED)
501 return;
503 for(;;)
505 IF_DEQUEUE(&sc->xmitq_hipri, m);
507 if(m == NULL)
509 IF_DEQUEUE(&sc->xmitq, m);
510 if(m == NULL)
511 break;
514 #if I4BINGACCT
515 sc->sc_outb += m->m_pkthdr.len;
516 #endif
518 x = 1;
520 if(IF_QFULL(isdn_linktab[unit]->tx_queue))
522 NDBGL4(L4_INGDBG, "ing%d: tx queue full!", unit);
523 m_freem(m);
525 else
527 IF_ENQUEUE(isdn_linktab[unit]->tx_queue, m);
531 if(x)
532 (*isdn_linktab[unit]->bch_tx_start)(isdn_linktab[unit]->unit, isdn_linktab[unit]->channel);
535 /*---------------------------------------------------------------------------*
536 * this routine is called from the HSCX interrupt handler
537 * each time a packet is received or transmitted. It should
538 * be used to implement an activity timeout mechanism.
539 *---------------------------------------------------------------------------*/
540 static void
541 ing_activity(int unit, int rxtx)
543 ing_softc[unit].sc_cdp->last_active_time = SECOND;
546 /*---------------------------------------------------------------------------*
547 * return this drivers linktab address
548 *---------------------------------------------------------------------------*/
549 drvr_link_t *
550 ing_ret_linktab(int unit)
552 return(&ing_drvr_linktab[unit]);
555 /*---------------------------------------------------------------------------*
556 * setup the isdn_linktab for this driver
557 *---------------------------------------------------------------------------*/
558 void
559 ing_set_linktab(int unit, isdn_link_t *ilt)
561 isdn_linktab[unit] = ilt;
564 /*---------------------------------------------------------------------------*
565 * initialize this drivers linktab
566 *---------------------------------------------------------------------------*/
567 static void
568 ing_init_linktab(int unit)
570 ing_drvr_linktab[unit].unit = unit;
571 ing_drvr_linktab[unit].bch_rx_data_ready = ing_rx_data_rdy;
572 ing_drvr_linktab[unit].bch_tx_queue_empty = ing_tx_queue_empty;
573 ing_drvr_linktab[unit].bch_activity = ing_activity;
574 ing_drvr_linktab[unit].line_connected = ing_connect;
575 ing_drvr_linktab[unit].line_disconnected = ing_disconnect;
576 ing_drvr_linktab[unit].dial_response = ing_dialresponse;
577 ing_drvr_linktab[unit].updown_ind = ing_updown;
580 /*===========================================================================*
581 * NETGRAPH INTERFACE ROUTINES
582 *===========================================================================*/
584 /*---------------------------------------------------------------------------*
585 * It is not possible or allowable to create a node of this type.
586 * If the hardware exists, it will already have created it.
587 *---------------------------------------------------------------------------*/
588 static int
589 ng_ing_constructor(node_p *nodep)
591 return(EINVAL);
594 /*---------------------------------------------------------------------------*
595 * Give our ok for a hook to be added...
596 * Add the hook's private info to the hook structure.
597 *---------------------------------------------------------------------------*/
598 static int
599 ng_ing_newhook(node_p node, hook_p hook, const char *name)
601 struct ing_softc *sc = node->private;
604 * check if it's our friend the debug hook
606 if(strcmp(name, NG_ING_HOOK_DEBUG) == 0)
608 hook->private = NULL; /* paranoid */
609 sc->debughook = hook;
610 return (0);
613 * Check for raw mode hook.
615 if(strcmp(name, NG_ING_HOOK_RAW) == 0)
617 hook->private = sc;
618 sc->hook = hook;
619 return (0);
622 return (EINVAL);
625 /*---------------------------------------------------------------------------*
626 * Get a netgraph control message.
627 * Check it is one we understand. If needed, send a response.
628 * We could save the address for an async action later, but don't here.
629 * Always free the message.
630 * The response should be in a malloc'd region that the caller can 'free'.
631 * A response is not required.
632 *---------------------------------------------------------------------------*/
633 static int
634 ng_ing_rcvmsg(node_p node, struct ng_mesg *msg, const char *retaddr,
635 struct ng_mesg **rptr)
637 struct ing_softc *sc = node->private;
639 struct ng_mesg *resp = NULL;
640 int error = 0;
642 if(msg->header.typecookie == NGM_GENERIC_COOKIE)
644 switch(msg->header.cmd)
646 case NGM_TEXT_STATUS:
648 char *arg;
649 char *p;
650 int pos = 0;
652 NG_MKRESPONSE(resp, msg,
653 sizeof(struct ng_mesg) + NG_TEXTRESPONSE,
654 M_INTWAIT | M_NULLOK);
656 if (resp == NULL)
658 error = ENOMEM;
659 break;
661 arg = (char *) resp->data;
663 switch(sc->sc_state)
665 case ST_IDLE:
666 p = "idle";
667 break;
668 case ST_DIALING:
669 p = "dialing";
670 break;
671 case ST_CONNECTED:
672 p = "connected";
673 break;
674 default:
675 p = "???";
676 break;
679 pos = ksprintf(arg, "state = %s (%d)\n", p, sc->sc_state);
680 #if I4BINGACCT
681 pos += ksprintf(arg + pos, "%d bytes in, %d bytes out\n", sc->sc_inb, sc->sc_outb);
682 #endif
683 pos += ksprintf(arg + pos, "%d pkts in, %d pkts out\n", sc->sc_inpkt, sc->sc_outpkt);
685 resp->header.arglen = pos + 1;
686 break;
689 default:
690 error = EINVAL;
691 break;
694 else if(msg->header.typecookie == NGM_ING_COOKIE)
696 switch (msg->header.cmd)
698 case NGM_ING_GET_STATUS:
700 struct ngingstat *stats;
702 NG_MKRESPONSE(resp, msg, sizeof(*stats),
703 M_INTWAIT | M_NULLOK);
705 if (!resp)
707 error = ENOMEM;
708 break;
711 stats = (struct ngingstat *) resp->data;
712 stats->packets_in = sc->packets_in;
713 stats->packets_out = sc->packets_out;
714 break;
717 case NGM_ING_SET_FLAG:
718 if (msg->header.arglen != sizeof(u_int32_t))
720 error = EINVAL;
721 break;
723 sc->flags = *((u_int32_t *) msg->data);
724 break;
726 default:
727 error = EINVAL; /* unknown command */
728 break;
731 else
733 error = EINVAL; /* unknown cookie type */
736 /* Take care of synchronous response, if any */
738 if (rptr)
739 *rptr = resp;
740 else if (resp)
741 FREE(resp, M_NETGRAPH);
743 /* Free the message and return */
745 FREE(msg, M_NETGRAPH);
746 return(error);
749 /*---------------------------------------------------------------------------*
750 * get data from another node and transmit it out on a B-channel
751 *---------------------------------------------------------------------------*/
752 static int
753 ng_ing_rcvdata(hook_p hook, struct mbuf *m, meta_p meta)
755 struct ing_softc *sc = hook->node->private;
756 struct ifqueue *xmitq_p;
758 if(hook->private == NULL)
760 NG_FREE_DATA(m, meta);
761 return(ENETDOWN);
764 if(sc->sc_state == ST_IDLE || sc->sc_state == ST_DIALING)
766 i4b_l4_dialout(BDRV_ING, sc->sc_unit);
767 sc->sc_state = ST_DIALING;
770 sc->sc_outpkt++;
773 * Now queue the data for when it can be sent
776 if (meta && meta->priority > 0)
778 xmitq_p = (&sc->xmitq_hipri);
780 else
782 xmitq_p = (&sc->xmitq);
785 crit_enter();
787 if (IF_QFULL(xmitq_p))
789 IF_DROP(xmitq_p);
790 crit_exit();
791 NG_FREE_DATA(m, meta);
792 return(ENOBUFS);
795 IF_ENQUEUE(xmitq_p, m);
797 ing_tx_queue_empty(sc->sc_unit);
799 crit_exit();
800 return (0);
803 /*---------------------------------------------------------------------------*
804 * Do local shutdown processing..
805 * If we are a persistant device, we might refuse to go away, and
806 * we'd only remove our links and reset ourself.
807 *---------------------------------------------------------------------------*/
808 static int
809 ng_ing_rmnode(node_p node)
811 struct ing_softc *sc = node->private;
813 node->flags |= NG_INVALID;
814 ng_cutlinks(node);
816 sc->packets_in = 0; /* reset stats */
817 sc->packets_out = 0;
819 node->flags &= ~NG_INVALID; /* reset invalid flag */
821 return (0);
824 /*---------------------------------------------------------------------------*
825 * This is called once we've already connected a new hook to the other node.
826 *---------------------------------------------------------------------------*/
827 static int
828 ng_ing_connect(hook_p hook)
830 return (0);
834 * Dook disconnection
836 * For this type, removal of the last link destroys the node
838 static int
839 ng_ing_disconnect(hook_p hook)
841 struct ing_softc *sc = hook->node->private;
843 if(hook->private == NULL) {
844 sc->debughook = NULL;
846 return (0);
849 /*===========================================================================*/
851 #endif /* NI4BING > 0 */