1 /* $NetBSD: if_fxp_cardbus.c,v 1.12 2000/05/08 18:23:36 thorpej Exp $ */ 2 3 /* 4 * Copyright (c) 1999 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Johan Danielsson. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 3. All advertising materials mentioning features or use of this software 19 * must display the following acknowledgement: 20 * This product includes software developed by the NetBSD 21 * Foundation, Inc. and its contributors. 22 * 4. Neither the name of The NetBSD Foundation nor the names of its 23 * contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36 * POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 /* 40 * CardBus front-end for the Intel i82557 family of Ethernet chips. 41 */ 42 43 #include "opt_inet.h" 44 #include "opt_ns.h" 45 #include "bpfilter.h" 46 #include "rnd.h" 47 48 #include <sys/param.h> 49 #include <sys/systm.h> 50 #include <sys/mbuf.h> 51 #include <sys/malloc.h> 52 #include <sys/kernel.h> 53 #include <sys/socket.h> 54 #include <sys/ioctl.h> 55 #include <sys/errno.h> 56 #include <sys/device.h> 57 58 #if NRND > 0 59 #include <sys/rnd.h> 60 #endif 61 62 #include <net/if.h> 63 #include <net/if_dl.h> 64 #include <net/if_media.h> 65 #include <net/if_ether.h> 66 67 #include <machine/endian.h> 68 69 #if NBPFILTER > 0 70 #include <net/bpf.h> 71 #endif 72 73 #ifdef INET 74 #include <netinet/in.h> 75 #include <netinet/if_inarp.h> 76 #endif 77 78 #ifdef NS 79 #include <netns/ns.h> 80 #include <netns/ns_if.h> 81 #endif 82 83 #include <machine/bus.h> 84 #include <machine/intr.h> 85 86 #include <dev/mii/miivar.h> 87 88 #include <dev/ic/i82557reg.h> 89 #include <dev/ic/i82557var.h> 90 91 #include <dev/pci/pcivar.h> 92 #include <dev/pci/pcireg.h> 93 #include <dev/pci/pcidevs.h> 94 95 #include <dev/cardbus/cardbusvar.h> 96 #include <dev/cardbus/cardbusdevs.h> 97 98 static int fxp_cardbus_match __P((struct device *, struct cfdata *, void *)); 99 static void fxp_cardbus_attach __P((struct device *, struct device *, void *)); 100 static int fxp_cardbus_detach __P((struct device * self, int flags)); 101 static void fxp_cardbus_setup __P((struct fxp_softc * sc)); 102 static int fxp_cardbus_enable __P((struct fxp_softc * sc)); 103 static void fxp_cardbus_disable __P((struct fxp_softc * sc)); 104 105 struct fxp_cardbus_softc { 106 struct fxp_softc sc; 107 cardbus_devfunc_t ct; 108 pcireg_t base0_reg; 109 pcireg_t base1_reg; 110 bus_size_t size; 111 }; 112 113 struct cfattach fxp_cardbus_ca = { 114 sizeof(struct fxp_cardbus_softc), fxp_cardbus_match, fxp_cardbus_attach, 115 fxp_cardbus_detach, fxp_activate 116 }; 117 118 #ifdef CBB_DEBUG 119 #define DPRINTF(X) printf X 120 #else 121 #define DPRINTF(X) 122 #endif 123 124 static int 125 fxp_cardbus_match(parent, match, aux) 126 struct device *parent; 127 struct cfdata *match; 128 void *aux; 129 { 130 struct cardbus_attach_args *ca = aux; 131 132 if (CARDBUS_VENDOR(ca->ca_id) == CARDBUS_VENDOR_INTEL && 133 CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_INTEL_82557) 134 return (1); 135 136 return (0); 137 } 138 139 static void 140 fxp_cardbus_attach(parent, self, aux) 141 struct device *parent, *self; 142 void *aux; 143 { 144 static const char thisfunc[] = "fxp_cardbus_attach"; 145 146 struct fxp_softc *sc = (struct fxp_softc *) self; 147 struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) self; 148 struct cardbus_attach_args *ca = aux; 149 bus_space_tag_t iot, memt; 150 bus_space_handle_t ioh, memh; 151 152 bus_addr_t adr; 153 bus_size_t size; 154 155 csc->ct = ca->ca_ct; 156 157 /* 158 * Map control/status registers. 159 */ 160 if (Cardbus_mapreg_map(csc->ct, CARDBUS_BASE1_REG, 161 PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, &adr, &size) == 0) { 162 csc->base1_reg = adr | 1; 163 sc->sc_st = iot; 164 sc->sc_sh = ioh; 165 csc->size = size; 166 } else if (Cardbus_mapreg_map(csc->ct, CARDBUS_BASE0_REG, 167 PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT, 168 0, &memt, &memh, &adr, &size) == 0) { 169 csc->base0_reg = adr; 170 sc->sc_st = memt; 171 sc->sc_sh = memh; 172 csc->size = size; 173 } else 174 panic("%s: failed to allocate mem and io space", thisfunc); 175 176 177 if (ca->ca_cis.cis1_info[0] && ca->ca_cis.cis1_info[1]) 178 printf(": %s %s\n", ca->ca_cis.cis1_info[0], 179 ca->ca_cis.cis1_info[1]); 180 else 181 printf("\n"); 182 183 sc->sc_dmat = ca->ca_dmat; 184 sc->sc_enable = fxp_cardbus_enable; 185 sc->sc_disable = fxp_cardbus_disable; 186 sc->sc_enabled = 0; 187 188 fxp_enable(sc); 189 fxp_attach(sc); 190 fxp_disable(sc); 191 } 192 193 static void 194 fxp_cardbus_setup(struct fxp_softc * sc) 195 { 196 struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) sc; 197 struct cardbus_softc *psc = 198 (struct cardbus_softc *) sc->sc_dev.dv_parent; 199 cardbus_chipset_tag_t cc = psc->sc_cc; 200 cardbus_function_tag_t cf = psc->sc_cf; 201 pcireg_t command; 202 203 cardbustag_t tag = cardbus_make_tag(cc, cf, csc->ct->ct_bus, 204 csc->ct->ct_dev, csc->ct->ct_func); 205 206 command = Cardbus_conf_read(csc->ct, tag, CARDBUS_COMMAND_STATUS_REG); 207 if (csc->base0_reg) { 208 Cardbus_conf_write(csc->ct, tag, 209 CARDBUS_BASE0_REG, csc->base0_reg); 210 (cf->cardbus_ctrl) (cc, CARDBUS_MEM_ENABLE); 211 command |= CARDBUS_COMMAND_MEM_ENABLE | 212 CARDBUS_COMMAND_MASTER_ENABLE; 213 } else if (csc->base1_reg) { 214 Cardbus_conf_write(csc->ct, tag, 215 CARDBUS_BASE1_REG, csc->base1_reg); 216 (cf->cardbus_ctrl) (cc, CARDBUS_IO_ENABLE); 217 command |= (CARDBUS_COMMAND_IO_ENABLE | 218 CARDBUS_COMMAND_MASTER_ENABLE); 219 } 220 221 (cf->cardbus_ctrl) (cc, CARDBUS_BM_ENABLE); 222 223 /* enable the card */ 224 Cardbus_conf_write(csc->ct, tag, CARDBUS_COMMAND_STATUS_REG, command); 225 } 226 227 static int 228 fxp_cardbus_enable(struct fxp_softc * sc) 229 { 230 struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) sc; 231 struct cardbus_softc *psc = 232 (struct cardbus_softc *) sc->sc_dev.dv_parent; 233 cardbus_chipset_tag_t cc = psc->sc_cc; 234 cardbus_function_tag_t cf = psc->sc_cf; 235 236 Cardbus_function_enable(csc->ct); 237 238 fxp_cardbus_setup(sc); 239 240 /* Map and establish the interrupt. */ 241 242 sc->sc_ih = cardbus_intr_establish(cc, cf, psc->sc_intrline, IPL_NET, 243 fxp_intr, sc); 244 if (NULL == sc->sc_ih) { 245 printf("%s: couldn't establish interrupt\n", 246 sc->sc_dev.dv_xname); 247 return 1; 248 } 249 250 printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname, 251 psc->sc_intrline); 252 253 return 0; 254 } 255 256 static void 257 fxp_cardbus_disable(struct fxp_softc * sc) 258 { 259 struct cardbus_softc *psc = 260 (struct cardbus_softc *) sc->sc_dev.dv_parent; 261 cardbus_chipset_tag_t cc = psc->sc_cc; 262 cardbus_function_tag_t cf = psc->sc_cf; 263 264 /* Remove interrupt handler. */ 265 cardbus_intr_disestablish(cc, cf, sc->sc_ih); 266 267 Cardbus_function_disable(((struct fxp_cardbus_softc *) sc)->ct); 268 } 269 270 static int 271 fxp_cardbus_detach(self, flags) 272 struct device *self; 273 int flags; 274 { 275 struct fxp_softc *sc = (struct fxp_softc *) self; 276 struct fxp_cardbus_softc *csc = (struct fxp_cardbus_softc *) self; 277 struct cardbus_devfunc *ct = csc->ct; 278 int rv, reg; 279 280 #ifdef DIAGNOSTIC 281 if (ct == NULL) 282 panic("%s: data structure lacks\n", sc->sc_dev.dv_xname); 283 #endif 284 285 rv = fxp_detach(sc); 286 if (rv == 0) { 287 /* 288 * Unhook the interrupt handler. 289 */ 290 cardbus_intr_disestablish(ct->ct_cc, ct->ct_cf, sc->sc_ih); 291 292 /* 293 * release bus space and close window 294 */ 295 if (csc->base0_reg) 296 reg = CARDBUS_BASE0_REG; 297 else 298 reg = CARDBUS_BASE1_REG; 299 Cardbus_mapreg_unmap(ct, reg, sc->sc_st, sc->sc_sh, csc->size); 300 } 301 return (rv); 302 } 303