132397ce0SDoug Ambrisko /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
37f2d13d6SPedro F. Giffuni *
432397ce0SDoug Ambrisko * Copyright (c) 2006 IronPort Systems
532397ce0SDoug Ambrisko * All rights reserved.
632397ce0SDoug Ambrisko *
732397ce0SDoug Ambrisko * Redistribution and use in source and binary forms, with or without
832397ce0SDoug Ambrisko * modification, are permitted provided that the following conditions
932397ce0SDoug Ambrisko * are met:
1032397ce0SDoug Ambrisko * 1. Redistributions of source code must retain the above copyright
1132397ce0SDoug Ambrisko * notice, this list of conditions and the following disclaimer.
1232397ce0SDoug Ambrisko * 2. Redistributions in binary form must reproduce the above copyright
1332397ce0SDoug Ambrisko * notice, this list of conditions and the following disclaimer in the
1432397ce0SDoug Ambrisko * documentation and/or other materials provided with the distribution.
1532397ce0SDoug Ambrisko *
1632397ce0SDoug Ambrisko * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
1732397ce0SDoug Ambrisko * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
1832397ce0SDoug Ambrisko * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1932397ce0SDoug Ambrisko * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2032397ce0SDoug Ambrisko * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2132397ce0SDoug Ambrisko * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2232397ce0SDoug Ambrisko * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2332397ce0SDoug Ambrisko * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2432397ce0SDoug Ambrisko * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
2532397ce0SDoug Ambrisko * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
2632397ce0SDoug Ambrisko * SUCH DAMAGE.
2732397ce0SDoug Ambrisko */
2832397ce0SDoug Ambrisko
2932397ce0SDoug Ambrisko #include <sys/param.h>
30eedc7fd9SGleb Smirnoff #include <sys/systm.h>
314e2f69f1SDmitry Chagin #include <sys/ctype.h>
3232397ce0SDoug Ambrisko #include <sys/kernel.h>
3332397ce0SDoug Ambrisko #include <sys/malloc.h>
3432397ce0SDoug Ambrisko #include <sys/mount.h>
3532397ce0SDoug Ambrisko #include <sys/sbuf.h>
3632397ce0SDoug Ambrisko #include <sys/smp.h>
3732397ce0SDoug Ambrisko #include <sys/bus.h>
3832397ce0SDoug Ambrisko #include <sys/pciio.h>
3932397ce0SDoug Ambrisko
4032397ce0SDoug Ambrisko #include <dev/pci/pcivar.h>
4132397ce0SDoug Ambrisko #include <dev/pci/pcireg.h>
4232397ce0SDoug Ambrisko
4332397ce0SDoug Ambrisko #include <compat/linux/linux_util.h>
4432397ce0SDoug Ambrisko #include <fs/pseudofs/pseudofs.h>
4532397ce0SDoug Ambrisko
467ae0972cSDmitry Chagin #include <compat/linsysfs/linsysfs.h>
477ae0972cSDmitry Chagin
487ae0972cSDmitry Chagin MALLOC_DEFINE(M_LINSYSFS, "linsysfs", "Linsysfs structures");
497ae0972cSDmitry Chagin
5032397ce0SDoug Ambrisko struct scsi_host_queue {
5132397ce0SDoug Ambrisko TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
5232397ce0SDoug Ambrisko char *path;
5332397ce0SDoug Ambrisko char *name;
5432397ce0SDoug Ambrisko };
5532397ce0SDoug Ambrisko
5632397ce0SDoug Ambrisko TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
5732397ce0SDoug Ambrisko
5832397ce0SDoug Ambrisko static int host_number = 0;
5932397ce0SDoug Ambrisko
6032397ce0SDoug Ambrisko static int
atoi(const char * str)6132397ce0SDoug Ambrisko atoi(const char *str)
6232397ce0SDoug Ambrisko {
6332397ce0SDoug Ambrisko return (int)strtol(str, (char **)NULL, 10);
6432397ce0SDoug Ambrisko }
6532397ce0SDoug Ambrisko
6632397ce0SDoug Ambrisko /*
6732397ce0SDoug Ambrisko * Filler function for proc_name
6832397ce0SDoug Ambrisko */
6932397ce0SDoug Ambrisko static int
linsysfs_scsiname(PFS_FILL_ARGS)7032397ce0SDoug Ambrisko linsysfs_scsiname(PFS_FILL_ARGS)
7132397ce0SDoug Ambrisko {
7232397ce0SDoug Ambrisko struct scsi_host_queue *scsi_host;
7332397ce0SDoug Ambrisko int index;
7432397ce0SDoug Ambrisko
7532397ce0SDoug Ambrisko if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
7632397ce0SDoug Ambrisko index = atoi(&pn->pn_parent->pn_name[4]);
7732397ce0SDoug Ambrisko } else {
7832397ce0SDoug Ambrisko sbuf_printf(sb, "unknown\n");
7932397ce0SDoug Ambrisko return (0);
8032397ce0SDoug Ambrisko }
8132397ce0SDoug Ambrisko TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
8232397ce0SDoug Ambrisko if (index-- == 0) {
8332397ce0SDoug Ambrisko sbuf_printf(sb, "%s\n", scsi_host->name);
8432397ce0SDoug Ambrisko return (0);
8532397ce0SDoug Ambrisko }
8632397ce0SDoug Ambrisko }
8732397ce0SDoug Ambrisko sbuf_printf(sb, "unknown\n");
8832397ce0SDoug Ambrisko return (0);
8932397ce0SDoug Ambrisko }
9032397ce0SDoug Ambrisko
9132397ce0SDoug Ambrisko /*
9232397ce0SDoug Ambrisko * Filler function for device sym-link
9332397ce0SDoug Ambrisko */
9432397ce0SDoug Ambrisko static int
linsysfs_link_scsi_host(PFS_FILL_ARGS)9532397ce0SDoug Ambrisko linsysfs_link_scsi_host(PFS_FILL_ARGS)
9632397ce0SDoug Ambrisko {
9732397ce0SDoug Ambrisko struct scsi_host_queue *scsi_host;
9832397ce0SDoug Ambrisko int index;
9932397ce0SDoug Ambrisko
10032397ce0SDoug Ambrisko if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
10132397ce0SDoug Ambrisko index = atoi(&pn->pn_parent->pn_name[4]);
10232397ce0SDoug Ambrisko } else {
10332397ce0SDoug Ambrisko sbuf_printf(sb, "unknown\n");
10432397ce0SDoug Ambrisko return (0);
10532397ce0SDoug Ambrisko }
10632397ce0SDoug Ambrisko TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
10732397ce0SDoug Ambrisko if (index-- == 0) {
10832397ce0SDoug Ambrisko sbuf_printf(sb, "../../../devices%s", scsi_host->path);
10932397ce0SDoug Ambrisko return(0);
11032397ce0SDoug Ambrisko }
11132397ce0SDoug Ambrisko }
11232397ce0SDoug Ambrisko sbuf_printf(sb, "unknown\n");
11332397ce0SDoug Ambrisko return (0);
11432397ce0SDoug Ambrisko }
11532397ce0SDoug Ambrisko
11632397ce0SDoug Ambrisko static int
linsysfs_fill_data(PFS_FILL_ARGS)1172d347b2eSConrad Meyer linsysfs_fill_data(PFS_FILL_ARGS)
1182d347b2eSConrad Meyer {
1192e6418c0SRyan Libby sbuf_printf(sb, "%s", (char *)pn->pn_data);
1202d347b2eSConrad Meyer return (0);
1212d347b2eSConrad Meyer }
1222d347b2eSConrad Meyer
1232d347b2eSConrad Meyer static int
linsysfs_fill_vendor(PFS_FILL_ARGS)1242d347b2eSConrad Meyer linsysfs_fill_vendor(PFS_FILL_ARGS)
1252d347b2eSConrad Meyer {
1262d347b2eSConrad Meyer sbuf_printf(sb, "0x%04x\n", pci_get_vendor((device_t)pn->pn_data));
1272d347b2eSConrad Meyer return (0);
1282d347b2eSConrad Meyer }
1292d347b2eSConrad Meyer
1302d347b2eSConrad Meyer static int
linsysfs_fill_device(PFS_FILL_ARGS)1312d347b2eSConrad Meyer linsysfs_fill_device(PFS_FILL_ARGS)
1322d347b2eSConrad Meyer {
1332d347b2eSConrad Meyer sbuf_printf(sb, "0x%04x\n", pci_get_device((device_t)pn->pn_data));
1342d347b2eSConrad Meyer return (0);
1352d347b2eSConrad Meyer }
1362d347b2eSConrad Meyer
1372d347b2eSConrad Meyer static int
linsysfs_fill_subvendor(PFS_FILL_ARGS)1382d347b2eSConrad Meyer linsysfs_fill_subvendor(PFS_FILL_ARGS)
1392d347b2eSConrad Meyer {
1402d347b2eSConrad Meyer sbuf_printf(sb, "0x%04x\n", pci_get_subvendor((device_t)pn->pn_data));
1412d347b2eSConrad Meyer return (0);
1422d347b2eSConrad Meyer }
1432d347b2eSConrad Meyer
1442d347b2eSConrad Meyer static int
linsysfs_fill_subdevice(PFS_FILL_ARGS)1452d347b2eSConrad Meyer linsysfs_fill_subdevice(PFS_FILL_ARGS)
1462d347b2eSConrad Meyer {
1472d347b2eSConrad Meyer sbuf_printf(sb, "0x%04x\n", pci_get_subdevice((device_t)pn->pn_data));
1482d347b2eSConrad Meyer return (0);
1492d347b2eSConrad Meyer }
1502d347b2eSConrad Meyer
1512d347b2eSConrad Meyer static int
linsysfs_fill_revid(PFS_FILL_ARGS)1522d347b2eSConrad Meyer linsysfs_fill_revid(PFS_FILL_ARGS)
1532d347b2eSConrad Meyer {
1542d347b2eSConrad Meyer sbuf_printf(sb, "0x%x\n", pci_get_revid((device_t)pn->pn_data));
1552d347b2eSConrad Meyer return (0);
1562d347b2eSConrad Meyer }
1572d347b2eSConrad Meyer
15803cea61bSTijl Coosemans static int
linsysfs_fill_config(PFS_FILL_ARGS)15903cea61bSTijl Coosemans linsysfs_fill_config(PFS_FILL_ARGS)
16003cea61bSTijl Coosemans {
16103cea61bSTijl Coosemans uint8_t config[48];
16203cea61bSTijl Coosemans device_t dev;
16303cea61bSTijl Coosemans uint32_t reg;
16403cea61bSTijl Coosemans
16503cea61bSTijl Coosemans dev = (device_t)pn->pn_data;
16603cea61bSTijl Coosemans bzero(config, sizeof(config));
16703cea61bSTijl Coosemans reg = pci_get_vendor(dev);
16803cea61bSTijl Coosemans config[0] = reg;
16903cea61bSTijl Coosemans config[1] = reg >> 8;
17003cea61bSTijl Coosemans reg = pci_get_device(dev);
17103cea61bSTijl Coosemans config[2] = reg;
17203cea61bSTijl Coosemans config[3] = reg >> 8;
17303cea61bSTijl Coosemans reg = pci_get_revid(dev);
17403cea61bSTijl Coosemans config[8] = reg;
17503cea61bSTijl Coosemans reg = pci_get_subvendor(dev);
17603cea61bSTijl Coosemans config[44] = reg;
17703cea61bSTijl Coosemans config[45] = reg >> 8;
17803cea61bSTijl Coosemans reg = pci_get_subdevice(dev);
17903cea61bSTijl Coosemans config[46] = reg;
18003cea61bSTijl Coosemans config[47] = reg >> 8;
18103cea61bSTijl Coosemans sbuf_bcat(sb, config, sizeof(config));
18203cea61bSTijl Coosemans return (0);
18303cea61bSTijl Coosemans }
18403cea61bSTijl Coosemans
1852d347b2eSConrad Meyer /*
1862d347b2eSConrad Meyer * Filler function for PCI uevent file
1872d347b2eSConrad Meyer */
1882d347b2eSConrad Meyer static int
linsysfs_fill_uevent_pci(PFS_FILL_ARGS)1892d347b2eSConrad Meyer linsysfs_fill_uevent_pci(PFS_FILL_ARGS)
1902d347b2eSConrad Meyer {
1912d347b2eSConrad Meyer device_t dev;
1922d347b2eSConrad Meyer
1932d347b2eSConrad Meyer dev = (device_t)pn->pn_data;
1942d347b2eSConrad Meyer sbuf_printf(sb, "DRIVER=%s\nPCI_CLASS=%X\nPCI_ID=%04X:%04X\n"
1952d347b2eSConrad Meyer "PCI_SUBSYS_ID=%04X:%04X\nPCI_SLOT_NAME=%04d:%02x:%02x.%x\n",
1962d347b2eSConrad Meyer linux_driver_get_name_dev(dev), pci_get_class(dev),
1972d347b2eSConrad Meyer pci_get_vendor(dev), pci_get_device(dev), pci_get_subvendor(dev),
1982d347b2eSConrad Meyer pci_get_subdevice(dev), pci_get_domain(dev), pci_get_bus(dev),
1992d347b2eSConrad Meyer pci_get_slot(dev), pci_get_function(dev));
2002d347b2eSConrad Meyer return (0);
2012d347b2eSConrad Meyer }
2022d347b2eSConrad Meyer
2032d347b2eSConrad Meyer /*
2042d347b2eSConrad Meyer * Filler function for drm uevent file
2052d347b2eSConrad Meyer */
2062d347b2eSConrad Meyer static int
linsysfs_fill_uevent_drm(PFS_FILL_ARGS)2072d347b2eSConrad Meyer linsysfs_fill_uevent_drm(PFS_FILL_ARGS)
2082d347b2eSConrad Meyer {
2092d347b2eSConrad Meyer device_t dev;
2102d347b2eSConrad Meyer int unit;
2112d347b2eSConrad Meyer
2122d347b2eSConrad Meyer dev = (device_t)pn->pn_data;
2132d347b2eSConrad Meyer unit = device_get_unit(dev);
2142d347b2eSConrad Meyer sbuf_printf(sb,
215df4c9752STijl Coosemans "MAJOR=226\nMINOR=%d\nDEVNAME=dri/card%d\nDEVTYPE=dri_minor\n",
216df4c9752STijl Coosemans unit, unit);
2172d347b2eSConrad Meyer return (0);
2182d347b2eSConrad Meyer }
2192d347b2eSConrad Meyer
2202d347b2eSConrad Meyer static char *
get_full_pfs_path(struct pfs_node * cur)2212d347b2eSConrad Meyer get_full_pfs_path(struct pfs_node *cur)
2222d347b2eSConrad Meyer {
2232d347b2eSConrad Meyer char *temp, *path;
2242d347b2eSConrad Meyer
2252d347b2eSConrad Meyer temp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
2262d347b2eSConrad Meyer path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
2272d347b2eSConrad Meyer path[0] = '\0';
2282d347b2eSConrad Meyer
2292d347b2eSConrad Meyer do {
2302d347b2eSConrad Meyer snprintf(temp, MAXPATHLEN, "%s/%s", cur->pn_name, path);
2312d347b2eSConrad Meyer strlcpy(path, temp, MAXPATHLEN);
2322d347b2eSConrad Meyer cur = cur->pn_parent;
2332d347b2eSConrad Meyer } while (cur->pn_parent != NULL);
2342d347b2eSConrad Meyer
2352d347b2eSConrad Meyer path[strlen(path) - 1] = '\0'; /* remove extra slash */
2362d347b2eSConrad Meyer free(temp, M_TEMP);
2372d347b2eSConrad Meyer return (path);
2382d347b2eSConrad Meyer }
2392d347b2eSConrad Meyer
2402d347b2eSConrad Meyer /*
2412d347b2eSConrad Meyer * Filler function for symlink from drm char device to PCI device
2422d347b2eSConrad Meyer */
2432d347b2eSConrad Meyer static int
linsysfs_fill_vgapci(PFS_FILL_ARGS)2442d347b2eSConrad Meyer linsysfs_fill_vgapci(PFS_FILL_ARGS)
2452d347b2eSConrad Meyer {
2462d347b2eSConrad Meyer char *path;
2472d347b2eSConrad Meyer
2482d347b2eSConrad Meyer path = get_full_pfs_path((struct pfs_node*)pn->pn_data);
2492d347b2eSConrad Meyer sbuf_printf(sb, "../../../%s", path);
2502d347b2eSConrad Meyer free(path, M_TEMP);
2512d347b2eSConrad Meyer return (0);
2522d347b2eSConrad Meyer }
2532d347b2eSConrad Meyer
254971b5f76SWarner Losh #undef PCI_DEV
2552d347b2eSConrad Meyer #define PCI_DEV "pci"
2562d347b2eSConrad Meyer #define DRMN_DEV "drmn"
2572d347b2eSConrad Meyer static int
linsysfs_run_bus(device_t dev,struct pfs_node * dir,struct pfs_node * scsi,struct pfs_node * chardev,struct pfs_node * drm,char * path,char * prefix)25803cea61bSTijl Coosemans linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
25903cea61bSTijl Coosemans struct pfs_node *chardev, struct pfs_node *drm, char *path, char *prefix)
26032397ce0SDoug Ambrisko {
26132397ce0SDoug Ambrisko struct scsi_host_queue *scsi_host;
26203cea61bSTijl Coosemans struct pfs_node *sub_dir, *cur_file;
2634d367f25SConrad Meyer int i, nchildren, error;
26432397ce0SDoug Ambrisko device_t *children, parent;
26532397ce0SDoug Ambrisko devclass_t devclass;
26632397ce0SDoug Ambrisko const char *name = NULL;
26732397ce0SDoug Ambrisko struct pci_devinfo *dinfo;
26803cea61bSTijl Coosemans char *device, *host, *new_path, *devname;
2692d347b2eSConrad Meyer
2702d347b2eSConrad Meyer new_path = path;
27103cea61bSTijl Coosemans devname = malloc(16, M_TEMP, M_WAITOK);
27232397ce0SDoug Ambrisko
27332397ce0SDoug Ambrisko parent = device_get_parent(dev);
27432397ce0SDoug Ambrisko if (parent) {
27532397ce0SDoug Ambrisko devclass = device_get_devclass(parent);
27632397ce0SDoug Ambrisko if (devclass != NULL)
27732397ce0SDoug Ambrisko name = devclass_get_name(devclass);
27832397ce0SDoug Ambrisko if (name && strcmp(name, PCI_DEV) == 0) {
27932397ce0SDoug Ambrisko dinfo = device_get_ivars(dev);
28032397ce0SDoug Ambrisko if (dinfo) {
28132397ce0SDoug Ambrisko device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
28232397ce0SDoug Ambrisko new_path = malloc(MAXPATHLEN, M_TEMP,
28332397ce0SDoug Ambrisko M_WAITOK);
28432397ce0SDoug Ambrisko new_path[0] = '\000';
28532397ce0SDoug Ambrisko strcpy(new_path, path);
28632397ce0SDoug Ambrisko host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
28732397ce0SDoug Ambrisko device[0] = '\000';
28832397ce0SDoug Ambrisko sprintf(device, "%s:%02x:%02x.%x",
28932397ce0SDoug Ambrisko prefix,
29032397ce0SDoug Ambrisko dinfo->cfg.bus,
29132397ce0SDoug Ambrisko dinfo->cfg.slot,
29232397ce0SDoug Ambrisko dinfo->cfg.func);
29332397ce0SDoug Ambrisko strcat(new_path, "/");
29432397ce0SDoug Ambrisko strcat(new_path, device);
29532397ce0SDoug Ambrisko dir = pfs_create_dir(dir, device,
296771709ebSDag-Erling Smørgrav NULL, NULL, NULL, 0);
2972d347b2eSConrad Meyer cur_file = pfs_create_file(dir, "vendor",
2982d347b2eSConrad Meyer &linsysfs_fill_vendor, NULL, NULL, NULL,
2992d347b2eSConrad Meyer PFS_RD);
3002d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
3012d347b2eSConrad Meyer cur_file = pfs_create_file(dir, "device",
3022d347b2eSConrad Meyer &linsysfs_fill_device, NULL, NULL, NULL,
3032d347b2eSConrad Meyer PFS_RD);
3042d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
3052d347b2eSConrad Meyer cur_file = pfs_create_file(dir,
3062d347b2eSConrad Meyer "subsystem_vendor",
3072d347b2eSConrad Meyer &linsysfs_fill_subvendor, NULL, NULL, NULL,
3082d347b2eSConrad Meyer PFS_RD);
3092d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
3102d347b2eSConrad Meyer cur_file = pfs_create_file(dir,
3112d347b2eSConrad Meyer "subsystem_device",
3122d347b2eSConrad Meyer &linsysfs_fill_subdevice, NULL, NULL, NULL,
3132d347b2eSConrad Meyer PFS_RD);
3142d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
3152d347b2eSConrad Meyer cur_file = pfs_create_file(dir, "revision",
3162d347b2eSConrad Meyer &linsysfs_fill_revid, NULL, NULL, NULL,
3172d347b2eSConrad Meyer PFS_RD);
3182d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
31903cea61bSTijl Coosemans cur_file = pfs_create_file(dir, "config",
32003cea61bSTijl Coosemans &linsysfs_fill_config, NULL, NULL, NULL,
32103cea61bSTijl Coosemans PFS_RD);
32203cea61bSTijl Coosemans cur_file->pn_data = (void*)dev;
3232d347b2eSConrad Meyer cur_file = pfs_create_file(dir, "uevent",
3242d347b2eSConrad Meyer &linsysfs_fill_uevent_pci, NULL, NULL,
3252d347b2eSConrad Meyer NULL, PFS_RD);
3262d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
3272d347b2eSConrad Meyer cur_file = pfs_create_link(dir, "subsystem",
3282d347b2eSConrad Meyer &linsysfs_fill_data, NULL, NULL, NULL, 0);
3292d347b2eSConrad Meyer /* libdrm just checks that the link ends in "/pci" */
3302d347b2eSConrad Meyer cur_file->pn_data = "/sys/bus/pci";
33132397ce0SDoug Ambrisko
33232397ce0SDoug Ambrisko if (dinfo->cfg.baseclass == PCIC_STORAGE) {
33332397ce0SDoug Ambrisko /* DJA only make this if needed */
33432397ce0SDoug Ambrisko sprintf(host, "host%d", host_number++);
33532397ce0SDoug Ambrisko strcat(new_path, "/");
33632397ce0SDoug Ambrisko strcat(new_path, host);
33736b0a373SDag-Erling Smørgrav pfs_create_dir(dir, host,
33836b0a373SDag-Erling Smørgrav NULL, NULL, NULL, 0);
33932397ce0SDoug Ambrisko scsi_host = malloc(sizeof(
34032397ce0SDoug Ambrisko struct scsi_host_queue),
34132397ce0SDoug Ambrisko M_DEVBUF, M_NOWAIT);
34232397ce0SDoug Ambrisko scsi_host->path = malloc(
34332397ce0SDoug Ambrisko strlen(new_path) + 1,
34432397ce0SDoug Ambrisko M_DEVBUF, M_NOWAIT);
34532397ce0SDoug Ambrisko scsi_host->path[0] = '\000';
34632397ce0SDoug Ambrisko bcopy(new_path, scsi_host->path,
34732397ce0SDoug Ambrisko strlen(new_path) + 1);
34832397ce0SDoug Ambrisko scsi_host->name = "unknown";
34932397ce0SDoug Ambrisko
35032397ce0SDoug Ambrisko sub_dir = pfs_create_dir(scsi, host,
351771709ebSDag-Erling Smørgrav NULL, NULL, NULL, 0);
35232397ce0SDoug Ambrisko pfs_create_link(sub_dir, "device",
35332397ce0SDoug Ambrisko &linsysfs_link_scsi_host,
354771709ebSDag-Erling Smørgrav NULL, NULL, NULL, 0);
35532397ce0SDoug Ambrisko pfs_create_file(sub_dir, "proc_name",
35632397ce0SDoug Ambrisko &linsysfs_scsiname,
357771709ebSDag-Erling Smørgrav NULL, NULL, NULL, PFS_RD);
35832397ce0SDoug Ambrisko scsi_host->name
35932397ce0SDoug Ambrisko = linux_driver_get_name_dev(dev);
36032397ce0SDoug Ambrisko TAILQ_INSERT_TAIL(&scsi_host_q,
36132397ce0SDoug Ambrisko scsi_host, scsi_host_next);
36232397ce0SDoug Ambrisko }
36332397ce0SDoug Ambrisko free(device, M_TEMP);
36432397ce0SDoug Ambrisko free(host, M_TEMP);
36532397ce0SDoug Ambrisko }
36632397ce0SDoug Ambrisko }
3672d347b2eSConrad Meyer
3682d347b2eSConrad Meyer devclass = device_get_devclass(dev);
3692d347b2eSConrad Meyer if (devclass != NULL)
3702d347b2eSConrad Meyer name = devclass_get_name(devclass);
3714d367f25SConrad Meyer else
3724d367f25SConrad Meyer name = NULL;
3732d347b2eSConrad Meyer if (name != NULL && strcmp(name, DRMN_DEV) == 0 &&
3742d347b2eSConrad Meyer device_get_unit(dev) >= 0) {
3754d367f25SConrad Meyer dinfo = device_get_ivars(parent);
3764d367f25SConrad Meyer if (dinfo != NULL && dinfo->cfg.baseclass == PCIC_DISPLAY) {
37755258ab0STijl Coosemans pfs_create_dir(dir, "drm", NULL, NULL, NULL, 0);
37803cea61bSTijl Coosemans sprintf(devname, "226:%d",
3792d347b2eSConrad Meyer device_get_unit(dev));
38003cea61bSTijl Coosemans sub_dir = pfs_create_dir(chardev,
38103cea61bSTijl Coosemans devname, NULL, NULL, NULL, 0);
38203cea61bSTijl Coosemans cur_file = pfs_create_link(sub_dir,
3832d347b2eSConrad Meyer "device", &linsysfs_fill_vgapci, NULL,
3842d347b2eSConrad Meyer NULL, NULL, PFS_RD);
3852d347b2eSConrad Meyer cur_file->pn_data = (void*)dir;
38603cea61bSTijl Coosemans cur_file = pfs_create_file(sub_dir,
3872d347b2eSConrad Meyer "uevent", &linsysfs_fill_uevent_drm, NULL,
3882d347b2eSConrad Meyer NULL, NULL, PFS_RD);
3892d347b2eSConrad Meyer cur_file->pn_data = (void*)dev;
39003cea61bSTijl Coosemans sprintf(devname, "card%d",
39103cea61bSTijl Coosemans device_get_unit(dev));
39203cea61bSTijl Coosemans sub_dir = pfs_create_dir(drm,
39303cea61bSTijl Coosemans devname, NULL, NULL, NULL, 0);
39403cea61bSTijl Coosemans cur_file = pfs_create_link(sub_dir,
39503cea61bSTijl Coosemans "device", &linsysfs_fill_vgapci, NULL,
39603cea61bSTijl Coosemans NULL, NULL, PFS_RD);
39703cea61bSTijl Coosemans cur_file->pn_data = (void*)dir;
3982d347b2eSConrad Meyer }
3992d347b2eSConrad Meyer }
40032397ce0SDoug Ambrisko }
40132397ce0SDoug Ambrisko
4024d367f25SConrad Meyer error = device_get_children(dev, &children, &nchildren);
4034d367f25SConrad Meyer if (error == 0) {
4044d367f25SConrad Meyer for (i = 0; i < nchildren; i++)
40532397ce0SDoug Ambrisko if (children[i])
4064d367f25SConrad Meyer linsysfs_run_bus(children[i], dir, scsi,
40703cea61bSTijl Coosemans chardev, drm, new_path, prefix);
4084d367f25SConrad Meyer free(children, M_TEMP);
40932397ce0SDoug Ambrisko }
41032397ce0SDoug Ambrisko if (new_path != path)
41132397ce0SDoug Ambrisko free(new_path, M_TEMP);
41203cea61bSTijl Coosemans free(devname, M_TEMP);
41332397ce0SDoug Ambrisko
41432397ce0SDoug Ambrisko return (1);
41532397ce0SDoug Ambrisko }
41632397ce0SDoug Ambrisko
41732397ce0SDoug Ambrisko /*
41812f3888aSEdward Tomasz Napierala * Filler function for sys/devices/system/cpu/{online,possible,present}
419039aba08SDmitry Chagin */
420039aba08SDmitry Chagin static int
linsysfs_cpuonline(PFS_FILL_ARGS)421039aba08SDmitry Chagin linsysfs_cpuonline(PFS_FILL_ARGS)
422039aba08SDmitry Chagin {
423039aba08SDmitry Chagin
424039aba08SDmitry Chagin sbuf_printf(sb, "%d-%d\n", CPU_FIRST(), mp_maxid);
425039aba08SDmitry Chagin return (0);
426039aba08SDmitry Chagin }
427039aba08SDmitry Chagin
428039aba08SDmitry Chagin /*
429039aba08SDmitry Chagin * Filler function for sys/devices/system/cpu/cpuX/online
430039aba08SDmitry Chagin */
431039aba08SDmitry Chagin static int
linsysfs_cpuxonline(PFS_FILL_ARGS)432039aba08SDmitry Chagin linsysfs_cpuxonline(PFS_FILL_ARGS)
433039aba08SDmitry Chagin {
434039aba08SDmitry Chagin
435039aba08SDmitry Chagin sbuf_printf(sb, "1\n");
436039aba08SDmitry Chagin return (0);
437039aba08SDmitry Chagin }
438039aba08SDmitry Chagin
439039aba08SDmitry Chagin static void
linsysfs_listcpus(struct pfs_node * dir)440039aba08SDmitry Chagin linsysfs_listcpus(struct pfs_node *dir)
441039aba08SDmitry Chagin {
442039aba08SDmitry Chagin struct pfs_node *cpu;
443039aba08SDmitry Chagin char *name;
444039aba08SDmitry Chagin int i, count, len;
445039aba08SDmitry Chagin
446039aba08SDmitry Chagin len = 1;
447039aba08SDmitry Chagin count = mp_maxcpus;
448039aba08SDmitry Chagin while (count > 10) {
449039aba08SDmitry Chagin count /= 10;
450039aba08SDmitry Chagin len++;
451039aba08SDmitry Chagin }
452039aba08SDmitry Chagin len += sizeof("cpu");
453039aba08SDmitry Chagin name = malloc(len, M_TEMP, M_WAITOK);
454039aba08SDmitry Chagin
455039aba08SDmitry Chagin for (i = 0; i < mp_ncpus; ++i) {
456039aba08SDmitry Chagin /* /sys/devices/system/cpu/cpuX */
457039aba08SDmitry Chagin sprintf(name, "cpu%d", i);
458039aba08SDmitry Chagin cpu = pfs_create_dir(dir, name, NULL, NULL, NULL, 0);
459039aba08SDmitry Chagin
460039aba08SDmitry Chagin pfs_create_file(cpu, "online", &linsysfs_cpuxonline,
461039aba08SDmitry Chagin NULL, NULL, NULL, PFS_RD);
462039aba08SDmitry Chagin }
463039aba08SDmitry Chagin free(name, M_TEMP);
464039aba08SDmitry Chagin }
465039aba08SDmitry Chagin
466039aba08SDmitry Chagin /*
46732397ce0SDoug Ambrisko * Constructor
46832397ce0SDoug Ambrisko */
46932397ce0SDoug Ambrisko static int
linsysfs_init(PFS_INIT_ARGS)47032397ce0SDoug Ambrisko linsysfs_init(PFS_INIT_ARGS)
47132397ce0SDoug Ambrisko {
47232397ce0SDoug Ambrisko struct pfs_node *root;
47303cea61bSTijl Coosemans struct pfs_node *class;
474039aba08SDmitry Chagin struct pfs_node *dir, *sys, *cpu;
47503cea61bSTijl Coosemans struct pfs_node *drm;
47632397ce0SDoug Ambrisko struct pfs_node *pci;
47732397ce0SDoug Ambrisko struct pfs_node *scsi;
4782d347b2eSConrad Meyer struct pfs_node *devdir, *chardev;
47946888dedSMark Johnston struct pfs_node *kernel;
48032397ce0SDoug Ambrisko devclass_t devclass;
48132397ce0SDoug Ambrisko device_t dev;
48232397ce0SDoug Ambrisko
48332397ce0SDoug Ambrisko TAILQ_INIT(&scsi_host_q);
48432397ce0SDoug Ambrisko
48532397ce0SDoug Ambrisko root = pi->pi_root;
48632397ce0SDoug Ambrisko
487dc0119c2SEdward Tomasz Napierala /* /sys/bus/... */
488dc0119c2SEdward Tomasz Napierala dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
489dc0119c2SEdward Tomasz Napierala
49032397ce0SDoug Ambrisko /* /sys/class/... */
49103cea61bSTijl Coosemans class = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
49203cea61bSTijl Coosemans scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0);
49303cea61bSTijl Coosemans drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0);
494bafe3b88SDmitry Chagin pfs_create_dir(class, "power_supply", NULL, NULL, NULL, 0);
49532397ce0SDoug Ambrisko
4964e2f69f1SDmitry Chagin /* /sys/class/net/.. */
4974e2f69f1SDmitry Chagin net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0);
4984e2f69f1SDmitry Chagin
49903cea61bSTijl Coosemans /* /sys/dev/... */
5002d347b2eSConrad Meyer devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0);
5012d347b2eSConrad Meyer chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0);
5022d347b2eSConrad Meyer
50303cea61bSTijl Coosemans /* /sys/devices/... */
50403cea61bSTijl Coosemans dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
50503cea61bSTijl Coosemans pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
50603cea61bSTijl Coosemans
50732397ce0SDoug Ambrisko devclass = devclass_find("root");
50832397ce0SDoug Ambrisko if (devclass == NULL) {
50932397ce0SDoug Ambrisko return (0);
51032397ce0SDoug Ambrisko }
51132397ce0SDoug Ambrisko
51232397ce0SDoug Ambrisko dev = devclass_get_device(devclass, 0);
51303cea61bSTijl Coosemans linsysfs_run_bus(dev, pci, scsi, chardev, drm, "/pci0000:00", "0000");
514039aba08SDmitry Chagin
515039aba08SDmitry Chagin /* /sys/devices/system */
516039aba08SDmitry Chagin sys = pfs_create_dir(dir, "system", NULL, NULL, NULL, 0);
517039aba08SDmitry Chagin
518039aba08SDmitry Chagin /* /sys/devices/system/cpu */
519039aba08SDmitry Chagin cpu = pfs_create_dir(sys, "cpu", NULL, NULL, NULL, 0);
520039aba08SDmitry Chagin
521039aba08SDmitry Chagin pfs_create_file(cpu, "online", &linsysfs_cpuonline,
522039aba08SDmitry Chagin NULL, NULL, NULL, PFS_RD);
52312f3888aSEdward Tomasz Napierala pfs_create_file(cpu, "possible", &linsysfs_cpuonline,
52412f3888aSEdward Tomasz Napierala NULL, NULL, NULL, PFS_RD);
52512f3888aSEdward Tomasz Napierala pfs_create_file(cpu, "present", &linsysfs_cpuonline,
52612f3888aSEdward Tomasz Napierala NULL, NULL, NULL, PFS_RD);
527039aba08SDmitry Chagin
528039aba08SDmitry Chagin linsysfs_listcpus(cpu);
529039aba08SDmitry Chagin
53046888dedSMark Johnston /* /sys/kernel */
53146888dedSMark Johnston kernel = pfs_create_dir(root, "kernel", NULL, NULL, NULL, 0);
53246888dedSMark Johnston /* /sys/kernel/debug, mountpoint for lindebugfs. */
533bafe3b88SDmitry Chagin pfs_create_dir(kernel, "debug", NULL, NULL, NULL, 0);
53446888dedSMark Johnston
5357ae0972cSDmitry Chagin linsysfs_net_init();
5367ae0972cSDmitry Chagin
53732397ce0SDoug Ambrisko return (0);
53832397ce0SDoug Ambrisko }
53932397ce0SDoug Ambrisko
54032397ce0SDoug Ambrisko /*
54132397ce0SDoug Ambrisko * Destructor
54232397ce0SDoug Ambrisko */
54332397ce0SDoug Ambrisko static int
linsysfs_uninit(PFS_INIT_ARGS)54432397ce0SDoug Ambrisko linsysfs_uninit(PFS_INIT_ARGS)
54532397ce0SDoug Ambrisko {
5465ac73157SAlexander Leidinger struct scsi_host_queue *scsi_host, *scsi_host_tmp;
54732397ce0SDoug Ambrisko
5485ac73157SAlexander Leidinger TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
5495ac73157SAlexander Leidinger scsi_host_tmp) {
55032397ce0SDoug Ambrisko TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
55132397ce0SDoug Ambrisko free(scsi_host->path, M_TEMP);
55232397ce0SDoug Ambrisko free(scsi_host, M_TEMP);
55332397ce0SDoug Ambrisko }
55432397ce0SDoug Ambrisko
5557ae0972cSDmitry Chagin linsysfs_net_uninit();
5567ae0972cSDmitry Chagin
55732397ce0SDoug Ambrisko return (0);
55832397ce0SDoug Ambrisko }
55932397ce0SDoug Ambrisko
5600e5c6bd4SJamie Gritton PSEUDOFS(linsysfs, 1, VFCF_JAIL);
561bbc82947SEd Maste #if defined(__aarch64__) || defined(__amd64__)
56267d39748SDmitry Chagin MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1);
56367d39748SDmitry Chagin #else
56432397ce0SDoug Ambrisko MODULE_DEPEND(linsysfs, linux, 1, 1, 1);
56567d39748SDmitry Chagin #endif
566