xref: /freebsd/sys/dev/firewire/fwohci_pci.c (revision b196276c20b577b364372f1aa1a646b9ce34bf5c)
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