1139749Simp/*- 2113584Ssimokawa * Copyright (c) 2003 Hidetoshi Shimokawa 3103285Sikob * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 4103285Sikob * All rights reserved. 5103285Sikob * 6103285Sikob * Redistribution and use in source and binary forms, with or without 7103285Sikob * modification, are permitted provided that the following conditions 8103285Sikob * are met: 9103285Sikob * 1. Redistributions of source code must retain the above copyright 10103285Sikob * notice, this list of conditions and the following disclaimer. 11103285Sikob * 2. Redistributions in binary form must reproduce the above copyright 12103285Sikob * notice, this list of conditions and the following disclaimer in the 13103285Sikob * documentation and/or other materials provided with the distribution. 14103285Sikob * 3. All advertising materials mentioning features or use of this software 15103285Sikob * must display the acknowledgement as bellow: 16103285Sikob * 17103285Sikob * This product includes software developed by K. Kobayashi and H. SHimokawa 18103285Sikob * 19103285Sikob * 4. The name of the author may not be used to endorse or promote products 20103285Sikob * derived from this software without specific prior written permission. 21103285Sikob * 22103285Sikob * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23103285Sikob * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24103285Sikob * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25103285Sikob * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26103285Sikob * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27103285Sikob * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28103285Sikob * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29103285Sikob * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30103285Sikob * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31103285Sikob * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32103285Sikob * POSSIBILITY OF SUCH DAMAGE. 33103285Sikob */ 34103285Sikob 35229093Shselasky#include <sys/cdefs.h> 36229093Shselasky__FBSDID("$FreeBSD$"); 37229093Shselasky 38113584Ssimokawa#define BOUNCE_BUFFER_TEST 0 39113584Ssimokawa 40103285Sikob#include <sys/param.h> 41103285Sikob#include <sys/systm.h> 42103285Sikob#include <sys/kernel.h> 43103285Sikob#include <sys/module.h> 44103285Sikob#include <sys/bus.h> 45103285Sikob#include <sys/queue.h> 46103285Sikob#include <machine/bus.h> 47103285Sikob#include <sys/rman.h> 48110195Ssimokawa#include <sys/malloc.h> 49127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 50117126Sscottl#include <sys/lock.h> 51117126Sscottl#include <sys/mutex.h> 52117732Ssimokawa#endif 53103285Sikob#include <machine/resource.h> 54103285Sikob 55127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 56117067Ssimokawa#include <machine/clock.h> /* for DELAY() */ 57117067Ssimokawa#endif 58117067Ssimokawa 59127468Ssimokawa#ifdef __DragonFly__ 60127468Ssimokawa#include <bus/pci/pcivar.h> 61127468Ssimokawa#include <bus/pci/pcireg.h> 62127468Ssimokawa 63127468Ssimokawa#include "firewire.h" 64127468Ssimokawa#include "firewirereg.h" 65127468Ssimokawa 66127468Ssimokawa#include "fwdma.h" 67127468Ssimokawa#include "fwohcireg.h" 68127468Ssimokawa#include "fwohcivar.h" 69127468Ssimokawa#else 70119290Ssimokawa#if __FreeBSD_version < 500000 71119290Ssimokawa#include <pci/pcivar.h> 72119290Ssimokawa#include <pci/pcireg.h> 73119290Ssimokawa#else 74119277Simp#include <dev/pci/pcivar.h> 75119277Simp#include <dev/pci/pcireg.h> 76119290Ssimokawa#endif 77103285Sikob 78103285Sikob#include <dev/firewire/firewire.h> 79103285Sikob#include <dev/firewire/firewirereg.h> 80103285Sikob 81113584Ssimokawa#include <dev/firewire/fwdma.h> 82103285Sikob#include <dev/firewire/fwohcireg.h> 83103285Sikob#include <dev/firewire/fwohcivar.h> 84127468Ssimokawa#endif 85103285Sikob 86103285Sikobstatic int fwohci_pci_attach(device_t self); 87103285Sikobstatic int fwohci_pci_detach(device_t self); 88103285Sikob 89103285Sikob/* 90103285Sikob * The probe routine. 91103285Sikob */ 92103285Sikobstatic int 93103285Sikobfwohci_pci_probe( device_t dev ) 94103285Sikob{ 95103285Sikob#if 1 96129585Sdfr uint32_t id; 97108504Ssimokawa 98111076Ssimokawa id = pci_get_devid(dev); 99132283Ssimokawa if (id == (FW_VENDORID_NATSEMI | FW_DEVICE_CS4210)) { 100132283Ssimokawa device_set_desc(dev, "National Semiconductor CS4210"); 101143161Simp return BUS_PROBE_DEFAULT; 102132283Ssimokawa } 103108504Ssimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD861)) { 104103285Sikob device_set_desc(dev, "NEC uPD72861"); 105143161Simp return BUS_PROBE_DEFAULT; 106103285Sikob } 107111075Ssimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD871)) { 108111075Ssimokawa device_set_desc(dev, "NEC uPD72871/2"); 109143161Simp return BUS_PROBE_DEFAULT; 110111075Ssimokawa } 111113957Ssimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72870)) { 112113957Ssimokawa device_set_desc(dev, "NEC uPD72870"); 113143161Simp return BUS_PROBE_DEFAULT; 114113957Ssimokawa } 115125239Ssimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72873)) { 116125239Ssimokawa device_set_desc(dev, "NEC uPD72873"); 117143161Simp return BUS_PROBE_DEFAULT; 118125239Ssimokawa } 119113957Ssimokawa if (id == (FW_VENDORID_NEC | FW_DEVICE_UPD72874)) { 120113957Ssimokawa device_set_desc(dev, "NEC uPD72874"); 121143161Simp return BUS_PROBE_DEFAULT; 122113957Ssimokawa } 123132283Ssimokawa if (id == (FW_VENDORID_SIS | FW_DEVICE_7007)) { 124132283Ssimokawa /* It has no real identifier, using device id. */ 125132283Ssimokawa device_set_desc(dev, "SiS 7007"); 126143161Simp return BUS_PROBE_DEFAULT; 127132283Ssimokawa } 128108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB22)) { 129103285Sikob device_set_desc(dev, "Texas Instruments TSB12LV22"); 130143161Simp return BUS_PROBE_DEFAULT; 131103285Sikob } 132108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB23)) { 133103285Sikob device_set_desc(dev, "Texas Instruments TSB12LV23"); 134143161Simp return BUS_PROBE_DEFAULT; 135103285Sikob } 136108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB26)) { 137103285Sikob device_set_desc(dev, "Texas Instruments TSB12LV26"); 138143161Simp return BUS_PROBE_DEFAULT; 139103285Sikob } 140108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43)) { 141103285Sikob device_set_desc(dev, "Texas Instruments TSB43AA22"); 142143161Simp return BUS_PROBE_DEFAULT; 143103285Sikob } 144108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43A)) { 145108504Ssimokawa device_set_desc(dev, "Texas Instruments TSB43AB22/A"); 146143161Simp return BUS_PROBE_DEFAULT; 147108504Ssimokawa } 148132283Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB21)) { 149132283Ssimokawa device_set_desc(dev, "Texas Instruments TSB43AB21/A/AI/A-EP"); 150143161Simp return BUS_PROBE_DEFAULT; 151132283Ssimokawa } 152113957Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB43AB23)) { 153113957Ssimokawa device_set_desc(dev, "Texas Instruments TSB43AB23"); 154143161Simp return BUS_PROBE_DEFAULT; 155113957Ssimokawa } 156115806Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TITSB82AA2)) { 157115806Ssimokawa device_set_desc(dev, "Texas Instruments TSB82AA2"); 158143161Simp return BUS_PROBE_DEFAULT; 159115806Ssimokawa } 160108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4450)) { 161108504Ssimokawa device_set_desc(dev, "Texas Instruments PCI4450"); 162143161Simp return BUS_PROBE_DEFAULT; 163108504Ssimokawa } 164108504Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4410A)) { 165108504Ssimokawa device_set_desc(dev, "Texas Instruments PCI4410A"); 166143161Simp return BUS_PROBE_DEFAULT; 167108504Ssimokawa } 168113957Ssimokawa if (id == (FW_VENDORID_TI | FW_DEVICE_TIPCI4451)) { 169113957Ssimokawa device_set_desc(dev, "Texas Instruments PCI4451"); 170143161Simp return BUS_PROBE_DEFAULT; 171113957Ssimokawa } 172133116Ssimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD1947)) { 173159535Simp device_printf(dev, "Sony i.LINK (CXD1947) not supported\n"); 174148106Simp return ENXIO; 175103285Sikob } 176133116Ssimokawa if (id == (FW_VENDORID_SONY | FW_DEVICE_CXD3222)) { 177133116Ssimokawa device_set_desc(dev, "Sony i.LINK (CXD3222)"); 178143161Simp return BUS_PROBE_DEFAULT; 179133116Ssimokawa } 180108504Ssimokawa if (id == (FW_VENDORID_VIA | FW_DEVICE_VT6306)) { 181133116Ssimokawa device_set_desc(dev, "VIA Fire II (VT6306)"); 182143161Simp return BUS_PROBE_DEFAULT; 183103285Sikob } 184113957Ssimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C551)) { 185113957Ssimokawa device_set_desc(dev, "Ricoh R5C551"); 186143161Simp return BUS_PROBE_DEFAULT; 187113957Ssimokawa } 188108504Ssimokawa if (id == (FW_VENDORID_RICOH | FW_DEVICE_R5C552)) { 189103285Sikob device_set_desc(dev, "Ricoh R5C552"); 190143161Simp return BUS_PROBE_DEFAULT; 191103285Sikob } 192108504Ssimokawa if (id == (FW_VENDORID_APPLE | FW_DEVICE_PANGEA)) { 193103485Sikob device_set_desc(dev, "Apple Pangea"); 194143161Simp return BUS_PROBE_DEFAULT; 195103485Sikob } 196108504Ssimokawa if (id == (FW_VENDORID_APPLE | FW_DEVICE_UNINORTH)) { 197103485Sikob device_set_desc(dev, "Apple UniNorth"); 198143161Simp return BUS_PROBE_DEFAULT; 199103485Sikob } 200108504Ssimokawa if (id == (FW_VENDORID_LUCENT | FW_DEVICE_FW322)) { 201103485Sikob device_set_desc(dev, "Lucent FW322/323"); 202143161Simp return BUS_PROBE_DEFAULT; 203103485Sikob } 204132283Ssimokawa if (id == (FW_VENDORID_INTEL | FW_DEVICE_82372FB)) { 205132283Ssimokawa device_set_desc(dev, "Intel 82372FB"); 206143161Simp return BUS_PROBE_DEFAULT; 207132283Ssimokawa } 208132283Ssimokawa if (id == (FW_VENDORID_ADAPTEC | FW_DEVICE_AIC5800)) { 209132283Ssimokawa device_set_desc(dev, "Adaptec AHA-894x/AIC-5800"); 210143161Simp return BUS_PROBE_DEFAULT; 211132283Ssimokawa } 212146439Smarius if (id == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW)) { 213146439Smarius device_set_desc(dev, "Sun PCIO-2"); 214146439Smarius return BUS_PROBE_DEFAULT; 215146439Smarius } 216103285Sikob#endif 217103285Sikob if (pci_get_class(dev) == PCIC_SERIALBUS 218103285Sikob && pci_get_subclass(dev) == PCIS_SERIALBUS_FW 219103285Sikob && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { 220131398Sjhb if (bootverbose) 221131398Sjhb device_printf(dev, "vendor=%x, dev=%x\n", 222131398Sjhb pci_get_vendor(dev), pci_get_device(dev)); 223103285Sikob device_set_desc(dev, "1394 Open Host Controller Interface"); 224143161Simp return BUS_PROBE_DEFAULT; 225103285Sikob } 226103285Sikob 227103285Sikob return ENXIO; 228103285Sikob} 229103285Sikob 230127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 231103285Sikobstatic void 232103285Sikobfwohci_dummy_intr(void *arg) 233103285Sikob{ 234103285Sikob /* XXX do nothing */ 235103285Sikob} 236103285Sikob#endif 237103285Sikob 238103285Sikobstatic int 239108642Ssimokawafwohci_pci_init(device_t self) 240103285Sikob{ 241113584Ssimokawa int olatency, latency, ocache_line, cache_line; 242129585Sdfr uint16_t cmd; 243103285Sikob 244103285Sikob cmd = pci_read_config(self, PCIR_COMMAND, 2); 245254306Sscottl cmd |= PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 246139759Ssimokawa#if 1 /* for broken hardware */ 247112522Ssimokawa cmd &= ~PCIM_CMD_MWRICEN; 248112522Ssimokawa#endif 249103285Sikob pci_write_config(self, PCIR_COMMAND, cmd, 2); 250103285Sikob 251146439Smarius /* 252146439Smarius * Some Sun PCIO-2 FireWire controllers have their intpin register 253146439Smarius * bogusly set to 0, although it should be 3. Correct that. 254146439Smarius */ 255146439Smarius if (pci_get_devid(self) == (FW_VENDORID_SUN | FW_DEVICE_PCIO2FW) && 256146439Smarius pci_get_intpin(self) == 0) 257146439Smarius pci_set_intpin(self, 3); 258146439Smarius 259113584Ssimokawa latency = olatency = pci_read_config(self, PCIR_LATTIMER, 1); 260112522Ssimokawa#define DEF_LATENCY 0x20 261113584Ssimokawa if (olatency < DEF_LATENCY) { 262103285Sikob latency = DEF_LATENCY; 263113584Ssimokawa pci_write_config(self, PCIR_LATTIMER, latency, 1); 264103285Sikob } 265108642Ssimokawa 266113584Ssimokawa cache_line = ocache_line = pci_read_config(self, PCIR_CACHELNSZ, 1); 267113584Ssimokawa#define DEF_CACHE_LINE 8 268113584Ssimokawa if (ocache_line < DEF_CACHE_LINE) { 269113584Ssimokawa cache_line = DEF_CACHE_LINE; 270113584Ssimokawa pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1); 271113584Ssimokawa } 272113584Ssimokawa 273113584Ssimokawa if (firewire_debug) { 274113584Ssimokawa device_printf(self, "latency timer %d -> %d.\n", 275113584Ssimokawa olatency, latency); 276113584Ssimokawa device_printf(self, "cache size %d -> %d.\n", 277113584Ssimokawa ocache_line, cache_line); 278113584Ssimokawa } 279113584Ssimokawa 280108642Ssimokawa return 0; 281108642Ssimokawa} 282108642Ssimokawa 283108642Ssimokawastatic int 284108642Ssimokawafwohci_pci_attach(device_t self) 285108642Ssimokawa{ 286108642Ssimokawa fwohci_softc_t *sc = device_get_softc(self); 287108642Ssimokawa int err; 288125238Ssimokawa int rid; 289127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 290108642Ssimokawa int intr; 291108642Ssimokawa /* For the moment, put in a message stating what is wrong */ 292108642Ssimokawa intr = pci_read_config(self, PCIR_INTLINE, 1); 293108642Ssimokawa if (intr == 0 || intr == 255) { 294108642Ssimokawa device_printf(self, "Invalid irq %d\n", intr); 295108642Ssimokawa#ifdef __i386__ 296108642Ssimokawa device_printf(self, "Please switch PNP-OS to 'No' in BIOS\n"); 297108642Ssimokawa#endif 298108642Ssimokawa } 299108642Ssimokawa#endif 300108642Ssimokawa 301132432Ssimokawa#if 0 302113584Ssimokawa if (bootverbose) 303113584Ssimokawa firewire_debug = bootverbose; 304132432Ssimokawa#endif 305113584Ssimokawa 306170374Ssimokawa mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF); 307108642Ssimokawa fwohci_pci_init(self); 308108642Ssimokawa 309103285Sikob rid = PCI_CBMEM; 310127468Ssimokawa#if __FreeBSD_version >= 502109 311127135Snjl sc->bsr = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid, RF_ACTIVE); 312127468Ssimokawa#else 313127468Ssimokawa sc->bsr = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 314127468Ssimokawa 0, ~0, 1, RF_ACTIVE); 315127468Ssimokawa#endif 316103285Sikob if (!sc->bsr) { 317103285Sikob device_printf(self, "Could not map memory\n"); 318103285Sikob return ENXIO; 319103285Sikob } 320103285Sikob 321103285Sikob sc->bst = rman_get_bustag(sc->bsr); 322103285Sikob sc->bsh = rman_get_bushandle(sc->bsr); 323103285Sikob 324103285Sikob rid = 0; 325127468Ssimokawa#if __FreeBSD_version >= 502109 326127135Snjl sc->irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid, 327103285Sikob RF_SHAREABLE | RF_ACTIVE); 328127468Ssimokawa#else 329127468Ssimokawa sc->irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1, 330127468Ssimokawa RF_SHAREABLE | RF_ACTIVE); 331127468Ssimokawa#endif 332103285Sikob if (sc->irq_res == NULL) { 333103285Sikob device_printf(self, "Could not allocate irq\n"); 334103285Sikob fwohci_pci_detach(self); 335103285Sikob return ENXIO; 336103285Sikob } 337103285Sikob 338187993Ssbruno err = bus_setup_intr(self, sc->irq_res, 339187993Ssbruno INTR_TYPE_NET | INTR_MPSAFE, 340187993Ssbruno NULL, (driver_intr_t *) fwohci_intr, 341187993Ssbruno sc, &sc->ih); 342103285Sikob 343127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 344103285Sikob /* XXX splcam() should mask this irq for sbp.c*/ 345103285Sikob err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_CAM, 346103285Sikob (driver_intr_t *) fwohci_dummy_intr, sc, &sc->ih_cam); 347121506Ssimokawa /* XXX splbio() should mask this irq for physio()/fwmem_strategy() */ 348121506Ssimokawa err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_BIO, 349121506Ssimokawa (driver_intr_t *) fwohci_dummy_intr, sc, &sc->ih_bio); 350103285Sikob#endif 351103285Sikob if (err) { 352103285Sikob device_printf(self, "Could not setup irq, %d\n", err); 353103285Sikob fwohci_pci_detach(self); 354103285Sikob return ENXIO; 355103285Sikob } 356103285Sikob 357166165Smarius err = bus_dma_tag_create( 358166165Smarius#if defined(__FreeBSD__) && __FreeBSD_version >= 700020 359166165Smarius /*parent*/bus_get_dma_tag(self), 360166165Smarius#else 361166165Smarius /*parent*/NULL, 362166165Smarius#endif 363166165Smarius /*alignment*/1, 364113584Ssimokawa /*boundary*/0, 365113584Ssimokawa#if BOUNCE_BUFFER_TEST 366113584Ssimokawa /*lowaddr*/BUS_SPACE_MAXADDR_24BIT, 367113584Ssimokawa#else 368113584Ssimokawa /*lowaddr*/BUS_SPACE_MAXADDR_32BIT, 369113584Ssimokawa#endif 370113584Ssimokawa /*highaddr*/BUS_SPACE_MAXADDR, 371113584Ssimokawa /*filter*/NULL, /*filterarg*/NULL, 372113584Ssimokawa /*maxsize*/0x100000, 373113584Ssimokawa /*nsegments*/0x20, 374113584Ssimokawa /*maxsegsz*/0x8000, 375113584Ssimokawa /*flags*/BUS_DMA_ALLOCNOW, 376127468Ssimokawa#if defined(__FreeBSD__) && __FreeBSD_version >= 501102 377117126Sscottl /*lockfunc*/busdma_lock_mutex, 378170374Ssimokawa /*lockarg*/FW_GMTX(&sc->fc), 379117228Ssimokawa#endif 380117228Ssimokawa &sc->fc.dmat); 381113584Ssimokawa if (err != 0) { 382113584Ssimokawa printf("fwohci_pci_attach: Could not allocate DMA tag " 383113584Ssimokawa "- error %d\n", err); 384113584Ssimokawa return (ENOMEM); 385113584Ssimokawa } 386113584Ssimokawa 387103285Sikob err = fwohci_init(sc, self); 388103285Sikob 389124877Ssimokawa if (err) { 390124877Ssimokawa device_printf(self, "fwohci_init failed with err=%d\n", err); 391124877Ssimokawa fwohci_pci_detach(self); 392124877Ssimokawa return EIO; 393124877Ssimokawa } 394103285Sikob 395125238Ssimokawa /* probe and attach a child device(firewire) */ 396125238Ssimokawa bus_generic_probe(self); 397125238Ssimokawa bus_generic_attach(self); 398124877Ssimokawa 399103285Sikob return 0; 400103285Sikob} 401103285Sikob 402103285Sikobstatic int 403103285Sikobfwohci_pci_detach(device_t self) 404103285Sikob{ 405103285Sikob fwohci_softc_t *sc = device_get_softc(self); 406103285Sikob int s; 407103285Sikob 408103285Sikob 409103285Sikob s = splfw(); 410108530Ssimokawa 411118416Ssimokawa if (sc->bsr) 412118416Ssimokawa fwohci_stop(sc, self); 413118416Ssimokawa 414103285Sikob bus_generic_detach(self); 415118416Ssimokawa if (sc->fc.bdev) { 416118416Ssimokawa device_delete_child(self, sc->fc.bdev); 417118416Ssimokawa sc->fc.bdev = NULL; 418118416Ssimokawa } 419103285Sikob 420103285Sikob /* disable interrupts that might have been switched on */ 421103285Sikob if (sc->bst && sc->bsh) 422103285Sikob bus_space_write_4(sc->bst, sc->bsh, 423103285Sikob FWOHCI_INTMASKCLR, OHCI_INT_EN); 424103285Sikob 425103285Sikob if (sc->irq_res) { 426168099Ssimokawa int err; 427168099Ssimokawa if (sc->ih) { 428168099Ssimokawa err = bus_teardown_intr(self, sc->irq_res, sc->ih); 429168099Ssimokawa if (err) 430168099Ssimokawa device_printf(self, 431168099Ssimokawa "Could not tear down irq, %d\n", err); 432127468Ssimokawa#if defined(__DragonFly__) || __FreeBSD_version < 500000 433168099Ssimokawa bus_teardown_intr(self, sc->irq_res, sc->ih_cam); 434168099Ssimokawa bus_teardown_intr(self, sc->irq_res, sc->ih_bio); 435103285Sikob#endif 436168099Ssimokawa sc->ih = NULL; 437168099Ssimokawa } 438103285Sikob bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); 439103285Sikob sc->irq_res = NULL; 440103285Sikob } 441103285Sikob 442103285Sikob if (sc->bsr) { 443103285Sikob bus_release_resource(self, SYS_RES_MEMORY,PCI_CBMEM,sc->bsr); 444103285Sikob sc->bsr = NULL; 445103285Sikob sc->bst = 0; 446103285Sikob sc->bsh = 0; 447103285Sikob } 448108527Ssimokawa 449108527Ssimokawa fwohci_detach(sc, self); 450170374Ssimokawa mtx_destroy(FW_GMTX(&sc->fc)); 451103285Sikob splx(s); 452103285Sikob 453103285Sikob return 0; 454103285Sikob} 455103285Sikob 456106809Ssimokawastatic int 457106809Ssimokawafwohci_pci_suspend(device_t dev) 458106809Ssimokawa{ 459116978Ssimokawa fwohci_softc_t *sc = device_get_softc(dev); 460108705Ssimokawa int err; 461108705Ssimokawa 462108642Ssimokawa device_printf(dev, "fwohci_pci_suspend\n"); 463108642Ssimokawa err = bus_generic_suspend(dev); 464108642Ssimokawa if (err) 465108642Ssimokawa return err; 466116978Ssimokawa fwohci_stop(sc, dev); 467106809Ssimokawa return 0; 468106809Ssimokawa} 469106809Ssimokawa 470106809Ssimokawastatic int 471106809Ssimokawafwohci_pci_resume(device_t dev) 472106809Ssimokawa{ 473108530Ssimokawa fwohci_softc_t *sc = device_get_softc(dev); 474108530Ssimokawa 475108642Ssimokawa fwohci_pci_init(dev); 476108642Ssimokawa fwohci_resume(sc, dev); 477106809Ssimokawa return 0; 478106809Ssimokawa} 479106809Ssimokawa 480108642Ssimokawastatic int 481108642Ssimokawafwohci_pci_shutdown(device_t dev) 482108642Ssimokawa{ 483108642Ssimokawa fwohci_softc_t *sc = device_get_softc(dev); 484108642Ssimokawa 485110145Ssimokawa bus_generic_shutdown(dev); 486110145Ssimokawa fwohci_stop(sc, dev); 487108642Ssimokawa return 0; 488108642Ssimokawa} 489108642Ssimokawa 490125238Ssimokawastatic device_t 491212413Savgfwohci_pci_add_child(device_t dev, u_int order, const char *name, int unit) 492125238Ssimokawa{ 493125238Ssimokawa struct fwohci_softc *sc; 494125238Ssimokawa device_t child; 495170374Ssimokawa int err = 0; 496125238Ssimokawa 497125238Ssimokawa sc = (struct fwohci_softc *)device_get_softc(dev); 498125238Ssimokawa child = device_add_child(dev, name, unit); 499125238Ssimokawa if (child == NULL) 500125238Ssimokawa return (child); 501125238Ssimokawa 502125238Ssimokawa sc->fc.bdev = child; 503125238Ssimokawa device_set_ivars(child, (void *)&sc->fc); 504125238Ssimokawa 505125238Ssimokawa err = device_probe_and_attach(child); 506125238Ssimokawa if (err) { 507125238Ssimokawa device_printf(dev, "probe_and_attach failed with err=%d\n", 508125238Ssimokawa err); 509125238Ssimokawa fwohci_pci_detach(dev); 510125238Ssimokawa device_delete_child(dev, child); 511125238Ssimokawa return NULL; 512125238Ssimokawa } 513125238Ssimokawa 514125238Ssimokawa /* XXX 515125238Ssimokawa * Clear the bus reset event flag to start transactions even when 516125238Ssimokawa * interrupt is disabled during the boot process. 517125238Ssimokawa */ 518167686Ssimokawa if (cold) { 519170374Ssimokawa int s; 520167686Ssimokawa DELAY(250); /* 2 cycles */ 521167686Ssimokawa s = splfw(); 522167686Ssimokawa fwohci_poll((void *)sc, 0, -1); 523167686Ssimokawa splx(s); 524167686Ssimokawa } 525125238Ssimokawa 526125238Ssimokawa return (child); 527125238Ssimokawa} 528125238Ssimokawa 529103285Sikobstatic device_method_t fwohci_methods[] = { 530103285Sikob /* Device interface */ 531103285Sikob DEVMETHOD(device_probe, fwohci_pci_probe), 532103285Sikob DEVMETHOD(device_attach, fwohci_pci_attach), 533103285Sikob DEVMETHOD(device_detach, fwohci_pci_detach), 534106809Ssimokawa DEVMETHOD(device_suspend, fwohci_pci_suspend), 535106809Ssimokawa DEVMETHOD(device_resume, fwohci_pci_resume), 536108642Ssimokawa DEVMETHOD(device_shutdown, fwohci_pci_shutdown), 537103285Sikob 538103285Sikob /* Bus interface */ 539125238Ssimokawa DEVMETHOD(bus_add_child, fwohci_pci_add_child), 540103285Sikob 541229093Shselasky DEVMETHOD_END 542103285Sikob}; 543103285Sikob 544103285Sikobstatic driver_t fwohci_driver = { 545103285Sikob "fwohci", 546103285Sikob fwohci_methods, 547103285Sikob sizeof(fwohci_softc_t), 548103285Sikob}; 549103285Sikob 550103285Sikobstatic devclass_t fwohci_devclass; 551103285Sikob 552127468Ssimokawa#ifdef FWOHCI_MODULE 553125238SsimokawaMODULE_DEPEND(fwohci, firewire, 1, 1, 1); 554125238Ssimokawa#endif 555103285SikobDRIVER_MODULE(fwohci, pci, fwohci_driver, fwohci_devclass, 0, 0); 556