xref: /dflybsd-src/sys/bus/u4b/usb_debug.c (revision 2b3f93ea6d1f70880f3e87f3c2cbe0dc0bfc9332)
1141a761fSMarkus Pfeiffer /* $FreeBSD: head/sys/dev/usb/usb_debug.c 267992 2014-06-28 03:56:17Z hselasky $ */
212bd3c8bSSascha Wildner /*-
312bd3c8bSSascha Wildner  * Copyright (c) 2008 Hans Petter Selasky. All rights reserved.
412bd3c8bSSascha Wildner  *
512bd3c8bSSascha Wildner  * Redistribution and use in source and binary forms, with or without
612bd3c8bSSascha Wildner  * modification, are permitted provided that the following conditions
712bd3c8bSSascha Wildner  * are met:
812bd3c8bSSascha Wildner  * 1. Redistributions of source code must retain the above copyright
912bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer.
1012bd3c8bSSascha Wildner  * 2. Redistributions in binary form must reproduce the above copyright
1112bd3c8bSSascha Wildner  *    notice, this list of conditions and the following disclaimer in the
1212bd3c8bSSascha Wildner  *    documentation and/or other materials provided with the distribution.
1312bd3c8bSSascha Wildner  *
1412bd3c8bSSascha Wildner  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1512bd3c8bSSascha Wildner  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1612bd3c8bSSascha Wildner  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1712bd3c8bSSascha Wildner  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
1812bd3c8bSSascha Wildner  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
1912bd3c8bSSascha Wildner  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2012bd3c8bSSascha Wildner  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2112bd3c8bSSascha Wildner  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2212bd3c8bSSascha Wildner  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2312bd3c8bSSascha Wildner  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2412bd3c8bSSascha Wildner  * SUCH DAMAGE.
2512bd3c8bSSascha Wildner  */
2612bd3c8bSSascha Wildner 
2712bd3c8bSSascha Wildner #include <sys/stdint.h>
2812bd3c8bSSascha Wildner #include <sys/queue.h>
2912bd3c8bSSascha Wildner #include <sys/types.h>
3012bd3c8bSSascha Wildner #include <sys/systm.h>
3112bd3c8bSSascha Wildner #include <sys/kernel.h>
3212bd3c8bSSascha Wildner #include <sys/bus.h>
3312bd3c8bSSascha Wildner #include <sys/module.h>
3412bd3c8bSSascha Wildner #include <sys/lock.h>
3512bd3c8bSSascha Wildner #include <sys/condvar.h>
3612bd3c8bSSascha Wildner #include <sys/sysctl.h>
3712bd3c8bSSascha Wildner #include <sys/unistd.h>
3812bd3c8bSSascha Wildner #include <sys/callout.h>
3912bd3c8bSSascha Wildner #include <sys/malloc.h>
40*2b3f93eaSMatthew Dillon #include <sys/caps.h>
4112bd3c8bSSascha Wildner 
42722d05c3SSascha Wildner #include <bus/u4b/usb.h>
43722d05c3SSascha Wildner #include <bus/u4b/usbdi.h>
4412bd3c8bSSascha Wildner 
45722d05c3SSascha Wildner #include <bus/u4b/usb_core.h>
46722d05c3SSascha Wildner #include <bus/u4b/usb_debug.h>
47722d05c3SSascha Wildner #include <bus/u4b/usb_process.h>
48722d05c3SSascha Wildner #include <bus/u4b/usb_device.h>
49722d05c3SSascha Wildner #include <bus/u4b/usb_busdma.h>
50722d05c3SSascha Wildner #include <bus/u4b/usb_transfer.h>
5112bd3c8bSSascha Wildner 
5212bd3c8bSSascha Wildner #include <ddb/ddb.h>
5312bd3c8bSSascha Wildner #include <ddb/db_sym.h>
5412bd3c8bSSascha Wildner 
5512bd3c8bSSascha Wildner /*
5612bd3c8bSSascha Wildner  * Define this unconditionally in case a kernel module is loaded that
5712bd3c8bSSascha Wildner  * has been compiled with debugging options.
5812bd3c8bSSascha Wildner  */
5912bd3c8bSSascha Wildner int	usb_debug = 0;
6012bd3c8bSSascha Wildner 
6112bd3c8bSSascha Wildner SYSCTL_NODE(_hw, OID_AUTO, usb, CTLFLAG_RW, 0, "USB debugging");
6212bd3c8bSSascha Wildner SYSCTL_INT(_hw_usb, OID_AUTO, debug, CTLFLAG_RW,
6312bd3c8bSSascha Wildner     &usb_debug, 0, "Debug level");
6412bd3c8bSSascha Wildner 
6512bd3c8bSSascha Wildner TUNABLE_INT("hw.usb.debug", &usb_debug);
6612bd3c8bSSascha Wildner 
675e41ab93SMarkus Pfeiffer #ifdef USB_DEBUG
685e41ab93SMarkus Pfeiffer /*
695e41ab93SMarkus Pfeiffer  * Sysctls to modify timings/delays
705e41ab93SMarkus Pfeiffer  */
715e41ab93SMarkus Pfeiffer static SYSCTL_NODE(_hw_usb, OID_AUTO, timings, CTLFLAG_RW, 0, "Timings");
725e41ab93SMarkus Pfeiffer static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS);
735e41ab93SMarkus Pfeiffer 
745e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_reset_delay", (int *)&usb_port_reset_delay);
755e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_delay, CTLTYPE_UINT | CTLFLAG_RW,
765e41ab93SMarkus Pfeiffer     &usb_port_reset_delay, sizeof(usb_port_reset_delay),
775e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Port Reset Delay");
785e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_root_reset_delay", (int *)&usb_port_root_reset_delay);
795e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_root_reset_delay, CTLTYPE_UINT | CTLFLAG_RW,
805e41ab93SMarkus Pfeiffer     &usb_port_root_reset_delay, sizeof(usb_port_root_reset_delay),
815e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Root Port Reset Delay");
825e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_reset_recovery", (int *)&usb_port_reset_recovery);
835e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_reset_recovery, CTLTYPE_UINT | CTLFLAG_RW,
845e41ab93SMarkus Pfeiffer     &usb_port_reset_recovery, sizeof(usb_port_reset_recovery),
855e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Port Reset Recovery");
865e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_powerup_delay", (int *)&usb_port_powerup_delay);
875e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_powerup_delay, CTLTYPE_UINT | CTLFLAG_RW,
885e41ab93SMarkus Pfeiffer     &usb_port_powerup_delay, sizeof(usb_port_powerup_delay),
895e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Port PowerUp Delay");
905e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.port_resume_delay", (int *)&usb_port_resume_delay);
915e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, port_resume_delay, CTLTYPE_UINT | CTLFLAG_RW,
925e41ab93SMarkus Pfeiffer     &usb_port_resume_delay, sizeof(usb_port_resume_delay),
935e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Port Resume Delay");
945e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.set_address_settle", (int *)&usb_set_address_settle);
955e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, set_address_settle, CTLTYPE_UINT | CTLFLAG_RW,
965e41ab93SMarkus Pfeiffer     &usb_set_address_settle, sizeof(usb_set_address_settle),
975e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Set Address Settle");
985e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_delay", (int *)&usb_resume_delay);
995e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_delay, CTLTYPE_UINT | CTLFLAG_RW,
1005e41ab93SMarkus Pfeiffer     &usb_resume_delay, sizeof(usb_resume_delay),
1015e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Resume Delay");
1025e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_wait", (int *)&usb_resume_wait);
1035e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_wait, CTLTYPE_UINT | CTLFLAG_RW,
1045e41ab93SMarkus Pfeiffer     &usb_resume_wait, sizeof(usb_resume_wait),
1055e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Resume Wait");
1065e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.resume_recovery", (int *)&usb_resume_recovery);
1075e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, resume_recovery, CTLTYPE_UINT | CTLFLAG_RW,
1085e41ab93SMarkus Pfeiffer     &usb_resume_recovery, sizeof(usb_resume_recovery),
1095e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Resume Recovery");
1105e41ab93SMarkus Pfeiffer TUNABLE_INT("hw.usb.timings.extra_power_up_time", (int *)&usb_extra_power_up_time);
1115e41ab93SMarkus Pfeiffer SYSCTL_PROC(_hw_usb_timings, OID_AUTO, extra_power_up_time, CTLTYPE_UINT | CTLFLAG_RW,
1125e41ab93SMarkus Pfeiffer     &usb_extra_power_up_time, sizeof(usb_extra_power_up_time),
1135e41ab93SMarkus Pfeiffer     usb_timings_sysctl_handler, "IU", "Extra PowerUp Time");
1145e41ab93SMarkus Pfeiffer #endif
1155e41ab93SMarkus Pfeiffer 
11612bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
11712bd3c8bSSascha Wildner  *	usb_dump_iface
11812bd3c8bSSascha Wildner  *
11912bd3c8bSSascha Wildner  * This function dumps information about an USB interface.
12012bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
12112bd3c8bSSascha Wildner void
usb_dump_iface(struct usb_interface * iface)12212bd3c8bSSascha Wildner usb_dump_iface(struct usb_interface *iface)
12312bd3c8bSSascha Wildner {
124722d05c3SSascha Wildner 	kprintf("usb_dump_iface: iface=%p\n", iface);
12512bd3c8bSSascha Wildner 	if (iface == NULL) {
12612bd3c8bSSascha Wildner 		return;
12712bd3c8bSSascha Wildner 	}
128722d05c3SSascha Wildner 	kprintf(" iface=%p idesc=%p altindex=%d\n",
12912bd3c8bSSascha Wildner 	    iface, iface->idesc, iface->alt_index);
13012bd3c8bSSascha Wildner }
13112bd3c8bSSascha Wildner 
13212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
13312bd3c8bSSascha Wildner  *	usb_dump_device
13412bd3c8bSSascha Wildner  *
13512bd3c8bSSascha Wildner  * This function dumps information about an USB device.
13612bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
13712bd3c8bSSascha Wildner void
usb_dump_device(struct usb_device * udev)13812bd3c8bSSascha Wildner usb_dump_device(struct usb_device *udev)
13912bd3c8bSSascha Wildner {
140722d05c3SSascha Wildner 	kprintf("usb_dump_device: dev=%p\n", udev);
14112bd3c8bSSascha Wildner 	if (udev == NULL) {
14212bd3c8bSSascha Wildner 		return;
14312bd3c8bSSascha Wildner 	}
144722d05c3SSascha Wildner 	kprintf(" bus=%p \n"
14512bd3c8bSSascha Wildner 	    " address=%d config=%d depth=%d speed=%d self_powered=%d\n"
14612bd3c8bSSascha Wildner 	    " power=%d langid=%d\n",
14712bd3c8bSSascha Wildner 	    udev->bus,
14812bd3c8bSSascha Wildner 	    udev->address, udev->curr_config_no, udev->depth, udev->speed,
14912bd3c8bSSascha Wildner 	    udev->flags.self_powered, udev->power, udev->langid);
15012bd3c8bSSascha Wildner }
15112bd3c8bSSascha Wildner 
15212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
15312bd3c8bSSascha Wildner  *	usb_dump_queue
15412bd3c8bSSascha Wildner  *
15512bd3c8bSSascha Wildner  * This function dumps the USB transfer that are queued up on an USB endpoint.
15612bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
15712bd3c8bSSascha Wildner void
usb_dump_queue(struct usb_endpoint * ep)15812bd3c8bSSascha Wildner usb_dump_queue(struct usb_endpoint *ep)
15912bd3c8bSSascha Wildner {
16012bd3c8bSSascha Wildner 	struct usb_xfer *xfer;
1615e41ab93SMarkus Pfeiffer 	usb_stream_t x;
16212bd3c8bSSascha Wildner 
163722d05c3SSascha Wildner 	kprintf("usb_dump_queue: endpoint=%p xfer: ", ep);
1645e41ab93SMarkus Pfeiffer 	for (x = 0; x != USB_MAX_EP_STREAMS; x++) {
1655e41ab93SMarkus Pfeiffer 		TAILQ_FOREACH(xfer, &ep->endpoint_q[x].head, wait_entry) {
166722d05c3SSascha Wildner 			kprintf(" %p", xfer);
16712bd3c8bSSascha Wildner 		}
1685e41ab93SMarkus Pfeiffer 	}
169722d05c3SSascha Wildner 	kprintf("\n");
17012bd3c8bSSascha Wildner }
17112bd3c8bSSascha Wildner 
17212bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
17312bd3c8bSSascha Wildner  *	usb_dump_endpoint
17412bd3c8bSSascha Wildner  *
17512bd3c8bSSascha Wildner  * This function dumps information about an USB endpoint.
17612bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
17712bd3c8bSSascha Wildner void
usb_dump_endpoint(struct usb_endpoint * ep)17812bd3c8bSSascha Wildner usb_dump_endpoint(struct usb_endpoint *ep)
17912bd3c8bSSascha Wildner {
18012bd3c8bSSascha Wildner 	if (ep) {
181722d05c3SSascha Wildner 		kprintf("usb_dump_endpoint: endpoint=%p", ep);
18212bd3c8bSSascha Wildner 
183722d05c3SSascha Wildner 		kprintf(" edesc=%p isoc_next=%d toggle_next=%d",
18412bd3c8bSSascha Wildner 		    ep->edesc, ep->isoc_next, ep->toggle_next);
18512bd3c8bSSascha Wildner 
18612bd3c8bSSascha Wildner 		if (ep->edesc) {
187722d05c3SSascha Wildner 			kprintf(" bEndpointAddress=0x%02x",
18812bd3c8bSSascha Wildner 			    ep->edesc->bEndpointAddress);
18912bd3c8bSSascha Wildner 		}
190722d05c3SSascha Wildner 		kprintf("\n");
19112bd3c8bSSascha Wildner 		usb_dump_queue(ep);
19212bd3c8bSSascha Wildner 	} else {
193722d05c3SSascha Wildner 		kprintf("usb_dump_endpoint: endpoint=NULL\n");
19412bd3c8bSSascha Wildner 	}
19512bd3c8bSSascha Wildner }
19612bd3c8bSSascha Wildner 
19712bd3c8bSSascha Wildner /*------------------------------------------------------------------------*
19812bd3c8bSSascha Wildner  *	usb_dump_xfer
19912bd3c8bSSascha Wildner  *
20012bd3c8bSSascha Wildner  * This function dumps information about an USB transfer.
20112bd3c8bSSascha Wildner  *------------------------------------------------------------------------*/
20212bd3c8bSSascha Wildner void
usb_dump_xfer(struct usb_xfer * xfer)20312bd3c8bSSascha Wildner usb_dump_xfer(struct usb_xfer *xfer)
20412bd3c8bSSascha Wildner {
20512bd3c8bSSascha Wildner 	struct usb_device *udev;
206722d05c3SSascha Wildner 	kprintf("usb_dump_xfer: xfer=%p\n", xfer);
20712bd3c8bSSascha Wildner 	if (xfer == NULL) {
20812bd3c8bSSascha Wildner 		return;
20912bd3c8bSSascha Wildner 	}
21012bd3c8bSSascha Wildner 	if (xfer->endpoint == NULL) {
211722d05c3SSascha Wildner 		kprintf("xfer %p: endpoint=NULL\n",
21212bd3c8bSSascha Wildner 		    xfer);
21312bd3c8bSSascha Wildner 		return;
21412bd3c8bSSascha Wildner 	}
21512bd3c8bSSascha Wildner 	udev = xfer->xroot->udev;
216722d05c3SSascha Wildner 	kprintf("xfer %p: udev=%p vid=0x%04x pid=0x%04x addr=%d "
21712bd3c8bSSascha Wildner 	    "endpoint=%p ep=0x%02x attr=0x%02x\n",
21812bd3c8bSSascha Wildner 	    xfer, udev,
21912bd3c8bSSascha Wildner 	    UGETW(udev->ddesc.idVendor),
22012bd3c8bSSascha Wildner 	    UGETW(udev->ddesc.idProduct),
22112bd3c8bSSascha Wildner 	    udev->address, xfer->endpoint,
22212bd3c8bSSascha Wildner 	    xfer->endpoint->edesc->bEndpointAddress,
22312bd3c8bSSascha Wildner 	    xfer->endpoint->edesc->bmAttributes);
22412bd3c8bSSascha Wildner }
2255e41ab93SMarkus Pfeiffer 
2265e41ab93SMarkus Pfeiffer #ifdef USB_DEBUG
2275e41ab93SMarkus Pfeiffer unsigned int usb_port_reset_delay	= USB_PORT_RESET_DELAY;
2285e41ab93SMarkus Pfeiffer unsigned int usb_port_root_reset_delay	= USB_PORT_ROOT_RESET_DELAY;
2295e41ab93SMarkus Pfeiffer unsigned int usb_port_reset_recovery	= USB_PORT_RESET_RECOVERY;
2305e41ab93SMarkus Pfeiffer unsigned int usb_port_powerup_delay	= USB_PORT_POWERUP_DELAY;
2315e41ab93SMarkus Pfeiffer unsigned int usb_port_resume_delay	= USB_PORT_RESUME_DELAY;
2325e41ab93SMarkus Pfeiffer unsigned int usb_set_address_settle	= USB_SET_ADDRESS_SETTLE;
2335e41ab93SMarkus Pfeiffer unsigned int usb_resume_delay		= USB_RESUME_DELAY;
2345e41ab93SMarkus Pfeiffer unsigned int usb_resume_wait		= USB_RESUME_WAIT;
2355e41ab93SMarkus Pfeiffer unsigned int usb_resume_recovery	= USB_RESUME_RECOVERY;
2365e41ab93SMarkus Pfeiffer unsigned int usb_extra_power_up_time	= USB_EXTRA_POWER_UP_TIME;
2375e41ab93SMarkus Pfeiffer 
2385e41ab93SMarkus Pfeiffer /*------------------------------------------------------------------------*
2395e41ab93SMarkus Pfeiffer  *	usb_timings_sysctl_handler
2405e41ab93SMarkus Pfeiffer  *
2415e41ab93SMarkus Pfeiffer  * This function updates timings variables, adjusting them where necessary.
2425e41ab93SMarkus Pfeiffer  *------------------------------------------------------------------------*/
usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)2435e41ab93SMarkus Pfeiffer static int usb_timings_sysctl_handler(SYSCTL_HANDLER_ARGS)
2445e41ab93SMarkus Pfeiffer {
2455e41ab93SMarkus Pfeiffer 	int error = 0;
2465e41ab93SMarkus Pfeiffer 	unsigned int val;
2475e41ab93SMarkus Pfeiffer 
2485e41ab93SMarkus Pfeiffer 	/*
2495e41ab93SMarkus Pfeiffer 	 * Attempt to get a coherent snapshot by making a copy of the data.
2505e41ab93SMarkus Pfeiffer 	 */
2515e41ab93SMarkus Pfeiffer 	if (arg1)
2525e41ab93SMarkus Pfeiffer 		val = *(unsigned int *)arg1;
2535e41ab93SMarkus Pfeiffer 	else
2545e41ab93SMarkus Pfeiffer 		val = arg2;
2555e41ab93SMarkus Pfeiffer 	error = SYSCTL_OUT(req, &val, sizeof(int));
2565e41ab93SMarkus Pfeiffer 	if (error || !req->newptr)
2575e41ab93SMarkus Pfeiffer 		return (error);
2585e41ab93SMarkus Pfeiffer 
2595e41ab93SMarkus Pfeiffer 	if (!arg1)
2605e41ab93SMarkus Pfeiffer 		return EPERM;
2615e41ab93SMarkus Pfeiffer 
2625e41ab93SMarkus Pfeiffer 	error = SYSCTL_IN(req, &val, sizeof(unsigned int));
2635e41ab93SMarkus Pfeiffer 	if (error)
2645e41ab93SMarkus Pfeiffer 		return (error);
2655e41ab93SMarkus Pfeiffer 
2665e41ab93SMarkus Pfeiffer 	/*
2675e41ab93SMarkus Pfeiffer 	 * Now make sure the values are decent, and certainly no lower than
2685e41ab93SMarkus Pfeiffer 	 * what the USB spec prescribes.
2695e41ab93SMarkus Pfeiffer 	 */
2705e41ab93SMarkus Pfeiffer 	unsigned int *p = (unsigned int *)arg1;
2715e41ab93SMarkus Pfeiffer 	if (p == &usb_port_reset_delay) {
2725e41ab93SMarkus Pfeiffer 		if (val < USB_PORT_RESET_DELAY_SPEC)
2735e41ab93SMarkus Pfeiffer 			return (EINVAL);
2745e41ab93SMarkus Pfeiffer 	} else if (p == &usb_port_root_reset_delay) {
2755e41ab93SMarkus Pfeiffer 		if (val < USB_PORT_ROOT_RESET_DELAY_SPEC)
2765e41ab93SMarkus Pfeiffer 			return (EINVAL);
2775e41ab93SMarkus Pfeiffer 	} else if (p == &usb_port_reset_recovery) {
2785e41ab93SMarkus Pfeiffer 		if (val < USB_PORT_RESET_RECOVERY_SPEC)
2795e41ab93SMarkus Pfeiffer 			return (EINVAL);
2805e41ab93SMarkus Pfeiffer 	} else if (p == &usb_port_powerup_delay) {
2815e41ab93SMarkus Pfeiffer 		if (val < USB_PORT_POWERUP_DELAY_SPEC)
2825e41ab93SMarkus Pfeiffer 			return (EINVAL);
2835e41ab93SMarkus Pfeiffer 	} else if (p == &usb_port_resume_delay) {
2845e41ab93SMarkus Pfeiffer 		if (val < USB_PORT_RESUME_DELAY_SPEC)
2855e41ab93SMarkus Pfeiffer 			return (EINVAL);
2865e41ab93SMarkus Pfeiffer 	} else if (p == &usb_set_address_settle) {
2875e41ab93SMarkus Pfeiffer 		if (val < USB_SET_ADDRESS_SETTLE_SPEC)
2885e41ab93SMarkus Pfeiffer 			return (EINVAL);
2895e41ab93SMarkus Pfeiffer 	} else if (p == &usb_resume_delay) {
2905e41ab93SMarkus Pfeiffer 		if (val < USB_RESUME_DELAY_SPEC)
2915e41ab93SMarkus Pfeiffer 			return (EINVAL);
2925e41ab93SMarkus Pfeiffer 	} else if (p == &usb_resume_wait) {
2935e41ab93SMarkus Pfeiffer 		if (val < USB_RESUME_WAIT_SPEC)
2945e41ab93SMarkus Pfeiffer 			return (EINVAL);
2955e41ab93SMarkus Pfeiffer 	} else if (p == &usb_resume_recovery) {
2965e41ab93SMarkus Pfeiffer 		if (val < USB_RESUME_RECOVERY_SPEC)
2975e41ab93SMarkus Pfeiffer 			return (EINVAL);
2985e41ab93SMarkus Pfeiffer 	} else if (p == &usb_extra_power_up_time) {
2995e41ab93SMarkus Pfeiffer 		if (val < USB_EXTRA_POWER_UP_TIME_SPEC)
3005e41ab93SMarkus Pfeiffer 			return (EINVAL);
3015e41ab93SMarkus Pfeiffer 	} else {
3025e41ab93SMarkus Pfeiffer 		/* noop */
3035e41ab93SMarkus Pfeiffer 	}
3045e41ab93SMarkus Pfeiffer 
3055e41ab93SMarkus Pfeiffer 	*p = val;
3065e41ab93SMarkus Pfeiffer 	return 0;
3075e41ab93SMarkus Pfeiffer }
3085e41ab93SMarkus Pfeiffer #endif
309