1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2002 Adaptec Inc. 5 * All rights reserved. 6 * 7 * Written by: David Jeffery 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <sys/cdefs.h> 32 __FBSDID("$FreeBSD$"); 33 34 #include <dev/ips/ipsreg.h> 35 #include <dev/ips/ips.h> 36 37 #include <dev/pci/pcireg.h> 38 #include <dev/pci/pcivar.h> 39 40 static int ips_pci_free(ips_softc_t *sc); 41 static void ips_intrhook(void *arg); 42 43 static int ips_pci_probe(device_t dev) 44 { 45 46 if ((pci_get_vendor(dev) == IPS_VENDOR_ID) && 47 (pci_get_device(dev) == IPS_MORPHEUS_DEVICE_ID)) { 48 device_set_desc(dev, "IBM ServeRAID Adapter"); 49 return (BUS_PROBE_DEFAULT); 50 } else if ((pci_get_vendor(dev) == IPS_VENDOR_ID) && 51 (pci_get_device(dev) == IPS_COPPERHEAD_DEVICE_ID)) { 52 device_set_desc(dev, "IBM ServeRAID Adapter"); 53 return (BUS_PROBE_DEFAULT); 54 } else if ((pci_get_vendor(dev) == IPS_VENDOR_ID_ADAPTEC) && 55 (pci_get_device(dev) == IPS_MARCO_DEVICE_ID)) { 56 device_set_desc(dev, "Adaptec ServeRAID Adapter"); 57 return (BUS_PROBE_DEFAULT); 58 } 59 return(ENXIO); 60 } 61 62 static int ips_pci_attach(device_t dev) 63 { 64 ips_softc_t *sc; 65 66 DEVICE_PRINTF(1, dev, "in attach.\n"); 67 sc = (ips_softc_t *)device_get_softc(dev); 68 sc->dev = dev; 69 mtx_init(&sc->queue_mtx, "IPS bioqueue lock", NULL, MTX_DEF); 70 sema_init(&sc->cmd_sema, 0, "IPS Command Semaphore"); 71 callout_init_mtx(&sc->timer, &sc->queue_mtx, 0); 72 73 if(pci_get_device(dev) == IPS_MORPHEUS_DEVICE_ID){ 74 sc->ips_adapter_reinit = ips_morpheus_reinit; 75 sc->ips_adapter_intr = ips_morpheus_intr; 76 sc->ips_issue_cmd = ips_issue_morpheus_cmd; 77 sc->ips_poll_cmd = ips_morpheus_poll; 78 } else if(pci_get_device(dev) == IPS_COPPERHEAD_DEVICE_ID){ 79 sc->ips_adapter_reinit = ips_copperhead_reinit; 80 sc->ips_adapter_intr = ips_copperhead_intr; 81 sc->ips_issue_cmd = ips_issue_copperhead_cmd; 82 sc->ips_poll_cmd = ips_copperhead_poll; 83 } else if (pci_get_device(dev) == IPS_MARCO_DEVICE_ID){ 84 sc->ips_adapter_reinit = ips_morpheus_reinit; 85 sc->ips_adapter_intr = ips_morpheus_intr; 86 sc->ips_issue_cmd = ips_issue_morpheus_cmd; 87 sc->ips_poll_cmd = ips_morpheus_poll; 88 } else 89 goto error; 90 /* make sure busmastering is on */ 91 pci_enable_busmaster(dev); 92 /* setting up io space */ 93 sc->iores = NULL; 94 PRINTF(10, "trying MEMIO\n"); 95 if(pci_get_device(dev) == IPS_COPPERHEAD_DEVICE_ID) 96 sc->rid = PCIR_BAR(1); 97 else 98 sc->rid = PCIR_BAR(0); 99 sc->iotype = SYS_RES_MEMORY; 100 sc->iores = bus_alloc_resource_any(dev, sc->iotype, &sc->rid, 101 RF_ACTIVE); 102 if(!sc->iores){ 103 PRINTF(10, "trying PORTIO\n"); 104 sc->rid = PCIR_BAR(0); 105 sc->iotype = SYS_RES_IOPORT; 106 sc->iores = bus_alloc_resource_any(dev, sc->iotype, 107 &sc->rid, RF_ACTIVE); 108 } 109 if(sc->iores == NULL){ 110 device_printf(dev, "resource allocation failed\n"); 111 return (ENXIO); 112 } 113 /*allocate an interrupt. when does the irq become active? after leaving attach? */ 114 sc->irqrid = 0; 115 if(!(sc->irqres = bus_alloc_resource_any(dev, SYS_RES_IRQ, 116 &sc->irqrid, RF_SHAREABLE | RF_ACTIVE))){ 117 device_printf(dev, "irq allocation failed\n"); 118 goto error; 119 } 120 if(bus_setup_intr(dev, sc->irqres, INTR_TYPE_BIO|INTR_MPSAFE, NULL, 121 sc->ips_adapter_intr, sc, &sc->irqcookie)){ 122 device_printf(dev, "irq setup failed\n"); 123 goto error; 124 } 125 if (bus_dma_tag_create( /* PCI parent */bus_get_dma_tag(dev), 126 /* alignemnt */ 1, 127 /* boundary */ 0, 128 /* lowaddr */ BUS_SPACE_MAXADDR_32BIT, 129 /* highaddr */ BUS_SPACE_MAXADDR, 130 /* filter */ NULL, 131 /* filterarg */ NULL, 132 /* maxsize */ BUS_SPACE_MAXSIZE_32BIT, 133 /* numsegs */ IPS_MAX_SG_ELEMENTS, 134 /* maxsegsize*/ BUS_SPACE_MAXSIZE_32BIT, 135 /* flags */ 0, 136 /* lockfunc */ NULL, 137 /* lockarg */ NULL, 138 &sc->adapter_dmatag) != 0) { 139 device_printf(dev, "can't alloc dma tag\n"); 140 goto error; 141 } 142 sc->ips_ich.ich_func = ips_intrhook; 143 sc->ips_ich.ich_arg = sc; 144 bioq_init(&sc->queue); 145 if (config_intrhook_establish(&sc->ips_ich) != 0) { 146 printf("IPS can't establish configuration hook\n"); 147 goto error; 148 } 149 return 0; 150 error: 151 ips_pci_free(sc); 152 return (ENXIO); 153 } 154 155 static void 156 ips_intrhook(void *arg) 157 { 158 struct ips_softc *sc = (struct ips_softc *)arg; 159 160 config_intrhook_disestablish(&sc->ips_ich); 161 if (ips_adapter_init(sc)) 162 ips_pci_free(sc); 163 else 164 sc->configured = 1; 165 } 166 167 static int ips_pci_free(ips_softc_t *sc) 168 { 169 if(sc->adapter_dmatag) 170 bus_dma_tag_destroy(sc->adapter_dmatag); 171 if(sc->irqcookie) 172 bus_teardown_intr(sc->dev, sc->irqres, sc->irqcookie); 173 if(sc->irqres) 174 bus_release_resource(sc->dev, SYS_RES_IRQ, sc->irqrid, sc->irqres); 175 if(sc->iores) 176 bus_release_resource(sc->dev, sc->iotype, sc->rid, sc->iores); 177 sc->configured = 0; 178 mtx_destroy(&sc->queue_mtx); 179 sema_destroy(&sc->cmd_sema); 180 return 0; 181 } 182 183 static int ips_pci_detach(device_t dev) 184 { 185 ips_softc_t *sc; 186 DEVICE_PRINTF(1, dev, "detaching ServeRaid\n"); 187 sc = (ips_softc_t *) device_get_softc(dev); 188 if (sc->configured) { 189 sc->configured = 0; 190 ips_flush_cache(sc); 191 if(ips_adapter_free(sc)) 192 return EBUSY; 193 ips_pci_free(sc); 194 bioq_flush(&sc->queue, NULL, ENXIO); 195 } 196 return 0; 197 } 198 199 static int ips_pci_shutdown(device_t dev) 200 { 201 ips_softc_t *sc = (ips_softc_t *) device_get_softc(dev); 202 if (sc->configured) { 203 ips_flush_cache(sc); 204 } 205 return 0; 206 } 207 208 static device_method_t ips_driver_methods[] = { 209 DEVMETHOD(device_probe, ips_pci_probe), 210 DEVMETHOD(device_attach, ips_pci_attach), 211 DEVMETHOD(device_detach, ips_pci_detach), 212 DEVMETHOD(device_shutdown, ips_pci_shutdown), 213 {0,0} 214 }; 215 216 static driver_t ips_pci_driver = { 217 "ips", 218 ips_driver_methods, 219 sizeof(ips_softc_t), 220 }; 221 222 static devclass_t ips_devclass; 223 DRIVER_MODULE(ips, pci, ips_pci_driver, ips_devclass, 0, 0); 224