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