1 1.47 msaitoh /* $NetBSD: if_mbe_pcmcia.c,v 1.47 2016/07/07 06:55:42 msaitoh Exp $ */ 2 1.1 enami 3 1.1 enami /*- 4 1.32 mycroft * Copyright (c) 1998, 2000, 2004 The NetBSD Foundation, Inc. 5 1.1 enami * All rights reserved. 6 1.1 enami * 7 1.1 enami * This code is derived from software contributed to The NetBSD Foundation 8 1.1 enami * by Enami Tsugutomo. 9 1.1 enami * 10 1.1 enami * Redistribution and use in source and binary forms, with or without 11 1.1 enami * modification, are permitted provided that the following conditions 12 1.1 enami * are met: 13 1.1 enami * 1. Redistributions of source code must retain the above copyright 14 1.1 enami * notice, this list of conditions and the following disclaimer. 15 1.1 enami * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 enami * notice, this list of conditions and the following disclaimer in the 17 1.1 enami * documentation and/or other materials provided with the distribution. 18 1.1 enami * 19 1.1 enami * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 enami * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 enami * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 enami * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 enami * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 enami * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 enami * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 enami * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 enami * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 enami * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 enami * POSSIBILITY OF SUCH DAMAGE. 30 1.1 enami */ 31 1.21 lukem 32 1.21 lukem #include <sys/cdefs.h> 33 1.47 msaitoh __KERNEL_RCSID(0, "$NetBSD: if_mbe_pcmcia.c,v 1.47 2016/07/07 06:55:42 msaitoh Exp $"); 34 1.1 enami 35 1.1 enami #include <sys/param.h> 36 1.1 enami #include <sys/systm.h> 37 1.1 enami #include <sys/device.h> 38 1.1 enami #include <sys/socket.h> 39 1.1 enami 40 1.1 enami #include <net/if.h> 41 1.1 enami #include <net/if_ether.h> 42 1.1 enami #include <net/if_media.h> 43 1.1 enami 44 1.42 ad #include <sys/intr.h> 45 1.42 ad #include <sys/bus.h> 46 1.1 enami 47 1.1 enami #include <dev/ic/mb86960reg.h> 48 1.1 enami #include <dev/ic/mb86960var.h> 49 1.1 enami 50 1.1 enami #include <dev/pcmcia/pcmciareg.h> 51 1.1 enami #include <dev/pcmcia/pcmciavar.h> 52 1.3 christos #include <dev/pcmcia/pcmciadevs.h> 53 1.1 enami 54 1.44 tsutsui int mbe_pcmcia_match(device_t, cfdata_t, void *); 55 1.36 perry int mbe_pcmcia_validate_config(struct pcmcia_config_entry *); 56 1.44 tsutsui void mbe_pcmcia_attach(device_t, device_t, void *); 57 1.44 tsutsui int mbe_pcmcia_detach(device_t, int); 58 1.1 enami 59 1.1 enami struct mbe_pcmcia_softc { 60 1.1 enami struct mb86960_softc sc_mb86960; /* real "mb" softc */ 61 1.1 enami 62 1.34 mycroft struct pcmcia_function *sc_pf; /* our PCMCIA function */ 63 1.1 enami void *sc_ih; /* interrupt cookie */ 64 1.34 mycroft 65 1.34 mycroft int sc_state; 66 1.34 mycroft #define MBE_PCMCIA_ATTACHED 3 67 1.1 enami }; 68 1.1 enami 69 1.44 tsutsui CFATTACH_DECL_NEW(mbe_pcmcia, sizeof(struct mbe_pcmcia_softc), 70 1.29 thorpej mbe_pcmcia_match, mbe_pcmcia_attach, mbe_pcmcia_detach, mb86960_activate); 71 1.1 enami 72 1.36 perry int mbe_pcmcia_enable(struct mb86960_softc *); 73 1.36 perry void mbe_pcmcia_disable(struct mb86960_softc *); 74 1.1 enami 75 1.1 enami struct mbe_pcmcia_get_enaddr_args { 76 1.44 tsutsui uint8_t enaddr[ETHER_ADDR_LEN]; 77 1.18 is int maddr; 78 1.1 enami }; 79 1.36 perry int mbe_pcmcia_get_enaddr_from_cis(struct pcmcia_tuple *, void *); 80 1.36 perry int mbe_pcmcia_get_enaddr_from_mem(struct mbe_pcmcia_softc *, 81 1.36 perry struct mbe_pcmcia_get_enaddr_args *); 82 1.36 perry int mbe_pcmcia_get_enaddr_from_io(struct mbe_pcmcia_softc *, 83 1.36 perry struct mbe_pcmcia_get_enaddr_args *); 84 1.1 enami 85 1.24 ichiro static const struct mbe_pcmcia_product { 86 1.32 mycroft struct pcmcia_product mpp_product; 87 1.24 ichiro int mpp_enet_maddr; 88 1.32 mycroft int mpp_flags; 89 1.25 ichiro #define MBH10302 0x0001 /* FUJITSU MBH10302 */ 90 1.7 thorpej } mbe_pcmcia_products[] = { 91 1.32 mycroft { { PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_LAK_CD021BX, 92 1.32 mycroft PCMCIA_CIS_TDK_LAK_CD021BX }, 93 1.39 christos -1, 0 }, 94 1.13 cgd 95 1.32 mycroft { { PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_LAK_CF010, 96 1.32 mycroft PCMCIA_CIS_TDK_LAK_CF010 }, 97 1.39 christos -1, 0 }, 98 1.19 enami 99 1.7 thorpej #if 0 /* XXX 86960-based? */ 100 1.32 mycroft { { PCMCIA_VENDOR_TDK, PCMCIA_PRODUCT_TDK_LAK_DFL9610, 101 1.32 mycroft PCMCIA_CIS_TDK_DFL9610 }, 102 1.34 mycroft -1, MBH10302 /* XXX */ }, 103 1.7 thorpej #endif 104 1.8 tron 105 1.32 mycroft { { PCMCIA_VENDOR_CONTEC, PCMCIA_PRODUCT_CONTEC_CNETPC, 106 1.32 mycroft PCMCIA_CIS_CONTEC_CNETPC }, 107 1.39 christos -1, 0 }, 108 1.13 cgd 109 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_LA501, 110 1.32 mycroft PCMCIA_CIS_FUJITSU_LA501 }, 111 1.39 christos -1, 0 }, 112 1.13 cgd 113 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_FMV_J181, 114 1.32 mycroft PCMCIA_CIS_FUJITSU_FMV_J181 }, 115 1.34 mycroft -1, MBH10302 }, 116 1.25 ichiro 117 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_FMV_J182, 118 1.32 mycroft PCMCIA_CIS_FUJITSU_FMV_J182 }, 119 1.39 christos 0xf2c, 0 }, 120 1.25 ichiro 121 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_FMV_J182A, 122 1.32 mycroft PCMCIA_CIS_FUJITSU_FMV_J182A }, 123 1.39 christos 0x1cc, 0 }, 124 1.23 ichiro 125 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_ITCFJ182A, 126 1.32 mycroft PCMCIA_CIS_FUJITSU_ITCFJ182A }, 127 1.39 christos 0x1cc, 0 }, 128 1.18 is 129 1.32 mycroft { { PCMCIA_VENDOR_FUJITSU, PCMCIA_PRODUCT_FUJITSU_LA10S, 130 1.32 mycroft PCMCIA_CIS_FUJITSU_LA10S }, 131 1.39 christos -1, 0 }, 132 1.25 ichiro 133 1.32 mycroft { { PCMCIA_VENDOR_RATOC, PCMCIA_PRODUCT_RATOC_REX_R280, 134 1.32 mycroft PCMCIA_CIS_RATOC_REX_R280 }, 135 1.39 christos 0x1fc, 0 }, 136 1.7 thorpej }; 137 1.44 tsutsui static const size_t mbe_pcmcia_nproducts = __arraycount(mbe_pcmcia_products); 138 1.24 ichiro 139 1.1 enami int 140 1.44 tsutsui mbe_pcmcia_match(device_t parent, cfdata_t cf, void *aux) 141 1.1 enami { 142 1.1 enami struct pcmcia_attach_args *pa = aux; 143 1.1 enami 144 1.47 msaitoh if (pcmcia_product_lookup(pa, mbe_pcmcia_products, 145 1.47 msaitoh mbe_pcmcia_nproducts, sizeof(mbe_pcmcia_products[0]), NULL)) 146 1.44 tsutsui return 1; 147 1.44 tsutsui return 0; 148 1.1 enami } 149 1.1 enami 150 1.34 mycroft int 151 1.44 tsutsui mbe_pcmcia_validate_config(struct pcmcia_config_entry *cfe) 152 1.34 mycroft { 153 1.44 tsutsui 154 1.47 msaitoh if (cfe->iftype != PCMCIA_IFTYPE_IO || cfe->num_iospace < 1) 155 1.44 tsutsui return EINVAL; 156 1.44 tsutsui return 0; 157 1.34 mycroft } 158 1.34 mycroft 159 1.1 enami void 160 1.44 tsutsui mbe_pcmcia_attach(device_t parent, device_t self, void *aux) 161 1.1 enami { 162 1.44 tsutsui struct mbe_pcmcia_softc *psc = device_private(self); 163 1.1 enami struct mb86960_softc *sc = &psc->sc_mb86960; 164 1.1 enami struct pcmcia_attach_args *pa = aux; 165 1.1 enami struct pcmcia_config_entry *cfe; 166 1.1 enami struct mbe_pcmcia_get_enaddr_args pgea; 167 1.7 thorpej const struct mbe_pcmcia_product *mpp; 168 1.34 mycroft int error; 169 1.1 enami 170 1.44 tsutsui sc->sc_dev = self; 171 1.1 enami psc->sc_pf = pa->pf; 172 1.1 enami 173 1.34 mycroft error = pcmcia_function_configure(pa->pf, mbe_pcmcia_validate_config); 174 1.34 mycroft if (error) { 175 1.47 msaitoh aprint_error_dev(self, "configure failed, error=%d\n", error); 176 1.34 mycroft return; 177 1.1 enami } 178 1.1 enami 179 1.34 mycroft cfe = pa->pf->cfe; 180 1.34 mycroft sc->sc_bst = cfe->iospace[0].handle.iot; 181 1.34 mycroft sc->sc_bsh = cfe->iospace[0].handle.ioh; 182 1.34 mycroft 183 1.34 mycroft mpp = pcmcia_product_lookup(pa, mbe_pcmcia_products, 184 1.34 mycroft mbe_pcmcia_nproducts, sizeof(mbe_pcmcia_products[0]), NULL); 185 1.34 mycroft if (!mpp) 186 1.44 tsutsui panic("%s: impossible", __func__); 187 1.1 enami 188 1.25 ichiro /* Read station address from io/mem or CIS. */ 189 1.19 enami if (mpp->mpp_enet_maddr >= 0) { 190 1.19 enami pgea.maddr = mpp->mpp_enet_maddr; 191 1.18 is if (mbe_pcmcia_get_enaddr_from_mem(psc, &pgea) != 0) { 192 1.43 cegger aprint_error_dev(self, "couldn't get ethernet address " 193 1.43 cegger "from memory\n"); 194 1.35 mycroft goto fail; 195 1.18 is } 196 1.34 mycroft } else if (mpp->mpp_flags & MBH10302) { 197 1.25 ichiro bus_space_write_1(sc->sc_bst, sc->sc_bsh, FE_MBH0 , 198 1.25 ichiro FE_MBH0_MASK | FE_MBH0_INTR_ENABLE); 199 1.25 ichiro if (mbe_pcmcia_get_enaddr_from_io(psc, &pgea) != 0) { 200 1.44 tsutsui aprint_error_dev(self, 201 1.44 tsutsui "couldn't get ethernet address from i/o\n"); 202 1.35 mycroft goto fail; 203 1.25 ichiro } 204 1.18 is } else { 205 1.34 mycroft if (pa->pf->pf_funce_lan_nidlen != ETHER_ADDR_LEN) { 206 1.44 tsutsui aprint_error_dev(self, 207 1.44 tsutsui "couldn't get ethernet address from CIS\n"); 208 1.35 mycroft goto fail; 209 1.18 is } 210 1.34 mycroft memcpy(pgea.enaddr, pa->pf->pf_funce_lan_nid, ETHER_ADDR_LEN); 211 1.10 enami } 212 1.1 enami 213 1.1 enami /* Perform generic initialization. */ 214 1.34 mycroft if (mpp->mpp_flags & MBH10302) 215 1.30 tsutsui sc->sc_flags |= FE_FLAGS_MB86960; 216 1.30 tsutsui 217 1.35 mycroft sc->sc_enable = mbe_pcmcia_enable; 218 1.35 mycroft sc->sc_disable = mbe_pcmcia_disable; 219 1.35 mycroft 220 1.35 mycroft error = mbe_pcmcia_enable(sc); 221 1.35 mycroft if (error) 222 1.35 mycroft goto fail; 223 1.35 mycroft 224 1.30 tsutsui mb86960_attach(sc, pgea.enaddr); 225 1.1 enami mb86960_config(sc, NULL, 0, 0); 226 1.1 enami 227 1.34 mycroft mbe_pcmcia_disable(sc); 228 1.34 mycroft psc->sc_state = MBE_PCMCIA_ATTACHED; 229 1.14 enami return; 230 1.14 enami 231 1.34 mycroft fail: 232 1.34 mycroft pcmcia_function_unconfigure(pa->pf); 233 1.4 thorpej } 234 1.4 thorpej 235 1.4 thorpej int 236 1.46 cegger mbe_pcmcia_detach(device_t self, int flags) 237 1.4 thorpej { 238 1.44 tsutsui struct mbe_pcmcia_softc *psc = device_private(self); 239 1.12 enami int error; 240 1.12 enami 241 1.34 mycroft if (psc->sc_state != MBE_PCMCIA_ATTACHED) 242 1.44 tsutsui return 0; 243 1.14 enami 244 1.14 enami error = mb86960_detach(&psc->sc_mb86960); 245 1.34 mycroft if (error) 246 1.44 tsutsui return error; 247 1.5 thorpej 248 1.34 mycroft pcmcia_function_unconfigure(psc->sc_pf); 249 1.5 thorpej 250 1.44 tsutsui return 0; 251 1.1 enami } 252 1.1 enami 253 1.1 enami int 254 1.44 tsutsui mbe_pcmcia_enable(struct mb86960_softc *sc) 255 1.1 enami { 256 1.44 tsutsui struct mbe_pcmcia_softc *psc = (struct mbe_pcmcia_softc *)sc; 257 1.34 mycroft int error; 258 1.1 enami 259 1.1 enami /* Establish the interrupt handler. */ 260 1.1 enami psc->sc_ih = pcmcia_intr_establish(psc->sc_pf, IPL_NET, mb86960_intr, 261 1.1 enami sc); 262 1.34 mycroft if (!psc->sc_ih) 263 1.44 tsutsui return EIO; 264 1.1 enami 265 1.34 mycroft error = pcmcia_function_enable(psc->sc_pf); 266 1.34 mycroft if (error) { 267 1.17 enami pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 268 1.34 mycroft psc->sc_ih = 0; 269 1.17 enami } 270 1.16 enami 271 1.44 tsutsui return error; 272 1.1 enami } 273 1.1 enami 274 1.1 enami void 275 1.44 tsutsui mbe_pcmcia_disable(struct mb86960_softc *sc) 276 1.1 enami { 277 1.44 tsutsui struct mbe_pcmcia_softc *psc = (struct mbe_pcmcia_softc *)sc; 278 1.1 enami 279 1.1 enami pcmcia_function_disable(psc->sc_pf); 280 1.17 enami pcmcia_intr_disestablish(psc->sc_pf, psc->sc_ih); 281 1.34 mycroft psc->sc_ih = 0; 282 1.25 ichiro } 283 1.25 ichiro 284 1.25 ichiro int 285 1.44 tsutsui mbe_pcmcia_get_enaddr_from_io(struct mbe_pcmcia_softc *psc, 286 1.44 tsutsui struct mbe_pcmcia_get_enaddr_args *ea) 287 1.37 perry { 288 1.34 mycroft struct mb86960_softc *sc = &psc->sc_mb86960; 289 1.25 ichiro int i; 290 1.25 ichiro 291 1.25 ichiro for (i = 0; i < ETHER_ADDR_LEN; i++) 292 1.34 mycroft ea->enaddr[i] = bus_space_read_1(sc->sc_bst, sc->sc_bsh, 293 1.34 mycroft FE_MBH_ENADDR + i); 294 1.44 tsutsui return 0; 295 1.18 is } 296 1.18 is 297 1.18 is int 298 1.44 tsutsui mbe_pcmcia_get_enaddr_from_mem(struct mbe_pcmcia_softc *psc, 299 1.44 tsutsui struct mbe_pcmcia_get_enaddr_args *ea) 300 1.18 is { 301 1.18 is struct mb86960_softc *sc = &psc->sc_mb86960; 302 1.18 is struct pcmcia_mem_handle pcmh; 303 1.22 soren bus_size_t offset; 304 1.20 enami int i, mwindow, rv = 1; 305 1.18 is 306 1.18 is if (ea->maddr < 0) 307 1.20 enami goto bad_memaddr; 308 1.18 is 309 1.18 is if (pcmcia_mem_alloc(psc->sc_pf, ETHER_ADDR_LEN * 2, &pcmh)) { 310 1.44 tsutsui aprint_error_dev(sc->sc_dev, "can't alloc mem for enet addr\n"); 311 1.20 enami goto memalloc_failed; 312 1.18 is } 313 1.18 is 314 1.18 is if (pcmcia_mem_map(psc->sc_pf, PCMCIA_MEM_ATTR, ea->maddr, 315 1.19 enami ETHER_ADDR_LEN * 2, &pcmh, &offset, &mwindow)) { 316 1.44 tsutsui aprint_error_dev(sc->sc_dev, "can't map mem for enet addr\n"); 317 1.20 enami goto memmap_failed; 318 1.18 is } 319 1.18 is 320 1.18 is for (i = 0; i < ETHER_ADDR_LEN; i++) 321 1.18 is ea->enaddr[i] = bus_space_read_1(pcmh.memt, pcmh.memh, 322 1.19 enami offset + (i * 2)); 323 1.18 is 324 1.20 enami rv = 0; 325 1.18 is pcmcia_mem_unmap(psc->sc_pf, mwindow); 326 1.20 enami memmap_failed: 327 1.18 is pcmcia_mem_free(psc->sc_pf, &pcmh); 328 1.20 enami memalloc_failed: 329 1.20 enami bad_memaddr: 330 1.18 is 331 1.44 tsutsui return rv; 332 1.1 enami } 333