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/ed/if_ed_wd80x3.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 /*-
    2  * Copyright (c) 2005, M. Warner Losh
    3  * All rights reserved.
    4  * Copyright (c) 1995, David Greenman 
    5  * All rights reserved.
    6  *
    7  * Redistribution and use in source and binary forms, with or without
    8  * modification, are permitted provided that the following conditions
    9  * are met:
   10  * 1. Redistributions of source code must retain the above copyright
   11  *    notice unmodified, this list of conditions, and the following
   12  *    disclaimer.
   13  * 2. Redistributions in binary form must reproduce the above copyright
   14  *    notice, this list of conditions and the following disclaimer in the
   15  *    documentation and/or other materials provided with the distribution.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  */
   29 
   30 #include <sys/cdefs.h>
   31 __FBSDID("$FreeBSD$");
   32 
   33 #include "opt_ed.h"
   34 
   35 #include <sys/param.h>
   36 #include <sys/systm.h>
   37 #include <sys/sockio.h>
   38 #include <sys/mbuf.h>
   39 #include <sys/kernel.h>
   40 #include <sys/socket.h>
   41 #include <sys/syslog.h>
   42 
   43 #include <sys/bus.h>
   44 
   45 #include <machine/bus.h>
   46 #include <sys/rman.h>
   47 #include <machine/resource.h>
   48 
   49 #include <net/ethernet.h>
   50 #include <net/if.h>
   51 #include <net/if_arp.h>
   52 #include <net/if_dl.h>
   53 #include <net/if_mib.h>
   54 #include <net/if_media.h>
   55 
   56 #include <net/bpf.h>
   57 
   58 #include <dev/ed/if_edreg.h>
   59 #include <dev/ed/if_edvar.h>
   60 
   61 /*
   62  * Interrupt conversion table for WD/SMC ASIC/83C584
   63  */
   64 static uint16_t ed_intr_val[] = {
   65         9,
   66         3,
   67         5,
   68         7,
   69         10,
   70         11,
   71         15,
   72         4
   73 };
   74 
   75 /*
   76  * Interrupt conversion table for 83C790
   77  */
   78 static uint16_t ed_790_intr_val[] = {
   79         0,
   80         9,
   81         3,
   82         5,
   83         7,
   84         10,
   85         11,
   86         15
   87 };
   88 
   89 /*
   90  * Probe and vendor-specific initialization routine for SMC/WD80x3 boards
   91  */
   92 int
   93 ed_probe_WD80x3_generic(device_t dev, int flags, uint16_t *intr_vals[])
   94 {
   95         struct ed_softc *sc = device_get_softc(dev);
   96         int     error;
   97         int     i;
   98         u_int   memsize;
   99         u_char  iptr, isa16bit, sum, totalsum;
  100         u_long  irq, junk, pmem;
  101 
  102         sc->chip_type = ED_CHIP_TYPE_DP8390;
  103 
  104         if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
  105                 totalsum = ED_WD_ROM_CHECKSUM_TOTAL_TOSH_ETHER;
  106                 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_POW);
  107                 DELAY(10000);
  108         }
  109         else
  110                 totalsum = ED_WD_ROM_CHECKSUM_TOTAL;
  111 
  112         /*
  113          * Attempt to do a checksum over the station address PROM. If it
  114          * fails, it's probably not a SMC/WD board. There is a problem with
  115          * this, though: some clone WD boards don't pass the checksum test.
  116          * Danpex boards for one.
  117          */
  118         for (sum = 0, i = 0; i < 8; ++i)
  119                 sum += ed_asic_inb(sc, ED_WD_PROM + i);
  120 
  121         if (sum != totalsum) {
  122                 /*
  123                  * Checksum is invalid. This often happens with cheap WD8003E
  124                  * clones.  In this case, the checksum byte (the eighth byte)
  125                  * seems to always be zero.
  126                  */
  127                 if (ed_asic_inb(sc, ED_WD_CARD_ID) != ED_TYPE_WD8003E ||
  128                     ed_asic_inb(sc, ED_WD_PROM + 7) != 0)
  129                         return (ENXIO);
  130         }
  131         /* reset card to force it into a known state. */
  132         if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER)
  133                 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST | ED_WD_MSR_POW);
  134         else
  135                 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_RST);
  136 
  137         DELAY(100);
  138         ed_asic_outb(sc, ED_WD_MSR, ed_asic_inb(sc, ED_WD_MSR) & ~ED_WD_MSR_RST);
  139         /* wait in the case this card is reading its EEROM */
  140         DELAY(5000);
  141 
  142         sc->vendor = ED_VENDOR_WD_SMC;
  143         sc->type = ed_asic_inb(sc, ED_WD_CARD_ID);
  144 
  145         /*
  146          * Set initial values for width/size.
  147          */
  148         memsize = 8192;
  149         isa16bit = 0;
  150         switch (sc->type) {
  151         case ED_TYPE_WD8003S:
  152                 sc->type_str = "WD8003S";
  153                 break;
  154         case ED_TYPE_WD8003E:
  155                 sc->type_str = "WD8003E";
  156                 break;
  157         case ED_TYPE_WD8003EB:
  158                 sc->type_str = "WD8003EB";
  159                 break;
  160         case ED_TYPE_WD8003W:
  161                 sc->type_str = "WD8003W";
  162                 break;
  163         case ED_TYPE_WD8013EBT:
  164                 sc->type_str = "WD8013EBT";
  165                 memsize = 16384;
  166                 isa16bit = 1;
  167                 break;
  168         case ED_TYPE_WD8013W:
  169                 sc->type_str = "WD8013W";
  170                 memsize = 16384;
  171                 isa16bit = 1;
  172                 break;
  173         case ED_TYPE_WD8013EP:  /* also WD8003EP */
  174                 if (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) {
  175                         isa16bit = 1;
  176                         memsize = 16384;
  177                         sc->type_str = "WD8013EP";
  178                 } else
  179                         sc->type_str = "WD8003EP";
  180                 break;
  181         case ED_TYPE_WD8013WC:
  182                 sc->type_str = "WD8013WC";
  183                 memsize = 16384;
  184                 isa16bit = 1;
  185                 break;
  186         case ED_TYPE_WD8013EBP:
  187                 sc->type_str = "WD8013EBP";
  188                 memsize = 16384;
  189                 isa16bit = 1;
  190                 break;
  191         case ED_TYPE_WD8013EPC:
  192                 sc->type_str = "WD8013EPC";
  193                 memsize = 16384;
  194                 isa16bit = 1;
  195                 break;
  196         case ED_TYPE_SMC8216C: /* 8216 has 16K shared mem -- 8416 has 8K */
  197         case ED_TYPE_SMC8216T:
  198                 if (sc->type == ED_TYPE_SMC8216C)
  199                         sc->type_str = "SMC8216/SMC8216C";
  200                 else
  201                         sc->type_str = "SMC8216T";
  202 
  203                 ed_asic_outb(sc, ED_WD790_HWR,
  204                     ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
  205                 switch (ed_asic_inb(sc, ED_WD790_RAR) & ED_WD790_RAR_SZ64) {
  206                 case ED_WD790_RAR_SZ64:
  207                         memsize = 65536;
  208                         break;
  209                 case ED_WD790_RAR_SZ32:
  210                         memsize = 32768;
  211                         break;
  212                 case ED_WD790_RAR_SZ16:
  213                         memsize = 16384;
  214                         break;
  215                 case ED_WD790_RAR_SZ8:
  216                         /* 8216 has 16K shared mem -- 8416 has 8K */
  217                         if (sc->type == ED_TYPE_SMC8216C)
  218                                 sc->type_str = "SMC8416C/SMC8416BT";
  219                         else
  220                                 sc->type_str = "SMC8416T";
  221                         memsize = 8192;
  222                         break;
  223                 }
  224                 ed_asic_outb(sc, ED_WD790_HWR,
  225                     ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
  226 
  227                 isa16bit = 1;
  228                 sc->chip_type = ED_CHIP_TYPE_WD790;
  229                 break;
  230         case ED_TYPE_TOSHIBA1:
  231                 sc->type_str = "Toshiba1";
  232                 memsize = 32768;
  233                 isa16bit = 1;
  234                 break;
  235         case ED_TYPE_TOSHIBA4:
  236                 sc->type_str = "Toshiba4";
  237                 memsize = 32768;
  238                 isa16bit = 1;
  239                 break;
  240         default:
  241                 sc->type_str = "";
  242                 break;
  243         }
  244 
  245         /*
  246          * Make some adjustments to initial values depending on what is found
  247          * in the ICR.
  248          */
  249         if (isa16bit && (sc->type != ED_TYPE_WD8013EBT)
  250           && (sc->type != ED_TYPE_TOSHIBA1) && (sc->type != ED_TYPE_TOSHIBA4)
  251             && ((ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_16BIT) == 0)) {
  252                 isa16bit = 0;
  253                 memsize = 8192;
  254         }
  255 
  256         /* Override memsize? XXX */
  257         error = ed_alloc_memory(dev, 0, memsize);
  258         if (error)
  259                 return (error);
  260         sc->mem_start = 0;
  261 
  262 #ifdef ED_DEBUG
  263         printf("type = %x type_str=%s isa16bit=%d memsize=%d id_msize=%lu\n",
  264             sc->type, sc->type_str, isa16bit, memsize,
  265             rman_get_size(sc->mem_res));
  266         for (i = 0; i < 8; i++)
  267                 printf("%x -> %x\n", i, ed_asic_inb(sc, i));
  268 #endif
  269         pmem = rman_get_start(sc->mem_res);
  270         if (!(flags & ED_FLAGS_PCCARD)) {
  271                 error = ed_isa_mem_ok(dev, pmem, memsize);
  272                 if (error)
  273                         return (error);
  274         }
  275 
  276         /*
  277          * (note that if the user specifies both of the following flags that
  278          * '8bit' mode intentionally has precedence)
  279          */
  280         if (flags & ED_FLAGS_FORCE_16BIT_MODE)
  281                 isa16bit = 1;
  282         if (flags & ED_FLAGS_FORCE_8BIT_MODE)
  283                 isa16bit = 0;
  284 
  285         /*
  286          * If possible, get the assigned interrupt number from the card and
  287          * use it.
  288          */
  289         if ((sc->type & ED_WD_SOFTCONFIG) &&
  290             (sc->chip_type != ED_CHIP_TYPE_WD790)) {
  291 
  292                 /*
  293                  * Assemble together the encoded interrupt number.
  294                  */
  295                 iptr = (ed_asic_inb(sc, ED_WD_ICR) & ED_WD_ICR_IR2) |
  296                     ((ed_asic_inb(sc, ED_WD_IRR) &
  297                       (ED_WD_IRR_IR0 | ED_WD_IRR_IR1)) >> 5);
  298 
  299                 /*
  300                  * If no interrupt specified (or "?"), use what the board tells us.
  301                  */
  302                 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
  303                 if (error && intr_vals[0] != NULL)
  304                         error = bus_set_resource(dev, SYS_RES_IRQ, 0,
  305                             intr_vals[0][iptr], 1);
  306                 if (error)
  307                         return (error);
  308 
  309                 /*
  310                  * Enable the interrupt.
  311                  */
  312                 ed_asic_outb(sc, ED_WD_IRR,
  313                      ed_asic_inb(sc, ED_WD_IRR) | ED_WD_IRR_IEN);
  314         }
  315         if (sc->chip_type == ED_CHIP_TYPE_WD790) {
  316                 ed_asic_outb(sc, ED_WD790_HWR,
  317                   ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH);
  318                 iptr = (((ed_asic_inb(sc, ED_WD790_GCR) & ED_WD790_GCR_IR2) >> 4) |
  319                         (ed_asic_inb(sc, ED_WD790_GCR) &
  320                          (ED_WD790_GCR_IR1 | ED_WD790_GCR_IR0)) >> 2);
  321                 ed_asic_outb(sc, ED_WD790_HWR,
  322                     ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH);
  323 
  324                 /*
  325                  * If no interrupt specified (or "?"), use what the board tells us.
  326                  */
  327                 error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
  328                 if (error && intr_vals[1] != NULL)
  329                         error = bus_set_resource(dev, SYS_RES_IRQ, 0,
  330                           intr_vals[1][iptr], 1);
  331                 if (error)
  332                         return (error);
  333 
  334                 /*
  335                  * Enable interrupts.
  336                  */
  337                 ed_asic_outb(sc, ED_WD790_ICR,
  338                   ed_asic_inb(sc, ED_WD790_ICR) | ED_WD790_ICR_EIL);
  339         }
  340         error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
  341         if (error) {
  342                 device_printf(dev, "%s cards don't support auto-detected/assigned interrupts.\n",
  343                               sc->type_str);
  344                 return (ENXIO);
  345         }
  346         sc->isa16bit = isa16bit;
  347         sc->mem_shared = 1;
  348 
  349         /*
  350          * allocate one xmit buffer if < 16k, two buffers otherwise
  351          */
  352         if (memsize < 16384 || (flags & ED_FLAGS_NO_MULTI_BUFFERING))
  353                 sc->txb_cnt = 1;
  354         else
  355                 sc->txb_cnt = 2;
  356         sc->tx_page_start = ED_WD_PAGE_OFFSET;
  357         sc->rec_page_start = ED_WD_PAGE_OFFSET + ED_TXBUF_SIZE * sc->txb_cnt;
  358         sc->rec_page_stop = ED_WD_PAGE_OFFSET + memsize / ED_PAGE_SIZE;
  359         sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * sc->rec_page_start);
  360         sc->mem_size = memsize;
  361         sc->mem_end = sc->mem_start + memsize;
  362 
  363         /*
  364          * Get station address from on-board ROM
  365          */
  366         for (i = 0; i < ETHER_ADDR_LEN; ++i)
  367                 sc->enaddr[i] = ed_asic_inb(sc, ED_WD_PROM + i);
  368 
  369         /*
  370          * Set upper address bits and 8/16 bit access to shared memory.
  371          */
  372         if (isa16bit) {
  373                 if (sc->chip_type == ED_CHIP_TYPE_WD790)
  374                         sc->wd_laar_proto = ed_asic_inb(sc, ED_WD_LAAR);
  375                 else
  376                         sc->wd_laar_proto = ED_WD_LAAR_L16EN |
  377                             ((pmem >> 19) & ED_WD_LAAR_ADDRHI);
  378                 /*
  379                  * Enable 16bit access
  380                  */
  381                 ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto |
  382                     ED_WD_LAAR_M16EN);
  383         } else {
  384                 if (((sc->type & ED_WD_SOFTCONFIG) ||
  385                      (sc->type == ED_TYPE_TOSHIBA1) ||
  386                      (sc->type == ED_TYPE_TOSHIBA4) ||
  387                      (sc->type == ED_TYPE_WD8013EBT)) &&
  388                     (sc->chip_type != ED_CHIP_TYPE_WD790)) {
  389                         sc->wd_laar_proto = (pmem >> 19) &
  390                             ED_WD_LAAR_ADDRHI;
  391                         ed_asic_outb(sc, ED_WD_LAAR, sc->wd_laar_proto);
  392                 }
  393         }
  394 
  395         /*
  396          * Set address and enable interface shared memory.
  397          */
  398         if (sc->chip_type != ED_CHIP_TYPE_WD790) {
  399                 if (ED_FLAGS_GETTYPE(flags) == ED_FLAGS_TOSH_ETHER) {
  400                         ed_asic_outb(sc, ED_WD_MSR + 1,
  401                             ((pmem >> 8) & 0xe0) | 4);
  402                         ed_asic_outb(sc, ED_WD_MSR + 2, ((pmem >> 16) & 0x0f));
  403                         ed_asic_outb(sc, ED_WD_MSR,
  404                             ED_WD_MSR_MENB | ED_WD_MSR_POW);
  405                 } else {
  406                         ed_asic_outb(sc, ED_WD_MSR, ((pmem >> 13) &
  407                             ED_WD_MSR_ADDR) | ED_WD_MSR_MENB);
  408                 }
  409                 sc->cr_proto = ED_CR_RD2;
  410         } else {
  411                 ed_asic_outb(sc, ED_WD_MSR, ED_WD_MSR_MENB);
  412                 ed_asic_outb(sc, ED_WD790_HWR,
  413                     (ed_asic_inb(sc, ED_WD790_HWR) | ED_WD790_HWR_SWH));
  414                 ed_asic_outb(sc, ED_WD790_RAR,
  415                     ((pmem >> 13) & 0x0f) | ((pmem >> 11) & 0x40) |
  416                      (ed_asic_inb(sc, ED_WD790_RAR) & 0xb0));
  417                 ed_asic_outb(sc, ED_WD790_HWR,
  418                     (ed_asic_inb(sc, ED_WD790_HWR) & ~ED_WD790_HWR_SWH));
  419                 sc->cr_proto = 0;
  420         }
  421 
  422         /*
  423          * Disable 16bit access to shared memory - we leave it
  424          * disabled so that 1) machines reboot properly when the board
  425          * is set 16 bit mode and there are conflicting 8bit
  426          * devices/ROMS in the same 128k address space as this boards
  427          * shared memory. and 2) so that other 8 bit devices with
  428          * shared memory can be used in this 128k region, too.
  429          */
  430         error = ed_clear_memory(dev);
  431         ed_disable_16bit_access(sc);
  432         sc->sc_write_mbufs = ed_shmem_write_mbufs;
  433         return (error);
  434 }
  435 
  436 int
  437 ed_probe_WD80x3(device_t dev, int port_rid, int flags)
  438 {
  439         struct ed_softc *sc = device_get_softc(dev);
  440         int     error;
  441         static uint16_t *intr_vals[] = {ed_intr_val, ed_790_intr_val};
  442 
  443         error = ed_alloc_port(dev, port_rid, ED_WD_IO_PORTS);
  444         if (error)
  445                 return (error);
  446 
  447         sc->asic_offset = ED_WD_ASIC_OFFSET;
  448         sc->nic_offset  = ED_WD_NIC_OFFSET;
  449 
  450         return ed_probe_WD80x3_generic(dev, flags, intr_vals);
  451 }

Cache object: e5776b5d9ed5b825a40c7cf1d324d544


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