1098ca2bdSWarner Losh /*-
2718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-4-Clause
3718cf2ccSPedro F. Giffuni *
477ee030bSHidetoshi Shimokawa * Copyright (c) 2003 Hidetoshi Shimokawa
53c60ba66SKatsushi Kobayashi * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa
63c60ba66SKatsushi Kobayashi * All rights reserved.
73c60ba66SKatsushi Kobayashi *
83c60ba66SKatsushi Kobayashi * Redistribution and use in source and binary forms, with or without
93c60ba66SKatsushi Kobayashi * modification, are permitted provided that the following conditions
103c60ba66SKatsushi Kobayashi * are met:
113c60ba66SKatsushi Kobayashi * 1. Redistributions of source code must retain the above copyright
123c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer.
133c60ba66SKatsushi Kobayashi * 2. Redistributions in binary form must reproduce the above copyright
143c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer in the
153c60ba66SKatsushi Kobayashi * documentation and/or other materials provided with the distribution.
163c60ba66SKatsushi Kobayashi * 3. All advertising materials mentioning features or use of this software
173c60ba66SKatsushi Kobayashi * must display the acknowledgement as bellow:
183c60ba66SKatsushi Kobayashi *
193c60ba66SKatsushi Kobayashi * This product includes software developed by K. Kobayashi and H. SHimokawa
203c60ba66SKatsushi Kobayashi *
213c60ba66SKatsushi Kobayashi * 4. The name of the author may not be used to endorse or promote products
223c60ba66SKatsushi Kobayashi * derived from this software without specific prior written permission.
233c60ba66SKatsushi Kobayashi *
243c60ba66SKatsushi Kobayashi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
253c60ba66SKatsushi Kobayashi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
263c60ba66SKatsushi Kobayashi * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
273c60ba66SKatsushi Kobayashi * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
283c60ba66SKatsushi Kobayashi * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
293c60ba66SKatsushi Kobayashi * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
303c60ba66SKatsushi Kobayashi * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
313c60ba66SKatsushi Kobayashi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
323c60ba66SKatsushi Kobayashi * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
333c60ba66SKatsushi Kobayashi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
343c60ba66SKatsushi Kobayashi * POSSIBILITY OF SUCH DAMAGE.
353c60ba66SKatsushi Kobayashi */
363c60ba66SKatsushi Kobayashi
374b7ec270SMarius Strobl #include <sys/cdefs.h>
3877ee030bSHidetoshi Shimokawa #define BOUNCE_BUFFER_TEST 0
3977ee030bSHidetoshi Shimokawa
403c60ba66SKatsushi Kobayashi #include <sys/param.h>
413c60ba66SKatsushi Kobayashi #include <sys/systm.h>
423c60ba66SKatsushi Kobayashi #include <sys/kernel.h>
433c60ba66SKatsushi Kobayashi #include <sys/module.h>
443c60ba66SKatsushi Kobayashi #include <sys/bus.h>
453c60ba66SKatsushi Kobayashi #include <sys/queue.h>
463c60ba66SKatsushi Kobayashi #include <machine/bus.h>
473c60ba66SKatsushi Kobayashi #include <sys/rman.h>
485166f1dfSHidetoshi Shimokawa #include <sys/malloc.h>
49f6b1c44dSScott Long #include <sys/lock.h>
50f6b1c44dSScott Long #include <sys/mutex.h>
513c60ba66SKatsushi Kobayashi #include <machine/resource.h>
523c60ba66SKatsushi Kobayashi
534fbd232cSWarner Losh #include <dev/pci/pcivar.h>
544fbd232cSWarner Losh #include <dev/pci/pcireg.h>
553c60ba66SKatsushi Kobayashi
563c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire.h>
573c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirereg.h>
583c60ba66SKatsushi Kobayashi
5977ee030bSHidetoshi Shimokawa #include <dev/firewire/fwdma.h>
603c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcireg.h>
613c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcivar.h>
623c60ba66SKatsushi Kobayashi
633c60ba66SKatsushi Kobayashi static int fwohci_pci_attach(device_t self);
643c60ba66SKatsushi Kobayashi static int fwohci_pci_detach(device_t self);
653c60ba66SKatsushi Kobayashi
663c60ba66SKatsushi Kobayashi /*
673c60ba66SKatsushi Kobayashi * The probe routine.
683c60ba66SKatsushi Kobayashi */
693c60ba66SKatsushi Kobayashi static int
fwohci_pci_probe(device_t dev)703c60ba66SKatsushi Kobayashi fwohci_pci_probe(device_t dev)
713c60ba66SKatsushi Kobayashi {
7203161bbcSDoug Rabson uint32_t id;
7378953135SHidetoshi Shimokawa
7469f034daSHidetoshi Shimokawa id = pci_get_devid(dev);
756e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) {
766e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "National Semiconductor CS4210");
77538565c4SWarner Losh return BUS_PROBE_DEFAULT;
786e2b0d0bSHidetoshi Shimokawa }
7978953135SHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) {
803c60ba66SKatsushi Kobayashi device_set_desc(dev, "NEC uPD72861");
81538565c4SWarner Losh return BUS_PROBE_DEFAULT;
823c60ba66SKatsushi Kobayashi }
8312f2a295SHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) {
8412f2a295SHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72871/2");
85538565c4SWarner Losh return BUS_PROBE_DEFAULT;
8612f2a295SHidetoshi Shimokawa }
878fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) {
888fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72870");
89538565c4SWarner Losh return BUS_PROBE_DEFAULT;
908fd36d4aSHidetoshi Shimokawa }
91dbc80c7bSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) {
92dbc80c7bSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72873");
93538565c4SWarner Losh return BUS_PROBE_DEFAULT;
94dbc80c7bSHidetoshi Shimokawa }
958fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) {
968fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72874");
97538565c4SWarner Losh return BUS_PROBE_DEFAULT;
988fd36d4aSHidetoshi Shimokawa }
996e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) {
1006e2b0d0bSHidetoshi Shimokawa /* It has no real identifier, using device id. */
1016e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "SiS 7007");
102538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1036e2b0d0bSHidetoshi Shimokawa }
10478953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) {
1053c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV22");
106538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1073c60ba66SKatsushi Kobayashi }
10878953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) {
1093c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV23");
110538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1113c60ba66SKatsushi Kobayashi }
11278953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) {
1133c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV26");
114538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1153c60ba66SKatsushi Kobayashi }
11678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) {
1173c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB43AA22");
118538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1193c60ba66SKatsushi Kobayashi }
12078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) {
12178953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB22/A");
122538565c4SWarner Losh return BUS_PROBE_DEFAULT;
12378953135SHidetoshi Shimokawa }
1246e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) {
1256e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP");
126538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1276e2b0d0bSHidetoshi Shimokawa }
1288fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) {
1298fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB23");
130538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1318fd36d4aSHidetoshi Shimokawa }
1323be95df6SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) {
1333be95df6SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB82AA2");
134538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1353be95df6SHidetoshi Shimokawa }
13678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) {
13778953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4450");
138538565c4SWarner Losh return BUS_PROBE_DEFAULT;
13978953135SHidetoshi Shimokawa }
14078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) {
14178953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4410A");
142538565c4SWarner Losh return BUS_PROBE_DEFAULT;
14378953135SHidetoshi Shimokawa }
1448fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) {
1458fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4451");
146538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1478fd36d4aSHidetoshi Shimokawa }
148433dd56bSHidetoshi Shimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) {
149d47f7646SWarner Losh device_printf(dev, "Sony i.LINK (CXD1947) not supported\n");
1504143dbe3SWarner Losh return ENXIO;
151433dd56bSHidetoshi Shimokawa }
152433dd56bSHidetoshi Shimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) {
153433dd56bSHidetoshi Shimokawa device_set_desc(dev, "Sony i.LINK (CXD3222)");
154538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1553c60ba66SKatsushi Kobayashi }
15678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) {
157433dd56bSHidetoshi Shimokawa device_set_desc(dev, "VIA Fire II (VT6306)");
158538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1593c60ba66SKatsushi Kobayashi }
1608fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) {
1618fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Ricoh R5C551");
162538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1638fd36d4aSHidetoshi Shimokawa }
16478953135SHidetoshi Shimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) {
1653c60ba66SKatsushi Kobayashi device_set_desc(dev, "Ricoh R5C552");
166538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1673c60ba66SKatsushi Kobayashi }
16878953135SHidetoshi Shimokawa if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) {
169a9c9b698SKatsushi Kobayashi device_set_desc(dev, "Apple Pangea");
170538565c4SWarner Losh return BUS_PROBE_DEFAULT;
171a9c9b698SKatsushi Kobayashi }
17233d62e33SWarner Losh if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH2)) {
17333d62e33SWarner Losh device_set_desc(dev, "Apple UniNorth 2");
174538565c4SWarner Losh return BUS_PROBE_DEFAULT;
175a9c9b698SKatsushi Kobayashi }
17678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) {
177a9c9b698SKatsushi Kobayashi device_set_desc(dev, "Lucent FW322/323");
178538565c4SWarner Losh return BUS_PROBE_DEFAULT;
179a9c9b698SKatsushi Kobayashi }
1806e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) {
1816e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Intel 82372FB");
182538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1836e2b0d0bSHidetoshi Shimokawa }
1846e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) {
1856e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Adaptec AHA-894x/AIC-5800");
186538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1876e2b0d0bSHidetoshi Shimokawa }
1883c60ba66SKatsushi Kobayashi if (pci_get_class(dev) == PCIC_SERIALBUS
1893c60ba66SKatsushi Kobayashi && pci_get_subclass(dev) == PCIS_SERIALBUS_FW
1903c60ba66SKatsushi Kobayashi && pci_get_progif(dev) == PCI_INTERFACE_OHCI) {
19139981fedSJohn Baldwin if (bootverbose)
19239981fedSJohn Baldwin device_printf(dev, "vendor=%x, dev=%x\n",
19339981fedSJohn Baldwin pci_get_vendor(dev), pci_get_device(dev));
1943c60ba66SKatsushi Kobayashi device_set_desc(dev, "1394 Open Host Controller Interface");
195538565c4SWarner Losh return BUS_PROBE_DEFAULT;
1963c60ba66SKatsushi Kobayashi }
1973c60ba66SKatsushi Kobayashi
1983c60ba66SKatsushi Kobayashi return ENXIO;
1993c60ba66SKatsushi Kobayashi }
2003c60ba66SKatsushi Kobayashi
2013c60ba66SKatsushi Kobayashi static int
fwohci_pci_init(device_t self)2029339321dSHidetoshi Shimokawa fwohci_pci_init(device_t self)
2033c60ba66SKatsushi Kobayashi {
20477ee030bSHidetoshi Shimokawa int olatency, latency, ocache_line, cache_line;
20503161bbcSDoug Rabson uint16_t cmd;
2063c60ba66SKatsushi Kobayashi
2073c60ba66SKatsushi Kobayashi cmd = pci_read_config(self, PCIR_COMMAND, 2);
208c68534f1SScott Long cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
209e726a7e1SHidetoshi Shimokawa #if 1 /* for broken hardware */
210a84fda13SHidetoshi Shimokawa cmd &= ~PCIM_CMD_MWRICEN;
211a84fda13SHidetoshi Shimokawa #endif
2123c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_COMMAND, cmd, 2);
2133c60ba66SKatsushi Kobayashi
21477ee030bSHidetoshi Shimokawa latency = olatency = pci_read_config(self, PCIR_LATTIMER, 1);
215a84fda13SHidetoshi Shimokawa #define DEF_LATENCY 0x20
21677ee030bSHidetoshi Shimokawa if (olatency < DEF_LATENCY) {
2173c60ba66SKatsushi Kobayashi latency = DEF_LATENCY;
2183c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_LATTIMER, latency, 1);
2193c60ba66SKatsushi Kobayashi }
22077ee030bSHidetoshi Shimokawa
22177ee030bSHidetoshi Shimokawa cache_line = ocache_line = pci_read_config(self, PCIR_CACHELNSZ, 1);
22277ee030bSHidetoshi Shimokawa #define DEF_CACHE_LINE 8
22377ee030bSHidetoshi Shimokawa if (ocache_line < DEF_CACHE_LINE) {
2243c60ba66SKatsushi Kobayashi cache_line = DEF_CACHE_LINE;
2253c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1);
22677ee030bSHidetoshi Shimokawa }
22777ee030bSHidetoshi Shimokawa
22877ee030bSHidetoshi Shimokawa if (firewire_debug) {
22977ee030bSHidetoshi Shimokawa device_printf(self, "latency timer %d -> %d.\n",
23077ee030bSHidetoshi Shimokawa olatency, latency);
23177ee030bSHidetoshi Shimokawa device_printf(self, "cache size %d -> %d.\n",
23277ee030bSHidetoshi Shimokawa ocache_line, cache_line);
23377ee030bSHidetoshi Shimokawa }
2349339321dSHidetoshi Shimokawa
2359339321dSHidetoshi Shimokawa return 0;
2369339321dSHidetoshi Shimokawa }
2379339321dSHidetoshi Shimokawa
2389339321dSHidetoshi Shimokawa static int
fwohci_pci_attach(device_t self)2399339321dSHidetoshi Shimokawa fwohci_pci_attach(device_t self)
2409339321dSHidetoshi Shimokawa {
2419339321dSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(self);
2429339321dSHidetoshi Shimokawa int err;
243b180671cSHidetoshi Shimokawa int rid;
2449339321dSHidetoshi Shimokawa
245f9d9941fSHidetoshi Shimokawa #if 0
24677ee030bSHidetoshi Shimokawa if (bootverbose)
24777ee030bSHidetoshi Shimokawa firewire_debug = bootverbose;
248f9d9941fSHidetoshi Shimokawa #endif
24977ee030bSHidetoshi Shimokawa
2509950b741SHidetoshi Shimokawa mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
2519339321dSHidetoshi Shimokawa fwohci_pci_init(self);
2529339321dSHidetoshi Shimokawa
2533c60ba66SKatsushi Kobayashi rid = PCI_CBMEM;
2545f96beb9SNate Lawson sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
2553c60ba66SKatsushi Kobayashi if (!sc->bsr) {
2563c60ba66SKatsushi Kobayashi device_printf(self, "Could not map memory\n");
2573c60ba66SKatsushi Kobayashi return ENXIO;
2583c60ba66SKatsushi Kobayashi }
2593c60ba66SKatsushi Kobayashi
2603c60ba66SKatsushi Kobayashi sc->bst = rman_get_bustag(sc->bsr);
2613c60ba66SKatsushi Kobayashi sc->bsh = rman_get_bushandle(sc->bsr);
2623c60ba66SKatsushi Kobayashi
2633c60ba66SKatsushi Kobayashi rid = 0;
2645f96beb9SNate Lawson sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
2653c60ba66SKatsushi Kobayashi RF_SHAREABLE | RF_ACTIVE);
2663c60ba66SKatsushi Kobayashi if (sc->irq_res == NULL) {
2673c60ba66SKatsushi Kobayashi device_printf(self, "Could not allocate irq\n");
2683c60ba66SKatsushi Kobayashi fwohci_pci_detach(self);
2693c60ba66SKatsushi Kobayashi return ENXIO;
2703c60ba66SKatsushi Kobayashi }
2713c60ba66SKatsushi Kobayashi
27277ee030bSHidetoshi Shimokawa err = bus_setup_intr(self, sc->irq_res,
27377ee030bSHidetoshi Shimokawa INTR_TYPE_NET | INTR_MPSAFE,
2743042cc43SSean Bruno NULL, (driver_intr_t *) fwohci_intr,
2753042cc43SSean Bruno sc, &sc->ih);
2763042cc43SSean Bruno
2773c60ba66SKatsushi Kobayashi if (err) {
2783c60ba66SKatsushi Kobayashi device_printf(self, "Could not setup irq, %d\n", err);
2793c60ba66SKatsushi Kobayashi fwohci_pci_detach(self);
2803c60ba66SKatsushi Kobayashi return ENXIO;
2813c60ba66SKatsushi Kobayashi }
2823c60ba66SKatsushi Kobayashi
283c2175ff5SMarius Strobl err = bus_dma_tag_create(
284c2175ff5SMarius Strobl /*parent*/bus_get_dma_tag(self),
285c2175ff5SMarius Strobl /*alignment*/1,
28677ee030bSHidetoshi Shimokawa /*boundary*/0,
28777ee030bSHidetoshi Shimokawa #if BOUNCE_BUFFER_TEST
28877ee030bSHidetoshi Shimokawa /*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
28977ee030bSHidetoshi Shimokawa #else
29077ee030bSHidetoshi Shimokawa /*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
29177ee030bSHidetoshi Shimokawa #endif
29277ee030bSHidetoshi Shimokawa /*highaddr*/BUS_SPACE_MAXADDR,
29377ee030bSHidetoshi Shimokawa /*filter*/NULL, /*filterarg*/NULL,
29477ee030bSHidetoshi Shimokawa /*maxsize*/0x100000,
29577ee030bSHidetoshi Shimokawa /*nsegments*/0x20,
29677ee030bSHidetoshi Shimokawa /*maxsegsz*/0x8000,
29777ee030bSHidetoshi Shimokawa /*flags*/BUS_DMA_ALLOCNOW,
298f6b1c44dSScott Long /*lockfunc*/busdma_lock_mutex,
2999950b741SHidetoshi Shimokawa /*lockarg*/FW_GMTX(&sc->fc),
3004f933468SHidetoshi Shimokawa &sc->fc.dmat);
30177ee030bSHidetoshi Shimokawa if (err != 0) {
30223667f08SAlexander Kabaev device_printf(self, "fwohci_pci_attach: Could not allocate DMA "
30323667f08SAlexander Kabaev "tag - error %d\n", err);
30423667f08SAlexander Kabaev fwohci_pci_detach(self);
30577ee030bSHidetoshi Shimokawa return (ENOMEM);
30677ee030bSHidetoshi Shimokawa }
30777ee030bSHidetoshi Shimokawa
3083c60ba66SKatsushi Kobayashi err = fwohci_init(sc, self);
3093c60ba66SKatsushi Kobayashi
31023667f08SAlexander Kabaev if (err != 0) {
3111398a889SHidetoshi Shimokawa device_printf(self, "fwohci_init failed with err=%d\n", err);
3121398a889SHidetoshi Shimokawa fwohci_pci_detach(self);
3131398a889SHidetoshi Shimokawa return EIO;
3141398a889SHidetoshi Shimokawa }
3151398a889SHidetoshi Shimokawa
316b180671cSHidetoshi Shimokawa /* probe and attach a child device(firewire) */
317723da5d9SJohn Baldwin bus_identify_children(self);
318*18250ec6SJohn Baldwin bus_attach_children(self);
319c26f4c71SHidetoshi Shimokawa
3203c60ba66SKatsushi Kobayashi return 0;
3213c60ba66SKatsushi Kobayashi }
3223c60ba66SKatsushi Kobayashi
3233c60ba66SKatsushi Kobayashi static int
fwohci_pci_detach(device_t self)3243c60ba66SKatsushi Kobayashi fwohci_pci_detach(device_t self)
3253c60ba66SKatsushi Kobayashi {
3263c60ba66SKatsushi Kobayashi fwohci_softc_t *sc = device_get_softc(self);
3273c60ba66SKatsushi Kobayashi int s;
3283c60ba66SKatsushi Kobayashi
3293c60ba66SKatsushi Kobayashi s = splfw();
330d0fd7bc6SHidetoshi Shimokawa
33118349893SHidetoshi Shimokawa if (sc->bsr)
33264cf5240SHidetoshi Shimokawa fwohci_stop(sc, self);
33318349893SHidetoshi Shimokawa
3343c60ba66SKatsushi Kobayashi bus_generic_detach(self);
33523667f08SAlexander Kabaev
3363c60ba66SKatsushi Kobayashi /* disable interrupts that might have been switched on */
3373c60ba66SKatsushi Kobayashi if (sc->bst && sc->bsh)
3383c60ba66SKatsushi Kobayashi bus_space_write_4(sc->bst, sc->bsh,
3393c60ba66SKatsushi Kobayashi FWOHCI_INTMASKCLR, OHCI_INT_EN);
3403c60ba66SKatsushi Kobayashi
3413c60ba66SKatsushi Kobayashi if (sc->irq_res) {
342437a3435SHidetoshi Shimokawa int err;
343437a3435SHidetoshi Shimokawa if (sc->ih) {
344437a3435SHidetoshi Shimokawa err = bus_teardown_intr(self, sc->irq_res, sc->ih);
3453c60ba66SKatsushi Kobayashi if (err)
346437a3435SHidetoshi Shimokawa device_printf(self,
347437a3435SHidetoshi Shimokawa "Could not tear down irq, %d\n", err);
3483c60ba66SKatsushi Kobayashi sc->ih = NULL;
3493c60ba66SKatsushi Kobayashi }
3503c60ba66SKatsushi Kobayashi bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
3513c60ba66SKatsushi Kobayashi sc->irq_res = NULL;
3523c60ba66SKatsushi Kobayashi }
3533c60ba66SKatsushi Kobayashi
3543c60ba66SKatsushi Kobayashi if (sc->bsr) {
3553c60ba66SKatsushi Kobayashi bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->bsr);
3563c60ba66SKatsushi Kobayashi sc->bsr = NULL;
3573c60ba66SKatsushi Kobayashi sc->bst = 0;
3583c60ba66SKatsushi Kobayashi sc->bsh = 0;
3593c60ba66SKatsushi Kobayashi }
3601f2361f8SHidetoshi Shimokawa
3611f2361f8SHidetoshi Shimokawa fwohci_detach(sc, self);
3629950b741SHidetoshi Shimokawa mtx_destroy(FW_GMTX(&sc->fc));
3633c60ba66SKatsushi Kobayashi splx(s);
3643c60ba66SKatsushi Kobayashi
3653c60ba66SKatsushi Kobayashi return 0;
3663c60ba66SKatsushi Kobayashi }
3673c60ba66SKatsushi Kobayashi
3685e2a411fSHidetoshi Shimokawa static int
fwohci_pci_suspend(device_t dev)3695e2a411fSHidetoshi Shimokawa fwohci_pci_suspend(device_t dev)
3705e2a411fSHidetoshi Shimokawa {
371630529adSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev);
3729339321dSHidetoshi Shimokawa int err;
373bda19384SHidetoshi Shimokawa
374bda19384SHidetoshi Shimokawa device_printf(dev, "fwohci_pci_suspend\n");
3759339321dSHidetoshi Shimokawa err = bus_generic_suspend(dev);
3769339321dSHidetoshi Shimokawa if (err)
3779339321dSHidetoshi Shimokawa return err;
378630529adSHidetoshi Shimokawa fwohci_stop(sc, dev);
3795e2a411fSHidetoshi Shimokawa return 0;
3805e2a411fSHidetoshi Shimokawa }
3815e2a411fSHidetoshi Shimokawa
3825e2a411fSHidetoshi Shimokawa static int
fwohci_pci_resume(device_t dev)3835e2a411fSHidetoshi Shimokawa fwohci_pci_resume(device_t dev)
3845e2a411fSHidetoshi Shimokawa {
385d0fd7bc6SHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev);
386d0fd7bc6SHidetoshi Shimokawa
3879339321dSHidetoshi Shimokawa fwohci_pci_init(dev);
3889339321dSHidetoshi Shimokawa fwohci_resume(sc, dev);
3899339321dSHidetoshi Shimokawa return 0;
3909339321dSHidetoshi Shimokawa }
3919339321dSHidetoshi Shimokawa
3929339321dSHidetoshi Shimokawa static int
fwohci_pci_shutdown(device_t dev)3939339321dSHidetoshi Shimokawa fwohci_pci_shutdown(device_t dev)
3949339321dSHidetoshi Shimokawa {
3959339321dSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev);
3969339321dSHidetoshi Shimokawa
39764cf5240SHidetoshi Shimokawa bus_generic_shutdown(dev);
39864cf5240SHidetoshi Shimokawa fwohci_stop(sc, dev);
3995e2a411fSHidetoshi Shimokawa return 0;
4005e2a411fSHidetoshi Shimokawa }
4015e2a411fSHidetoshi Shimokawa
402b180671cSHidetoshi Shimokawa static device_t
fwohci_pci_add_child(device_t dev,u_int order,const char * name,int unit)4033d844eddSAndriy Gapon fwohci_pci_add_child(device_t dev, u_int order, const char *name, int unit)
404b180671cSHidetoshi Shimokawa {
405b180671cSHidetoshi Shimokawa struct fwohci_softc *sc;
406b180671cSHidetoshi Shimokawa device_t child;
4079950b741SHidetoshi Shimokawa int err = 0;
408b180671cSHidetoshi Shimokawa
409b180671cSHidetoshi Shimokawa sc = (struct fwohci_softc *)device_get_softc(dev);
410b180671cSHidetoshi Shimokawa child = device_add_child(dev, name, unit);
411b180671cSHidetoshi Shimokawa if (child == NULL)
412b180671cSHidetoshi Shimokawa return (child);
413b180671cSHidetoshi Shimokawa
414b180671cSHidetoshi Shimokawa sc->fc.bdev = child;
41523667f08SAlexander Kabaev device_set_ivars(child, &sc->fc);
416b180671cSHidetoshi Shimokawa
417b180671cSHidetoshi Shimokawa err = device_probe_and_attach(child);
418b180671cSHidetoshi Shimokawa if (err) {
419b180671cSHidetoshi Shimokawa device_printf(dev, "probe_and_attach failed with err=%d\n",
420b180671cSHidetoshi Shimokawa err);
421b180671cSHidetoshi Shimokawa fwohci_pci_detach(dev);
422b180671cSHidetoshi Shimokawa device_delete_child(dev, child);
423b180671cSHidetoshi Shimokawa return NULL;
424b180671cSHidetoshi Shimokawa }
425b180671cSHidetoshi Shimokawa
426b180671cSHidetoshi Shimokawa /* XXX
427b180671cSHidetoshi Shimokawa * Clear the bus reset event flag to start transactions even when
428b180671cSHidetoshi Shimokawa * interrupt is disabled during the boot process.
429b180671cSHidetoshi Shimokawa */
43006767d30SHidetoshi Shimokawa if (cold) {
4319950b741SHidetoshi Shimokawa int s;
432b180671cSHidetoshi Shimokawa DELAY(250); /* 2 cycles */
433b180671cSHidetoshi Shimokawa s = splfw();
43423667f08SAlexander Kabaev fwohci_poll(&sc->fc, 0, -1);
435b180671cSHidetoshi Shimokawa splx(s);
43606767d30SHidetoshi Shimokawa }
437b180671cSHidetoshi Shimokawa
438b180671cSHidetoshi Shimokawa return (child);
439b180671cSHidetoshi Shimokawa }
440b180671cSHidetoshi Shimokawa
4413c60ba66SKatsushi Kobayashi static device_method_t fwohci_methods[] = {
4423c60ba66SKatsushi Kobayashi /* Device interface */
4433c60ba66SKatsushi Kobayashi DEVMETHOD(device_probe, fwohci_pci_probe),
4443c60ba66SKatsushi Kobayashi DEVMETHOD(device_attach, fwohci_pci_attach),
4453c60ba66SKatsushi Kobayashi DEVMETHOD(device_detach, fwohci_pci_detach),
4465e2a411fSHidetoshi Shimokawa DEVMETHOD(device_suspend, fwohci_pci_suspend),
4475e2a411fSHidetoshi Shimokawa DEVMETHOD(device_resume, fwohci_pci_resume),
4489339321dSHidetoshi Shimokawa DEVMETHOD(device_shutdown, fwohci_pci_shutdown),
4493c60ba66SKatsushi Kobayashi
4503c60ba66SKatsushi Kobayashi /* Bus interface */
451b180671cSHidetoshi Shimokawa DEVMETHOD(bus_add_child, fwohci_pci_add_child),
4523c60ba66SKatsushi Kobayashi
4534b7ec270SMarius Strobl DEVMETHOD_END
4543c60ba66SKatsushi Kobayashi };
4553c60ba66SKatsushi Kobayashi
4563c60ba66SKatsushi Kobayashi static driver_t fwohci_driver = {
4573c60ba66SKatsushi Kobayashi "fwohci",
4583c60ba66SKatsushi Kobayashi fwohci_methods,
4593c60ba66SKatsushi Kobayashi sizeof(fwohci_softc_t),
4603c60ba66SKatsushi Kobayashi };
4613c60ba66SKatsushi Kobayashi
462b180671cSHidetoshi Shimokawa #ifdef FWOHCI_MODULE
463b180671cSHidetoshi Shimokawa MODULE_DEPEND(fwohci, firewire, 1, 1, 1);
464b180671cSHidetoshi Shimokawa #endif
4658984411bSJohn Baldwin DRIVER_MODULE(fwohci, pci, fwohci_driver, 0, 0);
466