svn commit: r269541 - in head: . sys/boot/kshim sys/boot/usb sys/boot/usb/tools
Brooks Davis
brooks at FreeBSD.org
Mon Aug 4 23:00:15 UTC 2014
Author: brooks
Date: Mon Aug 4 23:00:13 2014
New Revision: 269541
URL: http://svnweb.freebsd.org/changeset/base/269541
Log:
Merge from CheriBSD:
Make the sysinit tool a build tool rather than building in with
/usr/bin/cc and running it from OBJDIR. (It will be moved to usr.bin
once a manpage is written and a few style cleanups are done.)
Split the makefile bits for Hans' kernel shim layer into their own
includable kshim.mk.
Move USB support into a .mk file so loaders can include it.
Added:
head/sys/boot/kshim/
head/sys/boot/kshim/bsd_busspace.c
- copied unchanged from r269540, head/sys/boot/usb/bsd_busspace.c
head/sys/boot/kshim/bsd_global.h
- copied unchanged from r269521, head/sys/boot/usb/bsd_global.h
head/sys/boot/kshim/bsd_kernel.c
- copied unchanged from r269521, head/sys/boot/usb/bsd_kernel.c
head/sys/boot/kshim/bsd_kernel.h
- copied unchanged from r269521, head/sys/boot/usb/bsd_kernel.h
head/sys/boot/kshim/kshim.mk
- copied, changed from r269521, head/sys/boot/usb/Makefile
head/sys/boot/kshim/sysinit.h
- copied unchanged from r269521, head/sys/boot/usb/tools/sysinit.h
head/sys/boot/usb/tools/Makefile (contents, props changed)
head/sys/boot/usb/usbcore.mk
- copied, changed from r269521, head/sys/boot/usb/Makefile
Deleted:
head/sys/boot/usb/bsd_busspace.c
head/sys/boot/usb/bsd_global.h
head/sys/boot/usb/bsd_kernel.c
head/sys/boot/usb/bsd_kernel.h
head/sys/boot/usb/tools/sysinit.h
Modified:
head/Makefile.inc1
head/sys/boot/usb/Makefile
Modified: head/Makefile.inc1
==============================================================================
--- head/Makefile.inc1 Mon Aug 4 22:37:02 2014 (r269540)
+++ head/Makefile.inc1 Mon Aug 4 23:00:13 2014 (r269541)
@@ -1406,7 +1406,8 @@ cross-tools: .MAKE
usr.bin/xlint/lint1 usr.bin/xlint/lint2 usr.bin/xlint/xlint \
${_btxld} \
${_crunchide} \
- ${_kgzip}
+ ${_kgzip} \
+ sys/boot/usb/tools
${_+_}@${ECHODIR} "===> ${_tool} (obj,depend,all,install)"; \
cd ${.CURDIR}/${_tool} && \
${MAKE} DIRPRFX=${_tool}/ obj && \
Copied: head/sys/boot/kshim/bsd_busspace.c (from r269540, head/sys/boot/usb/bsd_busspace.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/boot/kshim/bsd_busspace.c Mon Aug 4 23:00:13 2014 (r269541, copy of r269540, head/sys/boot/usb/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 <bsd_kernel.h>
+
+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;
+ }
+}
Copied: head/sys/boot/kshim/bsd_global.h (from r269521, head/sys/boot/usb/bsd_global.h)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/boot/kshim/bsd_global.h Mon Aug 4 23:00:13 2014 (r269541, copy of r269521, head/sys/boot/usb/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 <bsd_kernel.h>
+
+#define USB_DEBUG_VAR usb_debug
+#include <dev/usb/usb_freebsd_loader.h>
+#include <dev/usb/usb_endian.h>
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_debug.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_dynamic.h>
+#include <dev/usb/usb_transfer.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_hub.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_cdc.h>
+#include <dev/usb/usb_dev.h>
+#include <dev/usb/usb_mbuf.h>
+#include <dev/usb/usb_msctest.h>
+#include <dev/usb/usb_pci.h>
+#include <dev/usb/usb_pf.h>
+#include <dev/usb/usb_request.h>
+#include <dev/usb/usb_util.h>
+#include <dev/usb/usb_compat_linux.h>
+#include <dev/usb/usbhid.h>
+#include <dev/usb/usb_ioctl.h>
+#include <dev/usb/usb_generic.h>
+#include <dev/usb/quirk/usb_quirk.h>
+#include <dev/usb/template/usb_template.h>
+
+extern struct usb_process usb_process[USB_PROC_MAX];
+
+#endif /* _BSD_GLOBAL_H_ */
Copied: head/sys/boot/kshim/bsd_kernel.c (from r269521, head/sys/boot/usb/bsd_kernel.c)
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/boot/kshim/bsd_kernel.c Mon Aug 4 23:00:13 2014 (r269541, copy of r269521, head/sys/boot/usb/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 <bsd_global.h>
+
+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);
+}
+
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list