aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorDoug Ambrisko <ambrisko@FreeBSD.org>2006-05-09 22:27:01 +0000
committerDoug Ambrisko <ambrisko@FreeBSD.org>2006-05-09 22:27:01 +0000
commit32397ce071bdd5e4185220f3715694351f860d91 (patch)
treed8dbe60ab35f553873253d68cb94cc9d3698b5c8 /sys
parent4577652f105068592dd22a2be4a83126f08fbbad (diff)
downloadsrc-32397ce071bdd5e4185220f3715694351f860d91.tar.gz
src-32397ce071bdd5e4185220f3715694351f860d91.zip
Add in linsysfs. A linux 2.6 like sys filesystem to pacify the Linux
LSI MegaRAID SAS utility. Sponsored by: IronPort Systems Man page help from: brueffer
Notes
Notes: svn path=/head/; revision=158381
Diffstat (limited to 'sys')
-rw-r--r--sys/amd64/conf/GENERIC1
-rw-r--r--sys/amd64/conf/NOTES4
-rw-r--r--sys/compat/linsysfs/linsysfs.c285
-rw-r--r--sys/conf/files.amd641
-rw-r--r--sys/conf/files.i3861
-rw-r--r--sys/conf/files.pc981
-rw-r--r--sys/i386/conf/NOTES4
-rw-r--r--sys/modules/Makefile2
-rw-r--r--sys/modules/linsysfs/Makefile11
-rw-r--r--sys/pc98/conf/NOTES4
10 files changed, 314 insertions, 0 deletions
diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC
index 3093a212360d..a1dc9dd77ab1 100644
--- a/sys/amd64/conf/GENERIC
+++ b/sys/amd64/conf/GENERIC
@@ -75,6 +75,7 @@ options SMP # Symmetric MultiProcessor Kernel
# Linux 32-bit ABI support
options COMPAT_LINUX32 # Compatible with i386 linux binaries
options LINPROCFS # Cannot be a module yet.
+options LINSYSFS
# Bus support.
device acpi
diff --git a/sys/amd64/conf/NOTES b/sys/amd64/conf/NOTES
index 6269c52f5d35..114fd257a76c 100644
--- a/sys/amd64/conf/NOTES
+++ b/sys/amd64/conf/NOTES
@@ -507,6 +507,10 @@ options COMPAT_LINUX32
# and PSEUDOFS)
options LINPROCFS
+#Enable the linux-like sys filesystem support (requires COMPAT_LINUX32
+# and PSEUDOFS)
+options LINSYSFS
+
#
# SysVR4 ABI emulation
#
diff --git a/sys/compat/linsysfs/linsysfs.c b/sys/compat/linsysfs/linsysfs.c
new file mode 100644
index 000000000000..ab3886e8c19f
--- /dev/null
+++ b/sys/compat/linsysfs/linsysfs.c
@@ -0,0 +1,285 @@
+/*-
+ * Copyright (c) 2006 IronPort Systems
+ * 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/blist.h>
+#include <sys/conf.h>
+#include <sys/exec.h>
+#include <sys/filedesc.h>
+#include <sys/kernel.h>
+#include <sys/linker.h>
+#include <sys/malloc.h>
+#include <sys/mount.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
+#include <sys/resourcevar.h>
+#include <sys/sbuf.h>
+#include <sys/smp.h>
+#include <sys/socket.h>
+#include <sys/vnode.h>
+#include <sys/bus.h>
+#include <sys/pciio.h>
+
+#include <dev/pci/pcivar.h>
+#include <dev/pci/pcireg.h>
+
+#include <net/if.h>
+
+#include <vm/vm.h>
+#include <vm/pmap.h>
+#include <vm/vm_map.h>
+#include <vm/vm_param.h>
+#include <vm/vm_object.h>
+#include <vm/swap_pager.h>
+
+#include <machine/bus.h>
+
+#include "opt_compat.h"
+#ifdef COMPAT_LINUX32 /* XXX */
+#include <machine/../linux32/linux.h>
+#else
+#include <machine/../linux/linux.h>
+#endif
+#include <compat/linux/linux_ioctl.h>
+#include <compat/linux/linux_mib.h>
+#include <compat/linux/linux_util.h>
+#include <fs/pseudofs/pseudofs.h>
+#include <fs/procfs/procfs.h>
+
+struct scsi_host_queue {
+ TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
+ char *path;
+ char *name;
+};
+
+TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
+
+static int host_number = 0;
+
+static int
+atoi(const char *str)
+{
+ return (int)strtol(str, (char **)NULL, 10);
+}
+
+/*
+ * Filler function for proc_name
+ */
+static int
+linsysfs_scsiname(PFS_FILL_ARGS)
+{
+ struct scsi_host_queue *scsi_host;
+ int index;
+
+ if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
+ index = atoi(&pn->pn_parent->pn_name[4]);
+ } else {
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+ }
+ TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
+ if (index-- == 0) {
+ sbuf_printf(sb, "%s\n", scsi_host->name);
+ return (0);
+ }
+ }
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+}
+
+/*
+ * Filler function for device sym-link
+ */
+static int
+linsysfs_link_scsi_host(PFS_FILL_ARGS)
+{
+ struct scsi_host_queue *scsi_host;
+ int index;
+
+ if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
+ index = atoi(&pn->pn_parent->pn_name[4]);
+ } else {
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+ }
+ TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
+ if (index-- == 0) {
+ sbuf_printf(sb, "../../../devices%s", scsi_host->path);
+ return(0);
+ }
+ }
+ sbuf_printf(sb, "unknown\n");
+ return (0);
+}
+
+#define PCI_DEV "pci"
+static int
+linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path,
+ char *prefix)
+{
+ struct scsi_host_queue *scsi_host;
+ struct pfs_node *sub_dir;
+ int i, nchildren;
+ device_t *children, parent;
+ devclass_t devclass;
+ const char *name = NULL;
+ struct pci_devinfo *dinfo;
+ char *device, *host, *new_path = path;
+
+ parent = device_get_parent(dev);
+ if (parent) {
+ devclass = device_get_devclass(parent);
+ if (devclass != NULL)
+ name = devclass_get_name(devclass);
+ if (name && strcmp(name, PCI_DEV) == 0) {
+ dinfo = device_get_ivars(dev);
+ if (dinfo) {
+ device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ new_path = malloc(MAXPATHLEN, M_TEMP,
+ M_WAITOK);
+ new_path[0] = '\000';
+ strcpy(new_path, path);
+ host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
+ device[0] = '\000';
+ sprintf(device, "%s:%02x:%02x.%x",
+ prefix,
+ dinfo->cfg.bus,
+ dinfo->cfg.slot,
+ dinfo->cfg.func);
+ strcat(new_path, "/");
+ strcat(new_path, device);
+ dir = pfs_create_dir(dir, device,
+ NULL, NULL, 0);
+
+ if (dinfo->cfg.baseclass == PCIC_STORAGE) {
+ /* DJA only make this if needed */
+ sprintf(host, "host%d", host_number++);
+ strcat(new_path, "/");
+ strcat(new_path, host);
+ sub_dir = pfs_create_dir(dir,
+ host, NULL, NULL, 0);
+ scsi_host = malloc(sizeof(
+ struct scsi_host_queue),
+ M_DEVBUF, M_NOWAIT);
+ scsi_host->path = malloc(
+ strlen(new_path) + 1,
+ M_DEVBUF, M_NOWAIT);
+ scsi_host->path[0] = '\000';
+ bcopy(new_path, scsi_host->path,
+ strlen(new_path) + 1);
+ scsi_host->name = "unknown";
+
+ sub_dir = pfs_create_dir(scsi, host,
+ NULL, NULL, 0);
+ pfs_create_link(sub_dir, "device",
+ &linsysfs_link_scsi_host,
+ NULL, NULL, 0);
+ pfs_create_file(sub_dir, "proc_name",
+ &linsysfs_scsiname,
+ NULL, NULL, PFS_RD);
+ scsi_host->name
+ = linux_driver_get_name_dev(dev);
+ TAILQ_INSERT_TAIL(&scsi_host_q,
+ scsi_host, scsi_host_next);
+ }
+ free(device, M_TEMP);
+ free(host, M_TEMP);
+ }
+ }
+ }
+
+ device_get_children(dev, &children, &nchildren);
+ for (i = 0; i < nchildren; i++) {
+ if (children[i])
+ linsysfs_run_bus(children[i], dir, scsi, new_path, prefix);
+ }
+ if (new_path != path)
+ free(new_path, M_TEMP);
+
+ return (1);
+}
+
+/*
+ * Constructor
+ */
+static int
+linsysfs_init(PFS_INIT_ARGS)
+{
+ struct pfs_node *root;
+ struct pfs_node *dir;
+ struct pfs_node *pci;
+ struct pfs_node *scsi;
+ devclass_t devclass;
+ device_t dev;
+
+ TAILQ_INIT(&scsi_host_q);
+
+ root = pi->pi_root;
+
+ /* /sys/class/... */
+ scsi = pfs_create_dir(root, "class", NULL, NULL, 0);
+ scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, 0);
+
+ /* /sys/device */
+ dir = pfs_create_dir(root, "devices", NULL, NULL, 0);
+
+ /* /sys/device/pci0000:00 */
+ pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, 0);
+
+ devclass = devclass_find("root");
+ if (devclass == NULL) {
+ return (0);
+ }
+
+ dev = devclass_get_device(devclass, 0);
+ linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000");
+ return (0);
+}
+
+/*
+ * Destructor
+ */
+static int
+linsysfs_uninit(PFS_INIT_ARGS)
+{
+ struct scsi_host_queue *scsi_host;
+
+ TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
+ TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
+ free(scsi_host->path, M_TEMP);
+ free(scsi_host, M_TEMP);
+ }
+
+ return (0);
+}
+
+PSEUDOFS(linsysfs, 1);
+MODULE_DEPEND(linsysfs, linux, 1, 1, 1);
+MODULE_DEPEND(linsysfs, procfs, 1, 1, 1);
diff --git a/sys/conf/files.amd64 b/sys/conf/files.amd64
index 992b258fd064..9b8416659891 100644
--- a/sys/conf/files.amd64
+++ b/sys/conf/files.amd64
@@ -218,6 +218,7 @@ compat/freebsd32/freebsd32_syscalls.c optional compat_ia32
compat/freebsd32/freebsd32_sysent.c optional compat_ia32
compat/ia32/ia32_sysvec.c optional compat_ia32
compat/linprocfs/linprocfs.c optional linprocfs
+compat/linsysfs/linsysfs.c optional linsysfs
kern/imgact_elf32.c optional compat_ia32
#
# Linux/i386 binary support
diff --git a/sys/conf/files.i386 b/sys/conf/files.i386
index 007870a0b6ff..ff23f6ca28ce 100644
--- a/sys/conf/files.i386
+++ b/sys/conf/files.i386
@@ -84,6 +84,7 @@ rr232x_lib.o optional rr232x \
#
#
compat/linprocfs/linprocfs.c optional linprocfs
+compat/linsysfs/linsysfs.c optional linsysfs
compat/linux/linux_file.c optional compat_linux
compat/linux/linux_getcwd.c optional compat_linux
compat/linux/linux_ioctl.c optional compat_linux
diff --git a/sys/conf/files.pc98 b/sys/conf/files.pc98
index 5dcb53109992..764b43645894 100644
--- a/sys/conf/files.pc98
+++ b/sys/conf/files.pc98
@@ -54,6 +54,7 @@ opt_ah.h optional ath_hal \
clean "opt_ah.h"
#
compat/linprocfs/linprocfs.c optional linprocfs
+compat/linsysfs/linsysfs.c optional linsysfs
compat/linux/linux_file.c optional compat_linux
compat/linux/linux_getcwd.c optional compat_linux
compat/linux/linux_ioctl.c optional compat_linux
diff --git a/sys/i386/conf/NOTES b/sys/i386/conf/NOTES
index 8ac64f0d6ad3..27553e1bdb72 100644
--- a/sys/i386/conf/NOTES
+++ b/sys/i386/conf/NOTES
@@ -1041,6 +1041,10 @@ options COMPAT_AOUT
# and PSEUDOFS)
options LINPROCFS
+#Enable the linux-like sys filesystem support (requires COMPAT_LINUX
+# and PSEUDOFS)
+options LINSYSFS
+
#
# SysVR4 ABI emulation
#
diff --git a/sys/modules/Makefile b/sys/modules/Makefile
index cbafb6dc7b54..d039e0173fd9 100644
--- a/sys/modules/Makefile
+++ b/sys/modules/Makefile
@@ -134,6 +134,7 @@ SUBDIR= ${_3dfx} \
libmbpool \
libmchain \
${_linprocfs} \
+ ${_linsysfs} \
${_linux} \
lmc \
${_lnc} \
@@ -357,6 +358,7 @@ _ie= ie
_if_ndis= if_ndis
_io= io
_linprocfs= linprocfs
+_linsysfs= linsysfs
_linux= linux
_lnc= lnc
_mse= mse
diff --git a/sys/modules/linsysfs/Makefile b/sys/modules/linsysfs/Makefile
new file mode 100644
index 000000000000..084b82833c2e
--- /dev/null
+++ b/sys/modules/linsysfs/Makefile
@@ -0,0 +1,11 @@
+# $FreeBSD$
+
+.PATH: ${.CURDIR}/../../compat/linsysfs
+
+KMOD= linsysfs
+SRCS= vnode_if.h \
+ device_if.h bus_if.h pci_if.h \
+ linsysfs.c \
+ opt_compat.h
+
+.include <bsd.kmod.mk>
diff --git a/sys/pc98/conf/NOTES b/sys/pc98/conf/NOTES
index f5094c0ec824..7862b0f3797a 100644
--- a/sys/pc98/conf/NOTES
+++ b/sys/pc98/conf/NOTES
@@ -658,6 +658,10 @@ options COMPAT_AOUT
# and PSEUDOFS)
options LINPROCFS
+# Enable the linux-like sys filesystem support (requires COMPAT_LINUX
+# and PSEUDOFS)
+options LINSYSFS
+
#
# SysVR4 ABI emulation
#