2 * Copyright (c) 1996-2000 Whistle Communications, Inc.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of author nor the names of its
14 * contributors may be used to endorse or promote products derived
15 * from this software without specific prior written permission.
17 * THIS SOFTWARE IS PROVIDED BY NICK HIBMA AND CONTRIBUTORS
18 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
19 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
21 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
22 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
23 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
24 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
25 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
26 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 * POSSIBILITY OF SUCH DAMAGE.
31 #include <sys/cdefs.h>
32 __FBSDID("$FreeBSD$");
34 /* Driver for arbitrary double bulk pipe devices.
35 * The driver assumes that there will be the same driver on the other side.
37 * XXX Some more information on what the framing of the IP packets looks like.
39 * To take full advantage of bulk transmission, packets should be chosen
40 * between 1k and 5k in size (1k to make sure the sending side starts
41 * straming, and <5k to avoid overflowing the system with small TDs).
45 /* probe/attach/detach:
46 * Connect the driver to the hardware and netgraph
48 * udbp_setup_out_transfer(sc);
49 * Setup an outbound transfer. Only one transmit can be active at the same
51 * XXX If it is required that the driver is able to queue multiple requests
52 * let me know. That is slightly difficult, due to the fact that we
53 * cannot call usbd_alloc_xfer in int context.
55 * udbp_setup_in_transfer(sc)
56 * Prepare an in transfer that will be waiting for data to come in. It
57 * is submitted and sits there until data is available.
58 * The callback resubmits a new transfer on completion.
60 * The reason we submit a bulk in transfer is that USB does not know about
61 * interrupts. The bulk transfer continuously polls the device for data.
62 * While the device has no data available, the device NAKs the TDs. As soon
63 * as there is data, the transfer happens and the data comes flowing in.
65 * In case you were wondering, interrupt transfers happen exactly that way.
66 * It therefore doesn't make sense to use the interrupt pipe to signal
67 * 'data ready' and then schedule a bulk transfer to fetch it. That would
68 * incur a 2ms delay at least, without reducing bandwidth requirements.
74 #include <sys/param.h>
75 #include <sys/systm.h>
76 #include <sys/kernel.h>
77 #include <sys/malloc.h>
78 #include <sys/module.h>
82 #if __FreeBSD_version >= 500014
83 #include <sys/selinfo.h>
85 #include <sys/select.h>
89 #include <sys/socket.h>
90 #include <sys/ctype.h>
91 #include <sys/errno.h>
92 #include <sys/sysctl.h>
94 #include <machine/bus.h>
96 #include <dev/usb/usb.h>
97 #include <dev/usb/usbdi.h>
98 #include <dev/usb/usbdi_util.h>
99 #include <dev/usb/usbdivar.h>
100 #include <dev/usb/usbhid.h>
105 #include <netgraph/ng_message.h>
106 #include <netgraph/ng_parse.h>
107 #include <dev/usb/udbp.h>
108 #include <netgraph/netgraph.h>
111 #define DPRINTF(x) if (udbpdebug) logprintf x
112 #define DPRINTFN(n,x) if (udbpdebug>(n)) logprintf x
114 SYSCTL_NODE(_hw_usb, OID_AUTO, udbp, CTLFLAG_RW, 0, "USB udbp");
115 SYSCTL_INT(_hw_usb_udbp, OID_AUTO, debug, CTLFLAG_RW,
116 &udbpdebug, 0, "udbp debug level");
119 #define DPRINTFN(n,x)
122 #define MS_TO_TICKS(ms) ((ms) * hz / 1000)
124 #define UDBP_TIMEOUT 2000 /* timeout on outbound transfers, in msecs */
125 #define UDBP_BUFFERSIZE 2048 /* maximum number of bytes in one transfer */
129 device_t sc_dev; /* base device */
130 usbd_interface_handle sc_iface;
132 usbd_pipe_handle sc_bulkin_pipe;
134 usbd_xfer_handle sc_bulkin_xfer;
135 void *sc_bulkin_buffer;
136 int sc_bulkin_bufferlen;
137 int sc_bulkin_datalen;
139 usbd_pipe_handle sc_bulkout_pipe;
141 usbd_xfer_handle sc_bulkout_xfer;
142 void *sc_bulkout_buffer;
143 int sc_bulkout_bufferlen;
144 int sc_bulkout_datalen;
147 # define DISCONNECTED 0x01
148 # define OUT_BUSY 0x02
149 # define NETGRAPH_INITIALISED 0x04
150 node_p node; /* back pointer to node */
151 hook_p hook; /* pointer to the hook */
152 u_int packets_in; /* packets in from downstream */
153 u_int packets_out; /* packets out towards downstream */
154 struct ifqueue xmitq_hipri; /* hi-priority transmit queue */
155 struct ifqueue xmitq; /* low-priority transmit queue */
158 typedef struct udbp_softc *udbp_p;
162 static ng_constructor_t ng_udbp_constructor;
163 static ng_rcvmsg_t ng_udbp_rcvmsg;
164 static ng_shutdown_t ng_udbp_rmnode;
165 static ng_newhook_t ng_udbp_newhook;
166 static ng_connect_t ng_udbp_connect;
167 static ng_rcvdata_t ng_udbp_rcvdata;
168 static ng_disconnect_t ng_udbp_disconnect;
170 /* Parse type for struct ngudbpstat */
171 static const struct ng_parse_struct_field
172 ng_udbp_stat_type_fields[] = NG_UDBP_STATS_TYPE_INFO;
173 static const struct ng_parse_type ng_udbp_stat_type = {
174 &ng_parse_struct_type,
175 &ng_udbp_stat_type_fields
178 /* List of commands and how to convert arguments to/from ASCII */
179 static const struct ng_cmdlist ng_udbp_cmdlist[] = {
191 &ng_parse_int32_type,
197 /* Netgraph node type descriptor */
198 static struct ng_type ng_udbp_typestruct = {
199 .version = NG_ABI_VERSION,
200 .name = NG_UDBP_NODE_TYPE,
201 .constructor = ng_udbp_constructor,
202 .rcvmsg = ng_udbp_rcvmsg,
203 .shutdown = ng_udbp_rmnode,
204 .newhook = ng_udbp_newhook,
205 .connect = ng_udbp_connect,
206 .rcvdata = ng_udbp_rcvdata,
207 .disconnect = ng_udbp_disconnect,
208 .cmdlist = ng_udbp_cmdlist,
211 static int udbp_setup_in_transfer (udbp_p sc);
212 static void udbp_in_transfer_cb (usbd_xfer_handle xfer,
213 usbd_private_handle priv,
216 static int udbp_setup_out_transfer (udbp_p sc);
217 static void udbp_out_transfer_cb (usbd_xfer_handle xfer,
218 usbd_private_handle priv,
221 USB_DECLARE_DRIVER(udbp);
225 USB_MATCH_START(udbp, uaa);
226 usb_interface_descriptor_t *id;
228 return (UMATCH_NONE);
229 id = usbd_get_interface_descriptor(uaa->iface);
231 /* XXX Julian, add the id of the device if you have one to test
232 * things with. run 'usbdevs -v' and note the 3 ID's that appear.
233 * The Vendor Id and Product Id are in hex and the Revision Id is in
234 * bcd. But as usual if the revision is 0x101 then you should compare
235 * the revision id in the device descriptor with 0x101
236 * Or go search the file usbdevs.h. Maybe the device is already in
239 if ((uaa->vendor == USB_VENDOR_NETCHIP &&
240 uaa->product == USB_PRODUCT_NETCHIP_TURBOCONNECT))
241 return(UMATCH_VENDOR_PRODUCT);
243 if ((uaa->vendor == USB_VENDOR_PROLIFIC &&
244 (uaa->product == USB_PRODUCT_PROLIFIC_PL2301 ||
245 uaa->product == USB_PRODUCT_PROLIFIC_PL2302)))
246 return(UMATCH_VENDOR_PRODUCT);
248 if ((uaa->vendor == USB_VENDOR_ANCHOR &&
249 uaa->product == USB_PRODUCT_ANCHOR_EZLINK))
250 return(UMATCH_VENDOR_PRODUCT);
252 return (UMATCH_NONE);
257 USB_ATTACH_START(udbp, sc, uaa);
258 usbd_interface_handle iface = uaa->iface;
259 usb_interface_descriptor_t *id;
260 usb_endpoint_descriptor_t *ed, *ed_bulkin = NULL, *ed_bulkout = NULL;
264 static int ngudbp_done_init=0;
266 sc->flags |= DISCONNECTED;
267 /* fetch the interface handle for the first interface */
268 (void) usbd_device2interface_handle(uaa->device, 0, &iface);
269 id = usbd_get_interface_descriptor(iface);
270 usbd_devinfo(uaa->device, USBD_SHOW_INTERFACE_CLASS, devinfo);
273 /* Find the two first bulk endpoints */
274 for (i = 0 ; i < id->bNumEndpoints; i++) {
275 ed = usbd_interface2endpoint_descriptor(iface, i);
277 printf("%s: could not read endpoint descriptor\n",
278 device_get_nameunit(sc->sc_dev));
279 USB_ATTACH_ERROR_RETURN;
282 if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_IN
283 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
285 } else if (UE_GET_DIR(ed->bEndpointAddress) == UE_DIR_OUT
286 && (ed->bmAttributes & UE_XFERTYPE) == UE_BULK) {
290 if (ed_bulkin && ed_bulkout) /* found all we need */
294 /* Verify that we goething sensible */
295 if (ed_bulkin == NULL || ed_bulkout == NULL) {
296 printf("%s: bulk-in and/or bulk-out endpoint not found\n",
297 device_get_nameunit(sc->sc_dev));
298 USB_ATTACH_ERROR_RETURN;
301 if (ed_bulkin->wMaxPacketSize[0] != ed_bulkout->wMaxPacketSize[0] ||
302 ed_bulkin->wMaxPacketSize[1] != ed_bulkout->wMaxPacketSize[1]) {
303 printf("%s: bulk-in and bulk-out have different packet sizes %d %d %d %d\n",
304 device_get_nameunit(sc->sc_dev),
305 ed_bulkin->wMaxPacketSize[0],
306 ed_bulkout->wMaxPacketSize[0],
307 ed_bulkin->wMaxPacketSize[1],
308 ed_bulkout->wMaxPacketSize[1]);
309 USB_ATTACH_ERROR_RETURN;
312 sc->sc_bulkin = ed_bulkin->bEndpointAddress;
313 sc->sc_bulkout = ed_bulkout->bEndpointAddress;
315 DPRINTF(("%s: Bulk-in: 0x%02x, bulk-out 0x%02x, packet size = %d\n",
316 device_get_nameunit(sc->sc_dev), sc->sc_bulkin, sc->sc_bulkout,
317 ed_bulkin->wMaxPacketSize[0]));
319 /* Allocate the in transfer struct */
320 sc->sc_bulkin_xfer = usbd_alloc_xfer(uaa->device);
321 if (!sc->sc_bulkin_xfer) {
324 sc->sc_bulkout_xfer = usbd_alloc_xfer(uaa->device);
325 if (!sc->sc_bulkout_xfer) {
328 sc->sc_bulkin_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
329 if (!sc->sc_bulkin_buffer) {
332 sc->sc_bulkout_buffer = malloc(UDBP_BUFFERSIZE, M_USBDEV, M_WAITOK);
333 if (!sc->sc_bulkout_xfer || !sc->sc_bulkout_buffer) {
336 sc->sc_bulkin_bufferlen = UDBP_BUFFERSIZE;
337 sc->sc_bulkout_bufferlen = UDBP_BUFFERSIZE;
339 /* We have decided on which endpoints to use, now open the pipes */
340 err = usbd_open_pipe(iface, sc->sc_bulkin,
341 USBD_EXCLUSIVE_USE, &sc->sc_bulkin_pipe);
343 printf("%s: cannot open bulk-in pipe (addr %d)\n",
344 device_get_nameunit(sc->sc_dev), sc->sc_bulkin);
347 err = usbd_open_pipe(iface, sc->sc_bulkout,
348 USBD_EXCLUSIVE_USE, &sc->sc_bulkout_pipe);
350 printf("%s: cannot open bulk-out pipe (addr %d)\n",
351 device_get_nameunit(sc->sc_dev), sc->sc_bulkout);
355 if (!ngudbp_done_init){
357 if (ng_newtype(&ng_udbp_typestruct)) {
358 printf("ngudbp install failed\n");
363 if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
365 sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
366 if ((err = ng_name_node(sc->node, nodename))) {
367 NG_NODE_UNREF(sc->node);
371 NG_NODE_SET_PRIVATE(sc->node, sc);
372 sc->xmitq.ifq_maxlen = IFQ_MAXLEN;
373 sc->xmitq_hipri.ifq_maxlen = IFQ_MAXLEN;
374 mtx_init(&sc->xmitq.ifq_mtx, "usb_xmitq", NULL,
376 mtx_init(&sc->xmitq_hipri.ifq_mtx,
377 "usb_xmitq_hipri", NULL, MTX_DEF);
380 sc->flags = NETGRAPH_INITIALISED;
381 /* sc->flags &= ~DISCONNECTED; */ /* XXX */
384 /* the device is now operational */
387 /* schedule the first incoming xfer */
388 err = udbp_setup_in_transfer(sc);
392 USB_ATTACH_SUCCESS_RETURN;
394 #if 0 /* probably done in udbp_detach() */
395 if (sc->sc_bulkout_buffer) {
396 FREE(sc->sc_bulkout_buffer, M_USBDEV);
398 if (sc->sc_bulkin_buffer) {
399 FREE(sc->sc_bulkin_buffer, M_USBDEV);
401 if (sc->sc_bulkout_xfer) {
402 usbd_free_xfer(sc->sc_bulkout_xfer);
404 if (sc->sc_bulkin_xfer) {
405 usbd_free_xfer(sc->sc_bulkin_xfer);
409 USB_ATTACH_ERROR_RETURN;
415 USB_DETACH_START(udbp, sc);
417 sc->flags |= DISCONNECTED;
419 DPRINTF(("%s: disconnected\n", device_get_nameunit(self)));
421 if (sc->sc_bulkin_pipe) {
422 usbd_abort_pipe(sc->sc_bulkin_pipe);
423 usbd_close_pipe(sc->sc_bulkin_pipe);
425 if (sc->sc_bulkout_pipe) {
426 usbd_abort_pipe(sc->sc_bulkout_pipe);
427 usbd_close_pipe(sc->sc_bulkout_pipe);
430 if (sc->flags & NETGRAPH_INITIALISED) {
431 ng_rmnode_self(sc->node);
432 NG_NODE_SET_PRIVATE(sc->node, NULL);
433 NG_NODE_UNREF(sc->node);
434 sc->node = NULL; /* Paranoid */
437 if (sc->sc_bulkin_xfer)
438 usbd_free_xfer(sc->sc_bulkin_xfer);
439 if (sc->sc_bulkout_xfer)
440 usbd_free_xfer(sc->sc_bulkout_xfer);
442 if (sc->sc_bulkin_buffer)
443 free(sc->sc_bulkin_buffer, M_USBDEV);
444 if (sc->sc_bulkout_buffer)
445 free(sc->sc_bulkout_buffer, M_USBDEV);
451 udbp_setup_in_transfer(udbp_p sc)
453 void *priv = sc; /* XXX this should probably be some pointer to
454 * struct describing the transfer (mbuf?)
460 * How should we arrange for 2 extra bytes at the start of the
464 /* Initialise a USB transfer and then schedule it */
466 (void) usbd_setup_xfer( sc->sc_bulkin_xfer,
469 sc->sc_bulkin_buffer,
470 sc->sc_bulkin_bufferlen,
473 udbp_in_transfer_cb);
475 err = usbd_transfer(sc->sc_bulkin_xfer);
476 if (err && err != USBD_IN_PROGRESS) {
477 DPRINTF(("%s: failed to setup in-transfer, %s\n",
478 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
482 return (USBD_NORMAL_COMPLETION);
486 udbp_in_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
489 udbp_p sc = priv; /* XXX see priv above */
495 if (err != USBD_CANCELLED) {
496 DPRINTF(("%s: bulk-out transfer failed: %s\n",
497 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
499 /* USBD_CANCELLED happens at unload of the driver */
503 /* Transfer has failed, packet is not received */
508 s = splimp(); /* block network stuff too */
510 /* get packet from device and send on */
511 m = m_devget(sc->sc_bulkin_buffer, len, 0, NULL, NULL);
512 NG_SEND_DATA_ONLY(err, sc->hook, m);
517 /* schedule the next in transfer */
518 udbp_setup_in_transfer(sc);
523 udbp_setup_out_transfer(udbp_p sc)
525 void *priv = sc; /* XXX this should probably be some pointer to
526 * struct describing the transfer (mbuf?)
536 if (sc->flags & OUT_BUSY)
537 panic("out transfer already in use, we should add queuing");
538 sc->flags |= OUT_BUSY;
540 s1 = splimp(); /* Queueing happens at splnet */
541 IF_DEQUEUE(&sc->xmitq_hipri, m);
543 IF_DEQUEUE(&sc->xmitq, m);
548 sc->flags &= ~OUT_BUSY;
549 return (USBD_NORMAL_COMPLETION);
552 pktlen = m->m_pkthdr.len;
553 if (pktlen > sc->sc_bulkout_bufferlen) {
554 printf("%s: Packet too large, %d > %d\n",
555 device_get_nameunit(sc->sc_dev), pktlen,
556 sc->sc_bulkout_bufferlen);
557 return (USBD_IOERROR);
560 m_copydata(m, 0, pktlen, sc->sc_bulkout_buffer);
563 /* Initialise a USB transfer and then schedule it */
565 (void) usbd_setup_xfer( sc->sc_bulkout_xfer,
568 sc->sc_bulkout_buffer,
572 udbp_out_transfer_cb);
574 err = usbd_transfer(sc->sc_bulkout_xfer);
575 if (err && err != USBD_IN_PROGRESS) {
576 DPRINTF(("%s: failed to setup out-transfer, %s\n",
577 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
581 return (USBD_NORMAL_COMPLETION);
585 udbp_out_transfer_cb(usbd_xfer_handle xfer, usbd_private_handle priv,
588 udbp_p sc = priv; /* XXX see priv above */
592 DPRINTF(("%s: bulk-out transfer failed: %s\n",
593 device_get_nameunit(sc->sc_dev), usbd_errstr(err)));
594 /* Transfer has failed, packet is not transmitted */
595 /* XXX Invalidate packet */
599 /* packet has been transmitted */
601 s = splusb(); /* mark the buffer available */
602 sc->flags &= ~OUT_BUSY;
603 udbp_setup_out_transfer(sc);
607 DRIVER_MODULE(udbp, uhub, udbp_driver, udbp_devclass, usbd_driver_load, 0);
608 MODULE_DEPEND(udbp, netgraph, NG_ABI_VERSION, NG_ABI_VERSION, NG_ABI_VERSION);
611 /***********************************************************************
612 * Start of Netgraph methods
613 **********************************************************************/
616 * If this is a device node so this work is done in the attach()
617 * routine and the constructor will return EINVAL as you should not be able
618 * to create nodes that depend on hardware (unless you can add the hardware :)
621 ng_udbp_constructor(node_p node)
627 * Give our ok for a hook to be added...
628 * If we are not running this might kick a device into life.
629 * Possibly decode information out of the hook name.
630 * Add the hook's private info to the hook structure.
631 * (if we had some). In this example, we assume that there is a
632 * an array of structs, called 'channel' in the private info,
633 * one for each active channel. The private
634 * pointer of each hook points to the appropriate UDBP_hookinfo struct
635 * so that the source of an input packet is easily identified.
638 ng_udbp_newhook(node_p node, hook_p hook, const char *name)
640 const udbp_p sc = NG_NODE_PRIVATE(node);
643 /* Possibly start up the device if it's not already going */
644 if ((sc->flags & SCF_RUNNING) == 0) {
645 ng_udbp_start_hardware(sc);
649 if (strcmp(name, NG_UDBP_HOOK_NAME) == 0) {
651 NG_HOOK_SET_PRIVATE(hook, NULL);
653 return (EINVAL); /* not a hook we know about */
659 * Get a netgraph control message.
660 * Check it is one we understand. If needed, send a response.
661 * We could save the address for an async action later, but don't here.
662 * Always free the message.
663 * The response should be in a malloc'd region that the caller can 'free'.
664 * A response is not required.
665 * Theoretically you could respond defferently to old message types if
666 * the cookie in the header didn't match what we consider to be current
667 * (so that old userland programs could continue to work).
670 ng_udbp_rcvmsg(node_p node, item_p item, hook_p lasthook)
672 const udbp_p sc = NG_NODE_PRIVATE(node);
673 struct ng_mesg *resp = NULL;
677 NGI_GET_MSG(item, msg);
678 /* Deal with message according to cookie and command */
679 switch (msg->header.typecookie) {
680 case NGM_UDBP_COOKIE:
681 switch (msg->header.cmd) {
682 case NGM_UDBP_GET_STATUS:
684 struct ngudbpstat *stats;
686 NG_MKRESPONSE(resp, msg, sizeof(*stats), M_NOWAIT);
691 stats = (struct ngudbpstat *) resp->data;
692 stats->packets_in = sc->packets_in;
693 stats->packets_out = sc->packets_out;
696 case NGM_UDBP_SET_FLAG:
697 if (msg->header.arglen != sizeof(u_int32_t)) {
701 sc->flags = *((u_int32_t *) msg->data);
704 error = EINVAL; /* unknown command */
709 error = EINVAL; /* unknown cookie type */
713 /* Take care of synchronous response, if any */
714 NG_RESPOND_MSG(error, node, item, resp);
720 * Accept data from the hook and queue it for output.
723 ng_udbp_rcvdata(hook_p hook, item_p item)
725 const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
727 struct ifqueue *xmitq_p;
730 struct ng_tag_prio *ptag;
736 * Now queue the data for when it can be sent
738 if ((ptag = (struct ng_tag_prio *)m_tag_locate(m, NGM_GENERIC_COOKIE,
739 NG_TAG_PRIO, NULL)) != NULL && (ptag->priority > NG_PRIO_CUTOFF) )
740 xmitq_p = (&sc->xmitq_hipri);
742 xmitq_p = (&sc->xmitq);
746 if (_IF_QFULL(xmitq_p)) {
753 _IF_ENQUEUE(xmitq_p, m);
755 if (!(sc->flags & OUT_BUSY))
756 udbp_setup_out_transfer(sc);
761 * It was an error case.
762 * check if we need to free the mbuf, and then return the error
769 * Do local shutdown processing..
770 * We are a persistant device, we refuse to go away, and
771 * only remove our links and reset ourself.
774 ng_udbp_rmnode(node_p node)
776 const udbp_p sc = NG_NODE_PRIVATE(node);
779 if (sc->flags & DISCONNECTED) {
781 * WE are really going away.. hardware must have gone.
782 * Assume that the hardware drive part will clear up the
783 * sc, in fact it may already have done so..
784 * In which case we may have just segfaulted..XXX
789 /* stolen from attach routine */
790 /* Drain the queues */
791 IF_DRAIN(&sc->xmitq_hipri);
792 IF_DRAIN(&sc->xmitq);
794 sc->packets_in = 0; /* reset stats */
796 NG_NODE_UNREF(node); /* forget it ever existed */
798 if ((err = ng_make_node_common(&ng_udbp_typestruct, &sc->node)) == 0) {
800 sprintf(nodename, "%s", device_get_nameunit(sc->sc_dev));
801 if ((err = ng_name_node(sc->node, nodename))) {
802 NG_NODE_UNREF(sc->node); /* out damned spot! */
803 sc->flags &= ~NETGRAPH_INITIALISED;
806 NG_NODE_SET_PRIVATE(sc->node, sc);
813 * This is called once we've already connected a new hook to the other node.
814 * It gives us a chance to balk at the last minute.
817 ng_udbp_connect(hook_p hook)
819 /* probably not at splnet, force outward queueing */
820 NG_HOOK_FORCE_QUEUE(NG_HOOK_PEER(hook));
821 /* be really amiable and just say "YUP that's OK by me! " */
828 * For this type, removal of the last link destroys the node
831 ng_udbp_disconnect(hook_p hook)
833 const udbp_p sc = NG_NODE_PRIVATE(NG_HOOK_NODE(hook));
836 if ((NG_NODE_NUMHOOKS(NG_HOOK_NODE(hook)) == 0)
837 && (NG_NODE_IS_VALID(NG_HOOK_NODE(hook))))
838 ng_rmnode_self(NG_HOOK_NODE(hook));