Home | History | Annotate | Line # | Download | only in cardbus
if_ex_cardbus.c revision 1.3
      1 /*	$NetBSD: if_ex_cardbus.c,v 1.3 1999/10/15 10:59:57 augustss Exp $	*/
      2 
      3 /*
      4  * CardBus specific routines for 3Com 3C575-family CardBus ethernet adapter
      5  *
      6  * Copyright (c) 1998 and 1999
      7  *       HAYAKAWA Koichi.  All rights reserved.
      8  *
      9  * Redistribution and use in source and binary forms, with or without
     10  * modification, are permitted provided that the following conditions
     11  * are met:
     12  * 1. Redistributions of source code must retain the above copyright
     13  *    notice, this list of conditions and the following disclaimer.
     14  * 2. Redistributions in binary form must reproduce the above copyright
     15  *    notice, this list of conditions and the following disclaimer in the
     16  *    documentation and/or other materials provided with the distribution.
     17  * 3. All advertising materials mentioning features or use of this software
     18  *    must display the following acknowledgement:
     19  *      This product includes software developed by the author.
     20  * 4. Neither the name of the author nor the names of any co-contributors
     21  *    may be used to endorse or promote products derived from this software
     22  *    without specific prior written permission.
     23  *
     24  * THIS SOFTWARE IS PROVIDED BY HAYAKAWA KOICHI ``AS IS'' AND
     25  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     26  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     27  * ARE DISCLAIMED.  IN NO EVENT SHALL TAKESHI OHASHI OR CONTRIBUTORS BE LIABLE
     28  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     29  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     30  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     31  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     32  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     33  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     34  * SUCH DAMAGE.
     35  *
     36  *
     37  */
     38 
     39 
     40 /* #define EX_DEBUG 4 */	/* define to report infomation for debugging */
     41 
     42 #define EX_POWER_STATIC		/* do not use enable/disable functions */
     43 				/* I'm waiting elinkxl.c uses
     44                                    sc->enable and sc->disable
     45                                    functions. */
     46 
     47 #include <sys/param.h>
     48 #include <sys/systm.h>
     49 #include <sys/kernel.h>
     50 #include <sys/conf.h>
     51 #include <sys/ioctl.h>
     52 #include <sys/device.h>
     53 #include <sys/errno.h>
     54 #include <sys/syslog.h>
     55 /* #include <sys/signalvar.h> */
     56 #include <sys/mbuf.h>
     57 #include <sys/socket.h>
     58 #include <sys/ioctl.h>
     59 #include <sys/select.h>
     60 #include <sys/queue.h>
     61 
     62 #include <net/if.h>
     63 #include <net/if_dl.h>
     64 #include <net/if_media.h>
     65 #include <net/if_types.h>
     66 #include <net/netisr.h>
     67 #include <net/if_ether.h>
     68 
     69 #if defined INET
     70 #include <netinet/in.h>
     71 #include <netinet/in_systm.h>
     72 #include <netinet/in_var.h>
     73 #include <netinet/ip.h>
     74 #endif
     75 
     76 #ifdef NS
     77 #include <netns/ns.h>
     78 #include <netns/ns_if.h>
     79 #endif
     80 
     81 #if NBPFILTER > 0
     82 #include <net/bpf.h>
     83 #include <net/bpfdesc.h>
     84 #endif
     85 
     86 #include <machine/cpu.h>
     87 #include <machine/pio.h>
     88 #include <machine/bus.h>
     89 #if defined pciinc
     90 #include <dev/pci/pcidevs.h>
     91 #endif
     92 #if pccard
     93 #include <dev/pccard/cardbusvar.h>
     94 #include <dev/pccard/pccardcis.h>
     95 #else
     96 #include <dev/cardbus/cardbusvar.h>
     97 #include <dev/cardbus/cardbusdevs.h>
     98 #endif
     99 
    100 #include <dev/mii/miivar.h>
    101 
    102 #include <dev/ic/elink3var.h>
    103 #include <dev/ic/elink3reg.h>
    104 #include <dev/ic/elinkxlreg.h>
    105 #include <dev/ic/elinkxlvar.h>
    106 
    107 #if defined DEBUG && !defined EX_DEBUG
    108 #define EX_DEBUG
    109 #endif
    110 
    111 #if defined EX_DEBUG
    112 #define STATIC
    113 #define DPRINTF(a) printf a
    114 #else
    115 #define STATIC static
    116 #define DPRINTF(a)
    117 #endif
    118 
    119 #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG  CARDBUS_BASE2_REG  /* means 0x18 */
    120 #define EX_CB_INTR 4		/* intr acknowledge reg. CardBus only */
    121 #define EX_CB_INTR_ACK 0x8000 /* intr acknowledge bit */
    122 
    123 
    124 /* Definitions, most of them has turned out to be unneccesary, but here they
    125  * are anyway.
    126  */
    127 
    128 
    129 STATIC int ex_cardbus_match __P((struct device *, struct cfdata *, void *));
    130 STATIC void ex_cardbus_attach __P((struct device *, struct device *,void *));
    131 STATIC int ex_cardbus_detach __P((struct device *, int));
    132 STATIC void ex_cardbus_intr_ack __P((struct ex_softc *));
    133 
    134 #if 0
    135 static void expoll __P((void *arg));
    136 #endif
    137 
    138 #if !defined EX_POWER_STATIC
    139 STATIC int ex_cardbus_enable __P((struct ex_softc *sc));
    140 STATIC void ex_cardbus_disable __P((struct ex_softc *sc));
    141 #endif /* !defined EX_POWER_STATIC */
    142 
    143 
    144 struct ex_cardbus_softc {
    145   struct ex_softc sc_softc;
    146 
    147   cardbus_devfunc_t sc_ct;
    148   int sc_intrline;
    149   u_int8_t sc_cardbus_flags;
    150 #define EX_REATTACH		0x01
    151 #define EX_ABSENT		0x02
    152   u_int8_t sc_cardtype;
    153 #define EX_3C575		1
    154 #define EX_3C575B		2
    155 
    156   /* CardBus function status space.  575B requests it. */
    157   bus_space_tag_t sc_funct;
    158   bus_space_handle_t sc_funch;
    159 };
    160 
    161 struct cfattach ex_cardbus_ca = {
    162   sizeof(struct ex_cardbus_softc), ex_cardbus_match,
    163   ex_cardbus_attach, ex_cardbus_detach
    164 };
    165 
    166 
    167 
    168 STATIC int
    169 ex_cardbus_match(parent, cf, aux)
    170      struct device *parent;
    171      struct cfdata *cf;
    172      void *aux;
    173 {
    174   struct cardbus_attach_args *ca = aux;
    175 
    176   if ((CARDBUS_VENDOR(ca->ca_id) == CARDBUS_VENDOR_3COM)) {
    177     if (CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575TX
    178 	|| CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575BTX) {
    179       return 1;
    180     }
    181   }
    182   return 0;
    183 }
    184 
    185 
    186 
    187 
    188 
    189 
    190 STATIC void
    191 ex_cardbus_attach(parent, self, aux)
    192      struct device *parent;
    193      struct device *self;
    194      void *aux;
    195 {
    196   struct ex_cardbus_softc *psc = (void *)self;
    197   struct ex_softc *sc = &psc->sc_softc;
    198   struct cardbus_attach_args *ca = aux;
    199   cardbus_devfunc_t ct = ca->ca_ct;
    200   cardbus_chipset_tag_t cc = ct->ct_cc;
    201   cardbus_function_tag_t cf = ct->ct_cf;
    202   cardbusreg_t iob, command, bhlc;
    203   bus_space_handle_t ioh;
    204   bus_addr_t adr;
    205 
    206 
    207   if (cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0,
    208 			 &(sc->sc_iot), &ioh, &adr, NULL)) {
    209     panic("io alloc in ex_attach_cardbus\n");
    210   }
    211   iob = adr;
    212   sc->sc_ioh = ioh;
    213 
    214 #if rbus
    215 #else
    216   (ct->ct_cf->cardbus_io_open)(cc, 0, iob, iob + 0x40);
    217 #endif
    218   (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
    219 
    220   /* enable the card */
    221   command = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG);
    222 
    223   /* Card specific configuration */
    224   switch (CARDBUS_PRODUCT(ca->ca_id)) {
    225   case CARDBUS_PRODUCT_3COM_3C575TX:
    226     psc->sc_cardtype = EX_3C575;
    227     command |= (CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE);
    228     printf(": 3Com 3C575TX (boomerang)\n");
    229     break;
    230   case CARDBUS_PRODUCT_3COM_3C575BTX:
    231     psc->sc_cardtype = EX_3C575B;
    232     command |= (CARDBUS_COMMAND_IO_ENABLE |
    233 		CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE);
    234 
    235     /* Cardbus function status window */
    236     if (cardbus_mapreg_map(ct, CARDBUS_3C575BTX_FUNCSTAT_PCIREG,
    237 			   CARDBUS_MAPREG_TYPE_MEM, 0,
    238 			   &psc->sc_funct, &psc->sc_funch, 0, NULL)) {
    239       panic("mem alloc in ex_attach_cardbus\n");
    240     }
    241 
    242     /*
    243      * Make sure CardBus brigde can access memory space.  Usually
    244      * memory access is enabled by BIOS, but some BIOSes do not enable
    245      * it.
    246      */
    247     (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
    248 
    249     /* Setup interrupt acknowledge hook */
    250     sc->intr_ack = ex_cardbus_intr_ack;
    251 
    252     printf(": 3Com 3C575BTX (cyclone)\n");
    253     break;
    254   }
    255 
    256   cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG, command);
    257 
    258   /*
    259    * set latency timmer
    260    */
    261   bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG);
    262   if (CARDBUS_LATTIMER(bhlc) < 0x20) {
    263     /* at least the value of latency timer should 0x20. */
    264     DPRINTF(("if_ex_cardbus: lattimer 0x%x -> 0x20\n",
    265 	     CARDBUS_LATTIMER(bhlc)));
    266     bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
    267     bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT);
    268     cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc);
    269   }
    270 
    271   sc->sc_dmat = ca->ca_dmat;
    272   sc->ex_bustype = EX_BUS_CARDBUS;
    273   psc->sc_ct = ca->ca_ct;
    274   psc->sc_intrline = ca->ca_intrline;
    275 
    276   switch (psc->sc_cardtype) {
    277   case EX_3C575:
    278     sc->ex_conf = EX_CONF_MII|EX_CONF_INTPHY;
    279     break;
    280   case EX_3C575B:
    281     sc->ex_conf = EX_CONF_90XB|EX_CONF_MII|EX_CONF_INTPHY;
    282     break;
    283   }
    284 
    285 #if !defined EX_POWER_STATIC
    286   sc->enable = ex_cardbus_enable;
    287   sc->disable = ex_cardbus_disable;
    288 #else
    289   sc->enable = NULL;
    290   sc->disable = NULL;
    291 #endif
    292   sc->enabled = 1;
    293 
    294 
    295 #if defined EX_POWER_STATIC
    296   /* Map and establish the interrupt. */
    297 
    298   sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
    299 				     ex_intr, psc);
    300   if (sc->sc_ih == NULL) {
    301     printf("%s: couldn't establish interrupt",
    302 	   sc->sc_dev.dv_xname);
    303     printf(" at %d", ca->ca_intrline);
    304     printf("\n");
    305     return;
    306   }
    307   printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname, ca->ca_intrline);
    308 #endif
    309 
    310 #if 0
    311   timeout(expoll, sc, hz/20);	/* XXX */
    312 #endif
    313 
    314   bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, GLOBAL_RESET);
    315   delay(400);
    316   {
    317     int i = 0;
    318     while (bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS) \
    319 	   & S_COMMAND_IN_PROGRESS) {
    320       if (++i > 10000) {
    321 	printf("ex: timeout %x\n", bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS));
    322 	printf("ex: addr %x\n", cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BASE0_REG));
    323 	return;			/* emargency exit */
    324       }
    325     }
    326   }
    327 
    328   ex_config(sc); /* I'm BOOMERANG or CYCLONE */
    329 
    330   if (psc->sc_cardtype == EX_3C575B) {
    331     bus_space_write_4(psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK);
    332   }
    333 
    334 #if !defined EX_POWER_STATIC
    335   cardbus_function_disable(psc->sc_ct);
    336   sc->enabled = 0;
    337 #endif
    338   return;
    339 }
    340 
    341 
    342 
    343 STATIC void
    344 ex_cardbus_intr_ack(sc)
    345      struct ex_softc *sc;
    346 {
    347   struct ex_cardbus_softc *psc = (struct ex_cardbus_softc *)sc;
    348   bus_space_write_4 (psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK);
    349 }
    350 
    351 
    352 STATIC int
    353 ex_cardbus_detach(self, arg)
    354      struct device *self;
    355      int arg;
    356 {
    357   struct ex_cardbus_softc *psc = (void *)self;
    358   struct ex_softc *sc = &psc->sc_softc;
    359   cardbus_function_tag_t cf = psc->sc_ct->ct_cf;
    360   cardbus_chipset_tag_t cc = psc->sc_ct->ct_cc;
    361 
    362   /*
    363    * XXX Currently, no detach.
    364    */
    365   printf("- ex_cardbus_detach\n");
    366 
    367   cardbus_intr_disestablish(cc, cf, sc->sc_ih);
    368 
    369   sc->enabled = 0;
    370 
    371   return EBUSY;
    372 }
    373 
    374 
    375 
    376 #if !defined EX_POWER_STATIC
    377 STATIC int
    378 ex_cardbus_enable(sc)
    379      struct ex_softc *sc;
    380 {
    381   struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
    382   cardbus_function_tag_t cf = csc->sc_ct->ct_cf;
    383   cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc;
    384 
    385   cardbus_function_enable(csc->sc_ct);
    386   cardbus_restore_bar(csc->sc_ct);
    387 
    388   sc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, ex_intr, sc);
    389   if (NULL == sc->sc_ih) {
    390     printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname);
    391     return 1;
    392   }
    393 
    394 /*  printf("ex_pccard_enable: %s turned on\n", sc->sc_dev.dv_xname); */
    395   return 0;
    396 }
    397 
    398 
    399 
    400 
    401 STATIC void
    402 ex_cardbus_disable(sc)
    403      struct ex_softc *sc;
    404 {
    405   struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
    406   cardbus_function_tag_t cf = csc->sc_ct->ct_cf;
    407   cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc;
    408 
    409   cardbus_save_bar(csc->sc_ct);
    410 
    411   cardbus_function_disable(csc->sc_ct);
    412 
    413   cardbus_intr_disestablish(cc, cf, sc->sc_ih);
    414 }
    415 
    416 #endif /* EX_POWER_STATIC */
    417