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/riscv/htif/htif_block.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) 2015-2016 Ruslan Bukin <br@bsdpad.com>
    3  * All rights reserved.
    4  *
    5  * Portions of this software were developed by SRI International and the
    6  * University of Cambridge Computer Laboratory under DARPA/AFRL contract
    7  * FA8750-10-C-0237 ("CTSRD"), as part of the DARPA CRASH research programme.
    8  *
    9  * Portions of this software were developed by the University of Cambridge
   10  * Computer Laboratory as part of the CTSRD Project, with support from the
   11  * UK Higher Education Innovation Fund (HEIF).
   12  *
   13  * Redistribution and use in source and binary forms, with or without
   14  * modification, are permitted provided that the following conditions
   15  * are met:
   16  * 1. Redistributions of source code must retain the above copyright
   17  *    notice, this list of conditions and the following disclaimer.
   18  * 2. Redistributions in binary form must reproduce the above copyright
   19  *    notice, this list of conditions and the following disclaimer in the
   20  *    documentation and/or other materials provided with the distribution.
   21  *
   22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   32  * SUCH DAMAGE.
   33  */
   34 
   35 #include <sys/cdefs.h>
   36 __FBSDID("$FreeBSD: releng/11.2/sys/riscv/htif/htif_block.c 298476 2016-04-22 15:12:05Z br $");
   37 
   38 #include <sys/param.h>
   39 #include <sys/systm.h>
   40 #include <sys/kernel.h>
   41 #include <sys/kthread.h>
   42 #include <sys/selinfo.h>
   43 #include <sys/module.h>
   44 #include <sys/lock.h>
   45 #include <sys/mutex.h>
   46 #include <sys/malloc.h>
   47 #include <sys/sysctl.h>
   48 #include <sys/uio.h>
   49 
   50 #include <sys/bio.h>
   51 #include <sys/bus.h>
   52 #include <sys/conf.h>
   53 #include <sys/disk.h>
   54 #include <geom/geom_disk.h>
   55 
   56 #include <vm/vm.h>
   57 #include <vm/pmap.h>
   58 
   59 #include <machine/md_var.h>
   60 #include <machine/bus.h>
   61 #include <machine/trap.h>
   62 #include <sys/rman.h>
   63 
   64 #include "htif.h"
   65 
   66 #define SECTOR_SIZE_SHIFT       (9)
   67 #define SECTOR_SIZE             (1 << SECTOR_SIZE_SHIFT)
   68 
   69 #define HTIF_BLK_LOCK(_sc)      mtx_lock(&(_sc)->sc_mtx)
   70 #define HTIF_BLK_UNLOCK(_sc)    mtx_unlock(&(_sc)->sc_mtx)
   71 #define HTIF_BLK_LOCK_INIT(_sc) \
   72         mtx_init(&_sc->sc_mtx, device_get_nameunit(_sc->dev), \
   73             "htif_blk", MTX_DEF)
   74 #define HTIF_BLK_LOCK_DESTROY(_sc)      mtx_destroy(&_sc->sc_mtx);
   75 #define HTIF_BLK_ASSERT_LOCKED(_sc)     mtx_assert(&_sc->sc_mtx, MA_OWNED);
   76 #define HTIF_BLK_ASSERT_UNLOCKED(_sc)   mtx_assert(&_sc->sc_mtx, MA_NOTOWNED);
   77 
   78 static void htif_blk_task(void *arg);
   79 
   80 static disk_open_t      htif_blk_open;
   81 static disk_close_t     htif_blk_close;
   82 static disk_strategy_t  htif_blk_strategy;
   83 
   84 struct htif_blk_softc {
   85         device_t        dev;
   86         struct disk     *disk;
   87         struct mtx      htif_io_mtx;
   88         struct mtx      sc_mtx;
   89         struct proc     *p;
   90         struct bio_queue_head bio_queue;
   91         int             running;
   92         int             intr_chan;
   93         int             cmd_done;
   94         int             index;
   95         uint16_t        curtag;
   96 };
   97 
   98 struct htif_blk_request {
   99         uint64_t addr;
  100         uint64_t offset;        /* offset in bytes */
  101         uint64_t size;          /* length in bytes */
  102         uint64_t tag;
  103 };
  104 
  105 static void
  106 htif_blk_intr(void *arg, uint64_t entry)
  107 {
  108         struct htif_blk_softc *sc;
  109         uint64_t devcmd;
  110         uint64_t data;
  111 
  112         sc = arg;
  113 
  114         devcmd = HTIF_DEV_CMD(entry);
  115         data = HTIF_DEV_DATA(entry);
  116 
  117         if (sc->curtag == data) {
  118                 wmb();
  119                 sc->cmd_done = 1;
  120                 wakeup(&sc->intr_chan);
  121         } else {
  122                 device_printf(sc->dev, "Unexpected tag %d (should be %d)\n",
  123                     data, sc->curtag);
  124         }
  125 }
  126 
  127 static int
  128 htif_blk_probe(device_t dev)
  129 {
  130 
  131         return (0);
  132 }
  133 
  134 static int
  135 htif_blk_attach(device_t dev)
  136 {
  137         struct htif_blk_softc *sc;
  138         char prefix[] = " size=";
  139         char *str;
  140         long size;
  141 
  142         sc = device_get_softc(dev);
  143         sc->dev = dev;
  144 
  145         mtx_init(&sc->htif_io_mtx, device_get_nameunit(dev), "htif_blk", MTX_DEF);
  146         HTIF_BLK_LOCK_INIT(sc);
  147 
  148         str = strstr(htif_get_id(dev), prefix);
  149 
  150         size = strtol((str + 6), NULL, 10);
  151         if (size == 0) {
  152                 return (ENXIO);
  153         }
  154 
  155         sc->index = htif_get_index(dev);
  156         if (sc->index < 0)
  157                 return (EINVAL);
  158         htif_setup_intr(sc->index, htif_blk_intr, sc);
  159 
  160         sc->disk = disk_alloc();
  161         sc->disk->d_drv1 = sc;
  162 
  163         sc->disk->d_maxsize = 4096; /* Max transfer */
  164         sc->disk->d_name = "htif_blk";
  165         sc->disk->d_open = htif_blk_open;
  166         sc->disk->d_close = htif_blk_close;
  167         sc->disk->d_strategy = htif_blk_strategy;
  168         sc->disk->d_unit = 0;
  169         sc->disk->d_sectorsize = SECTOR_SIZE;
  170         sc->disk->d_mediasize = size;
  171         disk_create(sc->disk, DISK_VERSION);
  172 
  173         bioq_init(&sc->bio_queue);
  174 
  175         sc->running = 1;
  176 
  177         kproc_create(&htif_blk_task, sc, &sc->p, 0, 0, "%s: transfer", 
  178             device_get_nameunit(dev));
  179 
  180         return (0);
  181 }
  182 
  183 static int
  184 htif_blk_open(struct disk *dp)
  185 {
  186 
  187         return (0);
  188 }
  189 
  190 static int
  191 htif_blk_close(struct disk *dp)
  192 {
  193 
  194         return (0);
  195 }
  196 
  197 static void
  198 htif_blk_task(void *arg)
  199 {
  200         struct htif_blk_request req __aligned(HTIF_ALIGN);
  201         struct htif_blk_softc *sc;
  202         uint64_t req_paddr;
  203         struct bio *bp;
  204         uint64_t paddr;
  205         uint64_t cmd;
  206         int i;
  207 
  208         sc = (struct htif_blk_softc *)arg;
  209 
  210         while (1) {
  211                 HTIF_BLK_LOCK(sc);
  212                 do {
  213                         bp = bioq_takefirst(&sc->bio_queue);
  214                         if (bp == NULL)
  215                                 msleep(sc, &sc->sc_mtx, PRIBIO, "jobqueue", 0);
  216                 } while (bp == NULL);
  217                 HTIF_BLK_UNLOCK(sc);
  218 
  219                 if (bp->bio_cmd == BIO_READ || bp->bio_cmd == BIO_WRITE) {
  220                         HTIF_BLK_LOCK(sc);
  221 
  222                         rmb();
  223                         req.offset = (bp->bio_pblkno * sc->disk->d_sectorsize);
  224                         req.size = bp->bio_bcount;
  225                         paddr = vtophys(bp->bio_data);
  226                         KASSERT(paddr != 0, ("paddr is 0"));
  227                         req.addr = paddr;
  228                         sc->curtag++;
  229                         req.tag = sc->curtag;
  230 
  231                         cmd = sc->index;
  232                         cmd <<= HTIF_DEV_ID_SHIFT;
  233                         if (bp->bio_cmd == BIO_READ)
  234                                 cmd |= (HTIF_CMD_READ << HTIF_CMD_SHIFT);
  235                         else
  236                                 cmd |= (HTIF_CMD_WRITE << HTIF_CMD_SHIFT);
  237                         req_paddr = vtophys(&req);
  238                         KASSERT(req_paddr != 0, ("req_paddr is 0"));
  239                         cmd |= req_paddr;
  240 
  241                         sc->cmd_done = 0;
  242                         htif_command(cmd);
  243 
  244                         /* Wait for interrupt */
  245                         i = 0;
  246                         while (sc->cmd_done == 0) {
  247                                 msleep(&sc->intr_chan, &sc->sc_mtx, PRIBIO, "intr", hz/2);
  248 
  249                                 if (i++ > 2) {
  250                                         /* TODO: try to re-issue operation on timeout ? */
  251                                         bp->bio_error = EIO;
  252                                         bp->bio_flags |= BIO_ERROR;
  253                                         disk_err(bp, "hard error", -1, 1);
  254                                         break;
  255                                 }
  256                         }
  257                         HTIF_BLK_UNLOCK(sc);
  258 
  259                         biodone(bp);
  260                 } else {
  261                         printf("unknown op %d\n", bp->bio_cmd);
  262                 }
  263         }
  264 }
  265 
  266 static void
  267 htif_blk_strategy(struct bio *bp)
  268 {
  269         struct htif_blk_softc *sc;
  270 
  271         sc = bp->bio_disk->d_drv1;
  272 
  273         HTIF_BLK_LOCK(sc);
  274         if (sc->running > 0) {
  275                 bioq_disksort(&sc->bio_queue, bp);
  276                 HTIF_BLK_UNLOCK(sc);
  277                 wakeup(sc);
  278         } else {
  279                 HTIF_BLK_UNLOCK(sc);
  280                 biofinish(bp, NULL, ENXIO);
  281         }
  282 }
  283 
  284 static device_method_t htif_blk_methods[] = {
  285         DEVMETHOD(device_probe,         htif_blk_probe),
  286         DEVMETHOD(device_attach,        htif_blk_attach),
  287 };
  288 
  289 static driver_t htif_blk_driver = {
  290         "htif_blk",
  291         htif_blk_methods,
  292         sizeof(struct htif_blk_softc)
  293 };
  294 
  295 static devclass_t       htif_blk_devclass;
  296 
  297 DRIVER_MODULE(htif_blk, htif, htif_blk_driver, htif_blk_devclass, 0, 0);

Cache object: a3cc05ef809b0857cf57811e306a871f


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