File:  [DragonFly] / src / sys / bus / usb / usb.c
Revision 1.10: download - view: text, annotated - select for diffs
Thu Jan 8 18:12:59 2004 UTC (10 years, 10 months ago) by asmodai
Branches: MAIN
CVS tags: HEAD
Get rid of PZERO.  This was removed about the first of August.
It probably compiled due to the preprocessor defining code out.

    1: /*
    2:  * $NetBSD: usb.c,v 1.68 2002/02/20 20:30:12 christos Exp $
    3:  * $FreeBSD: src/sys/dev/usb/usb.c,v 1.95 2003/11/09 23:54:21 joe Exp $
    4:  * $DragonFly: src/sys/bus/usb/usb.c,v 1.10 2004/01/08 18:12:59 asmodai Exp $
    5:  */
    6: 
    7: /* Also already merged from NetBSD:
    8:  *	$NetBSD: usb.c,v 1.70 2002/05/09 21:54:32 augustss Exp $
    9:  *	$NetBSD: usb.c,v 1.71 2002/06/01 23:51:04 lukem Exp $
   10:  *	$NetBSD: usb.c,v 1.73 2002/09/23 05:51:19 simonb Exp $
   11:  */
   12: 
   13: /*
   14:  * Copyright (c) 1998 The NetBSD Foundation, Inc.
   15:  * All rights reserved.
   16:  *
   17:  * This code is derived from software contributed to The NetBSD Foundation
   18:  * by Lennart Augustsson (lennart@augustsson.net) at
   19:  * Carlstedt Research & Technology.
   20:  *
   21:  * Redistribution and use in source and binary forms, with or without
   22:  * modification, are permitted provided that the following conditions
   23:  * are met:
   24:  * 1. Redistributions of source code must retain the above copyright
   25:  *    notice, this list of conditions and the following disclaimer.
   26:  * 2. Redistributions in binary form must reproduce the above copyright
   27:  *    notice, this list of conditions and the following disclaimer in the
   28:  *    documentation and/or other materials provided with the distribution.
   29:  * 3. All advertising materials mentioning features or use of this software
   30:  *    must display the following acknowledgement:
   31:  *        This product includes software developed by the NetBSD
   32:  *        Foundation, Inc. and its contributors.
   33:  * 4. Neither the name of The NetBSD Foundation nor the names of its
   34:  *    contributors may be used to endorse or promote products derived
   35:  *    from this software without specific prior written permission.
   36:  *
   37:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   38:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   39:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   40:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   41:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   42:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   43:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   44:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   45:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   46:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   47:  * POSSIBILITY OF SUCH DAMAGE.
   48:  */
   49: 
   50: /*
   51:  * USB specifications and other documentation can be found at
   52:  * http://www.usb.org/developers/data/ and
   53:  * http://www.usb.org/developers/index.html .
   54:  */
   55: 
   56: #include <sys/param.h>
   57: #include <sys/systm.h>
   58: #include <sys/kernel.h>
   59: #include <sys/lock.h>
   60: #include <sys/malloc.h>
   61: #if __FreeBSD_version >= 500000
   62: #include <sys/mutex.h>
   63: #endif
   64: #if defined(__NetBSD__) || defined(__OpenBSD__)
   65: #include <sys/device.h>
   66: #elif defined(__FreeBSD__)
   67: #include <sys/unistd.h>
   68: #include <sys/module.h>
   69: #include <sys/bus.h>
   70: #include <sys/filio.h>
   71: #include <sys/uio.h>
   72: #endif
   73: #include <sys/kthread.h>
   74: #include <sys/proc.h>
   75: #include <sys/conf.h>
   76: #include <sys/poll.h>
   77: #if __FreeBSD_version >= 500014
   78: #include <sys/selinfo.h>
   79: #else
   80: #include <sys/select.h>
   81: #endif
   82: #include <sys/vnode.h>
   83: #include <sys/signalvar.h>
   84: #include <sys/sysctl.h>
   85: 
   86: #include "usb.h"
   87: #include "usbdi.h"
   88: #include "usbdi_util.h"
   89: 
   90: #define USBUNIT(d)	(minor(d))	/* usb_discover device nodes, kthread */
   91: #define USB_DEV_MINOR	255		/* event queue device */
   92: 
   93: #if defined(__FreeBSD__)
   94: MALLOC_DEFINE(M_USB, "USB", "USB");
   95: MALLOC_DEFINE(M_USBDEV, "USBdev", "USB device");
   96: MALLOC_DEFINE(M_USBHC, "USBHC", "USB host controller");
   97: 
   98: #include "usb_if.h"
   99: #endif /* defined(__FreeBSD__) */
  100: 
  101: #include <machine/bus.h>
  102: 
  103: #include "usbdivar.h"
  104: #include "usb_quirks.h"
  105: 
  106: /* Define this unconditionally in case a kernel module is loaded that
  107:  * has been compiled with debugging options.
  108:  */
  109: SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
  110: 
  111: #ifdef USB_DEBUG
  112: #define DPRINTF(x)	if (usbdebug) logprintf x
  113: #define DPRINTFN(n,x)	if (usbdebug>(n)) logprintf x
  114: int	usbdebug = 0;
  115: SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
  116: 	   &usbdebug, 0, "usb debug level");
  117: /*
  118:  * 0  - do usual exploration
  119:  * 1  - do not use timeout exploration
  120:  * >1 - do no exploration
  121:  */
  122: int	usb_noexplore = 0;
  123: #else
  124: #define DPRINTF(x)
  125: #define DPRINTFN(n,x)
  126: #endif
  127: 
  128: struct usb_softc {
  129: 	USBBASEDEVICE	sc_dev;		/* base device */
  130: 	usbd_bus_handle sc_bus;		/* USB controller */
  131: 	struct usbd_port sc_port;	/* dummy port for root hub */
  132: 
  133: 	struct thread	*sc_event_thread;
  134: 
  135: 	char		sc_dying;
  136: };
  137: 
  138: TAILQ_HEAD(, usb_task) usb_all_tasks;
  139: 
  140: #if defined(__NetBSD__) || defined(__OpenBSD__)
  141: cdev_decl(usb);
  142: #elif defined(__FreeBSD__)
  143: d_open_t  usbopen;
  144: d_close_t usbclose;
  145: d_read_t usbread;
  146: d_ioctl_t usbioctl;
  147: int usbpoll(dev_t, int, usb_proc_ptr);
  148: 
  149: struct cdevsw usb_cdevsw = {
  150: 	/* name */      "usb",
  151: 	/* maj */       USB_CDEV_MAJOR,
  152: 	/* flags */     0,
  153: 	/* port */	NULL,
  154: 	/* autoq */	0,
  155: 
  156: 	/* open */      usbopen,
  157: 	/* close */     usbclose,
  158: 	/* read */      usbread,
  159: 	/* write */     nowrite,
  160: 	/* ioctl */     usbioctl,
  161: 	/* poll */      usbpoll,
  162: 	/* mmap */      nommap,
  163: 	/* strategy */  nostrategy,
  164: 	/* dump */      nodump,
  165: 	/* psize */     nopsize
  166: };
  167: #endif
  168: 
  169: Static void	usb_discover(void *);
  170: Static void	usb_create_event_thread(void *);
  171: Static void	usb_event_thread(void *);
  172: Static void	usb_task_thread(void *);
  173: Static usb_proc_ptr	usb_task_thread_proc = NULL;
  174: 
  175: #define USB_MAX_EVENTS 100
  176: struct usb_event_q {
  177: 	struct usb_event ue;
  178: 	TAILQ_ENTRY(usb_event_q) next;
  179: };
  180: Static TAILQ_HEAD(, usb_event_q) usb_events =
  181: 	TAILQ_HEAD_INITIALIZER(usb_events);
  182: Static int usb_nevents = 0;
  183: Static struct selinfo usb_selevent;
  184: Static struct proc *usb_async_proc;  /* process that wants USB SIGIO */
  185: Static int usb_dev_open = 0;
  186: Static void usb_add_event(int, struct usb_event *);
  187: 
  188: Static int usb_get_next_event(struct usb_event *);
  189: 
  190: #if defined(__NetBSD__) || defined(__OpenBSD__)
  191: /* Flag to see if we are in the cold boot process. */
  192: extern int cold;
  193: #endif
  194: 
  195: Static const char *usbrev_str[] = USBREV_STR;
  196: 
  197: USB_DECLARE_DRIVER_INIT(usb,
  198: 			DEVMETHOD(device_suspend, bus_generic_suspend),
  199: 			DEVMETHOD(device_resume, bus_generic_resume),
  200: 			DEVMETHOD(device_shutdown, bus_generic_shutdown)
  201: 			);
  202: 
  203: #if defined(__FreeBSD__)
  204: MODULE_VERSION(usb, 1);
  205: #endif
  206: 
  207: USB_MATCH(usb)
  208: {
  209: 	DPRINTF(("usbd_match\n"));
  210: 	return (UMATCH_GENERIC);
  211: }
  212: 
  213: USB_ATTACH(usb)
  214: {
  215: #if defined(__NetBSD__) || defined(__OpenBSD__)
  216: 	struct usb_softc *sc = (struct usb_softc *)self;
  217: #elif defined(__FreeBSD__)
  218: 	struct usb_softc *sc = device_get_softc(self);
  219: 	void *aux = device_get_ivars(self);
  220: 	static int global_init_done = 0;
  221: #endif
  222: 	usbd_device_handle dev;
  223: 	usbd_status err;
  224: 	int usbrev;
  225: 	int speed;
  226: 	struct usb_event ue;
  227: 
  228: 	sc->sc_dev = self;
  229: 
  230: 	DPRINTF(("usbd_attach\n"));
  231: 
  232: 	usbd_init();
  233: 	sc->sc_bus = aux;
  234: 	sc->sc_bus->usbctl = sc;
  235: 	sc->sc_port.power = USB_MAX_POWER;
  236: 
  237: #if defined(__FreeBSD__)
  238: 	printf("%s", USBDEVNAME(sc->sc_dev));
  239: #endif
  240: 	usbrev = sc->sc_bus->usbrev;
  241: 	printf(": USB revision %s", usbrev_str[usbrev]);
  242: 	switch (usbrev) {
  243: 	case USBREV_1_0:
  244: 	case USBREV_1_1:
  245: 		speed = USB_SPEED_FULL;
  246: 		break;
  247: 	case USBREV_2_0:
  248: 		speed = USB_SPEED_HIGH;
  249: 		break;
  250: 	default:
  251: 		printf(", not supported\n");
  252: 		sc->sc_dying = 1;
  253: 		USB_ATTACH_ERROR_RETURN;
  254: 	}
  255: 	printf("\n");
  256: 
  257: 	/* Make sure not to use tsleep() if we are cold booting. */
  258: 	if (cold)
  259: 		sc->sc_bus->use_polling++;
  260: 
  261: 	ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
  262: 	usb_add_event(USB_EVENT_CTRLR_ATTACH, &ue);
  263: 
  264: #ifdef USB_USE_SOFTINTR
  265: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  266: 	/* XXX we should have our own level */
  267: 	sc->sc_bus->soft = softintr_establish(IPL_SOFTNET,
  268: 	    sc->sc_bus->methods->soft_intr, sc->sc_bus);
  269: 	if (sc->sc_bus->soft == NULL) {
  270: 		printf("%s: can't register softintr\n", USBDEVNAME(sc->sc_dev));
  271: 		sc->sc_dying = 1;
  272: 		USB_ATTACH_ERROR_RETURN;
  273: 	}
  274: #else
  275: 	usb_callout_init(sc->sc_bus->softi);
  276: #endif
  277: #endif
  278: 
  279: 	err = usbd_new_device(USBDEV(sc->sc_dev), sc->sc_bus, 0, speed, 0,
  280: 		  &sc->sc_port);
  281: 	if (!err) {
  282: 		dev = sc->sc_port.device;
  283: 		if (dev->hub == NULL) {
  284: 			sc->sc_dying = 1;
  285: 			printf("%s: root device is not a hub\n",
  286: 			       USBDEVNAME(sc->sc_dev));
  287: 			USB_ATTACH_ERROR_RETURN;
  288: 		}
  289: 		sc->sc_bus->root_hub = dev;
  290: #if 1
  291: 		/*
  292: 		 * Turning this code off will delay attachment of USB devices
  293: 		 * until the USB event thread is running, which means that
  294: 		 * the keyboard will not work until after cold boot.
  295: 		 */
  296: #if defined(__FreeBSD__)
  297: 		if (cold)
  298: #else
  299: 		if (cold && (sc->sc_dev.dv_cfdata->cf_flags & 1))
  300: #endif
  301: 			dev->hub->explore(sc->sc_bus->root_hub);
  302: #endif
  303: 	} else {
  304: 		printf("%s: root hub problem, error=%d\n",
  305: 		       USBDEVNAME(sc->sc_dev), err);
  306: 		sc->sc_dying = 1;
  307: 	}
  308: 	if (cold)
  309: 		sc->sc_bus->use_polling--;
  310: 
  311: 	config_pending_incr();
  312: #if defined(__NetBSD__) || defined(__OpenBSD__)
  313: 	usb_kthread_create(usb_create_event_thread, sc);
  314: #endif
  315: 
  316: #if defined(__FreeBSD__)
  317: 	usb_create_event_thread(sc);
  318: 	/* The per controller devices (used for usb_discover) */
  319: 	/* XXX This is redundant now, but old usbd's will want it */
  320: 	make_dev(&usb_cdevsw, device_get_unit(self), UID_ROOT, GID_OPERATOR,
  321: 		0660, "usb%d", device_get_unit(self));
  322: 	if (!global_init_done) {
  323: 		/* The device spitting out events */
  324: 		make_dev(&usb_cdevsw, USB_DEV_MINOR, UID_ROOT, GID_OPERATOR,
  325: 			0660, "usb");
  326: 		global_init_done = 1;
  327: 	}
  328: #endif
  329: 
  330: 	USB_ATTACH_SUCCESS_RETURN;
  331: }
  332: 
  333: void
  334: usb_create_event_thread(void *arg)
  335: {
  336: 	struct usb_softc *sc = arg;
  337: 	static int created = 0;
  338: 
  339: 	if (usb_kthread_create1(usb_event_thread, sc, &sc->sc_event_thread,
  340: 			   "%s", USBDEVNAME(sc->sc_dev))) {
  341: 		printf("%s: unable to create event thread for\n",
  342: 		       USBDEVNAME(sc->sc_dev));
  343: 		panic("usb_create_event_thread");
  344: 	}
  345: 	if (!created) {
  346: 		created = 1;
  347: 		TAILQ_INIT(&usb_all_tasks);
  348: 		if (usb_kthread_create2(usb_task_thread, NULL,
  349: 					&usb_task_thread_proc, "usbtask")) {
  350: 			printf("unable to create task thread\n");
  351: 			panic("usb_create_event_thread task");
  352: 		}
  353: 	}
  354: }
  355: 
  356: /*
  357:  * Add a task to be performed by the task thread.  This function can be
  358:  * called from any context and the task will be executed in a process
  359:  * context ASAP.
  360:  */
  361: void
  362: usb_add_task(usbd_device_handle dev, struct usb_task *task)
  363: {
  364: 	int s;
  365: 
  366: 	s = splusb();
  367: 	if (!task->onqueue) {
  368: 		DPRINTFN(2,("usb_add_task: task=%p\n", task));
  369: 		TAILQ_INSERT_TAIL(&usb_all_tasks, task, next);
  370: 		task->onqueue = 1;
  371: 	} else {
  372: 		DPRINTFN(3,("usb_add_task: task=%p on q\n", task));
  373: 	}
  374: 	wakeup(&usb_all_tasks);
  375: 	splx(s);
  376: }
  377: 
  378: void
  379: usb_rem_task(usbd_device_handle dev, struct usb_task *task)
  380: {
  381: 	int s;
  382: 
  383: 	s = splusb();
  384: 	if (task->onqueue) {
  385: 		TAILQ_REMOVE(&usb_all_tasks, task, next);
  386: 		task->onqueue = 0;
  387: 	}
  388: 	splx(s);
  389: }
  390: 
  391: void
  392: usb_event_thread(void *arg)
  393: {
  394: 	struct usb_softc *sc = arg;
  395: 
  396: 	DPRINTF(("usb_event_thread: start\n"));
  397: 
  398: 	/*
  399: 	 * In case this controller is a companion controller to an
  400: 	 * EHCI controller we need to wait until the EHCI controller
  401: 	 * has grabbed the port.
  402: 	 * XXX It would be nicer to do this with a tsleep(), but I don't
  403: 	 * know how to synchronize the creation of the threads so it
  404: 	 * will work.
  405: 	 */
  406: 	usb_delay_ms(sc->sc_bus, 500);
  407: 
  408: 	/* Make sure first discover does something. */
  409: 	sc->sc_bus->needs_explore = 1;
  410: 	usb_discover(sc);
  411: 	config_pending_decr();
  412: 
  413: 	while (!sc->sc_dying) {
  414: #ifdef USB_DEBUG
  415: 		if (usb_noexplore < 2)
  416: #endif
  417: 		usb_discover(sc);
  418: #ifdef USB_DEBUG
  419: 		(void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
  420: 			usb_noexplore ? 0 : hz * 60);
  421: #else
  422: 		(void)tsleep(&sc->sc_bus->needs_explore, 0, "usbevt",
  423: 			hz * 60);
  424: #endif
  425: 		DPRINTFN(2,("usb_event_thread: woke up\n"));
  426: 	}
  427: 	sc->sc_event_thread = NULL;
  428: 
  429: 	/* In case parent is waiting for us to exit. */
  430: 	wakeup(sc);
  431: 
  432: 	DPRINTF(("usb_event_thread: exit\n"));
  433: 	kthread_exit();
  434: }
  435: 
  436: void
  437: usb_task_thread(void *arg)
  438: {
  439: 	struct usb_task *task;
  440: 	int s;
  441: 
  442: #if defined(__FreeBSD__) && __FreeBSD_version >= 500000
  443: 	mtx_lock(&Giant);
  444: #endif
  445: 
  446: 	DPRINTF(("usb_task_thread: start\n"));
  447: 
  448: 	s = splusb();
  449: 	for (;;) {
  450: 		task = TAILQ_FIRST(&usb_all_tasks);
  451: 		if (task == NULL) {
  452: 			tsleep(&usb_all_tasks, 0, "usbtsk", 0);
  453: 			task = TAILQ_FIRST(&usb_all_tasks);
  454: 		}
  455: 		DPRINTFN(2,("usb_task_thread: woke up task=%p\n", task));
  456: 		if (task != NULL) {
  457: 			TAILQ_REMOVE(&usb_all_tasks, task, next);
  458: 			task->onqueue = 0;
  459: 			splx(s);
  460: 			task->fun(task->arg);
  461: 			s = splusb();
  462: 		}
  463: 	}
  464: }
  465: 
  466: #if defined(__NetBSD__) || defined(__OpenBSD__)
  467: int
  468: usbctlprint(void *aux, const char *pnp)
  469: {
  470: 	/* only "usb"es can attach to host controllers */
  471: 	if (pnp)
  472: 		printf("usb at %s", pnp);
  473: 
  474: 	return (UNCONF);
  475: }
  476: #endif /* defined(__NetBSD__) || defined(__OpenBSD__) */
  477: 
  478: int
  479: usbopen(dev_t dev, int flag, int mode, usb_proc_ptr p)
  480: {
  481: 	int unit = USBUNIT(dev);
  482: 	struct usb_softc *sc;
  483: 
  484: 	if (unit == USB_DEV_MINOR) {
  485: 		if (usb_dev_open)
  486: 			return (EBUSY);
  487: 		usb_dev_open = 1;
  488: 		usb_async_proc = NULL;
  489: 		return (0);
  490: 	}
  491: 
  492: 	USB_GET_SC_OPEN(usb, unit, sc);
  493: 
  494: 	if (sc->sc_dying)
  495: 		return (EIO);
  496: 
  497: 	return (0);
  498: }
  499: 
  500: int
  501: usbread(dev_t dev, struct uio *uio, int flag)
  502: {
  503: 	struct usb_event ue;
  504: 	int unit = USBUNIT(dev);
  505: 	int s, error, n;
  506: 
  507: 	if (unit != USB_DEV_MINOR)
  508: 		return (ENODEV);
  509: 
  510: 	if (uio->uio_resid != sizeof(struct usb_event))
  511: 		return (EINVAL);
  512: 
  513: 	error = 0;
  514: 	s = splusb();
  515: 	for (;;) {
  516: 		n = usb_get_next_event(&ue);
  517: 		if (n != 0)
  518: 			break;
  519: 		if (flag & IO_NDELAY) {
  520: 			error = EWOULDBLOCK;
  521: 			break;
  522: 		}
  523: 		error = tsleep(&usb_events, PCATCH, "usbrea", 0);
  524: 		if (error)
  525: 			break;
  526: 	}
  527: 	splx(s);
  528: 	if (!error)
  529: 		error = uiomove((void *)&ue, uio->uio_resid, uio);
  530: 
  531: 	return (error);
  532: }
  533: 
  534: int
  535: usbclose(dev_t dev, int flag, int mode, usb_proc_ptr p)
  536: {
  537: 	int unit = USBUNIT(dev);
  538: 
  539: 	if (unit == USB_DEV_MINOR) {
  540: 		usb_async_proc = NULL;
  541: 		usb_dev_open = 0;
  542: 	}
  543: 
  544: 	return (0);
  545: }
  546: 
  547: int
  548: usbioctl(dev_t devt, u_long cmd, caddr_t data, int flag, usb_proc_ptr p)
  549: {
  550: 	struct usb_softc *sc;
  551: 	int unit = USBUNIT(devt);
  552: 
  553: 	if (unit == USB_DEV_MINOR) {
  554: 		switch (cmd) {
  555: 		case FIONBIO:
  556: 			/* All handled in the upper FS layer. */
  557: 			return (0);
  558: 
  559: 		case FIOASYNC:
  560: 			if (*(int *)data)
  561: #if defined(__DragonFly__)
  562: 				usb_async_proc = p->td_proc;
  563: #elif __FreeBSD_version >= 500000
  564: 				usb_async_proc = p->td_proc;
  565: #else
  566: 				usb_async_proc = p;
  567: #endif
  568: 			else
  569: 				usb_async_proc = NULL;
  570: 			return (0);
  571: 
  572: 		default:
  573: 			return (EINVAL);
  574: 		}
  575: 	}
  576: 
  577: 	USB_GET_SC(usb, unit, sc);
  578: 
  579: 	if (sc->sc_dying)
  580: 		return (EIO);
  581: 
  582: 	switch (cmd) {
  583: #if defined(__FreeBSD__)
  584: 	/* This part should be deleted */
  585:   	case USB_DISCOVER:
  586:   		break;
  587: #endif
  588: 	case USB_REQUEST:
  589: 	{
  590: 		struct usb_ctl_request *ur = (void *)data;
  591: 		int len = UGETW(ur->ucr_request.wLength);
  592: 		struct iovec iov;
  593: 		struct uio uio;
  594: 		void *ptr = 0;
  595: 		int addr = ur->ucr_addr;
  596: 		usbd_status err;
  597: 		int error = 0;
  598: 
  599: 		DPRINTF(("usbioctl: USB_REQUEST addr=%d len=%d\n", addr, len));
  600: 		if (len < 0 || len > 32768)
  601: 			return (EINVAL);
  602: 		if (addr < 0 || addr >= USB_MAX_DEVICES ||
  603: 		    sc->sc_bus->devices[addr] == 0)
  604: 			return (EINVAL);
  605: 		if (len != 0) {
  606: 			iov.iov_base = (caddr_t)ur->ucr_data;
  607: 			iov.iov_len = len;
  608: 			uio.uio_iov = &iov;
  609: 			uio.uio_iovcnt = 1;
  610: 			uio.uio_resid = len;
  611: 			uio.uio_offset = 0;
  612: 			uio.uio_segflg = UIO_USERSPACE;
  613: 			uio.uio_rw =
  614: 				ur->ucr_request.bmRequestType & UT_READ ?
  615: 				UIO_READ : UIO_WRITE;
  616: 			uio.uio_td = p;
  617: 			ptr = malloc(len, M_TEMP, M_WAITOK);
  618: 			if (uio.uio_rw == UIO_WRITE) {
  619: 				error = uiomove(ptr, len, &uio);
  620: 				if (error)
  621: 					goto ret;
  622: 			}
  623: 		}
  624: 		err = usbd_do_request_flags(sc->sc_bus->devices[addr],
  625: 			  &ur->ucr_request, ptr, ur->ucr_flags, &ur->ucr_actlen,
  626: 			  USBD_DEFAULT_TIMEOUT);
  627: 		if (err) {
  628: 			error = EIO;
  629: 			goto ret;
  630: 		}
  631: 		if (len != 0) {
  632: 			if (uio.uio_rw == UIO_READ) {
  633: 				error = uiomove(ptr, len, &uio);
  634: 				if (error)
  635: 					goto ret;
  636: 			}
  637: 		}
  638: 	ret:
  639: 		if (ptr)
  640: 			free(ptr, M_TEMP);
  641: 		return (error);
  642: 	}
  643: 
  644: 	case USB_DEVICEINFO:
  645: 	{
  646: 		struct usb_device_info *di = (void *)data;
  647: 		int addr = di->udi_addr;
  648: 		usbd_device_handle dev;
  649: 
  650: 		if (addr < 1 || addr >= USB_MAX_DEVICES)
  651: 			return (EINVAL);
  652: 		dev = sc->sc_bus->devices[addr];
  653: 		if (dev == NULL)
  654: 			return (ENXIO);
  655: 		usbd_fill_deviceinfo(dev, di, 1);
  656: 		break;
  657: 	}
  658: 
  659: 	case USB_DEVICESTATS:
  660: 		*(struct usb_device_stats *)data = sc->sc_bus->stats;
  661: 		break;
  662: 
  663: 	default:
  664: 		return (EINVAL);
  665: 	}
  666: 	return (0);
  667: }
  668: 
  669: int
  670: usbpoll(dev_t dev, int events, usb_proc_ptr p)
  671: {
  672: 	int revents, mask, s;
  673: 	int unit = USBUNIT(dev);
  674: 
  675: 	if (unit == USB_DEV_MINOR) {
  676: 		revents = 0;
  677: 		mask = POLLIN | POLLRDNORM;
  678: 
  679: 		s = splusb();
  680: 		if (events & mask && usb_nevents > 0)
  681: 			revents |= events & mask;
  682: 		if (revents == 0 && events & mask)
  683: 			selrecord(p, &usb_selevent);
  684: 		splx(s);
  685: 
  686: 		return (revents);
  687: 	} else {
  688: #if defined(__FreeBSD__)
  689: 		return (0);	/* select/poll never wakes up - back compat */
  690: #else
  691: 		return (ENXIO);
  692: #endif
  693: 	}
  694: }
  695: 
  696: /* Explore device tree from the root. */
  697: Static void
  698: usb_discover(void *v)
  699: {
  700: 	struct usb_softc *sc = v;
  701: 
  702: #if defined(__FreeBSD__)
  703: 	/* splxxx should be changed to mutexes for preemption safety some day */
  704: 	int s;
  705: #endif
  706: 
  707: 	DPRINTFN(2,("usb_discover\n"));
  708: #ifdef USB_DEBUG
  709: 	if (usb_noexplore > 1)
  710: 		return;
  711: #endif
  712: 
  713: 	/*
  714: 	 * We need mutual exclusion while traversing the device tree,
  715: 	 * but this is guaranteed since this function is only called
  716: 	 * from the event thread for the controller.
  717: 	 */
  718: #if defined(__FreeBSD__)
  719: 	s = splusb();
  720: #endif
  721: 	while (sc->sc_bus->needs_explore && !sc->sc_dying) {
  722: 		sc->sc_bus->needs_explore = 0;
  723: #if defined(__FreeBSD__)
  724: 		splx(s);
  725: #endif
  726: 		sc->sc_bus->root_hub->hub->explore(sc->sc_bus->root_hub);
  727: #if defined(__FreeBSD__)
  728: 		s = splusb();
  729: #endif
  730: 	}
  731: #if defined(__FreeBSD__)
  732: 	splx(s);
  733: #endif
  734: }
  735: 
  736: void
  737: usb_needs_explore(usbd_device_handle dev)
  738: {
  739: 	DPRINTFN(2,("usb_needs_explore\n"));
  740: 	dev->bus->needs_explore = 1;
  741: 	wakeup(&dev->bus->needs_explore);
  742: }
  743: 
  744: /* Called at splusb() */
  745: int
  746: usb_get_next_event(struct usb_event *ue)
  747: {
  748: 	struct usb_event_q *ueq;
  749: 
  750: 	if (usb_nevents <= 0)
  751: 		return (0);
  752: 	ueq = TAILQ_FIRST(&usb_events);
  753: #ifdef DIAGNOSTIC
  754: 	if (ueq == NULL) {
  755: 		printf("usb: usb_nevents got out of sync! %d\n", usb_nevents);
  756: 		usb_nevents = 0;
  757: 		return (0);
  758: 	}
  759: #endif
  760: 	*ue = ueq->ue;
  761: 	TAILQ_REMOVE(&usb_events, ueq, next);
  762: 	free(ueq, M_USBDEV);
  763: 	usb_nevents--;
  764: 	return (1);
  765: }
  766: 
  767: void
  768: usbd_add_dev_event(int type, usbd_device_handle udev)
  769: {
  770: 	struct usb_event ue;
  771: 
  772: 	usbd_fill_deviceinfo(udev, &ue.u.ue_device, USB_EVENT_IS_ATTACH(type));
  773: 	usb_add_event(type, &ue);
  774: }
  775: 
  776: void
  777: usbd_add_drv_event(int type, usbd_device_handle udev, device_ptr_t dev)
  778: {
  779: 	struct usb_event ue;
  780: 
  781: 	ue.u.ue_driver.ue_cookie = udev->cookie;
  782: 	strncpy(ue.u.ue_driver.ue_devname, USBDEVPTRNAME(dev),
  783: 		sizeof ue.u.ue_driver.ue_devname);
  784: 	usb_add_event(type, &ue);
  785: }
  786: 
  787: void
  788: usb_add_event(int type, struct usb_event *uep)
  789: {
  790: 	struct usb_event_q *ueq;
  791: 	struct usb_event ue;
  792: 	struct timeval thetime;
  793: 	int s;
  794: 
  795: 	ueq = malloc(sizeof *ueq, M_USBDEV, M_WAITOK);
  796: 	ueq->ue = *uep;
  797: 	ueq->ue.ue_type = type;
  798: 	microtime(&thetime);
  799: 	TIMEVAL_TO_TIMESPEC(&thetime, &ueq->ue.ue_time);
  800: 
  801: 	s = splusb();
  802: 	if (USB_EVENT_IS_DETACH(type)) {
  803: 		struct usb_event_q *ueqi, *ueqi_next;
  804: 
  805: 		for (ueqi = TAILQ_FIRST(&usb_events); ueqi; ueqi = ueqi_next) {
  806: 			ueqi_next = TAILQ_NEXT(ueqi, next);
  807: 			if (ueqi->ue.u.ue_driver.ue_cookie.cookie ==
  808: 			    uep->u.ue_device.udi_cookie.cookie) {
  809: 				TAILQ_REMOVE(&usb_events, ueqi, next);
  810: 				free(ueqi, M_USBDEV);
  811: 				usb_nevents--;
  812: 				ueqi_next = TAILQ_FIRST(&usb_events);
  813: 			}
  814: 		}
  815: 	}
  816: 	if (usb_nevents >= USB_MAX_EVENTS) {
  817: 		/* Too many queued events, drop an old one. */
  818: 		DPRINTF(("usb: event dropped\n"));
  819: 		(void)usb_get_next_event(&ue);
  820: 	}
  821: 	TAILQ_INSERT_TAIL(&usb_events, ueq, next);
  822: 	usb_nevents++;
  823: 	wakeup(&usb_events);
  824: 	selwakeuppri(&usb_selevent, 0);
  825: 	if (usb_async_proc != NULL) {
  826: 		PROC_LOCK(usb_async_proc);
  827: 		psignal(usb_async_proc, SIGIO);
  828: 		PROC_UNLOCK(usb_async_proc);
  829: 	}
  830: 	splx(s);
  831: }
  832: 
  833: void
  834: usb_schedsoftintr(usbd_bus_handle bus)
  835: {
  836: 	DPRINTFN(10,("usb_schedsoftintr: polling=%d\n", bus->use_polling));
  837: #ifdef USB_USE_SOFTINTR
  838: 	if (bus->use_polling) {
  839: 		bus->methods->soft_intr(bus);
  840: 	} else {
  841: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  842: 		softintr_schedule(bus->soft);
  843: #else
  844: 		if (!callout_pending(&bus->softi))
  845: 			callout_reset(&bus->softi, 0, bus->methods->soft_intr,
  846: 			    bus);
  847: #endif /* __HAVE_GENERIC_SOFT_INTERRUPTS */
  848: 	}
  849: #else
  850: 	bus->methods->soft_intr(bus);
  851: #endif /* USB_USE_SOFTINTR */
  852: }
  853: 
  854: 
  855: #if defined(__NetBSD__) || defined(__OpenBSD__)
  856: int
  857: usb_activate(device_ptr_t self, enum devact act)
  858: {
  859: 	struct usb_softc *sc = (struct usb_softc *)self;
  860: 	usbd_device_handle dev = sc->sc_port.device;
  861: 	int i, rv = 0;
  862: 
  863: 	switch (act) {
  864: 	case DVACT_ACTIVATE:
  865: 		return (EOPNOTSUPP);
  866: 
  867: 	case DVACT_DEACTIVATE:
  868: 		sc->sc_dying = 1;
  869: 		if (dev != NULL && dev->cdesc != NULL && dev->subdevs != NULL) {
  870: 			for (i = 0; dev->subdevs[i]; i++)
  871: 				rv |= config_deactivate(dev->subdevs[i]);
  872: 		}
  873: 		break;
  874: 	}
  875: 	return (rv);
  876: }
  877: 
  878: int
  879: usb_detach(device_ptr_t self, int flags)
  880: {
  881: 	struct usb_softc *sc = (struct usb_softc *)self;
  882: 	struct usb_event ue;
  883: 
  884: 	DPRINTF(("usb_detach: start\n"));
  885: 
  886: 	sc->sc_dying = 1;
  887: 
  888: 	/* Make all devices disconnect. */
  889: 	if (sc->sc_port.device != NULL)
  890: 		usb_disconnect_port(&sc->sc_port, self);
  891: 
  892: 	/* Kill off event thread. */
  893: 	if (sc->sc_event_thread != NULL) {
  894: 		wakeup(&sc->sc_bus->needs_explore);
  895: 		if (tsleep(sc, 0, "usbdet", hz * 60))
  896: 			printf("%s: event thread didn't die\n",
  897: 			       USBDEVNAME(sc->sc_dev));
  898: 		DPRINTF(("usb_detach: event thread dead\n"));
  899: 	}
  900: 
  901: 	usbd_finish();
  902: 
  903: #ifdef USB_USE_SOFTINTR
  904: #ifdef __HAVE_GENERIC_SOFT_INTERRUPTS
  905: 	if (sc->sc_bus->soft != NULL) {
  906: 		softintr_disestablish(sc->sc_bus->soft);
  907: 		sc->sc_bus->soft = NULL;
  908: 	}
  909: #else
  910: 	callout_stop(&sc->sc_bus->softi);
  911: #endif
  912: #endif
  913: 
  914: 	ue.u.ue_ctrlr.ue_bus = USBDEVUNIT(sc->sc_dev);
  915: 	usb_add_event(USB_EVENT_CTRLR_DETACH, &ue);
  916: 
  917: 	return (0);
  918: }
  919: #elif defined(__FreeBSD__)
  920: int
  921: usb_detach(device_t self)
  922: {
  923: 	DPRINTF(("%s: unload, prevented\n", USBDEVNAME(self)));
  924: 
  925: 	return (EINVAL);
  926: }
  927: #endif
  928: 
  929: 
  930: #if defined(__FreeBSD__)
  931: DRIVER_MODULE(usb, ohci, usb_driver, usb_devclass, 0, 0);
  932: DRIVER_MODULE(usb, uhci, usb_driver, usb_devclass, 0, 0);
  933: DRIVER_MODULE(usb, ehci, usb_driver, usb_devclass, 0, 0);
  934: #endif