diff --git a/Makefile.inc1 b/Makefile.inc1 index 15e5fd8..0080ed7 100644 --- a/Makefile.inc1 +++ b/Makefile.inc1 @@ -1424,7 +1424,8 @@ cross-tools: .MAKE usr.bin/xlint/lint1 usr.bin/xlint/lint2 usr.bin/xlint/xlint \ ${_btxld} \ ${_crunchide} \ - ${_kgzip} + ${_kgzip} \ + usr.bin/sysinit ${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \ cd ${.CURDIR}/${_tool} && \ ${MAKE} DIRPRFX=${_tool}/ obj && \ diff --git a/sys/boot/kshim/bsd_busspace.c b/sys/boot/kshim/bsd_busspace.c new file mode 100644 index 0000000..c9ba09f --- /dev/null +++ b/sys/boot/kshim/bsd_busspace.c @@ -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; + } +} diff --git a/sys/boot/kshim/bsd_global.h b/sys/boot/kshim/bsd_global.h new file mode 100644 index 0000000..2fb0dcc --- /dev/null +++ b/sys/boot/kshim/bsd_global.h @@ -0,0 +1,65 @@ +/* $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 + +extern struct usb_process usb_process[USB_PROC_MAX]; + +#endif /* _BSD_GLOBAL_H_ */ diff --git a/sys/boot/kshim/bsd_kernel.c b/sys/boot/kshim/bsd_kernel.c new file mode 100644 index 0000000..d41b9f4 --- /dev/null +++ b/sys/boot/kshim/bsd_kernel.c @@ -0,0 +1,1239 @@ +/* $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 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, driver_filter_t *filter, + driver_intr_t *fn, void *arg) +{ + dev->dev_irq_filter = filter; + 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) { + int status; + if (child->dev_irq_filter != NULL) + status = child->dev_irq_filter(child->dev_irq_arg); + else + status = FILTER_SCHEDULE_THREAD; + + if (status == FILTER_SCHEDULE_THREAD) { + 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); +} + +static void +devclass_delete_device(const struct module_data *mod, device_t dev) +{ + if (mod == NULL) { + return; + } + mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL; + dev->dev_module = NULL; +} + +static device_t +make_device(device_t parent, const char *name) +{ + device_t dev = NULL; + const struct module_data *mod = NULL; + + if (name) { + + mod = devclass_find_create(name); + + if (!mod) { + + DPRINTF("%s:%d:%s: can't find device " + "class %s\n", __FILE__, __LINE__, + __FUNCTION__, name); + + goto done; + } + } + dev = malloc(sizeof(*dev), + M_DEVBUF, M_WAITOK | M_ZERO); + + if (dev == NULL) + goto done; + + dev->dev_parent = parent; + TAILQ_INIT(&dev->dev_children); + + if (name) { + dev->dev_fixed_class = 1; + if (devclass_add_device(mod, dev)) { + goto error; + } + } +done: + return (dev); + +error: + if (dev) { + free(dev, M_DEVBUF); + } + return (NULL); +} + +device_t +device_add_child(device_t dev, const char *name, int unit) +{ + device_t child; + + if (unit != -1) { + device_printf(dev, "Unit is not -1\n"); + } + child = make_device(dev, name); + if (child == NULL) { + device_printf(dev, "Could not add child '%s'\n", name); + goto done; + } + if (dev == NULL) { + /* no parent */ + goto done; + } + TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link); +done: + return (child); +} + +int +device_delete_child(device_t dev, device_t child) +{ + int error = 0; + device_t grandchild; + + /* remove children first */ + + while ((grandchild = TAILQ_FIRST(&child->dev_children))) { + error = device_delete_child(child, grandchild); + if (error) { + device_printf(dev, "Error deleting child!\n"); + goto done; + } + } + + error = device_detach(child); + + if (error) + goto done; + + devclass_delete_device(child->dev_module, child); + + if (dev != NULL) { + /* remove child from parent */ + TAILQ_REMOVE(&dev->dev_children, child, dev_link); + } + free(child, M_DEVBUF); + +done: + return (error); +} + +int +device_delete_children(device_t dev) +{ + device_t child; + int error = 0; + + while ((child = TAILQ_FIRST(&dev->dev_children))) { + error = device_delete_child(dev, child); + if (error) { + device_printf(dev, "Error deleting child!\n"); + break; + } + } + return (error); +} + +void +device_quiet(device_t dev) +{ + dev->dev_quiet = 1; +} + +const char * +device_get_desc(device_t dev) +{ + if (dev) + return &(dev->dev_desc[0]); + return (unknown_string); +} + +static int +default_method(void) +{ + /* do nothing */ + DPRINTF("Default method called\n"); + return (0); +} + +void * +device_get_method(device_t dev, const char *what) +{ + const struct device_method *mtod; + + mtod = dev->dev_module->driver->methods; + while (mtod->func != NULL) { + if (devclass_equal(mtod->desc, what)) { + return (mtod->func); + } + mtod++; + } + return ((void *)&default_method); +} + +const char * +device_get_name(device_t dev) +{ + if (dev == NULL) + return (unknown_string); + + return (dev->dev_module->driver->name); +} + +static int +device_allocate_softc(device_t dev) +{ + const struct module_data *mod; + + mod = dev->dev_module; + + if ((dev->dev_softc_alloc == 0) && + (mod->driver->size != 0)) { + dev->dev_sc = malloc(mod->driver->size, + M_DEVBUF, M_WAITOK | M_ZERO); + + if (dev->dev_sc == NULL) + return (ENOMEM); + + dev->dev_softc_alloc = 1; + } + return (0); +} + +int +device_probe_and_attach(device_t dev) +{ + const struct module_data *mod; + const char *bus_name_parent; + + bus_name_parent = device_get_name(device_get_parent(dev)); + + if (dev->dev_attached) + return (0); /* fail-safe */ + + if (dev->dev_fixed_class) { + + mod = dev->dev_module; + + if (DEVICE_PROBE(dev) <= 0) { + + if (device_allocate_softc(dev) == 0) { + + if (DEVICE_ATTACH(dev) == 0) { + /* success */ + dev->dev_attached = 1; + return (0); + } + } + } + device_detach(dev); + + goto error; + } + /* + * Else find a module for our device, if any + */ + + TAILQ_FOREACH(mod, &module_head, entry) { + if (devclass_equal(mod->bus_name, bus_name_parent)) { + if (devclass_create(mod->devclass_pp)) { + continue; + } + if (devclass_add_device(mod, dev)) { + continue; + } + if (DEVICE_PROBE(dev) <= 0) { + + if (device_allocate_softc(dev) == 0) { + + if (DEVICE_ATTACH(dev) == 0) { + /* success */ + dev->dev_attached = 1; + return (0); + } + } + } + /* else try next driver */ + + device_detach(dev); + } + } + +error: + return (ENODEV); +} + +int +device_detach(device_t dev) +{ + const struct module_data *mod = dev->dev_module; + int error; + + if (dev->dev_attached) { + + error = DEVICE_DETACH(dev); + if (error) { + return error; + } + dev->dev_attached = 0; + } + device_set_softc(dev, NULL); + + if (dev->dev_fixed_class == 0) + devclass_delete_device(mod, dev); + + return (0); +} + +void +device_set_softc(device_t dev, void *softc) +{ + if (dev->dev_softc_alloc) { + free(dev->dev_sc, M_DEVBUF); + dev->dev_sc = NULL; + } + dev->dev_sc = softc; + dev->dev_softc_alloc = 0; +} + +void * +device_get_softc(device_t dev) +{ + if (dev == NULL) + return (NULL); + + return (dev->dev_sc); +} + +int +device_is_attached(device_t dev) +{ + return (dev->dev_attached); +} + +void +device_set_desc(device_t dev, const char *desc) +{ + snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc); +} + +void +device_set_desc_copy(device_t dev, const char *desc) +{ + device_set_desc(dev, desc); +} + +void * +devclass_get_softc(devclass_t dc, int unit) +{ + return (device_get_softc(devclass_get_device(dc, unit))); +} + +int +devclass_get_maxunit(devclass_t dc) +{ + int max_unit = 0; + + if (dc) { + max_unit = DEVCLASS_MAXUNIT; + while (max_unit--) { + if (dc->dev_list[max_unit]) { + break; + } + } + max_unit++; + } + return (max_unit); +} + +device_t +devclass_get_device(devclass_t dc, int unit) +{ + return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? + NULL : dc->dev_list[unit]); +} + +devclass_t +devclass_find(const char *classname) +{ + const struct module_data *mod; + + TAILQ_FOREACH(mod, &module_head, entry) { + if (devclass_equal(mod->mod_name, classname)) + return (mod->devclass_pp[0]); + } + return (NULL); +} + +void +module_register(void *data) +{ + struct module_data *mdata = data; + + TAILQ_INSERT_TAIL(&module_head, mdata, entry); +} + +/*------------------------------------------------------------------------* + * System startup + *------------------------------------------------------------------------*/ + +static void +sysinit_run(const void **ppdata) +{ + const struct sysinit *psys; + + while ((psys = *ppdata) != NULL) { + (psys->func) (psys->data); + ppdata++; + } +} + +/*------------------------------------------------------------------------* + * USB process API + *------------------------------------------------------------------------*/ + +static int usb_do_process(struct usb_process *); +static int usb_proc_level = -1; +static struct mtx usb_proc_mtx; + +void +usb_idle(void) +{ + int old_level = usb_proc_level; + int old_giant = Giant.owned; + int worked; + + device_run_interrupts(usb_pci_root); + + do { + worked = 0; + Giant.owned = 0; + + while (++usb_proc_level < USB_PROC_MAX) + worked |= usb_do_process(usb_process + usb_proc_level); + + usb_proc_level = old_level; + Giant.owned = old_giant; + + } while (worked); +} + +void +usb_init(void) +{ + sysinit_run(sysinit_data); +} + +void +usb_uninit(void) +{ + sysinit_run(sysuninit_data); +} + +static void +usb_process_init_sub(struct usb_process *up) +{ + TAILQ_INIT(&up->up_qhead); + + cv_init(&up->up_cv, "-"); + cv_init(&up->up_drain, "usbdrain"); + + up->up_mtx = &usb_proc_mtx; +} + +static void +usb_process_init(void *arg) +{ + uint8_t x; + + mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE); + + for (x = 0; x != USB_PROC_MAX; x++) + usb_process_init_sub(&usb_process[x]); + +} +SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL); + +static int +usb_do_process(struct usb_process *up) +{ + struct usb_proc_msg *pm; + int worked = 0; + + mtx_lock(&usb_proc_mtx); + +repeat: + pm = TAILQ_FIRST(&up->up_qhead); + + if (pm != NULL) { + + worked = 1; + + (pm->pm_callback) (pm); + + if (pm == TAILQ_FIRST(&up->up_qhead)) { + /* nothing changed */ + TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); + pm->pm_qentry.tqe_prev = NULL; + } + goto repeat; + } + mtx_unlock(&usb_proc_mtx); + + return (worked); +} + +void * +usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) +{ + struct usb_proc_msg *pm0 = _pm0; + struct usb_proc_msg *pm1 = _pm1; + struct usb_proc_msg *pm2; + usb_size_t d; + uint8_t t; + + t = 0; + + if (pm0->pm_qentry.tqe_prev) { + t |= 1; + } + if (pm1->pm_qentry.tqe_prev) { + t |= 2; + } + if (t == 0) { + /* + * No entries are queued. Queue "pm0" and use the existing + * message number. + */ + pm2 = pm0; + } else if (t == 1) { + /* Check if we need to increment the message number. */ + if (pm0->pm_num == up->up_msg_num) { + up->up_msg_num++; + } + pm2 = pm1; + } else if (t == 2) { + /* Check if we need to increment the message number. */ + if (pm1->pm_num == up->up_msg_num) { + up->up_msg_num++; + } + pm2 = pm0; + } else if (t == 3) { + /* + * Both entries are queued. Re-queue the entry closest to + * the end. + */ + d = (pm1->pm_num - pm0->pm_num); + + /* Check sign after subtraction */ + if (d & 0x80000000) { + pm2 = pm0; + } else { + pm2 = pm1; + } + + TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); + } else { + pm2 = NULL; /* panic - should not happen */ + } + + /* Put message last on queue */ + + pm2->pm_num = up->up_msg_num; + TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); + + return (pm2); +} + +/*------------------------------------------------------------------------* + * usb_proc_is_gone + * + * Return values: + * 0: USB process is running + * Else: USB process is tearing down + *------------------------------------------------------------------------*/ +uint8_t +usb_proc_is_gone(struct usb_process *up) +{ + return (0); +} + +/*------------------------------------------------------------------------* + * usb_proc_mwait + * + * This function will return when the USB process message pointed to + * by "pm" is no longer on a queue. This function must be called + * having "usb_proc_mtx" locked. + *------------------------------------------------------------------------*/ +void +usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) +{ + struct usb_proc_msg *pm0 = _pm0; + struct usb_proc_msg *pm1 = _pm1; + + /* Just remove the messages from the queue. */ + if (pm0->pm_qentry.tqe_prev) { + TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); + pm0->pm_qentry.tqe_prev = NULL; + } + if (pm1->pm_qentry.tqe_prev) { + TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); + pm1->pm_qentry.tqe_prev = NULL; + } +} + +/*------------------------------------------------------------------------* + * SYSTEM attach + *------------------------------------------------------------------------*/ + +#ifdef USB_PCI_PROBE_LIST +static device_method_t pci_methods[] = { + DEVMETHOD_END +}; + +static driver_t pci_driver = { + .name = "pci", + .methods = pci_methods, +}; + +static devclass_t pci_devclass; + +DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0); + +static const char *usb_pci_devices[] = { + USB_PCI_PROBE_LIST +}; + +#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *)) + +static device_t usb_pci_dev[USB_PCI_USB_MAX]; + +static void +usb_pci_mod_load(void *arg) +{ + uint32_t x; + + usb_pci_root = device_add_child(NULL, "pci", -1); + if (usb_pci_root == NULL) + return; + + for (x = 0; x != USB_PCI_USB_MAX; x++) { + usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1); + if (usb_pci_dev[x] == NULL) + continue; + if (device_probe_and_attach(usb_pci_dev[x])) { + device_printf(usb_pci_dev[x], + "WARNING: Probe and attach failed!\n"); + } + } +} +SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0); + +static void +usb_pci_mod_unload(void *arg) +{ + uint32_t x; + + for (x = 0; x != USB_PCI_USB_MAX; x++) { + if (usb_pci_dev[x]) { + device_detach(usb_pci_dev[x]); + device_delete_child(usb_pci_root, usb_pci_dev[x]); + } + } + if (usb_pci_root) + device_delete_child(NULL, usb_pci_root); +} +SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0); +#endif + +/*------------------------------------------------------------------------* + * MALLOC API + *------------------------------------------------------------------------*/ + +#ifndef HAVE_MALLOC +#define USB_POOL_ALIGN 8 + +static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN); +static uint32_t usb_pool_rem = USB_POOL_SIZE; +static uint32_t usb_pool_entries; + +struct malloc_hdr { + TAILQ_ENTRY(malloc_hdr) entry; + uint32_t size; +} __aligned(USB_POOL_ALIGN); + +static TAILQ_HEAD(, malloc_hdr) malloc_head = + TAILQ_HEAD_INITIALIZER(malloc_head); + +void * +usb_malloc(unsigned long size) +{ + struct malloc_hdr *hdr; + + size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1); + size += sizeof(struct malloc_hdr); + + TAILQ_FOREACH(hdr, &malloc_head, entry) { + if (hdr->size == size) + break; + } + + if (hdr) { + DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", + (int)usb_pool_entries, (int)usb_pool_rem, (int)size); + + TAILQ_REMOVE(&malloc_head, hdr, entry); + memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); + return (hdr + 1); + } + if (usb_pool_rem >= size) { + hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem); + hdr->size = size; + + usb_pool_rem -= size; + usb_pool_entries++; + + DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", + (int)usb_pool_entries, (int)usb_pool_rem, (int)size); + + memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); + return (hdr + 1); + } + return (NULL); +} + +void +usb_free(void *arg) +{ + struct malloc_hdr *hdr; + + if (arg == NULL) + return; + + hdr = arg; + hdr--; + + TAILQ_INSERT_TAIL(&malloc_head, hdr, entry); +} +#endif + +char * +usb_strdup(const char *str) +{ + char *tmp; + int len; + + len = 1 + strlen(str); + + tmp = malloc(len,XXX,XXX); + if (tmp == NULL) + return (NULL); + + memcpy(tmp, str, len); + return (tmp); +} diff --git a/sys/boot/kshim/bsd_kernel.h b/sys/boot/kshim/bsd_kernel.h new file mode 100644 index 0000000..975211e --- /dev/null +++ b/sys/boot/kshim/bsd_kernel.h @@ -0,0 +1,496 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2011 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_KERNEL_H_ +#define _BSD_KERNEL_H_ + +#define _KERNEL +#undef __FreeBSD_version +#define __FreeBSD_version 1100000 + +#include +#include +#include + +#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) +#define isdigit(x) ((x) >= '0' && (x) <= '9') +#define panic(...) do { printf("USB PANIC: " __VA_ARGS__); while (1) ; } while (0) +#define rebooting 0 +#define M_USB 0 +#define M_USBDEV 0 +#define USB_PROC_MAX 3 +#define USB_BUS_GIANT_PROC(bus) (usb_process + 2) +#define USB_BUS_NON_GIANT_PROC(bus) (usb_process + 2) +#define USB_BUS_EXPLORE_PROC(bus) (usb_process + 0) +#define USB_BUS_CONTROL_XFER_PROC(bus) (usb_process + 1) +#define SYSCTL_DECL(...) +#define SYSCTL_NODE(name,...) struct { } name __used +#define SYSCTL_INT(...) +#define TUNABLE_INT(...) +#define MALLOC_DECLARE(...) +#define MALLOC_DEFINE(...) +#define EVENTHANDLER_DECLARE(...) +#define EVENTHANDLER_INVOKE(...) +#define KASSERT(...) +#define SCHEDULER_STOPPED(x) (0) +#define PI_SWI(...) (0) +#define UNIQ_NAME(x) x +#define UNIQ_NAME_STR(x) #x +#define DEVCLASS_MAXUNIT 32 +#define MOD_LOAD 1 +#define MOD_UNLOAD 2 +#define DEVMETHOD(what,func) { #what, (void *)&func } +#define DEVMETHOD_END {0,0} +#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ + static struct module_data bsd_##name##_##busname##_driver_mod = { \ + evh, arg, #busname, #name, #busname "/" #name, \ + &driver, &devclass, { 0, 0 } }; \ +SYSINIT(bsd_##name##_##busname##_driver_mod, SI_SUB_DRIVERS, \ + SI_ORDER_MIDDLE, module_register, \ + &bsd_##name##_##busname##_driver_mod) +#define SYSINIT(uniq, subs, order, _func, _data) \ +const struct sysinit UNIQ_NAME(sysinit_##uniq) = { \ + .func = (_func), \ + .data = __DECONST(void *, _data) \ +}; \ +SYSINIT_ENTRY(uniq##_entry, "sysinit", (subs), \ + (order), "const struct sysinit", \ + UNIQ_NAME_STR(sysinit_##uniq), "SYSINIT") + +#define SYSUNINIT(uniq, subs, order, _func, _data) \ +const struct sysinit UNIQ_NAME(sysuninit_##uniq) = { \ + .func = (_func), \ + .data = __DECONST(void *, _data) \ +}; \ +SYSINIT_ENTRY(uniq##_entry, "sysuninit", (subs), \ + (order), "const struct sysuninit", \ + UNIQ_NAME_STR(sysuninit_##uniq), "SYSUNINIT") +#define MODULE_DEPEND(...) +#define MODULE_VERSION(...) +#define NULL ((void *)0) +#define BUS_SPACE_BARRIER_READ 0x01 +#define BUS_SPACE_BARRIER_WRITE 0x02 +#define hz 1000 +#undef PAGE_SIZE +#define PAGE_SIZE 4096 +#undef MIN +#define MIN(a,b) (((a) < (b)) ? (a) : (b)) +#undef MAX +#define MAX(a,b) (((a) > (b)) ? (a) : (b)) +#define MTX_DEF 0 +#define MTX_SPIN 0 +#define MTX_RECURSE 0 +#define SX_DUPOK 0 +#define SX_NOWITNESS 0 +#define WITNESS_WARN(...) +#define cold 0 +#define BUS_PROBE_GENERIC 0 +#define CALLOUT_RETURNUNLOCKED 0x1 +#undef va_list +#define va_list __builtin_va_list +#undef va_size +#define va_size(type) __builtin_va_size(type) +#undef va_start +#define va_start(ap, last) __builtin_va_start(ap, last) +#undef va_end +#define va_end(ap) __builtin_va_end(ap) +#undef va_arg +#define va_arg(ap, type) __builtin_va_arg((ap), type) +#define DEVICE_ATTACH(dev, ...) \ + (((device_attach_t *)(device_get_method(dev, "device_attach")))(dev,## __VA_ARGS__)) +#define DEVICE_DETACH(dev, ...) \ + (((device_detach_t *)(device_get_method(dev, "device_detach")))(dev,## __VA_ARGS__)) +#define DEVICE_PROBE(dev, ...) \ + (((device_probe_t *)(device_get_method(dev, "device_probe")))(dev,## __VA_ARGS__)) +#define DEVICE_RESUME(dev, ...) \ + (((device_resume_t *)(device_get_method(dev, "device_resume")))(dev,## __VA_ARGS__)) +#define DEVICE_SHUTDOWN(dev, ...) \ + (((device_shutdown_t *)(device_get_method(dev, "device_shutdown")))(dev,## __VA_ARGS__)) +#define DEVICE_SUSPEND(dev, ...) \ + (((device_suspend_t *)(device_get_method(dev, "device_suspend")))(dev,## __VA_ARGS__)) +#define USB_HANDLE_REQUEST(dev, ...) \ + (((usb_handle_request_t *)(device_get_method(dev, "usb_handle_request")))(dev,## __VA_ARGS__)) +#define USB_TAKE_CONTROLLER(dev, ...) \ + (((usb_take_controller_t *)(device_get_method(dev, "usb_take_controller")))(dev,## __VA_ARGS__)) + +enum { + SI_SUB_DUMMY = 0x0000000, + SI_SUB_LOCK = 0x1B00000, + SI_SUB_KLD = 0x2000000, + SI_SUB_DRIVERS = 0x3100000, + SI_SUB_PSEUDO = 0x7000000, + SI_SUB_KICK_SCHEDULER = 0xa000000, + SI_SUB_RUN_SCHEDULER = 0xfffffff +}; + +enum { + SI_ORDER_FIRST = 0x0000000, + SI_ORDER_SECOND = 0x0000001, + SI_ORDER_THIRD = 0x0000002, + SI_ORDER_FOURTH = 0x0000003, + SI_ORDER_MIDDLE = 0x1000000, + SI_ORDER_ANY = 0xfffffff /* last */ +}; + +struct uio; +struct thread; +struct malloc_type; +struct usb_process; + +#ifndef HAVE_STANDARD_DEFS +#define _UINT8_T_DECLARED +typedef unsigned char uint8_t; +#define _INT8_T_DECLARED +typedef signed char int8_t; +#define _UINT16_T_DECLARED +typedef unsigned short uint16_t; +#define _INT16_T_DECLARED +typedef signed short int16_t; +#define _UINT32_T_DECLARED +typedef unsigned int uint32_t; +#define _INT32_T_DECLARED +typedef signed int int32_t; +#define _UINT64_T_DECLARED +typedef unsigned long long uint64_t; +#define _INT16_T_DECLARED +typedef signed long long int64_t; + +typedef uint16_t uid_t; +typedef uint16_t gid_t; +typedef uint16_t mode_t; + +typedef uint8_t *caddr_t; +#define _UINTPTR_T_DECLARED +typedef unsigned long uintptr_t; + +#define _SIZE_T_DECLARED +typedef unsigned long size_t; +typedef unsigned long u_long; +#endif + +typedef unsigned long bus_addr_t; +typedef unsigned long bus_size_t; + +typedef void *bus_dmamap_t; +typedef void *bus_dma_tag_t; + +typedef void *bus_space_tag_t; +typedef uint8_t *bus_space_handle_t; + +/* SYSINIT API */ + +#include + +struct sysinit { + void (*func) (void *arg); + void *data; +}; + +/* MUTEX API */ + +struct mtx { + int owned; + struct mtx *parent; +}; + +#define mtx_assert(...) do { } while (0) +void mtx_init(struct mtx *, const char *, const char *, int); +void mtx_lock(struct mtx *); +void mtx_unlock(struct mtx *); +#define mtx_lock_spin(x) mtx_lock(x) +#define mtx_unlock_spin(x) mtx_unlock(x) +int mtx_owned(struct mtx *); +void mtx_destroy(struct mtx *); + +extern struct mtx Giant; + +/* SX API */ + +struct sx { + int owned; +}; + +#define sx_assert(...) do { } while (0) +#define sx_init(...) sx_init_flags(__VA_ARGS__, 0) +void sx_init_flags(struct sx *, const char *, int); +void sx_destroy(struct sx *); +void sx_xlock(struct sx *); +void sx_xunlock(struct sx *); +int sx_xlocked(struct sx *); + +/* CONDVAR API */ + +struct cv { + int sleeping; +}; + +void cv_init(struct cv *, const char *desc); +void cv_destroy(struct cv *); +void cv_wait(struct cv *, struct mtx *); +int cv_timedwait(struct cv *, struct mtx *, int); +void cv_signal(struct cv *); +void cv_broadcast(struct cv *); + +/* CALLOUT API */ + +typedef void callout_fn_t (void *); + +extern volatile int ticks; + +struct callout { + LIST_ENTRY(callout) entry; + callout_fn_t *func; + void *arg; + struct mtx *mtx; + int flags; + int timeout; +}; + +void callout_init_mtx(struct callout *, struct mtx *, int); +void callout_reset(struct callout *, int, callout_fn_t *, void *); +void callout_stop(struct callout *); +void callout_drain(struct callout *); +int callout_pending(struct callout *); +void callout_process(int timeout); + +/* DEVICE API */ + +struct driver; +struct devclass; +struct device; +struct module; +struct module_data; + +typedef struct driver driver_t; +typedef struct devclass *devclass_t; +typedef struct device *device_t; +typedef void (driver_intr_t)(void *arg); +typedef int (driver_filter_t)(void *arg); +#define FILTER_STRAY 0x01 +#define FILTER_HANDLED 0x02 +#define FILTER_SCHEDULE_THREAD 0x04 + +typedef int device_attach_t (device_t dev); +typedef int device_detach_t (device_t dev); +typedef int device_resume_t (device_t dev); +typedef int device_shutdown_t (device_t dev); +typedef int device_probe_t (device_t dev); +typedef int device_suspend_t (device_t dev); + +typedef int bus_child_location_str_t (device_t parent, device_t child, char *buf, size_t buflen); +typedef int bus_child_pnpinfo_str_t (device_t parent, device_t child, char *buf, size_t buflen); +typedef void bus_driver_added_t (device_t dev, driver_t *driver); + +struct device_method { + const char *desc; + void *const func; +}; + +typedef struct device_method device_method_t; + +struct device { + TAILQ_HEAD(device_list, device) dev_children; + TAILQ_ENTRY(device) dev_link; + + struct device *dev_parent; + const struct module_data *dev_module; + void *dev_sc; + void *dev_aux; + driver_filter_t *dev_irq_filter; + driver_intr_t *dev_irq_fn; + void *dev_irq_arg; + + uint16_t dev_unit; + + char dev_nameunit[64]; + char dev_desc[64]; + + uint8_t dev_res_alloc:1; + uint8_t dev_quiet:1; + uint8_t dev_softc_set:1; + uint8_t dev_softc_alloc:1; + uint8_t dev_attached:1; + uint8_t dev_fixed_class:1; + uint8_t dev_unit_manual:1; +}; + +struct devclass { + device_t dev_list[DEVCLASS_MAXUNIT]; +}; + +struct driver { + const char *name; + const struct device_method *methods; + uint32_t size; +}; + +struct module_data { + int (*callback) (struct module *, int, void *arg); + void *arg; + const char *bus_name; + const char *mod_name; + const char *long_name; + const struct driver *driver; + struct devclass **devclass_pp; + TAILQ_ENTRY(module_data) entry; +}; + +device_t device_get_parent(device_t dev); +void *device_get_method(device_t dev, const char *what); +const char *device_get_name(device_t dev); +const char *device_get_nameunit(device_t dev); + +#define device_printf(dev, fmt,...) \ + printf("%s: " fmt, device_get_nameunit(dev),## __VA_ARGS__) +device_t device_add_child(device_t dev, const char *name, int unit); +void device_quiet(device_t dev); +void device_set_interrupt(device_t dev, driver_filter_t *, driver_intr_t *, void *); +void device_run_interrupts(device_t parent); +void device_set_ivars(device_t dev, void *ivars); +void *device_get_ivars(device_t dev); +const char *device_get_desc(device_t dev); +int device_probe_and_attach(device_t dev); +int device_detach(device_t dev); +void *device_get_softc(device_t dev); +void device_set_softc(device_t dev, void *softc); +int device_delete_child(device_t dev, device_t child); +int device_delete_children(device_t dev); +int device_is_attached(device_t dev); +void device_set_desc(device_t dev, const char *desc); +void device_set_desc_copy(device_t dev, const char *desc); +int device_get_unit(device_t dev); +void *devclass_get_softc(devclass_t dc, int unit); +int devclass_get_maxunit(devclass_t dc); +device_t devclass_get_device(devclass_t dc, int unit); +devclass_t devclass_find(const char *classname); + +#define bus_get_dma_tag(...) (NULL) +int bus_generic_detach(device_t dev); +int bus_generic_resume(device_t dev); +int bus_generic_shutdown(device_t dev); +int bus_generic_suspend(device_t dev); +int bus_generic_print_child(device_t dev, device_t child); +void bus_generic_driver_added(device_t dev, driver_t *driver); + +/* BUS SPACE API */ + +void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t data); +void bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t data); +void bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t data); + +uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); +uint16_t bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); +uint32_t bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); + +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); +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); +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); + +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); +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); +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); + +void bus_space_read_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count); +void bus_space_write_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count); +void bus_space_read_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count); +void bus_space_write_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count); + +void bus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags); + +void module_register(void *); + +/* LIB-C */ + +void *memset(void *, int, size_t len); +void *memcpy(void *, const void *, size_t len); +int printf(const char *,...) __printflike(1, 2); +int snprintf(char *restrict str, size_t size, const char *restrict format,...) __printflike(3, 4); +size_t strlen(const char *s); + +/* MALLOC API */ + +#undef malloc +#define malloc(s,x,f) usb_malloc(s) +void *usb_malloc(size_t); + +#undef free +#define free(p,x) usb_free(p) +void usb_free(void *); + +#define strdup(p,x) usb_strdup(p) +char *usb_strdup(const char *str); + +/* ENDIANNESS */ + +#ifndef HAVE_ENDIAN_DEFS + +/* Assume little endian */ + +#define htole64(x) ((uint64_t)(x)) +#define le64toh(x) ((uint64_t)(x)) + +#define htole32(x) ((uint32_t)(x)) +#define le32toh(x) ((uint32_t)(x)) + +#define htole16(x) ((uint16_t)(x)) +#define le16toh(x) ((uint16_t)(x)) + +#define be32toh(x) ((uint32_t)(x)) +#define htobe32(x) ((uint32_t)(x)) + +#else +#include +#endif + +/* USB */ + +typedef int usb_handle_request_t (device_t dev, const void *req, void **pptr, uint16_t *plen, uint16_t offset, uint8_t *pstate); +typedef int usb_take_controller_t (device_t dev); + +void usb_idle(void); +void usb_init(void); +void usb_uninit(void); + +/* set some defaults */ + +#ifndef USB_POOL_SIZE +#define USB_POOL_SIZE (1024*1024) /* 1 MByte */ +#endif + +int pause(const char *, int); +void DELAY(unsigned int); + +/* OTHER */ + +struct selinfo { +}; + +/* SYSTEM STARTUP API */ + +extern const void *sysinit_data[]; +extern const void *sysuninit_data[]; + +#endif /* _BSD_KERNEL_H_ */ diff --git a/sys/boot/kshim/kshim.mk b/sys/boot/kshim/kshim.mk new file mode 100644 index 0000000..f583e99 --- /dev/null +++ b/sys/boot/kshim/kshim.mk @@ -0,0 +1,79 @@ +# +# $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. +# + +KSHIM_DIR:= ${.PARSEDIR} +.PATH: ${KSHIM_DIR} + +CFLAGS+= -I${KSHIM_DIR} +CFLAGS+= -I${KSHIM_DIR}/../.. +CFLAGS+= -DUSB_GLOBAL_INCLUDE_FILE=\"bsd_global.h\" +CFLAGS+= -DHAVE_ENDIAN_DEFS + +# +# Single threaded BSD kernel +# +SRCS+= bsd_kernel.c + +# +# BUSSPACE implementation +# +SRCS+= bsd_busspace.c + +SRCS+= sysinit_data.c +SRCS+= sysuninit_data.c + +CLEANFILES+= sysinit.bin +CLEANFILES+= sysinit_data.c +CLEANFILES+= sysuninit_data.c + +SRCS+= ${KSRCS} +SYSINIT_OBJS= ${KSRCS:R:C/$/.osys/} +CLEANFILES+= ${SYSINIT_OBJS} + +# +# SYSINIT() and SYSUNINIT() handling +# + +sysinit_data.c: sysinit.bin + sysinit -i sysinit.bin -o ${.TARGET} -k sysinit -s sysinit_data + +sysuninit_data.c: sysinit.bin + sysinit -i sysinit.bin -o ${.TARGET} -R -k sysuninit -s sysuninit_data + +.for KSRC in ${KSRCS:R} +${KSRC}.osys: ${KSRC}.o + ${OBJCOPY} -j ".debug.sysinit" -O binary ${KSRC}.o ${KSRC}.osys +.endfor + +sysinit.bin: ${SYSINIT_OBJS} + cat ${.ALLSRC} > sysinit.bin diff --git a/sys/boot/kshim/sysinit.h b/sys/boot/kshim/sysinit.h new file mode 100644 index 0000000..a7a450e --- /dev/null +++ b/sys/boot/kshim/sysinit.h @@ -0,0 +1,57 @@ +/* $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 _SYSINIT_H_ +#define _SYSINIT_H_ + +struct sysinit_data { + uint8_t b_keyword_name[64]; + uint8_t b_debug_info[128]; + uint8_t b_global_type[128]; + uint8_t b_global_name[128]; + uint8_t b_file_name[256]; + uint32_t dw_endian32; + uint32_t dw_msb_value; /* must be non-zero, else entry is skipped */ + uint32_t dw_lsb_value; + uint32_t dw_file_line; +} __attribute__((__packed__)); + +#define SYSINIT_ENTRY(uniq, keyword, msb, lsb, g_type, g_name, debug) \ + static const struct sysinit_data sysinit_##uniq \ + __attribute__((__section__(".debug.sysinit"), \ + __used__, __aligned__(1))) = { \ + .b_keyword_name = { keyword }, \ + .b_debug_info = { debug }, \ + .b_global_type = { g_type }, \ + .b_global_name = { g_name }, \ + .b_file_name = { __FILE__ }, \ + .dw_endian32 = 0x76543210U, \ + .dw_msb_value = (msb), \ + .dw_lsb_value = (lsb), \ + .dw_file_line = __LINE__ \ +} + +#endif /* _SYSINIT_H_ */ diff --git a/sys/boot/mips/beri/loader/Makefile b/sys/boot/mips/beri/loader/Makefile index 3a75189..198ff93 100644 --- a/sys/boot/mips/beri/loader/Makefile +++ b/sys/boot/mips/beri/loader/Makefile @@ -142,8 +142,9 @@ FILES+= menu.rc # Do garbage collection CFLAGS+= -ffunction-sections -fdata-sections CFLAGS+= -Wl,--gc-sections -# Link USB BOOT library -LDADD+= ${.OBJDIR}/../../../usb/libusbboot.a +HAVE_UMASS_LOADER= 1 +HAVE_SAF1761OTG= 1 +.include "../../../usb/usbcore.mk" CFLAGS+= -I${.CURDIR}/../../../usb # Define USB SUPPORT CFLAGS+= -DLOADER_USB_SUPPORT @@ -151,4 +152,7 @@ CFLAGS+= -DLOADER_USB_SUPPORT all: loader +.if defined(LOADER_USB_SUPPORT) +.include "../../../kshim/kshim.mk" +.endif .include diff --git a/sys/boot/usb/Makefile b/sys/boot/usb/Makefile index cd4dec0..1b94b3d 100644 --- a/sys/boot/usb/Makefile +++ b/sys/boot/usb/Makefile @@ -1,7 +1,13 @@ # # $FreeBSD$ # -# Copyright (c) 2013 Hans Petter Selasky. All rights reserved. +# 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 @@ -25,37 +31,15 @@ # SUCH DAMAGE. # -T=${.CURDIR}/tools -S=${.CURDIR}/../.. - -.PATH: \ - ${.CURDIR} \ - ${.CURDIR}/storage \ - ${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?= /usr/bin/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+= -I${.CURDIR}/../common CFLAGS+= -g -CFLAGS+= -DUSB_MSCTEST_BULK_SIZE=65536 -CFLAGS+= -DUSB_POOL_SIZE=131072 CFLAGS+= -fno-pic -CFLAGS+= -DHAVE_ENDIAN_DEFS .if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" CFLAGS+= -march=i386 @@ -68,148 +52,7 @@ CFLAGS+= -m32 CFLAGS+= -mno-abicalls .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+= usb_controller.c - -.if defined(HAVE_AT91DCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"at91dci\"" -SRCS+= at91dci.c -.endif - -.if defined(HAVE_ATMEGADCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"atmegadci\"" -SRCS+= atmegadci.c -.endif - -.if defined(HAVE_AVR32DCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"avr32dci\"" -SRCS+= avr32dci.c -.endif - -.if defined(HAVE_DWCOTG) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"dwcotg\"" -SRCS+= dwcotg.c -.endif - -.if defined(HAVE_MUSBOTG) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"musbotg\"" -SRCS+= musbotg.c -.endif - -.if defined(HAVE_EHCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"ehci\"" -SRCS+= ehci.c -.endif - -.if defined(HAVE_OHCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"ohci\"" -SRCS+= ohci.c -.endif - -.if defined(HAVE_UHCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"uhci\"" -SRCS+= uhci.c -.endif - -.if defined(HAVE_XHCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"xhci\"" -SRCS+= xhci.c -.endif - -.if defined(HAVE_USS820DCI) -CFLAGS += -DUSB_PCI_PROBE_LIST="\"uss820dci\"" -SRCS+= 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 -SRCS+= saf1761_otg.c -SRCS+= saf1761_otg_boot.c -.endif - -# -# 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 - -# -# USB mass storage support -# -SRCS+= umass_common.c - -.if defined(HAVE_UMASS_LOADER) -SRCS+= umass_loader.c -.endif - -CLEANFILES+= sysinit -CLEANFILES+= sysinit.bin -CLEANFILES+= sysinit_data.c -CLEANFILES+= sysuninit_data.c - -CLEANFILES+= ${SRCS:C/\.c/.osys/g} +.include "usbcore.mk" +.include "../kshim/kshim.mk" .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 diff --git a/sys/boot/usb/bsd_busspace.c b/sys/boot/usb/bsd_busspace.c deleted file mode 100644 index c9ba09f..0000000 --- a/sys/boot/usb/bsd_busspace.c +++ /dev/null @@ -1,207 +0,0 @@ -/* $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; - } -} diff --git a/sys/boot/usb/bsd_global.h b/sys/boot/usb/bsd_global.h deleted file mode 100644 index 2fb0dcc..0000000 --- a/sys/boot/usb/bsd_global.h +++ /dev/null @@ -1,65 +0,0 @@ -/* $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 - -extern struct usb_process usb_process[USB_PROC_MAX]; - -#endif /* _BSD_GLOBAL_H_ */ diff --git a/sys/boot/usb/bsd_kernel.c b/sys/boot/usb/bsd_kernel.c deleted file mode 100644 index d41b9f4..0000000 --- a/sys/boot/usb/bsd_kernel.c +++ /dev/null @@ -1,1239 +0,0 @@ -/* $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 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, driver_filter_t *filter, - driver_intr_t *fn, void *arg) -{ - dev->dev_irq_filter = filter; - 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) { - int status; - if (child->dev_irq_filter != NULL) - status = child->dev_irq_filter(child->dev_irq_arg); - else - status = FILTER_SCHEDULE_THREAD; - - if (status == FILTER_SCHEDULE_THREAD) { - 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); -} - -static void -devclass_delete_device(const struct module_data *mod, device_t dev) -{ - if (mod == NULL) { - return; - } - mod->devclass_pp[0]->dev_list[dev->dev_unit] = NULL; - dev->dev_module = NULL; -} - -static device_t -make_device(device_t parent, const char *name) -{ - device_t dev = NULL; - const struct module_data *mod = NULL; - - if (name) { - - mod = devclass_find_create(name); - - if (!mod) { - - DPRINTF("%s:%d:%s: can't find device " - "class %s\n", __FILE__, __LINE__, - __FUNCTION__, name); - - goto done; - } - } - dev = malloc(sizeof(*dev), - M_DEVBUF, M_WAITOK | M_ZERO); - - if (dev == NULL) - goto done; - - dev->dev_parent = parent; - TAILQ_INIT(&dev->dev_children); - - if (name) { - dev->dev_fixed_class = 1; - if (devclass_add_device(mod, dev)) { - goto error; - } - } -done: - return (dev); - -error: - if (dev) { - free(dev, M_DEVBUF); - } - return (NULL); -} - -device_t -device_add_child(device_t dev, const char *name, int unit) -{ - device_t child; - - if (unit != -1) { - device_printf(dev, "Unit is not -1\n"); - } - child = make_device(dev, name); - if (child == NULL) { - device_printf(dev, "Could not add child '%s'\n", name); - goto done; - } - if (dev == NULL) { - /* no parent */ - goto done; - } - TAILQ_INSERT_TAIL(&dev->dev_children, child, dev_link); -done: - return (child); -} - -int -device_delete_child(device_t dev, device_t child) -{ - int error = 0; - device_t grandchild; - - /* remove children first */ - - while ((grandchild = TAILQ_FIRST(&child->dev_children))) { - error = device_delete_child(child, grandchild); - if (error) { - device_printf(dev, "Error deleting child!\n"); - goto done; - } - } - - error = device_detach(child); - - if (error) - goto done; - - devclass_delete_device(child->dev_module, child); - - if (dev != NULL) { - /* remove child from parent */ - TAILQ_REMOVE(&dev->dev_children, child, dev_link); - } - free(child, M_DEVBUF); - -done: - return (error); -} - -int -device_delete_children(device_t dev) -{ - device_t child; - int error = 0; - - while ((child = TAILQ_FIRST(&dev->dev_children))) { - error = device_delete_child(dev, child); - if (error) { - device_printf(dev, "Error deleting child!\n"); - break; - } - } - return (error); -} - -void -device_quiet(device_t dev) -{ - dev->dev_quiet = 1; -} - -const char * -device_get_desc(device_t dev) -{ - if (dev) - return &(dev->dev_desc[0]); - return (unknown_string); -} - -static int -default_method(void) -{ - /* do nothing */ - DPRINTF("Default method called\n"); - return (0); -} - -void * -device_get_method(device_t dev, const char *what) -{ - const struct device_method *mtod; - - mtod = dev->dev_module->driver->methods; - while (mtod->func != NULL) { - if (devclass_equal(mtod->desc, what)) { - return (mtod->func); - } - mtod++; - } - return ((void *)&default_method); -} - -const char * -device_get_name(device_t dev) -{ - if (dev == NULL) - return (unknown_string); - - return (dev->dev_module->driver->name); -} - -static int -device_allocate_softc(device_t dev) -{ - const struct module_data *mod; - - mod = dev->dev_module; - - if ((dev->dev_softc_alloc == 0) && - (mod->driver->size != 0)) { - dev->dev_sc = malloc(mod->driver->size, - M_DEVBUF, M_WAITOK | M_ZERO); - - if (dev->dev_sc == NULL) - return (ENOMEM); - - dev->dev_softc_alloc = 1; - } - return (0); -} - -int -device_probe_and_attach(device_t dev) -{ - const struct module_data *mod; - const char *bus_name_parent; - - bus_name_parent = device_get_name(device_get_parent(dev)); - - if (dev->dev_attached) - return (0); /* fail-safe */ - - if (dev->dev_fixed_class) { - - mod = dev->dev_module; - - if (DEVICE_PROBE(dev) <= 0) { - - if (device_allocate_softc(dev) == 0) { - - if (DEVICE_ATTACH(dev) == 0) { - /* success */ - dev->dev_attached = 1; - return (0); - } - } - } - device_detach(dev); - - goto error; - } - /* - * Else find a module for our device, if any - */ - - TAILQ_FOREACH(mod, &module_head, entry) { - if (devclass_equal(mod->bus_name, bus_name_parent)) { - if (devclass_create(mod->devclass_pp)) { - continue; - } - if (devclass_add_device(mod, dev)) { - continue; - } - if (DEVICE_PROBE(dev) <= 0) { - - if (device_allocate_softc(dev) == 0) { - - if (DEVICE_ATTACH(dev) == 0) { - /* success */ - dev->dev_attached = 1; - return (0); - } - } - } - /* else try next driver */ - - device_detach(dev); - } - } - -error: - return (ENODEV); -} - -int -device_detach(device_t dev) -{ - const struct module_data *mod = dev->dev_module; - int error; - - if (dev->dev_attached) { - - error = DEVICE_DETACH(dev); - if (error) { - return error; - } - dev->dev_attached = 0; - } - device_set_softc(dev, NULL); - - if (dev->dev_fixed_class == 0) - devclass_delete_device(mod, dev); - - return (0); -} - -void -device_set_softc(device_t dev, void *softc) -{ - if (dev->dev_softc_alloc) { - free(dev->dev_sc, M_DEVBUF); - dev->dev_sc = NULL; - } - dev->dev_sc = softc; - dev->dev_softc_alloc = 0; -} - -void * -device_get_softc(device_t dev) -{ - if (dev == NULL) - return (NULL); - - return (dev->dev_sc); -} - -int -device_is_attached(device_t dev) -{ - return (dev->dev_attached); -} - -void -device_set_desc(device_t dev, const char *desc) -{ - snprintf(dev->dev_desc, sizeof(dev->dev_desc), "%s", desc); -} - -void -device_set_desc_copy(device_t dev, const char *desc) -{ - device_set_desc(dev, desc); -} - -void * -devclass_get_softc(devclass_t dc, int unit) -{ - return (device_get_softc(devclass_get_device(dc, unit))); -} - -int -devclass_get_maxunit(devclass_t dc) -{ - int max_unit = 0; - - if (dc) { - max_unit = DEVCLASS_MAXUNIT; - while (max_unit--) { - if (dc->dev_list[max_unit]) { - break; - } - } - max_unit++; - } - return (max_unit); -} - -device_t -devclass_get_device(devclass_t dc, int unit) -{ - return (((unit < 0) || (unit >= DEVCLASS_MAXUNIT) || (dc == NULL)) ? - NULL : dc->dev_list[unit]); -} - -devclass_t -devclass_find(const char *classname) -{ - const struct module_data *mod; - - TAILQ_FOREACH(mod, &module_head, entry) { - if (devclass_equal(mod->mod_name, classname)) - return (mod->devclass_pp[0]); - } - return (NULL); -} - -void -module_register(void *data) -{ - struct module_data *mdata = data; - - TAILQ_INSERT_TAIL(&module_head, mdata, entry); -} - -/*------------------------------------------------------------------------* - * System startup - *------------------------------------------------------------------------*/ - -static void -sysinit_run(const void **ppdata) -{ - const struct sysinit *psys; - - while ((psys = *ppdata) != NULL) { - (psys->func) (psys->data); - ppdata++; - } -} - -/*------------------------------------------------------------------------* - * USB process API - *------------------------------------------------------------------------*/ - -static int usb_do_process(struct usb_process *); -static int usb_proc_level = -1; -static struct mtx usb_proc_mtx; - -void -usb_idle(void) -{ - int old_level = usb_proc_level; - int old_giant = Giant.owned; - int worked; - - device_run_interrupts(usb_pci_root); - - do { - worked = 0; - Giant.owned = 0; - - while (++usb_proc_level < USB_PROC_MAX) - worked |= usb_do_process(usb_process + usb_proc_level); - - usb_proc_level = old_level; - Giant.owned = old_giant; - - } while (worked); -} - -void -usb_init(void) -{ - sysinit_run(sysinit_data); -} - -void -usb_uninit(void) -{ - sysinit_run(sysuninit_data); -} - -static void -usb_process_init_sub(struct usb_process *up) -{ - TAILQ_INIT(&up->up_qhead); - - cv_init(&up->up_cv, "-"); - cv_init(&up->up_drain, "usbdrain"); - - up->up_mtx = &usb_proc_mtx; -} - -static void -usb_process_init(void *arg) -{ - uint8_t x; - - mtx_init(&usb_proc_mtx, "usb-proc-mtx", NULL, MTX_DEF | MTX_RECURSE); - - for (x = 0; x != USB_PROC_MAX; x++) - usb_process_init_sub(&usb_process[x]); - -} -SYSINIT(usb_process_init, SI_SUB_LOCK, SI_ORDER_MIDDLE, usb_process_init, NULL); - -static int -usb_do_process(struct usb_process *up) -{ - struct usb_proc_msg *pm; - int worked = 0; - - mtx_lock(&usb_proc_mtx); - -repeat: - pm = TAILQ_FIRST(&up->up_qhead); - - if (pm != NULL) { - - worked = 1; - - (pm->pm_callback) (pm); - - if (pm == TAILQ_FIRST(&up->up_qhead)) { - /* nothing changed */ - TAILQ_REMOVE(&up->up_qhead, pm, pm_qentry); - pm->pm_qentry.tqe_prev = NULL; - } - goto repeat; - } - mtx_unlock(&usb_proc_mtx); - - return (worked); -} - -void * -usb_proc_msignal(struct usb_process *up, void *_pm0, void *_pm1) -{ - struct usb_proc_msg *pm0 = _pm0; - struct usb_proc_msg *pm1 = _pm1; - struct usb_proc_msg *pm2; - usb_size_t d; - uint8_t t; - - t = 0; - - if (pm0->pm_qentry.tqe_prev) { - t |= 1; - } - if (pm1->pm_qentry.tqe_prev) { - t |= 2; - } - if (t == 0) { - /* - * No entries are queued. Queue "pm0" and use the existing - * message number. - */ - pm2 = pm0; - } else if (t == 1) { - /* Check if we need to increment the message number. */ - if (pm0->pm_num == up->up_msg_num) { - up->up_msg_num++; - } - pm2 = pm1; - } else if (t == 2) { - /* Check if we need to increment the message number. */ - if (pm1->pm_num == up->up_msg_num) { - up->up_msg_num++; - } - pm2 = pm0; - } else if (t == 3) { - /* - * Both entries are queued. Re-queue the entry closest to - * the end. - */ - d = (pm1->pm_num - pm0->pm_num); - - /* Check sign after subtraction */ - if (d & 0x80000000) { - pm2 = pm0; - } else { - pm2 = pm1; - } - - TAILQ_REMOVE(&up->up_qhead, pm2, pm_qentry); - } else { - pm2 = NULL; /* panic - should not happen */ - } - - /* Put message last on queue */ - - pm2->pm_num = up->up_msg_num; - TAILQ_INSERT_TAIL(&up->up_qhead, pm2, pm_qentry); - - return (pm2); -} - -/*------------------------------------------------------------------------* - * usb_proc_is_gone - * - * Return values: - * 0: USB process is running - * Else: USB process is tearing down - *------------------------------------------------------------------------*/ -uint8_t -usb_proc_is_gone(struct usb_process *up) -{ - return (0); -} - -/*------------------------------------------------------------------------* - * usb_proc_mwait - * - * This function will return when the USB process message pointed to - * by "pm" is no longer on a queue. This function must be called - * having "usb_proc_mtx" locked. - *------------------------------------------------------------------------*/ -void -usb_proc_mwait(struct usb_process *up, void *_pm0, void *_pm1) -{ - struct usb_proc_msg *pm0 = _pm0; - struct usb_proc_msg *pm1 = _pm1; - - /* Just remove the messages from the queue. */ - if (pm0->pm_qentry.tqe_prev) { - TAILQ_REMOVE(&up->up_qhead, pm0, pm_qentry); - pm0->pm_qentry.tqe_prev = NULL; - } - if (pm1->pm_qentry.tqe_prev) { - TAILQ_REMOVE(&up->up_qhead, pm1, pm_qentry); - pm1->pm_qentry.tqe_prev = NULL; - } -} - -/*------------------------------------------------------------------------* - * SYSTEM attach - *------------------------------------------------------------------------*/ - -#ifdef USB_PCI_PROBE_LIST -static device_method_t pci_methods[] = { - DEVMETHOD_END -}; - -static driver_t pci_driver = { - .name = "pci", - .methods = pci_methods, -}; - -static devclass_t pci_devclass; - -DRIVER_MODULE(pci, pci, pci_driver, pci_devclass, 0, 0); - -static const char *usb_pci_devices[] = { - USB_PCI_PROBE_LIST -}; - -#define USB_PCI_USB_MAX (sizeof(usb_pci_devices) / sizeof(void *)) - -static device_t usb_pci_dev[USB_PCI_USB_MAX]; - -static void -usb_pci_mod_load(void *arg) -{ - uint32_t x; - - usb_pci_root = device_add_child(NULL, "pci", -1); - if (usb_pci_root == NULL) - return; - - for (x = 0; x != USB_PCI_USB_MAX; x++) { - usb_pci_dev[x] = device_add_child(usb_pci_root, usb_pci_devices[x], -1); - if (usb_pci_dev[x] == NULL) - continue; - if (device_probe_and_attach(usb_pci_dev[x])) { - device_printf(usb_pci_dev[x], - "WARNING: Probe and attach failed!\n"); - } - } -} -SYSINIT(usb_pci_mod_load, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_load, 0); - -static void -usb_pci_mod_unload(void *arg) -{ - uint32_t x; - - for (x = 0; x != USB_PCI_USB_MAX; x++) { - if (usb_pci_dev[x]) { - device_detach(usb_pci_dev[x]); - device_delete_child(usb_pci_root, usb_pci_dev[x]); - } - } - if (usb_pci_root) - device_delete_child(NULL, usb_pci_root); -} -SYSUNINIT(usb_pci_mod_unload, SI_SUB_RUN_SCHEDULER, SI_ORDER_MIDDLE, usb_pci_mod_unload, 0); -#endif - -/*------------------------------------------------------------------------* - * MALLOC API - *------------------------------------------------------------------------*/ - -#ifndef HAVE_MALLOC -#define USB_POOL_ALIGN 8 - -static uint8_t usb_pool[USB_POOL_SIZE] __aligned(USB_POOL_ALIGN); -static uint32_t usb_pool_rem = USB_POOL_SIZE; -static uint32_t usb_pool_entries; - -struct malloc_hdr { - TAILQ_ENTRY(malloc_hdr) entry; - uint32_t size; -} __aligned(USB_POOL_ALIGN); - -static TAILQ_HEAD(, malloc_hdr) malloc_head = - TAILQ_HEAD_INITIALIZER(malloc_head); - -void * -usb_malloc(unsigned long size) -{ - struct malloc_hdr *hdr; - - size = (size + USB_POOL_ALIGN - 1) & ~(USB_POOL_ALIGN - 1); - size += sizeof(struct malloc_hdr); - - TAILQ_FOREACH(hdr, &malloc_head, entry) { - if (hdr->size == size) - break; - } - - if (hdr) { - DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", - (int)usb_pool_entries, (int)usb_pool_rem, (int)size); - - TAILQ_REMOVE(&malloc_head, hdr, entry); - memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); - return (hdr + 1); - } - if (usb_pool_rem >= size) { - hdr = (void *)(usb_pool + USB_POOL_SIZE - usb_pool_rem); - hdr->size = size; - - usb_pool_rem -= size; - usb_pool_entries++; - - DPRINTF("MALLOC: Entries = %d; Remainder = %d; Size = %d\n", - (int)usb_pool_entries, (int)usb_pool_rem, (int)size); - - memset(hdr + 1, 0, hdr->size - sizeof(*hdr)); - return (hdr + 1); - } - return (NULL); -} - -void -usb_free(void *arg) -{ - struct malloc_hdr *hdr; - - if (arg == NULL) - return; - - hdr = arg; - hdr--; - - TAILQ_INSERT_TAIL(&malloc_head, hdr, entry); -} -#endif - -char * -usb_strdup(const char *str) -{ - char *tmp; - int len; - - len = 1 + strlen(str); - - tmp = malloc(len,XXX,XXX); - if (tmp == NULL) - return (NULL); - - memcpy(tmp, str, len); - return (tmp); -} diff --git a/sys/boot/usb/bsd_kernel.h b/sys/boot/usb/bsd_kernel.h deleted file mode 100644 index 975211e..0000000 --- a/sys/boot/usb/bsd_kernel.h +++ /dev/null @@ -1,496 +0,0 @@ -/* $FreeBSD$ */ -/*- - * Copyright (c) 2011 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_KERNEL_H_ -#define _BSD_KERNEL_H_ - -#define _KERNEL -#undef __FreeBSD_version -#define __FreeBSD_version 1100000 - -#include -#include -#include - -#define isalpha(x) (((x) >= 'a' && (x) <= 'z') || ((x) >= 'A' && (x) <= 'Z')) -#define isdigit(x) ((x) >= '0' && (x) <= '9') -#define panic(...) do { printf("USB PANIC: " __VA_ARGS__); while (1) ; } while (0) -#define rebooting 0 -#define M_USB 0 -#define M_USBDEV 0 -#define USB_PROC_MAX 3 -#define USB_BUS_GIANT_PROC(bus) (usb_process + 2) -#define USB_BUS_NON_GIANT_PROC(bus) (usb_process + 2) -#define USB_BUS_EXPLORE_PROC(bus) (usb_process + 0) -#define USB_BUS_CONTROL_XFER_PROC(bus) (usb_process + 1) -#define SYSCTL_DECL(...) -#define SYSCTL_NODE(name,...) struct { } name __used -#define SYSCTL_INT(...) -#define TUNABLE_INT(...) -#define MALLOC_DECLARE(...) -#define MALLOC_DEFINE(...) -#define EVENTHANDLER_DECLARE(...) -#define EVENTHANDLER_INVOKE(...) -#define KASSERT(...) -#define SCHEDULER_STOPPED(x) (0) -#define PI_SWI(...) (0) -#define UNIQ_NAME(x) x -#define UNIQ_NAME_STR(x) #x -#define DEVCLASS_MAXUNIT 32 -#define MOD_LOAD 1 -#define MOD_UNLOAD 2 -#define DEVMETHOD(what,func) { #what, (void *)&func } -#define DEVMETHOD_END {0,0} -#define DRIVER_MODULE(name, busname, driver, devclass, evh, arg) \ - static struct module_data bsd_##name##_##busname##_driver_mod = { \ - evh, arg, #busname, #name, #busname "/" #name, \ - &driver, &devclass, { 0, 0 } }; \ -SYSINIT(bsd_##name##_##busname##_driver_mod, SI_SUB_DRIVERS, \ - SI_ORDER_MIDDLE, module_register, \ - &bsd_##name##_##busname##_driver_mod) -#define SYSINIT(uniq, subs, order, _func, _data) \ -const struct sysinit UNIQ_NAME(sysinit_##uniq) = { \ - .func = (_func), \ - .data = __DECONST(void *, _data) \ -}; \ -SYSINIT_ENTRY(uniq##_entry, "sysinit", (subs), \ - (order), "const struct sysinit", \ - UNIQ_NAME_STR(sysinit_##uniq), "SYSINIT") - -#define SYSUNINIT(uniq, subs, order, _func, _data) \ -const struct sysinit UNIQ_NAME(sysuninit_##uniq) = { \ - .func = (_func), \ - .data = __DECONST(void *, _data) \ -}; \ -SYSINIT_ENTRY(uniq##_entry, "sysuninit", (subs), \ - (order), "const struct sysuninit", \ - UNIQ_NAME_STR(sysuninit_##uniq), "SYSUNINIT") -#define MODULE_DEPEND(...) -#define MODULE_VERSION(...) -#define NULL ((void *)0) -#define BUS_SPACE_BARRIER_READ 0x01 -#define BUS_SPACE_BARRIER_WRITE 0x02 -#define hz 1000 -#undef PAGE_SIZE -#define PAGE_SIZE 4096 -#undef MIN -#define MIN(a,b) (((a) < (b)) ? (a) : (b)) -#undef MAX -#define MAX(a,b) (((a) > (b)) ? (a) : (b)) -#define MTX_DEF 0 -#define MTX_SPIN 0 -#define MTX_RECURSE 0 -#define SX_DUPOK 0 -#define SX_NOWITNESS 0 -#define WITNESS_WARN(...) -#define cold 0 -#define BUS_PROBE_GENERIC 0 -#define CALLOUT_RETURNUNLOCKED 0x1 -#undef va_list -#define va_list __builtin_va_list -#undef va_size -#define va_size(type) __builtin_va_size(type) -#undef va_start -#define va_start(ap, last) __builtin_va_start(ap, last) -#undef va_end -#define va_end(ap) __builtin_va_end(ap) -#undef va_arg -#define va_arg(ap, type) __builtin_va_arg((ap), type) -#define DEVICE_ATTACH(dev, ...) \ - (((device_attach_t *)(device_get_method(dev, "device_attach")))(dev,## __VA_ARGS__)) -#define DEVICE_DETACH(dev, ...) \ - (((device_detach_t *)(device_get_method(dev, "device_detach")))(dev,## __VA_ARGS__)) -#define DEVICE_PROBE(dev, ...) \ - (((device_probe_t *)(device_get_method(dev, "device_probe")))(dev,## __VA_ARGS__)) -#define DEVICE_RESUME(dev, ...) \ - (((device_resume_t *)(device_get_method(dev, "device_resume")))(dev,## __VA_ARGS__)) -#define DEVICE_SHUTDOWN(dev, ...) \ - (((device_shutdown_t *)(device_get_method(dev, "device_shutdown")))(dev,## __VA_ARGS__)) -#define DEVICE_SUSPEND(dev, ...) \ - (((device_suspend_t *)(device_get_method(dev, "device_suspend")))(dev,## __VA_ARGS__)) -#define USB_HANDLE_REQUEST(dev, ...) \ - (((usb_handle_request_t *)(device_get_method(dev, "usb_handle_request")))(dev,## __VA_ARGS__)) -#define USB_TAKE_CONTROLLER(dev, ...) \ - (((usb_take_controller_t *)(device_get_method(dev, "usb_take_controller")))(dev,## __VA_ARGS__)) - -enum { - SI_SUB_DUMMY = 0x0000000, - SI_SUB_LOCK = 0x1B00000, - SI_SUB_KLD = 0x2000000, - SI_SUB_DRIVERS = 0x3100000, - SI_SUB_PSEUDO = 0x7000000, - SI_SUB_KICK_SCHEDULER = 0xa000000, - SI_SUB_RUN_SCHEDULER = 0xfffffff -}; - -enum { - SI_ORDER_FIRST = 0x0000000, - SI_ORDER_SECOND = 0x0000001, - SI_ORDER_THIRD = 0x0000002, - SI_ORDER_FOURTH = 0x0000003, - SI_ORDER_MIDDLE = 0x1000000, - SI_ORDER_ANY = 0xfffffff /* last */ -}; - -struct uio; -struct thread; -struct malloc_type; -struct usb_process; - -#ifndef HAVE_STANDARD_DEFS -#define _UINT8_T_DECLARED -typedef unsigned char uint8_t; -#define _INT8_T_DECLARED -typedef signed char int8_t; -#define _UINT16_T_DECLARED -typedef unsigned short uint16_t; -#define _INT16_T_DECLARED -typedef signed short int16_t; -#define _UINT32_T_DECLARED -typedef unsigned int uint32_t; -#define _INT32_T_DECLARED -typedef signed int int32_t; -#define _UINT64_T_DECLARED -typedef unsigned long long uint64_t; -#define _INT16_T_DECLARED -typedef signed long long int64_t; - -typedef uint16_t uid_t; -typedef uint16_t gid_t; -typedef uint16_t mode_t; - -typedef uint8_t *caddr_t; -#define _UINTPTR_T_DECLARED -typedef unsigned long uintptr_t; - -#define _SIZE_T_DECLARED -typedef unsigned long size_t; -typedef unsigned long u_long; -#endif - -typedef unsigned long bus_addr_t; -typedef unsigned long bus_size_t; - -typedef void *bus_dmamap_t; -typedef void *bus_dma_tag_t; - -typedef void *bus_space_tag_t; -typedef uint8_t *bus_space_handle_t; - -/* SYSINIT API */ - -#include - -struct sysinit { - void (*func) (void *arg); - void *data; -}; - -/* MUTEX API */ - -struct mtx { - int owned; - struct mtx *parent; -}; - -#define mtx_assert(...) do { } while (0) -void mtx_init(struct mtx *, const char *, const char *, int); -void mtx_lock(struct mtx *); -void mtx_unlock(struct mtx *); -#define mtx_lock_spin(x) mtx_lock(x) -#define mtx_unlock_spin(x) mtx_unlock(x) -int mtx_owned(struct mtx *); -void mtx_destroy(struct mtx *); - -extern struct mtx Giant; - -/* SX API */ - -struct sx { - int owned; -}; - -#define sx_assert(...) do { } while (0) -#define sx_init(...) sx_init_flags(__VA_ARGS__, 0) -void sx_init_flags(struct sx *, const char *, int); -void sx_destroy(struct sx *); -void sx_xlock(struct sx *); -void sx_xunlock(struct sx *); -int sx_xlocked(struct sx *); - -/* CONDVAR API */ - -struct cv { - int sleeping; -}; - -void cv_init(struct cv *, const char *desc); -void cv_destroy(struct cv *); -void cv_wait(struct cv *, struct mtx *); -int cv_timedwait(struct cv *, struct mtx *, int); -void cv_signal(struct cv *); -void cv_broadcast(struct cv *); - -/* CALLOUT API */ - -typedef void callout_fn_t (void *); - -extern volatile int ticks; - -struct callout { - LIST_ENTRY(callout) entry; - callout_fn_t *func; - void *arg; - struct mtx *mtx; - int flags; - int timeout; -}; - -void callout_init_mtx(struct callout *, struct mtx *, int); -void callout_reset(struct callout *, int, callout_fn_t *, void *); -void callout_stop(struct callout *); -void callout_drain(struct callout *); -int callout_pending(struct callout *); -void callout_process(int timeout); - -/* DEVICE API */ - -struct driver; -struct devclass; -struct device; -struct module; -struct module_data; - -typedef struct driver driver_t; -typedef struct devclass *devclass_t; -typedef struct device *device_t; -typedef void (driver_intr_t)(void *arg); -typedef int (driver_filter_t)(void *arg); -#define FILTER_STRAY 0x01 -#define FILTER_HANDLED 0x02 -#define FILTER_SCHEDULE_THREAD 0x04 - -typedef int device_attach_t (device_t dev); -typedef int device_detach_t (device_t dev); -typedef int device_resume_t (device_t dev); -typedef int device_shutdown_t (device_t dev); -typedef int device_probe_t (device_t dev); -typedef int device_suspend_t (device_t dev); - -typedef int bus_child_location_str_t (device_t parent, device_t child, char *buf, size_t buflen); -typedef int bus_child_pnpinfo_str_t (device_t parent, device_t child, char *buf, size_t buflen); -typedef void bus_driver_added_t (device_t dev, driver_t *driver); - -struct device_method { - const char *desc; - void *const func; -}; - -typedef struct device_method device_method_t; - -struct device { - TAILQ_HEAD(device_list, device) dev_children; - TAILQ_ENTRY(device) dev_link; - - struct device *dev_parent; - const struct module_data *dev_module; - void *dev_sc; - void *dev_aux; - driver_filter_t *dev_irq_filter; - driver_intr_t *dev_irq_fn; - void *dev_irq_arg; - - uint16_t dev_unit; - - char dev_nameunit[64]; - char dev_desc[64]; - - uint8_t dev_res_alloc:1; - uint8_t dev_quiet:1; - uint8_t dev_softc_set:1; - uint8_t dev_softc_alloc:1; - uint8_t dev_attached:1; - uint8_t dev_fixed_class:1; - uint8_t dev_unit_manual:1; -}; - -struct devclass { - device_t dev_list[DEVCLASS_MAXUNIT]; -}; - -struct driver { - const char *name; - const struct device_method *methods; - uint32_t size; -}; - -struct module_data { - int (*callback) (struct module *, int, void *arg); - void *arg; - const char *bus_name; - const char *mod_name; - const char *long_name; - const struct driver *driver; - struct devclass **devclass_pp; - TAILQ_ENTRY(module_data) entry; -}; - -device_t device_get_parent(device_t dev); -void *device_get_method(device_t dev, const char *what); -const char *device_get_name(device_t dev); -const char *device_get_nameunit(device_t dev); - -#define device_printf(dev, fmt,...) \ - printf("%s: " fmt, device_get_nameunit(dev),## __VA_ARGS__) -device_t device_add_child(device_t dev, const char *name, int unit); -void device_quiet(device_t dev); -void device_set_interrupt(device_t dev, driver_filter_t *, driver_intr_t *, void *); -void device_run_interrupts(device_t parent); -void device_set_ivars(device_t dev, void *ivars); -void *device_get_ivars(device_t dev); -const char *device_get_desc(device_t dev); -int device_probe_and_attach(device_t dev); -int device_detach(device_t dev); -void *device_get_softc(device_t dev); -void device_set_softc(device_t dev, void *softc); -int device_delete_child(device_t dev, device_t child); -int device_delete_children(device_t dev); -int device_is_attached(device_t dev); -void device_set_desc(device_t dev, const char *desc); -void device_set_desc_copy(device_t dev, const char *desc); -int device_get_unit(device_t dev); -void *devclass_get_softc(devclass_t dc, int unit); -int devclass_get_maxunit(devclass_t dc); -device_t devclass_get_device(devclass_t dc, int unit); -devclass_t devclass_find(const char *classname); - -#define bus_get_dma_tag(...) (NULL) -int bus_generic_detach(device_t dev); -int bus_generic_resume(device_t dev); -int bus_generic_shutdown(device_t dev); -int bus_generic_suspend(device_t dev); -int bus_generic_print_child(device_t dev, device_t child); -void bus_generic_driver_added(device_t dev, driver_t *driver); - -/* BUS SPACE API */ - -void bus_space_write_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint8_t data); -void bus_space_write_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint16_t data); -void bus_space_write_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset, uint32_t data); - -uint8_t bus_space_read_1(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); -uint16_t bus_space_read_2(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); -uint32_t bus_space_read_4(bus_space_tag_t t, bus_space_handle_t h, bus_size_t offset); - -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); -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); -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); - -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); -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); -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); - -void bus_space_read_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count); -void bus_space_write_region_1(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint8_t *datap, bus_size_t count); -void bus_space_read_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count); -void bus_space_write_region_4(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, uint32_t *datap, bus_size_t count); - -void bus_space_barrier(bus_space_tag_t space, bus_space_handle_t handle, bus_size_t offset, bus_size_t length, int flags); - -void module_register(void *); - -/* LIB-C */ - -void *memset(void *, int, size_t len); -void *memcpy(void *, const void *, size_t len); -int printf(const char *,...) __printflike(1, 2); -int snprintf(char *restrict str, size_t size, const char *restrict format,...) __printflike(3, 4); -size_t strlen(const char *s); - -/* MALLOC API */ - -#undef malloc -#define malloc(s,x,f) usb_malloc(s) -void *usb_malloc(size_t); - -#undef free -#define free(p,x) usb_free(p) -void usb_free(void *); - -#define strdup(p,x) usb_strdup(p) -char *usb_strdup(const char *str); - -/* ENDIANNESS */ - -#ifndef HAVE_ENDIAN_DEFS - -/* Assume little endian */ - -#define htole64(x) ((uint64_t)(x)) -#define le64toh(x) ((uint64_t)(x)) - -#define htole32(x) ((uint32_t)(x)) -#define le32toh(x) ((uint32_t)(x)) - -#define htole16(x) ((uint16_t)(x)) -#define le16toh(x) ((uint16_t)(x)) - -#define be32toh(x) ((uint32_t)(x)) -#define htobe32(x) ((uint32_t)(x)) - -#else -#include -#endif - -/* USB */ - -typedef int usb_handle_request_t (device_t dev, const void *req, void **pptr, uint16_t *plen, uint16_t offset, uint8_t *pstate); -typedef int usb_take_controller_t (device_t dev); - -void usb_idle(void); -void usb_init(void); -void usb_uninit(void); - -/* set some defaults */ - -#ifndef USB_POOL_SIZE -#define USB_POOL_SIZE (1024*1024) /* 1 MByte */ -#endif - -int pause(const char *, int); -void DELAY(unsigned int); - -/* OTHER */ - -struct selinfo { -}; - -/* SYSTEM STARTUP API */ - -extern const void *sysinit_data[]; -extern const void *sysuninit_data[]; - -#endif /* _BSD_KERNEL_H_ */ diff --git a/sys/boot/usb/tools/sysinit.c b/sys/boot/usb/tools/sysinit.c deleted file mode 100644 index b968fe0..0000000 --- a/sys/boot/usb/tools/sysinit.c +++ /dev/null @@ -1,331 +0,0 @@ -/* $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 -#include -#include -#include -#include -#include -#include -#include -#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/sys/boot/usb/tools/sysinit.h b/sys/boot/usb/tools/sysinit.h deleted file mode 100644 index a7a450e..0000000 --- a/sys/boot/usb/tools/sysinit.h +++ /dev/null @@ -1,57 +0,0 @@ -/* $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 _SYSINIT_H_ -#define _SYSINIT_H_ - -struct sysinit_data { - uint8_t b_keyword_name[64]; - uint8_t b_debug_info[128]; - uint8_t b_global_type[128]; - uint8_t b_global_name[128]; - uint8_t b_file_name[256]; - uint32_t dw_endian32; - uint32_t dw_msb_value; /* must be non-zero, else entry is skipped */ - uint32_t dw_lsb_value; - uint32_t dw_file_line; -} __attribute__((__packed__)); - -#define SYSINIT_ENTRY(uniq, keyword, msb, lsb, g_type, g_name, debug) \ - static const struct sysinit_data sysinit_##uniq \ - __attribute__((__section__(".debug.sysinit"), \ - __used__, __aligned__(1))) = { \ - .b_keyword_name = { keyword }, \ - .b_debug_info = { debug }, \ - .b_global_type = { g_type }, \ - .b_global_name = { g_name }, \ - .b_file_name = { __FILE__ }, \ - .dw_endian32 = 0x76543210U, \ - .dw_msb_value = (msb), \ - .dw_lsb_value = (lsb), \ - .dw_file_line = __LINE__ \ -} - -#endif /* _SYSINIT_H_ */ diff --git a/sys/boot/usb/usbcore.mk b/sys/boot/usb/usbcore.mk new file mode 100644 index 0000000..8b6c59a --- /dev/null +++ b/sys/boot/usb/usbcore.mk @@ -0,0 +1,154 @@ +# +# $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}/../.. + +.PATH: \ + ${USBCOREDIR} \ + ${USBCOREDIR}/storage \ + ${S}/dev/usb \ + ${S}/dev/usb/controller \ + ${S}/dev/usb/serial \ + ${S}/dev/usb/storage \ + ${S}/dev/usb/template +.undef S + +CFLAGS+= -DUSB_MSCTEST_BULK_SIZE=65536 +CFLAGS+= -DUSB_POOL_SIZE=131072 + +# +# 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_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 + +# +# USB mass storage support +# +SRCS+= umass_common.c + +.if defined(HAVE_UMASS_LOADER) +CFLAGS+= -I${.CURDIR}/../common +SRCS+= umass_loader.c +.endif + diff --git a/usr.bin/Makefile b/usr.bin/Makefile index 353816a..7120723 100644 --- a/usr.bin/Makefile +++ b/usr.bin/Makefile @@ -350,6 +350,7 @@ SUBDIR+= indent SUBDIR+= lex SUBDIR+= mkstr SUBDIR+= rpcgen +SUBDIR+= sysinit SUBDIR+= unifdef SUBDIR+= xlint SUBDIR+= xstr diff --git a/usr.bin/sysinit/Makefile b/usr.bin/sysinit/Makefile new file mode 100644 index 0000000..1e25cad --- /dev/null +++ b/usr.bin/sysinit/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +PROG= sysinit +NO_MAN= + +CFLAGS+= -I${.CURDIR}/../../sys/boot/kshim + +.include diff --git a/usr.bin/sysinit/sysinit.c b/usr.bin/sysinit/sysinit.c new file mode 100644 index 0000000..c25afde --- /dev/null +++ b/usr.bin/sysinit/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 +#include +#include +#include +#include +#include +#include +#include +#include + +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); +}