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_3c503.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 #ifdef ED_3C503
   36 
   37 #include <sys/param.h>
   38 #include <sys/systm.h>
   39 #include <sys/sockio.h>
   40 #include <sys/mbuf.h>
   41 #include <sys/kernel.h>
   42 #include <sys/socket.h>
   43 #include <sys/syslog.h>
   44 
   45 #include <sys/bus.h>
   46 
   47 #include <machine/bus.h>
   48 #include <sys/rman.h>
   49 #include <machine/resource.h>
   50 
   51 #include <net/ethernet.h>
   52 #include <net/if.h>
   53 #include <net/if_arp.h>
   54 #include <net/if_dl.h>
   55 #include <net/if_mib.h>
   56 #include <net/if_media.h>
   57 
   58 #include <net/bpf.h>
   59 
   60 #include <dev/ed/if_edreg.h>
   61 #include <dev/ed/if_edvar.h>
   62 
   63 static void ed_3c503_mediachg(struct ed_softc *sc);
   64 
   65 /*
   66  * Probe and vendor-specific initialization routine for 3Com 3c503 boards
   67  */
   68 int
   69 ed_probe_3Com(device_t dev, int port_rid, int flags)
   70 {
   71         struct ed_softc *sc = device_get_softc(dev);
   72         int     error;
   73         int     i;
   74         u_int   memsize;
   75         u_char  isa16bit;
   76         u_long  conf_maddr, conf_msize, irq, junk, pmem;
   77 
   78         error = ed_alloc_port(dev, 0, ED_3COM_IO_PORTS);
   79         if (error)
   80                 return (error);
   81 
   82         sc->asic_offset = ED_3COM_ASIC_OFFSET;
   83         sc->nic_offset  = ED_3COM_NIC_OFFSET;
   84 
   85         /*
   86          * Verify that the kernel configured I/O address matches the board
   87          * configured address
   88          */
   89         switch (ed_asic_inb(sc, ED_3COM_BCFR)) {
   90         case ED_3COM_BCFR_300:
   91                 if (rman_get_start(sc->port_res) != 0x300)
   92                         return (ENXIO);
   93                 break;
   94         case ED_3COM_BCFR_310:
   95                 if (rman_get_start(sc->port_res) != 0x310)
   96                         return (ENXIO);
   97                 break;
   98         case ED_3COM_BCFR_330:
   99                 if (rman_get_start(sc->port_res) != 0x330)
  100                         return (ENXIO);
  101                 break;
  102         case ED_3COM_BCFR_350:
  103                 if (rman_get_start(sc->port_res) != 0x350)
  104                         return (ENXIO);
  105                 break;
  106         case ED_3COM_BCFR_250:
  107                 if (rman_get_start(sc->port_res) != 0x250)
  108                         return (ENXIO);
  109                 break;
  110         case ED_3COM_BCFR_280:
  111                 if (rman_get_start(sc->port_res) != 0x280)
  112                         return (ENXIO);
  113                 break;
  114         case ED_3COM_BCFR_2A0:
  115                 if (rman_get_start(sc->port_res) != 0x2a0)
  116                         return (ENXIO);
  117                 break;
  118         case ED_3COM_BCFR_2E0:
  119                 if (rman_get_start(sc->port_res) != 0x2e0)
  120                         return (ENXIO);
  121                 break;
  122         default:
  123                 return (ENXIO);
  124         }
  125 
  126         error = bus_get_resource(dev, SYS_RES_MEMORY, 0,
  127                                  &conf_maddr, &conf_msize);
  128         if (error)
  129                 return (error);
  130 
  131         /*
  132          * Verify that the kernel shared memory address matches the board
  133          * configured address.
  134          */
  135         switch (ed_asic_inb(sc, ED_3COM_PCFR)) {
  136         case ED_3COM_PCFR_DC000:
  137                 if (conf_maddr != 0xdc000)
  138                         return (ENXIO);
  139                 break;
  140         case ED_3COM_PCFR_D8000:
  141                 if (conf_maddr != 0xd8000)
  142                         return (ENXIO);
  143                 break;
  144         case ED_3COM_PCFR_CC000:
  145                 if (conf_maddr != 0xcc000)
  146                         return (ENXIO);
  147                 break;
  148         case ED_3COM_PCFR_C8000:
  149                 if (conf_maddr != 0xc8000)
  150                         return (ENXIO);
  151                 break;
  152         default:
  153                 return (ENXIO);
  154         }
  155 
  156 
  157         /*
  158          * Reset NIC and ASIC. Enable on-board transceiver throughout reset
  159          * sequence because it'll lock up if the cable isn't connected if we
  160          * don't.
  161          */
  162         ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_RST | ED_3COM_CR_XSEL);
  163 
  164         /*
  165          * Wait for a while, then un-reset it
  166          */
  167         DELAY(50);
  168 
  169         /*
  170          * The 3Com ASIC defaults to rather strange settings for the CR after
  171          * a reset - it's important to set it again after the following outb
  172          * (this is done when we map the PROM below).
  173          */
  174         ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
  175 
  176         /*
  177          * Wait a bit for the NIC to recover from the reset
  178          */
  179         DELAY(5000);
  180 
  181         sc->vendor = ED_VENDOR_3COM;
  182         sc->type_str = "3c503";
  183         sc->mem_shared = 1;
  184         sc->cr_proto = ED_CR_RD2;
  185 
  186         /*
  187          * Hmmm...a 16bit 3Com board has 16k of memory, but only an 8k window
  188          * to it.
  189          */
  190         memsize = 8192;
  191 
  192         /*
  193          * Get station address from on-board ROM
  194          */
  195 
  196         /*
  197          * First, map ethernet address PROM over the top of where the NIC
  198          * registers normally appear.
  199          */
  200         ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_EALO | ED_3COM_CR_XSEL);
  201 
  202         for (i = 0; i < ETHER_ADDR_LEN; ++i)
  203                 sc->enaddr[i] = ed_nic_inb(sc, i);
  204 
  205         /*
  206          * Unmap PROM - select NIC registers. The proper setting of the
  207          * tranceiver is set in ed_init so that the attach code is given a
  208          * chance to set the default based on a compile-time config option
  209          */
  210         ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
  211 
  212         /*
  213          * Determine if this is an 8bit or 16bit board
  214          */
  215 
  216         /*
  217          * select page 0 registers
  218          */
  219         ed_nic_outb(sc, ED_P0_CR, ED_CR_RD2 | ED_CR_STP);
  220 
  221         /*
  222          * Attempt to clear WTS bit. If it doesn't clear, then this is a 16bit
  223          * board.
  224          */
  225         ed_nic_outb(sc, ED_P0_DCR, 0);
  226 
  227         /*
  228          * select page 2 registers
  229          */
  230         ed_nic_outb(sc, ED_P0_CR, ED_CR_PAGE_2 | ED_CR_RD2 | ED_CR_STP);
  231 
  232         /*
  233          * The 3c503 forces the WTS bit to a one if this is a 16bit board
  234          */
  235         if (ed_nic_inb(sc, ED_P2_DCR) & ED_DCR_WTS)
  236                 isa16bit = 1;
  237         else
  238                 isa16bit = 0;
  239 
  240         /*
  241          * select page 0 registers
  242          */
  243         ed_nic_outb(sc, ED_P2_CR, ED_CR_RD2 | ED_CR_STP);
  244 
  245         error = ed_alloc_memory(dev, 0, memsize);
  246         if (error)
  247                 return (error);
  248 
  249         pmem = rman_get_start(sc->mem_res);
  250         error = ed_isa_mem_ok(dev, pmem, memsize);
  251         if (error)
  252                 return (error);
  253 
  254         sc->mem_start = 0;
  255         sc->mem_size = memsize;
  256         sc->mem_end = sc->mem_start + memsize;
  257 
  258         /*
  259          * We have an entire 8k window to put the transmit buffers on the
  260          * 16bit boards. But since the 16bit 3c503's shared memory is only
  261          * fast enough to overlap the loading of one full-size packet, trying
  262          * to load more than 2 buffers can actually leave the transmitter idle
  263          * during the load. So 2 seems the best value. (Although a mix of
  264          * variable-sized packets might change this assumption. Nonetheless,
  265          * we optimize for linear transfers of same-size packets.)
  266          */
  267         if (isa16bit) {
  268                 if (flags & ED_FLAGS_NO_MULTI_BUFFERING)
  269                         sc->txb_cnt = 1;
  270                 else
  271                         sc->txb_cnt = 2;
  272 
  273                 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_16BIT;
  274                 sc->rec_page_start = ED_3COM_RX_PAGE_OFFSET_16BIT;
  275                 sc->rec_page_stop = memsize / ED_PAGE_SIZE +
  276                     ED_3COM_RX_PAGE_OFFSET_16BIT;
  277                 sc->mem_ring = sc->mem_start;
  278         } else {
  279                 sc->txb_cnt = 1;
  280                 sc->tx_page_start = ED_3COM_TX_PAGE_OFFSET_8BIT;
  281                 sc->rec_page_start = ED_TXBUF_SIZE + ED_3COM_TX_PAGE_OFFSET_8BIT;
  282                 sc->rec_page_stop = memsize / ED_PAGE_SIZE +
  283                     ED_3COM_TX_PAGE_OFFSET_8BIT;
  284                 sc->mem_ring = sc->mem_start + (ED_PAGE_SIZE * ED_TXBUF_SIZE);
  285         }
  286 
  287         sc->isa16bit = isa16bit;
  288 
  289         /*
  290          * Initialize GA page start/stop registers. Probably only needed if
  291          * doing DMA, but what the hell.
  292          */
  293         ed_asic_outb(sc, ED_3COM_PSTR, sc->rec_page_start);
  294         ed_asic_outb(sc, ED_3COM_PSPR, sc->rec_page_stop);
  295 
  296         /*
  297          * Set IRQ. 3c503 only allows a choice of irq 2-5.
  298          */
  299         error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
  300         if (error)
  301                 return (error);
  302 
  303         switch (irq) {
  304         case 2:
  305         case 9:
  306                 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ2);
  307                 break;
  308         case 3:
  309                 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ3);
  310                 break;
  311         case 4:
  312                 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ4);
  313                 break;
  314         case 5:
  315                 ed_asic_outb(sc, ED_3COM_IDCFR, ED_3COM_IDCFR_IRQ5);
  316                 break;
  317         default:
  318                 device_printf(dev, "Invalid irq configuration (%ld) must be 3-5,9 for 3c503\n",
  319                               irq);
  320                 return (ENXIO);
  321         }
  322 
  323         /*
  324          * Initialize GA configuration register. Set bank and enable shared
  325          * mem.
  326          */
  327         ed_asic_outb(sc, ED_3COM_GACFR, ED_3COM_GACFR_RSEL |
  328             ED_3COM_GACFR_MBS0);
  329 
  330         /*
  331          * Initialize "Vector Pointer" registers. These gawd-awful things are
  332          * compared to 20 bits of the address on ISA, and if they match, the
  333          * shared memory is disabled. We set them to 0xffff0...allegedly the
  334          * reset vector.
  335          */
  336         ed_asic_outb(sc, ED_3COM_VPTR2, 0xff);
  337         ed_asic_outb(sc, ED_3COM_VPTR1, 0xff);
  338         ed_asic_outb(sc, ED_3COM_VPTR0, 0x00);
  339 
  340         error = ed_clear_memory(dev);
  341         if (error == 0) {
  342                 sc->sc_mediachg = ed_3c503_mediachg;
  343                 sc->sc_write_mbufs = ed_shmem_write_mbufs;
  344         }
  345         return (error);
  346 }
  347 
  348 static void
  349 ed_3c503_mediachg(struct ed_softc *sc)
  350 {
  351         struct ifnet *ifp = sc->ifp;
  352 
  353         /*
  354          * If this is a 3Com board, the tranceiver must be software enabled
  355          * (there is no settable hardware default).
  356          */
  357         if (ifp->if_flags & IFF_LINK2)
  358                 ed_asic_outb(sc, ED_3COM_CR, 0);
  359         else
  360                 ed_asic_outb(sc, ED_3COM_CR, ED_3COM_CR_XSEL);
  361 }
  362 
  363 #endif /* ED_3C503 */

Cache object: 1c095b8fd5feeaaa52848f41c11f0cec


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