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/firewire/fwohci_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  * SPDX-License-Identifier: BSD-4-Clause
    3  *
    4  * Copyright (c) 2003 Hidetoshi Shimokawa
    5  * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
    6  * All rights reserved.
    7  *
    8  * Redistribution and use in source and binary forms, with or without
    9  * modification, are permitted provided that the following conditions
   10  * are met:
   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  * 3. All advertising materials mentioning features or use of this software
   17  *    must display the acknowledgement as bellow:
   18  *
   19  *    This product includes software developed by K. Kobayashi and H. SHimokawa
   20  *
   21  * 4. The name of the author may not be used to endorse or promote products
   22  *    derived from this software without specific prior written permission.
   23  *
   24  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
   25  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
   26  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   27  * DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
   28  * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
   29  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
   30  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   32  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
   33  * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   34  * POSSIBILITY OF SUCH DAMAGE.
   35  */
   36 
   37 #include <sys/cdefs.h>
   38 __FBSDID("$FreeBSD$");
   39 
   40 #define BOUNCE_BUFFER_TEST      0
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/kernel.h>
   45 #include <sys/module.h>
   46 #include <sys/bus.h>
   47 #include <sys/queue.h>
   48 #include <machine/bus.h>
   49 #include <sys/rman.h>
   50 #include <sys/malloc.h>
   51 #include <sys/lock.h>
   52 #include <sys/mutex.h>
   53 #include <machine/resource.h>
   54 
   55 #include <dev/pci/pcivar.h>
   56 #include <dev/pci/pcireg.h>
   57 
   58 #include <dev/firewire/firewire.h>
   59 #include <dev/firewire/firewirereg.h>
   60 
   61 #include <dev/firewire/fwdma.h>
   62 #include <dev/firewire/fwohcireg.h>
   63 #include <dev/firewire/fwohcivar.h>
   64 
   65 static int fwohci_pci_attach(device_t self);
   66 static int fwohci_pci_detach(device_t self);
   67 
   68 /*
   69  * The probe routine.
   70  */
   71 static int
   72 fwohci_pci_probe(device_t dev)
   73 {
   74         uint32_t id;
   75 
   76         id = pci_get_devid(dev);
   77         if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) {
   78                 device_set_desc(dev, "National Semiconductor CS4210");
   79                 return BUS_PROBE_DEFAULT;
   80         }
   81         if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) {
   82                 device_set_desc(dev, "NEC uPD72861");
   83                 return BUS_PROBE_DEFAULT;
   84         }
   85         if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) {
   86                 device_set_desc(dev, "NEC uPD72871/2");
   87                 return BUS_PROBE_DEFAULT;
   88         }
   89         if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) {
   90                 device_set_desc(dev, "NEC uPD72870");
   91                 return BUS_PROBE_DEFAULT;
   92         }
   93         if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) {
   94                 device_set_desc(dev, "NEC uPD72873");
   95                 return BUS_PROBE_DEFAULT;
   96         }
   97         if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) {
   98                 device_set_desc(dev, "NEC uPD72874");
   99                 return BUS_PROBE_DEFAULT;
  100         }
  101         if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) {
  102                 /* It has no real identifier, using device id. */
  103                 device_set_desc(dev, "SiS 7007");
  104                 return BUS_PROBE_DEFAULT;
  105         }
  106         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) {
  107                 device_set_desc(dev, "Texas Instruments TSB12LV22");
  108                 return BUS_PROBE_DEFAULT;
  109         }
  110         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) {
  111                 device_set_desc(dev, "Texas Instruments TSB12LV23");
  112                 return BUS_PROBE_DEFAULT;
  113         }
  114         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) {
  115                 device_set_desc(dev, "Texas Instruments TSB12LV26");
  116                 return BUS_PROBE_DEFAULT;
  117         }
  118         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) {
  119                 device_set_desc(dev, "Texas Instruments TSB43AA22");
  120                 return BUS_PROBE_DEFAULT;
  121         }
  122         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) {
  123                 device_set_desc(dev, "Texas Instruments TSB43AB22/A");
  124                 return BUS_PROBE_DEFAULT;
  125         }
  126         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) {
  127                 device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP");
  128                 return BUS_PROBE_DEFAULT;
  129         }
  130         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) {
  131                 device_set_desc(dev, "Texas Instruments TSB43AB23");
  132                 return BUS_PROBE_DEFAULT;
  133         }
  134         if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) {
  135                 device_set_desc(dev, "Texas Instruments TSB82AA2");
  136                 return BUS_PROBE_DEFAULT;
  137         }
  138         if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) {
  139                 device_set_desc(dev, "Texas Instruments PCI4450");
  140                 return BUS_PROBE_DEFAULT;
  141         }
  142         if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) {
  143                 device_set_desc(dev, "Texas Instruments PCI4410A");
  144                 return BUS_PROBE_DEFAULT;
  145         }
  146         if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) {
  147                 device_set_desc(dev, "Texas Instruments PCI4451");
  148                 return BUS_PROBE_DEFAULT;
  149         }
  150         if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) {
  151                 device_printf(dev, "Sony i.LINK (CXD1947) not supported\n");
  152                 return ENXIO;
  153         }
  154         if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) {
  155                 device_set_desc(dev, "Sony i.LINK (CXD3222)");
  156                 return BUS_PROBE_DEFAULT;
  157         }
  158         if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) {
  159                 device_set_desc(dev, "VIA Fire II (VT6306)");
  160                 return BUS_PROBE_DEFAULT;
  161         }
  162         if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) {
  163                 device_set_desc(dev, "Ricoh R5C551");
  164                 return BUS_PROBE_DEFAULT;
  165         }
  166         if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) {
  167                 device_set_desc(dev, "Ricoh R5C552");
  168                 return BUS_PROBE_DEFAULT;
  169         }
  170         if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) {
  171                 device_set_desc(dev, "Apple Pangea");
  172                 return BUS_PROBE_DEFAULT;
  173         }
  174         if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH2)) {
  175                 device_set_desc(dev, "Apple UniNorth 2");
  176                 return BUS_PROBE_DEFAULT;
  177         }
  178         if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) {
  179                 device_set_desc(dev, "Lucent FW322/323");
  180                 return BUS_PROBE_DEFAULT;
  181         }
  182         if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) {
  183                 device_set_desc(dev, "Intel 82372FB");
  184                 return BUS_PROBE_DEFAULT;
  185         }
  186         if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) {
  187                 device_set_desc(dev, "Adaptec AHA-894x/AIC-5800");
  188                 return BUS_PROBE_DEFAULT;
  189         }
  190         if (pci_get_class(dev) == PCIC_SERIALBUS
  191                         && pci_get_subclass(dev) == PCIS_SERIALBUS_FW
  192                         && pci_get_progif(dev) == PCI_INTERFACE_OHCI) {
  193                 if (bootverbose)
  194                         device_printf(dev, "vendor=%x, dev=%x\n",
  195                             pci_get_vendor(dev), pci_get_device(dev));
  196                 device_set_desc(dev, "1394 Open Host Controller Interface");
  197                 return BUS_PROBE_DEFAULT;
  198         }
  199 
  200         return ENXIO;
  201 }
  202 
  203 static int
  204 fwohci_pci_init(device_t self)
  205 {
  206         int olatency, latency, ocache_line, cache_line;
  207         uint16_t cmd;
  208 
  209         cmd = pci_read_config(self, PCIR_COMMAND, 2);
  210         cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
  211 #if 1  /* for broken hardware */
  212         cmd &= ~PCIM_CMD_MWRICEN;
  213 #endif
  214         pci_write_config(self, PCIR_COMMAND, cmd, 2);
  215 
  216         latency = olatency = pci_read_config(self, PCIR_LATTIMER, 1);
  217 #define DEF_LATENCY 0x20
  218         if (olatency < DEF_LATENCY) {
  219                 latency = DEF_LATENCY;
  220                 pci_write_config(self, PCIR_LATTIMER, latency, 1);
  221         }
  222 
  223         cache_line = ocache_line = pci_read_config(self, PCIR_CACHELNSZ, 1);
  224 #define DEF_CACHE_LINE 8
  225         if (ocache_line < DEF_CACHE_LINE) {
  226                 cache_line = DEF_CACHE_LINE;
  227                 pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1);
  228         }
  229 
  230         if (firewire_debug) {
  231                 device_printf(self, "latency timer %d -> %d.\n",
  232                         olatency, latency);
  233                 device_printf(self, "cache size %d -> %d.\n",
  234                         ocache_line, cache_line);
  235         }
  236 
  237         return 0;
  238 }
  239 
  240 static int
  241 fwohci_pci_attach(device_t self)
  242 {
  243         fwohci_softc_t *sc = device_get_softc(self);
  244         int err;
  245         int rid;
  246 
  247 #if 0
  248         if (bootverbose)
  249                 firewire_debug = bootverbose;
  250 #endif
  251 
  252         mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
  253         fwohci_pci_init(self);
  254 
  255         rid = PCI_CBMEM;
  256         sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
  257         if (!sc->bsr) {
  258                 device_printf(self, "Could not map memory\n");
  259                 return ENXIO;
  260         }
  261 
  262         sc->bst = rman_get_bustag(sc->bsr);
  263         sc->bsh = rman_get_bushandle(sc->bsr);
  264 
  265         rid = 0;
  266         sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
  267                                      RF_SHAREABLE | RF_ACTIVE);
  268         if (sc->irq_res == NULL) {
  269                 device_printf(self, "Could not allocate irq\n");
  270                 fwohci_pci_detach(self);
  271                 return ENXIO;
  272         }
  273 
  274         err = bus_setup_intr(self, sc->irq_res,
  275                                 INTR_TYPE_NET | INTR_MPSAFE,
  276                                 NULL, (driver_intr_t *) fwohci_intr,
  277                                 sc, &sc->ih);
  278 
  279         if (err) {
  280                 device_printf(self, "Could not setup irq, %d\n", err);
  281                 fwohci_pci_detach(self);
  282                 return ENXIO;
  283         }
  284 
  285         err = bus_dma_tag_create(
  286                                 /*parent*/bus_get_dma_tag(self),
  287                                 /*alignment*/1,
  288                                 /*boundary*/0,
  289 #if BOUNCE_BUFFER_TEST
  290                                 /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
  291 #else
  292                                 /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
  293 #endif
  294                                 /*highaddr*/BUS_SPACE_MAXADDR,
  295                                 /*filter*/NULL, /*filterarg*/NULL,
  296                                 /*maxsize*/0x100000,
  297                                 /*nsegments*/0x20,
  298                                 /*maxsegsz*/0x8000,
  299                                 /*flags*/BUS_DMA_ALLOCNOW,
  300                                 /*lockfunc*/busdma_lock_mutex,
  301                                 /*lockarg*/FW_GMTX(&sc->fc),
  302                                 &sc->fc.dmat);
  303         if (err != 0) {
  304                 device_printf(self, "fwohci_pci_attach: Could not allocate DMA "
  305                     "tag - error %d\n", err);
  306                 fwohci_pci_detach(self);
  307                 return (ENOMEM);
  308         }
  309 
  310         err = fwohci_init(sc, self);
  311 
  312         if (err != 0) {
  313                 device_printf(self, "fwohci_init failed with err=%d\n", err);
  314                 fwohci_pci_detach(self);
  315                 return EIO;
  316         }
  317 
  318         /* probe and attach a child device(firewire) */
  319         bus_generic_probe(self);
  320         bus_generic_attach(self);
  321 
  322         return 0;
  323 }
  324 
  325 static int
  326 fwohci_pci_detach(device_t self)
  327 {
  328         fwohci_softc_t *sc = device_get_softc(self);
  329         int s;
  330 
  331         s = splfw();
  332 
  333         if (sc->bsr)
  334                 fwohci_stop(sc, self);
  335 
  336         bus_generic_detach(self);
  337 
  338         if (sc->fc.bdev) {
  339                 device_delete_child(self, sc->fc.bdev);
  340                 sc->fc.bdev = NULL;
  341         }
  342 
  343         /* disable interrupts that might have been switched on */
  344         if (sc->bst && sc->bsh)
  345                 bus_space_write_4(sc->bst, sc->bsh,
  346                                   FWOHCI_INTMASKCLR, OHCI_INT_EN);
  347 
  348         if (sc->irq_res) {
  349                 int err;
  350                 if (sc->ih) {
  351                         err = bus_teardown_intr(self, sc->irq_res, sc->ih);
  352                         if (err)
  353                                 device_printf(self,
  354                                          "Could not tear down irq, %d\n", err);
  355                         sc->ih = NULL;
  356                 }
  357                 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
  358                 sc->irq_res = NULL;
  359         }
  360 
  361         if (sc->bsr) {
  362                 bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->bsr);
  363                 sc->bsr = NULL;
  364                 sc->bst = 0;
  365                 sc->bsh = 0;
  366         }
  367 
  368         fwohci_detach(sc, self);
  369         mtx_destroy(FW_GMTX(&sc->fc));
  370         splx(s);
  371 
  372         return 0;
  373 }
  374 
  375 static int
  376 fwohci_pci_suspend(device_t dev)
  377 {
  378         fwohci_softc_t *sc = device_get_softc(dev);
  379         int err;
  380 
  381         device_printf(dev, "fwohci_pci_suspend\n");
  382         err = bus_generic_suspend(dev);
  383         if (err)
  384                 return err;
  385         fwohci_stop(sc, dev);
  386         return 0;
  387 }
  388 
  389 static int
  390 fwohci_pci_resume(device_t dev)
  391 {
  392         fwohci_softc_t *sc = device_get_softc(dev);
  393 
  394         fwohci_pci_init(dev);
  395         fwohci_resume(sc, dev);
  396         return 0;
  397 }
  398 
  399 static int
  400 fwohci_pci_shutdown(device_t dev)
  401 {
  402         fwohci_softc_t *sc = device_get_softc(dev);
  403 
  404         bus_generic_shutdown(dev);
  405         fwohci_stop(sc, dev);
  406         return 0;
  407 }
  408 
  409 static device_t
  410 fwohci_pci_add_child(device_t dev, u_int order, const char *name, int unit)
  411 {
  412         struct fwohci_softc *sc;
  413         device_t child;
  414         int err = 0;
  415 
  416         sc = (struct fwohci_softc *)device_get_softc(dev);
  417         child = device_add_child(dev, name, unit);
  418         if (child == NULL)
  419                 return (child);
  420 
  421         sc->fc.bdev = child;
  422         device_set_ivars(child, &sc->fc);
  423 
  424         err = device_probe_and_attach(child);
  425         if (err) {
  426                 device_printf(dev, "probe_and_attach failed with err=%d\n",
  427                     err);
  428                 fwohci_pci_detach(dev);
  429                 device_delete_child(dev, child);
  430                 return NULL;
  431         }
  432 
  433         /* XXX
  434          * Clear the bus reset event flag to start transactions even when
  435          * interrupt is disabled during the boot process.
  436          */
  437         if (cold) {
  438                 int s;
  439                 DELAY(250); /* 2 cycles */
  440                 s = splfw();
  441                 fwohci_poll(&sc->fc, 0, -1);
  442                 splx(s);
  443         }
  444 
  445         return (child);
  446 }
  447 
  448 static device_method_t fwohci_methods[] = {
  449         /* Device interface */
  450         DEVMETHOD(device_probe,         fwohci_pci_probe),
  451         DEVMETHOD(device_attach,        fwohci_pci_attach),
  452         DEVMETHOD(device_detach,        fwohci_pci_detach),
  453         DEVMETHOD(device_suspend,       fwohci_pci_suspend),
  454         DEVMETHOD(device_resume,        fwohci_pci_resume),
  455         DEVMETHOD(device_shutdown,      fwohci_pci_shutdown),
  456 
  457         /* Bus interface */
  458         DEVMETHOD(bus_add_child,        fwohci_pci_add_child),
  459 
  460         DEVMETHOD_END
  461 };
  462 
  463 static driver_t fwohci_driver = {
  464         "fwohci",
  465         fwohci_methods,
  466         sizeof(fwohci_softc_t),
  467 };
  468 
  469 #ifdef FWOHCI_MODULE
  470 MODULE_DEPEND(fwohci, firewire, 1, 1, 1);
  471 #endif
  472 DRIVER_MODULE(fwohci, pci, fwohci_driver, 0, 0);

Cache object: 487b70d8b81ad398a831f4e732819d81


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