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.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 /*      $OpenBSD: if_we.c,v 1.28 2022/04/06 18:59:28 naddy Exp $        */
    2 /*      $NetBSD: if_we.c,v 1.11 1998/07/05 06:49:14 jonathan Exp $      */
    3 
    4 /*-
    5  * Copyright (c) 1997, 1998 The NetBSD Foundation, Inc.
    6  * All rights reserved.
    7  *
    8  * This code is derived from software contributed to The NetBSD Foundation
    9  * by Jason R. Thorpe of the Numerical Aerospace Simulation Facility,
   10  * NASA Ames Research Center.
   11  *
   12  * Redistribution and use in source and binary forms, with or without
   13  * modification, are permitted provided that the following conditions
   14  * are met:
   15  * 1. Redistributions of source code must retain the above copyright
   16  *    notice, this list of conditions and the following disclaimer.
   17  * 2. Redistributions in binary form must reproduce the above copyright
   18  *    notice, this list of conditions and the following disclaimer in the
   19  *    documentation and/or other materials provided with the distribution.
   20  *
   21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
   22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
   23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
   25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
   31  * POSSIBILITY OF SUCH DAMAGE.
   32  */
   33 
   34 /*
   35  * Device driver for National Semiconductor DS8390/WD83C690 based ethernet
   36  * adapters.
   37  *
   38  * Copyright (c) 1994, 1995 Charles M. Hannum.  All rights reserved.
   39  *
   40  * Copyright (C) 1993, David Greenman.  This software may be used, modified,
   41  * copied, distributed, and sold, in both source and binary form provided that
   42  * the above copyright and these terms are retained.  Under no circumstances is
   43  * the author responsible for the proper functioning of this software, nor does
   44  * the author assume any responsibility for damages incurred with its use.
   45  */
   46 
   47 /*
   48  * Device driver for the Western Digital/SMC 8003 and 8013 series,
   49  * and the SMC Elite Ultra (8216).
   50  */
   51 
   52 #include "bpfilter.h"
   53 #include "we.h"
   54 
   55 #include <sys/param.h>
   56 #include <sys/systm.h>
   57 #include <sys/device.h>
   58 #include <sys/socket.h>
   59 #include <sys/mbuf.h>
   60 #include <sys/syslog.h>
   61 
   62 #include <net/if.h>
   63 #include <net/if_media.h>
   64 
   65 #include <netinet/in.h>
   66 #include <netinet/if_ether.h>
   67 
   68 #if NBPFILTER > 0
   69 #include <net/bpf.h>
   70 #endif
   71 
   72 #include <machine/bus.h>
   73 #include <machine/intr.h>
   74 
   75 #include <dev/isa/isareg.h>
   76 #include <dev/isa/isavar.h>
   77 
   78 #include <dev/ic/dp8390reg.h>
   79 #include <dev/ic/dp8390var.h>
   80 
   81 #include <dev/isa/if_wereg.h>
   82 
   83 #ifndef __BUS_SPACE_HAS_STREAM_METHODS
   84 #define bus_space_read_region_stream_2  bus_space_read_region_2
   85 #define bus_space_write_stream_2        bus_space_write_2
   86 #define bus_space_write_region_stream_2 bus_space_write_region_2
   87 #endif
   88 
   89 struct we_softc {
   90         struct dp8390_softc sc_dp8390;
   91 
   92         bus_space_tag_t sc_asict;       /* space tag for ASIC */
   93         bus_space_handle_t sc_asich;    /* space handle for ASIC */
   94 
   95         u_int8_t sc_laar_proto;
   96         u_int8_t sc_msr_proto;
   97 
   98         u_int8_t sc_type;               /* our type */
   99 
  100         int sc_16bitp;                  /* are we 16 bit? */
  101 
  102         void *sc_ih;                    /* interrupt handle */
  103 };
  104 
  105 int     we_probe(struct device *, void *, void *);
  106 int     we_match(struct device *, void *, void *);
  107 void    we_attach(struct device *, struct device *, void *);
  108 
  109 const struct cfattach we_isa_ca = {
  110         sizeof(struct we_softc), we_probe, we_attach
  111 };
  112 
  113 #if NWE_ISAPNP
  114 const struct cfattach we_isapnp_ca = {
  115         sizeof(struct we_softc), we_match, we_attach
  116 };
  117 #endif /* NWE_ISAPNP */
  118 
  119 struct cfdriver we_cd = {
  120         NULL, "we", DV_IFNET
  121 };
  122 
  123 const char *we_params(bus_space_tag_t, bus_space_handle_t, u_int8_t *,
  124             bus_size_t *, int *, int *);
  125 
  126 void    we_media_init(struct dp8390_softc *);
  127 
  128 int     we_mediachange(struct dp8390_softc *);
  129 void    we_mediastatus(struct dp8390_softc *, struct ifmediareq *);
  130 
  131 void    we_recv_int(struct dp8390_softc *);
  132 int     we_write_mbuf(struct dp8390_softc *, struct mbuf *, int);
  133 int     we_ring_copy(struct dp8390_softc *, int, caddr_t, u_short);
  134 void    we_read_hdr(struct dp8390_softc *, int, struct dp8390_ring *);
  135 int     we_test_mem(struct dp8390_softc *);
  136 
  137 static __inline void we_readmem(struct we_softc *, int, u_int8_t *, int);
  138 
  139 static const int we_584_irq[] = {
  140         9, 3, 5, 7, 10, 11, 15, 4,
  141 };
  142 #define NWE_584_IRQ     (sizeof(we_584_irq) / sizeof(we_584_irq[0]))
  143 
  144 static const int we_790_irq[] = {
  145         IRQUNK, 9, 3, 5, 7, 10, 11, 15,
  146 };
  147 #define NWE_790_IRQ     (sizeof(we_790_irq) / sizeof(we_790_irq[0]))
  148 
  149 /*
  150  * Delay needed when switching 16-bit access to shared memory.
  151  */
  152 #define WE_DELAY(wsc) delay(3)
  153 
  154 /*
  155  * Enable card RAM, and 16-bit access.
  156  */
  157 #define WE_MEM_ENABLE(wsc) \
  158 do { \
  159         if ((wsc)->sc_16bitp) \
  160                 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  161                     WE_LAAR, (wsc)->sc_laar_proto | WE_LAAR_M16EN); \
  162         bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  163             WE_MSR, wsc->sc_msr_proto | WE_MSR_MENB); \
  164         WE_DELAY((wsc)); \
  165 } while (0)
  166 
  167 /*
  168  * Disable card RAM, and 16-bit access.
  169  */
  170 #define WE_MEM_DISABLE(wsc) \
  171 do { \
  172         bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  173             WE_MSR, (wsc)->sc_msr_proto); \
  174         if ((wsc)->sc_16bitp) \
  175                 bus_space_write_1((wsc)->sc_asict, (wsc)->sc_asich, \
  176                     WE_LAAR, (wsc)->sc_laar_proto); \
  177         WE_DELAY((wsc)); \
  178 } while (0)
  179 
  180 int
  181 we_probe(struct device *parent, void *match, void *aux)
  182 {
  183         struct cfdata *cf = ((struct device *)match)->dv_cfdata;
  184 
  185         return (we_match(parent, cf, aux));
  186 }
  187 
  188 int
  189 we_match(struct device *parent, void *match, void *aux)
  190 {
  191         struct isa_attach_args *ia = aux;
  192         struct cfdata *cf = match;
  193         bus_space_tag_t asict, memt;
  194         bus_space_handle_t asich, memh;
  195         bus_size_t memsize;
  196         int asich_valid, memh_valid;
  197         int i, is790, rv = 0;
  198         u_int8_t x, type;
  199 
  200         asict = ia->ia_iot;
  201         memt = ia->ia_memt;
  202 
  203         asich_valid = memh_valid = 0;
  204 
  205         /* Disallow wildcarded i/o addresses. */
  206         if (ia->ia_iobase == -1 /* ISACF_PORT_DEFAULT */)
  207                 return (0);
  208 
  209         /* Disallow wildcarded mem address. */
  210         if (ia->ia_maddr == -1 /* ISACF_IOMEM_DEFAULT */)
  211                 return (0);
  212 
  213         /* Attempt to map the device. */
  214         if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp") && ia->ia_ioh)
  215                 asich = ia->ia_ioh;
  216         else {
  217                 if (bus_space_map(asict, ia->ia_iobase, WE_NPORTS, 0, &asich))
  218                         goto out;
  219                 asich_valid = 1;
  220         }
  221 
  222 #ifdef TOSH_ETHER
  223         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_POW);
  224 #endif
  225 
  226         /*
  227          * Attempt to do a checksum over the station address PROM.
  228          * If it fails, it's probably not a WD/SMC board.  There is
  229          * a problem with this, though.  Some clone WD8003E boards
  230          * (e.g. Danpex) won't pass the checksum.  In this case,
  231          * the checksum byte always seems to be 0.
  232          */
  233         for (x = 0, i = 0; i < 8; i++)
  234                 x += bus_space_read_1(asict, asich, WE_PROM + i);
  235 
  236         if (x != WE_ROM_CHECKSUM_TOTAL) {
  237                 /* Make sure it's an 8003E clone... */
  238                 if (bus_space_read_1(asict, asich, WE_CARD_ID) !=
  239                     WE_TYPE_WD8003E)
  240                         goto out;
  241 
  242                 /* Check the checksum byte. */
  243                 if (bus_space_read_1(asict, asich, WE_PROM + 7) != 0)
  244                         goto out;
  245         }
  246 
  247         /*
  248          * Reset the card to force it into a known state.
  249          */
  250 #ifdef TOSH_ETHER
  251         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST | WE_MSR_POW);
  252 #else
  253         bus_space_write_1(asict, asich, WE_MSR, WE_MSR_RST);
  254 #endif
  255         delay(100);
  256 
  257         bus_space_write_1(asict, asich, WE_MSR,
  258             bus_space_read_1(asict, asich, WE_MSR) & ~WE_MSR_RST);
  259 
  260         /* Wait in case the card is reading its EEPROM. */
  261         delay(5000);
  262 
  263         /*
  264          * Get parameters.
  265          */
  266         if (we_params(asict, asich, &type, &memsize, NULL, &is790) == NULL)
  267                 goto out;
  268 
  269         /* Allow user to override probed value. */
  270         if (ia->ia_msize)
  271                 memsize = ia->ia_msize;
  272 
  273         /* Attempt to map the memory space. */
  274         if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp") && ia->ia_memh)
  275                 memh = ia->ia_memh;
  276         else {
  277                 if (bus_space_map(memt, ia->ia_maddr, memsize, 0, &memh))
  278                         goto out;
  279                 memh_valid = 1;
  280         }
  281 
  282         /*
  283          * If possible, get the assigned interrupt number from the card
  284          * and use it.
  285          */
  286         if (is790) {
  287                 u_int8_t hwr;
  288 
  289                 /* Assemble together the encoded interrupt number. */
  290                 hwr = bus_space_read_1(asict, asich, WE790_HWR);
  291                 bus_space_write_1(asict, asich, WE790_HWR,
  292                     hwr | WE790_HWR_SWH);
  293 
  294                 x = bus_space_read_1(asict, asich, WE790_GCR);
  295                 i = ((x & WE790_GCR_IR2) >> 4) |
  296                     ((x & (WE790_GCR_IR1|WE790_GCR_IR0)) >> 2);
  297                 bus_space_write_1(asict, asich, WE790_HWR,
  298                     hwr & ~WE790_HWR_SWH);
  299 
  300                 if (ia->ia_irq != IRQUNK && ia->ia_irq != we_790_irq[i])
  301                         printf("%s%d: changing IRQ %d to %d\n",
  302                             we_cd.cd_name, cf->cf_unit, ia->ia_irq,
  303                             we_790_irq[i]);
  304                 ia->ia_irq = we_790_irq[i];
  305         } else if (type & WE_SOFTCONFIG) {
  306                 /* Assemble together the encoded interrupt number. */
  307                 i = (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_IR2) |
  308                     ((bus_space_read_1(asict, asich, WE_IRR) &
  309                       (WE_IRR_IR0 | WE_IRR_IR1)) >> 5);
  310 
  311                 if (ia->ia_irq != IRQUNK && ia->ia_irq != we_584_irq[i])
  312                         printf("%s%d: changing IRQ %d to %d\n",
  313                             we_cd.cd_name, cf->cf_unit, ia->ia_irq,
  314                             we_584_irq[i]);
  315                 ia->ia_irq = we_584_irq[i];
  316         }
  317 
  318         /* So, we say we've found it! */
  319         ia->ia_iosize = WE_NPORTS;
  320         ia->ia_msize = memsize;
  321         rv = 1;
  322 
  323  out:
  324         if (asich_valid)
  325                 bus_space_unmap(asict, asich, WE_NPORTS);
  326         if (memh_valid)
  327                 bus_space_unmap(memt, memh, memsize);
  328         return (rv);
  329 }
  330 
  331 void
  332 we_attach(struct device *parent, struct device *self, void *aux)
  333 {
  334         struct we_softc *wsc = (struct we_softc *)self;
  335         struct dp8390_softc *sc = &wsc->sc_dp8390;
  336         struct isa_attach_args *ia = aux;
  337         bus_space_tag_t nict, asict, memt;
  338         bus_space_handle_t nich, asich, memh;
  339         const char *typestr;
  340         u_int8_t x;
  341         int i;
  342 
  343         printf("\n");
  344 
  345         nict = asict = ia->ia_iot;
  346         memt = ia->ia_memt;
  347 
  348         /* Map the device. */
  349         if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp") && ia->ia_ioh)
  350                 asich = ia->ia_ioh;
  351         else if (bus_space_map(asict, ia->ia_iobase, WE_NPORTS, 0, &asich)) {
  352                 printf("%s: can't map nic i/o space\n",
  353                     sc->sc_dev.dv_xname);
  354                 return;
  355         }
  356 
  357         if (bus_space_subregion(asict, asich, WE_NIC_OFFSET, WE_NIC_NPORTS,
  358             &nich)) {
  359                 printf("%s: can't subregion i/o space\n",
  360                     sc->sc_dev.dv_xname);
  361                 return;
  362         }
  363 
  364         typestr = we_params(asict, asich, &wsc->sc_type, NULL,
  365             &wsc->sc_16bitp, &sc->is790);
  366         if (typestr == NULL) {
  367                 printf("%s: where did the card go?\n",
  368                     sc->sc_dev.dv_xname);
  369                 return;
  370         }
  371 
  372         /*
  373          * Map memory space.  Note we use the size that might have
  374          * been overridden by the user.
  375          */
  376         if (!strcmp(parent->dv_cfdata->cf_driver->cd_name, "isapnp") && ia->ia_memh)
  377                 memh = ia->ia_memh;
  378         else if (bus_space_map(memt, ia->ia_maddr, ia->ia_msize, 0, &memh)) {
  379                 printf("%s: can't map shared memory\n",
  380                     sc->sc_dev.dv_xname);
  381                 return;
  382         }
  383 
  384         /*
  385          * Allow user to override 16-bit mode.  8-bit takes precedence.
  386          */
  387         if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_16BIT_MODE)
  388                 wsc->sc_16bitp = 1;
  389         if (self->dv_cfdata->cf_flags & WE_FLAGS_FORCE_8BIT_MODE)
  390                 wsc->sc_16bitp = 0;
  391 
  392         wsc->sc_asict = asict;
  393         wsc->sc_asich = asich;
  394 
  395         sc->sc_regt = nict;
  396         sc->sc_regh = nich;
  397 
  398         sc->sc_buft = memt;
  399         sc->sc_bufh = memh;
  400 
  401         /* Interface is always enabled. */
  402         sc->sc_enabled = 1;
  403 
  404         /* Registers are linear. */
  405         for (i = 0; i < 16; i++)
  406                 sc->sc_reg_map[i] = i;
  407 
  408         /* Now we can use the NIC_{GET,PUT}() macros. */
  409 
  410         printf("%s: %s (%s-bit)", sc->sc_dev.dv_xname, typestr,
  411             wsc->sc_16bitp ? "16" : "8");
  412 
  413         /* Get station address from EEPROM. */
  414         for (i = 0; i < ETHER_ADDR_LEN; i++)
  415                 sc->sc_arpcom.ac_enaddr[i] =
  416                     bus_space_read_1(asict, asich, WE_PROM + i);
  417 
  418         /*
  419          * Set upper address bits and 8/16 bit access to shared memory.
  420          */
  421         if (sc->is790) {
  422                 wsc->sc_laar_proto =
  423                     bus_space_read_1(asict, asich, WE_LAAR) &
  424                     ~WE_LAAR_M16EN;
  425                 bus_space_write_1(asict, asich, WE_LAAR,
  426                     wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
  427         } else if ((wsc->sc_type & WE_SOFTCONFIG) ||
  428 #ifdef TOSH_ETHER
  429             (wsc->sc_type == WE_TYPE_TOSHIBA1) ||
  430             (wsc->sc_type == WE_TYPE_TOSHIBA4) ||
  431 #endif
  432             (wsc->sc_type == WE_TYPE_WD8013EBT)) {
  433                 wsc->sc_laar_proto = (ia->ia_maddr >> 19) & WE_LAAR_ADDRHI;
  434                 if (wsc->sc_16bitp)
  435                         wsc->sc_laar_proto |= WE_LAAR_L16EN;
  436                 bus_space_write_1(asict, asich, WE_LAAR,
  437                     wsc->sc_laar_proto | (wsc->sc_16bitp ? WE_LAAR_M16EN : 0));
  438         }
  439 
  440         /*
  441          * Set address and enable interface shared memory.
  442          */
  443         if (sc->is790) {
  444                 /* XXX MAGIC CONSTANTS XXX */
  445                 x = bus_space_read_1(asict, asich, 0x04);
  446                 bus_space_write_1(asict, asich, 0x04, x | 0x80);
  447                 bus_space_write_1(asict, asich, 0x0b,
  448                     ((ia->ia_maddr >> 13) & 0x0f) |
  449                     ((ia->ia_maddr >> 11) & 0x40) |
  450                     (bus_space_read_1(asict, asich, 0x0b) & 0xb0));
  451                 bus_space_write_1(asict, asich, 0x04, x);
  452                 wsc->sc_msr_proto = 0x00;
  453                 sc->cr_proto = 0x00;
  454         } else {
  455 #ifdef TOSH_ETHER
  456                 if (wsc->sc_type == WE_TYPE_TOSHIBA1 ||
  457                     wsc->sc_type == WE_TYPE_TOSHIBA4) {
  458                         bus_space_write_1(asict, asich, WE_MSR + 1,
  459                             ((ia->ia_maddr >> 8) & 0xe0) | 0x04);
  460                         bus_space_write_1(asict, asich, WE_MSR + 2,
  461                             ((ia->ia_maddr >> 16) & 0x0f));
  462                         wsc->sc_msr_proto = WE_MSR_POW;
  463                 } else
  464 #endif
  465                         wsc->sc_msr_proto = (ia->ia_maddr >> 13) &
  466                             WE_MSR_ADDR;
  467 
  468                 sc->cr_proto = ED_CR_RD2;
  469         }
  470 
  471         bus_space_write_1(asict, asich, WE_MSR,
  472             wsc->sc_msr_proto | WE_MSR_MENB);
  473         WE_DELAY(wsc);
  474 
  475         /*
  476          * DCR gets:
  477          *
  478          *      FIFO threshold to 8, No auto-init Remote DMA,
  479          *      byte order=80x86.
  480          *
  481          * 16-bit cards also get word-wide DMA transfers.
  482          */
  483         sc->dcr_reg = ED_DCR_FT1 | ED_DCR_LS |
  484             (wsc->sc_16bitp ? ED_DCR_WTS : 0);
  485 
  486         sc->test_mem = we_test_mem;
  487         sc->ring_copy = we_ring_copy;
  488         sc->write_mbuf = we_write_mbuf;
  489         sc->read_hdr = we_read_hdr;
  490         sc->recv_int = we_recv_int;
  491 
  492         sc->sc_mediachange = we_mediachange;
  493         sc->sc_mediastatus = we_mediastatus;
  494 
  495         sc->mem_start = 0;
  496         sc->mem_size = ia->ia_msize;
  497 
  498         sc->sc_flags = self->dv_cfdata->cf_flags;
  499 
  500         /* Do generic parts of attach. */
  501         if (wsc->sc_type & WE_SOFTCONFIG)
  502                 sc->sc_media_init = we_media_init;
  503         else
  504                 sc->sc_media_init = dp8390_media_init;
  505         if (dp8390_config(sc)) {
  506                 printf(": configuration failed\n");
  507                 return;
  508         }
  509 
  510         /*
  511          * Disable 16-bit access to shared memory - we leave it disabled
  512          * so that:
  513          *
  514          *      (1) machines reboot properly when the board is set to
  515          *          16-bit mode and there are conflicting 8-bit devices
  516          *          within the same 128k address space as this board's
  517          *          shared memory, and
  518          *
  519          *      (2) so that other 8-bit devices with shared memory
  520          *          in this same 128k address space will work.
  521          */
  522         WE_MEM_DISABLE(wsc);
  523 
  524         /*
  525          * Enable the configured interrupt.
  526          */
  527         if (sc->is790)
  528                 bus_space_write_1(asict, asich, WE790_ICR,
  529                     bus_space_read_1(asict, asich, WE790_ICR) |
  530                     WE790_ICR_EIL);
  531         else if (wsc->sc_type & WE_SOFTCONFIG)
  532                 bus_space_write_1(asict, asich, WE_IRR,
  533                     bus_space_read_1(asict, asich, WE_IRR) | WE_IRR_IEN);
  534         else if (ia->ia_irq == IRQUNK) {
  535                 printf("%s: can't wildcard IRQ on a %s\n",
  536                     sc->sc_dev.dv_xname, typestr);
  537                 return;
  538         }
  539 
  540         /* Establish interrupt handler. */
  541         wsc->sc_ih = isa_intr_establish(ia->ia_ic, ia->ia_irq, IST_EDGE,
  542             IPL_NET, dp8390_intr, sc, sc->sc_dev.dv_xname);
  543         if (wsc->sc_ih == NULL)
  544                 printf("%s: can't establish interrupt\n", sc->sc_dev.dv_xname);
  545 }
  546 
  547 int
  548 we_test_mem(struct dp8390_softc *sc)
  549 {
  550         struct we_softc *wsc = (struct we_softc *)sc;
  551         bus_space_tag_t memt = sc->sc_buft;
  552         bus_space_handle_t memh = sc->sc_bufh;
  553         bus_size_t memsize = sc->mem_size;
  554         int i;
  555 
  556         if (wsc->sc_16bitp)
  557                 bus_space_set_region_2(memt, memh, 0, 0, memsize >> 1);
  558         else
  559                 bus_space_set_region_1(memt, memh, 0, 0, memsize);
  560 
  561         if (wsc->sc_16bitp) {
  562                 for (i = 0; i < memsize; i += 2) {
  563                         if (bus_space_read_2(memt, memh, i) != 0)
  564                                 goto fail;
  565                 }
  566         } else {
  567                 for (i = 0; i < memsize; i++) {
  568                         if (bus_space_read_1(memt, memh, i) != 0)
  569                                 goto fail;
  570                 }
  571         }
  572 
  573         return (0);
  574 
  575  fail:
  576         printf("%s: failed to clear shared memory at offset 0x%x\n",
  577             sc->sc_dev.dv_xname, i);
  578         WE_MEM_DISABLE(wsc);
  579         return (1);
  580 }
  581 
  582 /*
  583  * Given a NIC memory source address and a host memory destination address,
  584  * copy 'len' from NIC to host using shared memory.  The 'len' is rounded
  585  * up to a word - ok as long as mbufs are word-sized.
  586  */
  587 static __inline void
  588 we_readmem(struct we_softc *wsc, int from, u_int8_t *to, int len)
  589 {
  590         bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
  591         bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
  592 
  593         if (len & 1)
  594                 ++len;
  595 
  596         if (wsc->sc_16bitp)
  597                 bus_space_read_region_stream_2(memt, memh, from,
  598                     (u_int16_t *)to, len >> 1);
  599         else
  600                 bus_space_read_region_1(memt, memh, from,
  601                     to, len);
  602 }
  603 
  604 int
  605 we_write_mbuf(struct dp8390_softc *sc, struct mbuf *m, int buf)
  606 {
  607         struct we_softc *wsc = (struct we_softc *)sc;
  608         bus_space_tag_t memt = wsc->sc_dp8390.sc_buft;
  609         bus_space_handle_t memh = wsc->sc_dp8390.sc_bufh;
  610         u_int8_t *data, savebyte[2];
  611         int savelen, len, leftover;
  612 #ifdef DIAGNOSTIC
  613         u_int8_t *lim;
  614 #endif
  615 
  616         savelen = m->m_pkthdr.len;
  617 
  618         WE_MEM_ENABLE(wsc);
  619 
  620         /*
  621          * 8-bit boards are simple; no alignment tricks are necessary.
  622          */
  623         if (wsc->sc_16bitp == 0) {
  624                 for (; m != NULL; buf += m->m_len, m = m->m_next)
  625                         bus_space_write_region_1(memt, memh,
  626                             buf, mtod(m, u_int8_t *), m->m_len);
  627                 goto out;
  628         }
  629 
  630         /* Start out with no leftover data. */
  631         leftover = 0;
  632         savebyte[0] = savebyte[1] = 0;
  633 
  634         for (; m != NULL; m = m->m_next) {
  635                 len = m->m_len;
  636                 if (len == 0)
  637                         continue;
  638                 data = mtod(m, u_int8_t *);
  639 #ifdef DIAGNOSTIC
  640                 lim = data + len;
  641 #endif
  642                 while (len > 0) {
  643                         if (leftover) {
  644                                 /*
  645                                  * Data left over (from mbuf or realignment).
  646                                  * Buffer the next byte, and write it and
  647                                  * the leftover data out.
  648                                  */
  649                                 savebyte[1] = *data++;
  650                                 len--;
  651                                 bus_space_write_stream_2(memt, memh, buf,
  652                                     *(u_int16_t *)savebyte);
  653                                 buf += 2;
  654                                 leftover = 0;
  655                         } else if (ALIGNED_POINTER(data, u_int16_t) == 0) {
  656                                 /*
  657                                  * Unaligned dta; buffer the next byte.
  658                                  */
  659                                 savebyte[0] = *data++;
  660                                 len--;
  661                                 leftover = 1;
  662                         } else {
  663                                 /*
  664                                  * Aligned data; output contiguous words as
  665                                  * much as we can, then buffer the remaining
  666                                  * byte, if any.
  667                                  */
  668                                 leftover = len & 1;
  669                                 len &= ~1;
  670                                 bus_space_write_region_stream_2(memt, memh,
  671                                     buf, (u_int16_t *)data, len >> 1);
  672                                 data += len;
  673                                 buf += len;
  674                                 if (leftover)
  675                                         savebyte[0] = *data++;
  676                                 len = 0;
  677                         }
  678                 }
  679                 if (len < 0)
  680                         panic("we_write_mbuf: negative len");
  681 #ifdef DIAGNOSTIC
  682                 if (data != lim)
  683                         panic("we_write_mbuf: data != lim");
  684 #endif
  685         }
  686         if (leftover) {
  687                 savebyte[1] = 0;
  688                 bus_space_write_stream_2(memt, memh, buf,
  689                     *(u_int16_t *)savebyte);
  690         }
  691 
  692  out:
  693         WE_MEM_DISABLE(wsc);
  694 
  695         return (savelen);
  696 }
  697 
  698 int
  699 we_ring_copy(struct dp8390_softc *sc, int src, caddr_t dst, u_short amount)
  700 {
  701         struct we_softc *wsc = (struct we_softc *)sc;
  702         u_short tmp_amount;
  703 
  704         /* Does copy wrap to lower addr in ring buffer? */
  705         if (src + amount > sc->mem_end) {
  706                 tmp_amount = sc->mem_end - src;
  707 
  708                 /* Copy amount up to end of NIC memory. */
  709                 we_readmem(wsc, src, dst, tmp_amount);
  710 
  711                 amount -= tmp_amount;
  712                 src = sc->mem_ring;
  713                 dst += tmp_amount;
  714         }
  715 
  716         we_readmem(wsc, src, dst, amount);
  717 
  718         return (src + amount);
  719 }
  720 
  721 void
  722 we_read_hdr(struct dp8390_softc *sc, int packet_ptr,
  723     struct dp8390_ring *packet_hdrp)
  724 {
  725         struct we_softc *wsc = (struct we_softc *)sc;
  726 
  727         we_readmem(wsc, packet_ptr, (u_int8_t *)packet_hdrp,
  728             sizeof(struct dp8390_ring));
  729 #if BYTE_ORDER == BIG_ENDIAN
  730         packet_hdrp->count = swap16(packet_hdrp->count);
  731 #endif
  732 }
  733 
  734 void
  735 we_recv_int(struct dp8390_softc *sc)
  736 {
  737         struct we_softc *wsc = (struct we_softc *)sc;
  738 
  739         WE_MEM_ENABLE(wsc);
  740         dp8390_rint(sc);
  741         WE_MEM_DISABLE(wsc);
  742 }
  743 
  744 void
  745 we_media_init(struct dp8390_softc *sc)
  746 {
  747         struct we_softc *wsc = (void *)sc;
  748         uint64_t defmedia = IFM_ETHER;
  749         u_int8_t x;
  750 
  751         if (sc->is790) {
  752                 x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR);
  753                 bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
  754                     x | WE790_HWR_SWH);
  755                 if (bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE790_GCR) &
  756                     WE790_GCR_GPOUT)
  757                         defmedia |= IFM_10_2;
  758                 else
  759                         defmedia |= IFM_10_5;
  760                 bus_space_write_1(wsc->sc_asict, wsc->sc_asich, WE790_HWR,
  761                     x &~ WE790_HWR_SWH);
  762         } else {
  763                 x = bus_space_read_1(wsc->sc_asict, wsc->sc_asich, WE_IRR);
  764                 if (x & WE_IRR_OUT2)
  765                         defmedia |= IFM_10_2;
  766                 else
  767                         defmedia |= IFM_10_5;
  768         }
  769 
  770         ifmedia_init(&sc->sc_media, 0, dp8390_mediachange, dp8390_mediastatus);
  771         ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_2, 0, NULL);
  772         ifmedia_add(&sc->sc_media, IFM_ETHER|IFM_10_5, 0, NULL);
  773         ifmedia_set(&sc->sc_media, defmedia);
  774 }
  775 
  776 int
  777 we_mediachange(struct dp8390_softc *sc)
  778 {
  779 
  780         /*
  781          * Current media is already set up.  Just reset the interface
  782          * to let the new value take hold.  The new media will be
  783          * set up in dp8390_init().
  784          */
  785         dp8390_reset(sc);
  786         return (0);
  787 }
  788 
  789 void
  790 we_mediastatus(struct dp8390_softc *sc, struct ifmediareq *ifmr)
  791 {
  792         struct ifmedia *ifm = &sc->sc_media;
  793 
  794         /*
  795          * The currently selected media is always the active media.
  796          */
  797         ifmr->ifm_active = ifm->ifm_cur->ifm_media;
  798 }
  799 
  800 const char *
  801 we_params(bus_space_tag_t asict, bus_space_handle_t asich,
  802     u_int8_t *typep, bus_size_t *memsizep, int *is16bitp,
  803     int *is790p)
  804 {
  805         const char *typestr;
  806         bus_size_t memsize;
  807         int is16bit, is790;
  808         u_int8_t type;
  809 
  810         memsize = 8192;
  811         is16bit = is790 = 0;
  812 
  813         type = bus_space_read_1(asict, asich, WE_CARD_ID);
  814         switch (type) {
  815         case WE_TYPE_WD8003S: 
  816                 typestr = "WD8003S"; 
  817                 break;
  818         case WE_TYPE_WD8003E:
  819                 typestr = "WD8003E";
  820                 break;
  821         case WE_TYPE_WD8003EB: 
  822                 typestr = "WD8003EB";
  823                 break;
  824         case WE_TYPE_WD8003W:
  825                 typestr = "WD8003W";
  826                 break;
  827         case WE_TYPE_WD8013EBT: 
  828                 typestr = "WD8013EBT";
  829                 memsize = 16384;
  830                 is16bit = 1;
  831                 break;
  832         case WE_TYPE_WD8013W:
  833                 typestr = "WD8013W";
  834                 memsize = 16384;
  835                 is16bit = 1;
  836                 break;
  837         case WE_TYPE_WD8013EP:          /* also WD8003EP */
  838                 if (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) {
  839                         is16bit = 1;
  840                         memsize = 16384;
  841                         typestr = "WD8013EP";
  842                 } else
  843                         typestr = "WD8003EP";
  844                 break;
  845         case WE_TYPE_WD8013WC:
  846                 typestr = "WD8013WC";
  847                 memsize = 16384;
  848                 is16bit = 1;
  849                 break;
  850         case WE_TYPE_WD8013EBP:
  851                 typestr = "WD8013EBP";
  852                 memsize = 16384;
  853                 is16bit = 1;
  854                 break;
  855         case WE_TYPE_WD8013EPC:
  856                 typestr = "WD8013EPC";
  857                 memsize = 16384;
  858                 is16bit = 1;
  859                 break;
  860         case WE_TYPE_SMC8216C:
  861         case WE_TYPE_SMC8216T:
  862             {
  863                 u_int8_t hwr;
  864 
  865                 typestr = (type == WE_TYPE_SMC8216C) ?
  866                     "SMC8216/SMC8216C" : "SMC8216T";
  867 
  868                 hwr = bus_space_read_1(asict, asich, WE790_HWR);
  869                 bus_space_write_1(asict, asich, WE790_HWR,
  870                     hwr | WE790_HWR_SWH);
  871                 switch (bus_space_read_1(asict, asich, WE790_RAR) &
  872                     WE790_RAR_SZ64) {
  873                 case WE790_RAR_SZ64:
  874                         memsize = 65536;
  875                         break;
  876                 case WE790_RAR_SZ32:
  877                         memsize = 32768;
  878                         break;
  879                 case WE790_RAR_SZ16:
  880                         memsize = 16384;
  881                         break;
  882                 case WE790_RAR_SZ8:
  883                         /* 8216 has 16K shared mem -- 8416 has 8K */
  884                         typestr = (type == WE_TYPE_SMC8216C) ?
  885                             "SMC8416C/SMC8416BT" : "SMC8416T";
  886                         memsize = 8192;
  887                         break;
  888                 }
  889                 bus_space_write_1(asict, asich, WE790_HWR, hwr);
  890 
  891                 is16bit = 1;
  892                 is790 = 1;
  893                 break;
  894             }
  895 #ifdef TOSH_ETHER
  896         case WE_TYPE_TOSHIBA1:
  897                 typestr = "Toshiba1";
  898                 memsize = 32768;
  899                 is16bit = 1;
  900                 break;
  901         case WE_TYPE_TOSHIBA4:
  902                 typestr = "Toshiba4";
  903                 memsize = 32768;
  904                 is16bit = 1;
  905                 break;
  906 #endif
  907         default:
  908                 /* Not one we recognize. */
  909                 return (NULL);
  910         }
  911 
  912         /*
  913          * Make some adjustments to initial values depending on what is
  914          * found in the ICR.
  915          */
  916         if (is16bit && (type != WE_TYPE_WD8013EBT) &&
  917 #ifdef TOSH_ETHER
  918             (type != WE_TYPE_TOSHIBA1 && type != WE_TYPE_TOSHIBA4) &&
  919 #endif
  920             (bus_space_read_1(asict, asich, WE_ICR) & WE_ICR_16BIT) == 0) {
  921                 is16bit = 0;
  922                 memsize = 8192;
  923         }
  924 
  925 #ifdef WE_DEBUG
  926         {
  927                 int i;
  928 
  929                 printf("we_params: type = 0x%x, typestr = %s, is16bit = %d, "
  930                     "memsize = %d\n", type, typestr, is16bit, memsize);
  931                 for (i = 0; i < 8; i++)
  932                         printf("     %d -> 0x%x\n", i,
  933                             bus_space_read_1(asict, asich, i));
  934         }
  935 #endif
  936 
  937         if (typep != NULL)
  938                 *typep = type;
  939         if (memsizep != NULL)
  940                 *memsizep = memsize;
  941         if (is16bitp != NULL)
  942                 *is16bitp = is16bit;
  943         if (is790p != NULL)
  944                 *is790p = is790;
  945         return (typestr);
  946 }

Cache object: 9c13edcefd3d960b85badb6a780a6e77


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