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/dev/raid/ida/ida_disk.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) 1999,2000 Jonathan Lemon
    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  * $FreeBSD: src/sys/dev/ida/ida_disk.c,v 1.12.2.6 2001/11/27 20:21:02 ps Exp $
   27  */
   28 
   29 /*
   30  * Disk driver for Compaq SMART RAID adapters.
   31  */
   32 
   33 #include <sys/param.h>
   34 #include <sys/systm.h>
   35 #include <sys/malloc.h>
   36 #include <sys/kernel.h>
   37 
   38 #include <sys/buf.h>
   39 #include <sys/bus.h>
   40 #include <sys/conf.h>
   41 #include <sys/cons.h>
   42 #include <sys/devicestat.h>
   43 #include <sys/disk.h>
   44 #include <sys/dtype.h>
   45 #include <sys/rman.h>
   46 #include <sys/thread2.h>
   47 
   48 #include <machine/clock.h>
   49 #include <machine/md_var.h>
   50 
   51 #include <vm/vm.h>
   52 #include <vm/pmap.h>
   53 
   54 #include "idareg.h"
   55 #include "idavar.h"
   56 
   57 /* prototypes */
   58 static int idad_probe(device_t dev);
   59 static int idad_attach(device_t dev);
   60 static int idad_detach(device_t dev);
   61 
   62 static  d_open_t        idad_open;
   63 static  d_close_t       idad_close;
   64 static  d_strategy_t    idad_strategy;
   65 static  d_dump_t        idad_dump;
   66 
   67 static struct dev_ops id_ops = {
   68         { "idad", 0, D_DISK },
   69         .d_open =       idad_open,
   70         .d_close =      idad_close,
   71         .d_read =       physread,
   72         .d_write =      physwrite,
   73         .d_strategy =   idad_strategy,
   74         .d_dump =       idad_dump,
   75 };
   76 
   77 static devclass_t       idad_devclass;
   78 
   79 static device_method_t idad_methods[] = {
   80         DEVMETHOD(device_probe,         idad_probe),
   81         DEVMETHOD(device_attach,        idad_attach),
   82         DEVMETHOD(device_detach,        idad_detach),
   83         DEVMETHOD_END
   84 };
   85 
   86 static driver_t idad_driver = {
   87         "idad",
   88         idad_methods,
   89         sizeof(struct idad_softc)
   90 };
   91 
   92 DRIVER_MODULE(idad, ida, idad_driver, idad_devclass, NULL, NULL);
   93 
   94 static __inline struct idad_softc *
   95 idad_getsoftc(cdev_t dev)
   96 {
   97 
   98         return ((struct idad_softc *)dev->si_drv1);
   99 }
  100 
  101 static int
  102 idad_open(struct dev_open_args *ap)
  103 {
  104         cdev_t dev = ap->a_head.a_dev;
  105         struct idad_softc *drv;
  106 
  107         drv = idad_getsoftc(dev);
  108         if (drv == NULL)
  109                 return (ENXIO);
  110 #if 0
  111         bzero(&info, sizeof(info));
  112         info.d_media_blksize = drv->secsize;            /* mandatory */
  113         info.d_media_blocks = drv->secperunit;
  114 
  115         info.d_secpertrack = drv->sectors;              /* optional */
  116         info.d_type = DTYPE_SCSI;
  117         info.d_nheads = drv->heads;
  118         info.d_ncylinders = drv->cylinders;
  119         info.d_secpercyl = drv->sectors * drv->heads;
  120 
  121         disk_setdiskinfo(&drv->disk, &info);
  122 #endif
  123         return (0);
  124 }
  125 
  126 static int
  127 idad_close(struct dev_close_args *ap)
  128 {
  129         cdev_t dev = ap->a_head.a_dev;
  130         struct idad_softc *drv;
  131 
  132         drv = idad_getsoftc(dev);
  133         if (drv == NULL)
  134                 return (ENXIO);
  135         return (0);
  136 }
  137 
  138 /*
  139  * Read/write routine for a buffer.  Finds the proper unit, range checks
  140  * arguments, and schedules the transfer.  Does not wait for the transfer
  141  * to complete.  Multi-page transfers are supported.  All I/O requests must
  142  * be a multiple of a sector in length.
  143  */
  144 static int
  145 idad_strategy(struct dev_strategy_args *ap)
  146 {
  147         cdev_t dev = ap->a_head.a_dev;
  148         struct bio *bio = ap->a_bio;
  149         struct buf *bp = bio->bio_buf;
  150         struct idad_softc *drv;
  151 
  152         drv = idad_getsoftc(dev);
  153         if (drv == NULL) {
  154                 bp->b_error = EINVAL;
  155                 goto bad;
  156         }
  157 
  158         /*
  159          * software write protect check
  160          */
  161         if ((drv->flags & DRV_WRITEPROT) && bp->b_cmd != BUF_CMD_READ) {
  162                 bp->b_error = EROFS;
  163                 goto bad;
  164         }
  165 
  166         /*
  167          * If it's a null transfer, return immediately
  168          */
  169         if (bp->b_bcount == 0)
  170                 goto done;
  171 
  172         bio->bio_driver_info = drv;
  173         crit_enter();
  174         devstat_start_transaction(&drv->stats);
  175         ida_submit_buf(drv->controller, bio);
  176         crit_exit();
  177         return(0);
  178 
  179 bad:
  180         bp->b_flags |= B_ERROR;
  181 
  182 done:
  183         /*
  184          * Correctly set the buf to indicate a completed transfer
  185          */
  186         bp->b_resid = bp->b_bcount;
  187         biodone(bio);
  188         return(0);
  189 }
  190 
  191 static int
  192 idad_dump(struct dev_dump_args *ap)
  193 {
  194         cdev_t dev = ap->a_head.a_dev;
  195         struct idad_softc *drv;
  196         int error = 0;
  197 
  198         drv = idad_getsoftc(dev);
  199         if (drv == NULL)
  200                 return (ENXIO);
  201 
  202         drv->controller->flags &= ~IDA_INTERRUPTS;
  203 
  204         if (ap->a_length > 0) {
  205                 error = ida_command(drv->controller, CMD_WRITE, ap->a_virtual,
  206                     ap->a_length, drv->drive, ap->a_offset / DEV_BSIZE, DMA_DATA_OUT);
  207         }
  208         drv->controller->flags |= IDA_INTERRUPTS;
  209         return (error);
  210 
  211 }
  212 
  213 void
  214 idad_intr(struct bio *bio)
  215 {
  216         struct idad_softc *drv = (struct idad_softc *)bio->bio_driver_info;
  217         struct buf *bp = bio->bio_buf;
  218 
  219         if (bp->b_flags & B_ERROR)
  220                 bp->b_error = EIO;
  221         else
  222                 bp->b_resid = 0;
  223 
  224         devstat_end_transaction_buf(&drv->stats, bp);
  225         biodone(bio);
  226 }
  227 
  228 static int
  229 idad_probe(device_t dev)
  230 {
  231 
  232         device_set_desc(dev, "Compaq Logical Drive");
  233         return (0);
  234 }
  235 
  236 static int
  237 idad_attach(device_t dev)
  238 {
  239         struct ida_drive_info dinfo;
  240         struct disk_info info;
  241         struct idad_softc *drv;
  242         device_t parent;
  243         cdev_t dsk;
  244         int error;
  245 
  246         drv = (struct idad_softc *)device_get_softc(dev);
  247         parent = device_get_parent(dev);
  248         drv->controller = (struct ida_softc *)device_get_softc(parent);
  249         drv->unit = device_get_unit(dev);
  250         drv->drive = drv->controller->num_drives;
  251         drv->controller->num_drives++;
  252 
  253         error = ida_command(drv->controller, CMD_GET_LOG_DRV_INFO,
  254             &dinfo, sizeof(dinfo), drv->drive, 0, DMA_DATA_IN);
  255         if (error) {
  256                 device_printf(dev, "CMD_GET_LOG_DRV_INFO failed\n");
  257                 return (ENXIO);
  258         }
  259 
  260         drv->cylinders = dinfo.ncylinders;
  261         drv->heads = dinfo.nheads;
  262         drv->sectors = dinfo.nsectors;
  263         drv->secsize = dinfo.secsize == 0 ? 512 : dinfo.secsize;
  264         drv->secperunit = dinfo.secperunit;
  265 
  266         /* XXX
  267          * other initialization
  268          */
  269         device_printf(dev, "%uMB (%u sectors), blocksize=%d\n",
  270             drv->secperunit / ((1024 * 1024) / drv->secsize),
  271             drv->secperunit, drv->secsize);
  272 
  273         devstat_add_entry(&drv->stats, "idad", drv->unit, drv->secsize,
  274             DEVSTAT_NO_ORDERED_TAGS,
  275             DEVSTAT_TYPE_STORARRAY| DEVSTAT_TYPE_IF_OTHER,
  276             DEVSTAT_PRIORITY_ARRAY);
  277 
  278         dsk = disk_create(drv->unit, &drv->disk, &id_ops);
  279 
  280         dsk->si_drv1 = drv;
  281         dsk->si_iosize_max = min(MAXPHYS,64*1024);              /* XXX guess? */
  282 
  283         /*
  284          * Set disk info, as it appears that all needed data is available already.
  285          * Setting the disk info will also cause the probing to start.
  286          */
  287         bzero(&info, sizeof(info));
  288         info.d_media_blksize = drv->secsize;            /* mandatory */
  289         info.d_media_blocks = drv->secperunit;
  290 
  291         info.d_secpertrack = drv->sectors;              /* optional */
  292         info.d_type = DTYPE_SCSI;
  293         info.d_nheads = drv->heads;
  294         info.d_ncylinders = drv->cylinders;
  295         info.d_secpercyl = drv->sectors * drv->heads;
  296 
  297         disk_setdiskinfo(&drv->disk, &info);
  298 
  299         return (0);
  300 }
  301 
  302 static int
  303 idad_detach(device_t dev)
  304 {
  305         struct idad_softc *drv;
  306 
  307         drv = (struct idad_softc *)device_get_softc(dev);
  308         devstat_remove_entry(&drv->stats);
  309         disk_destroy(&drv->disk);
  310         return (0);
  311 }

Cache object: 036362d7745440b24917fc797edce068


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