1 /* $OpenBSD: if_an_pcmcia.c,v 1.22 2011/07/03 15:47:17 matthew 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_dl.h> 38 #include <net/if_types.h> 39 #include <net/if_media.h> 40 41 #include <netinet/in.h> 42 #include <netinet/if_ether.h> 43 44 #include <net80211/ieee80211_var.h> 45 #include <net80211/ieee80211_radiotap.h> 46 47 #include <machine/bus.h> 48 49 #include <dev/pcmcia/pcmciareg.h> 50 #include <dev/pcmcia/pcmciavar.h> 51 #include <dev/pcmcia/pcmciadevs.h> 52 53 #include <dev/ic/anreg.h> 54 #include <dev/ic/anvar.h> 55 56 int an_pcmcia_match(struct device *, void *, void *); 57 void an_pcmcia_attach(struct device *, struct device *, void *); 58 int an_pcmcia_detach(struct device *, int); 59 int an_pcmcia_activate(struct device *, int); 60 61 struct an_pcmcia_softc { 62 struct an_softc sc_an; 63 64 struct pcmcia_io_handle sc_pcioh; 65 int sc_io_window; 66 struct pcmcia_function *sc_pf; 67 68 int sc_state; 69 #define AN_PCMCIA_ATTACHED 3 70 }; 71 72 struct cfattach an_pcmcia_ca = { 73 sizeof(struct an_pcmcia_softc), an_pcmcia_match, an_pcmcia_attach, 74 an_pcmcia_detach, an_pcmcia_activate 75 }; 76 77 int 78 an_pcmcia_match(struct device *parent, void *match, void *aux) 79 { 80 struct pcmcia_attach_args *pa = aux; 81 82 if (pa->pf->function != PCMCIA_FUNCTION_NETWORK) 83 return 0; 84 85 switch (pa->manufacturer) { 86 case PCMCIA_VENDOR_AIRONET: 87 switch (pa->product) { 88 case PCMCIA_PRODUCT_AIRONET_PC4500: 89 case PCMCIA_PRODUCT_AIRONET_PC4800: 90 case PCMCIA_PRODUCT_AIRONET_350: 91 return 1; 92 } 93 } 94 95 return 0; 96 } 97 98 void 99 an_pcmcia_attach(struct device *parent, struct device *self, void *aux) 100 { 101 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)self; 102 struct an_softc *sc = (struct an_softc *)self; 103 struct pcmcia_attach_args *pa = aux; 104 struct pcmcia_config_entry *cfe; 105 const char *intrstr; 106 int error; 107 108 psc->sc_pf = pa->pf; 109 cfe = SIMPLEQ_FIRST(&pa->pf->cfe_head); 110 111 pcmcia_function_init(pa->pf, cfe); 112 if (pcmcia_function_enable(pa->pf)) { 113 printf(": function enable failed\n"); 114 return; 115 } 116 117 if (pcmcia_io_alloc(pa->pf, 0, AN_IOSIZ, AN_IOSIZ, &psc->sc_pcioh)) { 118 printf(": can't alloc i/o space\n"); 119 pcmcia_function_disable(pa->pf); 120 return; 121 } 122 123 if (pcmcia_io_map(pa->pf, PCMCIA_WIDTH_IO16, 0, AN_IOSIZ, 124 &psc->sc_pcioh, &psc->sc_io_window)) { 125 printf(": can't map i/o space\n"); 126 pcmcia_io_free(pa->pf, &psc->sc_pcioh); 127 pcmcia_function_disable(pa->pf); 128 return; 129 } 130 131 sc->sc_iot = psc->sc_pcioh.iot; 132 sc->sc_ioh = psc->sc_pcioh.ioh; 133 134 sc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, an_intr, sc, 135 sc->sc_dev.dv_xname); 136 intrstr = pcmcia_intr_string(psc->sc_pf, sc->sc_ih); 137 if (*intrstr) 138 printf(", %s", intrstr); 139 printf("\n"); 140 141 error = an_attach(sc); 142 if (error) { 143 printf("%s: failed to attach controller\n", 144 self->dv_xname); 145 return; 146 } 147 148 psc->sc_state = AN_PCMCIA_ATTACHED; 149 } 150 151 int 152 an_pcmcia_detach(struct device *dev, int flags) 153 { 154 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev; 155 int error; 156 157 if (psc->sc_state != AN_PCMCIA_ATTACHED) 158 return (0); 159 160 error = an_detach(&psc->sc_an); 161 if (error) 162 return (error); 163 164 pcmcia_io_unmap(psc->sc_pf, psc->sc_io_window); 165 pcmcia_io_free(psc->sc_pf, &psc->sc_pcioh); 166 167 return 0; 168 } 169 170 int 171 an_pcmcia_activate(struct device *dev, int act) 172 { 173 struct an_pcmcia_softc *psc = (struct an_pcmcia_softc *)dev; 174 struct an_softc *sc = &psc->sc_an; 175 struct ieee80211com *ic = &sc->sc_ic; 176 struct ifnet *ifp = &ic->ic_if; 177 178 switch (act) { 179 case DVACT_DEACTIVATE: 180 ifp->if_timer = 0; 181 if (ifp->if_flags & IFF_RUNNING) 182 an_stop(ifp, 1); 183 if (sc->sc_ih) 184 pcmcia_intr_disestablish(psc->sc_pf, sc->sc_ih); 185 sc->sc_ih = NULL; 186 pcmcia_function_disable(psc->sc_pf); 187 break; 188 } 189 return (0); 190 } 191