1 /*- 2 * Copyright (c) 2003 Hidetoshi Shimokawa 3 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the acknowledgement as bellow: 16 * 17 * This product includes software developed by K. Kobayashi and H. SHimokawa 18 * 19 * 4. The name of the author may not be used to endorse or promote products 20 * derived from this software without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 24 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 25 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 26 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 27 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 28 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 30 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 31 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 32 * POSSIBILITY OF SUCH DAMAGE. 33 * 34 * $FreeBSD: src/sys/dev/firewire/fwohci_pci.c,v 1.60 2007/06/06 14:31:36 simokawa Exp $ 35 */ 36 37 #include <OS.h> 38 #include <KernelExport.h> 39 #include <lock.h> 40 #include <SupportDefs.h> 41 #include <PCI.h> 42 43 #include <stdlib.h> 44 #include <stdio.h> 45 #include <string.h> 46 #include <malloc.h> 47 48 #include "util.h" 49 #include "fwdebug.h" 50 #include "fwglue.h" 51 #include "queue.h" 52 #include "firewire.h" 53 #include "iec13213.h" 54 #include "firewirereg.h" 55 56 #include "fwdma.h" 57 #include "fwohcireg.h" 58 #include "fwohcivar.h" 59 60 #define PCIM_CMD_IOS 0x0001 61 #define PCIM_CMD_MEMEN 0x0002 62 #define PCIM_CMD_BUSMASTEREN 0x0004 63 #define PCIM_CMD_MWRICEN 0x0010 64 #define PCIM_CMD_PERRESPEN 0x0040 65 #define PCIM_CMD_SERRESPEN 0x0100 66 67 extern pci_module_info *gPci; 68 extern pci_info *pciInfo[MAX_CARDS]; 69 extern fwohci_softc_t *gFwohci_softc[MAX_CARDS]; 70 extern struct firewire_softc *gFirewire_softc[MAX_CARDS]; 71 72 status_t 73 fwohci_pci_detach(int index) 74 { 75 fwohci_softc_t *sc = gFwohci_softc[index]; 76 int s; 77 78 s = splfw(); 79 80 fwohci_stop(sc); 81 82 // bus_generic_detach(self); 83 firewire_detach(gFirewire_softc[index]); 84 /* if (sc->fc.bdev) { 85 device_delete_child(self, sc->fc.bdev); 86 sc->fc.bdev = NULL; 87 }*/ 88 89 /* disable interrupts that might have been switched on */ 90 OWRITE(sc, FWOHCI_INTMASKCLR, OHCI_INT_EN); 91 remove_io_interrupt_handler (sc->irq, fwohci_intr, sc); 92 delete_area(sc->regArea); 93 94 fwohci_detach(sc); 95 mtx_destroy(FW_GMTX(&sc->fc)); 96 splx(s); 97 return B_OK; 98 } 99 100 static void 101 fwohci_pci_add_child(int index) 102 { 103 struct fwohci_softc *sc; 104 int err = 0; 105 106 sc = gFwohci_softc[index]; 107 108 /* child = device_add_child(dev, name, unit); 109 if (child == NULL) 110 return (child); 111 112 sc->fc.bdev = child; 113 device_set_ivars(child, (void *)&sc->fc);*/ 114 115 // err = device_probe_and_attach(child); 116 err = firewire_attach(&sc->fc, gFirewire_softc[index]); 117 118 if (err) { 119 device_printf(dev, "firewire_attach failed with err=%d\n", 120 err); 121 fwohci_pci_detach(index); 122 // device_delete_child(dev, child); 123 return; 124 } 125 /* XXX 126 * Clear the bus reset event flag to start transactions even when 127 * interrupt is disabled during the boot process. 128 */ 129 // if (cold) { 130 // int s; 131 // DELAY(250); /* 2 cycles */ 132 // s = splfw(); 133 // fwohci_poll((void *)sc, 0, -1); 134 // splx(s); 135 // } 136 137 } 138 139 status_t 140 fwohci_pci_attach(int index) 141 { 142 fwohci_softc_t *sc = gFwohci_softc[index]; 143 pci_info *info = pciInfo[index]; 144 uint32 olatency, latency, ocache_line, cache_line; 145 uint32 val; 146 147 mtx_init(FW_GMTX(&sc->fc), "firewire", NULL, MTX_DEF); 148 149 val = gPci->read_pci_config(info->bus, info->device, info->function, 150 PCI_command, 2); 151 val |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 152 153 #if 1 /* for broken hardware */ 154 val &= ~PCIM_CMD_MWRICEN; 155 val &= ~(PCIM_CMD_SERRESPEN | PCIM_CMD_PERRESPEN); 156 #endif 157 gPci->write_pci_config(info->bus, info->device, info->function, 158 PCI_command, 2, val); 159 160 /* 161 * Some Sun PCIO-2 FireWire controllers have their intpin register 162 * bogusly set to 0, although it should be 3. Correct that. 163 */ 164 if (info->vendor_id == FW_VENDORID_SUN && info->device_id == (FW_DEVICE_PCIO2FW >> 16) && 165 info->u.h0.interrupt_pin == 0) 166 info->u.h0.interrupt_pin = 3; 167 168 latency = olatency = gPci->read_pci_config(info->bus, info->device, info->function, 169 PCI_latency, 1); 170 #define DEF_LATENCY 0x20 171 if (olatency < DEF_LATENCY) { 172 latency = DEF_LATENCY; 173 gPci->write_pci_config(info->bus, info->device, info->function, 174 PCI_latency, 1, latency); 175 } 176 177 cache_line = ocache_line = gPci->read_pci_config(info->bus, info->device, 178 info->function, PCI_line_size, 1); 179 #define DEF_CACHE_LINE 8 180 if (ocache_line < DEF_CACHE_LINE) { 181 cache_line = DEF_CACHE_LINE; 182 gPci->write_pci_config(info->bus, info->device, info->function, 183 PCI_line_size, 1, cache_line); 184 } 185 TRACE("latency timer %lx -> %lx.\n", olatency, latency); 186 TRACE("cache size %lx -> %lx.\n", ocache_line, cache_line); 187 188 // get IRQ 189 sc->irq = gPci->read_pci_config(info->bus, info->device, info->function, 190 PCI_interrupt_line, 1); 191 if (sc->irq == 0 || sc->irq == 0xff) { 192 ERROR("no IRQ assigned\n"); 193 goto err; 194 } 195 TRACE("IRQ %d\n", sc->irq); 196 197 // map registers into memory 198 // val = gPci->read_pci_config(info->bus, info->device, info->function, 0x14, 4); 199 // val &= PCI_address_memory_32_mask; 200 // TRACE("hardware register address %p\n", (void *) val); 201 TRACE("hardware register address %lx\n", info->u.h0.base_registers[0]); 202 sc->regArea = map_mem(&sc->regAddr, (void *)info->u.h0.base_registers[0], 0x800, 203 B_READ_AREA | B_WRITE_AREA, "fw ohci register"); 204 if (sc->regArea < B_OK) { 205 ERROR("can't map hardware registers\n"); 206 goto err; 207 } 208 TRACE("mapped registers to %p\n", sc->regAddr); 209 210 // setup interrupt handler 211 if (install_io_interrupt_handler(sc->irq, fwohci_intr, 212 sc, 0) < B_OK) { 213 ERROR("can't install interrupt handler\n"); 214 goto err; 215 } 216 217 if (fwohci_init(sc) < B_OK){ 218 219 ERROR("fwohci_init failed"); 220 goto err; 221 } 222 fwohci_pci_add_child(index); 223 return B_OK; 224 err: 225 delete_area(sc->regArea); 226 mtx_destroy(FW_GMTX(&sc->fc)); 227 return B_ERROR; 228 } 229