1 /* 2 * Copyright (c) 1998-2002 Katsushi Kobayashi and Hidetoshi Shimokawa 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 3. All advertising materials mentioning features or use of this software 14 * must display the acknowledgement as bellow: 15 * 16 * This product includes software developed by K. Kobayashi and H. SHimokawa 17 * 18 * 4. The name of the author may not be used to endorse or promote products 19 * derived from this software without specific prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 22 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 23 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 24 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 26 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 27 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 29 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 30 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 * 33 * $FreeBSD$ 34 */ 35 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kernel.h> 39 #include <sys/module.h> 40 #include <sys/bus.h> 41 #include <sys/queue.h> 42 #include <machine/bus.h> 43 #include <sys/rman.h> 44 #include <machine/resource.h> 45 46 #include <pci/pcivar.h> 47 #include <pci/pcireg.h> 48 49 #include <dev/firewire/firewire.h> 50 #include <dev/firewire/firewirebusreg.h> 51 #include <dev/firewire/firewirereg.h> 52 53 #include <dev/firewire/fwohcireg.h> 54 #include <dev/firewire/fwohcivar.h> 55 56 static int fwohci_pci_attach(device_t self); 57 static int fwohci_pci_detach(device_t self); 58 59 /* 60 * The probe routine. 61 */ 62 static int 63 fwohci_pci_probe( device_t dev ) 64 { 65 #if 1 66 if ((pci_get_vendor(dev) == FW_VENDORID_NEC) && 67 (pci_get_device(dev) == FW_DEVICE_UPD861)) { 68 device_set_desc(dev, "NEC uPD72861"); 69 return 0; 70 } 71 if ((pci_get_vendor(dev) == FW_VENDORID_TI) && 72 (pci_get_device(dev) == FW_DEVICE_TITSB22)) { 73 device_set_desc(dev, "Texas Instruments TSB12LV22"); 74 return 0; 75 } 76 if ((pci_get_vendor(dev) == FW_VENDORID_TI) && 77 (pci_get_device(dev) == FW_DEVICE_TITSB23)) { 78 device_set_desc(dev, "Texas Instruments TSB12LV23"); 79 return 0; 80 } 81 if ((pci_get_vendor(dev) == FW_VENDORID_TI) && 82 (pci_get_device(dev) == FW_DEVICE_TITSB26)) { 83 device_set_desc(dev, "Texas Instruments TSB12LV26"); 84 return 0; 85 } 86 if ((pci_get_vendor(dev) == FW_VENDORID_TI) && 87 (pci_get_device(dev) == FW_DEVICE_TITSB43)) { 88 device_set_desc(dev, "Texas Instruments TSB43AA22"); 89 return 0; 90 } 91 if ((pci_get_vendor(dev) == FW_VENDORID_SONY) && 92 (pci_get_device(dev) == FW_DEVICE_CX3022)) { 93 device_set_desc(dev, "SONY CX3022"); 94 return 0; 95 } 96 if ((pci_get_vendor(dev) == FW_VENDORID_VIA) && 97 (pci_get_device(dev) == FW_DEVICE_VT6306)) { 98 device_set_desc(dev, "VIA VT6306"); 99 return 0; 100 } 101 if ((pci_get_vendor(dev) == FW_VENDORID_RICOH) && 102 (pci_get_device(dev) == FW_DEVICE_R5C552)) { 103 device_set_desc(dev, "Ricoh R5C552"); 104 return 0; 105 } 106 if ((pci_get_vendor(dev) == FW_VENDORID_APPLE) && 107 (pci_get_device(dev) == FW_DEVICE_PANGEA)) { 108 device_set_desc(dev, "Apple Pangea"); 109 return 0; 110 } 111 if ((pci_get_vendor(dev) == FW_VENDORID_APPLE) && 112 (pci_get_device(dev) == FW_DEVICE_UNINORTH)) { 113 device_set_desc(dev, "Apple UniNorth"); 114 return 0; 115 } 116 if ((pci_get_vendor(dev) == FW_VENDORID_LUCENT) && 117 (pci_get_device(dev) == FW_DEVICE_FW322)) { 118 device_set_desc(dev, "Lucent FW322/323"); 119 return 0; 120 } 121 #endif 122 if (pci_get_class(dev) == PCIC_SERIALBUS 123 && pci_get_subclass(dev) == PCIS_SERIALBUS_FW 124 && pci_get_progif(dev) == PCI_INTERFACE_OHCI) { 125 printf("XXXfw: vendid=%x, dev=%x\n", pci_get_vendor(dev), 126 pci_get_device(dev)); 127 device_set_desc(dev, "1394 Open Host Controller Interface"); 128 return 0; 129 } 130 131 return ENXIO; 132 } 133 134 #if __FreeBSD_version < 500000 135 static void 136 fwohci_dummy_intr(void *arg) 137 { 138 /* XXX do nothing */ 139 } 140 #endif 141 142 static int 143 fwohci_pci_attach(device_t self) 144 { 145 fwohci_softc_t *sc = device_get_softc(self); 146 int err; 147 int rid; 148 int latency, cache_line; 149 u_int16_t cmd; 150 #if __FreeBSD_version < 500000 151 int intr; 152 /* For the moment, put in a message stating what is wrong */ 153 intr = pci_read_config(self, PCIR_INTLINE, 1); 154 if (intr == 0 || intr == 255) { 155 device_printf(self, "Invalid irq %d\n", intr); 156 #ifdef __i386__ 157 device_printf(self, "Please switch PNP-OS to 'No' in BIOS\n"); 158 #endif 159 #if 0 160 return ENXIO; 161 #endif 162 } 163 #endif 164 165 cmd = pci_read_config(self, PCIR_COMMAND, 2); 166 cmd |= PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN | PCIM_CMD_MWRICEN; 167 pci_write_config(self, PCIR_COMMAND, cmd, 2); 168 169 latency = pci_read_config(self, PCIR_LATTIMER, 1); 170 #define DEF_LATENCY 250 /* Derived from Max Bulk Transfer size 512 Bytes*/ 171 if( latency < DEF_LATENCY ) { 172 latency = DEF_LATENCY; 173 device_printf(self, "PCI bus latency was changing to"); 174 pci_write_config(self, PCIR_LATTIMER,latency, 1); 175 } else 176 { 177 device_printf(self, "PCI bus latency is"); 178 } 179 printf(" %d.\n", (int) latency); 180 cache_line = pci_read_config(self, PCIR_CACHELNSZ, 1); 181 #if 0 182 #define DEF_CACHE_LINE 0xc 183 cache_line = DEF_CACHE_LINE; 184 pci_write_config(self, PCIR_CACHELNSZ, cache_line, 1); 185 #endif 186 printf("cache size %d.\n", (int) cache_line); 187 /**/ 188 rid = PCI_CBMEM; 189 sc->bsr = bus_alloc_resource(self, SYS_RES_MEMORY, &rid, 190 0, ~0, 1, RF_ACTIVE); 191 if (!sc->bsr) { 192 device_printf(self, "Could not map memory\n"); 193 return ENXIO; 194 } 195 196 sc->bst = rman_get_bustag(sc->bsr); 197 sc->bsh = rman_get_bushandle(sc->bsr); 198 199 rid = 0; 200 sc->irq_res = bus_alloc_resource(self, SYS_RES_IRQ, &rid, 0, ~0, 1, 201 RF_SHAREABLE | RF_ACTIVE); 202 if (sc->irq_res == NULL) { 203 device_printf(self, "Could not allocate irq\n"); 204 fwohci_pci_detach(self); 205 return ENXIO; 206 } 207 208 sc->fc.bdev = device_add_child(self, "firewire", -1); 209 if (!sc->fc.bdev) { 210 device_printf(self, "Could not add firewire device\n"); 211 fwohci_pci_detach(self); 212 return ENOMEM; 213 } 214 device_set_ivars(sc->fc.bdev, sc); 215 216 err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_NET, 217 (driver_intr_t *) fwohci_intr, sc, &sc->ih); 218 #if __FreeBSD_version < 500000 219 /* XXX splcam() should mask this irq for sbp.c*/ 220 err = bus_setup_intr(self, sc->irq_res, INTR_TYPE_CAM, 221 (driver_intr_t *) fwohci_dummy_intr, sc, &sc->ih_cam); 222 #endif 223 if (err) { 224 device_printf(self, "Could not setup irq, %d\n", err); 225 fwohci_pci_detach(self); 226 return ENXIO; 227 } 228 229 err = fwohci_init(sc, self); 230 231 if (!err) 232 err = device_probe_and_attach(sc->fc.bdev); 233 234 if (err) { 235 device_printf(self, "Firewire init failed\n"); 236 fwohci_pci_detach(self); 237 return EIO; 238 } 239 240 return 0; 241 } 242 243 static int 244 fwohci_pci_detach(device_t self) 245 { 246 fwohci_softc_t *sc = device_get_softc(self); 247 int s; 248 249 250 s = splfw(); 251 bus_generic_detach(self); 252 253 /* disable interrupts that might have been switched on */ 254 if (sc->bst && sc->bsh) 255 bus_space_write_4(sc->bst, sc->bsh, 256 FWOHCI_INTMASKCLR, OHCI_INT_EN); 257 258 if (sc->irq_res) { 259 int err = bus_teardown_intr(self, sc->irq_res, sc->ih); 260 if (err) 261 /* XXX or should we panic? */ 262 device_printf(self, "Could not tear down irq, %d\n", 263 err); 264 #if __FreeBSD_version < 500000 265 err = bus_teardown_intr(self, sc->irq_res, sc->ih_cam); 266 #endif 267 sc->ih = NULL; 268 } 269 270 if (sc->fc.bdev) { 271 device_delete_child(self, sc->fc.bdev); 272 sc->fc.bdev = NULL; 273 } 274 275 if (sc->irq_res) { 276 bus_release_resource(self, SYS_RES_IRQ, 0, sc->irq_res); 277 sc->irq_res = NULL; 278 } 279 280 if (sc->bsr) { 281 bus_release_resource(self, SYS_RES_MEMORY,PCI_CBMEM,sc->bsr); 282 sc->bsr = NULL; 283 sc->bst = 0; 284 sc->bsh = 0; 285 } 286 splx(s); 287 288 return 0; 289 } 290 291 static device_method_t fwohci_methods[] = { 292 /* Device interface */ 293 DEVMETHOD(device_probe, fwohci_pci_probe), 294 DEVMETHOD(device_attach, fwohci_pci_attach), 295 DEVMETHOD(device_detach, fwohci_pci_detach), 296 DEVMETHOD(device_shutdown, bus_generic_shutdown), 297 298 /* Bus interface */ 299 DEVMETHOD(bus_print_child, bus_generic_print_child), 300 301 { 0, 0 } 302 }; 303 304 static driver_t fwohci_driver = { 305 "fwohci", 306 fwohci_methods, 307 sizeof(fwohci_softc_t), 308 }; 309 310 static devclass_t fwohci_devclass; 311 312 DRIVER_MODULE(fwohci, pci, fwohci_driver, fwohci_devclass, 0, 0); 313 DRIVER_MODULE(fwohci, cardbus, fwohci_driver, fwohci_devclass, 0, 0); 314