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/scc/scc_core.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) 2004-2006 Marcel Moolenaar
    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  *
    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 WARRANTIES
   17  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
   18  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
   19  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   20  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
   21  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
   22  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
   23  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
   24  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
   25  */
   26 
   27 #include <sys/cdefs.h>
   28 __FBSDID("$FreeBSD: releng/11.2/sys/dev/scc/scc_core.c 331722 2018-03-29 02:50:57Z eadler $");
   29 
   30 #include <sys/param.h>
   31 #include <sys/systm.h>
   32 #include <sys/bus.h>
   33 #include <sys/conf.h>
   34 #include <sys/kernel.h>
   35 #include <sys/malloc.h>
   36 #include <sys/queue.h>
   37 #include <sys/serial.h>
   38 
   39 #include <machine/bus.h>
   40 #include <machine/resource.h>
   41 #include <sys/rman.h>
   42 
   43 #include <dev/scc/scc_bfe.h>
   44 #include <dev/scc/scc_bus.h>
   45 
   46 #include "scc_if.h"
   47 
   48 devclass_t scc_devclass;
   49 const char scc_driver_name[] = "scc";
   50 
   51 static MALLOC_DEFINE(M_SCC, "SCC", "SCC driver");
   52 
   53 static int
   54 scc_bfe_intr(void *arg)
   55 {
   56         struct scc_softc *sc = arg;
   57         struct scc_chan *ch;
   58         struct scc_class *cl;
   59         struct scc_mode *m;
   60         int c, i, ipend, isrc;
   61 
   62         cl = sc->sc_class;
   63         while (!sc->sc_leaving && (ipend = SCC_IPEND(sc)) != 0) {
   64                 i = 0, isrc = SER_INT_OVERRUN;
   65                 while (ipend) {
   66                         while (i < SCC_ISRCCNT && !(ipend & isrc))
   67                                 i++, isrc <<= 1;
   68                         KASSERT(i < SCC_ISRCCNT, ("%s", __func__));
   69                         ipend &= ~isrc;
   70                         for (c = 0; c < cl->cl_channels; c++) {
   71                                 ch = &sc->sc_chan[c];
   72                                 if (!(ch->ch_ipend & isrc))
   73                                         continue;
   74                                 m = &ch->ch_mode[0];
   75                                 if (m->ih_src[i] == NULL)
   76                                         continue;
   77                                 if ((*m->ih_src[i])(m->ih_arg))
   78                                         ch->ch_ipend &= ~isrc;
   79                         }
   80                 }
   81                 for (c = 0; c < cl->cl_channels; c++) {
   82                         ch = &sc->sc_chan[c];
   83                         if (!ch->ch_ipend)
   84                                 continue;
   85                         m = &ch->ch_mode[0];
   86                         if (m->ih != NULL)
   87                                 (*m->ih)(m->ih_arg);
   88                         else
   89                                 SCC_ICLEAR(sc, ch);
   90                 }
   91                 return (FILTER_HANDLED);
   92         }
   93         return (FILTER_STRAY);
   94 }
   95 
   96 int
   97 scc_bfe_attach(device_t dev, u_int ipc)
   98 {
   99         struct resource_list_entry *rle;
  100         struct scc_chan *ch;
  101         struct scc_class *cl;
  102         struct scc_mode *m;
  103         struct scc_softc *sc, *sc0;
  104         const char *sep;
  105         bus_space_handle_t bh;
  106         rman_res_t base, size, start, sz;
  107         int c, error, mode, sysdev;
  108 
  109         /*
  110          * The sc_class field defines the type of SCC we're going to work
  111          * with and thus the size of the softc. Replace the generic softc
  112          * with one that matches the SCC now that we're certain we handle
  113          * the device.
  114          */
  115         sc0 = device_get_softc(dev);
  116         cl = sc0->sc_class;
  117         if (cl->size > sizeof(*sc)) {
  118                 sc = malloc(cl->size, M_SCC, M_WAITOK|M_ZERO);
  119                 bcopy(sc0, sc, sizeof(*sc));
  120                 device_set_softc(dev, sc);
  121         } else
  122                 sc = sc0;
  123 
  124         size = abs(cl->cl_range) << sc->sc_bas.regshft;
  125 
  126         mtx_init(&sc->sc_hwmtx, "scc_hwmtx", NULL, MTX_SPIN);
  127 
  128         /*
  129          * Re-allocate. We expect that the softc contains the information
  130          * collected by scc_bfe_probe() intact.
  131          */
  132         sc->sc_rres = bus_alloc_resource_anywhere(dev, sc->sc_rtype,
  133             &sc->sc_rrid, cl->cl_channels * size, RF_ACTIVE);
  134         if (sc->sc_rres == NULL)
  135                 return (ENXIO);
  136         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
  137         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
  138 
  139         /*
  140          * Allocate interrupt resources. There may be a different interrupt
  141          * per channel. We allocate them all...
  142          */
  143         sc->sc_chan = malloc(sizeof(struct scc_chan) * cl->cl_channels,
  144             M_SCC, M_WAITOK | M_ZERO);
  145         for (c = 0; c < cl->cl_channels; c++) {
  146                 ch = &sc->sc_chan[c];
  147                 /*
  148                  * XXX temporary hack. If we have more than 1 interrupt
  149                  * per channel, allocate the first for the channel. At
  150                  * this time only the macio bus front-end has more than
  151                  * 1 interrupt per channel and we don't use the 2nd and
  152                  * 3rd, because we don't support DMA yet.
  153                  */
  154                 ch->ch_irid = c * ipc;
  155                 ch->ch_ires = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  156                     &ch->ch_irid, RF_ACTIVE | RF_SHAREABLE);
  157                 if (ipc == 0)
  158                         break;
  159         }
  160 
  161         /*
  162          * Create the control structures for our children. Probe devices
  163          * and query them to see if we can reset the hardware.
  164          */
  165         sysdev = 0;
  166         base = rman_get_start(sc->sc_rres);
  167         sz = (size != 0) ? size : rman_get_size(sc->sc_rres);
  168         start = base + ((cl->cl_range < 0) ? size * (cl->cl_channels - 1) : 0);
  169         for (c = 0; c < cl->cl_channels; c++) {
  170                 ch = &sc->sc_chan[c];
  171                 resource_list_init(&ch->ch_rlist);
  172                 ch->ch_nr = c + 1;
  173 
  174                 if (!SCC_ENABLED(sc, ch))
  175                         goto next;
  176 
  177                 ch->ch_enabled = 1;
  178                 resource_list_add(&ch->ch_rlist, sc->sc_rtype, 0, start,
  179                     start + sz - 1, sz);
  180                 rle = resource_list_find(&ch->ch_rlist, sc->sc_rtype, 0);
  181                 rle->res = &ch->ch_rres;
  182                 bus_space_subregion(rman_get_bustag(sc->sc_rres),
  183                     rman_get_bushandle(sc->sc_rres), start - base, sz, &bh);
  184                 rman_set_bushandle(rle->res, bh);
  185                 rman_set_bustag(rle->res, rman_get_bustag(sc->sc_rres));
  186 
  187                 resource_list_add(&ch->ch_rlist, SYS_RES_IRQ, 0, c, c, 1);
  188                 rle = resource_list_find(&ch->ch_rlist, SYS_RES_IRQ, 0);
  189                 rle->res = (ch->ch_ires != NULL) ? ch->ch_ires :
  190                             sc->sc_chan[0].ch_ires;
  191 
  192                 for (mode = 0; mode < SCC_NMODES; mode++) {
  193                         m = &ch->ch_mode[mode];
  194                         m->m_chan = ch;
  195                         m->m_mode = 1U << mode;
  196                         if ((cl->cl_modes & m->m_mode) == 0 || ch->ch_sysdev)
  197                                 continue;
  198                         m->m_dev = device_add_child(dev, NULL, -1);
  199                         device_set_ivars(m->m_dev, (void *)m);
  200                         error = device_probe_child(dev, m->m_dev);
  201                         if (!error) {
  202                                 m->m_probed = 1;
  203                                 m->m_sysdev = SERDEV_SYSDEV(m->m_dev) ? 1 : 0;
  204                                 ch->ch_sysdev |= m->m_sysdev;
  205                         }
  206                 }
  207 
  208          next:
  209                 start += (cl->cl_range < 0) ? -size : size;
  210                 sysdev |= ch->ch_sysdev;
  211         }
  212 
  213         /*
  214          * Have the hardware driver initialize the hardware. Tell it
  215          * whether or not a hardware reset should be performed.
  216          */
  217         if (bootverbose) {
  218                 device_printf(dev, "%sresetting hardware\n",
  219                     (sysdev) ? "not " : "");
  220         }
  221         error = SCC_ATTACH(sc, !sysdev);
  222         if (error)
  223                 goto fail;
  224 
  225         /*
  226          * Setup our interrupt handler. Make it FAST under the assumption
  227          * that our children's are fast as well. We make it MPSAFE as soon
  228          * as a child sets up a MPSAFE interrupt handler.
  229          * Of course, if we can't setup a fast handler, we make it MPSAFE
  230          * right away.
  231          */
  232         for (c = 0; c < cl->cl_channels; c++) {
  233                 ch = &sc->sc_chan[c];
  234                 if (ch->ch_ires == NULL)
  235                         continue;
  236                 error = bus_setup_intr(dev, ch->ch_ires,
  237                     INTR_TYPE_TTY, scc_bfe_intr, NULL, sc,
  238                     &ch->ch_icookie);
  239                 if (error) {
  240                         error = bus_setup_intr(dev, ch->ch_ires,
  241                             INTR_TYPE_TTY | INTR_MPSAFE, NULL,
  242                             (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie);
  243                 } else
  244                         sc->sc_fastintr = 1;
  245 
  246                 if (error) {
  247                         device_printf(dev, "could not activate interrupt\n");
  248                         bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
  249                             ch->ch_ires);
  250                         ch->ch_ires = NULL;
  251                 }
  252         }
  253         sc->sc_polled = 1;
  254         for (c = 0; c < cl->cl_channels; c++) {
  255                 if (sc->sc_chan[0].ch_ires != NULL)
  256                         sc->sc_polled = 0;
  257         }
  258 
  259         /*
  260          * Attach all child devices that were probed successfully.
  261          */
  262         for (c = 0; c < cl->cl_channels; c++) {
  263                 ch = &sc->sc_chan[c];
  264                 for (mode = 0; mode < SCC_NMODES; mode++) {
  265                         m = &ch->ch_mode[mode];
  266                         if (!m->m_probed)
  267                                 continue;
  268                         error = device_attach(m->m_dev);
  269                         if (error)
  270                                 continue;
  271                         m->m_attached = 1;
  272                 }
  273         }
  274 
  275         if (bootverbose && (sc->sc_fastintr || sc->sc_polled)) {
  276                 sep = "";
  277                 device_print_prettyname(dev);
  278                 if (sc->sc_fastintr) {
  279                         printf("%sfast interrupt", sep);
  280                         sep = ", ";
  281                 }
  282                 if (sc->sc_polled) {
  283                         printf("%spolled mode", sep);
  284                         sep = ", ";
  285                 }
  286                 printf("\n");
  287         }
  288 
  289         return (0);
  290 
  291  fail:
  292         for (c = 0; c < cl->cl_channels; c++) {
  293                 ch = &sc->sc_chan[c];
  294                 if (ch->ch_ires == NULL)
  295                         continue;
  296                 bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
  297                     ch->ch_ires);
  298         }
  299         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  300         return (error);
  301 }
  302 
  303 int
  304 scc_bfe_detach(device_t dev)
  305 {
  306         struct scc_chan *ch;
  307         struct scc_class *cl;
  308         struct scc_mode *m;
  309         struct scc_softc *sc;
  310         int chan, error, mode;
  311 
  312         sc = device_get_softc(dev);
  313         cl = sc->sc_class;
  314 
  315         /* Detach our children. */
  316         error = 0;
  317         for (chan = 0; chan < cl->cl_channels; chan++) {
  318                 ch = &sc->sc_chan[chan];
  319                 for (mode = 0; mode < SCC_NMODES; mode++) {
  320                         m = &ch->ch_mode[mode];
  321                         if (!m->m_attached)
  322                                 continue;
  323                         if (device_detach(m->m_dev) != 0)
  324                                 error = ENXIO;
  325                         else
  326                                 m->m_attached = 0;
  327                 }
  328         }
  329 
  330         if (error)
  331                 return (error);
  332 
  333         for (chan = 0; chan < cl->cl_channels; chan++) {
  334                 ch = &sc->sc_chan[chan];
  335                 if (ch->ch_ires == NULL)
  336                         continue;
  337                 bus_teardown_intr(dev, ch->ch_ires, ch->ch_icookie);
  338                 bus_release_resource(dev, SYS_RES_IRQ, ch->ch_irid,
  339                     ch->ch_ires);
  340         }
  341         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  342 
  343         free(sc->sc_chan, M_SCC);
  344 
  345         mtx_destroy(&sc->sc_hwmtx);
  346         return (0);
  347 }
  348 
  349 int
  350 scc_bfe_probe(device_t dev, u_int regshft, u_int rclk, u_int rid)
  351 {
  352         struct scc_softc *sc;
  353         struct scc_class *cl;
  354         u_long size, sz;
  355         int error;
  356 
  357         /*
  358          * Initialize the instance. Note that the instance (=softc) does
  359          * not necessarily match the hardware specific softc. We can't do
  360          * anything about it now, because we may not attach to the device.
  361          * Hardware drivers cannot use any of the class specific fields
  362          * while probing.
  363          */
  364         sc = device_get_softc(dev);
  365         cl = sc->sc_class;
  366         kobj_init((kobj_t)sc, (kobj_class_t)cl);
  367         sc->sc_dev = dev;
  368         if (device_get_desc(dev) == NULL)
  369                 device_set_desc(dev, cl->name);
  370 
  371         size = abs(cl->cl_range) << regshft;
  372 
  373         /*
  374          * Allocate the register resource. We assume that all SCCs have a
  375          * single register window in either I/O port space or memory mapped
  376          * I/O space. Any SCC that needs multiple windows will consequently
  377          * not be supported by this driver as-is.
  378          */
  379         sc->sc_rrid = rid;
  380         sc->sc_rtype = SYS_RES_MEMORY;
  381         sc->sc_rres = bus_alloc_resource_anywhere(dev, sc->sc_rtype,
  382             &sc->sc_rrid, cl->cl_channels * size, RF_ACTIVE);
  383         if (sc->sc_rres == NULL) {
  384                 sc->sc_rrid = rid;
  385                 sc->sc_rtype = SYS_RES_IOPORT;
  386                 sc->sc_rres = bus_alloc_resource_anywhere(dev, sc->sc_rtype,
  387                     &sc->sc_rrid, cl->cl_channels * size, RF_ACTIVE);
  388                 if (sc->sc_rres == NULL)
  389                         return (ENXIO);
  390         }
  391 
  392         /*
  393          * Fill in the bus access structure and call the hardware specific
  394          * probe method.
  395          */
  396         sz = (size != 0) ? size : rman_get_size(sc->sc_rres);
  397         sc->sc_bas.bsh = rman_get_bushandle(sc->sc_rres);
  398         sc->sc_bas.bst = rman_get_bustag(sc->sc_rres);
  399         sc->sc_bas.range = sz;
  400         sc->sc_bas.rclk = rclk;
  401         sc->sc_bas.regshft = regshft;
  402 
  403         error = SCC_PROBE(sc);
  404         bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
  405         return ((error == 0) ? BUS_PROBE_DEFAULT : error);
  406 }
  407 
  408 struct resource *
  409 scc_bus_alloc_resource(device_t dev, device_t child, int type, int *rid,
  410     rman_res_t start, rman_res_t end, rman_res_t count, u_int flags)
  411 {
  412         struct resource_list_entry *rle;
  413         struct scc_chan *ch;
  414         struct scc_mode *m;
  415 
  416         if (device_get_parent(child) != dev)
  417                 return (NULL);
  418 
  419         /* We only support default allocations. */
  420         if (!RMAN_IS_DEFAULT_RANGE(start, end))
  421                 return (NULL);
  422 
  423         m = device_get_ivars(child);
  424         ch = m->m_chan;
  425         rle = resource_list_find(&ch->ch_rlist, type, 0);
  426         if (rle == NULL)
  427                 return (NULL);
  428         *rid = 0;
  429         return (rle->res);
  430 }
  431 
  432 int
  433 scc_bus_get_resource(device_t dev, device_t child, int type, int rid,
  434     rman_res_t *startp, rman_res_t *countp)
  435 {
  436         struct resource_list_entry *rle;
  437         struct scc_chan *ch;
  438         struct scc_mode *m;
  439 
  440         if (device_get_parent(child) != dev)
  441                 return (EINVAL);
  442 
  443         m = device_get_ivars(child);
  444         ch = m->m_chan;
  445         rle = resource_list_find(&ch->ch_rlist, type, rid);
  446         if (rle == NULL)
  447                 return (EINVAL);
  448 
  449         if (startp != NULL)
  450                 *startp = rle->start;
  451         if (countp != NULL)
  452                 *countp = rle->count;
  453         return (0);
  454 }
  455 
  456 int
  457 scc_bus_read_ivar(device_t dev, device_t child, int index, uintptr_t *result)
  458 {
  459         struct scc_chan *ch;
  460         struct scc_class *cl;
  461         struct scc_mode *m;
  462         struct scc_softc *sc;
  463 
  464         if (device_get_parent(child) != dev)
  465                 return (EINVAL);
  466 
  467         sc = device_get_softc(dev);
  468         cl = sc->sc_class;
  469         m = device_get_ivars(child);
  470         ch = m->m_chan;
  471 
  472         switch (index) {
  473         case SCC_IVAR_CHANNEL:
  474                 *result = ch->ch_nr;
  475                 break;
  476         case SCC_IVAR_CLASS:
  477                 *result = cl->cl_class;
  478                 break;
  479         case SCC_IVAR_CLOCK:
  480                 *result = sc->sc_bas.rclk;
  481                 break;
  482         case SCC_IVAR_MODE:
  483                 *result = m->m_mode;
  484                 break;
  485         case SCC_IVAR_REGSHFT:
  486                 *result = sc->sc_bas.regshft;
  487                 break;
  488         case SCC_IVAR_HWMTX:
  489                 *result = (uintptr_t)&sc->sc_hwmtx;
  490                 break;
  491         default:
  492                 return (EINVAL);
  493         }
  494         return (0);
  495 }
  496 
  497 int
  498 scc_bus_release_resource(device_t dev, device_t child, int type, int rid,
  499     struct resource *res)
  500 {
  501         struct resource_list_entry *rle;
  502         struct scc_chan *ch;
  503         struct scc_mode *m;
  504 
  505         if (device_get_parent(child) != dev)
  506                 return (EINVAL);
  507 
  508         m = device_get_ivars(child);
  509         ch = m->m_chan;
  510         rle = resource_list_find(&ch->ch_rlist, type, rid);
  511         return ((rle == NULL) ? EINVAL : 0);
  512 }
  513 
  514 int
  515 scc_bus_setup_intr(device_t dev, device_t child, struct resource *r, int flags,
  516     driver_filter_t *filt, void (*ihand)(void *), void *arg, void **cookiep)
  517 {
  518         struct scc_chan *ch;
  519         struct scc_mode *m;
  520         struct scc_softc *sc;
  521         int c, i, isrc;
  522 
  523         if (device_get_parent(child) != dev)
  524                 return (EINVAL);
  525 
  526         /* Interrupt handlers must be FAST or MPSAFE. */
  527         if (filt == NULL && !(flags & INTR_MPSAFE))
  528                 return (EINVAL);
  529 
  530         sc = device_get_softc(dev);
  531         if (sc->sc_polled)
  532                 return (ENXIO);
  533 
  534         if (sc->sc_fastintr && filt == NULL) {
  535                 sc->sc_fastintr = 0;
  536                 for (c = 0; c < sc->sc_class->cl_channels; c++) {
  537                         ch = &sc->sc_chan[c];
  538                         if (ch->ch_ires == NULL)
  539                                 continue;
  540                         bus_teardown_intr(dev, ch->ch_ires, ch->ch_icookie);
  541                         bus_setup_intr(dev, ch->ch_ires,
  542                             INTR_TYPE_TTY | INTR_MPSAFE, NULL,
  543                             (driver_intr_t *)scc_bfe_intr, sc, &ch->ch_icookie);
  544                 }
  545         }
  546 
  547         m = device_get_ivars(child);
  548         m->m_hasintr = 1;
  549         m->m_fastintr = (filt != NULL) ? 1 : 0;
  550         m->ih = (filt != NULL) ? filt : (driver_filter_t *)ihand;
  551         m->ih_arg = arg;
  552 
  553         i = 0, isrc = SER_INT_OVERRUN;
  554         while (i < SCC_ISRCCNT) {
  555                 m->ih_src[i] = SERDEV_IHAND(child, isrc);
  556                 if (m->ih_src[i] != NULL)
  557                         m->ih = NULL;
  558                 i++, isrc <<= 1;
  559         }
  560         return (0);
  561 }
  562 
  563 int
  564 scc_bus_teardown_intr(device_t dev, device_t child, struct resource *r,
  565     void *cookie)
  566 {
  567         struct scc_mode *m;
  568         int i;
  569 
  570         if (device_get_parent(child) != dev)
  571                 return (EINVAL);
  572 
  573         m = device_get_ivars(child);
  574         if (!m->m_hasintr)
  575                 return (EINVAL);
  576 
  577         m->m_hasintr = 0;
  578         m->m_fastintr = 0;
  579         m->ih = NULL;
  580         m->ih_arg = NULL;
  581         for (i = 0; i < SCC_ISRCCNT; i++)
  582                 m->ih_src[i] = NULL;
  583         return (0);
  584 }

Cache object: ec9ac38583f8f2d7e60a79f018a50d08


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