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$");
   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 "opt_compat.h"
   65 #ifdef COMPAT_LINUX32                           /* XXX */
   66 #include <machine/../linux32/linux.h>
   67 #else
   68 #include <machine/../linux/linux.h>
   69 #endif
   70 #include <compat/linux/linux_ioctl.h>
   71 #include <compat/linux/linux_mib.h>
   72 #include <compat/linux/linux_util.h>
   73 #include <fs/pseudofs/pseudofs.h>
   74 
   75 struct scsi_host_queue {
   76         TAILQ_ENTRY(scsi_host_queue) scsi_host_next;
   77         char *path;
   78         char *name;
   79 };
   80 
   81 TAILQ_HEAD(,scsi_host_queue) scsi_host_q;
   82 
   83 static int host_number = 0;
   84 
   85 static int
   86 atoi(const char *str)
   87 {
   88         return (int)strtol(str, (char **)NULL, 10);
   89 }
   90 
   91 /*
   92  * Filler function for proc_name
   93  */
   94 static int
   95 linsysfs_scsiname(PFS_FILL_ARGS)
   96 {
   97         struct scsi_host_queue *scsi_host;
   98         int index;
   99 
  100         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
  101                 index = atoi(&pn->pn_parent->pn_name[4]);
  102         } else {
  103                 sbuf_printf(sb, "unknown\n");
  104                 return (0);
  105         }
  106         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  107                 if (index-- == 0) {
  108                         sbuf_printf(sb, "%s\n", scsi_host->name);
  109                         return (0);
  110                 }
  111         }
  112         sbuf_printf(sb, "unknown\n");
  113         return (0);
  114 }
  115 
  116 /*
  117  * Filler function for device sym-link
  118  */
  119 static int
  120 linsysfs_link_scsi_host(PFS_FILL_ARGS)
  121 {
  122         struct scsi_host_queue *scsi_host;
  123         int index;
  124 
  125         if (strncmp(pn->pn_parent->pn_name, "host", 4) == 0) {
  126                 index = atoi(&pn->pn_parent->pn_name[4]);
  127         } else {
  128                 sbuf_printf(sb, "unknown\n");
  129                 return (0);
  130         }
  131         TAILQ_FOREACH(scsi_host, &scsi_host_q, scsi_host_next) {
  132                 if (index-- == 0) {
  133                         sbuf_printf(sb, "../../../devices%s", scsi_host->path);
  134                         return(0);
  135                 }
  136         }
  137         sbuf_printf(sb, "unknown\n");
  138         return (0);
  139 }
  140 
  141 #define PCI_DEV "pci"
  142 static int
  143 linsysfs_run_bus(device_t dev, struct pfs_node *dir, struct pfs_node *scsi, char *path,
  144    char *prefix)
  145 {
  146         struct scsi_host_queue *scsi_host;
  147         struct pfs_node *sub_dir;
  148         int i, nchildren;
  149         device_t *children, parent;
  150         devclass_t devclass;
  151         const char *name = NULL;
  152         struct pci_devinfo *dinfo;
  153         char *device, *host, *new_path = path;
  154 
  155         parent = device_get_parent(dev);
  156         if (parent) {
  157                 devclass = device_get_devclass(parent);
  158                 if (devclass != NULL)
  159                         name = devclass_get_name(devclass);
  160                 if (name && strcmp(name, PCI_DEV) == 0) {
  161                         dinfo = device_get_ivars(dev);
  162                         if (dinfo) {
  163                                 device = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  164                                 new_path = malloc(MAXPATHLEN, M_TEMP,
  165                                     M_WAITOK);
  166                                 new_path[0] = '\000';
  167                                 strcpy(new_path, path);
  168                                 host = malloc(MAXPATHLEN, M_TEMP, M_WAITOK);
  169                                 device[0] = '\000';
  170                                 sprintf(device, "%s:%02x:%02x.%x",
  171                                     prefix,
  172                                     dinfo->cfg.bus,
  173                                     dinfo->cfg.slot,
  174                                     dinfo->cfg.func);
  175                                 strcat(new_path, "/");
  176                                 strcat(new_path, device);
  177                                 dir = pfs_create_dir(dir, device,
  178                                     NULL, NULL, NULL, 0);
  179 
  180                                 if (dinfo->cfg.baseclass == PCIC_STORAGE) {
  181                                         /* DJA only make this if needed */
  182                                         sprintf(host, "host%d", host_number++);
  183                                         strcat(new_path, "/");
  184                                         strcat(new_path, host);
  185                                         sub_dir = pfs_create_dir(dir,
  186                                             host, NULL, NULL, NULL, 0);
  187                                         scsi_host = malloc(sizeof(
  188                                             struct scsi_host_queue),
  189                                             M_DEVBUF, M_NOWAIT);
  190                                         scsi_host->path = malloc(
  191                                             strlen(new_path) + 1,
  192                                             M_DEVBUF, M_NOWAIT);
  193                                         scsi_host->path[0] = '\000';
  194                                         bcopy(new_path, scsi_host->path,
  195                                             strlen(new_path) + 1);
  196                                         scsi_host->name = "unknown";
  197 
  198                                         sub_dir = pfs_create_dir(scsi, host,
  199                                             NULL, NULL, NULL, 0);
  200                                         pfs_create_link(sub_dir, "device",
  201                                             &linsysfs_link_scsi_host,
  202                                             NULL, NULL, NULL, 0);
  203                                         pfs_create_file(sub_dir, "proc_name",
  204                                             &linsysfs_scsiname,
  205                                             NULL, NULL, NULL, PFS_RD);
  206                                         scsi_host->name
  207                                             = linux_driver_get_name_dev(dev);
  208                                         TAILQ_INSERT_TAIL(&scsi_host_q,
  209                                             scsi_host, scsi_host_next);
  210                                 }
  211                                 free(device, M_TEMP);
  212                                 free(host, M_TEMP);
  213                         }
  214                 }
  215         }
  216 
  217         device_get_children(dev, &children, &nchildren);
  218         for (i = 0; i < nchildren; i++) {
  219                 if (children[i])
  220                         linsysfs_run_bus(children[i], dir, scsi, new_path, prefix);
  221         }
  222         if (new_path != path)
  223                 free(new_path, M_TEMP);
  224 
  225         return (1);
  226 }
  227 
  228 /*
  229  * Constructor
  230  */
  231 static int
  232 linsysfs_init(PFS_INIT_ARGS)
  233 {
  234         struct pfs_node *root;
  235         struct pfs_node *dir;
  236         struct pfs_node *pci;
  237         struct pfs_node *scsi;
  238         devclass_t devclass;
  239         device_t dev;
  240 
  241         TAILQ_INIT(&scsi_host_q);
  242 
  243         root = pi->pi_root;
  244 
  245         /* /sys/class/... */
  246         scsi = pfs_create_dir(root, "class", NULL, NULL, NULL, 0);
  247         scsi = pfs_create_dir(scsi, "scsi_host", NULL, NULL, NULL, 0);
  248 
  249         /* /sys/device */
  250         dir = pfs_create_dir(root, "devices", NULL, NULL, NULL, 0);
  251 
  252         /* /sys/device/pci0000:00 */
  253         pci = pfs_create_dir(dir, "pci0000:00", NULL, NULL, NULL, 0);
  254 
  255         devclass = devclass_find("root");
  256         if (devclass == NULL) {
  257                 return (0);
  258         }
  259 
  260         dev = devclass_get_device(devclass, 0);
  261         linsysfs_run_bus(dev, pci, scsi, "/pci0000:00", "0000");
  262         return (0);
  263 }
  264 
  265 /*
  266  * Destructor
  267  */
  268 static int
  269 linsysfs_uninit(PFS_INIT_ARGS)
  270 {
  271         struct scsi_host_queue *scsi_host, *scsi_host_tmp;
  272 
  273         TAILQ_FOREACH_SAFE(scsi_host, &scsi_host_q, scsi_host_next,
  274             scsi_host_tmp) {
  275                 TAILQ_REMOVE(&scsi_host_q, scsi_host, scsi_host_next);
  276                 free(scsi_host->path, M_TEMP);
  277                 free(scsi_host, M_TEMP);
  278         }
  279 
  280         return (0);
  281 }
  282 
  283 PSEUDOFS(linsysfs, 1);
  284 MODULE_DEPEND(linsysfs, linux, 1, 1, 1);

Cache object: 0f9e8c2f1cd53880563fc6d1feed777c


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