1098ca2bdSWarner Losh /*- 277ee030bSHidetoshi Shimokawa * Copyright (c) 2003 Hidetoshi Shimokawa 33c60ba66SKatsushi Kobayashi * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 43c60ba66SKatsushi Kobayashi * All rights reserved. 53c60ba66SKatsushi Kobayashi * 63c60ba66SKatsushi Kobayashi * Redistribution and use in source and binary forms, with or without 73c60ba66SKatsushi Kobayashi * modification, are permitted provided that the following conditions 83c60ba66SKatsushi Kobayashi * are met: 93c60ba66SKatsushi Kobayashi * 1. Redistributions of source code must retain the above copyright 103c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer. 113c60ba66SKatsushi Kobayashi * 2. Redistributions in binary form must reproduce the above copyright 123c60ba66SKatsushi Kobayashi * notice, this list of conditions and the following disclaimer in the 133c60ba66SKatsushi Kobayashi * documentation and/or other materials provided with the distribution. 143c60ba66SKatsushi Kobayashi * 3. All advertising materials mentioning features or use of this software 153c60ba66SKatsushi Kobayashi * must display the acknowledgement as bellow: 163c60ba66SKatsushi Kobayashi * 173c60ba66SKatsushi Kobayashi * This product includes software developed by K. Kobayashi and H. SHimokawa 183c60ba66SKatsushi Kobayashi * 193c60ba66SKatsushi Kobayashi * 4. The name of the author may not be used to endorse or promote products 203c60ba66SKatsushi Kobayashi * derived from this software without specific prior written permission. 213c60ba66SKatsushi Kobayashi * 223c60ba66SKatsushi Kobayashi * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 233c60ba66SKatsushi Kobayashi * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 243c60ba66SKatsushi Kobayashi * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 253c60ba66SKatsushi Kobayashi * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 263c60ba66SKatsushi Kobayashi * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 273c60ba66SKatsushi Kobayashi * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 283c60ba66SKatsushi Kobayashi * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 293c60ba66SKatsushi Kobayashi * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 303c60ba66SKatsushi Kobayashi * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 313c60ba66SKatsushi Kobayashi * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 323c60ba66SKatsushi Kobayashi * POSSIBILITY OF SUCH DAMAGE. 333c60ba66SKatsushi Kobayashi */ 343c60ba66SKatsushi Kobayashi 354b7ec270SMarius Strobl #include <sys/cdefs.h> 364b7ec270SMarius Strobl __FBSDID("$FreeBSD$"); 374b7ec270SMarius Strobl 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> 4910d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 501102 50f6b1c44dSScott Long #include <sys/lock.h> 51f6b1c44dSScott Long #include <sys/mutex.h> 529547314fSHidetoshi Shimokawa #endif 533c60ba66SKatsushi Kobayashi #include <machine/resource.h> 543c60ba66SKatsushi Kobayashi 5510d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 56170e7a20SHidetoshi Shimokawa #include <machine/clock.h> /* for DELAY() */ 57170e7a20SHidetoshi Shimokawa #endif 58170e7a20SHidetoshi Shimokawa 5910d3ed64SHidetoshi Shimokawa #ifdef __DragonFly__ 6010d3ed64SHidetoshi Shimokawa #include <bus/pci/pcivar.h> 6110d3ed64SHidetoshi Shimokawa #include <bus/pci/pcireg.h> 6210d3ed64SHidetoshi Shimokawa 6310d3ed64SHidetoshi Shimokawa #include "firewire.h" 6410d3ed64SHidetoshi Shimokawa #include "firewirereg.h" 6510d3ed64SHidetoshi Shimokawa 6610d3ed64SHidetoshi Shimokawa #include "fwdma.h" 6710d3ed64SHidetoshi Shimokawa #include "fwohcireg.h" 6810d3ed64SHidetoshi Shimokawa #include "fwohcivar.h" 6910d3ed64SHidetoshi Shimokawa #else 702109dbc4SHidetoshi Shimokawa #if __FreeBSD_version < 500000 712109dbc4SHidetoshi Shimokawa #include <pci/pcivar.h> 722109dbc4SHidetoshi Shimokawa #include <pci/pcireg.h> 732109dbc4SHidetoshi Shimokawa #else 744fbd232cSWarner Losh #include <dev/pci/pcivar.h> 754fbd232cSWarner Losh #include <dev/pci/pcireg.h> 762109dbc4SHidetoshi Shimokawa #endif 773c60ba66SKatsushi Kobayashi 783c60ba66SKatsushi Kobayashi #include <dev/firewire/firewire.h> 793c60ba66SKatsushi Kobayashi #include <dev/firewire/firewirereg.h> 803c60ba66SKatsushi Kobayashi 8177ee030bSHidetoshi Shimokawa #include <dev/firewire/fwdma.h> 823c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcireg.h> 833c60ba66SKatsushi Kobayashi #include <dev/firewire/fwohcivar.h> 8410d3ed64SHidetoshi Shimokawa #endif 853c60ba66SKatsushi Kobayashi 863c60ba66SKatsushi Kobayashi static int fwohci_pci_attach(device_t self); 873c60ba66SKatsushi Kobayashi static int fwohci_pci_detach(device_t self); 883c60ba66SKatsushi Kobayashi 893c60ba66SKatsushi Kobayashi /* 903c60ba66SKatsushi Kobayashi * The probe routine. 913c60ba66SKatsushi Kobayashi */ 923c60ba66SKatsushi Kobayashi static int 933c60ba66SKatsushi Kobayashi fwohci_pci_probe( device_t dev ) 943c60ba66SKatsushi Kobayashi { 953c60ba66SKatsushi Kobayashi #if 1 9603161bbcSDoug Rabson uint32_t id; 9778953135SHidetoshi Shimokawa 9869f034daSHidetoshi Shimokawa id = pci_get_devid(dev); 996e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) { 1006e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "National Semiconductor CS4210"); 101538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1026e2b0d0bSHidetoshi Shimokawa } 10378953135SHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) { 1043c60ba66SKatsushi Kobayashi device_set_desc(dev, "NEC uPD72861"); 105538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1063c60ba66SKatsushi Kobayashi } 10712f2a295SHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) { 10812f2a295SHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72871/2"); 109538565c4SWarner Losh return BUS_PROBE_DEFAULT; 11012f2a295SHidetoshi Shimokawa } 1118fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) { 1128fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72870"); 113538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1148fd36d4aSHidetoshi Shimokawa } 115dbc80c7bSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) { 116dbc80c7bSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72873"); 117538565c4SWarner Losh return BUS_PROBE_DEFAULT; 118dbc80c7bSHidetoshi Shimokawa } 1198fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) { 1208fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "NEC uPD72874"); 121538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1228fd36d4aSHidetoshi Shimokawa } 1236e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) { 1246e2b0d0bSHidetoshi Shimokawa /* It has no real identifier, using device id. */ 1256e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "SiS 7007"); 126538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1276e2b0d0bSHidetoshi Shimokawa } 12878953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) { 1293c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV22"); 130538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1313c60ba66SKatsushi Kobayashi } 13278953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) { 1333c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV23"); 134538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1353c60ba66SKatsushi Kobayashi } 13678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) { 1373c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB12LV26"); 138538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1393c60ba66SKatsushi Kobayashi } 14078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) { 1413c60ba66SKatsushi Kobayashi device_set_desc(dev, "Texas Instruments TSB43AA22"); 142538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1433c60ba66SKatsushi Kobayashi } 14478953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) { 14578953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB22/A"); 146538565c4SWarner Losh return BUS_PROBE_DEFAULT; 14778953135SHidetoshi Shimokawa } 1486e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) { 1496e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP"); 150538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1516e2b0d0bSHidetoshi Shimokawa } 1528fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) { 1538fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB43AB23"); 154538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1558fd36d4aSHidetoshi Shimokawa } 1563be95df6SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) { 1573be95df6SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments TSB82AA2"); 158538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1593be95df6SHidetoshi Shimokawa } 16078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) { 16178953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4450"); 162538565c4SWarner Losh return BUS_PROBE_DEFAULT; 16378953135SHidetoshi Shimokawa } 16478953135SHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) { 16578953135SHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4410A"); 166538565c4SWarner Losh return BUS_PROBE_DEFAULT; 16778953135SHidetoshi Shimokawa } 1688fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) { 1698fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Texas Instruments PCI4451"); 170538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1718fd36d4aSHidetoshi Shimokawa } 172433dd56bSHidetoshi Shimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) { 173d47f7646SWarner Losh device_printf(dev, "Sony i.LINK (CXD1947) not supported\n"); 1744143dbe3SWarner Losh return ENXIO; 175433dd56bSHidetoshi Shimokawa } 176433dd56bSHidetoshi Shimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) { 177433dd56bSHidetoshi Shimokawa device_set_desc(dev, "Sony i.LINK (CXD3222)"); 178538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1793c60ba66SKatsushi Kobayashi } 18078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) { 181433dd56bSHidetoshi Shimokawa device_set_desc(dev, "VIA Fire II (VT6306)"); 182538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1833c60ba66SKatsushi Kobayashi } 1848fd36d4aSHidetoshi Shimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) { 1858fd36d4aSHidetoshi Shimokawa device_set_desc(dev, "Ricoh R5C551"); 186538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1878fd36d4aSHidetoshi Shimokawa } 18878953135SHidetoshi Shimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) { 1893c60ba66SKatsushi Kobayashi device_set_desc(dev, "Ricoh R5C552"); 190538565c4SWarner Losh return BUS_PROBE_DEFAULT; 1913c60ba66SKatsushi Kobayashi } 19278953135SHidetoshi Shimokawa if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) { 193a9c9b698SKatsushi Kobayashi device_set_desc(dev, "Apple Pangea"); 194538565c4SWarner Losh return BUS_PROBE_DEFAULT; 195a9c9b698SKatsushi Kobayashi } 19678953135SHidetoshi Shimokawa if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH)) { 197a9c9b698SKatsushi Kobayashi device_set_desc(dev, "Apple UniNorth"); 198538565c4SWarner Losh return BUS_PROBE_DEFAULT; 199a9c9b698SKatsushi Kobayashi } 20078953135SHidetoshi Shimokawa if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) { 201a9c9b698SKatsushi Kobayashi device_set_desc(dev, "Lucent FW322/323"); 202538565c4SWarner Losh return BUS_PROBE_DEFAULT; 203a9c9b698SKatsushi Kobayashi } 2046e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) { 2056e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Intel 82372FB"); 206538565c4SWarner Losh return BUS_PROBE_DEFAULT; 2076e2b0d0bSHidetoshi Shimokawa } 2086e2b0d0bSHidetoshi Shimokawa if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) { 2096e2b0d0bSHidetoshi Shimokawa device_set_desc(dev, "Adaptec AHA-894x/AIC-5800"); 210538565c4SWarner Losh return BUS_PROBE_DEFAULT; 2116e2b0d0bSHidetoshi Shimokawa } 212c44123e1SMarius Strobl if (id == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW)) { 213c44123e1SMarius Strobl device_set_desc(dev, "Sun PCIO-2"); 214c44123e1SMarius Strobl return BUS_PROBE_DEFAULT; 215c44123e1SMarius Strobl } 2163c60ba66SKatsushi Kobayashi #endif 2173c60ba66SKatsushi Kobayashi if (pci_get_class(dev) == PCIC_SERIALBUS 2183c60ba66SKatsushi Kobayashi && pci_get_subclass(dev) == PCIS_SERIALBUS_FW 2193c60ba66SKatsushi Kobayashi && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { 22039981fedSJohn Baldwin if (bootverbose) 22139981fedSJohn Baldwin device_printf(dev, "vendor=%x, dev=%x\n", 22239981fedSJohn Baldwin pci_get_vendor(dev), pci_get_device(dev)); 2233c60ba66SKatsushi Kobayashi device_set_desc(dev, "1394 Open Host Controller Interface"); 224538565c4SWarner Losh return BUS_PROBE_DEFAULT; 2253c60ba66SKatsushi Kobayashi } 2263c60ba66SKatsushi Kobayashi 2273c60ba66SKatsushi Kobayashi return ENXIO; 2283c60ba66SKatsushi Kobayashi } 2293c60ba66SKatsushi Kobayashi 23010d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 2313c60ba66SKatsushi Kobayashi static void 2323c60ba66SKatsushi Kobayashi fwohci_dummy_intr(void *arg) 2333c60ba66SKatsushi Kobayashi { 2343c60ba66SKatsushi Kobayashi /* XXX do nothing */ 2353c60ba66SKatsushi Kobayashi } 2363c60ba66SKatsushi Kobayashi #endif 2373c60ba66SKatsushi Kobayashi 2383c60ba66SKatsushi Kobayashi static int 2399339321dSHidetoshi Shimokawa fwohci_pci_init(device_t self) 2403c60ba66SKatsushi Kobayashi { 24177ee030bSHidetoshi Shimokawa int olatency, latency, ocache_line, cache_line; 24203161bbcSDoug Rabson uint16_t cmd; 2433c60ba66SKatsushi Kobayashi 2443c60ba66SKatsushi Kobayashi cmd = pci_read_config(self, PCIR_COMMAND, 2); 245*c68534f1SScott Long cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 246e726a7e1SHidetoshi Shimokawa #if 1 /* for broken hardware */ 247a84fda13SHidetoshi Shimokawa cmd &= ~PCIM_CMD_MWRICEN; 248a84fda13SHidetoshi Shimokawa #endif 2493c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_COMMAND, cmd, 2); 2503c60ba66SKatsushi Kobayashi 251c44123e1SMarius Strobl /* 252c44123e1SMarius Strobl * Some Sun PCIO-2 FireWire controllers have their intpin register 253c44123e1SMarius Strobl * bogusly set to 0, although it should be 3. Correct that. 254c44123e1SMarius Strobl */ 255c44123e1SMarius Strobl if (pci_get_devid(self) == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW) && 256c44123e1SMarius Strobl pci_get_intpin(self) == 0) 257c44123e1SMarius Strobl pci_set_intpin(self, 3); 258c44123e1SMarius Strobl 25977ee030bSHidetoshi Shimokawa latency = olatency = pci_read_config(self, PCIR_LATTIMER, 1); 260a84fda13SHidetoshi Shimokawa #define DEF_LATENCY 0x20 26177ee030bSHidetoshi Shimokawa if (olatency < DEF_LATENCY) { 2623c60ba66SKatsushi Kobayashi latency = DEF_LATENCY; 2633c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_LATTIMER, latency, 1); 2643c60ba66SKatsushi Kobayashi } 26577ee030bSHidetoshi Shimokawa 26677ee030bSHidetoshi Shimokawa cache_line = ocache_line = pci_read_config(self, PCIR_CACHELNSZ, 1); 26777ee030bSHidetoshi Shimokawa #define DEF_CACHE_LINE 8 26877ee030bSHidetoshi Shimokawa if (ocache_line < DEF_CACHE_LINE) { 2693c60ba66SKatsushi Kobayashi cache_line = DEF_CACHE_LINE; 2703c60ba66SKatsushi Kobayashi pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1); 27177ee030bSHidetoshi Shimokawa } 27277ee030bSHidetoshi Shimokawa 27377ee030bSHidetoshi Shimokawa if (firewire_debug) { 27477ee030bSHidetoshi Shimokawa device_printf(self, "latency timer %d -> %d.\n", 27577ee030bSHidetoshi Shimokawa olatency, latency); 27677ee030bSHidetoshi Shimokawa device_printf(self, "cache size %d -> %d.\n", 27777ee030bSHidetoshi Shimokawa ocache_line, cache_line); 27877ee030bSHidetoshi Shimokawa } 2799339321dSHidetoshi Shimokawa 2809339321dSHidetoshi Shimokawa return 0; 2819339321dSHidetoshi Shimokawa } 2829339321dSHidetoshi Shimokawa 2839339321dSHidetoshi Shimokawa static int 2849339321dSHidetoshi Shimokawa fwohci_pci_attach(device_t self) 2859339321dSHidetoshi Shimokawa { 2869339321dSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(self); 2879339321dSHidetoshi Shimokawa int err; 288b180671cSHidetoshi Shimokawa int rid; 28910d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 2909339321dSHidetoshi Shimokawa int intr; 2919339321dSHidetoshi Shimokawa /* For the moment, put in a message stating what is wrong */ 2929339321dSHidetoshi Shimokawa intr = pci_read_config(self, PCIR_INTLINE, 1); 2939339321dSHidetoshi Shimokawa if (intr == 0 || intr == 255) { 2949339321dSHidetoshi Shimokawa device_printf(self, "Invalid irq %d\n", intr); 2959339321dSHidetoshi Shimokawa #ifdef __i386__ 2969339321dSHidetoshi Shimokawa device_printf(self, "Please switch PNP-OS to 'No' in BIOS\n"); 2979339321dSHidetoshi Shimokawa #endif 2989339321dSHidetoshi Shimokawa } 2999339321dSHidetoshi Shimokawa #endif 3009339321dSHidetoshi Shimokawa 301f9d9941fSHidetoshi Shimokawa #if 0 30277ee030bSHidetoshi Shimokawa if (bootverbose) 30377ee030bSHidetoshi Shimokawa firewire_debug = bootverbose; 304f9d9941fSHidetoshi Shimokawa #endif 30577ee030bSHidetoshi Shimokawa 3069950b741SHidetoshi Shimokawa mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF); 3079339321dSHidetoshi Shimokawa fwohci_pci_init(self); 3089339321dSHidetoshi Shimokawa 3093c60ba66SKatsushi Kobayashi rid = PCI_CBMEM; 31010d3ed64SHidetoshi Shimokawa #if __FreeBSD_version >= 502109 3115f96beb9SNate Lawson sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 31210d3ed64SHidetoshi Shimokawa #else 31310d3ed64SHidetoshi Shimokawa sc->bsr = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 31410d3ed64SHidetoshi Shimokawa 0, ~0, 1, RF_ACTIVE); 31510d3ed64SHidetoshi Shimokawa #endif 3163c60ba66SKatsushi Kobayashi if (!sc->bsr) { 3173c60ba66SKatsushi Kobayashi device_printf(self, "Could not map memory\n"); 3183c60ba66SKatsushi Kobayashi return ENXIO; 3193c60ba66SKatsushi Kobayashi } 3203c60ba66SKatsushi Kobayashi 3213c60ba66SKatsushi Kobayashi sc->bst = rman_get_bustag(sc->bsr); 3223c60ba66SKatsushi Kobayashi sc->bsh = rman_get_bushandle(sc->bsr); 3233c60ba66SKatsushi Kobayashi 3243c60ba66SKatsushi Kobayashi rid = 0; 32510d3ed64SHidetoshi Shimokawa #if __FreeBSD_version >= 502109 3265f96beb9SNate Lawson sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 3273c60ba66SKatsushi Kobayashi RF_SHAREABLE | RF_ACTIVE); 32810d3ed64SHidetoshi Shimokawa #else 32910d3ed64SHidetoshi Shimokawa sc->irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1, 33010d3ed64SHidetoshi Shimokawa RF_SHAREABLE | RF_ACTIVE); 33110d3ed64SHidetoshi Shimokawa #endif 3323c60ba66SKatsushi Kobayashi if (sc->irq_res == NULL) { 3333c60ba66SKatsushi Kobayashi device_printf(self, "Could not allocate irq\n"); 3343c60ba66SKatsushi Kobayashi fwohci_pci_detach(self); 3353c60ba66SKatsushi Kobayashi return ENXIO; 3363c60ba66SKatsushi Kobayashi } 3373c60ba66SKatsushi Kobayashi 33877ee030bSHidetoshi Shimokawa err = bus_setup_intr(self, sc->irq_res, 33977ee030bSHidetoshi Shimokawa INTR_TYPE_NET | INTR_MPSAFE, 3403042cc43SSean Bruno NULL, (driver_intr_t *) fwohci_intr, 3413042cc43SSean Bruno sc, &sc->ih); 3423042cc43SSean Bruno 34310d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 3443c60ba66SKatsushi Kobayashi /* XXX splcam() should mask this irq for sbp.c*/ 3453c60ba66SKatsushi Kobayashi err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_CAM, 3463c60ba66SKatsushi Kobayashi (driver_intr_t *) fwohci_dummy_intr, sc, &sc->ih_cam); 34765290832SHidetoshi Shimokawa /* XXX splbio() should mask this irq for physio()/fwmem_strategy() */ 34865290832SHidetoshi Shimokawa err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, 34965290832SHidetoshi Shimokawa (driver_intr_t *) fwohci_dummy_intr, sc, &sc->ih_bio); 3503c60ba66SKatsushi Kobayashi #endif 3513c60ba66SKatsushi Kobayashi if (err) { 3523c60ba66SKatsushi Kobayashi device_printf(self, "Could not setup irq, %d\n", err); 3533c60ba66SKatsushi Kobayashi fwohci_pci_detach(self); 3543c60ba66SKatsushi Kobayashi return ENXIO; 3553c60ba66SKatsushi Kobayashi } 3563c60ba66SKatsushi Kobayashi 357c2175ff5SMarius Strobl err = bus_dma_tag_create( 358c2175ff5SMarius Strobl #if defined(__FreeBSD__) && __FreeBSD_version >= 700020 359c2175ff5SMarius Strobl /*parent*/bus_get_dma_tag(self), 360c2175ff5SMarius Strobl #else 361c2175ff5SMarius Strobl /*parent*/NULL, 362c2175ff5SMarius Strobl #endif 363c2175ff5SMarius Strobl /*alignment*/1, 36477ee030bSHidetoshi Shimokawa /*boundary*/0, 36577ee030bSHidetoshi Shimokawa #if BOUNCE_BUFFER_TEST 36677ee030bSHidetoshi Shimokawa /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 36777ee030bSHidetoshi Shimokawa #else 36877ee030bSHidetoshi Shimokawa /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 36977ee030bSHidetoshi Shimokawa #endif 37077ee030bSHidetoshi Shimokawa /*highaddr*/BUS_SPACE_MAXADDR, 37177ee030bSHidetoshi Shimokawa /*filter*/NULL, /*filterarg*/NULL, 37277ee030bSHidetoshi Shimokawa /*maxsize*/0x100000, 37377ee030bSHidetoshi Shimokawa /*nsegments*/0x20, 37477ee030bSHidetoshi Shimokawa /*maxsegsz*/0x8000, 37577ee030bSHidetoshi Shimokawa /*flags*/BUS_DMA_ALLOCNOW, 37610d3ed64SHidetoshi Shimokawa #if defined(__FreeBSD__) && __FreeBSD_version >= 501102 377f6b1c44dSScott Long /*lockfunc*/busdma_lock_mutex, 3789950b741SHidetoshi Shimokawa /*lockarg*/FW_GMTX(&sc->fc), 3794f933468SHidetoshi Shimokawa #endif 3804f933468SHidetoshi Shimokawa &sc->fc.dmat); 38177ee030bSHidetoshi Shimokawa if (err != 0) { 38277ee030bSHidetoshi Shimokawa printf("fwohci_pci_attach: Could not allocate DMA tag " 38377ee030bSHidetoshi Shimokawa "- error %d\n", err); 38477ee030bSHidetoshi Shimokawa return (ENOMEM); 38577ee030bSHidetoshi Shimokawa } 38677ee030bSHidetoshi Shimokawa 3873c60ba66SKatsushi Kobayashi err = fwohci_init(sc, self); 3883c60ba66SKatsushi Kobayashi 3891398a889SHidetoshi Shimokawa if (err) { 3901398a889SHidetoshi Shimokawa device_printf(self, "fwohci_init failed with err=%d\n", err); 3911398a889SHidetoshi Shimokawa fwohci_pci_detach(self); 3921398a889SHidetoshi Shimokawa return EIO; 3931398a889SHidetoshi Shimokawa } 3941398a889SHidetoshi Shimokawa 395b180671cSHidetoshi Shimokawa /* probe and attach a child device(firewire) */ 396b180671cSHidetoshi Shimokawa bus_generic_probe(self); 397b180671cSHidetoshi Shimokawa bus_generic_attach(self); 398c26f4c71SHidetoshi Shimokawa 3993c60ba66SKatsushi Kobayashi return 0; 4003c60ba66SKatsushi Kobayashi } 4013c60ba66SKatsushi Kobayashi 4023c60ba66SKatsushi Kobayashi static int 4033c60ba66SKatsushi Kobayashi fwohci_pci_detach(device_t self) 4043c60ba66SKatsushi Kobayashi { 4053c60ba66SKatsushi Kobayashi fwohci_softc_t *sc = device_get_softc(self); 4063c60ba66SKatsushi Kobayashi int s; 4073c60ba66SKatsushi Kobayashi 4083c60ba66SKatsushi Kobayashi 4093c60ba66SKatsushi Kobayashi s = splfw(); 410d0fd7bc6SHidetoshi Shimokawa 41118349893SHidetoshi Shimokawa if (sc->bsr) 41264cf5240SHidetoshi Shimokawa fwohci_stop(sc, self); 41318349893SHidetoshi Shimokawa 4143c60ba66SKatsushi Kobayashi bus_generic_detach(self); 41518349893SHidetoshi Shimokawa if (sc->fc.bdev) { 41618349893SHidetoshi Shimokawa device_delete_child(self, sc->fc.bdev); 41718349893SHidetoshi Shimokawa sc->fc.bdev = NULL; 41818349893SHidetoshi Shimokawa } 4193c60ba66SKatsushi Kobayashi 4203c60ba66SKatsushi Kobayashi /* disable interrupts that might have been switched on */ 4213c60ba66SKatsushi Kobayashi if (sc->bst && sc->bsh) 4223c60ba66SKatsushi Kobayashi bus_space_write_4(sc->bst, sc->bsh, 4233c60ba66SKatsushi Kobayashi FWOHCI_INTMASKCLR, OHCI_INT_EN); 4243c60ba66SKatsushi Kobayashi 4253c60ba66SKatsushi Kobayashi if (sc->irq_res) { 426437a3435SHidetoshi Shimokawa int err; 427437a3435SHidetoshi Shimokawa if (sc->ih) { 428437a3435SHidetoshi Shimokawa err = bus_teardown_intr(self, sc->irq_res, sc->ih); 4293c60ba66SKatsushi Kobayashi if (err) 430437a3435SHidetoshi Shimokawa device_printf(self, 431437a3435SHidetoshi Shimokawa "Could not tear down irq, %d\n", err); 43210d3ed64SHidetoshi Shimokawa #if defined(__DragonFly__) || __FreeBSD_version < 500000 43365290832SHidetoshi Shimokawa bus_teardown_intr(self, sc->irq_res, sc->ih_cam); 43465290832SHidetoshi Shimokawa bus_teardown_intr(self, sc->irq_res, sc->ih_bio); 4353c60ba66SKatsushi Kobayashi #endif 4363c60ba66SKatsushi Kobayashi sc->ih = NULL; 4373c60ba66SKatsushi Kobayashi } 4383c60ba66SKatsushi Kobayashi bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); 4393c60ba66SKatsushi Kobayashi sc->irq_res = NULL; 4403c60ba66SKatsushi Kobayashi } 4413c60ba66SKatsushi Kobayashi 4423c60ba66SKatsushi Kobayashi if (sc->bsr) { 4433c60ba66SKatsushi Kobayashi bus_release_resource(self, SYS_RES_MEMORY,PCI_CBMEM,sc->bsr); 4443c60ba66SKatsushi Kobayashi sc->bsr = NULL; 4453c60ba66SKatsushi Kobayashi sc->bst = 0; 4463c60ba66SKatsushi Kobayashi sc->bsh = 0; 4473c60ba66SKatsushi Kobayashi } 4481f2361f8SHidetoshi Shimokawa 4491f2361f8SHidetoshi Shimokawa fwohci_detach(sc, self); 4509950b741SHidetoshi Shimokawa mtx_destroy(FW_GMTX(&sc->fc)); 4513c60ba66SKatsushi Kobayashi splx(s); 4523c60ba66SKatsushi Kobayashi 4533c60ba66SKatsushi Kobayashi return 0; 4543c60ba66SKatsushi Kobayashi } 4553c60ba66SKatsushi Kobayashi 4565e2a411fSHidetoshi Shimokawa static int 4575e2a411fSHidetoshi Shimokawa fwohci_pci_suspend(device_t dev) 4585e2a411fSHidetoshi Shimokawa { 459630529adSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev); 4609339321dSHidetoshi Shimokawa int err; 461bda19384SHidetoshi Shimokawa 462bda19384SHidetoshi Shimokawa device_printf(dev, "fwohci_pci_suspend\n"); 4639339321dSHidetoshi Shimokawa err = bus_generic_suspend(dev); 4649339321dSHidetoshi Shimokawa if (err) 4659339321dSHidetoshi Shimokawa return err; 466630529adSHidetoshi Shimokawa fwohci_stop(sc, dev); 4675e2a411fSHidetoshi Shimokawa return 0; 4685e2a411fSHidetoshi Shimokawa } 4695e2a411fSHidetoshi Shimokawa 4705e2a411fSHidetoshi Shimokawa static int 4715e2a411fSHidetoshi Shimokawa fwohci_pci_resume(device_t dev) 4725e2a411fSHidetoshi Shimokawa { 473d0fd7bc6SHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev); 474d0fd7bc6SHidetoshi Shimokawa 4759339321dSHidetoshi Shimokawa fwohci_pci_init(dev); 4769339321dSHidetoshi Shimokawa fwohci_resume(sc, dev); 4779339321dSHidetoshi Shimokawa return 0; 4789339321dSHidetoshi Shimokawa } 4799339321dSHidetoshi Shimokawa 4809339321dSHidetoshi Shimokawa static int 4819339321dSHidetoshi Shimokawa fwohci_pci_shutdown(device_t dev) 4829339321dSHidetoshi Shimokawa { 4839339321dSHidetoshi Shimokawa fwohci_softc_t *sc = device_get_softc(dev); 4849339321dSHidetoshi Shimokawa 48564cf5240SHidetoshi Shimokawa bus_generic_shutdown(dev); 48664cf5240SHidetoshi Shimokawa fwohci_stop(sc, dev); 4875e2a411fSHidetoshi Shimokawa return 0; 4885e2a411fSHidetoshi Shimokawa } 4895e2a411fSHidetoshi Shimokawa 490b180671cSHidetoshi Shimokawa static device_t 4913d844eddSAndriy Gapon fwohci_pci_add_child(device_t dev, u_int order, const char *name, int unit) 492b180671cSHidetoshi Shimokawa { 493b180671cSHidetoshi Shimokawa struct fwohci_softc *sc; 494b180671cSHidetoshi Shimokawa device_t child; 4959950b741SHidetoshi Shimokawa int err = 0; 496b180671cSHidetoshi Shimokawa 497b180671cSHidetoshi Shimokawa sc = (struct fwohci_softc *)device_get_softc(dev); 498b180671cSHidetoshi Shimokawa child = device_add_child(dev, name, unit); 499b180671cSHidetoshi Shimokawa if (child == NULL) 500b180671cSHidetoshi Shimokawa return (child); 501b180671cSHidetoshi Shimokawa 502b180671cSHidetoshi Shimokawa sc->fc.bdev = child; 503b180671cSHidetoshi Shimokawa device_set_ivars(child, (void *)&sc->fc); 504b180671cSHidetoshi Shimokawa 505b180671cSHidetoshi Shimokawa err = device_probe_and_attach(child); 506b180671cSHidetoshi Shimokawa if (err) { 507b180671cSHidetoshi Shimokawa device_printf(dev, "probe_and_attach failed with err=%d\n", 508b180671cSHidetoshi Shimokawa err); 509b180671cSHidetoshi Shimokawa fwohci_pci_detach(dev); 510b180671cSHidetoshi Shimokawa device_delete_child(dev, child); 511b180671cSHidetoshi Shimokawa return NULL; 512b180671cSHidetoshi Shimokawa } 513b180671cSHidetoshi Shimokawa 514b180671cSHidetoshi Shimokawa /* XXX 515b180671cSHidetoshi Shimokawa * Clear the bus reset event flag to start transactions even when 516b180671cSHidetoshi Shimokawa * interrupt is disabled during the boot process. 517b180671cSHidetoshi Shimokawa */ 51806767d30SHidetoshi Shimokawa if (cold) { 5199950b741SHidetoshi Shimokawa int s; 520b180671cSHidetoshi Shimokawa DELAY(250); /* 2 cycles */ 521b180671cSHidetoshi Shimokawa s = splfw(); 522b180671cSHidetoshi Shimokawa fwohci_poll((void *)sc, 0, -1); 523b180671cSHidetoshi Shimokawa splx(s); 52406767d30SHidetoshi Shimokawa } 525b180671cSHidetoshi Shimokawa 526b180671cSHidetoshi Shimokawa return (child); 527b180671cSHidetoshi Shimokawa } 528b180671cSHidetoshi Shimokawa 5293c60ba66SKatsushi Kobayashi static device_method_t fwohci_methods[] = { 5303c60ba66SKatsushi Kobayashi /* Device interface */ 5313c60ba66SKatsushi Kobayashi DEVMETHOD(device_probe, fwohci_pci_probe), 5323c60ba66SKatsushi Kobayashi DEVMETHOD(device_attach, fwohci_pci_attach), 5333c60ba66SKatsushi Kobayashi DEVMETHOD(device_detach, fwohci_pci_detach), 5345e2a411fSHidetoshi Shimokawa DEVMETHOD(device_suspend, fwohci_pci_suspend), 5355e2a411fSHidetoshi Shimokawa DEVMETHOD(device_resume, fwohci_pci_resume), 5369339321dSHidetoshi Shimokawa DEVMETHOD(device_shutdown, fwohci_pci_shutdown), 5373c60ba66SKatsushi Kobayashi 5383c60ba66SKatsushi Kobayashi /* Bus interface */ 539b180671cSHidetoshi Shimokawa DEVMETHOD(bus_add_child, fwohci_pci_add_child), 5403c60ba66SKatsushi Kobayashi 5414b7ec270SMarius Strobl DEVMETHOD_END 5423c60ba66SKatsushi Kobayashi }; 5433c60ba66SKatsushi Kobayashi 5443c60ba66SKatsushi Kobayashi static driver_t fwohci_driver = { 5453c60ba66SKatsushi Kobayashi "fwohci", 5463c60ba66SKatsushi Kobayashi fwohci_methods, 5473c60ba66SKatsushi Kobayashi sizeof(fwohci_softc_t), 5483c60ba66SKatsushi Kobayashi }; 5493c60ba66SKatsushi Kobayashi 5503c60ba66SKatsushi Kobayashi static devclass_t fwohci_devclass; 5513c60ba66SKatsushi Kobayashi 552b180671cSHidetoshi Shimokawa #ifdef FWOHCI_MODULE 553b180671cSHidetoshi Shimokawa MODULE_DEPEND(fwohci, firewire, 1, 1, 1); 554b180671cSHidetoshi Shimokawa #endif 5553c60ba66SKatsushi Kobayashi DRIVER_MODULE(fwohci, pci, fwohci_driver, fwohci_devclass, 0, 0); 556