Page MenuHomeFreeBSD

D47417.diff
No OneTemporary

D47417.diff

diff --git a/sys/compat/linsysfs/linsysfs.h b/sys/compat/linsysfs/linsysfs.h
--- a/sys/compat/linsysfs/linsysfs.h
+++ b/sys/compat/linsysfs/linsysfs.h
@@ -28,11 +28,23 @@
#ifndef _COMPAT_LINSYSFS_LINSYSFS_H_
#define _COMPAT_LINSYSFS_LINSYSFS_H_
+#include "usbdevs.h"
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_device.h>
+
MALLOC_DECLARE(M_LINSYSFS);
extern struct pfs_node *net;
+extern struct pfs_node *tty, *platform;
+
+struct pfs_node *linsysfs_find_uhub(device_t dev);
+void linsysfs_usb_create_nodes(struct pfs_node *dir, struct usb_device *udev);
void linsysfs_net_init(void);
void linsysfs_net_uninit(void);
+void linsysfs_tty_init(void);
+void linsysfs_tty_uninit(void);
+
#endif /* _COMPAT_LINSYSFS_LINSYSFS_H_ */
diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c
--- a/sys/compat/linsysfs/linsysfs.c
+++ b/sys/compat/linsysfs/linsysfs.c
@@ -36,10 +36,22 @@
#include <sys/smp.h>
#include <sys/bus.h>
#include <sys/pciio.h>
+#include <sys/syslog.h>
+#include <sys/condvar.h>
#include <dev/pci/pcivar.h>
#include <dev/pci/pcireg.h>
+#include "usbdevs.h"
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usb_device.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_hub.h>
+#include <dev/usb/serial/uftdi.h>
+
#include <compat/linux/linux_util.h>
#include <fs/pseudofs/pseudofs.h>
@@ -53,10 +65,26 @@
char *name;
};
-TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
+static TAILQ_HEAD(,scsi_host_queue) scsi_host_q = TAILQ_HEAD_INITIALIZER(scsi_host_q);
static int host_number = 0;
+/*
+ * Mapping of uhub devices to sysfs nodes.
+ * We shouldn't have to sync access, since they
+ * are created only in linsysfs_init() and
+ * thereafter only queried via linsysfs_find_uhub().
+ */
+struct uhub_queue {
+ TAILQ_ENTRY(uhub_queue) uhub_next;
+ device_t dev;
+ struct pfs_node *dir;
+};
+
+static TAILQ_HEAD(,uhub_queue) uhub_q = TAILQ_HEAD_INITIALIZER(uhub_q);
+
+static int usb_number = 0;
+
static int
atoi(const char *str)
{
@@ -251,6 +279,106 @@
return (0);
}
+struct pfs_node *
+linsysfs_find_uhub(device_t dev)
+{
+ struct uhub_queue *uhub;
+
+ TAILQ_FOREACH(uhub, &uhub_q, uhub_next) {
+ if (uhub->dev == dev)
+ return (uhub->dir);
+ }
+
+ return (NULL);
+}
+
+/*
+ * USB device fillers
+ */
+static int
+linsysfs_usb_busnum(PFS_FILL_ARGS)
+{
+ struct usb_device *udev = pn->pn_data;
+ sbuf_printf(sb, "%d\n", device_get_unit(udev->bus->bdev));
+ return (0);
+}
+
+static int
+linsysfs_usb_devnum(PFS_FILL_ARGS)
+{
+ /*
+ * With USB_HAVE_COMPAT_LINUX there is also udev->devnum,
+ * which is the same as device_get_unit(dev).
+ */
+ struct usb_device *udev = pn->pn_data;
+ sbuf_printf(sb, "%d\n", udev->device_index);
+ return (0);
+}
+
+static int
+linsysfs_fill_uword(PFS_FILL_ARGS)
+{
+ uWord *word = pn->pn_data;
+ sbuf_printf(sb, "%04x\n", UGETW(*word));
+ return (0);
+}
+
+static int
+linsysfs_fill_string(PFS_FILL_ARGS)
+{
+ const char *str = pn->pn_data;
+ sbuf_printf(sb, "%s\n", str);
+ return (0);
+}
+
+void
+linsysfs_usb_create_nodes(struct pfs_node *dir, struct usb_device *udev)
+{
+ struct pfs_node *cur_file;
+
+ cur_file = pfs_create_file(dir, "idVendor",
+ &linsysfs_fill_uword,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)&udev->ddesc.idVendor;
+ cur_file = pfs_create_file(dir, "idProduct",
+ &linsysfs_fill_uword,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)&udev->ddesc.idProduct;
+ cur_file = pfs_create_file(dir, "bcdDevice",
+ &linsysfs_fill_uword,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)&udev->ddesc.bcdDevice;
+ if (udev->bus != NULL) {
+ cur_file = pfs_create_file(dir, "busnum",
+ &linsysfs_usb_busnum,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)udev;
+ }
+ cur_file = pfs_create_file(dir, "devnum",
+ &linsysfs_usb_devnum,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)udev;
+ if (udev->product) {
+ cur_file = pfs_create_file(dir, "product",
+ &linsysfs_fill_string,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)udev->product;
+ }
+ if (udev->manufacturer) {
+ cur_file = pfs_create_file(dir, "manufacturer",
+ &linsysfs_fill_string,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)udev->manufacturer;
+ }
+ if (udev->serial) {
+ cur_file = pfs_create_file(dir, "serial",
+ &linsysfs_fill_string,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void*)udev->serial;
+ }
+ /* FIXME: add some more nodes */
+}
+
#undef PCI_DEV
#define PCI_DEV "pci"
#define DRMN_DEV "drmn"
@@ -329,6 +457,11 @@
/* libdrm just checks that the link ends in "/pci" */
cur_file->pn_data = "/sys/bus/pci";
+#if 0
+ log(LOG_DEBUG, "baseclass=%d, subclass=%d\n",
+ dinfo->cfg.baseclass, dinfo->cfg.subclass);
+#endif
+
if (dinfo->cfg.baseclass == PCIC_STORAGE) {
/* DJA only make this if needed */
sprintf(host, "host%d", host_number++);
@@ -362,6 +495,10 @@
}
free(device, M_TEMP);
free(host, M_TEMP);
+ } else {
+#if 0
+ log(LOG_DEBUG, "Unhandled parent devclass: %s\n", name);
+#endif
}
}
@@ -396,7 +533,30 @@
NULL, NULL, PFS_RD);
cur_file->pn_data = (void*)dir;
}
+ } else if (name != NULL && strcmp(name, "uhub") == 0) {
+ struct uhub_softc *sc = device_get_softc(dev);
+ if (sc != NULL && sc->sc_udev != NULL) {
+ char name[MAXPATHLEN];
+ snprintf(name, sizeof(name), "usb%d", usb_number++);
+ sub_dir = pfs_create_dir(dir, name,
+ NULL, NULL, NULL, 0);
+ linsysfs_usb_create_nodes(sub_dir, sc->sc_udev);
+
+ struct uhub_queue *uhub = malloc(sizeof(struct uhub_queue),
+ M_DEVBUF, M_NOWAIT);
+ uhub->dev = dev;
+ uhub->dir = sub_dir;
+ TAILQ_INSERT_TAIL(&uhub_q, uhub, uhub_next);
+ }
+ } else {
+#if 0
+ log(LOG_DEBUG, "Unhandled devclass: %s\n", name);
+#endif
}
+ } else {
+#if 0
+ log(LOG_DEBUG, "Device without parent: %s\n", device_get_name(dev));
+#endif
}
error = device_get_children(dev, &children, &nchildren);
@@ -480,8 +640,6 @@
devclass_t devclass;
device_t dev;
- TAILQ_INIT(&scsi_host_q);
-
root = pi->pi_root;
/* /sys/bus/... */
@@ -496,6 +654,9 @@
/* /sys/class/net/.. */
net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0);
+ /* /sys/class/tty/... */
+ tty = pfs_create_dir(class, "tty", NULL, NULL, NULL, 0);
+
/* /sys/dev/... */
devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0);
chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0);
@@ -527,12 +688,16 @@
linsysfs_listcpus(cpu);
+ /* /sys/devices/platform */
+ platform = pfs_create_dir(dir, "platform", NULL, NULL, NULL, 0);
+
/* /sys/kernel */
kernel = pfs_create_dir(root, "kernel", NULL, NULL, NULL, 0);
/* /sys/kernel/debug, mountpoint for lindebugfs. */
pfs_create_dir(kernel, "debug", NULL, NULL, NULL, 0);
linsysfs_net_init();
+ linsysfs_tty_init();
return (0);
}
@@ -552,7 +717,15 @@
free(scsi_host, M_TEMP);
}
+ struct uhub_queue *uhub, *uhub_tmp;
+
+ TAILQ_FOREACH_SAFE(uhub, &uhub_q, uhub_next, uhub_tmp) {
+ TAILQ_REMOVE(&uhub_q, uhub, uhub_next);
+ free(uhub, M_TEMP);
+ }
+
linsysfs_net_uninit();
+ linsysfs_tty_uninit();
return (0);
}
diff --git a/sys/compat/linsysfs/linsysfs_tty.c b/sys/compat/linsysfs/linsysfs_tty.c
new file mode 100644
--- /dev/null
+++ b/sys/compat/linsysfs/linsysfs_tty.c
@@ -0,0 +1,435 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2024 Robin Haberkorn <robin.haberkorn@googlemail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/dirent.h>
+#include <sys/eventhandler.h>
+#include <sys/kernel.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/sbuf.h>
+#include <sys/socket.h>
+#include <sys/syslog.h>
+#include <sys/tty.h>
+#include <sys/types.h>
+
+#include <fs/devfs/devfs.h>
+#include <machine/bus.h>
+
+#include <dev/uart/uart.h>
+#include <dev/uart/uart_bus.h>
+#include <dev/uart/uart_cpu.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+#include <dev/usb/usbdi_util.h>
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_ioctl.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/serial/usb_serial.h>
+#include <dev/usb/serial/uftdi.h>
+#include <dev/usb/serial/umodem.h>
+
+#include <compat/linux/linux.h>
+#include <compat/linux/linux_common.h>
+#include <compat/linux/linux_util.h>
+#include <fs/pseudofs/pseudofs.h>
+
+#include <compat/linsysfs/linsysfs.h>
+
+struct pfs_node *tty, *platform;
+static eventhandler_tag tty_attach_tag, tty_detach_tag;
+
+static uint32_t tty_latch_count = 0;
+static struct mtx tty_latch_mtx;
+MTX_SYSINIT(tty_latch_mtx, &tty_latch_mtx, "lsftty", MTX_DEF);
+
+struct tty_nodes_queue {
+ TAILQ_ENTRY(tty_nodes_queue) tty_nodes_next;
+ device_t dev;
+ struct pfs_node *dir;
+ struct pfs_node *link;
+};
+static TAILQ_HEAD(,tty_nodes_queue) tty_nodes_q = TAILQ_HEAD_INITIALIZER(tty_nodes_q);
+
+/*
+ * NOTE: "pts" devices are handled differently.
+ * In particular they don't expose their software context (softc),
+ * so it's not straight forward to get their /dev name.
+ */
+static const char *linsysfs_tty_devclasses[] = {"uart", "umodem", "uftdi", NULL};
+
+/*
+ * FIXME: Why is this used instead of a plain mtx_lock() and mtx_unlock()?
+ */
+static void
+linsysfs_tty_latch_hold(void)
+{
+ mtx_lock(&tty_latch_mtx);
+ if (tty_latch_count++ > 0)
+ mtx_sleep(&tty_latch_count, &tty_latch_mtx, PDROP, "lsftty", 0);
+ else
+ mtx_unlock(&tty_latch_mtx);
+}
+
+static void
+linsysfs_tty_latch_rele(void)
+{
+ mtx_lock(&tty_latch_mtx);
+ if (--tty_latch_count > 0)
+ wakeup_one(&tty_latch_count);
+ mtx_unlock(&tty_latch_mtx);
+}
+
+/*
+ * Get the device name as used under /dev.
+ */
+static struct tty *
+linsysfs_tty_get(device_t dev)
+{
+ const char *class_name = device_get_name(dev);
+ if (class_name == NULL)
+ return (NULL);
+
+ if (strcmp(class_name, "uart") == 0) {
+ /* should be ttyuX */
+ struct uart_softc *sc = device_get_softc(dev);
+ if (sc != NULL /*&& sc->sc_sysdev != NULL && sc->sc_sysdev->type == UART_DEV_CONSOLE*/)
+ return (sc->sc_u.u_tty.tp);
+ } else if (strcmp(class_name, "uftdi") == 0) {
+ /* should be ttyUX */
+ struct uftdi_softc *sc = device_get_softc(dev);
+ return (sc->sc_ucom.sc_tty);
+ } else if (strcmp(class_name, "umodem") == 0) {
+ /* should be ttyUX */
+ struct umodem_softc *sc = device_get_softc(dev);
+ return (sc->sc_ucom.sc_tty);
+#if 0
+ } else if (strcmp(class_name, "uftdi") == 0 ||
+ strcmp(class_name, "umodem") == 0) {
+ /*
+ * NOTE: This depends on the layout of private softc structures.
+ * On the other hand it should work with drivers like u3g as well.
+ */
+ struct ucom_super_softc *sc = device_get_softc(dev);
+ struct ucom_softc *uc = (struct ucom_softc *)(sc + 1);
+ return (uc->sc_tty);
+#endif
+ }
+
+ return (NULL);
+}
+
+static int
+linsysfs_tty_dev(PFS_FILL_ARGS)
+{
+ device_t dev = pn->pn_data;
+
+ struct tty *tp = linsysfs_tty_get(dev);
+ if (tp == NULL)
+ return (0);
+ dev_t devn = tty_udev(tp);
+
+ sbuf_printf(sb, "%d:%d\n",
+ linux_encode_major(devn), linux_encode_minor(devn));
+ return (0);
+}
+
+static int
+linsysfs_tty_device(PFS_FILL_ARGS)
+{
+ struct pfs_node *device = pn->pn_data;
+
+ /*
+ * Either /sys/platform/DRIVER or
+ * /sys/devices/pci.../X/usbX/X-Y/ttyUX.
+ */
+ sbuf_printf(sb, "../../../%s", device->pn_name);
+ return (0);
+}
+
+static int
+linsysfs_tty_subsystem(PFS_FILL_ARGS)
+{
+ char buf[MAXPATHLEN] = "";
+
+ for (struct pfs_node *cur = pn->pn_data;
+ cur->pn_parent != NULL; cur = cur->pn_parent)
+ strcat(buf, "../");
+
+ sbuf_printf(sb, "%sclass/tty", buf);
+ return (0);
+}
+
+static int
+linsysfs_tty_uevent(PFS_FILL_ARGS)
+{
+ device_t dev = pn->pn_data;
+
+ struct tty *tp = linsysfs_tty_get(dev);
+ if (tp == NULL)
+ return (0);
+ dev_t devn = tty_udev(tp);
+
+ sbuf_printf(sb, "MAJOR=%d\nMINOR=%d\nDEVNAME=%s\n",
+ linux_encode_major(devn), linux_encode_minor(devn), tty_devname(tp));
+
+ return (0);
+}
+
+static int
+linsysfs_tty_class(PFS_FILL_ARGS)
+{
+ struct pfs_node *cur = pn->pn_data;
+
+ char *temp, *path;
+
+ temp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ path[0] = '\0';
+
+ do {
+ snprintf(temp, MAXPATHLEN, "%s/%s", cur->pn_name, path);
+ strlcpy(path, temp, MAXPATHLEN);
+ cur = cur->pn_parent;
+ } while (cur->pn_parent != NULL);
+
+ path[strlen(path) - 1] = '\0'; /* remove extra slash */
+ /* path will always be unter /sys/devices */
+ sbuf_printf(sb, "../../%s", path);
+
+ free(temp, M_TEMP);
+ free(path, M_TEMP);
+ return (0);
+}
+
+static void
+linsysfs_tty_add(device_t dev)
+{
+ struct tty_nodes_queue *nq;
+ struct pfs_node *cur_file;
+ struct pfs_node *per_dev_entry = NULL;
+ struct pfs_node *parent_entry = NULL;
+ struct pfs_node *ttydir, *tty_entry, *tty_link;
+ const char *class_name = device_get_name(dev);
+
+ struct tty *tp = linsysfs_tty_get(dev);
+ if (tp == NULL) {
+#if 0
+ log(LOG_DEBUG, "Cannot get device name of %s\n",
+ device_get_nameunit(dev));
+#endif
+ return;
+ }
+
+ device_t parent_dev = device_get_parent(dev);
+ if (parent_dev != NULL) {
+ struct pfs_node *uhub = linsysfs_find_uhub(parent_dev);
+ if (uhub != NULL) {
+ struct usb_device *udev = NULL;
+
+ if (strcmp(class_name, "uftdi") == 0) {
+ struct uftdi_softc *sc = device_get_softc(dev);
+ udev = sc != NULL ? sc->sc_udev : NULL;
+ } else if (strcmp(class_name, "umodem") == 0) {
+ struct umodem_softc *sc = device_get_softc(dev);
+ udev = sc != NULL ? sc->sc_udev : NULL;
+ }
+
+ if (udev != NULL && udev->bus != NULL) {
+ char name[MAXPATHLEN];
+ snprintf(name, sizeof(name), "%d-%d",
+ device_get_unit(udev->bus->bdev),
+ udev->device_index);
+ /* /sys/devices/pci/X/X/usbX/X-Y */
+ parent_entry = pfs_create_dir(uhub, name,
+ NULL, NULL, NULL, 0);
+ linsysfs_usb_create_nodes(parent_entry, udev);
+
+ /* /sys/devices/pci/X/X/usbX/X-Y/ttyX */
+ parent_entry = pfs_create_dir(parent_entry, tty_devname(tp),
+ NULL, NULL, NULL, 0);
+ /* FIXME: fill these nodes */
+
+ per_dev_entry = parent_entry;
+ }
+ }
+ }
+
+ /*
+ * If the TTY node is not located under a per-USB node,
+ * we create a generic per-driver entry under /sys/platform.
+ *
+ * These cannot be initialized in linsysfs_tty_init().
+ * 1.) There could be asynchronous events before they are created.
+ * 2.) Modules could be loaded only afterwards.
+ */
+ if (parent_entry == NULL)
+ parent_entry = pfs_find_node(platform, class_name);
+ if (parent_entry == NULL)
+ /* /sys/devices/platform/CLASS */
+ parent_entry = pfs_create_dir(platform, class_name,
+ NULL, NULL, NULL, 0);
+ MPASS(parent_entry != NULL);
+
+ /* PARENT/tty */
+ ttydir = pfs_find_node(parent_entry, "tty");
+ if (ttydir == NULL)
+ ttydir = pfs_create_dir(parent_entry, "tty",
+ NULL, NULL, NULL, 0);
+ /* FIXME: Fill the rest of the platform structure */
+
+ tty_entry = pfs_find_node(ttydir, tty_devname(tp));
+ if (tty_entry == NULL) {
+ /* PARENT/tty/ttyX */
+ tty_entry = pfs_create_dir(ttydir, tty_devname(tp),
+ NULL, NULL, NULL, 0);
+ /* FIXME: Add "active"? */
+ cur_file = pfs_create_file(tty_entry, "dev", &linsysfs_tty_dev,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void *)dev;
+ cur_file = pfs_create_link(tty_entry, "device", &linsysfs_tty_device,
+ NULL, NULL, NULL, 0);
+ cur_file->pn_data = (void *)parent_entry;
+ /* FIXME: Fill power? */
+ cur_file = pfs_create_dir(tty_entry, "power",
+ NULL, NULL, NULL, 0);
+ cur_file = pfs_create_link(tty_entry, "subsystem", &linsysfs_tty_subsystem,
+ NULL, NULL, NULL, 0);
+ cur_file->pn_data = (void *)tty_entry;
+ cur_file = pfs_create_file(tty_entry, "uevent", &linsysfs_tty_uevent,
+ NULL, NULL, NULL, PFS_RD);
+ cur_file->pn_data = (void *)dev;
+ if (per_dev_entry == NULL)
+ per_dev_entry = tty_entry;
+
+ /* /sys/class/tty/ttyX -> PARENT/tty/ttyX */
+ tty_link = pfs_create_link(tty, tty_devname(tp), &linsysfs_tty_class,
+ NULL, NULL, NULL, 0);
+ tty_link->pn_data = (void *)tty_entry;
+ }
+ /*
+ * There is a small time window between registering the device_attach
+ * eventhandler and creating the initial list of TTY devices.
+ * If a device is attached in the meantime, it might already
+ * exist in tty_nodes_q.
+ */
+ TAILQ_FOREACH(nq, &tty_nodes_q, tty_nodes_next) {
+ if (nq->dev == dev)
+ return;
+ }
+ MPASS(tty_link != NULL && per_dev_entry != NULL);
+ nq = malloc(sizeof(*nq), M_LINSYSFS, M_WAITOK);
+ nq->dev = dev;
+ nq->dir = per_dev_entry;
+ nq->link = tty_link;
+ TAILQ_INSERT_TAIL(&tty_nodes_q, nq, tty_nodes_next);
+}
+
+static void
+linsysfs_tty_delete(device_t dev)
+{
+ struct tty_nodes_queue *nq, *nq_tmp;
+
+ TAILQ_FOREACH_SAFE(nq, &tty_nodes_q, tty_nodes_next, nq_tmp) {
+ if (nq->dev == dev) {
+ TAILQ_REMOVE(&tty_nodes_q, nq, tty_nodes_next);
+ pfs_destroy(nq->link);
+ pfs_destroy(nq->dir);
+ free(nq, M_LINSYSFS);
+ break;
+ }
+ }
+}
+
+static void
+linsysfs_tty_attach(void *arg __unused, device_t dev)
+{
+ linsysfs_tty_latch_hold();
+ linsysfs_tty_add(dev);
+ linsysfs_tty_latch_rele();
+}
+
+static void
+linsysfs_tty_detach(void *arg __unused, device_t dev)
+{
+ linsysfs_tty_latch_hold();
+ linsysfs_tty_delete(dev);
+ linsysfs_tty_latch_rele();
+}
+
+void
+linsysfs_tty_init(void)
+{
+ MPASS(tty != NULL && platform != NULL);
+
+ tty_attach_tag = EVENTHANDLER_REGISTER(device_attach,
+ linsysfs_tty_attach, NULL, EVENTHANDLER_PRI_ANY);
+ tty_detach_tag = EVENTHANDLER_REGISTER(device_detach,
+ linsysfs_tty_detach, NULL, EVENTHANDLER_PRI_ANY);
+
+ /*
+ * If a TTY device is attached only now, it might end
+ * up in tty_nodes_q and the event might still be dispatched.
+ */
+ for (const char **p = linsysfs_tty_devclasses; *p != NULL; p++) {
+ device_t *devices;
+ int devices_count;
+ devclass_t class = devclass_find(*p);
+ if (class == NULL ||
+ devclass_get_devices(class, &devices, &devices_count) != 0)
+ continue;
+
+ for (int i = 0; i < devices_count; i++)
+ linsysfs_tty_attach(NULL, devices[i]);
+
+ free(devices, M_TEMP);
+ }
+}
+
+void
+linsysfs_tty_uninit(void)
+{
+ struct tty_nodes_queue *nq, *nq_tmp;
+
+ EVENTHANDLER_DEREGISTER(device_attach, tty_attach_tag);
+ EVENTHANDLER_DEREGISTER(device_detach, tty_detach_tag);
+
+ linsysfs_tty_latch_hold();
+ TAILQ_FOREACH_SAFE(nq, &tty_nodes_q, tty_nodes_next, nq_tmp) {
+ TAILQ_REMOVE(&tty_nodes_q, nq, tty_nodes_next);
+ free(nq, M_LINSYSFS);
+ }
+ linsysfs_tty_latch_rele();
+}
diff --git a/sys/dev/usb/serial/uftdi.h b/sys/dev/usb/serial/uftdi.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/usb/serial/uftdi.h
@@ -0,0 +1,62 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2000 The NetBSD Foundation, Inc.
+ * 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 _UFTDI_H_
+#define _UFTDI_H_
+
+#include <dev/usb/usb_process.h>
+#include <dev/usb/serial/usb_serial.h>
+
+enum {
+ UFTDI_BULK_DT_WR,
+ UFTDI_BULK_DT_RD,
+ UFTDI_N_TRANSFER,
+};
+
+struct uftdi_softc {
+ struct ucom_super_softc sc_super_ucom;
+ struct ucom_softc sc_ucom;
+
+ struct usb_device *sc_udev;
+ struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER];
+ device_t sc_dev;
+ struct mtx sc_mtx;
+
+ uint32_t sc_unit;
+
+ uint16_t sc_last_lcr;
+ uint16_t sc_bcdDevice;
+
+ uint8_t sc_devtype;
+ uint8_t sc_devflags;
+ uint8_t sc_hdrlen;
+ uint8_t sc_msr;
+ uint8_t sc_lsr;
+ uint8_t sc_bitmode;
+};
+
+#endif /* _UFTDI_H_ */
diff --git a/sys/dev/usb/serial/uftdi.c b/sys/dev/usb/serial/uftdi.c
--- a/sys/dev/usb/serial/uftdi.c
+++ b/sys/dev/usb/serial/uftdi.c
@@ -80,6 +80,7 @@
#include <dev/usb/serial/usb_serial.h>
#include <dev/usb/serial/uftdi_reg.h>
+#include <dev/usb/serial/uftdi.h>
#include <dev/usb/uftdiio.h>
static SYSCTL_NODE(_hw_usb, OID_AUTO, uftdi, CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
@@ -122,12 +123,6 @@
#define UFTDI_OBUFSIZE 2048
#define UFTDI_OPKTSIZE 64
-enum {
- UFTDI_BULK_DT_WR,
- UFTDI_BULK_DT_RD,
- UFTDI_N_TRANSFER,
-};
-
enum {
DEVT_SIO,
DEVT_232A,
@@ -143,28 +138,6 @@
#define DEVF_BAUDBITS_HINDEX 0x01 /* Baud bits in high byte of index. */
#define DEVF_BAUDCLK_12M 0X02 /* Base baud clock is 12MHz. */
-struct uftdi_softc {
- struct ucom_super_softc sc_super_ucom;
- struct ucom_softc sc_ucom;
-
- struct usb_device *sc_udev;
- struct usb_xfer *sc_xfer[UFTDI_N_TRANSFER];
- device_t sc_dev;
- struct mtx sc_mtx;
-
- uint32_t sc_unit;
-
- uint16_t sc_last_lcr;
- uint16_t sc_bcdDevice;
-
- uint8_t sc_devtype;
- uint8_t sc_devflags;
- uint8_t sc_hdrlen;
- uint8_t sc_msr;
- uint8_t sc_lsr;
- uint8_t sc_bitmode;
-};
-
struct uftdi_param_config {
uint16_t baud_lobits;
uint16_t baud_hibits;
diff --git a/sys/dev/usb/serial/umodem.h b/sys/dev/usb/serial/umodem.h
new file mode 100644
--- /dev/null
+++ b/sys/dev/usb/serial/umodem.h
@@ -0,0 +1,93 @@
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause
+ *
+ * Copyright (c) 2003 M. Warner Losh <imp@FreeBSD.org>
+ *
+ * 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.
+ */
+
+/*-
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (lennart@augustsson.net) at
+ * Carlstedt Research & Technology.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 FOUNDATION 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 _UMODEM_H_
+#define _UMODEM_H_
+
+#include <dev/usb/usb_process.h>
+#include <dev/usb/serial/usb_serial.h>
+
+enum {
+ UMODEM_BULK_WR,
+ UMODEM_BULK_RD,
+ UMODEM_INTR_WR,
+ UMODEM_INTR_RD,
+ UMODEM_N_TRANSFER,
+};
+
+struct umodem_softc {
+ struct ucom_super_softc sc_super_ucom;
+ struct ucom_softc sc_ucom;
+
+ struct usb_xfer *sc_xfer[UMODEM_N_TRANSFER];
+ struct usb_device *sc_udev;
+ struct mtx sc_mtx;
+
+ uint16_t sc_line;
+
+ uint8_t sc_lsr; /* local status register */
+ uint8_t sc_msr; /* modem status register */
+ uint8_t sc_ctrl_iface_no;
+ uint8_t sc_data_iface_no;
+ uint8_t sc_iface_index[2];
+ uint8_t sc_cm_over_data;
+ uint8_t sc_cm_cap; /* CM capabilities */
+ uint8_t sc_acm_cap; /* ACM capabilities */
+ uint8_t sc_line_coding[32]; /* used in USB device mode */
+ uint8_t sc_abstract_state[32]; /* used in USB device mode */
+};
+
+#endif /* _UMODEM_H_ */
diff --git a/sys/dev/usb/serial/umodem.c b/sys/dev/usb/serial/umodem.c
--- a/sys/dev/usb/serial/umodem.c
+++ b/sys/dev/usb/serial/umodem.c
@@ -107,6 +107,7 @@
#include <dev/usb/quirk/usb_quirk.h>
#include <dev/usb/serial/usb_serial.h>
+#include <dev/usb/serial/umodem.h>
#ifdef USB_DEBUG
static int umodem_debug = 0;
@@ -162,38 +163,8 @@
*/
#define UMODEM_BUF_SIZE 1024
-enum {
- UMODEM_BULK_WR,
- UMODEM_BULK_RD,
- UMODEM_INTR_WR,
- UMODEM_INTR_RD,
- UMODEM_N_TRANSFER,
-};
-
#define UMODEM_MODVER 1 /* module version */
-struct umodem_softc {
- struct ucom_super_softc sc_super_ucom;
- struct ucom_softc sc_ucom;
-
- struct usb_xfer *sc_xfer[UMODEM_N_TRANSFER];
- struct usb_device *sc_udev;
- struct mtx sc_mtx;
-
- uint16_t sc_line;
-
- uint8_t sc_lsr; /* local status register */
- uint8_t sc_msr; /* modem status register */
- uint8_t sc_ctrl_iface_no;
- uint8_t sc_data_iface_no;
- uint8_t sc_iface_index[2];
- uint8_t sc_cm_over_data;
- uint8_t sc_cm_cap; /* CM capabilities */
- uint8_t sc_acm_cap; /* ACM capabilities */
- uint8_t sc_line_coding[32]; /* used in USB device mode */
- uint8_t sc_abstract_state[32]; /* used in USB device mode */
-};
-
static device_probe_t umodem_probe;
static device_attach_t umodem_attach;
static device_detach_t umodem_detach;
diff --git a/sys/dev/usb/usb_hub.h b/sys/dev/usb/usb_hub.h
--- a/sys/dev/usb/usb_hub.h
+++ b/sys/dev/usb/usb_hub.h
@@ -62,6 +62,38 @@
#endif
};
+enum {
+ UHUB_INTR_TRANSFER,
+#if USB_HAVE_TT_SUPPORT
+ UHUB_RESET_TT_TRANSFER,
+#endif
+ UHUB_N_TRANSFER,
+};
+
+struct uhub_current_state {
+ uint16_t port_change;
+ uint16_t port_status;
+};
+
+struct uhub_softc {
+ struct uhub_current_state sc_st; /* current state */
+#if (USB_HAVE_FIXED_PORT != 0)
+ struct usb_hub sc_hub;
+#endif
+ device_t sc_dev; /* base device */
+ struct mtx sc_mtx; /* our mutex */
+ struct usb_device *sc_udev; /* USB device */
+ struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
+#if USB_HAVE_DISABLE_ENUM
+ int sc_disable_enumeration;
+ int sc_disable_port_power;
+#endif
+ uint8_t sc_usb_port_errors; /* error counter */
+#define UHUB_USB_PORT_ERRORS_MAX 4
+ uint8_t sc_flags;
+#define UHUB_FLAG_DID_EXPLORE 0x01
+};
+
/* function prototypes */
void usb_hs_bandwidth_alloc(struct usb_xfer *xfer);
diff --git a/sys/dev/usb/usb_hub_private.h b/sys/dev/usb/usb_hub_private.h
--- a/sys/dev/usb/usb_hub_private.h
+++ b/sys/dev/usb/usb_hub_private.h
@@ -35,37 +35,6 @@
#define USB_HUB_PRIVATE_H_
#define UHUB_INTR_INTERVAL 250 /* ms */
-enum {
- UHUB_INTR_TRANSFER,
-#if USB_HAVE_TT_SUPPORT
- UHUB_RESET_TT_TRANSFER,
-#endif
- UHUB_N_TRANSFER,
-};
-
-struct uhub_current_state {
- uint16_t port_change;
- uint16_t port_status;
-};
-
-struct uhub_softc {
- struct uhub_current_state sc_st; /* current state */
-#if (USB_HAVE_FIXED_PORT != 0)
- struct usb_hub sc_hub;
-#endif
- device_t sc_dev; /* base device */
- struct mtx sc_mtx; /* our mutex */
- struct usb_device *sc_udev; /* USB device */
- struct usb_xfer *sc_xfer[UHUB_N_TRANSFER]; /* interrupt xfer */
-#if USB_HAVE_DISABLE_ENUM
- int sc_disable_enumeration;
- int sc_disable_port_power;
-#endif
- uint8_t sc_usb_port_errors; /* error counter */
-#define UHUB_USB_PORT_ERRORS_MAX 4
- uint8_t sc_flags;
-#define UHUB_FLAG_DID_EXPLORE 0x01
-};
struct hub_result {
struct usb_device *udev;
uint8_t portno;
diff --git a/sys/modules/linsysfs/Makefile b/sys/modules/linsysfs/Makefile
--- a/sys/modules/linsysfs/Makefile
+++ b/sys/modules/linsysfs/Makefile
@@ -4,7 +4,7 @@
KMOD= linsysfs
SRCS= vnode_if.h \
device_if.h bus_if.h pci_if.h \
- linsysfs.c linsysfs_net.c
+ linsysfs.c linsysfs_net.c linsysfs_tty.c
.if !defined(KERNBUILDDIR)
.warning Building Linuxulator outside of a kernel does not make sense

File Metadata

Mime Type
text/plain
Expires
Thu, Jun 25, 3:41 PM (9 h, 39 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
34324561
Default Alt Text
D47417.diff (30 KB)

Event Timeline