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  * Copyright (c) 2006 IronPort Systems
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  *
   14  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   24  * SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/10.4/sys/compat/linsysfs/linsysfs.c 295951 2016-02-24 02:34:11Z araujo $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/queue.h>
   32 #include <sys/blist.h>
   33 #include <sys/conf.h>
   34 #include <sys/exec.h>
   35 #include <sys/filedesc.h>
   36 #include <sys/kernel.h>
   37 #include <sys/linker.h>
   38 #include <sys/malloc.h>
   39 #include <sys/mount.h>
   40 #include <sys/mutex.h>
   41 #include <sys/proc.h>
   42 #include <sys/resourcevar.h>
   43 #include <sys/sbuf.h>
   44 #include <sys/smp.h>
   45 #include <sys/socket.h>
   46 #include <sys/vnode.h>
   47 #include <sys/bus.h>
   48 #include <sys/pciio.h>
   49 
   50 #include <dev/pci/pcivar.h>
   51 #include <dev/pci/pcireg.h>
   52 
   53 #include <net/if.h>
   54 
   55 #include <vm/vm.h>
   56 #include <vm/pmap.h>
   57 #include <vm/vm_map.h>
   58 #include <vm/vm_param.h>
   59 #include <vm/vm_object.h>
   60 #include <vm/swap_pager.h>
   61 
   62 #include <machine/bus.h>
   63 
   64 #include <compat/linux/linux_ioctl.h>
   65 #include <compat/linux/linux_mib.h>
   66 #include <compat/linux/linux_util.h>
   67 #include <fs/pseudofs/pseudofs.h>
   68 
   69 struct scsi_host_queue {
   70         TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
   71         char *path;
   72         char *name;
   73 };
   74 
   75 TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
   76 
   77 static int host_number = 0;
   78 
   79 static int
   80 atoi(const char *str)
   81 {
   82         return (int)strtol(str, (char **)NULL, 10);
   83 }
   84 
   85 /*
   86  * Filler function for proc_name
   87  */
   88 static int
   89 linsysfs_scsiname(PFS_FILL_ARGS)
   90 {
   91         struct scsi_host_queue *scsi_host;
   92         int index;
   93 
   94         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
   95                 index = atoi(&pn->pn_parent->pn_name[4]);
   96         } else {
   97                 sbuf_printf(sb, "unknown\n");
   98                 return (0);
   99         }
  100         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  101                 if (index-- == 0) {
  102                         sbuf_printf(sb, "%s\n", scsi_host->name);
  103                         return (0);
  104                 }
  105         }
  106         sbuf_printf(sb, "unknown\n");
  107         return (0);
  108 }
  109 
  110 /*
  111  * Filler function for device sym-link
  112  */
  113 static int
  114 linsysfs_link_scsi_host(PFS_FILL_ARGS)
  115 {
  116         struct scsi_host_queue *scsi_host;
  117         int index;
  118 
  119         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
  120                 index = atoi(&pn->pn_parent->pn_name[4]);
  121         } else {
  122                 sbuf_printf(sb, "unknown\n");
  123                 return (0);
  124         }
  125         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  126                 if (index-- == 0) {
  127                         sbuf_printf(sb, "../../../devices%s", scsi_host->path);
  128                         return(0);
  129                 }
  130         }
  131         sbuf_printf(sb, "unknown\n");
  132         return (0);
  133 }
  134 
  135 #define PCI_DEV "pci"
  136 static int
  137 linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path,
  138    char *prefix)
  139 {
  140         struct scsi_host_queue *scsi_host;
  141         struct pfs_node *sub_dir;
  142         int i, nchildren;
  143         device_t *children, parent;
  144         devclass_t devclass;
  145         const char *name = NULL;
  146         struct pci_devinfo *dinfo;
  147         char *device, *host, *new_path = path;
  148 
  149         parent = device_get_parent(dev);
  150         if (parent) {
  151                 devclass = device_get_devclass(parent);
  152                 if (devclass != NULL)
  153                         name = devclass_get_name(devclass);
  154                 if (name && strcmp(name, PCI_DEV) == 0) {
  155                         dinfo = device_get_ivars(dev);
  156                         if (dinfo) {
  157                                 device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  158                                 new_path = malloc(MAXPATHLEN, M_TEMP,
  159                                     M_WAITOK);
  160                                 new_path[0] = '\000';
  161                                 strcpy(new_path, path);
  162                                 host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  163                                 device[0] = '\000';
  164                                 sprintf(device, "%s:%02x:%02x.%x",
  165                                     prefix,
  166                                     dinfo->cfg.bus,
  167                                     dinfo->cfg.slot,
  168                                     dinfo->cfg.func);
  169                                 strcat(new_path, "/");
  170                                 strcat(new_path, device);
  171                                 dir = pfs_create_dir(dir, device,
  172                                     NULL, NULL, NULL, 0);
  173 
  174                                 if (dinfo->cfg.baseclass == PCIC_STORAGE) {
  175                                         /* DJA only make this if needed */
  176                                         sprintf(host, "host%d", host_number++);
  177                                         strcat(new_path, "/");
  178                                         strcat(new_path, host);
  179                                         pfs_create_dir(dir, host,
  180                                             NULL, NULL, NULL, 0);
  181                                         scsi_host = malloc(sizeof(
  182                                             struct scsi_host_queue),
  183                                             M_DEVBUF, M_NOWAIT);
  184                                         scsi_host->path = malloc(
  185                                             strlen(new_path) + 1,
  186                                             M_DEVBUF, M_NOWAIT);
  187                                         scsi_host->path[0] = '\000';
  188                                         bcopy(new_path, scsi_host->path,
  189                                             strlen(new_path) + 1);
  190                                         scsi_host->name = "unknown";
  191 
  192                                         sub_dir = pfs_create_dir(scsi, host,
  193                                             NULL, NULL, NULL, 0);
  194                                         pfs_create_link(sub_dir, "device",
  195                                             &linsysfs_link_scsi_host,
  196                                             NULL, NULL, NULL, 0);
  197                                         pfs_create_file(sub_dir, "proc_name",
  198                                             &linsysfs_scsiname,
  199                                             NULL, NULL, NULL, PFS_RD);
  200                                         scsi_host->name
  201                                             = linux_driver_get_name_dev(dev);
  202                                         TAILQ_INSERT_TAIL(&scsi_host_q,
  203                                             scsi_host, scsi_host_next);
  204                                 }
  205                                 free(device, M_TEMP);
  206                                 free(host, M_TEMP);
  207                         }
  208                 }
  209         }
  210 
  211         device_get_children(dev, &children, &nchildren);
  212         for (i = 0; i < nchildren; i++) {
  213                 if (children[i])
  214                         linsysfs_run_bus(children[i], dir, scsi, new_path, prefix);
  215         }
  216         if (new_path != path)
  217                 free(new_path, M_TEMP);
  218 
  219         return (1);
  220 }
  221 
  222 /*
  223  * Constructor
  224  */
  225 static int
  226 linsysfs_init(PFS_INIT_ARGS)
  227 {
  228         struct pfs_node *root;
  229         struct pfs_node *dir;
  230         struct pfs_node *pci;
  231         struct pfs_node *scsi;
  232         devclass_t devclass;
  233         device_t dev;
  234 
  235         TAILQ_INIT(&scsi_host_q);
  236 
  237         root = pi->pi_root;
  238 
  239         /* /sys/class/... */
  240         scsi = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
  241         scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, NULL, 0);
  242 
  243         /* /sys/device */
  244         dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
  245 
  246         /* /sys/device/pci0000:00 */
  247         pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
  248 
  249         devclass = devclass_find("root");
  250         if (devclass == NULL) {
  251                 return (0);
  252         }
  253 
  254         dev = devclass_get_device(devclass, 0);
  255         linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000");
  256         return (0);
  257 }
  258 
  259 /*
  260  * Destructor
  261  */
  262 static int
  263 linsysfs_uninit(PFS_INIT_ARGS)
  264 {
  265         struct scsi_host_queue *scsi_host, *scsi_host_tmp;
  266 
  267         TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
  268             scsi_host_tmp) {
  269                 TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
  270                 free(scsi_host->path, M_TEMP);
  271                 free(scsi_host, M_TEMP);
  272         }
  273 
  274         return (0);
  275 }
  276 
  277 PSEUDOFS(linsysfs, 1, PR_ALLOW_MOUNT_LINSYSFS);
  278 #if defined(__amd64__)
  279 MODULE_DEPEND(linsysfs, linux_common, 1, 1, 1);
  280 #else
  281 MODULE_DEPEND(linsysfs, linux, 1, 1, 1);
  282 #endif

Cache object: ed7e4b99b721396738b96494ba685b7c


[ 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.