1 1.46 sevan /* $NetBSD: fwohci_pci.c,v 1.46 2018/03/31 17:54:53 sevan Exp $ */ 2 1.5 enami 3 1.1 matt /*- 4 1.1 matt * Copyright (c) 2000 The NetBSD Foundation, Inc. 5 1.1 matt * All rights reserved. 6 1.1 matt * 7 1.1 matt * This code is derived from software contributed to The NetBSD Foundation 8 1.1 matt * by Matt Thomas of 3am Software Foundry. 9 1.1 matt * 10 1.1 matt * Redistribution and use in source and binary forms, with or without 11 1.1 matt * modification, are permitted provided that the following conditions 12 1.1 matt * are met: 13 1.1 matt * 1. Redistributions of source code must retain the above copyright 14 1.1 matt * notice, this list of conditions and the following disclaimer. 15 1.1 matt * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 matt * notice, this list of conditions and the following disclaimer in the 17 1.1 matt * documentation and/or other materials provided with the distribution. 18 1.1 matt * 19 1.1 matt * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 matt * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 matt * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 matt * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 matt * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 matt * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 matt * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 matt * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 matt * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 matt * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 matt * POSSIBILITY OF SUCH DAMAGE. 30 1.1 matt */ 31 1.11 lukem 32 1.11 lukem #include <sys/cdefs.h> 33 1.46 sevan __KERNEL_RCSID(0, "$NetBSD: fwohci_pci.c,v 1.46 2018/03/31 17:54:53 sevan Exp $"); 34 1.1 matt 35 1.1 matt #include <sys/param.h> 36 1.37 kiyohara #include <sys/bus.h> 37 1.1 matt #include <sys/device.h> 38 1.37 kiyohara #include <sys/intr.h> 39 1.17 haya #include <sys/select.h> 40 1.37 kiyohara #include <sys/socket.h> 41 1.37 kiyohara #include <sys/systm.h> 42 1.1 matt 43 1.37 kiyohara #include <dev/pci/pcidevs.h> 44 1.1 matt #include <dev/pci/pcireg.h> 45 1.1 matt #include <dev/pci/pcivar.h> 46 1.22 kiyohara #include <dev/ieee1394/firewire.h> 47 1.22 kiyohara #include <dev/ieee1394/firewirereg.h> 48 1.22 kiyohara #include <dev/ieee1394/fwdma.h> 49 1.1 matt #include <dev/ieee1394/fwohcireg.h> 50 1.1 matt #include <dev/ieee1394/fwohcivar.h> 51 1.1 matt 52 1.1 matt struct fwohci_pci_softc { 53 1.1 matt struct fwohci_softc psc_sc; 54 1.27 kiyohara 55 1.1 matt pci_chipset_tag_t psc_pc; 56 1.27 kiyohara pcitag_t psc_tag; 57 1.27 kiyohara 58 1.1 matt void *psc_ih; 59 1.1 matt }; 60 1.1 matt 61 1.33 cegger static int fwohci_pci_match(device_t, cfdata_t, void *); 62 1.31 kiyohara static void fwohci_pci_attach(device_t, device_t, void *); 63 1.38 kiyohara static int fwohci_pci_detach(device_t, int); 64 1.28 jmcneill 65 1.36 dyoung static bool fwohci_pci_suspend(device_t, const pmf_qual_t *); 66 1.36 dyoung static bool fwohci_pci_resume(device_t, const pmf_qual_t *); 67 1.1 matt 68 1.31 kiyohara CFATTACH_DECL_NEW(fwohci_pci, sizeof(struct fwohci_pci_softc), 69 1.38 kiyohara fwohci_pci_match, fwohci_pci_attach, fwohci_pci_detach, NULL); 70 1.1 matt 71 1.1 matt static int 72 1.43 msaitoh fwohci_pci_match(device_t parent, cfdata_t match, void *aux) 73 1.1 matt { 74 1.7 enami struct pci_attach_args *pa = (struct pci_attach_args *) aux; 75 1.1 matt 76 1.35 macallan /* 77 1.35 macallan * XXX 78 1.46 sevan * UniNorth Firewire controller commonly found in Pismo G3 PowerBooks, 79 1.46 sevan * G4 Titanium PowerBooks and some iMac G3s, hang the system 80 1.35 macallan * when trying to discover devices - don't attach to those for now 81 1.46 sevan * until someone with the right hardware can investigate. 82 1.46 sevan * These controllers are based on the Ti TSB41AB1 chipset. 83 1.35 macallan */ 84 1.35 macallan if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_APPLE) && 85 1.45 sevan (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_APPLE_UNINORTH_FW)) 86 1.43 msaitoh return 0; 87 1.7 enami if (PCI_CLASS(pa->pa_class) == PCI_CLASS_SERIALBUS && 88 1.7 enami PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_SERIALBUS_FIREWIRE && 89 1.7 enami PCI_INTERFACE(pa->pa_class) == PCI_INTERFACE_OHCI) 90 1.7 enami return 1; 91 1.21 perry 92 1.7 enami return 0; 93 1.1 matt } 94 1.1 matt 95 1.1 matt static void 96 1.31 kiyohara fwohci_pci_attach(device_t parent, device_t self, void *aux) 97 1.1 matt { 98 1.7 enami struct pci_attach_args *pa = (struct pci_attach_args *) aux; 99 1.31 kiyohara struct fwohci_pci_softc *psc = device_private(self); 100 1.1 matt char const *intrstr; 101 1.1 matt pci_intr_handle_t ih; 102 1.39 kiyohara uint32_t csr; 103 1.42 christos char intrbuf[PCI_INTRSTR_LEN]; 104 1.1 matt 105 1.40 drochner pci_aprint_devinfo(pa, "IEEE 1394 Controller"); 106 1.1 matt 107 1.41 riastrad fwohci_init(&psc->psc_sc); 108 1.41 riastrad 109 1.31 kiyohara psc->psc_sc.fc.dev = self; 110 1.22 kiyohara psc->psc_sc.fc.dmat = pa->pa_dmat; 111 1.1 matt psc->psc_pc = pa->pa_pc; 112 1.27 kiyohara psc->psc_tag = pa->pa_tag; 113 1.1 matt 114 1.7 enami /* Map I/O registers */ 115 1.7 enami if (pci_mapreg_map(pa, PCI_OHCI_MAP_REGISTER, PCI_MAPREG_TYPE_MEM, 0, 116 1.43 msaitoh &psc->psc_sc.bst, &psc->psc_sc.bsh, NULL, &psc->psc_sc.bssize)) { 117 1.31 kiyohara aprint_error_dev(self, "can't map OHCI register space\n"); 118 1.28 jmcneill goto fail; 119 1.7 enami } 120 1.7 enami 121 1.7 enami /* Disable interrupts, so we don't get any spurious ones. */ 122 1.37 kiyohara OWRITE(&psc->psc_sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 123 1.7 enami 124 1.7 enami /* Enable the device. */ 125 1.7 enami csr = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 126 1.39 kiyohara csr |= PCI_COMMAND_MASTER_ENABLE | PCI_COMMAND_MEM_ENABLE; 127 1.39 kiyohara pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, csr); 128 1.39 kiyohara 129 1.39 kiyohara /* 130 1.39 kiyohara * Some Sun FireWire controllers have their intpin register 131 1.39 kiyohara * bogusly set to 0, although it should be 3. Correct that. 132 1.39 kiyohara */ 133 1.39 kiyohara if ((PCI_VENDOR(pa->pa_id) == PCI_VENDOR_SUN) && 134 1.39 kiyohara (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_SUN_FIREWIRE)) 135 1.39 kiyohara if (pa->pa_intrpin == 0) 136 1.39 kiyohara pa->pa_intrpin = 3; 137 1.8 enami 138 1.1 matt /* Map and establish the interrupt. */ 139 1.6 sommerfe if (pci_intr_map(pa, &ih)) { 140 1.31 kiyohara aprint_error_dev(self, "couldn't map interrupt\n"); 141 1.28 jmcneill goto fail; 142 1.1 matt } 143 1.42 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 144 1.44 msaitoh psc->psc_ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_BIO, 145 1.44 msaitoh fwohci_intr, &psc->psc_sc, device_xname(self)); 146 1.1 matt if (psc->psc_ih == NULL) { 147 1.31 kiyohara aprint_error_dev(self, "couldn't establish interrupt"); 148 1.1 matt if (intrstr != NULL) 149 1.31 kiyohara aprint_error(" at %s", intrstr); 150 1.31 kiyohara aprint_error("\n"); 151 1.28 jmcneill goto fail; 152 1.1 matt } 153 1.31 kiyohara aprint_normal_dev(self, "interrupting at %s\n", intrstr); 154 1.1 matt 155 1.41 riastrad if (fwohci_attach(&psc->psc_sc) != 0) 156 1.41 riastrad goto fail; 157 1.41 riastrad 158 1.28 jmcneill if (!pmf_device_register(self, fwohci_pci_suspend, fwohci_pci_resume)) 159 1.28 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 160 1.27 kiyohara 161 1.28 jmcneill return; 162 1.28 jmcneill 163 1.28 jmcneill fail: 164 1.28 jmcneill /* In the event that we fail to attach, register a null pnp handler */ 165 1.28 jmcneill if (!pmf_device_register(self, NULL, NULL)) 166 1.28 jmcneill aprint_error_dev(self, "couldn't establish power handler\n"); 167 1.28 jmcneill 168 1.28 jmcneill return; 169 1.1 matt } 170 1.27 kiyohara 171 1.38 kiyohara static int 172 1.38 kiyohara fwohci_pci_detach(device_t self, int flags) 173 1.38 kiyohara { 174 1.38 kiyohara struct fwohci_pci_softc *psc = device_private(self); 175 1.38 kiyohara int rv; 176 1.38 kiyohara 177 1.38 kiyohara pmf_device_deregister(self); 178 1.38 kiyohara rv = fwohci_detach(&psc->psc_sc, flags); 179 1.38 kiyohara if (rv) 180 1.38 kiyohara return rv; 181 1.38 kiyohara 182 1.38 kiyohara if (psc->psc_ih != NULL) { 183 1.38 kiyohara pci_intr_disestablish(psc->psc_pc, psc->psc_ih); 184 1.38 kiyohara psc->psc_ih = NULL; 185 1.38 kiyohara } 186 1.38 kiyohara if (psc->psc_sc.bssize) { 187 1.38 kiyohara bus_space_unmap(psc->psc_sc.bst, psc->psc_sc.bsh, 188 1.38 kiyohara psc->psc_sc.bssize); 189 1.38 kiyohara psc->psc_sc.bssize = 0; 190 1.38 kiyohara } 191 1.38 kiyohara return 0; 192 1.38 kiyohara } 193 1.38 kiyohara 194 1.28 jmcneill static bool 195 1.36 dyoung fwohci_pci_suspend(device_t dv, const pmf_qual_t *qual) 196 1.27 kiyohara { 197 1.28 jmcneill struct fwohci_pci_softc *psc = device_private(dv); 198 1.28 jmcneill int s; 199 1.27 kiyohara 200 1.28 jmcneill s = splbio(); 201 1.37 kiyohara fwohci_stop(&psc->psc_sc); 202 1.28 jmcneill splx(s); 203 1.28 jmcneill 204 1.28 jmcneill return true; 205 1.27 kiyohara } 206 1.27 kiyohara 207 1.28 jmcneill static bool 208 1.36 dyoung fwohci_pci_resume(device_t dv, const pmf_qual_t *qual) 209 1.27 kiyohara { 210 1.28 jmcneill struct fwohci_pci_softc *psc = device_private(dv); 211 1.27 kiyohara int s; 212 1.27 kiyohara 213 1.27 kiyohara s = splbio(); 214 1.37 kiyohara fwohci_resume(&psc->psc_sc); 215 1.27 kiyohara splx(s); 216 1.28 jmcneill 217 1.28 jmcneill return true; 218 1.27 kiyohara } 219