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

Cache object: 712395927c74b59d4f5d3f65b533608d


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