xref: /freebsd/sys/dev/firewire/fwohci_pci.c (revision 33d62e33b3fe2adab49a5b99542690a4af8fe8aa)
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>
384b7ec270SMarius Strobl __FBSDID("$FreeBSD$");
394b7ec270SMarius Strobl 
4077ee030bSHidetoshi Shimokawa #define BOUNCE_BUFFER_TEST	0
4177ee030bSHidetoshi Shimokawa 
423c60ba66SKatsushi Kobayashi #include <sys/param.h>
433c60ba66SKatsushi Kobayashi #include <sys/systm.h>
443c60ba66SKatsushi Kobayashi #include <sys/kernel.h>
453c60ba66SKatsushi Kobayashi #include <sys/module.h>
463c60ba66SKatsushi Kobayashi #include <sys/bus.h>
473c60ba66SKatsushi Kobayashi #include <sys/queue.h>
483c60ba66SKatsushi Kobayashi #include <machine/bus.h>
493c60ba66SKatsushi Kobayashi #include <sys/rman.h>
505166f1dfSHidetoshi Shimokawa #include <sys/malloc.h>
51f6b1c44dSScott Long #include <sys/lock.h>
52f6b1c44dSScott Long #include <sys/mutex.h>
533c60ba66SKatsushi Kobayashi #include <machine/resource.h>
543c60ba66SKatsushi Kobayashi 
554fbd232cSWarner Losh #include <dev/pci/pcivar.h>
564fbd232cSWarner Losh #include <dev/pci/pcireg.h>
573c60ba66SKatsushi Kobayashi 
583c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire.h>
593c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirereg.h>
603c60ba66SKatsushi Kobayashi 
6177ee030bSHidetoshi Shimokawa #include <dev/firewire/fwdma.h>
623c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcireg.h>
633c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcivar.h>
643c60ba66SKatsushi Kobayashi 
653c60ba66SKatsushi Kobayashi static int fwohci_pci_attach(device_t self);
663c60ba66SKatsushi Kobayashi static int fwohci_pci_detach(device_t self);
673c60ba66SKatsushi Kobayashi 
683c60ba66SKatsushi Kobayashi /*
693c60ba66SKatsushi Kobayashi  * The probe routine.
703c60ba66SKatsushi Kobayashi  */
713c60ba66SKatsushi Kobayashi static int
723c60ba66SKatsushi Kobayashi fwohci_pci_probe(device_t dev)
733c60ba66SKatsushi Kobayashi {
7403161bbcSDoug Rabson 	uint32_t id;
7578953135SHidetoshi Shimokawa 
7669f034daSHidetoshi Shimokawa 	id = pci_get_devid(dev);
776e2b0d0bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) {
786e2b0d0bSHidetoshi Shimokawa 		device_set_desc(dev, "National Semiconductor CS4210");
79538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
806e2b0d0bSHidetoshi Shimokawa 	}
8178953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) {
823c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "NEC uPD72861");
83538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
843c60ba66SKatsushi Kobayashi 	}
8512f2a295SHidetoshi Shimokawa 	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) {
8612f2a295SHidetoshi Shimokawa 		device_set_desc(dev, "NEC uPD72871/2");
87538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
8812f2a295SHidetoshi Shimokawa 	}
898fd36d4aSHidetoshi Shimokawa 	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) {
908fd36d4aSHidetoshi Shimokawa 		device_set_desc(dev, "NEC uPD72870");
91538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
928fd36d4aSHidetoshi Shimokawa 	}
93dbc80c7bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) {
94dbc80c7bSHidetoshi Shimokawa 		device_set_desc(dev, "NEC uPD72873");
95538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
96dbc80c7bSHidetoshi Shimokawa 	}
978fd36d4aSHidetoshi Shimokawa 	if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) {
988fd36d4aSHidetoshi Shimokawa 		device_set_desc(dev, "NEC uPD72874");
99538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1008fd36d4aSHidetoshi Shimokawa 	}
1016e2b0d0bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) {
1026e2b0d0bSHidetoshi Shimokawa 		/* It has no real identifier, using device id. */
1036e2b0d0bSHidetoshi Shimokawa 		device_set_desc(dev, "SiS 7007");
104538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1056e2b0d0bSHidetoshi Shimokawa 	}
10678953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) {
1073c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "Texas Instruments TSB12LV22");
108538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1093c60ba66SKatsushi Kobayashi 	}
11078953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) {
1113c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "Texas Instruments TSB12LV23");
112538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1133c60ba66SKatsushi Kobayashi 	}
11478953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) {
1153c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "Texas Instruments TSB12LV26");
116538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1173c60ba66SKatsushi Kobayashi 	}
11878953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) {
1193c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "Texas Instruments TSB43AA22");
120538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1213c60ba66SKatsushi Kobayashi 	}
12278953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) {
12378953135SHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments TSB43AB22/A");
124538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
12578953135SHidetoshi Shimokawa 	}
1266e2b0d0bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) {
1276e2b0d0bSHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP");
128538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1296e2b0d0bSHidetoshi Shimokawa 	}
1308fd36d4aSHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) {
1318fd36d4aSHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments TSB43AB23");
132538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1338fd36d4aSHidetoshi Shimokawa 	}
1343be95df6SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) {
1353be95df6SHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments TSB82AA2");
136538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1373be95df6SHidetoshi Shimokawa 	}
13878953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) {
13978953135SHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments PCI4450");
140538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
14178953135SHidetoshi Shimokawa 	}
14278953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) {
14378953135SHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments PCI4410A");
144538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
14578953135SHidetoshi Shimokawa 	}
1468fd36d4aSHidetoshi Shimokawa 	if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) {
1478fd36d4aSHidetoshi Shimokawa 		device_set_desc(dev, "Texas Instruments PCI4451");
148538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1498fd36d4aSHidetoshi Shimokawa 	}
150433dd56bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) {
151d47f7646SWarner Losh 		device_printf(dev, "Sony i.LINK (CXD1947) not supported\n");
1524143dbe3SWarner Losh 		return ENXIO;
153433dd56bSHidetoshi Shimokawa 	}
154433dd56bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) {
155433dd56bSHidetoshi Shimokawa 		device_set_desc(dev, "Sony i.LINK (CXD3222)");
156538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1573c60ba66SKatsushi Kobayashi 	}
15878953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) {
159433dd56bSHidetoshi Shimokawa 		device_set_desc(dev, "VIA Fire II (VT6306)");
160538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1613c60ba66SKatsushi Kobayashi 	}
1628fd36d4aSHidetoshi Shimokawa 	if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) {
1638fd36d4aSHidetoshi Shimokawa 		device_set_desc(dev, "Ricoh R5C551");
164538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1658fd36d4aSHidetoshi Shimokawa 	}
16678953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) {
1673c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "Ricoh R5C552");
168538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1693c60ba66SKatsushi Kobayashi 	}
17078953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) {
171a9c9b698SKatsushi Kobayashi 		device_set_desc(dev, "Apple Pangea");
172538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
173a9c9b698SKatsushi Kobayashi 	}
174*33d62e33SWarner Losh 	if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH2)) {
175*33d62e33SWarner Losh 		device_set_desc(dev, "Apple UniNorth 2");
176538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
177a9c9b698SKatsushi Kobayashi 	}
17878953135SHidetoshi Shimokawa 	if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) {
179a9c9b698SKatsushi Kobayashi 		device_set_desc(dev, "Lucent FW322/323");
180538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
181a9c9b698SKatsushi Kobayashi 	}
1826e2b0d0bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) {
1836e2b0d0bSHidetoshi Shimokawa 		device_set_desc(dev, "Intel 82372FB");
184538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1856e2b0d0bSHidetoshi Shimokawa 	}
1866e2b0d0bSHidetoshi Shimokawa 	if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) {
1876e2b0d0bSHidetoshi Shimokawa 		device_set_desc(dev, "Adaptec AHA-894x/AIC-5800");
188538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
1896e2b0d0bSHidetoshi Shimokawa 	}
190c44123e1SMarius Strobl 	if (id == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW)) {
191c44123e1SMarius Strobl 		device_set_desc(dev, "Sun PCIO-2");
192c44123e1SMarius Strobl 		return BUS_PROBE_DEFAULT;
193c44123e1SMarius Strobl 	}
1943c60ba66SKatsushi Kobayashi 	if (pci_get_class(dev) == PCIC_SERIALBUS
1953c60ba66SKatsushi Kobayashi 			&& pci_get_subclass(dev) == PCIS_SERIALBUS_FW
1963c60ba66SKatsushi Kobayashi 			&& pci_get_progif(dev) == PCI_INTERFACE_OHCI) {
19739981fedSJohn Baldwin 		if (bootverbose)
19839981fedSJohn Baldwin 			device_printf(dev, "vendor=%x, dev=%x\n",
19939981fedSJohn Baldwin 			    pci_get_vendor(dev), pci_get_device(dev));
2003c60ba66SKatsushi Kobayashi 		device_set_desc(dev, "1394 Open Host Controller Interface");
201538565c4SWarner Losh 		return BUS_PROBE_DEFAULT;
2023c60ba66SKatsushi Kobayashi 	}
2033c60ba66SKatsushi Kobayashi 
2043c60ba66SKatsushi Kobayashi 	return ENXIO;
2053c60ba66SKatsushi Kobayashi }
2063c60ba66SKatsushi Kobayashi 
2073c60ba66SKatsushi Kobayashi static int
2089339321dSHidetoshi Shimokawa fwohci_pci_init(device_t self)
2093c60ba66SKatsushi Kobayashi {
21077ee030bSHidetoshi Shimokawa 	int olatency, latency, ocache_line, cache_line;
21103161bbcSDoug Rabson 	uint16_t cmd;
2123c60ba66SKatsushi Kobayashi 
2133c60ba66SKatsushi Kobayashi 	cmd = pci_read_config(self, PCIR_COMMAND, 2);
214c68534f1SScott Long 	cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN;
215e726a7e1SHidetoshi Shimokawa #if 1  /* for broken hardware */
216a84fda13SHidetoshi Shimokawa 	cmd &= ~PCIM_CMD_MWRICEN;
217a84fda13SHidetoshi Shimokawa #endif
2183c60ba66SKatsushi Kobayashi 	pci_write_config(self, PCIR_COMMAND, cmd, 2);
2193c60ba66SKatsushi Kobayashi 
220c44123e1SMarius Strobl 	/*
221c44123e1SMarius Strobl 	 * Some Sun PCIO-2 FireWire controllers have their intpin register
222c44123e1SMarius Strobl 	 * bogusly set to 0, although it should be 3. Correct that.
223c44123e1SMarius Strobl 	 */
224c44123e1SMarius Strobl 	if (pci_get_devid(self) == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW) &&
225c44123e1SMarius Strobl 	    pci_get_intpin(self) == 0)
226c44123e1SMarius Strobl 		pci_set_intpin(self, 3);
227c44123e1SMarius Strobl 
22877ee030bSHidetoshi Shimokawa 	latency = olatency = pci_read_config(self, PCIR_LATTIMER, 1);
229a84fda13SHidetoshi Shimokawa #define DEF_LATENCY 0x20
23077ee030bSHidetoshi Shimokawa 	if (olatency < DEF_LATENCY) {
2313c60ba66SKatsushi Kobayashi 		latency = DEF_LATENCY;
2323c60ba66SKatsushi Kobayashi 		pci_write_config(self, PCIR_LATTIMER, latency, 1);
2333c60ba66SKatsushi Kobayashi 	}
23477ee030bSHidetoshi Shimokawa 
23577ee030bSHidetoshi Shimokawa 	cache_line = ocache_line = pci_read_config(self, PCIR_CACHELNSZ, 1);
23677ee030bSHidetoshi Shimokawa #define DEF_CACHE_LINE 8
23777ee030bSHidetoshi Shimokawa 	if (ocache_line < DEF_CACHE_LINE) {
2383c60ba66SKatsushi Kobayashi 		cache_line = DEF_CACHE_LINE;
2393c60ba66SKatsushi Kobayashi 		pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1);
24077ee030bSHidetoshi Shimokawa 	}
24177ee030bSHidetoshi Shimokawa 
24277ee030bSHidetoshi Shimokawa 	if (firewire_debug) {
24377ee030bSHidetoshi Shimokawa 		device_printf(self, "latency timer %d -> %d.\n",
24477ee030bSHidetoshi Shimokawa 			olatency, latency);
24577ee030bSHidetoshi Shimokawa 		device_printf(self, "cache size %d -> %d.\n",
24677ee030bSHidetoshi Shimokawa 			ocache_line, cache_line);
24777ee030bSHidetoshi Shimokawa 	}
2489339321dSHidetoshi Shimokawa 
2499339321dSHidetoshi Shimokawa 	return 0;
2509339321dSHidetoshi Shimokawa }
2519339321dSHidetoshi Shimokawa 
2529339321dSHidetoshi Shimokawa static int
2539339321dSHidetoshi Shimokawa fwohci_pci_attach(device_t self)
2549339321dSHidetoshi Shimokawa {
2559339321dSHidetoshi Shimokawa 	fwohci_softc_t *sc = device_get_softc(self);
2569339321dSHidetoshi Shimokawa 	int err;
257b180671cSHidetoshi Shimokawa 	int rid;
2589339321dSHidetoshi Shimokawa 
259f9d9941fSHidetoshi Shimokawa #if 0
26077ee030bSHidetoshi Shimokawa 	if (bootverbose)
26177ee030bSHidetoshi Shimokawa 		firewire_debug = bootverbose;
262f9d9941fSHidetoshi Shimokawa #endif
26377ee030bSHidetoshi Shimokawa 
2649950b741SHidetoshi Shimokawa 	mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF);
2659339321dSHidetoshi Shimokawa 	fwohci_pci_init(self);
2669339321dSHidetoshi Shimokawa 
2673c60ba66SKatsushi Kobayashi 	rid = PCI_CBMEM;
2685f96beb9SNate Lawson 	sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE);
2693c60ba66SKatsushi Kobayashi 	if (!sc->bsr) {
2703c60ba66SKatsushi Kobayashi 		device_printf(self, "Could not map memory\n");
2713c60ba66SKatsushi Kobayashi 		return ENXIO;
2723c60ba66SKatsushi Kobayashi         }
2733c60ba66SKatsushi Kobayashi 
2743c60ba66SKatsushi Kobayashi 	sc->bst = rman_get_bustag(sc->bsr);
2753c60ba66SKatsushi Kobayashi 	sc->bsh = rman_get_bushandle(sc->bsr);
2763c60ba66SKatsushi Kobayashi 
2773c60ba66SKatsushi Kobayashi 	rid = 0;
2785f96beb9SNate Lawson 	sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
2793c60ba66SKatsushi Kobayashi 				     RF_SHAREABLE | RF_ACTIVE);
2803c60ba66SKatsushi Kobayashi 	if (sc->irq_res == NULL) {
2813c60ba66SKatsushi Kobayashi 		device_printf(self, "Could not allocate irq\n");
2823c60ba66SKatsushi Kobayashi 		fwohci_pci_detach(self);
2833c60ba66SKatsushi Kobayashi 		return ENXIO;
2843c60ba66SKatsushi Kobayashi 	}
2853c60ba66SKatsushi Kobayashi 
28677ee030bSHidetoshi Shimokawa 	err = bus_setup_intr(self, sc->irq_res,
28777ee030bSHidetoshi Shimokawa 				INTR_TYPE_NET | INTR_MPSAFE,
2883042cc43SSean Bruno 				NULL, (driver_intr_t *) fwohci_intr,
2893042cc43SSean Bruno 				sc, &sc->ih);
2903042cc43SSean Bruno 
2913c60ba66SKatsushi Kobayashi 	if (err) {
2923c60ba66SKatsushi Kobayashi 		device_printf(self, "Could not setup irq, %d\n", err);
2933c60ba66SKatsushi Kobayashi 		fwohci_pci_detach(self);
2943c60ba66SKatsushi Kobayashi 		return ENXIO;
2953c60ba66SKatsushi Kobayashi 	}
2963c60ba66SKatsushi Kobayashi 
297c2175ff5SMarius Strobl 	err = bus_dma_tag_create(
298c2175ff5SMarius Strobl 				/*parent*/bus_get_dma_tag(self),
299c2175ff5SMarius Strobl 				/*alignment*/1,
30077ee030bSHidetoshi Shimokawa 				/*boundary*/0,
30177ee030bSHidetoshi Shimokawa #if BOUNCE_BUFFER_TEST
30277ee030bSHidetoshi Shimokawa 				/*lowaddr*/BUS_SPACE_MAXADDR_24BIT,
30377ee030bSHidetoshi Shimokawa #else
30477ee030bSHidetoshi Shimokawa 				/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
30577ee030bSHidetoshi Shimokawa #endif
30677ee030bSHidetoshi Shimokawa 				/*highaddr*/BUS_SPACE_MAXADDR,
30777ee030bSHidetoshi Shimokawa 				/*filter*/NULL, /*filterarg*/NULL,
30877ee030bSHidetoshi Shimokawa 				/*maxsize*/0x100000,
30977ee030bSHidetoshi Shimokawa 				/*nsegments*/0x20,
31077ee030bSHidetoshi Shimokawa 				/*maxsegsz*/0x8000,
31177ee030bSHidetoshi Shimokawa 				/*flags*/BUS_DMA_ALLOCNOW,
312f6b1c44dSScott Long 				/*lockfunc*/busdma_lock_mutex,
3139950b741SHidetoshi Shimokawa 				/*lockarg*/FW_GMTX(&sc->fc),
3144f933468SHidetoshi Shimokawa 				&sc->fc.dmat);
31577ee030bSHidetoshi Shimokawa 	if (err != 0) {
31623667f08SAlexander Kabaev 		device_printf(self, "fwohci_pci_attach: Could not allocate DMA "
31723667f08SAlexander Kabaev 		    "tag - error %d\n", err);
31823667f08SAlexander Kabaev 		fwohci_pci_detach(self);
31977ee030bSHidetoshi Shimokawa 		return (ENOMEM);
32077ee030bSHidetoshi Shimokawa 	}
32177ee030bSHidetoshi Shimokawa 
3223c60ba66SKatsushi Kobayashi 	err = fwohci_init(sc, self);
3233c60ba66SKatsushi Kobayashi 
32423667f08SAlexander Kabaev 	if (err != 0) {
3251398a889SHidetoshi Shimokawa 		device_printf(self, "fwohci_init failed with err=%d\n", err);
3261398a889SHidetoshi Shimokawa 		fwohci_pci_detach(self);
3271398a889SHidetoshi Shimokawa 		return EIO;
3281398a889SHidetoshi Shimokawa 	}
3291398a889SHidetoshi Shimokawa 
330b180671cSHidetoshi Shimokawa 	/* probe and attach a child device(firewire) */
331b180671cSHidetoshi Shimokawa 	bus_generic_probe(self);
332b180671cSHidetoshi Shimokawa 	bus_generic_attach(self);
333c26f4c71SHidetoshi Shimokawa 
3343c60ba66SKatsushi Kobayashi 	return 0;
3353c60ba66SKatsushi Kobayashi }
3363c60ba66SKatsushi Kobayashi 
3373c60ba66SKatsushi Kobayashi static int
3383c60ba66SKatsushi Kobayashi fwohci_pci_detach(device_t self)
3393c60ba66SKatsushi Kobayashi {
3403c60ba66SKatsushi Kobayashi 	fwohci_softc_t *sc = device_get_softc(self);
3413c60ba66SKatsushi Kobayashi 	int s;
3423c60ba66SKatsushi Kobayashi 
3433c60ba66SKatsushi Kobayashi 	s = splfw();
344d0fd7bc6SHidetoshi Shimokawa 
34518349893SHidetoshi Shimokawa 	if (sc->bsr)
34664cf5240SHidetoshi Shimokawa 		fwohci_stop(sc, self);
34718349893SHidetoshi Shimokawa 
3483c60ba66SKatsushi Kobayashi 	bus_generic_detach(self);
34923667f08SAlexander Kabaev 
35018349893SHidetoshi Shimokawa 	if (sc->fc.bdev) {
35118349893SHidetoshi Shimokawa 		device_delete_child(self, sc->fc.bdev);
35218349893SHidetoshi Shimokawa 		sc->fc.bdev = NULL;
35318349893SHidetoshi Shimokawa 	}
3543c60ba66SKatsushi Kobayashi 
3553c60ba66SKatsushi Kobayashi 	/* disable interrupts that might have been switched on */
3563c60ba66SKatsushi Kobayashi 	if (sc->bst && sc->bsh)
3573c60ba66SKatsushi Kobayashi 		bus_space_write_4(sc->bst, sc->bsh,
3583c60ba66SKatsushi Kobayashi 				  FWOHCI_INTMASKCLR, OHCI_INT_EN);
3593c60ba66SKatsushi Kobayashi 
3603c60ba66SKatsushi Kobayashi 	if (sc->irq_res) {
361437a3435SHidetoshi Shimokawa 		int err;
362437a3435SHidetoshi Shimokawa 		if (sc->ih) {
363437a3435SHidetoshi Shimokawa 			err = bus_teardown_intr(self, sc->irq_res, sc->ih);
3643c60ba66SKatsushi Kobayashi 			if (err)
365437a3435SHidetoshi Shimokawa 				device_printf(self,
366437a3435SHidetoshi Shimokawa 					 "Could not tear down irq, %d\n", err);
3673c60ba66SKatsushi Kobayashi 			sc->ih = NULL;
3683c60ba66SKatsushi Kobayashi 		}
3693c60ba66SKatsushi Kobayashi 		bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res);
3703c60ba66SKatsushi Kobayashi 		sc->irq_res = NULL;
3713c60ba66SKatsushi Kobayashi 	}
3723c60ba66SKatsushi Kobayashi 
3733c60ba66SKatsushi Kobayashi 	if (sc->bsr) {
3743c60ba66SKatsushi Kobayashi 		bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM, sc->bsr);
3753c60ba66SKatsushi Kobayashi 		sc->bsr = NULL;
3763c60ba66SKatsushi Kobayashi 		sc->bst = 0;
3773c60ba66SKatsushi Kobayashi 		sc->bsh = 0;
3783c60ba66SKatsushi Kobayashi 	}
3791f2361f8SHidetoshi Shimokawa 
3801f2361f8SHidetoshi Shimokawa 	fwohci_detach(sc, self);
3819950b741SHidetoshi Shimokawa 	mtx_destroy(FW_GMTX(&sc->fc));
3823c60ba66SKatsushi Kobayashi 	splx(s);
3833c60ba66SKatsushi Kobayashi 
3843c60ba66SKatsushi Kobayashi 	return 0;
3853c60ba66SKatsushi Kobayashi }
3863c60ba66SKatsushi Kobayashi 
3875e2a411fSHidetoshi Shimokawa static int
3885e2a411fSHidetoshi Shimokawa fwohci_pci_suspend(device_t dev)
3895e2a411fSHidetoshi Shimokawa {
390630529adSHidetoshi Shimokawa 	fwohci_softc_t *sc = device_get_softc(dev);
3919339321dSHidetoshi Shimokawa 	int err;
392bda19384SHidetoshi Shimokawa 
393bda19384SHidetoshi Shimokawa 	device_printf(dev, "fwohci_pci_suspend\n");
3949339321dSHidetoshi Shimokawa 	err = bus_generic_suspend(dev);
3959339321dSHidetoshi Shimokawa 	if (err)
3969339321dSHidetoshi Shimokawa 		return err;
397630529adSHidetoshi Shimokawa 	fwohci_stop(sc, dev);
3985e2a411fSHidetoshi Shimokawa 	return 0;
3995e2a411fSHidetoshi Shimokawa }
4005e2a411fSHidetoshi Shimokawa 
4015e2a411fSHidetoshi Shimokawa static int
4025e2a411fSHidetoshi Shimokawa fwohci_pci_resume(device_t dev)
4035e2a411fSHidetoshi Shimokawa {
404d0fd7bc6SHidetoshi Shimokawa 	fwohci_softc_t *sc = device_get_softc(dev);
405d0fd7bc6SHidetoshi Shimokawa 
4069339321dSHidetoshi Shimokawa 	fwohci_pci_init(dev);
4079339321dSHidetoshi Shimokawa 	fwohci_resume(sc, dev);
4089339321dSHidetoshi Shimokawa 	return 0;
4099339321dSHidetoshi Shimokawa }
4109339321dSHidetoshi Shimokawa 
4119339321dSHidetoshi Shimokawa static int
4129339321dSHidetoshi Shimokawa fwohci_pci_shutdown(device_t dev)
4139339321dSHidetoshi Shimokawa {
4149339321dSHidetoshi Shimokawa 	fwohci_softc_t *sc = device_get_softc(dev);
4159339321dSHidetoshi Shimokawa 
41664cf5240SHidetoshi Shimokawa 	bus_generic_shutdown(dev);
41764cf5240SHidetoshi Shimokawa 	fwohci_stop(sc, dev);
4185e2a411fSHidetoshi Shimokawa 	return 0;
4195e2a411fSHidetoshi Shimokawa }
4205e2a411fSHidetoshi Shimokawa 
421b180671cSHidetoshi Shimokawa static device_t
4223d844eddSAndriy Gapon fwohci_pci_add_child(device_t dev, u_int order, const char *name, int unit)
423b180671cSHidetoshi Shimokawa {
424b180671cSHidetoshi Shimokawa 	struct fwohci_softc *sc;
425b180671cSHidetoshi Shimokawa 	device_t child;
4269950b741SHidetoshi Shimokawa 	int err = 0;
427b180671cSHidetoshi Shimokawa 
428b180671cSHidetoshi Shimokawa 	sc = (struct fwohci_softc *)device_get_softc(dev);
429b180671cSHidetoshi Shimokawa 	child = device_add_child(dev, name, unit);
430b180671cSHidetoshi Shimokawa 	if (child == NULL)
431b180671cSHidetoshi Shimokawa 		return (child);
432b180671cSHidetoshi Shimokawa 
433b180671cSHidetoshi Shimokawa 	sc->fc.bdev = child;
43423667f08SAlexander Kabaev 	device_set_ivars(child, &sc->fc);
435b180671cSHidetoshi Shimokawa 
436b180671cSHidetoshi Shimokawa 	err = device_probe_and_attach(child);
437b180671cSHidetoshi Shimokawa 	if (err) {
438b180671cSHidetoshi Shimokawa 		device_printf(dev, "probe_and_attach failed with err=%d\n",
439b180671cSHidetoshi Shimokawa 		    err);
440b180671cSHidetoshi Shimokawa 		fwohci_pci_detach(dev);
441b180671cSHidetoshi Shimokawa 		device_delete_child(dev, child);
442b180671cSHidetoshi Shimokawa 		return NULL;
443b180671cSHidetoshi Shimokawa 	}
444b180671cSHidetoshi Shimokawa 
445b180671cSHidetoshi Shimokawa 	/* XXX
446b180671cSHidetoshi Shimokawa 	 * Clear the bus reset event flag to start transactions even when
447b180671cSHidetoshi Shimokawa 	 * interrupt is disabled during the boot process.
448b180671cSHidetoshi Shimokawa 	 */
44906767d30SHidetoshi Shimokawa 	if (cold) {
4509950b741SHidetoshi Shimokawa 		int s;
451b180671cSHidetoshi Shimokawa 		DELAY(250); /* 2 cycles */
452b180671cSHidetoshi Shimokawa 		s = splfw();
45323667f08SAlexander Kabaev 		fwohci_poll(&sc->fc, 0, -1);
454b180671cSHidetoshi Shimokawa 		splx(s);
45506767d30SHidetoshi Shimokawa 	}
456b180671cSHidetoshi Shimokawa 
457b180671cSHidetoshi Shimokawa 	return (child);
458b180671cSHidetoshi Shimokawa }
459b180671cSHidetoshi Shimokawa 
4603c60ba66SKatsushi Kobayashi static device_method_t fwohci_methods[] = {
4613c60ba66SKatsushi Kobayashi 	/* Device interface */
4623c60ba66SKatsushi Kobayashi 	DEVMETHOD(device_probe,		fwohci_pci_probe),
4633c60ba66SKatsushi Kobayashi 	DEVMETHOD(device_attach,	fwohci_pci_attach),
4643c60ba66SKatsushi Kobayashi 	DEVMETHOD(device_detach,	fwohci_pci_detach),
4655e2a411fSHidetoshi Shimokawa 	DEVMETHOD(device_suspend,	fwohci_pci_suspend),
4665e2a411fSHidetoshi Shimokawa 	DEVMETHOD(device_resume,	fwohci_pci_resume),
4679339321dSHidetoshi Shimokawa 	DEVMETHOD(device_shutdown,	fwohci_pci_shutdown),
4683c60ba66SKatsushi Kobayashi 
4693c60ba66SKatsushi Kobayashi 	/* Bus interface */
470b180671cSHidetoshi Shimokawa 	DEVMETHOD(bus_add_child,	fwohci_pci_add_child),
4713c60ba66SKatsushi Kobayashi 
4724b7ec270SMarius Strobl 	DEVMETHOD_END
4733c60ba66SKatsushi Kobayashi };
4743c60ba66SKatsushi Kobayashi 
4753c60ba66SKatsushi Kobayashi static driver_t fwohci_driver = {
4763c60ba66SKatsushi Kobayashi 	"fwohci",
4773c60ba66SKatsushi Kobayashi 	fwohci_methods,
4783c60ba66SKatsushi Kobayashi 	sizeof(fwohci_softc_t),
4793c60ba66SKatsushi Kobayashi };
4803c60ba66SKatsushi Kobayashi 
4813c60ba66SKatsushi Kobayashi static devclass_t fwohci_devclass;
4823c60ba66SKatsushi Kobayashi 
483b180671cSHidetoshi Shimokawa #ifdef FWOHCI_MODULE
484b180671cSHidetoshi Shimokawa MODULE_DEPEND(fwohci, firewire, 1, 1, 1);
485b180671cSHidetoshi Shimokawa #endif
4863c60ba66SKatsushi Kobayashi DRIVER_MODULE(fwohci, pci, fwohci_driver, fwohci_devclass, 0, 0);
487