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/powerpc/powernv/opal_nvram.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  * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
    3  *
    4  * Copyright (c) 2019 Justin Hibbits
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   16  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   17  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   18  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   19  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   20  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   21  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   23  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   24  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   25  * POSSIBILITY OF SUCH DAMAGE.
   26  *
   27  * $FreeBSD$
   28  */
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/module.h>
   33 #include <sys/bus.h>
   34 #include <sys/conf.h>
   35 #include <sys/disk.h>
   36 #include <sys/kernel.h>
   37 #include <sys/mutex.h>
   38 #include <sys/uio.h>
   39 
   40 #include <dev/ofw/openfirm.h>
   41 #include <dev/ofw/ofw_bus.h>
   42 #include <dev/ofw/ofw_bus_subr.h>
   43 
   44 #include <machine/bus.h>
   45 #include <machine/md_var.h>
   46 #include <machine/pio.h>
   47 #include <machine/resource.h>
   48 
   49 #include "opal.h"
   50 
   51 #include <sys/rman.h>
   52 
   53 #include <vm/vm.h>
   54 #include <vm/pmap.h>
   55 
   56 #define NVRAM_BUFSIZE   (65536) /* 64k blocks */
   57 
   58 struct opal_nvram_softc {
   59         device_t         sc_dev;
   60         struct mtx       sc_mtx;
   61         uint32_t         sc_size;
   62         uint8_t         *sc_buf;
   63         vm_paddr_t       sc_buf_phys;
   64 
   65         struct cdev     *sc_cdev;
   66         int              sc_isopen;
   67 };
   68 
   69 #define NVRAM_LOCK(sc)          mtx_lock(&sc->sc_mtx)
   70 #define NVRAM_UNLOCK(sc)        mtx_unlock(&sc->sc_mtx)
   71 
   72 /*
   73  * Device interface.
   74  */
   75 static int              opal_nvram_probe(device_t);
   76 static int              opal_nvram_attach(device_t);
   77 static int              opal_nvram_detach(device_t);
   78 
   79 /*
   80  * Driver methods.
   81  */
   82 static device_method_t  opal_nvram_methods[] = {
   83         /* Device interface */
   84         DEVMETHOD(device_probe,         opal_nvram_probe),
   85         DEVMETHOD(device_attach,        opal_nvram_attach),
   86         DEVMETHOD(device_detach,        opal_nvram_detach),
   87         { 0, 0 }
   88 };
   89 
   90 static driver_t opal_nvram_driver = {
   91         "opal_nvram",
   92         opal_nvram_methods,
   93         sizeof(struct opal_nvram_softc)
   94 };
   95 
   96 DRIVER_MODULE(opal_nvram, opal, opal_nvram_driver, 0, 0);
   97 
   98 /*
   99  * Cdev methods.
  100  */
  101 
  102 static  d_open_t        opal_nvram_open;
  103 static  d_close_t       opal_nvram_close;
  104 static  d_read_t        opal_nvram_read;
  105 static  d_write_t       opal_nvram_write;
  106 static  d_ioctl_t       opal_nvram_ioctl;
  107 
  108 static struct cdevsw opal_nvram_cdevsw = {
  109         .d_version =    D_VERSION,
  110         .d_open =       opal_nvram_open,
  111         .d_close =      opal_nvram_close,
  112         .d_read =       opal_nvram_read,
  113         .d_write =      opal_nvram_write,
  114         .d_ioctl =      opal_nvram_ioctl,
  115         .d_name =       "nvram",
  116 };
  117 
  118 static int
  119 opal_nvram_probe(device_t dev)
  120 {
  121 
  122         if (!ofw_bus_is_compatible(dev, "ibm,opal-nvram"))
  123                 return (ENXIO);
  124 
  125         device_set_desc(dev, "OPAL NVRAM");
  126         return (BUS_PROBE_DEFAULT);
  127 }
  128 
  129 static int
  130 opal_nvram_attach(device_t dev)
  131 {
  132         struct opal_nvram_softc *sc;
  133         phandle_t node;
  134         int err;
  135 
  136         node = ofw_bus_get_node(dev);
  137         sc = device_get_softc(dev);
  138 
  139         sc->sc_dev = dev;
  140 
  141         err = OF_getencprop(node, "#bytes", &sc->sc_size,
  142             sizeof(sc->sc_size));
  143 
  144         if (err < 0)
  145                 return (ENXIO);
  146 
  147         sc->sc_buf = contigmalloc(NVRAM_BUFSIZE, M_DEVBUF, M_WAITOK,
  148             0, BUS_SPACE_MAXADDR, PAGE_SIZE, 0);
  149         if (sc->sc_buf == NULL) {
  150                 device_printf(dev, "No memory for buffer.\n");
  151                 return (ENXIO);
  152         }
  153         sc->sc_buf_phys = pmap_kextract((vm_offset_t)sc->sc_buf);
  154         sc->sc_cdev = make_dev(&opal_nvram_cdevsw, 0, 0, 0, 0600,
  155             "nvram");
  156         sc->sc_cdev->si_drv1 = sc;
  157 
  158         mtx_init(&sc->sc_mtx, "opal_nvram", 0, MTX_DEF);
  159 
  160         return (0);
  161 }
  162 
  163 static int
  164 opal_nvram_detach(device_t dev)
  165 {
  166         struct opal_nvram_softc *sc;
  167 
  168         sc = device_get_softc(dev);
  169 
  170         if (sc->sc_cdev != NULL)
  171                 destroy_dev(sc->sc_cdev);
  172         if (sc->sc_buf != NULL)
  173                 contigfree(sc->sc_buf, NVRAM_BUFSIZE, M_DEVBUF);
  174 
  175         mtx_destroy(&sc->sc_mtx);
  176 
  177         return (0);
  178 }
  179 
  180 static int
  181 opal_nvram_open(struct cdev *dev, int flags, int fmt, struct thread *td)
  182 {
  183         struct opal_nvram_softc *sc = dev->si_drv1;
  184         int err;
  185 
  186         err = 0;
  187 
  188         NVRAM_LOCK(sc);
  189         if (sc->sc_isopen)
  190                 err = EBUSY;
  191         else
  192                 sc->sc_isopen = 1;
  193         NVRAM_UNLOCK(sc);
  194 
  195         return (err);
  196 }
  197 
  198 static int
  199 opal_nvram_close(struct cdev *dev, int fflag, int devtype, struct thread *td)
  200 {
  201         struct opal_nvram_softc *sc = dev->si_drv1;
  202 
  203         NVRAM_LOCK(sc);
  204         sc->sc_isopen = 0;
  205         NVRAM_UNLOCK(sc);
  206 
  207         return (0);
  208 }
  209 
  210 static int
  211 opal_nvram_read(struct cdev *dev, struct uio *uio, int ioflag)
  212 {
  213         struct opal_nvram_softc *sc = dev->si_drv1;
  214         int rv, amnt;
  215 
  216         rv = 0;
  217 
  218         NVRAM_LOCK(sc);
  219         while (uio->uio_resid > 0) {
  220                 amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset);
  221                 amnt = MIN(amnt, NVRAM_BUFSIZE);
  222                 if (amnt == 0)
  223                         break;
  224 
  225                 rv = opal_call(OPAL_READ_NVRAM, sc->sc_buf_phys,
  226                     amnt, uio->uio_offset);
  227                 if (rv != OPAL_SUCCESS) {
  228                         switch (rv) {
  229                         case OPAL_HARDWARE:
  230                                 rv = EIO;
  231                                 break;
  232                         case OPAL_PARAMETER:
  233                                 rv = EINVAL;
  234                                 break;
  235                         }
  236                         break;
  237                 }
  238                 rv = uiomove(sc->sc_buf, amnt, uio);
  239                 if (rv != 0)
  240                         break;
  241         }
  242         NVRAM_UNLOCK(sc);
  243 
  244         return (rv);
  245 }
  246 
  247 static int
  248 opal_nvram_write(struct cdev *dev, struct uio *uio, int ioflag)
  249 {
  250         off_t offset;
  251         int rv, amnt;
  252         struct opal_nvram_softc *sc = dev->si_drv1;
  253 
  254         rv = 0;
  255 
  256         NVRAM_LOCK(sc);
  257         while (uio->uio_resid > 0) {
  258                 amnt = MIN(uio->uio_resid, sc->sc_size - uio->uio_offset);
  259                 amnt = MIN(amnt, NVRAM_BUFSIZE);
  260                 if (amnt == 0) {
  261                         rv = ENOSPC;
  262                         break;
  263                 }
  264                 offset = uio->uio_offset;
  265                 rv = uiomove(sc->sc_buf, amnt, uio);
  266                 if (rv != 0)
  267                         break;
  268                 rv = opal_call(OPAL_WRITE_NVRAM, sc->sc_buf_phys, amnt,
  269                     offset);
  270                 if (rv != OPAL_SUCCESS) {
  271                         switch (rv) {
  272                         case OPAL_HARDWARE:
  273                                 rv = EIO;
  274                                 break;
  275                         case OPAL_PARAMETER:
  276                                 rv = EINVAL;
  277                                 break;
  278                         }
  279                         break;
  280                 }
  281         }
  282 
  283         NVRAM_UNLOCK(sc);
  284 
  285         return (rv);
  286 }
  287 
  288 static int
  289 opal_nvram_ioctl(struct cdev *dev, u_long cmd, caddr_t data, int fflag,
  290     struct thread *td)
  291 {
  292         struct opal_nvram_softc *sc = dev->si_drv1;
  293 
  294         switch (cmd) {
  295         case DIOCGMEDIASIZE:
  296                 *(off_t *)data = sc->sc_size;
  297                 return (0);
  298         }
  299         return (EINVAL);
  300 }

Cache object: 0687fe1a6bc1b8fb2c541dfcc8072298


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