The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/compat/linsysfs/linsysfs.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2006 IronPort Systems
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice, this list of conditions and the following disclaimer.
   12  * 2. Redistributions in binary form must reproduce the above copyright
   13  *    notice, this list of conditions and the following disclaimer in the
   14  *    documentation and/or other materials provided with the distribution.
   15  *
   16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   26  * SUCH DAMAGE.
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD$");
   31 
   32 #include <sys/param.h>
   33 #include <sys/systm.h>
   34 #include <sys/ctype.h>
   35 #include <sys/kernel.h>
   36 #include <sys/malloc.h>
   37 #include <sys/mount.h>
   38 #include <sys/sbuf.h>
   39 #include <sys/smp.h>
   40 #include <sys/socket.h>
   41 #include <sys/bus.h>
   42 #include <sys/pciio.h>
   43 
   44 #include <dev/pci/pcivar.h>
   45 #include <dev/pci/pcireg.h>
   46 
   47 #include <net/if.h>
   48 #include <net/if_var.h>
   49 #include <net/if_dl.h>
   50 
   51 #include <compat/linux/linux.h>
   52 #include <compat/linux/linux_common.h>
   53 #include <compat/linux/linux_util.h>
   54 #include <fs/pseudofs/pseudofs.h>
   55 
   56 struct scsi_host_queue {
   57         TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
   58         char *path;
   59         char *name;
   60 };
   61 
   62 TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
   63 
   64 static int host_number = 0;
   65 
   66 static int
   67 atoi(const char *str)
   68 {
   69         return (int)strtol(str, (char **)NULL, 10);
   70 }
   71 
   72 static int
   73 linsysfs_ifnet_addr(PFS_FILL_ARGS)
   74 {
   75         struct l_sockaddr lsa;
   76         struct ifnet *ifp;
   77 
   78         ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
   79         if (ifp == NULL)
   80                 return (ENOENT);
   81         if (linux_ifhwaddr(ifp, &lsa) != 0)
   82                 return (ENOENT);
   83         sbuf_printf(sb, "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n",
   84             lsa.sa_data[0], lsa.sa_data[1], lsa.sa_data[2],
   85             lsa.sa_data[3], lsa.sa_data[4], lsa.sa_data[5]);
   86         return (0);
   87 }
   88 
   89 static int
   90 linsysfs_ifnet_addrlen(PFS_FILL_ARGS)
   91 {
   92 
   93         sbuf_printf(sb, "%d\n", LINUX_IFHWADDRLEN);
   94         return (0);
   95 }
   96 
   97 static int
   98 linsysfs_ifnet_flags(PFS_FILL_ARGS)
   99 {
  100         struct ifnet *ifp;
  101         unsigned short flags;
  102 
  103         ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
  104         if (ifp == NULL)
  105                 return (ENOENT);
  106         linux_ifflags(ifp, &flags);
  107         sbuf_printf(sb, "0x%x\n", flags);
  108         return (0);
  109 }
  110 
  111 static int
  112 linsysfs_ifnet_ifindex(PFS_FILL_ARGS)
  113 {
  114         struct ifnet *ifp;
  115 
  116         ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
  117         if (ifp == NULL)
  118                 return (ENOENT);
  119         sbuf_printf(sb, "%u\n", ifp->if_index);
  120         return (0);
  121 }
  122 
  123 static int
  124 linsysfs_ifnet_mtu(PFS_FILL_ARGS)
  125 {
  126         struct ifnet *ifp;
  127 
  128         ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
  129         if (ifp == NULL)
  130                 return (ENOENT);
  131         sbuf_printf(sb, "%u\n", ifp->if_mtu);
  132         return (0);
  133 }
  134 
  135 static int
  136 linsysfs_ifnet_tx_queue_len(PFS_FILL_ARGS)
  137 {
  138 
  139         /* XXX */
  140         sbuf_printf(sb, "1000\n");
  141         return (0);
  142 }
  143 
  144 static int
  145 linsysfs_ifnet_type(PFS_FILL_ARGS)
  146 {
  147         struct l_sockaddr lsa;
  148         struct ifnet *ifp;
  149 
  150         ifp = ifname_linux_to_bsd(td, pn->pn_parent->pn_name, NULL);
  151         if (ifp == NULL)
  152                 return (ENOENT);
  153         if (linux_ifhwaddr(ifp, &lsa) != 0)
  154                 return (ENOENT);
  155         sbuf_printf(sb, "%d\n", lsa.sa_family);
  156         return (0);
  157 }
  158 
  159 static void
  160 linsysfs_listnics(struct pfs_node *dir)
  161 {
  162         struct pfs_node *nic;
  163         struct pfs_node *lo;
  164 
  165         nic = pfs_create_dir(dir, "eth0", NULL, NULL, NULL, 0);
  166 
  167         pfs_create_file(nic, "address", &linsysfs_ifnet_addr,
  168             NULL, NULL, NULL, PFS_RD);
  169 
  170         pfs_create_file(nic, "addr_len", &linsysfs_ifnet_addrlen,
  171             NULL, NULL, NULL, PFS_RD);
  172 
  173         pfs_create_file(nic, "flags", &linsysfs_ifnet_flags,
  174             NULL, NULL, NULL, PFS_RD);
  175 
  176         pfs_create_file(nic, "ifindex", &linsysfs_ifnet_ifindex,
  177             NULL, NULL, NULL, PFS_RD);
  178 
  179         pfs_create_file(nic, "mtu", &linsysfs_ifnet_mtu,
  180             NULL, NULL, NULL, PFS_RD);
  181 
  182         pfs_create_file(nic, "tx_queue_len", &linsysfs_ifnet_tx_queue_len,
  183             NULL, NULL, NULL, PFS_RD);
  184 
  185         pfs_create_file(nic, "type", &linsysfs_ifnet_type,
  186             NULL, NULL, NULL, PFS_RD);
  187 
  188         lo = pfs_create_dir(dir, "lo", NULL, NULL, NULL, 0);
  189 
  190         pfs_create_file(lo, "address", &linsysfs_ifnet_addr,
  191             NULL, NULL, NULL, PFS_RD);
  192 
  193         pfs_create_file(lo, "addr_len", &linsysfs_ifnet_addrlen,
  194             NULL, NULL, NULL, PFS_RD);
  195 
  196         pfs_create_file(lo, "flags", &linsysfs_ifnet_flags,
  197             NULL, NULL, NULL, PFS_RD);
  198 
  199         pfs_create_file(lo, "ifindex", &linsysfs_ifnet_ifindex,
  200             NULL, NULL, NULL, PFS_RD);
  201 
  202         pfs_create_file(lo, "mtu", &linsysfs_ifnet_mtu,
  203             NULL, NULL, NULL, PFS_RD);
  204 
  205         pfs_create_file(lo, "tx_queue_len", &linsysfs_ifnet_tx_queue_len,
  206             NULL, NULL, NULL, PFS_RD);
  207 
  208         pfs_create_file(lo, "type", &linsysfs_ifnet_type,
  209             NULL, NULL, NULL, PFS_RD);
  210 }
  211 
  212 /*
  213  * Filler function for proc_name
  214  */
  215 static int
  216 linsysfs_scsiname(PFS_FILL_ARGS)
  217 {
  218         struct scsi_host_queue *scsi_host;
  219         int index;
  220 
  221         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
  222                 index = atoi(&pn->pn_parent->pn_name[4]);
  223         } else {
  224                 sbuf_printf(sb, "unknown\n");
  225                 return (0);
  226         }
  227         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  228                 if (index-- == 0) {
  229                         sbuf_printf(sb, "%s\n", scsi_host->name);
  230                         return (0);
  231                 }
  232         }
  233         sbuf_printf(sb, "unknown\n");
  234         return (0);
  235 }
  236 
  237 /*
  238  * Filler function for device sym-link
  239  */
  240 static int
  241 linsysfs_link_scsi_host(PFS_FILL_ARGS)
  242 {
  243         struct scsi_host_queue *scsi_host;
  244         int index;
  245 
  246         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
  247                 index = atoi(&pn->pn_parent->pn_name[4]);
  248         } else {
  249                 sbuf_printf(sb, "unknown\n");
  250                 return (0);
  251         }
  252         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  253                 if (index-- == 0) {
  254                         sbuf_printf(sb, "../../../devices%s", scsi_host->path);
  255                         return(0);
  256                 }
  257         }
  258         sbuf_printf(sb, "unknown\n");
  259         return (0);
  260 }
  261 
  262 static int
  263 linsysfs_fill_data(PFS_FILL_ARGS)
  264 {
  265         sbuf_printf(sb, "%s", (char *)pn->pn_data);
  266         return (0);
  267 }
  268 
  269 static int
  270 linsysfs_fill_vendor(PFS_FILL_ARGS)
  271 {
  272         sbuf_printf(sb, "0x%04x\n", pci_get_vendor((device_t)pn->pn_data));
  273         return (0);
  274 }
  275 
  276 static int
  277 linsysfs_fill_device(PFS_FILL_ARGS)
  278 {
  279         sbuf_printf(sb, "0x%04x\n", pci_get_device((device_t)pn->pn_data));
  280         return (0);
  281 }
  282 
  283 static int
  284 linsysfs_fill_subvendor(PFS_FILL_ARGS)
  285 {
  286         sbuf_printf(sb, "0x%04x\n", pci_get_subvendor((device_t)pn->pn_data));
  287         return (0);
  288 }
  289 
  290 static int
  291 linsysfs_fill_subdevice(PFS_FILL_ARGS)
  292 {
  293         sbuf_printf(sb, "0x%04x\n", pci_get_subdevice((device_t)pn->pn_data));
  294         return (0);
  295 }
  296 
  297 static int
  298 linsysfs_fill_revid(PFS_FILL_ARGS)
  299 {
  300         sbuf_printf(sb, "0x%x\n", pci_get_revid((device_t)pn->pn_data));
  301         return (0);
  302 }
  303 
  304 static int
  305 linsysfs_fill_config(PFS_FILL_ARGS)
  306 {
  307         uint8_t config[48];
  308         device_t dev;
  309         uint32_t reg;
  310 
  311         dev = (device_t)pn->pn_data;
  312         bzero(config, sizeof(config));
  313         reg = pci_get_vendor(dev);
  314         config[0] = reg;
  315         config[1] = reg >> 8;
  316         reg = pci_get_device(dev);
  317         config[2] = reg;
  318         config[3] = reg >> 8;
  319         reg = pci_get_revid(dev);
  320         config[8] = reg;
  321         reg = pci_get_subvendor(dev);
  322         config[44] = reg;
  323         config[45] = reg >> 8;
  324         reg = pci_get_subdevice(dev);
  325         config[46] = reg;
  326         config[47] = reg >> 8;
  327         sbuf_bcat(sb, config, sizeof(config));
  328         return (0);
  329 }
  330 
  331 /*
  332  * Filler function for PCI uevent file
  333  */
  334 static int
  335 linsysfs_fill_uevent_pci(PFS_FILL_ARGS)
  336 {
  337         device_t dev;
  338 
  339         dev = (device_t)pn->pn_data;
  340         sbuf_printf(sb, "DRIVER=%s\nPCI_CLASS=%X\nPCI_ID=%04X:%04X\n"
  341             "PCI_SUBSYS_ID=%04X:%04X\nPCI_SLOT_NAME=%04d:%02x:%02x.%x\n",
  342             linux_driver_get_name_dev(dev), pci_get_class(dev),
  343             pci_get_vendor(dev), pci_get_device(dev), pci_get_subvendor(dev),
  344             pci_get_subdevice(dev), pci_get_domain(dev), pci_get_bus(dev),
  345             pci_get_slot(dev), pci_get_function(dev));
  346         return (0);
  347 }
  348 
  349 /*
  350  * Filler function for drm uevent file
  351  */
  352 static int
  353 linsysfs_fill_uevent_drm(PFS_FILL_ARGS)
  354 {
  355         device_t dev;
  356         int unit;
  357 
  358         dev = (device_t)pn->pn_data;
  359         unit = device_get_unit(dev);
  360         sbuf_printf(sb,
  361             "MAJOR=226\nMINOR=%d\nDEVNAME=dri/card%d\nDEVTYPE=dri_minor\n",
  362             unit, unit);
  363         return (0);
  364 }
  365 
  366 static char *
  367 get_full_pfs_path(struct pfs_node *cur)
  368 {
  369         char *temp, *path;
  370 
  371         temp = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  372         path = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  373         path[0] = '\0';
  374 
  375         do {
  376                 snprintf(temp, MAXPATHLEN, "%s/%s", cur->pn_name, path);
  377                 strlcpy(path, temp, MAXPATHLEN);
  378                 cur = cur->pn_parent;
  379         } while (cur->pn_parent != NULL);
  380 
  381         path[strlen(path) - 1] = '\0'; /* remove extra slash */
  382         free(temp, M_TEMP);
  383         return (path);
  384 }
  385 
  386 /*
  387  * Filler function for symlink from drm char device to PCI device
  388  */
  389 static int
  390 linsysfs_fill_vgapci(PFS_FILL_ARGS)
  391 {
  392         char *path;
  393 
  394         path = get_full_pfs_path((struct pfs_node*)pn->pn_data);
  395         sbuf_printf(sb, "../../../%s", path);
  396         free(path, M_TEMP);
  397         return (0);
  398 }
  399 
  400 #undef PCI_DEV
  401 #define PCI_DEV "pci"
  402 #define DRMN_DEV "drmn"
  403 static int
  404 linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi,
  405     struct pfs_node *chardev, struct pfs_node *drm, char *path, char *prefix)
  406 {
  407         struct scsi_host_queue *scsi_host;
  408         struct pfs_node *sub_dir, *cur_file;
  409         int i, nchildren, error;
  410         device_t *children, parent;
  411         devclass_t devclass;
  412         const char *name = NULL;
  413         struct pci_devinfo *dinfo;
  414         char *device, *host, *new_path, *devname;
  415 
  416         new_path = path;
  417         devname = malloc(16, M_TEMP, M_WAITOK);
  418 
  419         parent = device_get_parent(dev);
  420         if (parent) {
  421                 devclass = device_get_devclass(parent);
  422                 if (devclass != NULL)
  423                         name = devclass_get_name(devclass);
  424                 if (name && strcmp(name, PCI_DEV) == 0) {
  425                         dinfo = device_get_ivars(dev);
  426                         if (dinfo) {
  427                                 device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  428                                 new_path = malloc(MAXPATHLEN, M_TEMP,
  429                                     M_WAITOK);
  430                                 new_path[0] = '\000';
  431                                 strcpy(new_path, path);
  432                                 host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  433                                 device[0] = '\000';
  434                                 sprintf(device, "%s:%02x:%02x.%x",
  435                                     prefix,
  436                                     dinfo->cfg.bus,
  437                                     dinfo->cfg.slot,
  438                                     dinfo->cfg.func);
  439                                 strcat(new_path, "/");
  440                                 strcat(new_path, device);
  441                                 dir = pfs_create_dir(dir, device,
  442                                     NULL, NULL, NULL, 0);
  443                                 cur_file = pfs_create_file(dir, "vendor",
  444                                     &linsysfs_fill_vendor, NULL, NULL, NULL,
  445                                     PFS_RD);
  446                                 cur_file->pn_data = (void*)dev;
  447                                 cur_file = pfs_create_file(dir, "device",
  448                                     &linsysfs_fill_device, NULL, NULL, NULL,
  449                                     PFS_RD);
  450                                 cur_file->pn_data = (void*)dev;
  451                                 cur_file = pfs_create_file(dir,
  452                                     "subsystem_vendor",
  453                                     &linsysfs_fill_subvendor, NULL, NULL, NULL,
  454                                     PFS_RD);
  455                                 cur_file->pn_data = (void*)dev;
  456                                 cur_file = pfs_create_file(dir,
  457                                     "subsystem_device",
  458                                     &linsysfs_fill_subdevice, NULL, NULL, NULL,
  459                                     PFS_RD);
  460                                 cur_file->pn_data = (void*)dev;
  461                                 cur_file = pfs_create_file(dir, "revision",
  462                                     &linsysfs_fill_revid, NULL, NULL, NULL,
  463                                     PFS_RD);
  464                                 cur_file->pn_data = (void*)dev;
  465                                 cur_file = pfs_create_file(dir, "config",
  466                                     &linsysfs_fill_config, NULL, NULL, NULL,
  467                                     PFS_RD);
  468                                 cur_file->pn_data = (void*)dev;
  469                                 cur_file = pfs_create_file(dir, "uevent",
  470                                     &linsysfs_fill_uevent_pci, NULL, NULL,
  471                                     NULL, PFS_RD);
  472                                 cur_file->pn_data = (void*)dev;
  473                                 cur_file = pfs_create_link(dir, "subsystem",
  474                                     &linsysfs_fill_data, NULL, NULL, NULL, 0);
  475                                 /* libdrm just checks that the link ends in "/pci" */
  476                                 cur_file->pn_data = "/sys/bus/pci";
  477 
  478                                 if (dinfo->cfg.baseclass == PCIC_STORAGE) {
  479                                         /* DJA only make this if needed */
  480                                         sprintf(host, "host%d", host_number++);
  481                                         strcat(new_path, "/");
  482                                         strcat(new_path, host);
  483                                         pfs_create_dir(dir, host,
  484                                             NULL, NULL, NULL, 0);
  485                                         scsi_host = malloc(sizeof(
  486                                             struct scsi_host_queue),
  487                                             M_DEVBUF, M_NOWAIT);
  488                                         scsi_host->path = malloc(
  489                                             strlen(new_path) + 1,
  490                                             M_DEVBUF, M_NOWAIT);
  491                                         scsi_host->path[0] = '\000';
  492                                         bcopy(new_path, scsi_host->path,
  493                                             strlen(new_path) + 1);
  494                                         scsi_host->name = "unknown";
  495 
  496                                         sub_dir = pfs_create_dir(scsi, host,
  497                                             NULL, NULL, NULL, 0);
  498                                         pfs_create_link(sub_dir, "device",
  499                                             &linsysfs_link_scsi_host,
  500                                             NULL, NULL, NULL, 0);
  501                                         pfs_create_file(sub_dir, "proc_name",
  502                                             &linsysfs_scsiname,
  503                                             NULL, NULL, NULL, PFS_RD);
  504                                         scsi_host->name
  505                                             = linux_driver_get_name_dev(dev);
  506                                         TAILQ_INSERT_TAIL(&scsi_host_q,
  507                                             scsi_host, scsi_host_next);
  508                                 }
  509                                 free(device, M_TEMP);
  510                                 free(host, M_TEMP);
  511                         }
  512                 }
  513 
  514                 devclass = device_get_devclass(dev);
  515                 if (devclass != NULL)
  516                         name = devclass_get_name(devclass);
  517                 else
  518                         name = NULL;
  519                 if (name != NULL && strcmp(name, DRMN_DEV) == 0 &&
  520                     device_get_unit(dev) >= 0) {
  521                         dinfo = device_get_ivars(parent);
  522                         if (dinfo != NULL && dinfo->cfg.baseclass == PCIC_DISPLAY) {
  523                                 pfs_create_dir(dir, "drm", NULL, NULL, NULL, 0);
  524                                 sprintf(devname, "226:%d",
  525                                     device_get_unit(dev));
  526                                 sub_dir = pfs_create_dir(chardev,
  527                                     devname, NULL, NULL, NULL, 0);
  528                                 cur_file = pfs_create_link(sub_dir,
  529                                     "device", &linsysfs_fill_vgapci, NULL,
  530                                     NULL, NULL, PFS_RD);
  531                                 cur_file->pn_data = (void*)dir;
  532                                 cur_file = pfs_create_file(sub_dir,
  533                                     "uevent", &linsysfs_fill_uevent_drm, NULL,
  534                                     NULL, NULL, PFS_RD);
  535                                 cur_file->pn_data = (void*)dev;
  536                                 sprintf(devname, "card%d",
  537                                     device_get_unit(dev));
  538                                 sub_dir = pfs_create_dir(drm,
  539                                     devname, NULL, NULL, NULL, 0);
  540                                 cur_file = pfs_create_link(sub_dir,
  541                                     "device", &linsysfs_fill_vgapci, NULL,
  542                                     NULL, NULL, PFS_RD);
  543                                 cur_file->pn_data = (void*)dir;
  544                         }
  545                 }
  546         }
  547 
  548         error = device_get_children(dev, &children, &nchildren);
  549         if (error == 0) {
  550                 for (i = 0; i < nchildren; i++)
  551                         if (children[i])
  552                                 linsysfs_run_bus(children[i], dir, scsi,
  553                                     chardev, drm, new_path, prefix);
  554                 free(children, M_TEMP);
  555         }
  556         if (new_path != path)
  557                 free(new_path, M_TEMP);
  558         free(devname, M_TEMP);
  559 
  560         return (1);
  561 }
  562 
  563 /*
  564  * Filler function for sys/devices/system/cpu/{online,possible,present}
  565  */
  566 static int
  567 linsysfs_cpuonline(PFS_FILL_ARGS)
  568 {
  569 
  570         sbuf_printf(sb, "%d-%d\n", CPU_FIRST(), mp_maxid);
  571         return (0);
  572 }
  573 
  574 /*
  575  * Filler function for sys/devices/system/cpu/cpuX/online
  576  */
  577 static int
  578 linsysfs_cpuxonline(PFS_FILL_ARGS)
  579 {
  580 
  581         sbuf_printf(sb, "1\n");
  582         return (0);
  583 }
  584 
  585 static void
  586 linsysfs_listcpus(struct pfs_node *dir)
  587 {
  588         struct pfs_node *cpu;
  589         char *name;
  590         int i, count, len;
  591 
  592         len = 1;
  593         count = mp_maxcpus;
  594         while (count > 10) {
  595                 count /= 10;
  596                 len++;
  597         }
  598         len += sizeof("cpu");
  599         name = malloc(len, M_TEMP, M_WAITOK);
  600 
  601         for (i = 0; i < mp_ncpus; ++i) {
  602                 /* /sys/devices/system/cpu/cpuX */
  603                 sprintf(name, "cpu%d", i);
  604                 cpu = pfs_create_dir(dir, name, NULL, NULL, NULL, 0);
  605 
  606                 pfs_create_file(cpu, "online", &linsysfs_cpuxonline,
  607                     NULL, NULL, NULL, PFS_RD);
  608         }
  609         free(name, M_TEMP);
  610 }
  611 
  612 /*
  613  * Constructor
  614  */
  615 static int
  616 linsysfs_init(PFS_INIT_ARGS)
  617 {
  618         struct pfs_node *root;
  619         struct pfs_node *class;
  620         struct pfs_node *dir, *sys, *cpu;
  621         struct pfs_node *drm;
  622         struct pfs_node *pci;
  623         struct pfs_node *scsi;
  624         struct pfs_node *net;
  625         struct pfs_node *devdir, *chardev;
  626         struct pfs_node *kernel;
  627         devclass_t devclass;
  628         device_t dev;
  629 
  630         TAILQ_INIT(&scsi_host_q);
  631 
  632         root = pi->pi_root;
  633 
  634         /* /sys/bus/... */
  635         dir = pfs_create_dir(root, "bus", NULL, NULL, NULL, 0);
  636 
  637         /* /sys/class/... */
  638         class = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
  639         scsi = pfs_create_dir(class, "scsi_host", NULL, NULL, NULL, 0);
  640         drm = pfs_create_dir(class, "drm", NULL, NULL, NULL, 0);
  641         pfs_create_dir(class, "power_supply", NULL, NULL, NULL, 0);
  642 
  643         /* /sys/class/net/.. */
  644         net = pfs_create_dir(class, "net", NULL, NULL, NULL, 0);
  645 
  646         /* /sys/dev/... */
  647         devdir = pfs_create_dir(root, "dev", NULL, NULL, NULL, 0);
  648         chardev = pfs_create_dir(devdir, "char", NULL, NULL, NULL, 0);
  649 
  650         /* /sys/devices/... */
  651         dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
  652         pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
  653 
  654         devclass = devclass_find("root");
  655         if (devclass == NULL) {
  656                 return (0);
  657         }
  658 
  659         dev = devclass_get_device(devclass, 0);
  660         linsysfs_run_bus(dev, pci, scsi, chardev, drm, "/pci0000:00", "0000");
  661 
  662         /* /sys/devices/system */
  663         sys = pfs_create_dir(dir, "system", NULL, NULL, NULL, 0);
  664 
  665         /* /sys/devices/system/cpu */
  666         cpu = pfs_create_dir(sys, "cpu", NULL, NULL, NULL, 0);
  667 
  668         pfs_create_file(cpu, "online", &linsysfs_cpuonline,
  669             NULL, NULL, NULL, PFS_RD);
  670         pfs_create_file(cpu, "possible", &linsysfs_cpuonline,
  671             NULL, NULL, NULL, PFS_RD);
  672         pfs_create_file(cpu, "present", &linsysfs_cpuonline,
  673             NULL, NULL, NULL, PFS_RD);
  674 
  675         linsysfs_listcpus(cpu);
  676         linsysfs_listnics(net);
  677 
  678         /* /sys/kernel */
  679         kernel = pfs_create_dir(root, "kernel", NULL, NULL, NULL, 0);
  680         /* /sys/kernel/debug, mountpoint for lindebugfs. */
  681         pfs_create_dir(kernel, "debug", NULL, NULL, NULL, 0);
  682 
  683         /* /sys/subsystem/... */
  684         dir = pfs_create_dir(root, "subsystem", NULL, NULL, NULL, 0);
  685 
  686         return (0);
  687 }
  688 
  689 /*
  690  * Destructor
  691  */
  692 static int
  693 linsysfs_uninit(PFS_INIT_ARGS)
  694 {
  695         struct scsi_host_queue *scsi_host, *scsi_host_tmp;
  696 
  697         TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
  698             scsi_host_tmp) {
  699                 TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
  700                 free(scsi_host->path, M_TEMP);
  701                 free(scsi_host, M_TEMP);
  702         }
  703 
  704         return (0);
  705 }
  706 
  707 PSEUDOFS(linsysfs, 1, VFCF_JAIL);
  708 #if defined(__aarch64__) || defined(__amd64__)
  709 MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1);
  710 #else
  711 MODULE_DEPEND(linsysfs, linux, 1, 1, 1);
  712 #endif

Cache object: f60f3272b57e12df1edecf69c5164d4d


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.