Merge from vendor branch GROFF:
[dragonfly.git] / sys / dev / usbmisc / urio / urio.c
1 /*
2  * Copyright (c) 2000 Iwasa Kazmi
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
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  *
14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
18  * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  *
26  * This code is based on ugen.c and ulpt.c developed by Lennart Augustsson.
27  * This code includes software developed by the NetBSD Foundation, Inc. and
28  * its contributors.
29  */
30
31 /*
32  * $FreeBSD: src/sys/dev/usb/urio.c,v 1.28 2003/08/25 22:01:06 joe Exp $
33  * $DragonFly: src/sys/dev/usbmisc/urio/urio.c,v 1.11 2005/06/02 20:41:04 dillon Exp $
34  */
35
36 /*
37  * 2000/3/24  added NetBSD/OpenBSD support (from Alex Nemirovsky)
38  * 2000/3/07  use two bulk-pipe handles for read and write (Dirk)
39  * 2000/3/06  change major number(143), and copyright header
40  *            some fix for 4.0 (Dirk)
41  * 2000/3/05  codes for FreeBSD 4.x - CURRENT (Thanks to Dirk-Willem van Gulik)
42  * 2000/3/01  remove retry code from urioioctl()
43  *            change method of bulk transfer (no interrupt)
44  * 2000/2/28  small fixes for new rio_usb.h
45  * 2000/2/24  first version.
46  */
47
48 #include <sys/param.h>
49 #include <sys/systm.h>
50 #include <sys/kernel.h>
51 #include <sys/malloc.h>
52 #if defined(__NetBSD__)
53 #include <sys/device.h>
54 #include <sys/ioctl.h>
55 #elif defined(__FreeBSD__) || defined(__DragonFly__)
56 #include <sys/module.h>
57 #include <sys/bus.h>
58 #include <sys/ioccom.h>
59 #endif
60 #include <sys/fcntl.h>
61 #include <sys/filio.h>
62 #include <sys/conf.h>
63 #include <sys/uio.h>
64 #include <sys/tty.h>
65 #include <sys/file.h>
66 #if defined(__FreeBSD__) && __FreeBSD_version >= 500014
67 #include <sys/selinfo.h>
68 #else
69 #include <sys/select.h>
70 #endif
71 #include <sys/vnode.h>
72 #include <sys/poll.h>
73 #include <sys/sysctl.h>
74 #include <sys/proc.h>
75 #include <sys/thread2.h>
76
77 #include <bus/usb/usb.h>
78 #include <bus/usb/usbdi.h>
79 #include <bus/usb/usbdi_util.h>
80
81 #include <bus/usb/usbdevs.h>
82 #include <bus/usb/rio500_usb.h>
83
84 #ifdef USB_DEBUG
85 #define DPRINTF(x)      if (uriodebug) logprintf x
86 #define DPRINTFN(n,x)   if (uriodebug>(n)) logprintf x
87 int     uriodebug = 0;
88 SYSCTL_NODE(_hw_usb, OID_AUTO, urio, CTLFLAG_RW, 0, "USB urio");
89 SYSCTL_INT(_hw_usb_urio, OID_AUTO, debug, CTLFLAG_RW,
90            &uriodebug, 0, "urio debug level");
91 #else
92 #define DPRINTF(x)
93 #define DPRINTFN(n,x)
94 #endif
95
96 /* difference of usbd interface */
97 #define USBDI 1
98
99 #define RIO_OUT 0
100 #define RIO_IN  1
101 #define RIO_NODIR  2
102
103 #if defined(__NetBSD__)
104 int urioopen(dev_t, int, int, struct proc *);
105 int urioclose(dev_t, int, int, struct proc *p);
106 int urioread(dev_t, struct uio *uio, int);
107 int uriowrite(dev_t, struct uio *uio, int);
108 int urioioctl(dev_t, u_long, caddr_t, int, struct proc *);
109
110 cdev_decl(urio);
111 #define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
112                           ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
113                                                            RIO_NODIR))
114 #elif defined(__FreeBSD__) || defined(__DragonFly__)
115 d_open_t  urioopen;
116 d_close_t urioclose;
117 d_read_t  urioread;
118 d_write_t uriowrite;
119 d_ioctl_t urioioctl;
120
121 #define URIO_CDEV_MAJOR 143
122
123 Static struct cdevsw urio_cdevsw = {
124         /* name */      "urio",         
125         /* cmaj */      URIO_CDEV_MAJOR,
126         /* flags */     0,
127         /* port */      NULL,
128         /* clone */     NULL,
129         urioopen,       urioclose,      urioread,       uriowrite,
130         urioioctl,      nopoll,         nommap,         nostrategy,
131         nodump,         nopsize
132 };
133 #define RIO_UE_GET_DIR(p) ((UE_GET_DIR(p) == UE_DIR_IN) ? RIO_IN :\
134                           ((UE_GET_DIR(p) == UE_DIR_OUT) ? RIO_OUT :\
135                                                            RIO_NODIR))
136 #endif  /*defined(__FreeBSD__)*/
137
138 #define URIO_BBSIZE     1024
139
140 struct urio_softc {
141         USBBASEDEVICE sc_dev;
142         usbd_device_handle sc_udev;
143         usbd_interface_handle sc_iface;
144
145         int sc_opened;
146         usbd_pipe_handle sc_pipeh_in;
147         usbd_pipe_handle sc_pipeh_out;
148         int sc_epaddr[2];
149
150         int sc_refcnt;
151 #if defined(__NetBSD__) || defined(__OpenBSD__)
152         u_char sc_dying;
153 #endif
154 };
155
156 #define URIOUNIT(n) (minor(n))
157
158 #define RIO_RW_TIMEOUT 4000     /* ms */
159
160 USB_DECLARE_DRIVER(urio);
161
162 USB_MATCH(urio)
163 {
164         USB_MATCH_START(urio, uaa);
165         usb_device_descriptor_t *dd;
166
167         DPRINTFN(10,("urio_match\n"));
168         if (!uaa->iface)
169                 return UMATCH_NONE;
170
171         dd = usbd_get_device_descriptor(uaa->device);
172
173         if (dd &&
174             ((UGETW(dd->idVendor) == USB_VENDOR_DIAMOND &&
175             UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND_RIO500USB) ||
176             (UGETW(dd->idVendor) == USB_VENDOR_DIAMOND2 &&
177               (UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO600USB ||
178               UGETW(dd->idProduct) == USB_PRODUCT_DIAMOND2_RIO800USB))))
179                 return UMATCH_VENDOR_PRODUCT;
180         else
181                 return UMATCH_NONE;
182 }
183
184 USB_ATTACH(urio)
185 {
186         USB_ATTACH_START(urio, sc, uaa);
187         char devinfo[1024];
188         usbd_device_handle udev;
189         usbd_interface_handle iface;
190         u_int8_t epcount;
191 #if defined(__NetBSD__) || defined(__OpenBSD__)
192         u_int8_t niface;
193 #endif
194         usbd_status r;
195         char * ermsg = "<none>";
196         int i;
197
198         DPRINTFN(10,("urio_attach: sc=%p\n", sc));
199         usbd_devinfo(uaa->device, 0, devinfo);
200         USB_ATTACH_SETUP;
201         printf("%s: %s\n", USBDEVNAME(sc->sc_dev), devinfo);
202
203         sc->sc_udev = udev = uaa->device;
204
205 #if defined(__FreeBSD__) || defined(__DragonFly__)
206         if ((!uaa->device) || (!uaa->iface)) {
207                 ermsg = "device or iface";
208                 goto nobulk;
209         }
210         sc->sc_iface = iface = uaa->iface;
211 #elif defined(__NetBSD__) || defined(__OpenBSD__)
212         if (!udev) {
213                 ermsg = "device";
214                 goto nobulk;
215         }
216         r = usbd_interface_count(udev, &niface);
217         if (r) {
218                 ermsg = "iface";
219                 goto nobulk;
220         }
221         r = usbd_device2interface_handle(udev, 0, &iface);
222         if (r) {
223                 ermsg = "iface";
224                 goto nobulk;
225         }
226         sc->sc_iface = iface;
227 #endif
228         sc->sc_opened = 0;
229         sc->sc_pipeh_in = 0;
230         sc->sc_pipeh_out = 0;
231         sc->sc_refcnt = 0;
232
233         r = usbd_endpoint_count(iface, &epcount);
234         if (r != USBD_NORMAL_COMPLETION) {
235                 ermsg = "endpoints";
236                 goto nobulk;
237         }
238
239         sc->sc_epaddr[RIO_OUT] = 0xff;
240         sc->sc_epaddr[RIO_IN] = 0x00;
241
242         for (i = 0; i < epcount; i++) {
243                 usb_endpoint_descriptor_t *edesc =
244                         usbd_interface2endpoint_descriptor(iface, i);
245                 int d;
246
247                 if (!edesc) {
248                         ermsg = "interface endpoint";
249                         goto nobulk;
250                 }
251
252                 d = RIO_UE_GET_DIR(edesc->bEndpointAddress);
253                 if (d != RIO_NODIR)
254                         sc->sc_epaddr[d] = edesc->bEndpointAddress;
255         }
256         if ( sc->sc_epaddr[RIO_OUT] == 0xff ||
257              sc->sc_epaddr[RIO_IN] == 0x00) {
258                 ermsg = "Rio I&O";
259                 goto nobulk;
260         }
261
262 #if defined(__FreeBSD__) || defined(__DragonFly__)
263         cdevsw_add(&urio_cdevsw, -1, device_get_unit(self));
264         make_dev(&urio_cdevsw, device_get_unit(self),
265                         UID_ROOT, GID_OPERATOR,
266                         0644, "urio%d", device_get_unit(self));
267 #elif defined(__NetBSD__) || defined(__OpenBSD__)
268         usbd_add_drv_event(USB_EVENT_DRIVER_ATTACH, sc->sc_udev,
269                            USBDEV(sc->sc_dev));
270 #endif
271
272         DPRINTFN(10, ("urio_attach: %p\n", sc->sc_udev));
273
274         USB_ATTACH_SUCCESS_RETURN;
275
276  nobulk:
277         printf("%s: could not find %s\n", USBDEVNAME(sc->sc_dev),ermsg);
278         USB_ATTACH_ERROR_RETURN;
279 }
280
281
282 int
283 urioopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
284 {
285 #if (USBDI >= 1)
286         struct urio_softc * sc;
287 #endif
288         int unit = URIOUNIT(dev);
289         USB_GET_SC_OPEN(urio, unit, sc);
290
291         DPRINTFN(5, ("urioopen: flag=%d, mode=%d, unit=%d\n",
292                      flag, mode, unit));
293
294         if (sc->sc_opened)
295                 return EBUSY;
296
297         if ((flag & (FWRITE|FREAD)) != (FWRITE|FREAD))
298                 return EACCES;
299
300         sc->sc_opened = 1;
301         sc->sc_pipeh_in = 0;
302         sc->sc_pipeh_out = 0;
303         if (usbd_open_pipe(sc->sc_iface,
304                 sc->sc_epaddr[RIO_IN], 0, &sc->sc_pipeh_in)
305                         != USBD_NORMAL_COMPLETION)
306         {
307                         sc->sc_pipeh_in = 0;
308                         return EIO;
309         };
310         if (usbd_open_pipe(sc->sc_iface,
311                 sc->sc_epaddr[RIO_OUT], 0, &sc->sc_pipeh_out)
312                         != USBD_NORMAL_COMPLETION)
313         {
314                         usbd_close_pipe(sc->sc_pipeh_in);
315                         sc->sc_pipeh_in = 0;
316                         sc->sc_pipeh_out = 0;
317                         return EIO;
318         };
319         return 0;
320 }
321
322 int
323 urioclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
324 {
325 #if (USBDI >= 1)
326         struct urio_softc * sc;
327 #endif
328         int unit = URIOUNIT(dev);
329         USB_GET_SC(urio, unit, sc);
330
331         DPRINTFN(5, ("urioclose: flag=%d, mode=%d, unit=%d\n", flag, mode, unit));
332         if (sc->sc_pipeh_in)
333                 usbd_close_pipe(sc->sc_pipeh_in);
334
335         if (sc->sc_pipeh_out)
336                 usbd_close_pipe(sc->sc_pipeh_out);
337
338         sc->sc_pipeh_in = 0;
339         sc->sc_pipeh_out = 0;
340         sc->sc_opened = 0;
341         sc->sc_refcnt = 0;
342         return 0;
343 }
344
345 int
346 urioread(dev_t dev, struct uio *uio, int flag)
347 {
348 #if (USBDI >= 1)
349         struct urio_softc * sc;
350         usbd_xfer_handle reqh;
351 #else
352         usbd_request_handle reqh;
353         usbd_private_handle r_priv;
354         void *r_buff;
355         usbd_status r_status;
356 #endif
357         int unit = URIOUNIT(dev);
358         usbd_status r;
359         char buf[URIO_BBSIZE];
360         u_int32_t n, tn;
361         int error = 0;
362
363         USB_GET_SC(urio, unit, sc);
364
365         DPRINTFN(5, ("urioread: %d\n", unit));
366         if (!sc->sc_opened)
367                 return EIO;
368
369 #if (USBDI >= 1)
370         sc->sc_refcnt++;
371         reqh = usbd_alloc_xfer(sc->sc_udev);
372 #else
373         reqh = usbd_alloc_request();
374 #endif
375         if (reqh == 0)
376                 return ENOMEM;
377         while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
378                 DPRINTFN(1, ("urioread: start transfer %d bytes\n", n));
379                 tn = n;
380 #if (USBDI >= 1)
381                 usbd_setup_xfer(reqh, sc->sc_pipeh_in, 0, buf, tn,
382                                        0, RIO_RW_TIMEOUT, 0);
383 #else
384                 r = usbd_setup_request(reqh, sc->sc_pipeh_in, 0, buf, tn,
385                                        0, RIO_RW_TIMEOUT, 0);
386                 if (r != USBD_NORMAL_COMPLETION) {
387                         error = EIO;
388                         break;
389                 }
390 #endif
391                 r = usbd_sync_transfer(reqh);
392                 if (r != USBD_NORMAL_COMPLETION) {
393                         DPRINTFN(1, ("urioread: error=%d\n", r));
394                         usbd_clear_endpoint_stall(sc->sc_pipeh_in);
395                         tn = 0;
396                         error = EIO;
397                         break;
398                 }
399 #if (USBDI >= 1)
400                 usbd_get_xfer_status(reqh, 0, 0, &tn, 0);
401 #else
402                 usbd_get_request_status(reqh, &r_priv, &r_buff, &tn, &r_status);
403 #endif
404
405                 DPRINTFN(1, ("urioread: got %d bytes\n", tn));
406                 error = uiomove(buf, tn, uio);
407                 if (error || tn < n)
408                         break;
409         }
410 #if (USBDI >= 1)
411         usbd_free_xfer(reqh);
412 #else
413         usbd_free_request(reqh);
414 #endif
415
416         return error;
417 }
418
419 int
420 uriowrite(dev_t dev, struct uio *uio, int flag)
421 {
422 #if (USBDI >= 1)
423         struct urio_softc * sc;
424         usbd_xfer_handle reqh;
425 #else
426         usbd_request_handle reqh;
427 #endif
428         int unit = URIOUNIT(dev);
429         usbd_status r;
430         char buf[URIO_BBSIZE];
431         u_int32_t n;
432         int error = 0;
433
434         USB_GET_SC(urio, unit, sc);
435
436         DPRINTFN(5, ("uriowrite: %d\n", unit));
437         if (!sc->sc_opened)
438                 return EIO;
439
440 #if (USBDI >= 1)
441         sc->sc_refcnt++;
442         reqh = usbd_alloc_xfer(sc->sc_udev);
443 #else
444         reqh = usbd_alloc_request();
445 #endif
446         if (reqh == 0)
447                 return EIO;
448         while ((n = min(URIO_BBSIZE, uio->uio_resid)) != 0) {
449                 error = uiomove(buf, n, uio);
450                 if (error)
451                         break;
452                 DPRINTFN(1, ("uriowrite: transfer %d bytes\n", n));
453 #if (USBDI >= 1)
454                 usbd_setup_xfer(reqh, sc->sc_pipeh_out, 0, buf, n,
455                                        0, RIO_RW_TIMEOUT, 0);
456 #else
457                 r = usbd_setup_request(reqh, sc->sc_pipeh_out, 0, buf, n,
458                                        0, RIO_RW_TIMEOUT, 0);
459                 if (r != USBD_NORMAL_COMPLETION) {
460                         error = EIO;
461                         break;
462                 }
463 #endif
464                 r = usbd_sync_transfer(reqh);
465                 if (r != USBD_NORMAL_COMPLETION) {
466                         DPRINTFN(1, ("uriowrite: error=%d\n", r));
467                         usbd_clear_endpoint_stall(sc->sc_pipeh_out);
468                         error = EIO;
469                         break;
470                 }
471 #if (USBDI >= 1)
472                 usbd_get_xfer_status(reqh, 0, 0, 0, 0);
473 #endif
474         }
475
476 #if (USBDI >= 1)
477         usbd_free_xfer(reqh);
478 #else
479         usbd_free_request(reqh);
480 #endif
481
482         return error;
483 }
484
485
486 int
487 urioioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, usb_proc_ptr p)
488 {
489 #if (USBDI >= 1)
490         struct urio_softc * sc;
491 #endif
492         int unit = URIOUNIT(dev);
493         struct RioCommand *rio_cmd;
494         int requesttype, len;
495         struct iovec iov;
496         struct uio uio;
497         usb_device_request_t req;
498         int req_flags = 0, req_actlen = 0;
499         void *ptr = 0;
500         int error = 0;
501         usbd_status r;
502
503         USB_GET_SC(urio, unit, sc);
504
505         switch (cmd) {
506         case RIO_RECV_COMMAND:
507                 if (!(flag & FWRITE))
508                         return EPERM;
509                 rio_cmd = (struct RioCommand *)addr;
510                 if (rio_cmd == NULL)
511                         return EINVAL;
512                 len = rio_cmd->length;
513
514                 requesttype = rio_cmd->requesttype | UT_READ_VENDOR_DEVICE;
515                 DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
516                         requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
517                 break;
518
519         case RIO_SEND_COMMAND:
520                 if (!(flag & FWRITE))
521                         return EPERM;
522                 rio_cmd = (struct RioCommand *)addr;
523                 if (rio_cmd == NULL)
524                         return EINVAL;
525                 len = rio_cmd->length;
526
527                 requesttype = rio_cmd->requesttype | UT_WRITE_VENDOR_DEVICE;
528                 DPRINTFN(1,("sending command:reqtype=%0x req=%0x value=%0x index=%0x len=%0x\n",
529                         requesttype, rio_cmd->request, rio_cmd->value, rio_cmd->index, len));
530                 break;
531
532         default:
533                 return EINVAL;
534                 break;
535         }
536
537         /* Send rio control message */
538         req.bmRequestType = requesttype;
539         req.bRequest = rio_cmd->request;
540         USETW(req.wValue, rio_cmd->value);
541         USETW(req.wIndex, rio_cmd->index);
542         USETW(req.wLength, len);
543
544         if (len < 0 || len > 32767)
545                 return EINVAL;
546         if (len != 0) {
547                 iov.iov_base = (caddr_t)rio_cmd->buffer;
548                 iov.iov_len = len;
549                 uio.uio_iov = &iov;
550                 uio.uio_iovcnt = 1;
551                 uio.uio_resid = len;
552                 uio.uio_offset = 0;
553                 uio.uio_segflg = UIO_USERSPACE;
554                 uio.uio_rw =
555                         req.bmRequestType & UT_READ ?
556                         UIO_READ : UIO_WRITE;
557                 uio.uio_td = p;
558                 ptr = malloc(len, M_TEMP, M_WAITOK);
559                 if (uio.uio_rw == UIO_WRITE) {
560                         error = uiomove(ptr, len, &uio);
561                         if (error)
562                                 goto ret;
563                 }
564         }
565
566         r = usbd_do_request_flags(sc->sc_udev, &req,
567                                   ptr, req_flags, &req_actlen,
568                                   USBD_DEFAULT_TIMEOUT);
569         if (r == USBD_NORMAL_COMPLETION) {
570                 error = 0;
571                 if (len != 0) {
572                         if (uio.uio_rw == UIO_READ) {
573                                 error = uiomove(ptr, len, &uio);
574                         }
575                 }
576         } else {
577                 error = EIO;
578         }
579
580 ret:
581         if (ptr)
582                 free(ptr, M_TEMP);
583         return error;
584 }
585
586
587 #if defined(__NetBSD__) || defined(__OpenBSD__)
588 int
589 urio_activate(device_ptr_t self, enum devact act)
590 {
591         struct urio_softc *sc = (struct urio_softc *)self;
592
593         switch (act) {
594         case DVACT_ACTIVATE:
595                 return (EOPNOTSUPP);
596                 break;
597
598         case DVACT_DEACTIVATE:
599                 sc->sc_dying = 1;
600                 break;
601         }
602         return (0);
603 }
604
605 USB_DETACH(urio)
606 {
607         USB_DETACH_START(urio, sc);
608         struct urio_endpoint *sce;
609         int i, dir;
610         int s;
611 #if defined(__NetBSD__) || defined(__OpenBSD__)
612         int maj, mn;
613
614         DPRINTF(("urio_detach: sc=%p flags=%d\n", sc, flags));
615 #elif defined(__FreeBSD__) || defined(__DragonFly__)
616         DPRINTF(("urio_detach: sc=%p\n", sc));
617 #endif
618
619         sc->sc_dying = 1;
620         /* Abort all pipes.  Causes processes waiting for transfer to wake. */
621 #if 0
622         for (i = 0; i < USB_MAX_ENDPOINTS; i++) {
623                 for (dir = OUT; dir <= IN; dir++) {
624                         sce = &sc->sc_endpoints[i][dir];
625                         if (sce && sce->pipeh)
626                                 usbd_abort_pipe(sce->pipeh);
627                 }
628         }
629
630         crit_enter();
631         if (--sc->sc_refcnt >= 0) {
632                 /* Wake everyone */
633                 for (i = 0; i < USB_MAX_ENDPOINTS; i++)
634                         wakeup(&sc->sc_endpoints[i][IN]);
635                 /* Wait for processes to go away. */
636                 usb_detach_wait(USBDEV(sc->sc_dev));
637         }
638         crit_exit();
639 #else
640         if (sc->sc_pipeh_in)
641                 usbd_abort_pipe(sc->sc_pipeh_in);
642
643         if (sc->sc_pipeh_out)
644                 usbd_abort_pipe(sc->sc_pipeh_out);
645
646         crit_enter();
647         if (--sc->sc_refcnt >= 0) {
648                 /* Wait for processes to go away. */
649                 usb_detach_wait(USBDEV(sc->sc_dev));
650         }
651         crit_exit();
652 #endif
653
654 #if defined(__NetBSD__) || defined(__OpenBSD__)
655         /* locate the major number */
656         for (maj = 0; maj < nchrdev; maj++)
657                 if (cdevsw[maj].d_open == urioopen)
658                         break;
659
660         /* Nuke the vnodes for any open instances (calls close). */
661         mn = self->dv_unit * USB_MAX_ENDPOINTS;
662         vdevgone(maj, mn, mn + USB_MAX_ENDPOINTS - 1, VCHR);
663 #endif
664
665         usbd_add_drv_event(USB_EVENT_DRIVER_DETACH, sc->sc_udev,
666                            USBDEV(sc->sc_dev));
667
668         return (0);
669 }
670 #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
671
672 #if defined(__FreeBSD__) || defined(__DragonFly__)
673 Static int
674 urio_detach(device_t self)
675 {
676         DPRINTF(("%s: disconnected\n", USBDEVNAME(self)));
677         cdevsw_remove(&urio_cdevsw, -1, device_get_unit(self));
678         /* XXX not implemented yet */
679         device_set_desc(self, NULL);
680         return 0;
681 }
682
683 DRIVER_MODULE(urio, uhub, urio_driver, urio_devclass, usbd_driver_load, 0);
684 #endif