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_we_isa.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_we_isa.c,v 1.8 2002/10/02 03:10:48 thorpej Exp $    */
    2 
    3 /*-
    4  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    5  * All rights reserved.
    6  *
    7  * This code is derived from software contributed to The NetBSD Foundation
    8  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
    9  * NASA Ames Research Center.
   10  *
   11  * Redistribution and use in source and binary forms, with or without
   12  * modification, are permitted provided that the following conditions
   13  * are met:
   14  * 1. Redistributions of source code must retain the above copyright
   15  *    notice, this list of conditions and the following disclaimer.
   16  * 2. Redistributions in binary form must reproduce the above copyright
   17  *    notice, this list of conditions and the following disclaimer in the
   18  *    documentation and/or other materials provided with the distribution.
   19  * 3. All advertising materials mentioning features or use of this software
   20  *    must display the following acknowledgement:
   21  *      This product includes software developed by the NetBSD
   22  *      Foundation, Inc. and its contributors.
   23  * 4. Neither the name of The NetBSD Foundation nor the names of its
   24  *    contributors may be used to endorse or promote products derived
   25  *    from this software without specific prior written permission.
   26  *
   27  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   28  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   29  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   30  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   31  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   32  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   33  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   34  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   35  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   36  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   37  * POSSIBILITY OF SUCH DAMAGE.
   38  */
   39 
   40 /*
   41  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
   42  * adapters.
   43  *
   44  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
   45  *
   46  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
   47  * copied, distributed, and sold, in both source and binary form provided that
   48  * the above copyright and these terms are retained.  Under no circumstances is
   49  * the author responsible for the proper functioning of this software, nor does
   50  * the author assume any responsibility for damages incurred with its use.
   51  */
   52 
   53 /*
   54  * Device driver for the Western Digital/SMC 8003 and 8013 series,
   55  * and the SMC Elite Ultra (8216).
   56  */
   57 
   58 #include <sys/cdefs.h>
   59 __KERNEL_RCSID(0, "$NetBSD: if_we_isa.c,v 1.8 2002/10/02 03:10:48 thorpej Exp $");
   60 
   61 #include <sys/param.h>
   62 #include <sys/systm.h>
   63 #include <sys/device.h>
   64 #include <sys/socket.h>
   65 #include <sys/mbuf.h>
   66 #include <sys/syslog.h>
   67 
   68 #include <net/if.h>
   69 #include <net/if_dl.h>
   70 #include <net/if_types.h>
   71 #include <net/if_media.h>
   72 
   73 #include <net/if_ether.h>
   74 
   75 #include <machine/bus.h>
   76 #include <machine/bswap.h>
   77 #include <machine/intr.h>
   78 
   79 #include <dev/isa/isareg.h>
   80 #include <dev/isa/isavar.h>
   81 
   82 #include <dev/ic/dp8390reg.h>
   83 #include <dev/ic/dp8390var.h>
   84 #include <dev/ic/wereg.h>
   85 #include <dev/ic/wevar.h>
   86 
   87 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
   88 #define bus_space_read_region_stream_2  bus_space_read_region_2
   89 #define bus_space_write_stream_2        bus_space_write_2
   90 #define bus_space_write_region_stream_2 bus_space_write_region_2
   91 #endif
   92 
   93 int     we_isa_probe __P((struct device *, struct cfdata *, void *));
   94 void    we_isa_attach __P((struct device *, struct device *, void *));
   95 
   96 CFATTACH_DECL(we_isa, sizeof(struct we_softc),
   97     we_isa_probe, we_isa_attach, NULL, NULL);
   98 
   99 extern struct cfdriver we_cd;
  100 
  101 static const char *we_params __P((bus_space_tag_t, bus_space_handle_t,
  102                 u_int8_t *, bus_size_t *, int *, int *));
  103 
  104 static const int we_584_irq[] = {
  105         9, 3, 5, 7, 10, 11, 15, 4,
  106 };
  107 #define NWE_584_IRQ     (sizeof(we_584_irq) / sizeof(we_584_irq[0]))
  108 
  109 static const int we_790_irq[] = {
  110         ISACF_IRQ_DEFAULT, 9, 3, 5, 7, 10, 11, 15,
  111 };
  112 #define NWE_790_IRQ     (sizeof(we_790_irq) / sizeof(we_790_irq[0]))
  113 
  114 /*
  115  * Delay needed when switching 16-bit access to shared memory.
  116  */
  117 #define WE_DELAY(wsc) delay(3)
  118 
  119 /*
  120  * Enable card RAM, and 16-bit access.
  121  */
  122 #define WE_MEM_ENABLE(wsc) \
  123 do { \
  124         if ((wsc)->sc_16bitp) \
  125                 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  126                     WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \
  127         bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  128             WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \
  129         WE_DELAY((wsc)); \
  130 } while (0)
  131 
  132 /*
  133  * Disable card RAM, and 16-bit access.
  134  */
  135 #define WE_MEM_DISABLE(wsc) \
  136 do { \
  137         bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  138             WE_MSR, (wsc)->sc_msr_proto); \
  139         if ((wsc)->sc_16bitp) \
  140                 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  141                     WE_LAAR, (wsc)->sc_laar_proto); \
  142         WE_DELAY((wsc)); \
  143 } while (0)
  144 
  145 int
  146 we_isa_probe(parent, cf, aux)
  147         struct device *parent;
  148         struct cfdata *cf;
  149         void *aux;
  150 {
  151         struct isa_attach_args *ia = aux;
  152         bus_space_tag_t asict, memt;
  153         bus_space_handle_t asich, memh;
  154         bus_size_t memsize;
  155         int asich_valid, memh_valid;
  156         int i, is790, rv = 0;
  157         u_int8_t x, type;
  158 
  159         asict = ia->ia_iot;
  160         memt = ia->ia_memt;
  161 
  162         asich_valid = memh_valid = 0;
  163 
  164         if (ia->ia_nio < 1)
  165                 return (0);
  166         if (ia->ia_niomem < 1)
  167                 return (0);
  168         if (ia->ia_nirq < 1)
  169                 return (0);
  170 
  171         if (ISA_DIRECT_CONFIG(ia))
  172                 return (0);
  173 
  174         /* Disallow wildcarded i/o addresses. */
  175         if (ia->ia_io[0].ir_addr == ISACF_PORT_DEFAULT)
  176                 return (0);
  177 
  178         /* Disallow wildcarded mem address. */
  179         if (ia->ia_iomem[0].ir_addr == ISACF_IOMEM_DEFAULT)
  180                 return (0);
  181 
  182         /* Attempt to map the device. */
  183         if (bus_space_map(asict, ia->ia_io[0].ir_addr, WE_NPORTS, 0, &asich))
  184                 goto out;
  185         asich_valid = 1;
  186 
  187 #ifdef TOSH_ETHER
  188         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_POW);
  189 #endif
  190 
  191         /*
  192          * Attempt to do a checksum over the station address PROM.
  193          * If it fails, it's probably not a WD/SMC board.  There is
  194          * a problem with this, though.  Some clone WD8003E boards
  195          * (e.g. Danpex) won't pass the checksum.  In this case,
  196          * the checksum byte always seems to be 0.
  197          */
  198         for (x = 0, i = 0; i < 8; i++)
  199                 x += bus_space_read_1(asict, asich, WE_PROM + i);
  200 
  201         if (x != WE_ROM_CHECKSUM_TOTAL) {
  202                 /* Make sure it's an 8003E clone... */
  203                 if (bus_space_read_1(asict, asich, WE_CARD_ID) !=
  204                     WE_TYPE_WD8003E)
  205                         goto out;
  206 
  207                 /* Check the checksum byte. */
  208                 if (bus_space_read_1(asict, asich, WE_PROM + 7) != 0)
  209                         goto out;
  210         }
  211 
  212         /*
  213          * Reset the card to force it into a known state.
  214          */
  215 #ifdef TOSH_ETHER
  216         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST | WE_MSR_POW);
  217 #else
  218         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST);
  219 #endif
  220         delay(100);
  221 
  222         bus_space_write_1(asict, asich, WE_MSR,
  223             bus_space_read_1(asict, asich, WE_MSR) & ~WE_MSR_RST);
  224 
  225         /* Wait in case the card is reading it's EEPROM. */
  226         delay(5000);
  227 
  228         /*
  229          * Get parameters.
  230          */
  231         if (we_params(asict, asich, &type, &memsize, NULL, &is790) == NULL)
  232                 goto out;
  233 
  234         /* Allow user to override probed value. */
  235         if (ia->ia_iomem[0].ir_size)
  236                 memsize = ia->ia_iomem[0].ir_size;
  237 
  238         /* Attempt to map the memory space. */
  239         if (bus_space_map(memt, ia->ia_iomem[0].ir_addr, memsize, 0, &memh))
  240                 goto out;
  241         memh_valid = 1;
  242 
  243         /*
  244          * If possible, get the assigned interrupt number from the card
  245          * and use it.
  246          */
  247         if (is790) {
  248                 u_int8_t hwr;
  249 
  250                 /* Assemble together the encoded interrupt number. */
  251                 hwr = bus_space_read_1(asict, asich, WE790_HWR);
  252                 bus_space_write_1(asict, asich, WE790_HWR,
  253                     hwr | WE790_HWR_SWH);
  254 
  255                 x = bus_space_read_1(asict, asich, WE790_GCR);
  256                 i = ((x & WE790_GCR_IR2) >> 4) |
  257                     ((x & (WE790_GCR_IR1|WE790_GCR_IR0)) >> 2);
  258                 bus_space_write_1(asict, asich, WE790_HWR,
  259                     hwr & ~WE790_HWR_SWH);
  260 
  261                 if (ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT &&
  262                     ia->ia_irq[0].ir_irq != we_790_irq[i])
  263                         printf("%s%d: overriding configured IRQ %d to %d\n",
  264                             we_cd.cd_name, cf->cf_unit, ia->ia_irq[0].ir_irq,
  265                             we_790_irq[i]);
  266                 ia->ia_irq[0].ir_irq = we_790_irq[i];
  267         } else if (type & WE_SOFTCONFIG) {
  268                 /* Assemble together the encoded interrupt number. */
  269                 i = (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_IR2) |
  270                     ((bus_space_read_1(asict, asich, WE_IRR) &
  271                       (WE_IRR_IR0 | WE_IRR_IR1)) >> 5);
  272 
  273                 if (ia->ia_irq[0].ir_irq != ISACF_IRQ_DEFAULT &&
  274                     ia->ia_irq[0].ir_irq != we_584_irq[i])
  275                         printf("%s%d: overriding configured IRQ %d to %d\n",
  276                             we_cd.cd_name, cf->cf_unit, ia->ia_irq[0].ir_irq,
  277                             we_584_irq[i]);
  278                 ia->ia_irq[0].ir_irq = we_584_irq[i];
  279         }
  280 
  281         /* So, we say we've found it! */
  282         ia->ia_nio = 1;
  283         ia->ia_io[0].ir_size = WE_NPORTS;
  284 
  285         ia->ia_niomem = 1;
  286         ia->ia_iomem[0].ir_size = memsize;
  287 
  288         ia->ia_nirq = 1;
  289 
  290         ia->ia_ndrq = 0;
  291 
  292         rv = 1;
  293 
  294  out:
  295         if (asich_valid)
  296                 bus_space_unmap(asict, asich, WE_NPORTS);
  297         if (memh_valid)
  298                 bus_space_unmap(memt, memh, memsize);
  299         return (rv);
  300 }
  301 
  302 void
  303 we_isa_attach(parent, self, aux)
  304         struct device *parent, *self;
  305         void *aux;
  306 {
  307         struct we_softc *wsc = (struct we_softc *)self;
  308         struct dp8390_softc *sc = &wsc->sc_dp8390;
  309         struct isa_attach_args *ia = aux;
  310         bus_space_tag_t nict, asict, memt;
  311         bus_space_handle_t nich, asich, memh;
  312         const char *typestr;
  313 
  314         printf("\n");
  315 
  316         nict = asict = ia->ia_iot;
  317         memt = ia->ia_memt;
  318 
  319         /* Map the device. */
  320         if (bus_space_map(asict, ia->ia_io[0].ir_addr, WE_NPORTS, 0, &asich)) {
  321                 printf("%s: can't map nic i/o space\n",
  322                     sc->sc_dev.dv_xname);
  323                 return;
  324         }
  325 
  326         if (bus_space_subregion(asict, asich, WE_NIC_OFFSET, WE_NIC_NPORTS,
  327             &nich)) {
  328                 printf("%s: can't subregion i/o space\n",
  329                     sc->sc_dev.dv_xname);
  330                 return;
  331         }
  332 
  333         typestr = we_params(asict, asich, &wsc->sc_type, NULL,
  334             &wsc->sc_16bitp, &sc->is790);
  335         if (typestr == NULL) {
  336                 printf("%s: where did the card go?\n", sc->sc_dev.dv_xname);
  337                 return;
  338         }
  339 
  340         /*
  341          * Map memory space.  Note we use the size that might have
  342          * been overridden by the user.
  343          */
  344         if (bus_space_map(memt, ia->ia_iomem[0].ir_addr,
  345             ia->ia_iomem[0].ir_size, 0, &memh)) {
  346                 printf("%s: can't map shared memory\n",
  347                     sc->sc_dev.dv_xname);
  348                 return;
  349         }
  350 
  351         wsc->sc_asict = asict;
  352         wsc->sc_asich = asich;
  353 
  354         sc->sc_regt = nict;
  355         sc->sc_regh = nich;
  356 
  357         sc->sc_buft = memt;
  358         sc->sc_bufh = memh;
  359 
  360         wsc->sc_maddr = ia->ia_iomem[0].ir_addr;
  361         sc->mem_size = ia->ia_iomem[0].ir_size;
  362 
  363         /* Interface is always enabled. */
  364         sc->sc_enabled = 1;
  365 
  366         if (we_config(self, wsc, typestr))
  367                 return;
  368 
  369         /*
  370          * Enable the configured interrupt.
  371          */
  372         if (sc->is790)
  373                 bus_space_write_1(asict, asich, WE790_ICR,
  374                     bus_space_read_1(asict, asich, WE790_ICR) |
  375                     WE790_ICR_EIL);
  376         else if (wsc->sc_type & WE_SOFTCONFIG)
  377                 bus_space_write_1(asict, asich, WE_IRR,
  378                     bus_space_read_1(asict, asich, WE_IRR) | WE_IRR_IEN);
  379         else if (ia->ia_irq[0].ir_irq == ISACF_IRQ_DEFAULT) {
  380                 printf("%s: can't wildcard IRQ on a %s\n",
  381                     sc->sc_dev.dv_xname, typestr);
  382                 return;
  383         }
  384 
  385         /* Establish interrupt handler. */
  386         wsc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq[0].ir_irq,
  387             IST_EDGE, IPL_NET, dp8390_intr, sc);
  388         if (wsc->sc_ih == NULL)
  389                 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
  390 }
  391 
  392 static const char *
  393 we_params(asict, asich, typep, memsizep, is16bitp, is790p)
  394         bus_space_tag_t asict;
  395         bus_space_handle_t asich;
  396         u_int8_t *typep;
  397         bus_size_t *memsizep;
  398         int *is16bitp, *is790p;
  399 {
  400         const char *typestr;
  401         bus_size_t memsize;
  402         int is16bit, is790;
  403         u_int8_t type;
  404 
  405         memsize = 8192;
  406         is16bit = is790 = 0;
  407 
  408         type = bus_space_read_1(asict, asich, WE_CARD_ID);
  409         switch (type) {
  410         case WE_TYPE_WD8003S: 
  411                 typestr = "WD8003S"; 
  412                 break;
  413         case WE_TYPE_WD8003E:
  414                 typestr = "WD8003E";
  415                 break;
  416         case WE_TYPE_WD8003EB: 
  417                 typestr = "WD8003EB";
  418                 break;
  419         case WE_TYPE_WD8003W:
  420                 typestr = "WD8003W";
  421                 break;
  422         case WE_TYPE_WD8013EBT: 
  423                 typestr = "WD8013EBT";
  424                 memsize = 16384;
  425                 is16bit = 1;
  426                 break;
  427         case WE_TYPE_WD8013W:
  428                 typestr = "WD8013W";
  429                 memsize = 16384;
  430                 is16bit = 1;
  431                 break;
  432         case WE_TYPE_WD8013EP:          /* also WD8003EP */
  433                 if (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) {
  434                         is16bit = 1;
  435                         memsize = 16384;
  436                         typestr = "WD8013EP";
  437                 } else
  438                         typestr = "WD8003EP";
  439                 break;
  440         case WE_TYPE_WD8013WC:
  441                 typestr = "WD8013WC";
  442                 memsize = 16384;
  443                 is16bit = 1;
  444                 break;
  445         case WE_TYPE_WD8013EBP:
  446                 typestr = "WD8013EBP";
  447                 memsize = 16384;
  448                 is16bit = 1;
  449                 break;
  450         case WE_TYPE_WD8013EPC:
  451                 typestr = "WD8013EPC";
  452                 memsize = 16384;
  453                 is16bit = 1;
  454                 break;
  455         case WE_TYPE_SMC8216C:
  456         case WE_TYPE_SMC8216T:
  457             {
  458                 u_int8_t hwr;
  459 
  460                 typestr = (type == WE_TYPE_SMC8216C) ?
  461                     "SMC8216/SMC8216C" : "SMC8216T";
  462 
  463                 hwr = bus_space_read_1(asict, asich, WE790_HWR);
  464                 bus_space_write_1(asict, asich, WE790_HWR,
  465                     hwr | WE790_HWR_SWH);
  466                 switch (bus_space_read_1(asict, asich, WE790_RAR) &
  467                     WE790_RAR_SZ64) {
  468                 case WE790_RAR_SZ64:
  469                         memsize = 65536;
  470                         break;
  471                 case WE790_RAR_SZ32:
  472                         memsize = 32768;
  473                         break;
  474                 case WE790_RAR_SZ16:
  475                         memsize = 16384;
  476                         break;
  477                 case WE790_RAR_SZ8:
  478                         /* 8216 has 16K shared mem -- 8416 has 8K */
  479                         typestr = (type == WE_TYPE_SMC8216C) ?
  480                             "SMC8416C/SMC8416BT" : "SMC8416T";
  481                         memsize = 8192;
  482                         break;
  483                 }
  484                 bus_space_write_1(asict, asich, WE790_HWR, hwr);
  485 
  486                 is16bit = 1;
  487                 is790 = 1;
  488                 break;
  489             }
  490 #ifdef TOSH_ETHER
  491         case WE_TYPE_TOSHIBA1:
  492                 typestr = "Toshiba1";
  493                 memsize = 32768;
  494                 is16bit = 1;
  495                 break;
  496         case WE_TYPE_TOSHIBA4:
  497                 typestr = "Toshiba4";
  498                 memsize = 32768;
  499                 is16bit = 1;
  500                 break;
  501 #endif
  502         default:
  503                 /* Not one we recognize. */
  504                 return (NULL);
  505         }
  506 
  507         /*
  508          * Make some adjustments to initial values depending on what is
  509          * found in the ICR.
  510          */
  511         if (is16bit && (type != WE_TYPE_WD8013EBT) &&
  512 #ifdef TOSH_ETHER
  513             (type != WE_TYPE_TOSHIBA1 && type != WE_TYPE_TOSHIBA4) &&
  514 #endif
  515             (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) == 0) {
  516                 is16bit = 0;
  517                 memsize = 8192;
  518         }
  519 
  520 #ifdef WE_DEBUG
  521         {
  522                 int i;
  523 
  524                 printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, "
  525                     "memsize = %d\n", type, typestr, is16bit, memsize);
  526                 for (i = 0; i < 8; i++)
  527                         printf("     %d -> 0x%x\n", i,
  528                             bus_space_read_1(asict, asich, i));
  529         }
  530 #endif
  531 
  532         if (typep != NULL)
  533                 *typep = type;
  534         if (memsizep != NULL)
  535                 *memsizep = memsize;
  536         if (is16bitp != NULL)
  537                 *is16bitp = is16bit;
  538         if (is790p != NULL)
  539                 *is790p = is790;
  540         return (typestr);
  541 }

Cache object: 3756a416fd0c593f07d5c5aa2c4e778e


[ 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.