The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/dev/isa/if_ix.c

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*      $NetBSD: if_ix.c,v 1.17.8.1 2004/07/23 22:46:49 he Exp $        */
    2 
    3 /*-
    4  * Copyright (c) 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Rafal K. Boni.
    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 #include <sys/cdefs.h>
   40 __KERNEL_RCSID(0, "$NetBSD: if_ix.c,v 1.17.8.1 2004/07/23 22:46:49 he Exp $");
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/mbuf.h>
   45 #include <sys/errno.h>
   46 #include <sys/device.h>
   47 #include <sys/protosw.h>
   48 #include <sys/socket.h>
   49 
   50 #include <net/if.h>
   51 #include <net/if_dl.h>
   52 #include <net/if_types.h>
   53 #include <net/if_media.h>
   54 #include <net/if_ether.h>
   55 
   56 #include <machine/cpu.h>
   57 #include <machine/bus.h>
   58 #include <machine/intr.h>
   59 
   60 #include <dev/isa/isareg.h>
   61 #include <dev/isa/isavar.h>
   62 
   63 #include <dev/ic/i82586reg.h>
   64 #include <dev/ic/i82586var.h>
   65 #include <dev/isa/if_ixreg.h>
   66 
   67 #ifdef IX_DEBUG
   68 #define DPRINTF(x)      printf x
   69 #else
   70 #define DPRINTF(x)
   71 #endif
   72 
   73 int ix_media[] = {
   74         IFM_ETHER | IFM_10_5,
   75         IFM_ETHER | IFM_10_2,
   76         IFM_ETHER | IFM_10_T,
   77 };
   78 #define NIX_MEDIA       (sizeof(ix_media) / sizeof(ix_media[0]))
   79 
   80 struct ix_softc {
   81         struct ie_softc sc_ie;
   82 
   83         bus_space_tag_t sc_regt;        /* space tag for registers */
   84         bus_space_handle_t sc_regh;     /* space handle for registers */
   85 
   86         u_int8_t        use_pio;        /* use PIO rather than shared mem */
   87         u_int16_t       irq_encoded;    /* encoded IRQ */
   88         void            *sc_ih;         /* interrupt handle */
   89 };
   90 
   91 static void     ix_reset __P((struct ie_softc *, int));
   92 static void     ix_atten __P((struct ie_softc *, int));
   93 static int      ix_intrhook __P((struct ie_softc *, int));
   94 
   95 static void     ix_copyin __P((struct ie_softc *, void *, int, size_t));
   96 static void     ix_copyout __P((struct ie_softc *, const void *, int, size_t));
   97 
   98 static void     ix_bus_barrier __P((struct ie_softc *, int, int, int));
   99 
  100 static u_int16_t ix_read_16 __P((struct ie_softc *, int));
  101 static void     ix_write_16 __P((struct ie_softc *, int, u_int16_t));
  102 static void     ix_write_24 __P((struct ie_softc *, int, int));
  103 static void     ix_zeromem  __P((struct ie_softc *, int, int));
  104 
  105 static void     ix_mediastatus __P((struct ie_softc *, struct ifmediareq *));
  106 
  107 static u_int16_t ix_read_eeprom __P((bus_space_tag_t, bus_space_handle_t, int));
  108 static void     ix_eeprom_outbits __P((bus_space_tag_t, bus_space_handle_t, int, int));
  109 static int      ix_eeprom_inbits  __P((bus_space_tag_t, bus_space_handle_t));
  110 static void     ix_eeprom_clock   __P((bus_space_tag_t, bus_space_handle_t, int));
  111 
  112 int ix_match __P((struct device *, struct cfdata *, void *));
  113 void ix_attach __P((struct device *, struct device *, void *));
  114 
  115 /*
  116  * EtherExpress/16 support routines
  117  */
  118 static void
  119 ix_reset(sc, why)
  120         struct ie_softc *sc;
  121         int why;
  122 {
  123         struct ix_softc* isc = (struct ix_softc *) sc;
  124 
  125         switch (why) {
  126         case CHIP_PROBE:
  127                 bus_space_write_1(isc->sc_regt, isc->sc_regh, IX_ECTRL,
  128                                   IX_RESET_586);
  129                 delay(100);
  130                 bus_space_write_1(isc->sc_regt, isc->sc_regh, IX_ECTRL, 0);
  131                 delay(100);
  132                 break;
  133 
  134         case CARD_RESET:
  135                 break;
  136     }
  137 }
  138 
  139 static void
  140 ix_atten(sc, why)
  141         struct ie_softc *sc;
  142         int why;
  143 {
  144         struct ix_softc* isc = (struct ix_softc *) sc;
  145         bus_space_write_1(isc->sc_regt, isc->sc_regh, IX_ATTN, 0);
  146 }
  147 
  148 static u_int16_t
  149 ix_read_eeprom(iot, ioh, location)
  150         bus_space_tag_t iot;
  151         bus_space_handle_t ioh;
  152         int location;
  153 {
  154         int ectrl, edata;
  155 
  156         ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  157         ectrl &= IX_ECTRL_MASK;
  158         ectrl |= IX_ECTRL_EECS;
  159         bus_space_write_1(iot, ioh, IX_ECTRL, ectrl);
  160 
  161         ix_eeprom_outbits(iot, ioh, IX_EEPROM_READ, IX_EEPROM_OPSIZE1);
  162         ix_eeprom_outbits(iot, ioh, location, IX_EEPROM_ADDR_SIZE);
  163         edata = ix_eeprom_inbits(iot, ioh);
  164         ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  165         ectrl &= ~(IX_RESET_ASIC | IX_ECTRL_EEDI | IX_ECTRL_EECS);
  166         bus_space_write_1(iot, ioh, IX_ECTRL, ectrl);
  167         ix_eeprom_clock(iot, ioh, 1);
  168         ix_eeprom_clock(iot, ioh, 0);
  169         return (edata);
  170 }
  171 
  172 static void
  173 ix_eeprom_outbits(iot, ioh, edata, count)
  174         bus_space_tag_t iot;
  175         bus_space_handle_t ioh;
  176         int edata, count;
  177 {
  178         int ectrl, i;
  179 
  180         ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  181         ectrl &= ~IX_RESET_ASIC;
  182         for (i = count - 1; i >= 0; i--) {
  183                 ectrl &= ~IX_ECTRL_EEDI;
  184                 if (edata & (1 << i)) {
  185                         ectrl |= IX_ECTRL_EEDI;
  186                 }
  187                 bus_space_write_1(iot, ioh, IX_ECTRL, ectrl);
  188                 delay(1);       /* eeprom data must be setup for 0.4 uSec */
  189                 ix_eeprom_clock(iot, ioh, 1);
  190                 ix_eeprom_clock(iot, ioh, 0);
  191         }
  192         ectrl &= ~IX_ECTRL_EEDI;
  193         bus_space_write_1(iot, ioh, IX_ECTRL, ectrl);
  194         delay(1);               /* eeprom data must be held for 0.4 uSec */
  195 }
  196 
  197 static int
  198 ix_eeprom_inbits(iot, ioh)
  199         bus_space_tag_t iot;
  200         bus_space_handle_t ioh;
  201 {
  202         int ectrl, edata, i;
  203 
  204         ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  205         ectrl &= ~IX_RESET_ASIC;
  206         for (edata = 0, i = 0; i < 16; i++) {
  207                 edata = edata << 1;
  208                 ix_eeprom_clock(iot, ioh, 1);
  209                 ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  210                 if (ectrl & IX_ECTRL_EEDO) {
  211                         edata |= 1;
  212                 }
  213                 ix_eeprom_clock(iot, ioh, 0);
  214         }
  215         return (edata);
  216 }
  217 
  218 static void
  219 ix_eeprom_clock(iot, ioh, state)
  220         bus_space_tag_t iot;
  221         bus_space_handle_t ioh;
  222         int state;
  223 {
  224         int ectrl;
  225 
  226         ectrl = bus_space_read_1(iot, ioh, IX_ECTRL);
  227         ectrl &= ~(IX_RESET_ASIC | IX_ECTRL_EESK);
  228         if (state) {
  229                 ectrl |= IX_ECTRL_EESK;
  230         }
  231         bus_space_write_1(iot, ioh, IX_ECTRL, ectrl);
  232         delay(9);               /* EESK must be stable for 8.38 uSec */
  233 }
  234 
  235 static int
  236 ix_intrhook(sc, where)
  237         struct ie_softc *sc;
  238         int where;
  239 {
  240         struct ix_softc* isc = (struct ix_softc *) sc;
  241 
  242         switch (where) {
  243         case INTR_ENTER:
  244                 /* entering ISR: disable card interrupts */
  245                 bus_space_write_1(isc->sc_regt, isc->sc_regh,
  246                                   IX_IRQ, isc->irq_encoded);
  247                 break;
  248 
  249         case INTR_EXIT:
  250                 /* exiting ISR: re-enable card interrupts */
  251                 bus_space_write_1(isc->sc_regt, isc->sc_regh, IX_IRQ,
  252                                   isc->irq_encoded | IX_IRQ_ENABLE);
  253         break;
  254     }
  255 
  256     return 1;
  257 }
  258 
  259 
  260 static void
  261 ix_copyin (sc, dst, offset, size)
  262         struct ie_softc *sc;
  263         void *dst;
  264         int offset;
  265         size_t size;
  266 {
  267         int i, dribble;
  268         u_int8_t* bptr = dst;
  269         u_int16_t* wptr = dst;
  270         struct ix_softc* isc = (struct ix_softc *) sc;
  271 
  272         if (isc->use_pio) {
  273                 /* Reset read pointer to the specified offset */
  274                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2,
  275                                                   BUS_SPACE_BARRIER_READ);
  276                 bus_space_write_2(sc->bt, sc->bh, IX_READPTR, offset);
  277                 bus_space_barrier(sc->bt, sc->bh, IX_READPTR, 2,
  278                                                   BUS_SPACE_BARRIER_WRITE);
  279         } else {
  280         bus_space_barrier(sc->bt, sc->bh, offset, size,
  281                           BUS_SPACE_BARRIER_READ);
  282         }
  283 
  284         if (offset % 2) {
  285                 if (isc->use_pio)
  286                         *bptr = bus_space_read_1(sc->bt, sc->bh, IX_DATAPORT);
  287                 else
  288                 *bptr = bus_space_read_1(sc->bt, sc->bh, offset);
  289                 offset++; bptr++; size--;
  290         }
  291 
  292         dribble = size % 2;
  293         wptr = (u_int16_t*) bptr;
  294 
  295         if (isc->use_pio) {
  296                 for(i = 0; i <  size / 2; i++) {
  297                         *wptr = bus_space_read_2(sc->bt, sc->bh, IX_DATAPORT);
  298                         wptr++;
  299                 }
  300         } else {
  301                 bus_space_read_region_2(sc->bt, sc->bh, offset, 
  302                                         (u_int16_t *) bptr, size / 2);
  303         }
  304 
  305         if (dribble) {
  306                 bptr += size - 1;
  307                 offset += size - 1;
  308 
  309                 if (isc->use_pio)
  310                         *bptr = bus_space_read_1(sc->bt, sc->bh, IX_DATAPORT);
  311                 else
  312                 *bptr = bus_space_read_1(sc->bt, sc->bh, offset);
  313         }
  314 }
  315 
  316 static void
  317 ix_copyout (sc, src, offset, size)
  318         struct ie_softc *sc;
  319         const void *src;
  320         int offset;
  321         size_t size;
  322 {
  323         int i, dribble;
  324         int osize = size;
  325         int ooffset = offset;
  326         const u_int8_t* bptr = src;
  327         const u_int16_t* wptr = src;
  328         struct ix_softc* isc = (struct ix_softc *) sc;
  329 
  330         if (isc->use_pio) {
  331                 /* Reset write pointer to the specified offset */
  332                 bus_space_write_2(sc->bt, sc->bh, IX_WRITEPTR, offset);
  333                 bus_space_barrier(sc->bt, sc->bh, IX_WRITEPTR, 2, 
  334                                                   BUS_SPACE_BARRIER_WRITE);
  335         }
  336 
  337         if (offset % 2) {
  338                 if (isc->use_pio)
  339                         bus_space_write_1(sc->bt, sc->bh, IX_DATAPORT, *bptr);
  340                 else
  341                 bus_space_write_1(sc->bt, sc->bh, offset, *bptr);
  342                 offset++; bptr++; size--;
  343         }
  344 
  345         dribble = size % 2;
  346         wptr = (u_int16_t*) bptr;
  347 
  348         if (isc->use_pio) {
  349                 for(i = 0; i < size / 2; i++) {
  350                         bus_space_write_2(sc->bt, sc->bh, IX_DATAPORT, *wptr);
  351                         wptr++;
  352                 }
  353         } else {
  354                 bus_space_write_region_2(sc->bt, sc->bh, offset, 
  355                                          (u_int16_t *)bptr, size / 2);
  356         }
  357 
  358         if (dribble) {
  359                 bptr += size - 1;
  360                 offset += size - 1;
  361 
  362                 if (isc->use_pio)
  363                         bus_space_write_1(sc->bt, sc->bh, IX_DATAPORT, *bptr);
  364                 else
  365                 bus_space_write_1(sc->bt, sc->bh, offset, *bptr);
  366         }
  367 
  368         if (isc->use_pio)
  369                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2, 
  370                                                   BUS_SPACE_BARRIER_WRITE);
  371         else
  372         bus_space_barrier(sc->bt, sc->bh, ooffset, osize,
  373                           BUS_SPACE_BARRIER_WRITE);
  374 }
  375 
  376 static void
  377 ix_bus_barrier(sc, offset, length, flags)
  378         struct ie_softc *sc;
  379         int offset, length, flags;
  380 {
  381         struct ix_softc* isc = (struct ix_softc *) sc;
  382 
  383         if (isc->use_pio)
  384                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2, flags);
  385         else
  386                 bus_space_barrier(sc->bt, sc->bh, offset, length, flags);
  387 }
  388 
  389 static u_int16_t
  390 ix_read_16 (sc, offset)
  391         struct ie_softc *sc;
  392         int offset;
  393 {
  394         struct ix_softc* isc = (struct ix_softc *) sc;
  395 
  396         if (isc->use_pio) {
  397                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2,
  398                                                   BUS_SPACE_BARRIER_READ);
  399 
  400                 /* Reset read pointer to the specified offset */
  401                 bus_space_write_2(sc->bt, sc->bh, IX_READPTR, offset);
  402                 bus_space_barrier(sc->bt, sc->bh, IX_READPTR, 2, 
  403                                                   BUS_SPACE_BARRIER_WRITE);
  404 
  405                 return bus_space_read_2(sc->bt, sc->bh, IX_DATAPORT);
  406         } else {
  407                 bus_space_barrier(sc->bt, sc->bh, offset, 2, 
  408                                                   BUS_SPACE_BARRIER_READ);
  409         return bus_space_read_2(sc->bt, sc->bh, offset);
  410         }
  411 }
  412 
  413 static void
  414 ix_write_16 (sc, offset, value)
  415         struct ie_softc *sc;
  416         int offset;
  417         u_int16_t value;
  418 {
  419         struct ix_softc* isc = (struct ix_softc *) sc;
  420 
  421         if (isc->use_pio) {
  422                 /* Reset write pointer to the specified offset */
  423                 bus_space_write_2(sc->bt, sc->bh, IX_WRITEPTR, offset);
  424                 bus_space_barrier(sc->bt, sc->bh, IX_WRITEPTR, 2, 
  425                                                   BUS_SPACE_BARRIER_WRITE);
  426 
  427                 bus_space_write_2(sc->bt, sc->bh, IX_DATAPORT, value);
  428                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2, 
  429                                                   BUS_SPACE_BARRIER_WRITE);
  430         } else {
  431         bus_space_write_2(sc->bt, sc->bh, offset, value);
  432                 bus_space_barrier(sc->bt, sc->bh, offset, 2, 
  433                                                   BUS_SPACE_BARRIER_WRITE);
  434         }
  435 }
  436 
  437 static void
  438 ix_write_24 (sc, offset, addr)
  439         struct ie_softc *sc;
  440         int offset, addr;
  441 {
  442         char* ptr;
  443         struct ix_softc* isc = (struct ix_softc *) sc;
  444         int val = addr + (u_long) sc->sc_maddr - (u_long) sc->sc_iobase;
  445 
  446         if (isc->use_pio) {
  447                 /* Reset write pointer to the specified offset */
  448                 bus_space_write_2(sc->bt, sc->bh, IX_WRITEPTR, offset);
  449                 bus_space_barrier(sc->bt, sc->bh, IX_WRITEPTR, 2, 
  450                                                   BUS_SPACE_BARRIER_WRITE);
  451 
  452                 ptr = (char*) &val;
  453                 bus_space_write_2(sc->bt, sc->bh, IX_DATAPORT, 
  454                                                   *((u_int16_t *)ptr));
  455                 bus_space_write_2(sc->bt, sc->bh, IX_DATAPORT, 
  456                                                   *((u_int16_t *)(ptr + 2)));
  457                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2, 
  458                                                   BUS_SPACE_BARRIER_WRITE);
  459         } else {
  460                 bus_space_write_4(sc->bt, sc->bh, offset, val);
  461                 bus_space_barrier(sc->bt, sc->bh, offset, 4, 
  462                                                   BUS_SPACE_BARRIER_WRITE);
  463         }
  464 }
  465 
  466 static void
  467 ix_zeromem(sc, offset, count)
  468         struct ie_softc *sc;
  469         int offset, count;
  470 {
  471         int i;
  472         int dribble;
  473         struct ix_softc* isc = (struct ix_softc *) sc;
  474 
  475         if (isc->use_pio) {
  476                 /* Reset write pointer to the specified offset */
  477                 bus_space_write_2(sc->bt, sc->bh, IX_WRITEPTR, offset);
  478                 bus_space_barrier(sc->bt, sc->bh, IX_WRITEPTR, 2, 
  479                                                   BUS_SPACE_BARRIER_WRITE);
  480 
  481                 if (offset % 2) {
  482                         bus_space_write_1(sc->bt, sc->bh, IX_DATAPORT, 0);
  483                         count--;
  484                 }
  485 
  486                 dribble = count % 2;
  487                 for(i = 0; i < count / 2; i++)
  488                         bus_space_write_2(sc->bt, sc->bh, IX_DATAPORT, 0);
  489 
  490                 if (dribble)
  491                         bus_space_write_1(sc->bt, sc->bh, IX_DATAPORT, 0);
  492 
  493                 bus_space_barrier(sc->bt, sc->bh, IX_DATAPORT, 2, 
  494                                                   BUS_SPACE_BARRIER_WRITE);
  495         } else {
  496                 bus_space_set_region_1(sc->bt, sc->bh, offset, 0, count);
  497                 bus_space_barrier(sc->bt, sc->bh, offset, count, 
  498                                                   BUS_SPACE_BARRIER_WRITE);
  499         }
  500 }
  501 
  502 static void
  503 ix_mediastatus(sc, ifmr)
  504         struct ie_softc *sc;
  505         struct ifmediareq *ifmr;
  506 {
  507         struct ifmedia *ifm = &sc->sc_media;
  508 
  509         /*
  510          * The currently selected media is always the active media.
  511          */
  512         ifmr->ifm_active = ifm->ifm_cur->ifm_media;
  513 }
  514 
  515 int
  516 ix_match(parent, cf, aux)
  517         struct device *parent;
  518         struct cfdata *cf;
  519         void *aux;
  520 {
  521         int i;
  522         int rv = 0;
  523         bus_addr_t maddr;
  524         bus_size_t msize;
  525         u_short checksum = 0;
  526         bus_space_handle_t ioh;
  527         bus_space_tag_t iot;
  528         u_int8_t val, bart_config;
  529         u_short pg, adjust, decode, edecode;
  530         u_short board_id, id_var1, id_var2, irq, irq_encoded;
  531         struct isa_attach_args * const ia = aux;
  532         short irq_translate[] = {0, 0x09, 0x03, 0x04, 0x05, 0x0a, 0x0b, 0};
  533 
  534         if (ia->ia_nio < 1)
  535                 return (0);
  536         if (ia->ia_niomem < 1)
  537                 return (0);
  538         if (ia->ia_nirq < 1)
  539                 return (0);
  540 
  541         if (ISA_DIRECT_CONFIG(ia))
  542                 return (0);
  543 
  544         iot = ia->ia_iot;
  545 
  546         if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
  547                 return (0);
  548 
  549         if (bus_space_map(iot, ia->ia_io[0].ir_addr,
  550                           IX_IOSIZE, 0, &ioh) != 0) {
  551                 DPRINTF(("Can't map io space at 0x%x\n", ia->ia_iobase));
  552                 return (0);
  553         }
  554 
  555         /* XXX: reset any ee16 at the current iobase */
  556         bus_space_write_1(iot, ioh, IX_ECTRL, IX_RESET_ASIC);
  557         bus_space_write_1(iot, ioh, IX_ECTRL, 0);
  558         delay(240);
  559 
  560         /* now look for ee16. */
  561         board_id = id_var1 = id_var2 = 0;
  562         for (i = 0; i < 4 ; i++) {
  563                 id_var1 = bus_space_read_1(iot, ioh, IX_ID_PORT);
  564                 id_var2 = ((id_var1 & 0x03) << 2);
  565                 board_id |= (( id_var1 >> 4)  << id_var2);
  566         }
  567 
  568         if (board_id != IX_ID) {
  569                 DPRINTF(("BART ID mismatch (got 0x%04x, expected 0x%04x)\n",
  570                         board_id, IX_ID));
  571                 goto out;
  572         }
  573 
  574         /*
  575          * The shared RAM size and location of the EE16 is encoded into
  576          * EEPROM location 6.  The location of the first set bit tells us
  577          * the memory address (0xc0000 + (0x4000 * FSB)), where FSB is the
  578          * number of the first set bit.  The zeroes are then shifted out,
  579          * and the results is the memory size (1 = 16k, 3 = 32k, 7 = 48k,
  580          * 0x0f = 64k).
  581          *
  582          * Examples:
  583          *   0x3c -> 64k@0xc8000, 0x70 -> 48k@0xd0000, 0xc0 -> 32k@0xd8000
  584          *   0x80 -> 16k@0xdc000.
  585          *
  586          * Side note: this comes from reading the old driver rather than
  587          * from a more definitive source, so it could be out-of-whack
  588          * with what the card can do...
  589          */
  590 
  591         val = ix_read_eeprom(iot, ioh, 6) & 0xff;
  592         for (pg = 0; pg < 8; pg++) {
  593                 if (val & 1)
  594                         break;
  595                 val >>= 1;
  596         }
  597 
  598         maddr = 0xc0000 + (pg * 0x4000);
  599 
  600         switch (val) {
  601         case 0x00:
  602                 maddr = 0;
  603                 msize = 0;
  604                 break;
  605 
  606         case 0x01:
  607                 msize = 16 * 1024;
  608                 break;
  609 
  610         case 0x03:
  611                 msize = 32 * 1024;
  612                 break;
  613 
  614         case 0x07:
  615                 msize = 48 * 1024;
  616                 break;
  617 
  618         case 0x0f:
  619                 msize = 64 * 1024;
  620                 break;
  621 
  622         default:
  623                 DPRINTF(("invalid memory size %02x\n", val));
  624                 goto out;
  625         }
  626 
  627         if (ia->ia_iomem[0].ir_addr != ISACF_IOMEM_DEFAULT &&
  628             ia->ia_iomem[0].ir_addr != maddr) {
  629                 DPRINTF((
  630                   "ix_match: memaddr of board @ 0x%x doesn't match config\n",
  631                   ia->ia_iobase));
  632                 goto out;
  633         }
  634 
  635         if (ia->ia_iomem[0].ir_size != ISACF_IOSIZ_DEFAULT &&
  636             ia->ia_iomem[0].ir_size != msize) {
  637                 DPRINTF((
  638                    "ix_match: memsize of board @ 0x%x doesn't match config\n",
  639                    ia->ia_iobase));
  640                 goto out;
  641         }
  642 
  643         /* need to put the 586 in RESET, and leave it */
  644         bus_space_write_1(iot, ioh, IX_ECTRL, IX_RESET_586);
  645 
  646         /* read the eeprom and checksum it, should == IX_ID */
  647         for(i = 0; i < 0x40; i++)
  648                 checksum += ix_read_eeprom(iot, ioh, i);
  649 
  650         if (checksum != IX_ID) {
  651                 DPRINTF(("checksum mismatch (got 0x%04x, expected 0x%04x\n",
  652                         checksum, IX_ID));
  653                 goto out;
  654         }
  655 
  656         /*
  657          * Only do the following bit if using memory-mapped access.  For 
  658          * boards with no mapped memory, we use PIO.  We also use PIO for
  659          * boards with 16K of mapped memory, as those setups don't seem
  660          * to work otherwise.
  661          */
  662         if (msize != 0 && msize != 16384) {
  663                 /* Set board up with memory-mapping info */
  664         adjust = IX_MCTRL_FMCS16 | (pg & 0x3) << 2;
  665         decode = ((1 << (ia->ia_iomem[0].ir_size / 16384)) - 1) << pg;
  666         edecode = ((~decode >> 4) & 0xF0) | (decode >> 8);
  667 
  668         bus_space_write_1(iot, ioh, IX_MEMDEC, decode & 0xFF);
  669         bus_space_write_1(iot, ioh, IX_MCTRL, adjust);
  670         bus_space_write_1(iot, ioh, IX_MPCTRL, (~decode & 0xFF));
  671 
  672                 /* XXX disable Exxx */
  673                 bus_space_write_1(iot, ioh, IX_MECTRL, edecode); 
  674         }
  675 
  676         /*
  677          * Get the encoded interrupt number from the EEPROM, check it
  678          * against the passed in IRQ.  Issue a warning if they do not
  679          * match, and fail the probe.  If irq is 'ISACF_IRQ_DEFAULT' then we
  680          * use the EEPROM irq, and continue.
  681          */
  682         irq_encoded = ix_read_eeprom(iot, ioh, IX_EEPROM_CONFIG1);
  683         irq_encoded = (irq_encoded & IX_EEPROM_IRQ) >> IX_EEPROM_IRQ_SHIFT;
  684         irq = irq_translate[irq_encoded];
  685         if (ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT &&
  686             irq != ia->ia_irq[0].ir_irq) {
  687                 DPRINTF(("board IRQ %d does not match config\n", irq));
  688                 goto out;
  689         }
  690 
  691         /* disable the board interrupts */
  692         bus_space_write_1(iot, ioh, IX_IRQ, irq_encoded);
  693 
  694         bart_config = bus_space_read_1(iot, ioh, IX_CONFIG);
  695         bart_config |= IX_BART_LOOPBACK;
  696         bart_config |= IX_BART_MCS16_TEST; /* inb doesn't get bit! */
  697         bus_space_write_1(iot, ioh, IX_CONFIG, bart_config);
  698         bart_config = bus_space_read_1(iot, ioh, IX_CONFIG);
  699 
  700         bus_space_write_1(iot, ioh, IX_ECTRL, 0);
  701         delay(100);
  702 
  703         rv = 1;
  704 
  705         ia->ia_nio = 1;
  706         ia->ia_io[0].ir_size = IX_IOSIZE;
  707 
  708         ia->ia_niomem = 1;
  709         ia->ia_iomem[0].ir_addr = maddr;
  710         ia->ia_iomem[0].ir_size = msize;
  711 
  712         ia->ia_nirq = 1;
  713         ia->ia_irq[0].ir_irq = irq;
  714 
  715         DPRINTF(("ix_match: found board @ 0x%x\n", ia->ia_iobase));
  716 
  717 out:
  718         bus_space_unmap(iot, ioh, IX_IOSIZE);
  719         return (rv);
  720 }
  721 
  722 void
  723 ix_attach(parent, self, aux)
  724         struct device *parent;
  725         struct device *self;
  726         void   *aux;
  727 {
  728         struct ix_softc *isc = (void *)self;
  729         struct ie_softc *sc = &isc->sc_ie;
  730         struct isa_attach_args *ia = aux;
  731 
  732         int media;
  733         int i, memsize;
  734         u_int8_t bart_config;
  735         bus_space_tag_t iot;
  736         u_int8_t bpat, bval;
  737         u_int16_t wpat, wval;
  738         bus_space_handle_t ioh, memh;
  739         u_short irq_encoded;
  740         u_int8_t ethaddr[ETHER_ADDR_LEN];
  741 
  742         iot = ia->ia_iot;
  743 
  744         /* 
  745          * Shared memory access seems to fail on 16K mapped boards, so
  746          * disable shared memory access if the board is in 16K mode.  If 
  747          * no memory is mapped, we have no choice but to use PIO
  748          */
  749         isc->use_pio = (ia->ia_iomem[0].ir_size <= (16 * 1024));
  750 
  751         if (bus_space_map(iot, ia->ia_io[0].ir_addr,
  752                           ia->ia_io[0].ir_size, 0, &ioh) != 0) {
  753 
  754                 DPRINTF(("\n%s: can't map i/o space 0x%x-0x%x\n",
  755                           sc->sc_dev.dv_xname, ia->ia_[0].ir_addr,
  756                           ia->ia_io[0].ir_addr + ia->ia_io[0].ir_size - 1));
  757                 return;
  758         }
  759 
  760         /* We map memory even if using PIO so something else doesn't grab it */
  761         if (ia->ia_iomem[0].ir_size) {
  762         if (bus_space_map(ia->ia_memt, ia->ia_iomem[0].ir_addr,
  763                           ia->ia_iomem[0].ir_size, 0, &memh) != 0) {
  764                 DPRINTF(("\n%s: can't map iomem space 0x%x-0x%x\n",
  765                         sc->sc_dev.dv_xname, ia->ia_iomem[0].ir_addr,
  766                         ia->ia_iomem[0].ir_addr + ia->ia_iomem[0].ir_size - 1));
  767                 bus_space_unmap(iot, ioh, ia->ia_io[0].ir_size);
  768                 return;
  769         }
  770         }
  771 
  772         isc->sc_regt = iot;
  773         isc->sc_regh = ioh;
  774 
  775         /*
  776          * Get the hardware ethernet address from the EEPROM and
  777          * save it in the softc for use by the 586 setup code.
  778          */
  779         wval = ix_read_eeprom(iot, ioh, IX_EEPROM_ENET_HIGH);
  780         ethaddr[1] = wval & 0xFF;
  781         ethaddr[0] = wval >> 8;
  782         wval = ix_read_eeprom(iot, ioh, IX_EEPROM_ENET_MID);
  783         ethaddr[3] = wval & 0xFF;
  784         ethaddr[2] = wval >> 8;
  785         wval = ix_read_eeprom(iot, ioh, IX_EEPROM_ENET_LOW);
  786         ethaddr[5] = wval & 0xFF;
  787         ethaddr[4] = wval >> 8;
  788 
  789         sc->hwinit = NULL;
  790         sc->hwreset = ix_reset;
  791         sc->chan_attn = ix_atten;
  792         sc->intrhook = ix_intrhook;
  793 
  794         sc->memcopyin = ix_copyin;
  795         sc->memcopyout = ix_copyout;
  796 
  797         /* If using PIO, make sure to setup single-byte read/write functions */
  798         if (isc->use_pio) {
  799                 sc->ie_bus_barrier = ix_bus_barrier;
  800         } else {
  801                 sc->ie_bus_barrier = NULL;
  802         }
  803 
  804         sc->ie_bus_read16 = ix_read_16;
  805         sc->ie_bus_write16 = ix_write_16;
  806         sc->ie_bus_write24 = ix_write_24;
  807 
  808         sc->do_xmitnopchain = 0;
  809 
  810         sc->sc_mediachange = NULL;
  811         sc->sc_mediastatus = ix_mediastatus;
  812 
  813         if (isc->use_pio) {
  814                 sc->bt = iot;
  815                 sc->bh = ioh;
  816 
  817                 /* 
  818                  * If using PIO, the memory size is bounded by on-card memory, 
  819                  * not by how much is mapped into the memory-mapped region, so 
  820                  * determine how much total memory we have to play with here.  
  821                  */
  822                 for(memsize = 64 * 1024; memsize; memsize -= 16 * 1024) {
  823                         /* warm up shared memory, the zero it all out */
  824                         ix_zeromem(sc, 0, 32);
  825                         ix_zeromem(sc, 0, memsize);
  826 
  827                         /* Reset write pointer to the start of RAM */
  828                         bus_space_write_2(iot, ioh, IX_WRITEPTR, 0);
  829                         bus_space_barrier(iot, ioh, IX_WRITEPTR, 2, 
  830                                                     BUS_SPACE_BARRIER_WRITE);
  831 
  832                         /* write test pattern */
  833                         for(i = 0, wpat = 1; i < memsize; i += 2) {
  834                                 bus_space_write_2(iot, ioh, IX_DATAPORT, wpat);
  835                                 wpat += 3;
  836                         }
  837 
  838                         /* Flush all reads & writes to data port */
  839                         bus_space_barrier(iot, ioh, IX_DATAPORT, 2, 
  840                                                     BUS_SPACE_BARRIER_READ |
  841                                                     BUS_SPACE_BARRIER_WRITE);
  842 
  843                         /* Reset read pointer to beginning of card RAM */
  844                         bus_space_write_2(iot, ioh, IX_READPTR, 0);
  845                         bus_space_barrier(iot, ioh, IX_READPTR, 2, 
  846                                                     BUS_SPACE_BARRIER_WRITE);
  847 
  848                         /* read and verify test pattern */
  849                         for(i = 0, wpat = 1; i < memsize; i += 2) {
  850                                 wval = bus_space_read_2(iot, ioh, IX_DATAPORT);
  851 
  852                                 if (wval != wpat)
  853                                         break;
  854 
  855                                 wpat += 3;
  856                         }
  857 
  858                         /* If we failed, try next size down */
  859                         if (i != memsize)
  860                                 continue;
  861 
  862                         /* Now try it all with byte reads/writes */
  863                         ix_zeromem(sc, 0, 32);
  864                         ix_zeromem(sc, 0, memsize);
  865 
  866                         /* Reset write pointer to start of card RAM */
  867                         bus_space_write_2(iot, ioh, IX_WRITEPTR, 0);
  868                         bus_space_barrier(iot, ioh, IX_WRITEPTR, 2, 
  869                                                     BUS_SPACE_BARRIER_WRITE);
  870 
  871                         /* write out test pattern */
  872                         for(i = 0, bpat = 1; i < memsize; i++) {
  873                                 bus_space_write_1(iot, ioh, IX_DATAPORT, bpat);
  874                                 bpat += 3;
  875                         }
  876 
  877                         /* Flush all reads & writes to data port */
  878                         bus_space_barrier(iot, ioh, IX_DATAPORT, 2, 
  879                                                     BUS_SPACE_BARRIER_READ |
  880                                                     BUS_SPACE_BARRIER_WRITE);
  881 
  882                         /* Reset read pointer to beginning of card RAM */
  883                         bus_space_write_2(iot, ioh, IX_READPTR, 0);
  884                         bus_space_barrier(iot, ioh, IX_READPTR, 2, 
  885                                                     BUS_SPACE_BARRIER_WRITE);
  886 
  887                         /* read and verify test pattern */
  888                         for(i = 0, bpat = 1; i < memsize; i++) {
  889                                 bval = bus_space_read_1(iot, ioh, IX_DATAPORT);
  890 
  891                                 if (bval != bpat)
  892                                 bpat += 3;
  893                         }
  894 
  895                         /* If we got through all of memory, we're done! */ 
  896                         if (i == memsize)
  897                                 break;
  898                 }
  899 
  900                 /* Memory tests failed, punt... */
  901                 if (memsize == 0)  {
  902                         DPRINTF(("\n%s: can't determine size of on-card RAM\n",
  903                                 sc->sc_dev.dv_xname));
  904                         bus_space_unmap(iot, ioh, ia->ia_io[0].ir_size);
  905                         return;
  906                 }
  907 
  908                 sc->bt = iot;
  909                 sc->bh = ioh;
  910 
  911                 sc->sc_msize = memsize;
  912                 sc->sc_maddr = (void*) 0;
  913         } else {
  914         sc->bt = ia->ia_memt;
  915         sc->bh = memh;
  916 
  917         sc->sc_msize = ia->ia_iomem[0].ir_size;
  918         sc->sc_maddr = (void *)memh;
  919         }
  920 
  921         /* Map i/o space. */
  922         sc->sc_iobase = (char *)sc->sc_maddr + sc->sc_msize - (1 << 24);
  923 
  924         /* set up pointers to important on-card control structures */
  925         sc->iscp = 0;
  926         sc->scb = IE_ISCP_SZ;
  927         sc->scp = sc->sc_msize + IE_SCP_ADDR - (1 << 24);
  928 
  929         sc->buf_area = sc->scb + IE_SCB_SZ;
  930         sc->buf_area_sz = sc->sc_msize - IE_ISCP_SZ - IE_SCB_SZ - IE_SCP_SZ;
  931 
  932         /* zero card memory */
  933         ix_zeromem(sc, 0, 32);
  934         ix_zeromem(sc, 0, sc->sc_msize);
  935 
  936         /* set card to 16-bit bus mode */
  937         if (isc->use_pio) {
  938                 bus_space_write_2(sc->bt, sc->bh, IX_WRITEPTR, 
  939                                             IE_SCP_BUS_USE((u_long)sc->scp));
  940                 bus_space_barrier(sc->bt, sc->bh, IX_WRITEPTR, 2,
  941                                                   BUS_SPACE_BARRIER_WRITE);
  942 
  943                 bus_space_write_1(sc->bt, sc->bh, IX_DATAPORT,
  944                                   IE_SYSBUS_16BIT);
  945         } else {
  946                 bus_space_write_1(sc->bt, sc->bh, 
  947                                   IE_SCP_BUS_USE((u_long)sc->scp),
  948                                   IE_SYSBUS_16BIT);
  949         }
  950 
  951         /* set up pointers to key structures */
  952         ix_write_24(sc, IE_SCP_ISCP((u_long)sc->scp), (u_long) sc->iscp);
  953         ix_write_16(sc, IE_ISCP_SCB((u_long)sc->iscp), (u_long) sc->scb);
  954         ix_write_24(sc, IE_ISCP_BASE((u_long)sc->iscp), (u_long) sc->iscp);
  955 
  956         /* flush setup of pointers, check if chip answers */
  957         if (isc->use_pio) {
  958                 bus_space_barrier(sc->bt, sc->bh, 0, IX_IOSIZE,
  959                                   BUS_SPACE_BARRIER_WRITE);
  960         } else {
  961         bus_space_barrier(sc->bt, sc->bh, 0, sc->sc_msize,
  962                           BUS_SPACE_BARRIER_WRITE);
  963         }
  964 
  965         if (!i82586_proberam(sc)) {
  966                 DPRINTF(("\n%s: Can't talk to i82586!\n",
  967                         sc->sc_dev.dv_xname));
  968                 bus_space_unmap(iot, ioh, ia->ia_io[0].ir_size);
  969 
  970                 if (ia->ia_iomem[0].ir_size)
  971                 bus_space_unmap(ia->ia_memt, memh, ia->ia_iomem[0].ir_size);
  972                 return;
  973         }
  974 
  975         /* Figure out which media is being used... */
  976         if (ix_read_eeprom(iot, ioh, IX_EEPROM_CONFIG1) &
  977                                 IX_EEPROM_MEDIA_EXT) {
  978                 if (ix_read_eeprom(iot, ioh, IX_EEPROM_MEDIA) &
  979                                 IX_EEPROM_MEDIA_TP)
  980                         media = IFM_ETHER | IFM_10_T;
  981                 else
  982                         media = IFM_ETHER | IFM_10_2;
  983         } else
  984                 media = IFM_ETHER | IFM_10_5;
  985 
  986         /* Take the card out of lookback */
  987         bart_config = bus_space_read_1(iot, ioh, IX_CONFIG);
  988         bart_config &= ~IX_BART_LOOPBACK;
  989         bart_config |= IX_BART_MCS16_TEST; /* inb doesn't get bit! */
  990         bus_space_write_1(iot, ioh, IX_CONFIG, bart_config);
  991         bart_config = bus_space_read_1(iot, ioh, IX_CONFIG);
  992 
  993         irq_encoded = ix_read_eeprom(iot, ioh,
  994                                      IX_EEPROM_CONFIG1);
  995         irq_encoded = (irq_encoded & IX_EEPROM_IRQ) >> IX_EEPROM_IRQ_SHIFT;
  996 
  997         /* Enable interrupts */
  998         bus_space_write_1(iot, ioh, IX_IRQ,
  999                           irq_encoded | IX_IRQ_ENABLE);
 1000 
 1001         /* Flush all writes to registers */
 1002         bus_space_barrier(iot, ioh, 0, ia->ia_io[0].ir_size,
 1003             BUS_SPACE_BARRIER_WRITE);
 1004 
 1005         isc->irq_encoded = irq_encoded;
 1006 
 1007         i82586_attach(sc, "EtherExpress/16", ethaddr,
 1008                       ix_media, NIX_MEDIA, media);
 1009 
 1010         if (isc->use_pio)
 1011                 printf("%s: unsupported memory config, using PIO to access %d bytes of memory\n", sc->sc_dev.dv_xname, sc->sc_msize);
 1012 
 1013         isc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
 1014             IST_EDGE, IPL_NET, i82586_intr, sc);
 1015         if (isc->sc_ih == NULL)
 1016                 DPRINTF(("\n%s: can't establish interrupt\n",
 1017                         sc->sc_dev.dv_xname));
 1018 }
 1019 
 1020 CFATTACH_DECL(ix, sizeof(struct ix_softc),
 1021     ix_match, ix_attach, NULL, NULL);

Cache object: 50b770289fbfd913b5d7101ad6056bf0


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.