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