From owner-svn-src-all@FreeBSD.ORG Thu Jan 31 11:00:59 2013 Return-Path: Delivered-To: svn-src-all@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 02DB7F76; Thu, 31 Jan 2013 11:00:59 +0000 (UTC) (envelope-from hselasky@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:1900:2254:2068::e6a:0]) by mx1.freebsd.org (Postfix) with ESMTP id DA41DB23; Thu, 31 Jan 2013 11:00:58 +0000 (UTC) Received: from svn.freebsd.org ([127.0.1.70]) by svn.freebsd.org (8.14.5/8.14.5) with ESMTP id r0VB0wrc040294; Thu, 31 Jan 2013 11:00:58 GMT (envelope-from hselasky@svn.freebsd.org) Received: (from hselasky@localhost) by svn.freebsd.org (8.14.5/8.14.5/Submit) id r0VB0vfu040286; Thu, 31 Jan 2013 11:00:57 GMT (envelope-from hselasky@svn.freebsd.org) Message-Id: <201301311100.r0VB0vfu040286@svn.freebsd.org> From: Hans Petter Selasky Date: Thu, 31 Jan 2013 11:00:57 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org Subject: svn commit: r246145 - in head/sys/boot/usb: . tools X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 31 Jan 2013 11:00:59 -0000 Author: hselasky Date: Thu Jan 31 11:00:57 2013 New Revision: 246145 URL: http://svnweb.freebsd.org/changeset/base/246145 Log: Initial version of libusbboot, a fully stand-alone, single threaded and functional compilation of the FreeBSD USB stack for use with boot loaders and such. Discussed with: Hiroki Sato, hrs @ EuroBSDCon Added: head/sys/boot/usb/ head/sys/boot/usb/Makefile (contents, props changed) head/sys/boot/usb/Makefile.test (contents, props changed) head/sys/boot/usb/bsd_busspace.c (contents, props changed) head/sys/boot/usb/bsd_global.h (contents, props changed) head/sys/boot/usb/bsd_kernel.c (contents, props changed) head/sys/boot/usb/bsd_kernel.h (contents, props changed) head/sys/boot/usb/bsd_usbloader_test.c (contents, props changed) head/sys/boot/usb/tools/ head/sys/boot/usb/tools/sysinit.c (contents, props changed) head/sys/boot/usb/tools/sysinit.h (contents, props changed) head/sys/boot/usb/usb_busdma_loader.c (contents, props changed) Added: head/sys/boot/usb/Makefile ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/usb/Makefile Thu Jan 31 11:00:57 2013 (r246145) @@ -0,0 +1,150 @@ +# +# $FreeBSD$ +# +# Copyright (c) 2013 Hans Petter Selasky. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +T=${.CURDIR}/tools +S=${.CURDIR}/../.. + +.PATH: \ + ${.CURDIR} \ + ${S}/dev/usb \ + ${S}/dev/usb/controller \ + ${S}/dev/usb/serial \ + ${S}/dev/usb/storage \ + ${S}/dev/usb/template + +LIB= usbboot +INTERNALLIB= +OBJCOPY?= objcopy +SYSCC?= cc + +CFLAGS+= -DBOOTPROG=\"usbloader\" +CFLAGS+= -DUSB_GLOBAL_INCLUDE_FILE="\"bsd_global.h\"" +CFLAGS+= -ffunction-sections -fdata-sections +CFLAGS+= -ffreestanding +CFLAGS+= -Wformat -Wall +CFLAGS+= -I ${S} +CFLAGS+= -I ${T} +CFLAGS+= -I ${.CURDIR} +CFLAGS+= -g + +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -march=i386 +CFLAGS+= -mpreferred-stack-boundary=2 +.endif +.if ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -m32 +.endif + +# +# Single threaded BSD kernel +# +SRCS+= bsd_kernel.c + +# +# BUSSPACE implementation +# +SRCS+= bsd_busspace.c + +# +# BUSDMA implementation +# +SRCS+= usb_busdma_loader.c + +# +# USB controller drivers +# +SRCS+= at91dci.c +SRCS+= atmegadci.c +SRCS+= avr32dci.c +SRCS+= dwc_otg.c +SRCS+= ehci.c +SRCS+= musb_otg.c +SRCS+= ohci.c +SRCS+= uhci.c +SRCS+= uss820dci.c +SRCS+= xhci.c +SRCS+= usb_controller.c + +CFLAGS += -DUSB_PROBE_LIST="\"xhci\", \"ehci\", \"uhci\", \"ohci\"" + +# +# USB core and templates +# +SRCS+= usb_core.c +SRCS+= usb_debug.c +SRCS+= usb_device.c +SRCS+= usb_dynamic.c +SRCS+= usb_error.c +SRCS+= usb_handle_request.c +SRCS+= usb_hid.c +SRCS+= usb_hub.c +SRCS+= usb_lookup.c +SRCS+= usb_msctest.c +SRCS+= usb_parse.c +SRCS+= usb_request.c +SRCS+= usb_transfer.c +SRCS+= usb_util.c +SRCS+= usb_template.c +SRCS+= usb_template_cdce.c +SRCS+= usb_template_msc.c +SRCS+= usb_template_mtp.c +SRCS+= usb_template_modem.c +SRCS+= usb_template_mouse.c +SRCS+= usb_template_kbd.c +SRCS+= usb_template_audio.c +SRCS+= sysinit_data.c +SRCS+= sysuninit_data.c + +CLEANFILES+= sysinit +CLEANFILES+= sysinit.bin +CLEANFILES+= sysinit_data.c +CLEANFILES+= sysuninit_data.c + +CLEANFILES+= ${SRCS:C/\.c/.osys/g} + +.include + +# +# SYSINIT() and SYSUNINIT() handling +# +sysinit: ${T}/sysinit.c + ${SYSCC} -Wall -o ${.TARGET} ${.ALLSRC} + +sysinit_data.c: sysinit.bin sysinit + ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -k sysinit -s sysinit_data + +sysuninit_data.c: sysinit.bin sysinit + ${.OBJDIR}/sysinit -i sysinit.bin -o ${.TARGET} -R -k sysuninit -s sysuninit_data + +.for F in ${OBJS} +${F}sys: ${F} + ${OBJCOPY} -j ".debug.sysinit" -O binary ${F} ${.TARGET} + [ -f ${.TARGET} ] || touch ${.TARGET} +.endfor + +sysinit.bin: ${OBJS:C/\.o/.osys/g:C/sysinit_data.osys//g:C/sysuninit_data.osys//g} + cat ${.ALLSRC} > sysinit.bin Added: head/sys/boot/usb/Makefile.test ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/usb/Makefile.test Thu Jan 31 11:00:57 2013 (r246145) @@ -0,0 +1,61 @@ +# +# $FreeBSD$ +# +# Copyright (c) 2013 Hans Petter Selasky. All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND +# ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. +# + +# +# USB test application +# + +.PATH: ${.CURDIR} + +PROG= usbloader +MAN= +SRCS= + +CFLAGS+= -Wall +CFLAGS+= -g + +.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -march=i386 +CFLAGS+= -mpreferred-stack-boundary=2 +.endif +.if ${MACHINE_CPUARCH} == "amd64" +CFLAGS+= -m32 +.endif + +LDFLAGS+= -Wl,--gc-sections + +SRCS+= bsd_usbloader_test.c + +LDADD+= libusbboot.a +DPADD+= libusbboot.a + +all: libusbboot.a + +.include + +libusbboot.a: + make -f Makefile Added: head/sys/boot/usb/bsd_busspace.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/usb/bsd_busspace.c Thu Jan 31 11:00:57 2013 (r246145) @@ -0,0 +1,207 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2013 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +struct burst { + uint32_t dw0; + uint32_t dw1; + uint32_t dw2; + uint32_t dw3; + uint32_t dw4; + uint32_t dw5; + uint32_t dw6; + uint32_t dw7; +}; + +void +bus_space_read_multi_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint8_t *datap, bus_size_t count) +{ + while (count--) { + *datap++ = bus_space_read_1(t, h, offset); + } +} + +void +bus_space_read_multi_2(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint16_t *datap, bus_size_t count) +{ + while (count--) { + *datap++ = bus_space_read_2(t, h, offset); + } +} + +void +bus_space_read_multi_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint32_t *datap, bus_size_t count) +{ + h += offset; + + while (count--) { + *datap++ = *((volatile uint32_t *)h); + } +} + +void +bus_space_write_multi_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint8_t *datap, bus_size_t count) +{ + while (count--) { + uint8_t temp = *datap++; + + bus_space_write_1(t, h, offset, temp); + } +} + +void +bus_space_write_multi_2(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint16_t *datap, bus_size_t count) +{ + while (count--) { + uint16_t temp = *datap++; + + bus_space_write_2(t, h, offset, temp); + } +} + +void +bus_space_write_multi_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint32_t *datap, bus_size_t count) +{ + h += offset; + + while (count--) { + *((volatile uint32_t *)h) = *datap++; + } +} + +void +bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint8_t data) +{ + *((volatile uint8_t *)(h + offset)) = data; +} + +void +bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint16_t data) +{ + *((volatile uint16_t *)(h + offset)) = data; +} + +void +bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint32_t data) +{ + *((volatile uint32_t *)(h + offset)) = data; +} + +uint8_t +bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset) +{ + return (*((volatile uint8_t *)(h + offset))); +} + +uint16_t +bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset) +{ + return (*((volatile uint16_t *)(h + offset))); +} + +uint32_t +bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset) +{ + return (*((volatile uint32_t *)(h + offset))); +} + +void +bus_space_read_region_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint8_t *datap, bus_size_t count) +{ + h += offset; + + while (count--) { + *datap++ = *((volatile uint8_t *)h); + h += 1; + } +} + +void +bus_space_write_region_1(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint8_t *datap, bus_size_t count) +{ + h += offset; + + while (count--) { + *((volatile uint8_t *)h) = *datap++; + h += 1; + } +} + +void +bus_space_read_region_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint32_t *datap, bus_size_t count) +{ + enum { BURST = sizeof(struct burst) / 4 }; + + h += offset; + + while (count >= BURST) { + *(struct burst *)datap = *((/* volatile */ struct burst *)h); + + h += BURST * 4; + datap += BURST; + count -= BURST; + } + + while (count--) { + *datap++ = *((volatile uint32_t *)h); + h += 4; + } +} + +void +bus_space_write_region_4(bus_space_tag_t t, bus_space_handle_t h, + bus_size_t offset, uint32_t *datap, bus_size_t count) +{ + enum { BURST = sizeof(struct burst) / 4 }; + + h += offset; + + while (count >= BURST) { + *((/* volatile */ struct burst *)h) = *(struct burst *)datap; + + h += BURST * 4; + datap += BURST; + count -= BURST; + } + + while (count--) { + *((volatile uint32_t *)h) = *datap++; + h += 4; + } +} Added: head/sys/boot/usb/bsd_global.h ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/usb/bsd_global.h Thu Jan 31 11:00:57 2013 (r246145) @@ -0,0 +1,63 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2013 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef _BSD_GLOBAL_H_ +#define _BSD_GLOBAL_H_ + +#include + +#define USB_DEBUG_VAR usb_debug +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#endif /* _BSD_GLOBAL_H_ */ Added: head/sys/boot/usb/bsd_kernel.c ============================================================================== --- /dev/null 00:00:00 1970 (empty, because file is newly added) +++ head/sys/boot/usb/bsd_kernel.c Thu Jan 31 11:00:57 2013 (r246145) @@ -0,0 +1,1269 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2013 Hans Petter Selasky. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +static struct usb_process usb_process[USB_PROC_MAX]; +static device_t usb_pci_root; + +/*------------------------------------------------------------------------* + * Implementation of mutex API + *------------------------------------------------------------------------*/ + +struct mtx Giant; + +static void +mtx_system_init(void *arg) +{ + mtx_init(&Giant, "Giant", NULL, MTX_DEF | MTX_RECURSE); +} +SYSINIT(mtx_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, mtx_system_init, NULL); + +void +mtx_init(struct mtx *mtx, const char *name, const char *type, int opt) +{ + mtx->owned = 0; + mtx->parent = mtx; +} + +void +mtx_lock(struct mtx *mtx) +{ + mtx = mtx->parent; + mtx->owned++; +} + +void +mtx_unlock(struct mtx *mtx) +{ + mtx = mtx->parent; + mtx->owned--; +} + +int +mtx_owned(struct mtx *mtx) +{ + mtx = mtx->parent; + return (mtx->owned != 0); +} + +void +mtx_destroy(struct mtx *mtx) +{ + /* NOP */ +} + +/*------------------------------------------------------------------------* + * Implementation of shared/exclusive mutex API + *------------------------------------------------------------------------*/ + +void +sx_init_flags(struct sx *sx, const char *name, int flags) +{ + sx->owned = 0; +} + +void +sx_destroy(struct sx *sx) +{ + /* NOP */ +} + +void +sx_xlock(struct sx *sx) +{ + sx->owned++; +} + +void +sx_xunlock(struct sx *sx) +{ + sx->owned--; +} + +int +sx_xlocked(struct sx *sx) +{ + return (sx->owned != 0); +} + +/*------------------------------------------------------------------------* + * Implementaiton of condition variable API + *------------------------------------------------------------------------*/ + +void +cv_init(struct cv *cv, const char *desc) +{ + cv->sleeping = 0; +} + +void +cv_destroy(struct cv *cv) +{ + /* NOP */ +} + +void +cv_wait(struct cv *cv, struct mtx *mtx) +{ + cv_timedwait(cv, mtx, -1); +} + +int +cv_timedwait(struct cv *cv, struct mtx *mtx, int timo) +{ + int start = ticks; + int delta; + + if (cv->sleeping) + return (EWOULDBLOCK); /* not allowed */ + + cv->sleeping = 1; + + while (cv->sleeping) { + if (timo >= 0) { + delta = ticks - start; + if (delta >= timo || delta < 0) + break; + } + mtx_unlock(mtx); + + usb_idle(); + + mtx_lock(mtx); + } + + if (cv->sleeping) { + cv->sleeping = 0; + return (EWOULDBLOCK); /* not allowed */ + } + return (0); +} + +void +cv_signal(struct cv *cv) +{ + cv->sleeping = 0; +} + +void +cv_broadcast(struct cv *cv) +{ + cv->sleeping = 0; +} + +/*------------------------------------------------------------------------* + * Implementation of callout API + *------------------------------------------------------------------------*/ + +static void callout_proc_msg(struct usb_proc_msg *); + +volatile int ticks = 0; + +static LIST_HEAD(, callout) head_callout = LIST_HEAD_INITIALIZER(&head_callout); + +static struct mtx mtx_callout; +static struct usb_proc_msg callout_msg[2]; + +static void +callout_system_init(void *arg) +{ + mtx_init(&mtx_callout, "callout-mtx", NULL, MTX_DEF | MTX_RECURSE); + + callout_msg[0].pm_callback = &callout_proc_msg; + callout_msg[1].pm_callback = &callout_proc_msg; +} +SYSINIT(callout_system_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, callout_system_init, NULL); + +static void +callout_callback(struct callout *c) +{ + mtx_lock(c->mtx); + + mtx_lock(&mtx_callout); + if (c->entry.le_prev != NULL) { + LIST_REMOVE(c, entry); + c->entry.le_prev = NULL; + } + mtx_unlock(&mtx_callout); + + if (c->func) + (c->func) (c->arg); + + if (!(c->flags & CALLOUT_RETURNUNLOCKED)) + mtx_unlock(c->mtx); +} + +void +callout_process(int timeout) +{ + ticks += timeout; + usb_proc_msignal(usb_process + 2, &callout_msg[0], &callout_msg[1]); +} + +static void +callout_proc_msg(struct usb_proc_msg *pmsg) +{ + struct callout *c; + int delta; + +repeat: + mtx_lock(&mtx_callout); + + LIST_FOREACH(c, &head_callout, entry) { + + delta = c->timeout - ticks; + if (delta < 0) { + mtx_unlock(&mtx_callout); + + callout_callback(c); + + goto repeat; + } + } + mtx_unlock(&mtx_callout); +} + +void +callout_init_mtx(struct callout *c, struct mtx *mtx, int flags) +{ + memset(c, 0, sizeof(*c)); + + if (mtx == NULL) + mtx = &Giant; + + c->mtx = mtx; + c->flags = (flags & CALLOUT_RETURNUNLOCKED); +} + +void +callout_reset(struct callout *c, int to_ticks, + void (*func) (void *), void *arg) +{ + callout_stop(c); + + c->func = func; + c->arg = arg; + c->timeout = ticks + to_ticks; + + mtx_lock(&mtx_callout); + LIST_INSERT_HEAD(&head_callout, c, entry); + mtx_unlock(&mtx_callout); +} + +void +callout_stop(struct callout *c) +{ + mtx_lock(&mtx_callout); + + if (c->entry.le_prev != NULL) { + LIST_REMOVE(c, entry); + c->entry.le_prev = NULL; + } + mtx_unlock(&mtx_callout); + + c->func = NULL; + c->arg = NULL; +} + +void +callout_drain(struct callout *c) +{ + if (c->mtx == NULL) + return; /* not initialised */ + + mtx_lock(c->mtx); + callout_stop(c); + mtx_unlock(c->mtx); +} + +int +callout_pending(struct callout *c) +{ + int retval; + + mtx_lock(&mtx_callout); + retval = (c->entry.le_prev != NULL); + mtx_unlock(&mtx_callout); + + return (retval); +} + +/*------------------------------------------------------------------------* + * Implementation of device API + *------------------------------------------------------------------------*/ + +static const char unknown_string[] = { "unknown" }; + +static TAILQ_HEAD(, module_data) module_head = + TAILQ_HEAD_INITIALIZER(module_head); + +static uint8_t +devclass_equal(const char *a, const char *b) +{ + char ta, tb; + + if (a == b) + return (1); + + while (1) { + ta = *a; + tb = *b; + if (ta != tb) + return (0); + if (ta == 0) + break; + a++; + b++; + } + return (1); +} + +int +bus_generic_resume(device_t dev) +{ + return (0); +} + +int +bus_generic_shutdown(device_t dev) +{ + return (0); +} + +int +bus_generic_suspend(device_t dev) +{ + return (0); +} + +int +bus_generic_print_child(device_t dev, device_t child) +{ + return (0); +} + +void +bus_generic_driver_added(device_t dev, driver_t *driver) +{ + return; +} + +device_t +device_get_parent(device_t dev) +{ + return (dev ? dev->dev_parent : NULL); +} + +void +device_set_interrupt(device_t dev, intr_fn_t *fn, void *arg) +{ + dev->dev_irq_fn = fn; + dev->dev_irq_arg = arg; +} + +void +device_run_interrupts(device_t parent) +{ + device_t child; + + if (parent == NULL) + return; + + TAILQ_FOREACH(child, &parent->dev_children, dev_link) { + if (child->dev_irq_fn != NULL) + (child->dev_irq_fn) (child->dev_irq_arg); + } +} + +void +device_set_ivars(device_t dev, void *ivars) +{ + dev->dev_aux = ivars; +} + +void * +device_get_ivars(device_t dev) +{ + return (dev ? dev->dev_aux : NULL); +} + +int +device_get_unit(device_t dev) +{ + return (dev ? dev->dev_unit : 0); +} + +int +bus_generic_detach(device_t dev) +{ + device_t child; + int error; + + if (!dev->dev_attached) + return (EBUSY); + + TAILQ_FOREACH(child, &dev->dev_children, dev_link) { + if ((error = device_detach(child)) != 0) + return (error); + } + return (0); +} + +const char * +device_get_nameunit(device_t dev) +{ + if (dev && dev->dev_nameunit[0]) + return (dev->dev_nameunit); + + return (unknown_string); +} + +static uint8_t +devclass_create(devclass_t *dc_pp) +{ + if (dc_pp == NULL) { + return (1); + } + if (dc_pp[0] == NULL) { + dc_pp[0] = malloc(sizeof(**(dc_pp)), + M_DEVBUF, M_WAITOK | M_ZERO); + + if (dc_pp[0] == NULL) { + return (1); + } + } + return (0); +} + +static const struct module_data * +devclass_find_create(const char *classname) +{ + const struct module_data *mod; + + TAILQ_FOREACH(mod, &module_head, entry) { + if (devclass_equal(mod->mod_name, classname)) { + if (devclass_create(mod->devclass_pp)) { + continue; + } + return (mod); + } + } + return (NULL); +} + +static uint8_t +devclass_add_device(const struct module_data *mod, device_t dev) +{ + device_t *pp_dev; + device_t *end; + uint8_t unit; + + pp_dev = mod->devclass_pp[0]->dev_list; + end = pp_dev + DEVCLASS_MAXUNIT; + unit = 0; + + while (pp_dev != end) { + if (*pp_dev == NULL) { + *pp_dev = dev; + dev->dev_unit = unit; + dev->dev_module = mod; + snprintf(dev->dev_nameunit, + sizeof(dev->dev_nameunit), + "%s%d", device_get_name(dev), unit); + return (0); + } + pp_dev++; + unit++; + } + DPRINTF("Could not add device to devclass.\n"); + return (1); +} *** DIFF OUTPUT TRUNCATED AT 1000 LINES ***