Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F160454517
D47417.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
30 KB
Referenced Files
None
Subscribers
None
D47417.diff
View Options
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
Details
Attached
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)
Attached To
Mode
D47417: linsysfs: implemented /sys/class/tty
Attached
Detach File
Event Timeline
Log In to Comment