Home | History | Annotate | Line # | Download | only in cardbus
if_ex_cardbus.c revision 1.4
      1 /*	$NetBSD: if_ex_cardbus.c,v 1.4 1999/10/25 19:18:10 drochner 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 #include <machine/cpu.h>
     70 #include <machine/pio.h>
     71 #include <machine/bus.h>
     72 #if defined pciinc
     73 #include <dev/pci/pcidevs.h>
     74 #endif
     75 #if pccard
     76 #include <dev/pccard/cardbusvar.h>
     77 #include <dev/pccard/pccardcis.h>
     78 #else
     79 #include <dev/cardbus/cardbusvar.h>
     80 #include <dev/cardbus/cardbusdevs.h>
     81 #endif
     82 
     83 #include <dev/mii/miivar.h>
     84 
     85 #include <dev/ic/elink3var.h>
     86 #include <dev/ic/elink3reg.h>
     87 #include <dev/ic/elinkxlreg.h>
     88 #include <dev/ic/elinkxlvar.h>
     89 
     90 #if defined DEBUG && !defined EX_DEBUG
     91 #define EX_DEBUG
     92 #endif
     93 
     94 #if defined EX_DEBUG
     95 #define STATIC
     96 #define DPRINTF(a) printf a
     97 #else
     98 #define STATIC static
     99 #define DPRINTF(a)
    100 #endif
    101 
    102 #define CARDBUS_3C575BTX_FUNCSTAT_PCIREG  CARDBUS_BASE2_REG  /* means 0x18 */
    103 #define EX_CB_INTR 4		/* intr acknowledge reg. CardBus only */
    104 #define EX_CB_INTR_ACK 0x8000 /* intr acknowledge bit */
    105 
    106 
    107 /* Definitions, most of them has turned out to be unneccesary, but here they
    108  * are anyway.
    109  */
    110 
    111 
    112 STATIC int ex_cardbus_match __P((struct device *, struct cfdata *, void *));
    113 STATIC void ex_cardbus_attach __P((struct device *, struct device *,void *));
    114 STATIC int ex_cardbus_detach __P((struct device *, int));
    115 STATIC void ex_cardbus_intr_ack __P((struct ex_softc *));
    116 
    117 #if 0
    118 static void expoll __P((void *arg));
    119 #endif
    120 
    121 #if !defined EX_POWER_STATIC
    122 STATIC int ex_cardbus_enable __P((struct ex_softc *sc));
    123 STATIC void ex_cardbus_disable __P((struct ex_softc *sc));
    124 #endif /* !defined EX_POWER_STATIC */
    125 
    126 
    127 struct ex_cardbus_softc {
    128   struct ex_softc sc_softc;
    129 
    130   cardbus_devfunc_t sc_ct;
    131   int sc_intrline;
    132   u_int8_t sc_cardbus_flags;
    133 #define EX_REATTACH		0x01
    134 #define EX_ABSENT		0x02
    135   u_int8_t sc_cardtype;
    136 #define EX_3C575		1
    137 #define EX_3C575B		2
    138 
    139   /* CardBus function status space.  575B requests it. */
    140   bus_space_tag_t sc_funct;
    141   bus_space_handle_t sc_funch;
    142 };
    143 
    144 struct cfattach ex_cardbus_ca = {
    145   sizeof(struct ex_cardbus_softc), ex_cardbus_match,
    146   ex_cardbus_attach, ex_cardbus_detach
    147 };
    148 
    149 
    150 
    151 STATIC int
    152 ex_cardbus_match(parent, cf, aux)
    153      struct device *parent;
    154      struct cfdata *cf;
    155      void *aux;
    156 {
    157   struct cardbus_attach_args *ca = aux;
    158 
    159   if ((CARDBUS_VENDOR(ca->ca_id) == CARDBUS_VENDOR_3COM)) {
    160     if (CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575TX
    161 	|| CARDBUS_PRODUCT(ca->ca_id) == CARDBUS_PRODUCT_3COM_3C575BTX) {
    162       return 1;
    163     }
    164   }
    165   return 0;
    166 }
    167 
    168 
    169 
    170 
    171 
    172 
    173 STATIC void
    174 ex_cardbus_attach(parent, self, aux)
    175      struct device *parent;
    176      struct device *self;
    177      void *aux;
    178 {
    179   struct ex_cardbus_softc *psc = (void *)self;
    180   struct ex_softc *sc = &psc->sc_softc;
    181   struct cardbus_attach_args *ca = aux;
    182   cardbus_devfunc_t ct = ca->ca_ct;
    183   cardbus_chipset_tag_t cc = ct->ct_cc;
    184   cardbus_function_tag_t cf = ct->ct_cf;
    185   cardbusreg_t iob, command, bhlc;
    186   bus_space_handle_t ioh;
    187   bus_addr_t adr;
    188 
    189 
    190   if (cardbus_mapreg_map(ct, CARDBUS_BASE0_REG, CARDBUS_MAPREG_TYPE_IO, 0,
    191 			 &(sc->sc_iot), &ioh, &adr, NULL)) {
    192     panic("io alloc in ex_attach_cardbus\n");
    193   }
    194   iob = adr;
    195   sc->sc_ioh = ioh;
    196 
    197 #if rbus
    198 #else
    199   (ct->ct_cf->cardbus_io_open)(cc, 0, iob, iob + 0x40);
    200 #endif
    201   (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_IO_ENABLE);
    202 
    203   /* enable the card */
    204   command = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG);
    205 
    206   /* Card specific configuration */
    207   switch (CARDBUS_PRODUCT(ca->ca_id)) {
    208   case CARDBUS_PRODUCT_3COM_3C575TX:
    209     psc->sc_cardtype = EX_3C575;
    210     command |= (CARDBUS_COMMAND_IO_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE);
    211     printf(": 3Com 3C575TX (boomerang)\n");
    212     break;
    213   case CARDBUS_PRODUCT_3COM_3C575BTX:
    214     psc->sc_cardtype = EX_3C575B;
    215     command |= (CARDBUS_COMMAND_IO_ENABLE |
    216 		CARDBUS_COMMAND_MEM_ENABLE | CARDBUS_COMMAND_MASTER_ENABLE);
    217 
    218     /* Cardbus function status window */
    219     if (cardbus_mapreg_map(ct, CARDBUS_3C575BTX_FUNCSTAT_PCIREG,
    220 			   CARDBUS_MAPREG_TYPE_MEM, 0,
    221 			   &psc->sc_funct, &psc->sc_funch, 0, NULL)) {
    222       panic("mem alloc in ex_attach_cardbus\n");
    223     }
    224 
    225     /*
    226      * Make sure CardBus brigde can access memory space.  Usually
    227      * memory access is enabled by BIOS, but some BIOSes do not enable
    228      * it.
    229      */
    230     (ct->ct_cf->cardbus_ctrl)(cc, CARDBUS_MEM_ENABLE);
    231 
    232     /* Setup interrupt acknowledge hook */
    233     sc->intr_ack = ex_cardbus_intr_ack;
    234 
    235     printf(": 3Com 3C575BTX (cyclone)\n");
    236     break;
    237   }
    238 
    239   cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_COMMAND_STATUS_REG, command);
    240 
    241   /*
    242    * set latency timmer
    243    */
    244   bhlc = cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG);
    245   if (CARDBUS_LATTIMER(bhlc) < 0x20) {
    246     /* at least the value of latency timer should 0x20. */
    247     DPRINTF(("if_ex_cardbus: lattimer 0x%x -> 0x20\n",
    248 	     CARDBUS_LATTIMER(bhlc)));
    249     bhlc &= ~(CARDBUS_LATTIMER_MASK << CARDBUS_LATTIMER_SHIFT);
    250     bhlc |= (0x20 << CARDBUS_LATTIMER_SHIFT);
    251     cardbus_conf_write(cc, cf, ca->ca_tag, CARDBUS_BHLC_REG, bhlc);
    252   }
    253 
    254   sc->sc_dmat = ca->ca_dmat;
    255   sc->ex_bustype = EX_BUS_CARDBUS;
    256   psc->sc_ct = ca->ca_ct;
    257   psc->sc_intrline = ca->ca_intrline;
    258 
    259   switch (psc->sc_cardtype) {
    260   case EX_3C575:
    261     sc->ex_conf = EX_CONF_MII|EX_CONF_INTPHY;
    262     break;
    263   case EX_3C575B:
    264     sc->ex_conf = EX_CONF_90XB|EX_CONF_MII|EX_CONF_INTPHY;
    265     break;
    266   }
    267 
    268 #if !defined EX_POWER_STATIC
    269   sc->enable = ex_cardbus_enable;
    270   sc->disable = ex_cardbus_disable;
    271 #else
    272   sc->enable = NULL;
    273   sc->disable = NULL;
    274 #endif
    275   sc->enabled = 1;
    276 
    277 
    278 #if defined EX_POWER_STATIC
    279   /* Map and establish the interrupt. */
    280 
    281   sc->sc_ih = cardbus_intr_establish(cc, cf, ca->ca_intrline, IPL_NET,
    282 				     ex_intr, psc);
    283   if (sc->sc_ih == NULL) {
    284     printf("%s: couldn't establish interrupt",
    285 	   sc->sc_dev.dv_xname);
    286     printf(" at %d", ca->ca_intrline);
    287     printf("\n");
    288     return;
    289   }
    290   printf("%s: interrupting at %d\n", sc->sc_dev.dv_xname, ca->ca_intrline);
    291 #endif
    292 
    293 #if 0
    294   timeout(expoll, sc, hz/20);	/* XXX */
    295 #endif
    296 
    297   bus_space_write_2(sc->sc_iot, sc->sc_ioh, ELINK_COMMAND, GLOBAL_RESET);
    298   delay(400);
    299   {
    300     int i = 0;
    301     while (bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS) \
    302 	   & S_COMMAND_IN_PROGRESS) {
    303       if (++i > 10000) {
    304 	printf("ex: timeout %x\n", bus_space_read_2((sc)->sc_iot, (sc)->sc_ioh, ELINK_STATUS));
    305 	printf("ex: addr %x\n", cardbus_conf_read(cc, cf, ca->ca_tag, CARDBUS_BASE0_REG));
    306 	return;			/* emargency exit */
    307       }
    308     }
    309   }
    310 
    311   ex_config(sc); /* I'm BOOMERANG or CYCLONE */
    312 
    313   if (psc->sc_cardtype == EX_3C575B) {
    314     bus_space_write_4(psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK);
    315   }
    316 
    317 #if !defined EX_POWER_STATIC
    318   cardbus_function_disable(psc->sc_ct);
    319   sc->enabled = 0;
    320 #endif
    321   return;
    322 }
    323 
    324 
    325 
    326 STATIC void
    327 ex_cardbus_intr_ack(sc)
    328      struct ex_softc *sc;
    329 {
    330   struct ex_cardbus_softc *psc = (struct ex_cardbus_softc *)sc;
    331   bus_space_write_4 (psc->sc_funct, psc->sc_funch, EX_CB_INTR, EX_CB_INTR_ACK);
    332 }
    333 
    334 
    335 STATIC int
    336 ex_cardbus_detach(self, arg)
    337      struct device *self;
    338      int arg;
    339 {
    340   struct ex_cardbus_softc *psc = (void *)self;
    341   struct ex_softc *sc = &psc->sc_softc;
    342   cardbus_function_tag_t cf = psc->sc_ct->ct_cf;
    343   cardbus_chipset_tag_t cc = psc->sc_ct->ct_cc;
    344 
    345   /*
    346    * XXX Currently, no detach.
    347    */
    348   printf("- ex_cardbus_detach\n");
    349 
    350   cardbus_intr_disestablish(cc, cf, sc->sc_ih);
    351 
    352   sc->enabled = 0;
    353 
    354   return EBUSY;
    355 }
    356 
    357 
    358 
    359 #if !defined EX_POWER_STATIC
    360 STATIC int
    361 ex_cardbus_enable(sc)
    362      struct ex_softc *sc;
    363 {
    364   struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
    365   cardbus_function_tag_t cf = csc->sc_ct->ct_cf;
    366   cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc;
    367 
    368   cardbus_function_enable(csc->sc_ct);
    369   cardbus_restore_bar(csc->sc_ct);
    370 
    371   sc->sc_ih = cardbus_intr_establish(cc, cf, csc->sc_intrline, IPL_NET, ex_intr, sc);
    372   if (NULL == sc->sc_ih) {
    373     printf("%s: couldn't establish interrupt\n", sc->sc_dev.dv_xname);
    374     return 1;
    375   }
    376 
    377 /*  printf("ex_pccard_enable: %s turned on\n", sc->sc_dev.dv_xname); */
    378   return 0;
    379 }
    380 
    381 
    382 
    383 
    384 STATIC void
    385 ex_cardbus_disable(sc)
    386      struct ex_softc *sc;
    387 {
    388   struct ex_cardbus_softc *csc = (struct ex_cardbus_softc *)sc;
    389   cardbus_function_tag_t cf = csc->sc_ct->ct_cf;
    390   cardbus_chipset_tag_t cc = csc->sc_ct->ct_cc;
    391 
    392   cardbus_save_bar(csc->sc_ct);
    393 
    394   cardbus_function_disable(csc->sc_ct);
    395 
    396   cardbus_intr_disestablish(cc, cf, sc->sc_ih);
    397 }
    398 
    399 #endif /* EX_POWER_STATIC */
    400