1 1.44 christos /* $NetBSD: aic_pcmcia.c,v 1.44 2017/08/01 12:15:21 christos Exp $ */ 2 1.2 thorpej 3 1.2 thorpej /* 4 1.2 thorpej * Copyright (c) 1997 Marc Horowitz. All rights reserved. 5 1.2 thorpej * 6 1.2 thorpej * Redistribution and use in source and binary forms, with or without 7 1.2 thorpej * modification, are permitted provided that the following conditions 8 1.2 thorpej * are met: 9 1.2 thorpej * 1. Redistributions of source code must retain the above copyright 10 1.2 thorpej * notice, this list of conditions and the following disclaimer. 11 1.2 thorpej * 2. Redistributions in binary form must reproduce the above copyright 12 1.2 thorpej * notice, this list of conditions and the following disclaimer in the 13 1.2 thorpej * documentation and/or other materials provided with the distribution. 14 1.2 thorpej * 3. All advertising materials mentioning features or use of this software 15 1.2 thorpej * must display the following acknowledgement: 16 1.2 thorpej * This product includes software developed by Marc Horowitz. 17 1.2 thorpej * 4. The name of the author may not be used to endorse or promote products 18 1.2 thorpej * derived from this software without specific prior written permission. 19 1.2 thorpej * 20 1.2 thorpej * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 21 1.2 thorpej * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 22 1.2 thorpej * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 23 1.2 thorpej * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 24 1.2 thorpej * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 25 1.2 thorpej * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 1.2 thorpej * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 1.2 thorpej * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 1.2 thorpej * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 29 1.2 thorpej * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 1.2 thorpej */ 31 1.18 lukem 32 1.18 lukem #include <sys/cdefs.h> 33 1.44 christos __KERNEL_RCSID(0, "$NetBSD: aic_pcmcia.c,v 1.44 2017/08/01 12:15:21 christos Exp $"); 34 1.2 thorpej 35 1.2 thorpej #include <sys/param.h> 36 1.2 thorpej #include <sys/systm.h> 37 1.2 thorpej #include <sys/select.h> 38 1.2 thorpej #include <sys/device.h> 39 1.2 thorpej 40 1.36 ad #include <sys/cpu.h> 41 1.36 ad #include <sys/bus.h> 42 1.36 ad #include <sys/intr.h> 43 1.2 thorpej 44 1.2 thorpej #include <dev/scsipi/scsipi_all.h> 45 1.2 thorpej #include <dev/scsipi/scsipiconf.h> 46 1.2 thorpej #include <dev/scsipi/scsi_all.h> 47 1.2 thorpej 48 1.2 thorpej #include <dev/ic/aic6360var.h> 49 1.2 thorpej 50 1.2 thorpej #include <dev/pcmcia/pcmciareg.h> 51 1.2 thorpej #include <dev/pcmcia/pcmciavar.h> 52 1.6 christos #include <dev/pcmcia/pcmciadevs.h> 53 1.2 thorpej 54 1.2 thorpej struct aic_pcmcia_softc { 55 1.2 thorpej struct aic_softc sc_aic; /* real "aic" softc */ 56 1.2 thorpej 57 1.2 thorpej /* PCMCIA-specific goo. */ 58 1.2 thorpej struct pcmcia_function *sc_pf; /* our PCMCIA function */ 59 1.2 thorpej void *sc_ih; /* interrupt handler */ 60 1.25 mycroft 61 1.25 mycroft int sc_state; 62 1.25 mycroft #define AIC_PCMCIA_ATTACHED 3 63 1.2 thorpej }; 64 1.2 thorpej 65 1.42 tsutsui static int aic_pcmcia_match(device_t, cfdata_t, void *); 66 1.42 tsutsui static int aic_pcmcia_validate_config(struct pcmcia_config_entry *); 67 1.42 tsutsui static void aic_pcmcia_attach(device_t, device_t, void *); 68 1.42 tsutsui static int aic_pcmcia_detach(device_t, int); 69 1.42 tsutsui static int aic_pcmcia_enable(device_t, int); 70 1.25 mycroft 71 1.41 tsutsui CFATTACH_DECL_NEW(aic_pcmcia, sizeof(struct aic_pcmcia_softc), 72 1.43 dyoung aic_pcmcia_match, aic_pcmcia_attach, aic_pcmcia_detach, NULL); 73 1.2 thorpej 74 1.42 tsutsui static const struct pcmcia_product aic_pcmcia_products[] = { 75 1.29 mycroft { PCMCIA_VENDOR_ADAPTEC, PCMCIA_PRODUCT_ADAPTEC_APA1460, 76 1.29 mycroft PCMCIA_CIS_INVALID }, 77 1.7 thorpej 78 1.29 mycroft { PCMCIA_VENDOR_ADAPTEC, PCMCIA_PRODUCT_ADAPTEC_APA1460A, 79 1.29 mycroft PCMCIA_CIS_INVALID }, 80 1.7 thorpej 81 1.29 mycroft { PCMCIA_VENDOR_NEWMEDIA, PCMCIA_PRODUCT_NEWMEDIA_BUSTOASTER, 82 1.29 mycroft PCMCIA_CIS_INVALID }, 83 1.15 cgd }; 84 1.42 tsutsui static const size_t aic_pcmcia_nproducts = __arraycount(aic_pcmcia_products); 85 1.7 thorpej 86 1.2 thorpej int 87 1.41 tsutsui aic_pcmcia_match(device_t parent, cfdata_t match, void *aux) 88 1.2 thorpej { 89 1.2 thorpej struct pcmcia_attach_args *pa = aux; 90 1.2 thorpej 91 1.29 mycroft if (pcmcia_product_lookup(pa, aic_pcmcia_products, aic_pcmcia_nproducts, 92 1.29 mycroft sizeof(aic_pcmcia_products[0]), NULL)) 93 1.7 thorpej return (1); 94 1.2 thorpej return (0); 95 1.2 thorpej } 96 1.2 thorpej 97 1.25 mycroft int 98 1.38 dsl aic_pcmcia_validate_config(struct pcmcia_config_entry *cfe) 99 1.25 mycroft { 100 1.25 mycroft if (cfe->iftype != PCMCIA_IFTYPE_IO || 101 1.25 mycroft cfe->num_memspace != 0 || 102 1.25 mycroft cfe->num_iospace != 1) 103 1.25 mycroft return (EINVAL); 104 1.44 christos 105 1.44 christos cfe->iomask = 0; /* XXX: wrong from cfe?, quirk? */ 106 1.25 mycroft return (0); 107 1.25 mycroft } 108 1.25 mycroft 109 1.2 thorpej void 110 1.41 tsutsui aic_pcmcia_attach(device_t parent, device_t self, void *aux) 111 1.2 thorpej { 112 1.41 tsutsui struct aic_pcmcia_softc *psc = device_private(self); 113 1.2 thorpej struct aic_softc *sc = &psc->sc_aic; 114 1.2 thorpej struct pcmcia_attach_args *pa = aux; 115 1.2 thorpej struct pcmcia_config_entry *cfe; 116 1.2 thorpej struct pcmcia_function *pf = pa->pf; 117 1.25 mycroft int error; 118 1.2 thorpej 119 1.41 tsutsui sc->sc_dev = self; 120 1.2 thorpej psc->sc_pf = pf; 121 1.2 thorpej 122 1.25 mycroft error = pcmcia_function_configure(pf, aic_pcmcia_validate_config); 123 1.26 mycroft if (error) { 124 1.43 dyoung aprint_error_dev(self, "configure failed, error=%d\n", error); 125 1.26 mycroft return; 126 1.26 mycroft } 127 1.25 mycroft 128 1.25 mycroft cfe = pf->cfe; 129 1.25 mycroft sc->sc_iot = cfe->iospace[0].handle.iot; 130 1.25 mycroft sc->sc_ioh = cfe->iospace[0].handle.ioh; 131 1.25 mycroft 132 1.26 mycroft error = aic_pcmcia_enable(self, 1); 133 1.27 mycroft if (error) 134 1.26 mycroft goto fail; 135 1.2 thorpej 136 1.7 thorpej if (!aic_find(sc->sc_iot, sc->sc_ioh)) { 137 1.37 cegger aprint_error_dev(self, "unable to detect chip!\n"); 138 1.25 mycroft goto fail2; 139 1.7 thorpej } 140 1.2 thorpej 141 1.8 thorpej /* We can enable and disable the controller. */ 142 1.17 bouyer sc->sc_adapter.adapt_enable = aic_pcmcia_enable; 143 1.31 mycroft sc->sc_adapter.adapt_refcnt = 1; 144 1.2 thorpej 145 1.2 thorpej aicattach(sc); 146 1.31 mycroft scsipi_adapter_delref(&sc->sc_adapter); 147 1.25 mycroft psc->sc_state = AIC_PCMCIA_ATTACHED; 148 1.16 enami return; 149 1.16 enami 150 1.25 mycroft fail2: 151 1.25 mycroft aic_pcmcia_enable(self, 0); 152 1.25 mycroft fail: 153 1.25 mycroft pcmcia_function_unconfigure(pf); 154 1.8 thorpej } 155 1.8 thorpej 156 1.8 thorpej int 157 1.40 cegger aic_pcmcia_detach(device_t self, int flags) 158 1.12 enami { 159 1.41 tsutsui struct aic_pcmcia_softc *psc = device_private(self); 160 1.12 enami int error; 161 1.16 enami 162 1.41 tsutsui if (psc->sc_state != AIC_PCMCIA_ATTACHED) 163 1.16 enami return (0); 164 1.12 enami 165 1.25 mycroft error = aic_detach(self, flags); 166 1.25 mycroft if (error) 167 1.12 enami return (error); 168 1.12 enami 169 1.41 tsutsui pcmcia_function_unconfigure(psc->sc_pf); 170 1.12 enami 171 1.12 enami return (0); 172 1.12 enami } 173 1.25 mycroft 174 1.12 enami int 175 1.40 cegger aic_pcmcia_enable(device_t self, int onoff) 176 1.8 thorpej { 177 1.41 tsutsui struct aic_pcmcia_softc *psc = device_private(self); 178 1.41 tsutsui struct aic_softc *sc = &psc->sc_aic; 179 1.27 mycroft int error; 180 1.2 thorpej 181 1.8 thorpej if (onoff) { 182 1.31 mycroft /* Establish the interrupt handler. */ 183 1.41 tsutsui psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_BIO, 184 1.41 tsutsui aicintr, sc); 185 1.41 tsutsui if (!psc->sc_ih) 186 1.31 mycroft return (EIO); 187 1.31 mycroft 188 1.41 tsutsui error = pcmcia_function_enable(psc->sc_pf); 189 1.31 mycroft if (error) { 190 1.41 tsutsui pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 191 1.41 tsutsui psc->sc_ih = 0; 192 1.31 mycroft return (error); 193 1.31 mycroft } 194 1.13 enami 195 1.31 mycroft /* Initialize only chip. */ 196 1.41 tsutsui aic_init(sc, 0); 197 1.8 thorpej } else { 198 1.41 tsutsui pcmcia_function_disable(psc->sc_pf); 199 1.41 tsutsui pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 200 1.41 tsutsui psc->sc_ih = 0; 201 1.8 thorpej } 202 1.8 thorpej 203 1.8 thorpej return (0); 204 1.2 thorpej } 205