root/dev/isa/if_we.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. we_probe
  2. we_attach
  3. we_test_mem
  4. we_readmem
  5. we_write_mbuf
  6. we_ring_copy
  7. we_read_hdr
  8. we_recv_int
  9. we_media_init
  10. we_mediachange
  11. we_mediastatus
  12. we_params

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

/* [<][>][^][v][top][bottom][index][help] */