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/scsi/su.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 /* su: SCSI Universal. This is a universal SCSI device that
    2  * has a fixed minor number format.  This allows you to refer
    3  * to your devices by BUS, ID, LUN instead of st0, st1, ...
    4  *
    5  * This code looks up the underlying device for a given SCSI
    6  * target and uses that driver.
    7  *
    8  *Begin copyright
    9  *
   10  * Copyright (C) 1993, 1994, 1995, HD Associates, Inc.
   11  * PO Box 276
   12  * Pepperell, MA 01463
   13  * 508 433 5266
   14  * dufault@hda.com
   15  *
   16  * This code is contributed to the University of California at Berkeley:
   17  *
   18  * Redistribution and use in source and binary forms, with or without
   19  * modification, are permitted provided that the following conditions
   20  * are met:
   21  * 1. Redistributions of source code must retain the above copyright
   22  *    notice, this list of conditions and the following disclaimer.
   23  * 2. Redistributions in binary form must reproduce the above copyright
   24  *    notice, this list of conditions and the following disclaimer in the
   25  *    documentation and/or other materials provided with the distribution.
   26  * 3. All advertising materials mentioning features or use of this software
   27  *    must display the following acknowledgement:
   28  *      This product includes software developed by the University of
   29  *      California, Berkeley and its contributors.
   30  * 4. Neither the name of the University nor the names of its contributors
   31  *    may be used to endorse or promote products derived from this software
   32  *    without specific prior written permission.
   33  *
   34  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   35  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   36  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   37  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   38  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   39  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   40  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   41  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   42  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   43  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   44  * SUCH DAMAGE.
   45  *End copyright
   46  *
   47  * $FreeBSD: src/sys/scsi/su.c,v 1.14.4.1 1999/09/05 08:21:52 peter Exp $
   48  *
   49  * Tabstops 4
   50  * XXX devfs entries for this device should be handled by generic scsiconfig
   51  * Add a bdevsw interface.. ?
   52  */
   53 
   54 #include <sys/param.h>
   55 #include <sys/conf.h>
   56 #include <sys/errno.h>
   57 #include <sys/stat.h>
   58 #include <sys/param.h>
   59 #include <sys/buf.h>
   60 #include <sys/systm.h>
   61 #include <sys/kernel.h>
   62 #ifdef DEVFS
   63 #include <sys/devfsext.h>
   64 #endif /*DEVFS*/
   65 #include <scsi/scsiconf.h>
   66 #define CDEV_MAJOR 18
   67 
   68 /* These three used by ssc. */
   69 extern  d_open_t        suopen;
   70 extern  d_close_t       suclose;
   71 extern  d_ioctl_t       suioctl;
   72 
   73 static  d_read_t        suread;
   74 static  d_write_t       suwrite;
   75 static  d_select_t      suselect;
   76 static  d_strategy_t    sustrategy;
   77 
   78 static struct cdevsw su_cdevsw = 
   79         { suopen,       suclose,        suread,         suwrite,        /*18*/
   80           suioctl,      nostop,         nullreset,      nodevtotty,/* scsi */
   81           suselect,     nommap,         sustrategy, "su",       NULL,   -1 };
   82 
   83 
   84 /* Build an old style device number (unit encoded in the minor number)
   85  * from a base old one (no flag bits) and a full new one
   86  * (BUS, LUN, TARG in the minor number, and flag bits).
   87  *
   88  * OLDDEV has the major number and device unit only.  It was constructed
   89  * at attach time and is stored in the scsi_link structure.
   90  *
   91  * NEWDEV can have whatever in it, but only the old control flags and the
   92  * super bit are present.  IT CAN'T HAVE ANY UNIT INFORMATION or you'll
   93  * wind up with the wrong unit.
   94  */
   95 #define OLD_DEV(NEWDEV, OLDDEV) ((OLDDEV) | ((NEWDEV) & 0x080000FF))
   96 
   97 /* bnxio, cnxio: non existent device entries
   98  */
   99 static struct bdevsw bnxio = {
  100         nxopen,
  101         nxclose,
  102         nxstrategy,
  103         nxioctl,
  104         nxdump,
  105         nxpsize,
  106         0,
  107         "NON",
  108         NULL,
  109         -1
  110 };
  111 
  112 static struct cdevsw cnxio = {
  113         nxopen,
  114         nxclose,
  115         nxread,
  116         nxwrite,
  117         nxioctl,
  118         nxstop,
  119         nxreset,
  120         nxdevtotty,
  121         nxselect,
  122         nxmmap,
  123         nxstrategy,
  124         "NON",
  125         NULL,
  126         -1
  127 };
  128 
  129 /* getsws: Look up the base dev switch for a given "by minor number" style
  130  * device.
  131  */
  132 static int
  133 getsws(dev_t dev, int type,
  134         struct bdevsw **bdevp, struct cdevsw **cdevp, dev_t *base)
  135 {
  136         int ret = 0;
  137         struct scsi_link *scsi_link;
  138         int chr_dev, blk_dev;
  139 
  140         struct cdevsw *cdev;
  141         struct bdevsw *bdev;
  142 
  143         int bus = SCSI_BUS(dev),
  144             lun = SCSI_LUN(dev),
  145             id =  SCSI_ID(dev);
  146 
  147         /* Try to look up the base device by finding the major number in
  148          * the scsi_link structure:
  149          */
  150         if ((scsi_link = scsi_link_get(bus, id, lun)) == 0 ||
  151         scsi_link->dev == NODEV)
  152         {
  153                 ret = ENXIO;
  154 
  155                 /* XXX This assumes that you always have a character device if you
  156                  *     have a block device.  That seems reasonable.
  157                  */
  158                 cdev = &cnxio;
  159                 chr_dev = NODEV;
  160                 bdev = &bnxio;
  161                 blk_dev = NODEV;
  162         }
  163         else
  164         {
  165                 int bmaj, cmaj;
  166 
  167                 cmaj = major(scsi_link->dev);
  168                 cdev = cdevsw[cmaj];
  169                 chr_dev = OLD_DEV(dev, scsi_link->dev);
  170 
  171                 bmaj = chrtoblk(cmaj);
  172                 bdev = (bmaj == NODEV) ? &bnxio : bdevsw[bmaj];
  173                 blk_dev = OLD_DEV(dev, makedev(bmaj, minor(scsi_link->dev)));
  174         }
  175 
  176         if (cdevp)
  177                 *cdevp = cdev;
  178         if (bdevp)
  179                 *bdevp = bdev;
  180 
  181         if (type == S_IFCHR)
  182                 *base = chr_dev;
  183         else
  184                 *base = blk_dev;
  185 
  186         return ret;
  187 }
  188 
  189 int
  190 suopen(dev_t dev, int flag, int type, struct proc *p)
  191 {
  192         struct cdevsw *cdev;
  193         struct bdevsw *bdev;
  194         dev_t base;
  195 
  196         if (getsws(dev, type, &bdev, &cdev, &base))
  197         {
  198                 /* Device not configured?  Reprobe then try again.
  199                  */
  200                 int bus = SCSI_BUS(dev), lun = SCSI_LUN(dev), id =  SCSI_ID(dev);
  201 
  202                 if (scsi_probe_bus(bus, id, lun) || getsws(dev, type, &bdev, &cdev,
  203                 &base))
  204                         return ENXIO;
  205         }
  206 
  207         /* There is a properly configured underlying device.
  208          * Synthesize an appropriate device number:
  209          */
  210         if (type == S_IFCHR)
  211                 return (*cdev->d_open)(base, flag, S_IFCHR, p);
  212         else
  213                 return (*bdev->d_open)(base, flag, S_IFBLK, p);
  214 }
  215 
  216 int
  217 suclose(dev_t dev, int fflag, int type, struct proc *p)
  218 {
  219         struct cdevsw *cdev;
  220         struct bdevsw *bdev;
  221         dev_t base;
  222 
  223         (void)getsws(dev, type, &bdev, &cdev, &base);
  224 
  225         if (type == S_IFCHR)
  226                 return (*cdev->d_close)(base, fflag, S_IFCHR, p);
  227         else
  228                 return (*bdev->d_open)(base, fflag, S_IFBLK, p);
  229 }
  230 
  231 static  void
  232 sustrategy(struct buf *bp)
  233 {
  234         dev_t base;
  235         struct bdevsw *bdev;
  236         dev_t dev = bp->b_dev;
  237 
  238         /* XXX: I have no way of knowing if this was through the
  239          * block or the character entry point.
  240          */
  241         (void)getsws(dev, S_IFBLK, &bdev, 0, &base);
  242 
  243         bp->b_dev = base;
  244 
  245         (*bdev->d_strategy)(bp);
  246 
  247         bp->b_dev = dev;
  248 }
  249 
  250 int
  251 suioctl(dev_t dev, int cmd, caddr_t data, int fflag, struct proc *p)
  252 {
  253         struct cdevsw *cdev;
  254         dev_t base;
  255 
  256         /* XXX: I have no way of knowing if this was through the
  257          * block or the character entry point.
  258          */
  259         (void)getsws(dev, S_IFCHR, 0, &cdev, &base);
  260 
  261         return (*cdev->d_ioctl)(base, cmd, data, fflag, p);
  262 }
  263 
  264 static  int
  265 suread(dev_t dev, struct uio *uio, int ioflag)
  266 {
  267         dev_t base;
  268         struct cdevsw *cdev;
  269 
  270         (void)getsws(dev, S_IFCHR, 0, &cdev, &base);
  271 
  272         return (*cdev->d_read)(base, uio, ioflag);
  273 }
  274 
  275 static  int
  276 suwrite(dev_t dev, struct uio *uio, int ioflag)
  277 {
  278         dev_t base;
  279         struct cdevsw *cdev;
  280 
  281         (void)getsws(dev, S_IFCHR, 0, &cdev, &base);
  282 
  283         return (*cdev->d_write)(base, uio, ioflag);
  284 }
  285 
  286 static  int
  287 suselect(dev_t dev, int which, struct proc *p)
  288 {
  289         dev_t base;
  290         struct cdevsw *cdev;
  291 
  292         (void)getsws(dev, S_IFCHR, 0, &cdev, &base);
  293 
  294         return (*cdev->d_select)(base, which, p);
  295 }
  296 
  297 static su_devsw_installed = 0;
  298 
  299 static void
  300 su_drvinit(void *unused)
  301 {
  302         dev_t dev;
  303 
  304         if( ! su_devsw_installed ) {
  305                 dev = makedev(CDEV_MAJOR, 0);
  306                 cdevsw_add(&dev,&su_cdevsw, NULL);
  307                 su_devsw_installed = 1;
  308         }
  309 }
  310 
  311 SYSINIT(sudev,SI_SUB_DRIVERS,SI_ORDER_MIDDLE+CDEV_MAJOR,su_drvinit,NULL)
  312 
  313 

Cache object: 5636ae402a04b249071692e4a417985b


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