summaryrefslogtreecommitdiffstats
path: root/stand/usb
diff options
context:
space:
mode:
authorkevans <kevans@FreeBSD.org>2018-02-12 01:08:44 +0000
committerkevans <kevans@FreeBSD.org>2018-02-12 01:08:44 +0000
commit7d97ee5b28b409c00bfaf12daf5ab497a6038b9d (patch)
tree245306b754606bcf49c0ff17b131b58609b6c7a6 /stand/usb
parent43b278e1b66cf4de337a17034087ea785031bd6f (diff)
downloadFreeBSD-src-7d97ee5b28b409c00bfaf12daf5ab497a6038b9d.zip
FreeBSD-src-7d97ee5b28b409c00bfaf12daf5ab497a6038b9d.tar.gz
MFC r325834,r325997,326502: Move sys/boot to stand/
This is effectively a direct commit to stable/11, due to differences between stable/11 and head. Changes to DTS in sys/boot/fdt/dts were often accompanied by kernel changes. Many of these were also risc-v updates that likely had many more dependencies to MFC. Because of this, sys/boot/fdt/dts remains as-is while everything else in sys/boot relocates to stand/. r325834: Move sys/boot to stand. Fix all references to new location r325997: Remove empty directories. r326502: Document the sys/boot -> stand move in hier.7 and the top-level README.
Diffstat (limited to 'stand/usb')
-rw-r--r--stand/usb/Makefile58
-rw-r--r--stand/usb/Makefile.test61
-rw-r--r--stand/usb/bsd_usbloader_test.c101
-rw-r--r--stand/usb/storage/umass_common.c90
-rw-r--r--stand/usb/storage/umass_common.h41
-rw-r--r--stand/usb/storage/umass_loader.c239
-rw-r--r--stand/usb/tools/Makefile10
-rw-r--r--stand/usb/tools/sysinit.c331
-rw-r--r--stand/usb/usb_busdma_loader.c619
-rw-r--r--stand/usb/usbcore.mk175
10 files changed, 1725 insertions, 0 deletions
diff --git a/stand/usb/Makefile b/stand/usb/Makefile
new file mode 100644
index 0000000..1b94b3d
--- /dev/null
+++ b/stand/usb/Makefile
@@ -0,0 +1,58 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky.
+# Copyright (c) 2014 SRI International
+# All rights reserved.
+#
+# This software was developed by SRI International and the University of
+# Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+# ("CTSRD"), as part of the DARPA CRASH research programme.
+#
+# 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.
+#
+
+LIB= usbboot
+INTERNALLIB=
+
+CFLAGS+= -DBOOTPROG=\"usbloader\"
+CFLAGS+= -ffunction-sections -fdata-sections
+CFLAGS+= -ffreestanding
+CFLAGS+= -Wformat -Wall
+CFLAGS+= -g
+CFLAGS+= -fno-pic
+
+.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -march=i386
+CFLAGS.gcc+= -mpreferred-stack-boundary=2
+.endif
+.if ${MACHINE_CPUARCH} == "amd64"
+CFLAGS+= -m32
+.endif
+.if ${MACHINE_CPUARCH} == "mips"
+CFLAGS+= -mno-abicalls
+.endif
+
+
+.include "usbcore.mk"
+.include "../kshim/kshim.mk"
+.include <bsd.lib.mk>
diff --git a/stand/usb/Makefile.test b/stand/usb/Makefile.test
new file mode 100644
index 0000000..7c6a66d1
--- /dev/null
+++ b/stand/usb/Makefile.test
@@ -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.gcc+= -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
+
+.include <bsd.prog.mk>
+
+${PROG}: libusbboot.a
+
+libusbboot.a:
+ make -f Makefile
diff --git a/stand/usb/bsd_usbloader_test.c b/stand/usb/bsd_usbloader_test.c
new file mode 100644
index 0000000..35140b8
--- /dev/null
+++ b/stand/usb/bsd_usbloader_test.c
@@ -0,0 +1,101 @@
+/* $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 <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <time.h>
+
+extern int usleep(int);
+extern void callout_process(int);
+extern void usb_idle(void);
+extern void usb_init(void);
+extern void usb_uninit(void);
+
+#define hz 1000
+
+#ifdef HAVE_MALLOC
+void *
+usb_malloc(size_t size)
+{
+ return (malloc(size));
+}
+
+void
+usb_free(void *ptr)
+{
+ free(ptr);
+}
+#endif
+
+void
+DELAY(unsigned int delay)
+{
+ usleep(delay);
+}
+
+void
+delay(unsigned int delay)
+{
+ usleep(delay);
+}
+
+int
+pause(const char *what, int timeout)
+{
+ if (timeout == 0)
+ timeout = 1;
+
+ usleep((1000000 / hz) * timeout);
+
+ return (0);
+}
+
+int
+main(int argc, char **argv)
+{
+ uint32_t time;
+
+ usb_init();
+
+ time = 0;
+
+ while (1) {
+
+ usb_idle();
+
+ usleep(1000);
+
+ if (++time >= (1000 / hz)) {
+ time = 0;
+ callout_process(1);
+ }
+ }
+
+ usb_uninit();
+
+ return (0);
+}
diff --git a/stand/usb/storage/umass_common.c b/stand/usb/storage/umass_common.c
new file mode 100644
index 0000000..5ddd159
--- /dev/null
+++ b/stand/usb/storage/umass_common.c
@@ -0,0 +1,90 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2014 Hans Petter Selasky <hselasky@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 USB_GLOBAL_INCLUDE_FILE
+
+#include "umass_common.h"
+
+struct usb_attach_arg umass_uaa;
+
+static device_probe_t umass_probe;
+static device_attach_t umass_attach;
+static device_detach_t umass_detach;
+
+static devclass_t umass_devclass;
+
+static device_method_t umass_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, umass_probe),
+ DEVMETHOD(device_attach, umass_attach),
+ DEVMETHOD(device_detach, umass_detach),
+
+ DEVMETHOD_END
+};
+
+static driver_t umass_driver = {
+ .name = "umass",
+ .methods = umass_methods,
+};
+
+DRIVER_MODULE(umass, uhub, umass_driver, umass_devclass, NULL, 0);
+
+static int
+umass_probe(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+
+ if (uaa->usb_mode != USB_MODE_HOST ||
+ uaa->info.bInterfaceClass != UICLASS_MASS ||
+ uaa->info.bInterfaceSubClass != UISUBCLASS_SCSI ||
+ uaa->info.bInterfaceProtocol != UIPROTO_MASS_BBB ||
+ device_get_unit(dev) != 0)
+ return (ENXIO);
+ return (0);
+}
+
+static int
+umass_attach(device_t dev)
+{
+ struct usb_attach_arg *uaa = device_get_ivars(dev);
+ umass_uaa = *uaa;
+ return (0); /* success */
+}
+
+static int
+umass_detach(device_t dev)
+{
+
+#ifdef USB_DEBUG
+ memset(&umass_uaa, 0, sizeof(umass_uaa));
+#endif
+ return (0);
+}
diff --git a/stand/usb/storage/umass_common.h b/stand/usb/storage/umass_common.h
new file mode 100644
index 0000000..a8ffd49
--- /dev/null
+++ b/stand/usb/storage/umass_common.h
@@ -0,0 +1,41 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2014 Hans Petter Selasky <hselasky@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 _UMASS_COMMON_H_
+#define _UMASS_COMMON_H_
+
+struct usb_attach_arg;
+struct devsw;
+
+extern struct usb_attach_arg umass_uaa;
+extern struct devsw umass_disk;
+
+#endif /* _UMASS_COMMON_H_ */
diff --git a/stand/usb/storage/umass_loader.c b/stand/usb/storage/umass_loader.c
new file mode 100644
index 0000000..fbb890b
--- /dev/null
+++ b/stand/usb/storage/umass_loader.c
@@ -0,0 +1,239 @@
+/* $FreeBSD$ */
+/*-
+ * Copyright (c) 2014 Hans Petter Selasky <hselasky@FreeBSD.org>
+ * All rights reserved.
+ *
+ * This software was developed by SRI International and the University of
+ * Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
+ * ("CTSRD"), as part of the DARPA CRASH research programme.
+ *
+ * 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 <sys/param.h>
+
+#include <bootstrap.h>
+#include <stdarg.h>
+
+#include <stand.h>
+#include <disk.h>
+
+#define HAVE_STANDARD_DEFS
+
+#include USB_GLOBAL_INCLUDE_FILE
+
+#include "umass_common.h"
+
+static int umass_disk_init(void);
+static int umass_disk_open(struct open_file *,...);
+static int umass_disk_close(struct open_file *);
+static void umass_disk_cleanup(void);
+static int umass_disk_ioctl(struct open_file *, u_long, void *);
+static int umass_disk_strategy(void *, int, daddr_t, size_t, char *, size_t *);
+static int umass_disk_print(int);
+
+struct devsw umass_disk = {
+ .dv_name = "umass",
+ .dv_type = DEVT_DISK,
+ .dv_init = umass_disk_init,
+ .dv_strategy = umass_disk_strategy,
+ .dv_open = umass_disk_open,
+ .dv_close = umass_disk_close,
+ .dv_ioctl = umass_disk_ioctl,
+ .dv_print = umass_disk_print,
+ .dv_cleanup = umass_disk_cleanup,
+};
+
+static int
+umass_disk_init(void)
+{
+ uint32_t time;
+
+ usb_init();
+ usb_needs_explore_all();
+
+ /* wait 8 seconds for a USB mass storage device to appear */
+ for (time = 0; time < (8 * hz); time++) {
+ usb_idle();
+ delay(1000000 / hz);
+ time++;
+ callout_process(1);
+ if (umass_uaa.device != NULL)
+ return (0);
+ }
+ return (0);
+}
+
+static int
+umass_disk_strategy(void *devdata, int flag, daddr_t dblk, size_t size,
+ char *buf, size_t *rsizep)
+{
+ if (umass_uaa.device == NULL)
+ return (ENXIO);
+ if (rsizep != NULL)
+ *rsizep = 0;
+
+ flag &= F_MASK;
+ if (flag == F_WRITE) {
+ if (usb_msc_write_10(umass_uaa.device, 0, dblk, size >> 9, buf) != 0)
+ return (EINVAL);
+ } else if (flag == F_READ) {
+ if (usb_msc_read_10(umass_uaa.device, 0, dblk, size >> 9, buf) != 0)
+ return (EINVAL);
+ } else {
+ return (EROFS);
+ }
+
+ if (rsizep != NULL)
+ *rsizep = size;
+ return (0);
+}
+
+static int
+umass_disk_open_sub(struct disk_devdesc *dev)
+{
+ uint32_t nblock;
+ uint32_t blocksize;
+
+ if (usb_msc_read_capacity(umass_uaa.device, 0, &nblock, &blocksize) != 0)
+ return (EINVAL);
+
+ return (disk_open(dev, ((uint64_t)nblock + 1) * (uint64_t)blocksize, blocksize));
+}
+
+static int
+umass_disk_open(struct open_file *f,...)
+{
+ va_list ap;
+ struct disk_devdesc *dev;
+
+ va_start(ap, f);
+ dev = va_arg(ap, struct disk_devdesc *);
+ va_end(ap);
+
+ if (umass_uaa.device == NULL)
+ return (ENXIO);
+ if (dev->d_unit != 0)
+ return (EIO);
+ return (umass_disk_open_sub(dev));
+}
+
+static int
+umass_disk_ioctl(struct open_file *f, u_long cmd, void *buf)
+{
+ struct disk_devdesc *dev;
+ uint32_t nblock;
+ uint32_t blocksize;
+ int rc;
+
+ dev = (struct disk_devdesc *)(f->f_devdata);
+ if (dev == NULL)
+ return (EINVAL);
+
+ rc = disk_ioctl(dev, cmd, buf);
+ if (rc != ENOTTY)
+ return (rc);
+
+ switch (cmd) {
+ case DIOCGSECTORSIZE:
+ case DIOCGMEDIASIZE:
+ if (usb_msc_read_capacity(umass_uaa.device, 0,
+ &nblock, &blocksize) != 0)
+ return (EINVAL);
+
+ if (cmd == DIOCGMEDIASIZE)
+ *(uint64_t*)buf = nblock;
+ else
+ *(uint32_t*)buf = blocksize;
+
+ return (0);
+ default:
+ return (ENXIO);
+ }
+}
+
+static int
+umass_disk_close(struct open_file *f)
+{
+ struct disk_devdesc *dev;
+
+ dev = (struct disk_devdesc *)f->f_devdata;
+ return (disk_close(dev));
+}
+
+static int
+umass_disk_print(int verbose)
+{
+ struct disk_devdesc dev;
+
+ printf("%s devices:", umass_disk.dv_name);
+ if (pager_output("\n") != 0)
+ return (1);
+
+ memset(&dev, 0, sizeof(dev));
+
+ ret = pager_output(" umass0 UMASS device\n");
+ if (ret != 0)
+ return (ret);
+ dev.d_dev = &umass_disk;
+ dev.d_unit = 0;
+ dev.d_slice = -1;
+ dev.d_partition = -1;
+
+ if (umass_disk_open_sub(&dev) == 0) {
+ ret = disk_print(&dev, " umass0", verbose);
+ disk_close(&dev);
+ }
+ return (ret);
+}
+
+static void
+umass_disk_cleanup(void)
+{
+
+ usb_uninit();
+}
+
+
+/* USB specific functions */
+
+extern void callout_process(int);
+extern void usb_idle(void);
+extern void usb_init(void);
+extern void usb_uninit(void);
+
+void
+DELAY(unsigned int usdelay)
+{
+ delay(usdelay);
+}
+
+int
+pause(const char *what, int timeout)
+{
+ if (timeout == 0)
+ timeout = 1;
+
+ delay((1000000 / hz) * timeout);
+
+ return (0);
+}
diff --git a/stand/usb/tools/Makefile b/stand/usb/tools/Makefile
new file mode 100644
index 0000000..64cf28c
--- /dev/null
+++ b/stand/usb/tools/Makefile
@@ -0,0 +1,10 @@
+# $FreeBSD$
+
+PROG= sysinit
+MAN=
+
+CFLAGS+= -I${.CURDIR}/../../kshim
+
+BINDIR?= /usr/bin
+
+.include <bsd.prog.mk>
diff --git a/stand/usb/tools/sysinit.c b/stand/usb/tools/sysinit.c
new file mode 100644
index 0000000..b968fe0
--- /dev/null
+++ b/stand/usb/tools/sysinit.c
@@ -0,0 +1,331 @@
+/* $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.
+ */
+
+/*
+ * This utility sorts sysinit structure entries in binary format and
+ * prints out the result in C-format.
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include <stdlib.h>
+#include <err.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <sysexits.h>
+#include "sysinit.h"
+
+static int opt_R;
+static const char *input_f;
+static const char *output_f;
+static const char *struct_name;
+static const char *keyword;
+static struct sysinit_data **start;
+static struct sysinit_data **stop;
+
+static int input_file = -1;
+static int output_file = -1;
+
+static uint8_t *input_ptr;
+static uint32_t input_len;
+
+static uint32_t endian32;
+
+static char scratch_buf[4096];
+
+static int success;
+
+static void do_sysinit(void);
+
+/* the following function converts the numbers into host endian format */
+
+static uint32_t
+read32(uint32_t val)
+{
+ uint32_t temp;
+ uint32_t endian;
+
+ endian = endian32;
+ temp = 0;
+
+ while (val) {
+ temp |= (val & 0xF) << ((endian & 0xF) * 4);
+ endian >>= 4;
+ val >>= 4;
+ }
+ return (temp);
+}
+
+static void
+do_write(int fd, const char *buf)
+{
+ int len = strlen(buf);
+
+ if (write(fd, buf, len) != len)
+ err(EX_SOFTWARE, "Could not write to output file");
+}
+
+static void *
+do_malloc(int size)
+{
+ void *ptr;
+
+ ptr = malloc(size);
+ if (ptr == NULL)
+ errx(EX_SOFTWARE, "Could not allocate memory");
+ return (ptr);
+}
+
+static void
+usage(void)
+{
+ errx(EX_USAGE, "sysinit -i sysinit.bin -o sysinit_data.c \\\n"
+ "\t" "-k sysinit -s sysinit_data [ -R (reverse)]");
+}
+
+static void
+cleanup(void)
+{
+ if (output_file >= 0)
+ close(output_file);
+ if (input_file >= 0)
+ close(input_file);
+ if (success == 0) {
+ if (output_f)
+ unlink(output_f);
+ }
+}
+
+static int
+compare(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (-1);
+
+ return (0); /* equal */
+}
+
+static int
+compare_R(const void *_pa, const void *_pb)
+{
+ const struct sysinit_data * const *pa = _pa;
+ const struct sysinit_data * const *pb = _pb;
+
+ if ((*pa)->dw_msb_value > (*pb)->dw_msb_value)
+ return (-1);
+
+ if ((*pa)->dw_msb_value < (*pb)->dw_msb_value)
+ return (1);
+
+ if ((*pa)->dw_lsb_value > (*pb)->dw_lsb_value)
+ return (-1);
+
+ if ((*pa)->dw_lsb_value < (*pb)->dw_lsb_value)
+ return (1);
+
+ return (0); /* equal */
+}
+
+int
+main(int argc, char **argv)
+{
+ struct sysinit_data **sipp;
+ int c;
+ int entries;
+ off_t off;
+
+ while ((c = getopt(argc, argv, "k:s:i:o:Rh")) != -1) {
+ switch (c) {
+ case 'i':
+ input_f = optarg;
+ break;
+ case 'o':
+ output_f = optarg;
+ break;
+ case 'R':
+ opt_R = 1;
+ break;
+ case 'k':
+ keyword = optarg;
+ break;
+ case 's':
+ struct_name = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ if (input_f == NULL || output_f == NULL ||
+ struct_name == NULL || keyword == NULL)
+ usage();
+
+ atexit(&cleanup);
+
+ cleanup();
+
+ input_file = open(input_f, O_RDONLY);
+ if (input_file < 0)
+ err(EX_SOFTWARE, "Could not open input file: %s", input_f);
+
+ output_file = open(output_f, O_TRUNC | O_CREAT | O_RDWR, 0600);
+ if (output_file < 0)
+ err(EX_SOFTWARE, "Could not open output file: %s", output_f);
+
+ off = lseek(input_file, 0, SEEK_END);
+
+ input_ptr = do_malloc(off);
+ input_len = off;
+
+ if (input_len % (uint32_t)sizeof(struct sysinit_data)) {
+ errx(EX_SOFTWARE, "Input file size is not divisible by %u",
+ (unsigned int)sizeof(struct sysinit_data));
+ }
+ off = lseek(input_file, 0, SEEK_SET);
+ if (off < 0)
+ err(EX_SOFTWARE, "Could not seek to start of input file");
+
+ if (read(input_file, input_ptr, input_len) != input_len)
+ err(EX_SOFTWARE, "Could not read input file");
+
+ entries = input_len / (uint32_t)sizeof(struct sysinit_data);
+
+ start = do_malloc(sizeof(void *) * entries);
+ stop = start + entries;
+
+ for (c = 0; c != entries; c++)
+ start[c] = &((struct sysinit_data *)input_ptr)[c];
+
+ if (start != stop)
+ endian32 = (*start)->dw_endian32;
+
+ /* switch all fields to host endian order */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->dw_lsb_value = read32((*sipp)->dw_lsb_value);
+ (*sipp)->dw_msb_value = read32((*sipp)->dw_msb_value);
+ (*sipp)->dw_file_line = read32((*sipp)->dw_file_line);
+ }
+
+ if (opt_R == 0) {
+ /* sort entries, rising numerical order */
+ qsort(start, entries, sizeof(void *), &compare);
+ } else {
+ /* sort entries, falling numerical order */
+ qsort(start, entries, sizeof(void *), &compare_R);
+ }
+
+ /* safe all strings */
+ for (sipp = start; sipp < stop; sipp++) {
+ (*sipp)->b_keyword_name[sizeof((*sipp)->b_keyword_name) - 1] = 0;
+ (*sipp)->b_global_type[sizeof((*sipp)->b_global_type) - 1] = 0;
+ (*sipp)->b_global_name[sizeof((*sipp)->b_global_name) - 1] = 0;
+ (*sipp)->b_file_name[sizeof((*sipp)->b_file_name) - 1] = 0;
+ (*sipp)->b_debug_info[sizeof((*sipp)->b_debug_info) - 1] = 0;
+ }
+
+ if (strcmp(keyword, "sysinit") == 0)
+ do_sysinit();
+ else if (strcmp(keyword, "sysuninit") == 0)
+ do_sysinit();
+ else
+ errx(EX_USAGE, "Unknown keyword '%s'", keyword);
+
+ success = 1;
+
+ return (0);
+}
+
+static void
+do_sysinit(void)
+{
+ struct sysinit_data **sipp;
+ int c;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/*\n"
+ " * This file was automatically generated.\n"
+ " * Please do not edit.\n"
+ " */\n\n");
+
+ /* write out externals */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "/* #%04u: %s entry at %s:%u */\n",
+ c, (*sipp)->b_debug_info, (*sipp)->b_file_name,
+ (unsigned int)(*sipp)->dw_file_line);
+
+ do_write(output_file, scratch_buf);
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "extern %s %s;\n\n", (*sipp)->b_global_type,
+ (*sipp)->b_global_name);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "const void *%s[] = {\n", struct_name);
+
+ do_write(output_file, scratch_buf);
+
+ /* write out actual table */
+ for (c = 0, sipp = start; sipp < stop; c++, sipp++) {
+ if (strcmp((const char *)(*sipp)->b_keyword_name, keyword))
+ continue;
+ if ((*sipp)->dw_msb_value == 0)
+ continue;
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t&%s, /* #%04u */\n",
+ (*sipp)->b_global_name, (unsigned int)c);
+
+ do_write(output_file, scratch_buf);
+ }
+
+ snprintf(scratch_buf, sizeof(scratch_buf),
+ "\t(const void *)0\n"
+ "};\n");
+
+ do_write(output_file, scratch_buf);
+}
diff --git a/stand/usb/usb_busdma_loader.c b/stand/usb/usb_busdma_loader.c
new file mode 100644
index 0000000..90dc169
--- /dev/null
+++ b/stand/usb/usb_busdma_loader.c
@@ -0,0 +1,619 @@
+/* $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 <bsd_global.h>
+
+#if USB_HAVE_BUSDMA
+static void usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length);
+#endif
+
+/*------------------------------------------------------------------------*
+ * usbd_get_page - lookup DMA-able memory for the given offset
+ *
+ * NOTE: Only call this function when the "page_cache" structure has
+ * been properly initialized !
+ *------------------------------------------------------------------------*/
+void
+usbd_get_page(struct usb_page_cache *pc, usb_frlength_t offset,
+ struct usb_page_search *res)
+{
+#if USB_HAVE_BUSDMA
+ struct usb_page *page;
+
+ if (pc->page_start) {
+
+ /* Case 1 - something has been loaded into DMA */
+
+ if (pc->buffer) {
+
+ /* Case 1a - Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ }
+ offset += pc->page_offset_buf;
+
+ /* compute destination page */
+
+ page = pc->page_start;
+
+ if (pc->ismultiseg) {
+
+ page += (offset / USB_PAGE_SIZE);
+
+ offset %= USB_PAGE_SIZE;
+
+ res->length = USB_PAGE_SIZE - offset;
+ res->physaddr = page->physaddr + offset;
+ } else {
+ res->length = (usb_size_t)-1;
+ res->physaddr = page->physaddr + offset;
+ }
+ if (!pc->buffer) {
+
+ /* Case 1b - Non Kernel Virtual Address */
+
+ res->buffer = USB_ADD_BYTES(page->buffer, offset);
+ }
+ return;
+ }
+#endif
+ /* Case 2 - Plain PIO */
+
+ res->buffer = USB_ADD_BYTES(pc->buffer, offset);
+ res->length = (usb_size_t)-1;
+#if USB_HAVE_BUSDMA
+ res->physaddr = 0;
+#endif
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_in - copy directly to DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_in(struct usb_page_cache *cache, usb_frlength_t offset,
+ const void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search buf_res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &buf_res);
+
+ if (buf_res.length > len) {
+ buf_res.length = len;
+ }
+ memcpy(buf_res.buffer, ptr, buf_res.length);
+
+ offset += buf_res.length;
+ len -= buf_res.length;
+ ptr = USB_ADD_BYTES(ptr, buf_res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_copy_out - copy directly from DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_copy_out(struct usb_page_cache *cache, usb_frlength_t offset,
+ void *ptr, usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memcpy(ptr, res.buffer, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ ptr = USB_ADD_BYTES(ptr, res.length);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usbd_frame_zero - zero DMA-able memory
+ *------------------------------------------------------------------------*/
+void
+usbd_frame_zero(struct usb_page_cache *cache, usb_frlength_t offset,
+ usb_frlength_t len)
+{
+ struct usb_page_search res;
+
+ while (len != 0) {
+
+ usbd_get_page(cache, offset, &res);
+
+ if (res.length > len) {
+ res.length = len;
+ }
+ memset(res.buffer, 0, res.length);
+
+ offset += res.length;
+ len -= res.length;
+ }
+}
+
+#if USB_HAVE_BUSDMA
+
+/*------------------------------------------------------------------------*
+ * usb_pc_common_mem_cb - BUS-DMA callback function
+ *------------------------------------------------------------------------*/
+static void
+usb_pc_common_mem_cb(struct usb_page_cache *pc,
+ void *vaddr, uint32_t length)
+{
+ struct usb_page *pg;
+ usb_size_t rem;
+ bus_size_t off;
+ bus_addr_t phys = (uintptr_t)vaddr; /* XXX */
+ uint32_t nseg;
+
+ if (length == 0)
+ nseg = 1;
+ else
+ nseg = ((length + USB_PAGE_SIZE - 1) / USB_PAGE_SIZE);
+
+ pg = pc->page_start;
+ pg->physaddr = phys & ~(USB_PAGE_SIZE - 1);
+ rem = phys & (USB_PAGE_SIZE - 1);
+ pc->page_offset_buf = rem;
+ pc->page_offset_end += rem;
+ length += rem;
+
+ for (off = USB_PAGE_SIZE; off < length; off += USB_PAGE_SIZE) {
+ pg++;
+ pg->physaddr = (phys + off) & ~(USB_PAGE_SIZE - 1);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_alloc_mem - allocate DMA'able memory
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_alloc_mem(struct usb_page_cache *pc, struct usb_page *pg,
+ usb_size_t size, usb_size_t align)
+{
+ void *ptr;
+ uint32_t rem;
+
+ /* allocate zeroed memory */
+
+ if (align != 1) {
+ ptr = malloc(size + align, XXX, XXX);
+ if (ptr == NULL)
+ goto error;
+
+ rem = (-((uintptr_t)ptr)) & (align - 1);
+ } else {
+ ptr = malloc(size, XXX, XXX);
+ if (ptr == NULL)
+ goto error;
+ rem = 0;
+ }
+
+ /* setup page cache */
+ pc->buffer = ((uint8_t *)ptr) + rem;
+ pc->page_start = pg;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->map = NULL;
+ pc->tag = ptr;
+ pc->ismultiseg = (align == 1);
+
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, pc->buffer, size);
+
+ usb_pc_cpu_flush(pc);
+ return (0);
+
+error:
+ /* reset most of the page cache */
+ pc->buffer = NULL;
+ pc->page_start = NULL;
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = 0;
+ pc->map = NULL;
+ pc->tag = NULL;
+ return (1);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_free_mem - free DMA memory
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_free_mem(struct usb_page_cache *pc)
+{
+ if (pc != NULL && pc->buffer != NULL) {
+ free(pc->tag, XXX);
+ pc->buffer = NULL;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_load_mem - load virtual memory into DMA
+ *
+ * Return values:
+ * 0: Success
+ * Else: Error
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_load_mem(struct usb_page_cache *pc, usb_size_t size, uint8_t sync)
+{
+ /* setup page cache */
+ pc->page_offset_buf = 0;
+ pc->page_offset_end = size;
+ pc->ismultiseg = 1;
+
+ mtx_assert(pc->tag_parent->mtx, MA_OWNED);
+
+ if (size > 0) {
+ /* compute physical address */
+ usb_pc_common_mem_cb(pc, pc->buffer, size);
+ }
+ if (sync == 0) {
+ /*
+ * Call callback so that refcount is decremented
+ * properly:
+ */
+ pc->tag_parent->dma_error = 0;
+ (pc->tag_parent->func) (pc->tag_parent);
+ }
+ return (0);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_invalidate - invalidate CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_invalidate(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_cpu_flush - flush CPU cache
+ *------------------------------------------------------------------------*/
+void
+usb_pc_cpu_flush(struct usb_page_cache *pc)
+{
+ if (pc->page_offset_end == pc->page_offset_buf) {
+ /* nothing has been loaded into this page cache! */
+ return;
+ }
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_create - create a DMA map
+ *
+ * Returns:
+ * 0: Success
+ * Else: Failure
+ *------------------------------------------------------------------------*/
+uint8_t
+usb_pc_dmamap_create(struct usb_page_cache *pc, usb_size_t size)
+{
+ return (0); /* NOP, success */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_pc_dmamap_destroy
+ *
+ * This function is NULL safe.
+ *------------------------------------------------------------------------*/
+void
+usb_pc_dmamap_destroy(struct usb_page_cache *pc)
+{
+ /* NOP */
+}
+
+/*------------------------------------------------------------------------*
+ * usb_dma_tag_setup - initialise USB DMA tags
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_setup(struct usb_dma_parent_tag *udpt,
+ struct usb_dma_tag *udt, bus_dma_tag_t dmat,
+ struct mtx *mtx, usb_dma_callback_t *func,
+ uint8_t ndmabits, uint8_t nudt)
+{
+ memset(udpt, 0, sizeof(*udpt));
+
+ /* sanity checking */
+ if ((nudt == 0) ||
+ (ndmabits == 0) ||
+ (mtx == NULL)) {
+ /* something is corrupt */
+ return;
+ }
+ /* initialise condition variable */
+ cv_init(udpt->cv, "USB DMA CV");
+
+ /* store some information */
+ udpt->mtx = mtx;
+ udpt->func = func;
+ udpt->tag = dmat;
+ udpt->utag_first = udt;
+ udpt->utag_max = nudt;
+ udpt->dma_bits = ndmabits;
+
+ while (nudt--) {
+ memset(udt, 0, sizeof(*udt));
+ udt->tag_parent = udpt;
+ udt++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bus_tag_unsetup - factored out code
+ *------------------------------------------------------------------------*/
+void
+usb_dma_tag_unsetup(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_dma_tag *udt;
+ uint8_t nudt;
+
+ udt = udpt->utag_first;
+ nudt = udpt->utag_max;
+
+ while (nudt--) {
+ udt->align = 0;
+ udt++;
+ }
+
+ if (udpt->utag_max) {
+ /* destroy the condition variable */
+ cv_destroy(udpt->cv);
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_work_loop
+ *
+ * This function handles loading of virtual buffers into DMA and is
+ * only called when "dma_refcount" is zero.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_work_loop(struct usb_xfer_queue *pq)
+{
+ struct usb_xfer_root *info;
+ struct usb_xfer *xfer;
+ usb_frcount_t nframes;
+
+ xfer = pq->curr;
+ info = xfer->xroot;
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ if (xfer->error) {
+ /* some error happened */
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, 0);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (!xfer->flags_int.bdma_setup) {
+ struct usb_page *pg;
+ usb_frlength_t frlength_0;
+ uint8_t isread;
+
+ xfer->flags_int.bdma_setup = 1;
+
+ /* reset BUS-DMA load state */
+
+ info->dma_error = 0;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ frlength_0 = xfer->sumlen;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ frlength_0 = xfer->frlengths[0];
+ }
+
+ /*
+ * Set DMA direction first. This is needed to
+ * select the correct cache invalidate and cache
+ * flush operations.
+ */
+ isread = USB_GET_DATA_ISREAD(xfer);
+ pg = xfer->dma_page_ptr;
+
+ if (xfer->flags_int.control_xfr &&
+ xfer->flags_int.control_hdr) {
+ /* special case */
+ if (xfer->flags_int.usb_mode == USB_MODE_DEVICE) {
+ /* The device controller writes to memory */
+ xfer->frbuffers[0].isread = 1;
+ } else {
+ /* The host controller reads from memory */
+ xfer->frbuffers[0].isread = 0;
+ }
+ } else {
+ /* default case */
+ xfer->frbuffers[0].isread = isread;
+ }
+
+ /*
+ * Setup the "page_start" pointer which points to an array of
+ * USB pages where information about the physical address of a
+ * page will be stored. Also initialise the "isread" field of
+ * the USB page caches.
+ */
+ xfer->frbuffers[0].page_start = pg;
+
+ info->dma_nframes = nframes;
+ info->dma_currframe = 0;
+ info->dma_frlength_0 = frlength_0;
+
+ pg += (frlength_0 / USB_PAGE_SIZE);
+ pg += 2;
+
+ while (--nframes > 0) {
+ xfer->frbuffers[nframes].isread = isread;
+ xfer->frbuffers[nframes].page_start = pg;
+
+ pg += (xfer->frlengths[nframes] / USB_PAGE_SIZE);
+ pg += 2;
+ }
+
+ }
+ if (info->dma_error) {
+ USB_BUS_LOCK(info->bus);
+ usbd_transfer_done(xfer, USB_ERR_DMA_LOAD_FAILED);
+ USB_BUS_UNLOCK(info->bus);
+ return;
+ }
+ if (info->dma_currframe != info->dma_nframes) {
+
+ if (info->dma_currframe == 0) {
+ /* special case */
+ usb_pc_load_mem(xfer->frbuffers,
+ info->dma_frlength_0, 0);
+ } else {
+ /* default case */
+ nframes = info->dma_currframe;
+ usb_pc_load_mem(xfer->frbuffers + nframes,
+ xfer->frlengths[nframes], 0);
+ }
+
+ /* advance frame index */
+ info->dma_currframe++;
+
+ return;
+ }
+ /* go ahead */
+ usb_bdma_pre_sync(xfer);
+
+ /* start loading next USB transfer, if any */
+ usb_command_wrapper(pq, NULL);
+
+ /* finally start the hardware */
+ usbd_pipe_enter(xfer);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_done_event
+ *
+ * This function is called when the BUS-DMA has loaded virtual memory
+ * into DMA, if any.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_done_event(struct usb_dma_parent_tag *udpt)
+{
+ struct usb_xfer_root *info;
+
+ info = USB_DMATAG_TO_XROOT(udpt);
+
+ mtx_assert(info->xfer_mtx, MA_OWNED);
+
+ /* copy error */
+ info->dma_error = udpt->dma_error;
+
+ /* enter workloop again */
+ usb_command_wrapper(&info->dma_q,
+ info->dma_q.curr);
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_pre_sync
+ *
+ * This function handles DMA synchronisation that must be done before
+ * an USB transfer is started.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_pre_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ } else {
+ usb_pc_cpu_flush(pc);
+ }
+ pc++;
+ }
+}
+
+/*------------------------------------------------------------------------*
+ * usb_bdma_post_sync
+ *
+ * This function handles DMA synchronisation that must be done after
+ * an USB transfer is complete.
+ *------------------------------------------------------------------------*/
+void
+usb_bdma_post_sync(struct usb_xfer *xfer)
+{
+ struct usb_page_cache *pc;
+ usb_frcount_t nframes;
+
+ if (xfer->flags_int.isochronous_xfr) {
+ /* only one frame buffer */
+ nframes = 1;
+ } else {
+ /* can be multiple frame buffers */
+ nframes = xfer->nframes;
+ }
+
+ pc = xfer->frbuffers;
+
+ while (nframes--) {
+ if (pc->isread) {
+ usb_pc_cpu_invalidate(pc);
+ }
+ pc++;
+ }
+}
+#endif
diff --git a/stand/usb/usbcore.mk b/stand/usb/usbcore.mk
new file mode 100644
index 0000000..153a1d4
--- /dev/null
+++ b/stand/usb/usbcore.mk
@@ -0,0 +1,175 @@
+#
+# $FreeBSD$
+#
+# Copyright (c) 2013 Hans Petter Selasky.
+# Copyright (c) 2014 SRI International
+# All rights reserved.
+#
+# This software was developed by SRI International and the University of
+# Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
+# ("CTSRD"), as part of the DARPA CRASH research programme.
+#
+# 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.
+#
+
+USBCOREDIR:= ${.PARSEDIR}
+S=${USBCOREDIR}/../..
+
+MACHDEP_DIRS=
+
+.if defined(HAVE_EXYNOS_EHCI)
+MACHDEP_DIRS+= ${S}/arm/samsung/exynos
+.endif
+
+.PATH: \
+ ${USBCOREDIR} \
+ ${USBCOREDIR}/storage \
+ ${S}/dev/usb \
+ ${S}/dev/usb/controller \
+ ${S}/dev/usb/serial \
+ ${S}/dev/usb/storage \
+ ${S}/dev/usb/template \
+ ${MACHDEP_DIRS}
+.undef S
+
+USB_POOL_SIZE?= 131072
+
+CFLAGS+= -DUSB_MSCTEST_BULK_SIZE=65536
+CFLAGS+= -DUSB_POOL_SIZE=${USB_POOL_SIZE}
+
+
+#
+# BUSDMA implementation
+#
+SRCS+= usb_busdma_loader.c
+
+#
+# USB controller drivers
+#
+
+KSRCS+= usb_controller.c
+
+.if defined(HAVE_AT91DCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"at91dci\""
+KSRCS+= at91dci.c
+.endif
+
+.if defined(HAVE_ATMEGADCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"atmegadci\""
+KSRCS+= atmegadci.c
+.endif
+
+.if defined(HAVE_AVR32DCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"avr32dci\""
+KSRCS+= avr32dci.c
+.endif
+
+.if defined(HAVE_DWCOTG)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"dwcotg\""
+KSRCS+= dwcotg.c
+.endif
+
+.if defined(HAVE_MUSBOTG)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"musbotg\""
+KSRCS+= musbotg.c
+.endif
+
+.if defined(HAVE_EHCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"ehci\""
+KSRCS+= ehci.c
+.endif
+
+.if defined(HAVE_EXYNOS_EHCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"combiner\", \"pad\", \"ehci\""
+KSRCS+= ehci.c
+KSRCS+= exynos5_combiner.c
+KSRCS+= exynos5_pad.c
+KSRCS+= exynos5_ehci.c
+.endif
+
+.if defined(HAVE_OHCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"ohci\""
+KSRCS+= ohci.c
+.endif
+
+.if defined(HAVE_UHCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"uhci\""
+KSRCS+= uhci.c
+.endif
+
+.if defined(HAVE_XHCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"xhci\""
+KSRCS+= xhci.c
+.endif
+
+.if defined(HAVE_USS820DCI)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"uss820dci\""
+KSRCS+= uss820dci.c
+.endif
+
+.if defined(HAVE_SAF1761OTG)
+CFLAGS += -DUSB_PCI_PROBE_LIST="\"saf1761otg\""
+CFLAGS += -DUSB_PCI_MEMORY_ADDRESS=0x900000007f100000ULL
+CFLAGS += -DUSB_PCI_MEMORY_SIZE=0x40000U
+KSRCS+= saf1761_otg.c
+KSRCS+= saf1761_otg_boot.c
+.endif
+
+#
+# USB core and templates
+#
+KSRCS+= usb_core.c
+KSRCS+= usb_debug.c
+KSRCS+= usb_device.c
+KSRCS+= usb_dynamic.c
+KSRCS+= usb_error.c
+KSRCS+= usb_handle_request.c
+KSRCS+= usb_hid.c
+KSRCS+= usb_hub.c
+KSRCS+= usb_lookup.c
+KSRCS+= usb_msctest.c
+KSRCS+= usb_parse.c
+KSRCS+= usb_request.c
+KSRCS+= usb_transfer.c
+KSRCS+= usb_util.c
+KSRCS+= usb_template.c
+KSRCS+= usb_template_cdce.c
+KSRCS+= usb_template_msc.c
+KSRCS+= usb_template_mtp.c
+KSRCS+= usb_template_modem.c
+KSRCS+= usb_template_mouse.c
+KSRCS+= usb_template_kbd.c
+KSRCS+= usb_template_audio.c
+KSRCS+= usb_template_phone.c
+KSRCS+= usb_template_serialnet.c
+KSRCS+= usb_template_midi.c
+
+#
+# USB mass storage support
+#
+SRCS+= umass_common.c
+
+.if defined(HAVE_UMASS_LOADER)
+CFLAGS+= -I${.CURDIR}/../common
+SRCS+= umass_loader.c
+.endif
+
OpenPOWER on IntegriCloud