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/mvs/mvs_pci.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) 2010 Alexander Motin <mav@FreeBSD.org>
    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  *    without modification, immediately at the beginning of the file.
   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$");
   29 
   30 #include <sys/param.h>
   31 #include <sys/module.h>
   32 #include <sys/systm.h>
   33 #include <sys/kernel.h>
   34 #include <sys/bus.h>
   35 #include <sys/endian.h>
   36 #include <sys/malloc.h>
   37 #include <sys/lock.h>
   38 #include <sys/mutex.h>
   39 #include <vm/uma.h>
   40 #include <machine/stdarg.h>
   41 #include <machine/resource.h>
   42 #include <machine/bus.h>
   43 #include <sys/rman.h>
   44 #include <dev/pci/pcivar.h>
   45 #include <dev/pci/pcireg.h>
   46 #include "mvs.h"
   47 
   48 /* local prototypes */
   49 static int mvs_setup_interrupt(device_t dev);
   50 static void mvs_intr(void *data);
   51 static int mvs_suspend(device_t dev);
   52 static int mvs_resume(device_t dev);
   53 static int mvs_ctlr_setup(device_t dev);
   54 
   55 static struct {
   56         uint32_t        id;
   57         uint8_t         rev;
   58         const char      *name;
   59         int             ports;
   60         int             quirks;
   61 } mvs_ids[] = {
   62         {0x504011ab, 0x00, "Marvell 88SX5040",  4,      MVS_Q_GENI},
   63         {0x504111ab, 0x00, "Marvell 88SX5041",  4,      MVS_Q_GENI},
   64         {0x508011ab, 0x00, "Marvell 88SX5080",  8,      MVS_Q_GENI},
   65         {0x508111ab, 0x00, "Marvell 88SX5081",  8,      MVS_Q_GENI},
   66         {0x604011ab, 0x00, "Marvell 88SX6040",  4,      MVS_Q_GENII},
   67         {0x604111ab, 0x00, "Marvell 88SX6041",  4,      MVS_Q_GENII},
   68         {0x604211ab, 0x00, "Marvell 88SX6042",  4,      MVS_Q_GENIIE},
   69         {0x608011ab, 0x00, "Marvell 88SX6080",  8,      MVS_Q_GENII},
   70         {0x608111ab, 0x00, "Marvell 88SX6081",  8,      MVS_Q_GENII},
   71         {0x704211ab, 0x00, "Marvell 88SX7042",  4,      MVS_Q_GENIIE|MVS_Q_CT},
   72         {0x02419005, 0x00, "Adaptec 1420SA",    4,      MVS_Q_GENII},
   73         {0x02439005, 0x00, "Adaptec 1430SA",    4,      MVS_Q_GENIIE|MVS_Q_CT},
   74         {0x00000000, 0x00, NULL,        0,      0}
   75 };
   76 
   77 static int
   78 mvs_probe(device_t dev)
   79 {
   80         char buf[64];
   81         int i;
   82         uint32_t devid = pci_get_devid(dev);
   83         uint8_t revid = pci_get_revid(dev);
   84 
   85         for (i = 0; mvs_ids[i].id != 0; i++) {
   86                 if (mvs_ids[i].id == devid &&
   87                     mvs_ids[i].rev <= revid) {
   88                         snprintf(buf, sizeof(buf), "%s SATA controller",
   89                             mvs_ids[i].name);
   90                         device_set_desc_copy(dev, buf);
   91                         return (BUS_PROBE_VENDOR);
   92                 }
   93         }
   94         return (ENXIO);
   95 }
   96 
   97 static int
   98 mvs_attach(device_t dev)
   99 {
  100         struct mvs_controller *ctlr = device_get_softc(dev);
  101         device_t child;
  102         int     error, unit, i;
  103         uint32_t devid = pci_get_devid(dev);
  104         uint8_t revid = pci_get_revid(dev);
  105 
  106         ctlr->dev = dev;
  107         i = 0;
  108         while (mvs_ids[i].id != 0 &&
  109             (mvs_ids[i].id != devid ||
  110              mvs_ids[i].rev > revid))
  111                 i++;
  112         ctlr->channels = mvs_ids[i].ports;
  113         ctlr->quirks = mvs_ids[i].quirks;
  114         resource_int_value(device_get_name(dev),
  115             device_get_unit(dev), "ccc", &ctlr->ccc);
  116         ctlr->cccc = 8;
  117         resource_int_value(device_get_name(dev),
  118             device_get_unit(dev), "cccc", &ctlr->cccc);
  119         if (ctlr->ccc == 0 || ctlr->cccc == 0) {
  120                 ctlr->ccc = 0;
  121                 ctlr->cccc = 0;
  122         }
  123         if (ctlr->ccc > 100000)
  124                 ctlr->ccc = 100000;
  125         device_printf(dev,
  126             "Gen-%s, %d %sGbps ports, Port Multiplier %s%s\n",
  127             ((ctlr->quirks & MVS_Q_GENI) ? "I" :
  128              ((ctlr->quirks & MVS_Q_GENII) ? "II" : "IIe")),
  129             ctlr->channels,
  130             ((ctlr->quirks & MVS_Q_GENI) ? "1.5" : "3"),
  131             ((ctlr->quirks & MVS_Q_GENI) ?
  132             "not supported" : "supported"),
  133             ((ctlr->quirks & MVS_Q_GENIIE) ?
  134             " with FBS" : ""));
  135         mtx_init(&ctlr->mtx, "MVS controller lock", NULL, MTX_DEF);
  136         /* We should have a memory BAR(0). */
  137         ctlr->r_rid = PCIR_BAR(0);
  138         if (!(ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY,
  139             &ctlr->r_rid, RF_ACTIVE)))
  140                 return ENXIO;
  141         /* Setup our own memory management for channels. */
  142         ctlr->sc_iomem.rm_start = rman_get_start(ctlr->r_mem);
  143         ctlr->sc_iomem.rm_end = rman_get_end(ctlr->r_mem);
  144         ctlr->sc_iomem.rm_type = RMAN_ARRAY;
  145         ctlr->sc_iomem.rm_descr = "I/O memory addresses";
  146         if ((error = rman_init(&ctlr->sc_iomem)) != 0) {
  147                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
  148                 return (error);
  149         }
  150         if ((error = rman_manage_region(&ctlr->sc_iomem,
  151             rman_get_start(ctlr->r_mem), rman_get_end(ctlr->r_mem))) != 0) {
  152                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
  153                 rman_fini(&ctlr->sc_iomem);
  154                 return (error);
  155         }
  156         pci_enable_busmaster(dev);
  157         mvs_ctlr_setup(dev);
  158         /* Setup interrupts. */
  159         if (mvs_setup_interrupt(dev)) {
  160                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
  161                 rman_fini(&ctlr->sc_iomem);
  162                 return ENXIO;
  163         }
  164         /* Attach all channels on this controller */
  165         for (unit = 0; unit < ctlr->channels; unit++) {
  166                 child = device_add_child(dev, "mvsch", -1);
  167                 if (child == NULL)
  168                         device_printf(dev, "failed to add channel device\n");
  169                 else
  170                         device_set_ivars(child, (void *)(intptr_t)unit);
  171         }
  172         bus_generic_attach(dev);
  173         return 0;
  174 }
  175 
  176 static int
  177 mvs_detach(device_t dev)
  178 {
  179         struct mvs_controller *ctlr = device_get_softc(dev);
  180         device_t *children;
  181         int nchildren, i;
  182 
  183         /* Detach & delete all children */
  184         if (!device_get_children(dev, &children, &nchildren)) {
  185                 for (i = 0; i < nchildren; i++)
  186                         device_delete_child(dev, children[i]);
  187                 free(children, M_TEMP);
  188         }
  189         /* Free interrupt. */
  190         if (ctlr->irq.r_irq) {
  191                 bus_teardown_intr(dev, ctlr->irq.r_irq,
  192                     ctlr->irq.handle);
  193                 bus_release_resource(dev, SYS_RES_IRQ,
  194                     ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
  195         }
  196         pci_release_msi(dev);
  197         /* Free memory. */
  198         rman_fini(&ctlr->sc_iomem);
  199         if (ctlr->r_mem)
  200                 bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem);
  201         mtx_destroy(&ctlr->mtx);
  202         return (0);
  203 }
  204 
  205 static int
  206 mvs_ctlr_setup(device_t dev)
  207 {
  208         struct mvs_controller *ctlr = device_get_softc(dev);
  209         int i, ccc = ctlr->ccc, cccc = ctlr->cccc, ccim = 0;
  210 
  211         /* Mask chip interrupts */
  212         ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000);
  213         /* Mask PCI interrupts */
  214         ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000);
  215         /* Clear PCI interrupts */
  216         ATA_OUTL(ctlr->r_mem, CHIP_PCIIC, 0x00000000);
  217         if (ccc && bootverbose) {
  218                 device_printf(dev,
  219                     "CCC with %dus/%dcmd enabled\n",
  220                     ctlr->ccc, ctlr->cccc);
  221         }
  222         ccc *= 150;
  223         /* Configure chip-global CCC */
  224         if (ctlr->channels > 4 && (ctlr->quirks & MVS_Q_GENI) == 0) {
  225                 ATA_OUTL(ctlr->r_mem, CHIP_ICT, cccc);
  226                 ATA_OUTL(ctlr->r_mem, CHIP_ITT, ccc);
  227                 ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
  228                 if (ccc)
  229                         ccim |= IC_ALL_PORTS_COAL_DONE;
  230                 ccc = 0;
  231                 cccc = 0;
  232         }
  233         for (i = 0; i < ctlr->channels / 4; i++) {
  234                 /* Configure per-HC CCC */
  235                 ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ICT, cccc);
  236                 ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_ITT, ccc);
  237                 if (ccc)
  238                         ccim |= (IC_HC0_COAL_DONE << (i * IC_HC_SHIFT));
  239                 /* Clear HC interrupts */
  240                 ATA_OUTL(ctlr->r_mem, HC_BASE(i) + HC_IC, 0x00000000);
  241         }
  242         /* Enable chip interrupts */
  243         ctlr->gmim = (ccim ? ccim : (IC_DONE_HC0 | IC_DONE_HC1)) |
  244              IC_ERR_HC0 | IC_ERR_HC1;
  245         ctlr->mim = ctlr->gmim | ctlr->pmim;
  246         ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
  247         /* Enable PCI interrupts */
  248         ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x007fffff);
  249         return (0);
  250 }
  251 
  252 static void
  253 mvs_edma(device_t dev, device_t child, int mode)
  254 {
  255         struct mvs_controller *ctlr = device_get_softc(dev);
  256         int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
  257         int bit = IC_DONE_IRQ << (unit * 2 + unit / 4) ;
  258 
  259         if (ctlr->ccc == 0)
  260                 return;
  261         /* CCC is not working for non-EDMA mode. Unmask device interrupts. */
  262         mtx_lock(&ctlr->mtx);
  263         if (mode == MVS_EDMA_OFF)
  264                 ctlr->pmim |= bit;
  265         else
  266                 ctlr->pmim &= ~bit;
  267         ctlr->mim = ctlr->gmim | ctlr->pmim;
  268         if (!ctlr->msia)
  269                 ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
  270         mtx_unlock(&ctlr->mtx);
  271 }
  272 
  273 static int
  274 mvs_suspend(device_t dev)
  275 {
  276         struct mvs_controller *ctlr = device_get_softc(dev);
  277 
  278         bus_generic_suspend(dev);
  279         /* Mask chip interrupts */
  280         ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0x00000000);
  281         /* Mask PCI interrupts */
  282         ATA_OUTL(ctlr->r_mem, CHIP_PCIIM, 0x00000000);
  283         return 0;
  284 }
  285 
  286 static int
  287 mvs_resume(device_t dev)
  288 {
  289 
  290         mvs_ctlr_setup(dev);
  291         return (bus_generic_resume(dev));
  292 }
  293 
  294 static int
  295 mvs_setup_interrupt(device_t dev)
  296 {
  297         struct mvs_controller *ctlr = device_get_softc(dev);
  298         int msi = 0;
  299 
  300         /* Process hints. */
  301         resource_int_value(device_get_name(dev),
  302             device_get_unit(dev), "msi", &msi);
  303         if (msi < 0)
  304                 msi = 0;
  305         else if (msi > 0)
  306                 msi = min(1, pci_msi_count(dev));
  307         /* Allocate MSI if needed/present. */
  308         if (msi && pci_alloc_msi(dev, &msi) != 0)
  309                 msi = 0;
  310         ctlr->msi = msi;
  311         /* Allocate all IRQs. */
  312         ctlr->irq.r_irq_rid = msi ? 1 : 0;
  313         if (!(ctlr->irq.r_irq = bus_alloc_resource_any(dev, SYS_RES_IRQ,
  314             &ctlr->irq.r_irq_rid, RF_SHAREABLE | RF_ACTIVE))) {
  315                 device_printf(dev, "unable to map interrupt\n");
  316                 return (ENXIO);
  317         }
  318         if ((bus_setup_intr(dev, ctlr->irq.r_irq, ATA_INTR_FLAGS, NULL,
  319             mvs_intr, ctlr, &ctlr->irq.handle))) {
  320                 device_printf(dev, "unable to setup interrupt\n");
  321                 bus_release_resource(dev, SYS_RES_IRQ,
  322                     ctlr->irq.r_irq_rid, ctlr->irq.r_irq);
  323                 ctlr->irq.r_irq = 0;
  324                 return (ENXIO);
  325         }
  326         return (0);
  327 }
  328 
  329 /*
  330  * Common case interrupt handler.
  331  */
  332 static void
  333 mvs_intr(void *data)
  334 {
  335         struct mvs_controller *ctlr = data;
  336         struct mvs_intr_arg arg;
  337         void (*function)(void *);
  338         int p;
  339         u_int32_t ic, aic;
  340 
  341         ic = ATA_INL(ctlr->r_mem, CHIP_MIC);
  342         if (ctlr->msi) {
  343                 /* We have to to mask MSI during processing. */
  344                 mtx_lock(&ctlr->mtx);
  345                 ATA_OUTL(ctlr->r_mem, CHIP_MIM, 0);
  346                 ctlr->msia = 1; /* Deny MIM update during processing. */
  347                 mtx_unlock(&ctlr->mtx);
  348         } else if (ic == 0)
  349                 return;
  350         /* Acknowledge all-ports CCC interrupt. */
  351         if (ic & IC_ALL_PORTS_COAL_DONE)
  352                 ATA_OUTL(ctlr->r_mem, CHIP_ICC, ~CHIP_ICC_ALL_PORTS);
  353         for (p = 0; p < ctlr->channels; p++) {
  354                 if ((p & 3) == 0) {
  355                         if (p != 0)
  356                                 ic >>= 1;
  357                         if ((ic & IC_HC0) == 0) {
  358                                 p += 3;
  359                                 ic >>= 8;
  360                                 continue;
  361                         }
  362                         /* Acknowledge interrupts of this HC. */
  363                         aic = 0;
  364                         if (ic & (IC_DONE_IRQ << 0))
  365                                 aic |= HC_IC_DONE(0) | HC_IC_DEV(0);
  366                         if (ic & (IC_DONE_IRQ << 2))
  367                                 aic |= HC_IC_DONE(1) | HC_IC_DEV(1);
  368                         if (ic & (IC_DONE_IRQ << 4))
  369                                 aic |= HC_IC_DONE(2) | HC_IC_DEV(2);
  370                         if (ic & (IC_DONE_IRQ << 6))
  371                                 aic |= HC_IC_DONE(3) | HC_IC_DEV(3);
  372                         if (ic & IC_HC0_COAL_DONE)
  373                                 aic |= HC_IC_COAL;
  374                         ATA_OUTL(ctlr->r_mem, HC_BASE(p == 4) + HC_IC, ~aic);
  375                 }
  376                 /* Call per-port interrupt handler. */
  377                 arg.cause = ic & (IC_ERR_IRQ|IC_DONE_IRQ);
  378                 if ((arg.cause != 0) &&
  379                     (function = ctlr->interrupt[p].function)) {
  380                         arg.arg = ctlr->interrupt[p].argument;
  381                         function(&arg);
  382                 }
  383                 ic >>= 2;
  384         }
  385         if (ctlr->msi) {
  386                 /* Unmasking MSI triggers next interrupt, if needed. */
  387                 mtx_lock(&ctlr->mtx);
  388                 ctlr->msia = 0; /* Allow MIM update. */
  389                 ATA_OUTL(ctlr->r_mem, CHIP_MIM, ctlr->mim);
  390                 mtx_unlock(&ctlr->mtx);
  391         }
  392 }
  393 
  394 static struct resource *
  395 mvs_alloc_resource(device_t dev, device_t child, int type, int *rid,
  396                        u_long start, u_long end, u_long count, u_int flags)
  397 {
  398         struct mvs_controller *ctlr = device_get_softc(dev);
  399         int unit = ((struct mvs_channel *)device_get_softc(child))->unit;
  400         struct resource *res = NULL;
  401         int offset = HC_BASE(unit >> 2) + PORT_BASE(unit & 0x03);
  402         long st;
  403 
  404         switch (type) {
  405         case SYS_RES_MEMORY:
  406                 st = rman_get_start(ctlr->r_mem);
  407                 res = rman_reserve_resource(&ctlr->sc_iomem, st + offset,
  408                     st + offset + PORT_SIZE - 1, PORT_SIZE, RF_ACTIVE, child);
  409                 if (res) {
  410                         bus_space_handle_t bsh;
  411                         bus_space_tag_t bst;
  412                         bsh = rman_get_bushandle(ctlr->r_mem);
  413                         bst = rman_get_bustag(ctlr->r_mem);
  414                         bus_space_subregion(bst, bsh, offset, PORT_SIZE, &bsh);
  415                         rman_set_bushandle(res, bsh);
  416                         rman_set_bustag(res, bst);
  417                 }
  418                 break;
  419         case SYS_RES_IRQ:
  420                 if (*rid == ATA_IRQ_RID)
  421                         res = ctlr->irq.r_irq;
  422                 break;
  423         }
  424         return (res);
  425 }
  426 
  427 static int
  428 mvs_release_resource(device_t dev, device_t child, int type, int rid,
  429                          struct resource *r)
  430 {
  431 
  432         switch (type) {
  433         case SYS_RES_MEMORY:
  434                 rman_release_resource(r);
  435                 return (0);
  436         case SYS_RES_IRQ:
  437                 if (rid != ATA_IRQ_RID)
  438                         return ENOENT;
  439                 return (0);
  440         }
  441         return (EINVAL);
  442 }
  443 
  444 static int
  445 mvs_setup_intr(device_t dev, device_t child, struct resource *irq, 
  446                    int flags, driver_filter_t *filter, driver_intr_t *function, 
  447                    void *argument, void **cookiep)
  448 {
  449         struct mvs_controller *ctlr = device_get_softc(dev);
  450         int unit = (intptr_t)device_get_ivars(child);
  451 
  452         if (filter != NULL) {
  453                 printf("mvs.c: we cannot use a filter here\n");
  454                 return (EINVAL);
  455         }
  456         ctlr->interrupt[unit].function = function;
  457         ctlr->interrupt[unit].argument = argument;
  458         return (0);
  459 }
  460 
  461 static int
  462 mvs_teardown_intr(device_t dev, device_t child, struct resource *irq,
  463                       void *cookie)
  464 {
  465         struct mvs_controller *ctlr = device_get_softc(dev);
  466         int unit = (intptr_t)device_get_ivars(child);
  467 
  468         ctlr->interrupt[unit].function = NULL;
  469         ctlr->interrupt[unit].argument = NULL;
  470         return (0);
  471 }
  472 
  473 static int
  474 mvs_print_child(device_t dev, device_t child)
  475 {
  476         int retval;
  477 
  478         retval = bus_print_child_header(dev, child);
  479         retval += printf(" at channel %d",
  480             (int)(intptr_t)device_get_ivars(child));
  481         retval += bus_print_child_footer(dev, child);
  482 
  483         return (retval);
  484 }
  485 
  486 static int
  487 mvs_child_location_str(device_t dev, device_t child, char *buf,
  488     size_t buflen)
  489 {
  490 
  491         snprintf(buf, buflen, "channel=%d",
  492             (int)(intptr_t)device_get_ivars(child));
  493         return (0);
  494 }
  495 
  496 static device_method_t mvs_methods[] = {
  497         DEVMETHOD(device_probe,     mvs_probe),
  498         DEVMETHOD(device_attach,    mvs_attach),
  499         DEVMETHOD(device_detach,    mvs_detach),
  500         DEVMETHOD(device_suspend,   mvs_suspend),
  501         DEVMETHOD(device_resume,    mvs_resume),
  502         DEVMETHOD(bus_print_child,  mvs_print_child),
  503         DEVMETHOD(bus_alloc_resource,       mvs_alloc_resource),
  504         DEVMETHOD(bus_release_resource,     mvs_release_resource),
  505         DEVMETHOD(bus_setup_intr,   mvs_setup_intr),
  506         DEVMETHOD(bus_teardown_intr,mvs_teardown_intr),
  507         DEVMETHOD(bus_child_location_str, mvs_child_location_str),
  508         DEVMETHOD(mvs_edma,         mvs_edma),
  509         { 0, 0 }
  510 };
  511 static driver_t mvs_driver = {
  512         "mvs",
  513         mvs_methods,
  514         sizeof(struct mvs_controller)
  515 };
  516 DRIVER_MODULE(mvs, pci, mvs_driver, mvs_devclass, 0, 0);
  517 MODULE_VERSION(mvs, 1);
  518 MODULE_DEPEND(mvs, cam, 1, 1, 1);
  519 

Cache object: 6c2add16359bc03d4477fa0c50ec7c31


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