1 /* $OpenBSD: if_an_pcmcia.c,v 1.26 2015/11/24 17:11:40 mpi Exp $ */ 2 3 /* 4 * Copyright (c) 1999 Michael Shalayeff 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 26 * THE POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 #include <sys/param.h> 30 #include <sys/systm.h> 31 #include <sys/device.h> 32 #include <sys/timeout.h> 33 #include <sys/socket.h> 34 #include <sys/tree.h> 35 36 #include <net/if.h> 37 #include <net/if_media.h> 38 39 #include <netinet/in.h> 40 #include <netinet/if_ether.h> 41 42 #include <net80211/ieee80211_var.h> 43 #include <net80211/ieee80211_radiotap.h> 44 45 #include <dev/pcmcia/pcmciareg.h> 46 #include <dev/pcmcia/pcmciavar.h> 47 #include <dev/pcmcia/pcmciadevs.h> 48 49 #include <dev/ic/anreg.h> 50 #include <dev/ic/anvar.h> 51 52 int an_pcmcia_match(struct device *, void *, void *); 53 void an_pcmcia_attach(struct device *, struct device *, void *); 54 int an_pcmcia_detach(struct device *, int); 55 int an_pcmcia_activate(struct device *, int); 56 57 struct an_pcmcia_softc { 58 struct an_softc sc_an; 59 60 struct pcmcia_io_handle sc_pcioh; 61 int sc_io_window; 62 struct pcmcia_function *sc_pf; 63 64 int sc_state; 65 #define AN_PCMCIA_ATTACHED 3 66 }; 67 68 struct cfattach an_pcmcia_ca = { 69 sizeof(struct an_pcmcia_softc), an_pcmcia_match, an_pcmcia_attach, 70 an_pcmcia_detach, an_pcmcia_activate 71 }; 72 73 int 74 an_pcmcia_match(struct device *parent, void *match, void *aux) 75 { 76 struct pcmcia_attach_args *pa = aux; 77 78 if (pa->pf->function != PCMCIA_FUNCTION_NETWORK) 79 return 0; 80 81 switch (pa->manufacturer) { 82 case PCMCIA_VENDOR_AIRONET: 83 switch (pa->product) { 84 case PCMCIA_PRODUCT_AIRONET_PC4500: 85 case PCMCIA_PRODUCT_AIRONET_PC4800: 86 case PCMCIA_PRODUCT_AIRONET_350: 87 return 1; 88 } 89 } 90 91 return 0; 92 } 93 94 void 95 an_pcmcia_attach(struct device *parent, struct device *self, void *aux) 96 { 97 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)self; 98 struct an_softc *sc = (struct an_softc *)self; 99 struct pcmcia_attach_args *pa = aux; 100 struct pcmcia_config_entry *cfe; 101 const char *intrstr; 102 int error; 103 104 psc->sc_pf = pa->pf; 105 cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); 106 107 pcmcia_function_init(pa->pf, cfe); 108 if (pcmcia_function_enable(pa->pf)) { 109 printf(": function enable failed\n"); 110 return; 111 } 112 113 if (pcmcia_io_alloc(pa->pf, 0, AN_IOSIZ, AN_IOSIZ, &psc->sc_pcioh)) { 114 printf(": can't alloc i/o space\n"); 115 pcmcia_function_disable(pa->pf); 116 return; 117 } 118 119 if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16, 0, AN_IOSIZ, 120 &psc->sc_pcioh, &psc->sc_io_window)) { 121 printf(": can't map i/o space\n"); 122 pcmcia_io_free(pa->pf, &psc->sc_pcioh); 123 pcmcia_function_disable(pa->pf); 124 return; 125 } 126 127 sc->sc_iot = psc->sc_pcioh.iot; 128 sc->sc_ioh = psc->sc_pcioh.ioh; 129 sc->sc_enabled = 1; 130 131 sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, an_intr, sc, 132 sc->sc_dev.dv_xname); 133 intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih); 134 if (*intrstr) 135 printf(", %s", intrstr); 136 printf("\n"); 137 138 error = an_attach(sc); 139 if (error) { 140 printf("%s: failed to attach controller\n", 141 self->dv_xname); 142 return; 143 } 144 145 sc->sc_enabled = 0; 146 psc->sc_state = AN_PCMCIA_ATTACHED; 147 } 148 149 int 150 an_pcmcia_detach(struct device *dev, int flags) 151 { 152 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev; 153 int error; 154 155 if (psc->sc_state != AN_PCMCIA_ATTACHED) 156 return (0); 157 158 error = an_detach(&psc->sc_an); 159 if (error) 160 return (error); 161 162 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window); 163 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh); 164 165 return 0; 166 } 167 168 int 169 an_pcmcia_activate(struct device *dev, int act) 170 { 171 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev; 172 struct an_softc *sc = &psc->sc_an; 173 struct ieee80211com *ic = &sc->sc_ic; 174 struct ifnet *ifp = &ic->ic_if; 175 176 switch (act) { 177 case DVACT_DEACTIVATE: 178 ifp->if_timer = 0; 179 if (ifp->if_flags & IFF_RUNNING) 180 an_stop(ifp, 1); 181 if (sc->sc_ih) 182 pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); 183 sc->sc_ih = NULL; 184 pcmcia_function_disable(psc->sc_pf); 185 break; 186 } 187 return (0); 188 } 189