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/cs/if_cs.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) 1997,1998 Maxim Bolotin and Oleg Sharoiko.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice unmodified, this list of conditions, and the following
   10  *    disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  *
   15  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
   16  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   17  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   18  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
   19  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   20  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   21  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   22  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   23  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   24  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   25  * SUCH DAMAGE.
   26  *
   27  */
   28 
   29 #include <sys/cdefs.h>
   30 __FBSDID("$FreeBSD: releng/8.4/sys/dev/cs/if_cs.c 215342 2010-11-15 17:48:13Z sobomax $");
   31 
   32 /*
   33  *
   34  * Device driver for Crystal Semiconductor CS8920 based ethernet
   35  *   adapters. By Maxim Bolotin and Oleg Sharoiko, 27-April-1997
   36  */
   37 
   38 /*
   39 #define  CS_DEBUG 
   40  */
   41 
   42 #include <sys/param.h>
   43 #include <sys/systm.h>
   44 #include <sys/malloc.h>
   45 #include <sys/mbuf.h>
   46 #include <sys/socket.h>
   47 #include <sys/sockio.h>
   48 #include <sys/kernel.h>
   49 #include <sys/sysctl.h>
   50 #include <sys/syslog.h>
   51 
   52 #include <sys/module.h>
   53 #include <sys/bus.h>
   54 #include <machine/bus.h>
   55 #include <sys/rman.h>
   56 #include <machine/resource.h>
   57 
   58 #include <net/if.h>
   59 #include <net/if_arp.h>
   60 #include <net/if_dl.h>
   61 #include <net/if_media.h>
   62 #include <net/if_types.h>
   63 #include <net/ethernet.h>
   64 #include <net/bpf.h>
   65 
   66 #include <dev/cs/if_csvar.h>
   67 #include <dev/cs/if_csreg.h>
   68 
   69 #ifdef  CS_USE_64K_DMA
   70 #define CS_DMA_BUFFER_SIZE 65536
   71 #else
   72 #define CS_DMA_BUFFER_SIZE 16384
   73 #endif
   74 
   75 static void     cs_init(void *);
   76 static void     cs_init_locked(struct cs_softc *);
   77 static int      cs_ioctl(struct ifnet *, u_long, caddr_t);
   78 static void     cs_start(struct ifnet *);
   79 static void     cs_start_locked(struct ifnet *);
   80 static void     cs_stop(struct cs_softc *);
   81 static void     cs_reset(struct cs_softc *);
   82 static void     cs_watchdog(void *);
   83 
   84 static int      cs_mediachange(struct ifnet *);
   85 static void     cs_mediastatus(struct ifnet *, struct ifmediareq *);
   86 static int      cs_mediaset(struct cs_softc *, int);
   87 
   88 static void     cs_write_mbufs(struct cs_softc*, struct mbuf*);
   89 static void     cs_xmit_buf(struct cs_softc*);
   90 static int      cs_get_packet(struct cs_softc*);
   91 static void     cs_setmode(struct cs_softc*);
   92 
   93 static int      get_eeprom_data(struct cs_softc *sc, int, int, uint16_t *);
   94 static int      get_eeprom_cksum(int, int, uint16_t *);
   95 static int      wait_eeprom_ready( struct cs_softc *);
   96 static void     control_dc_dc( struct cs_softc *, int );
   97 static int      enable_tp(struct cs_softc *);
   98 static int      enable_aui(struct cs_softc *);
   99 static int      enable_bnc(struct cs_softc *);
  100 static int      cs_duplex_auto(struct cs_softc *);
  101 
  102 devclass_t cs_devclass;
  103 driver_intr_t   csintr;
  104 
  105 /* sysctl vars */
  106 SYSCTL_NODE(_hw, OID_AUTO, cs, CTLFLAG_RD, 0, "cs device parameters");
  107 
  108 int     cs_ignore_cksum_failure = 0;
  109 TUNABLE_INT("hw.cs.ignore_checksum_failure", &cs_ignore_cksum_failure);
  110 SYSCTL_INT(_hw_cs, OID_AUTO, ignore_checksum_failure, CTLFLAG_RW,
  111     &cs_ignore_cksum_failure, 0,
  112   "ignore checksum errors in cs card EEPROM");
  113 
  114 static int      cs_recv_delay = 570;
  115 TUNABLE_INT("hw.cs.recv_delay", &cs_recv_delay);
  116 SYSCTL_INT(_hw_cs, OID_AUTO, recv_delay, CTLFLAG_RW, &cs_recv_delay, 570, "");
  117 
  118 static int cs8900_eeint2irq[16] = {
  119          10,  11,  12,   5, 255, 255, 255, 255,
  120         255, 255, 255, 255, 255, 255, 255, 255 
  121 };
  122 
  123 static int cs8900_irq2eeint[16] = {
  124         255, 255, 255, 255, 255,   3, 255, 255,
  125         255,   0,   1,   2, 255, 255, 255, 255
  126 };
  127 
  128 static int
  129 get_eeprom_data(struct cs_softc *sc, int off, int len, uint16_t *buffer)
  130 {
  131         int i;
  132 
  133 #ifdef CS_DEBUG
  134         device_printf(sc->dev, "EEPROM data from %x for %x:\n", off, len);
  135 #endif
  136         for (i=0; i < len; i++) {
  137                 if (wait_eeprom_ready(sc) < 0)
  138                         return (-1);
  139                 /* Send command to EEPROM to read */
  140                 cs_writereg(sc, PP_EECMD, (off + i) | EEPROM_READ_CMD);
  141                 if (wait_eeprom_ready(sc) < 0)
  142                         return (-1);
  143                 buffer[i] = cs_readreg(sc, PP_EEData);
  144 
  145 #ifdef CS_DEBUG
  146                 printf("%04x ",buffer[i]);
  147 #endif
  148         }
  149 
  150 #ifdef CS_DEBUG
  151         printf("\n");
  152 #endif
  153         return (0);
  154 }
  155 
  156 static int
  157 get_eeprom_cksum(int off, int len, uint16_t *buffer)
  158 {
  159         int i;
  160         uint16_t cksum=0;
  161 
  162         for (i = 0; i < len; i++)
  163                 cksum += buffer[i];
  164         cksum &= 0xffff;
  165         if (cksum == 0 || cs_ignore_cksum_failure)
  166                 return (0);
  167         return (-1);
  168 }
  169 
  170 static int
  171 wait_eeprom_ready(struct cs_softc *sc)
  172 {
  173         int i;
  174 
  175         /*
  176          * From the CS8900A datasheet, section 3.5.2:
  177          * "Before issuing any command to the EEPROM, the host must wait
  178          * for the SIBUSY bit (Register 16, SelfST, bit 8) to clear.  After
  179          * each command has been issued, the host must wait again for SIBUSY
  180          * to clear."
  181          *
  182          * Before we issue the command, we should be !busy, so that will
  183          * be fast.  The datasheet suggests that clock out from the part
  184          * per word will be on the order of 25us, which is consistant with
  185          * the 1MHz serial clock and 16bits...  We should never hit 100,
  186          * let alone 15,000 here.  The original code did an unconditional
  187          * 30ms DELAY here.  Bad Kharma.  cs_readreg takes ~2us.
  188          */
  189         for (i = 0; i < 15000; i++)     /* 30ms max */
  190                 if (!(cs_readreg(sc, PP_SelfST) & SI_BUSY))
  191                         return (0);
  192         return (1);
  193 }
  194 
  195 static void
  196 control_dc_dc(struct cs_softc *sc, int on_not_off)
  197 {
  198         unsigned int self_control = HCB1_ENBL;
  199 
  200         if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0) ^ on_not_off)
  201                 self_control |= HCB1;
  202         else
  203                 self_control &= ~HCB1;
  204         cs_writereg(sc, PP_SelfCTL, self_control);
  205         DELAY(500000);  /* Bad! */
  206 }
  207 
  208 
  209 static int
  210 cs_duplex_auto(struct cs_softc *sc)
  211 {
  212         int i, error=0;
  213 
  214         cs_writereg(sc, PP_AutoNegCTL,
  215             RE_NEG_NOW | ALLOW_FDX | AUTO_NEG_ENABLE);
  216         for (i=0; cs_readreg(sc, PP_AutoNegST) & AUTO_NEG_BUSY; i++) {
  217                 if (i > 4000) {
  218                         device_printf(sc->dev,
  219                             "full/half duplex auto negotiation timeout\n");
  220                         error = ETIMEDOUT;
  221                         break;
  222                 }
  223                 DELAY(1000);
  224         }
  225         return (error);
  226 }
  227 
  228 static int
  229 enable_tp(struct cs_softc *sc)
  230 {
  231 
  232         cs_writereg(sc, PP_LineCTL, sc->line_ctl & ~AUI_ONLY);
  233         control_dc_dc(sc, 0);
  234         return (0);
  235 }
  236 
  237 static int
  238 enable_aui(struct cs_softc *sc)
  239 {
  240 
  241         cs_writereg(sc, PP_LineCTL,
  242             (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
  243         control_dc_dc(sc, 0);
  244         return (0);
  245 }
  246 
  247 static int
  248 enable_bnc(struct cs_softc *sc)
  249 {
  250 
  251         cs_writereg(sc, PP_LineCTL,
  252             (sc->line_ctl & ~AUTO_AUI_10BASET) | AUI_ONLY);
  253         control_dc_dc(sc, 1);
  254         return (0);
  255 }
  256 
  257 int
  258 cs_cs89x0_probe(device_t dev)
  259 {
  260         int i;
  261         int error;
  262         u_long irq, junk;
  263         struct cs_softc *sc = device_get_softc(dev);
  264         unsigned rev_type = 0;
  265         uint16_t id;
  266         char chip_revision;
  267         uint16_t eeprom_buff[CHKSUM_LEN];
  268         int chip_type, pp_isaint, pp_isadma;
  269 
  270         sc->dev = dev;
  271         error = cs_alloc_port(dev, 0, CS_89x0_IO_PORTS);
  272         if (error)
  273                 return (error);
  274 
  275         sc->nic_addr = rman_get_start(sc->port_res);
  276 
  277         if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG) {
  278                 /* Chip not detected. Let's try to reset it */
  279                 if (bootverbose)
  280                         device_printf(dev, "trying to reset the chip.\n");
  281                 cs_outw(sc, ADD_PORT, PP_SelfCTL);
  282                 i = cs_inw(sc, DATA_PORT);
  283                 cs_outw(sc, ADD_PORT, PP_SelfCTL);
  284                 cs_outw(sc, DATA_PORT, i | POWER_ON_RESET);
  285                 if ((cs_inw(sc, ADD_PORT) & ADD_MASK) != ADD_SIG)
  286                         return (ENXIO);
  287         }
  288 
  289         for (i = 0; i < 10000; i++) {
  290                 id = cs_readreg(sc, PP_ChipID);
  291                 if (id == CHIP_EISA_ID_SIG)
  292                         break;
  293         }
  294         if (i == 10000)
  295                 return (ENXIO);
  296 
  297         rev_type = cs_readreg(sc, PRODUCT_ID_ADD);
  298         chip_type = rev_type & ~REVISON_BITS;
  299         chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';
  300 
  301         sc->chip_type = chip_type;
  302 
  303         if (chip_type == CS8900) {
  304                 pp_isaint = PP_CS8900_ISAINT;
  305                 pp_isadma = PP_CS8900_ISADMA;
  306                 sc->send_cmd = TX_CS8900_AFTER_ALL;
  307         } else {
  308                 pp_isaint = PP_CS8920_ISAINT;
  309                 pp_isadma = PP_CS8920_ISADMA;
  310                 sc->send_cmd = TX_CS8920_AFTER_ALL;
  311         }
  312 
  313         /*
  314          * Clear some fields so that fail of EEPROM will left them clean
  315          */
  316         sc->auto_neg_cnf = 0;
  317         sc->adapter_cnf  = 0;
  318         sc->isa_config   = 0;
  319 
  320         /*
  321          * If no interrupt specified, use what the board tells us.
  322          */
  323         error = bus_get_resource(dev, SYS_RES_IRQ, 0, &irq, &junk);
  324 
  325         /*
  326          * Get data from EEPROM
  327          */
  328         if((cs_readreg(sc, PP_SelfST) & EEPROM_PRESENT) == 0) {
  329                 device_printf(dev, "No EEPROM, assuming defaults.\n");
  330         } else if (get_eeprom_data(sc,START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
  331                 device_printf(dev, "EEPROM read failed, assuming defaults.\n");
  332         } else if (get_eeprom_cksum(START_EEPROM_DATA,CHKSUM_LEN, eeprom_buff)<0) {
  333                 device_printf(dev, "EEPROM cheksum bad, assuming defaults.\n");
  334         } else {
  335                 sc->auto_neg_cnf = eeprom_buff[AUTO_NEG_CNF_OFFSET];
  336                 sc->adapter_cnf = eeprom_buff[ADAPTER_CNF_OFFSET];
  337                 sc->isa_config = eeprom_buff[ISA_CNF_OFFSET];
  338                 for (i=0; i<ETHER_ADDR_LEN/2; i++) {
  339                         sc->enaddr[i*2] = eeprom_buff[i];
  340                         sc->enaddr[i*2+1] = eeprom_buff[i] >> 8;
  341                 }
  342                 /*
  343                  * If no interrupt specified, use what the
  344                  * board tells us.
  345                  */
  346                 if (error) {
  347                         irq = sc->isa_config & INT_NO_MASK;
  348                         error = 0;
  349                         if (chip_type == CS8900) {
  350                                 irq = cs8900_eeint2irq[irq];
  351                         } else {
  352                                 if (irq > CS8920_NO_INTS)
  353                                         irq = 255;
  354                         }
  355                         if (irq == 255) {
  356                                 device_printf(dev, "invalid irq in EEPROM.\n");
  357                                 error = EINVAL;
  358                         }
  359                         if (!error)
  360                                 bus_set_resource(dev, SYS_RES_IRQ, 0,
  361                                     irq, 1);
  362                 }
  363         }
  364 
  365         if (!error && !(sc->flags & CS_NO_IRQ)) {
  366                 if (chip_type == CS8900) {
  367                         if (irq >= 0 || irq < 16)
  368                                 irq = cs8900_irq2eeint[irq];
  369                         else
  370                                 irq = 255;
  371                 } else {
  372                         if (irq > CS8920_NO_INTS)
  373                                 irq = 255;
  374                 }
  375                 if (irq == 255)
  376                         error = EINVAL;
  377         }
  378 
  379         if (error) {
  380                 device_printf(dev, "Unknown or invalid irq\n");
  381                 return (error);
  382         }
  383 
  384         if (!(sc->flags & CS_NO_IRQ))
  385                 cs_writereg(sc, pp_isaint, irq);
  386 
  387         /*
  388          * Temporary disabled
  389          *
  390         if (drq>0)
  391                 cs_writereg(sc, pp_isadma, drq);
  392         else {
  393                 device_printf(dev, "incorrect drq\n",);
  394                 return (0);
  395         }
  396         */
  397 
  398         if (bootverbose)
  399                  device_printf(dev, "CS89%c0%s rev %c media%s%s%s\n",
  400                         chip_type == CS8900 ? '' : '2',
  401                         chip_type == CS8920M ? "M" : "",
  402                         chip_revision,
  403                         (sc->adapter_cnf & A_CNF_10B_T) ? " TP"  : "",
  404                         (sc->adapter_cnf & A_CNF_AUI)   ? " AUI" : "",
  405                         (sc->adapter_cnf & A_CNF_10B_2) ? " BNC" : "");
  406 
  407         if ((sc->adapter_cnf & A_CNF_EXTND_10B_2) &&
  408             (sc->adapter_cnf & A_CNF_LOW_RX_SQUELCH))
  409                 sc->line_ctl = LOW_RX_SQUELCH;
  410         else
  411                 sc->line_ctl = 0;
  412 
  413         return (0);
  414 }
  415 
  416 /*
  417  * Allocate a port resource with the given resource id.
  418  */
  419 int
  420 cs_alloc_port(device_t dev, int rid, int size)
  421 {
  422         struct cs_softc *sc = device_get_softc(dev);
  423         struct resource *res;
  424 
  425         res = bus_alloc_resource(dev, SYS_RES_IOPORT, &rid,
  426             0ul, ~0ul, size, RF_ACTIVE);
  427         if (res == NULL)
  428                 return (ENOENT);
  429         sc->port_rid = rid;
  430         sc->port_res = res;
  431         return (0);
  432 }
  433 
  434 /*
  435  * Allocate an irq resource with the given resource id.
  436  */
  437 int
  438 cs_alloc_irq(device_t dev, int rid)
  439 {
  440         struct cs_softc *sc = device_get_softc(dev);
  441         struct resource *res;
  442 
  443         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, RF_ACTIVE);
  444         if (res == NULL)
  445                 return (ENOENT);
  446         sc->irq_rid = rid;
  447         sc->irq_res = res;
  448         return (0);
  449 }
  450 
  451 /*
  452  * Release all resources
  453  */
  454 void
  455 cs_release_resources(device_t dev)
  456 {
  457         struct cs_softc *sc = device_get_softc(dev);
  458 
  459         if (sc->port_res) {
  460                 bus_release_resource(dev, SYS_RES_IOPORT,
  461                     sc->port_rid, sc->port_res);
  462                 sc->port_res = 0;
  463         }
  464         if (sc->irq_res) {
  465                 bus_release_resource(dev, SYS_RES_IRQ,
  466                     sc->irq_rid, sc->irq_res);
  467                 sc->irq_res = 0;
  468         }
  469 }
  470 
  471 /*
  472  * Install the interface into kernel networking data structures
  473  */
  474 int
  475 cs_attach(device_t dev)
  476 {
  477         int error, media=0;
  478         struct cs_softc *sc = device_get_softc(dev);
  479         struct ifnet *ifp;
  480 
  481         sc->dev = dev;
  482         
  483         ifp = sc->ifp = if_alloc(IFT_ETHER);
  484         if (ifp == NULL) {
  485                 device_printf(dev, "can not if_alloc()\n");
  486                 cs_release_resources(dev);
  487                 return (ENOMEM);
  488         }
  489 
  490         mtx_init(&sc->lock, device_get_nameunit(dev), MTX_NETWORK_LOCK,
  491             MTX_DEF);
  492         callout_init_mtx(&sc->timer, &sc->lock, 0);
  493 
  494         CS_LOCK(sc);
  495         cs_stop(sc);
  496         CS_UNLOCK(sc);
  497 
  498         ifp->if_softc=sc;
  499         if_initname(ifp, device_get_name(dev), device_get_unit(dev));
  500         ifp->if_start=cs_start;
  501         ifp->if_ioctl=cs_ioctl;
  502         ifp->if_init=cs_init;
  503         IFQ_SET_MAXLEN(&ifp->if_snd, ifqmaxlen);
  504 
  505         ifp->if_flags=(IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST);
  506 
  507         /*
  508          * this code still in progress (DMA support)
  509          *
  510 
  511         sc->recv_ring=malloc(CS_DMA_BUFFER_SIZE<<1, M_DEVBUF, M_NOWAIT);
  512         if (sc->recv_ring == NULL) {
  513                 log(LOG_ERR,
  514                 "%s: Couldn't allocate memory for NIC\n", ifp->if_xname);
  515                 return(0);
  516         }
  517         if ((sc->recv_ring-(sc->recv_ring & 0x1FFFF))
  518             < (128*1024-CS_DMA_BUFFER_SIZE))
  519             sc->recv_ring+=16*1024;
  520 
  521         */
  522 
  523         sc->buffer=malloc(ETHER_MAX_LEN-ETHER_CRC_LEN,M_DEVBUF,M_NOWAIT);
  524         if (sc->buffer == NULL) {
  525                 device_printf(sc->dev, "Couldn't allocate memory for NIC\n");
  526                 if_free(ifp);
  527                 mtx_destroy(&sc->lock);
  528                 cs_release_resources(dev);
  529                 return(ENOMEM);
  530         }
  531 
  532         /*
  533          * Initialize the media structures.
  534          */
  535         ifmedia_init(&sc->media, 0, cs_mediachange, cs_mediastatus);
  536 
  537         if (sc->adapter_cnf & A_CNF_10B_T) {
  538                 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
  539                 if (sc->chip_type != CS8900) {
  540                         ifmedia_add(&sc->media,
  541                                 IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
  542                         ifmedia_add(&sc->media,
  543                                 IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
  544                 }
  545         } 
  546 
  547         if (sc->adapter_cnf & A_CNF_10B_2)
  548                 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_2, 0, NULL);
  549 
  550         if (sc->adapter_cnf & A_CNF_AUI)
  551                 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_5, 0, NULL);
  552 
  553         if (sc->adapter_cnf & A_CNF_MEDIA)
  554                 ifmedia_add(&sc->media, IFM_ETHER|IFM_AUTO, 0, NULL);
  555 
  556         /* Set default media from EEPROM */
  557         switch (sc->adapter_cnf & A_CNF_MEDIA_TYPE) {
  558         case A_CNF_MEDIA_AUTO:  media = IFM_ETHER|IFM_AUTO; break;
  559         case A_CNF_MEDIA_10B_T: media = IFM_ETHER|IFM_10_T; break;
  560         case A_CNF_MEDIA_10B_2: media = IFM_ETHER|IFM_10_2; break;
  561         case A_CNF_MEDIA_AUI:   media = IFM_ETHER|IFM_10_5; break;
  562         default:
  563                 device_printf(sc->dev, "no media, assuming 10baseT\n");
  564                 sc->adapter_cnf |= A_CNF_10B_T;
  565                 ifmedia_add(&sc->media, IFM_ETHER|IFM_10_T, 0, NULL);
  566                 if (sc->chip_type != CS8900) {
  567                         ifmedia_add(&sc->media,
  568                             IFM_ETHER|IFM_10_T|IFM_FDX, 0, NULL);
  569                         ifmedia_add(&sc->media,
  570                             IFM_ETHER|IFM_10_T|IFM_HDX, 0, NULL);
  571                 }
  572                 media = IFM_ETHER | IFM_10_T;
  573                 break;
  574         }
  575         ifmedia_set(&sc->media, media);
  576         cs_mediaset(sc, media);
  577 
  578         ether_ifattach(ifp, sc->enaddr);
  579 
  580         error = bus_setup_intr(dev, sc->irq_res, INTR_TYPE_NET | INTR_MPSAFE,
  581             NULL, csintr, sc, &sc->irq_handle);
  582         if (error) {
  583                 ether_ifdetach(ifp);
  584                 free(sc->buffer, M_DEVBUF);
  585                 if_free(ifp);
  586                 mtx_destroy(&sc->lock);
  587                 cs_release_resources(dev);
  588                 return (error);
  589         }
  590 
  591         return (0);
  592 }
  593 
  594 int
  595 cs_detach(device_t dev)
  596 {
  597         struct cs_softc *sc;
  598         struct ifnet *ifp;
  599 
  600         sc = device_get_softc(dev);
  601         ifp = sc->ifp;
  602 
  603         CS_LOCK(sc);
  604         cs_stop(sc);
  605         CS_UNLOCK(sc);
  606         callout_drain(&sc->timer);
  607         ether_ifdetach(ifp);
  608         bus_teardown_intr(dev, sc->irq_res, sc->irq_handle);
  609         cs_release_resources(dev);
  610         free(sc->buffer, M_DEVBUF);
  611         if_free(ifp);
  612         mtx_destroy(&sc->lock);
  613         return (0);
  614 }
  615 
  616 /*
  617  * Initialize the board
  618  */
  619 static void
  620 cs_init(void *xsc)
  621 {
  622         struct cs_softc *sc=(struct cs_softc *)xsc;
  623 
  624         CS_LOCK(sc);
  625         cs_init_locked(sc);
  626         CS_UNLOCK(sc);
  627 }
  628 
  629 static void
  630 cs_init_locked(struct cs_softc *sc)
  631 {
  632         struct ifnet *ifp = sc->ifp;
  633         int i, rx_cfg;
  634 
  635         /*
  636          * reset watchdog timer
  637          */
  638         sc->tx_timeout = 0;
  639         sc->buf_len = 0;
  640         
  641         /*
  642          * Hardware initialization of cs
  643          */
  644 
  645         /* Enable receiver and transmitter */
  646         cs_writereg(sc, PP_LineCTL,
  647                 cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON);
  648 
  649         /* Configure the receiver mode */
  650         cs_setmode(sc);
  651 
  652         /*
  653          * This defines what type of frames will cause interrupts
  654          * Bad frames should generate interrupts so that the driver
  655          * could track statistics of discarded packets
  656          */
  657         rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL | RX_RUNT_ENBL |
  658                  RX_EXTRA_DATA_ENBL;
  659         if (sc->isa_config & STREAM_TRANSFER)
  660                 rx_cfg |= RX_STREAM_ENBL;
  661         cs_writereg(sc, PP_RxCFG, rx_cfg);
  662         cs_writereg(sc, PP_TxCFG, TX_LOST_CRS_ENBL |
  663                     TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL |
  664                     TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL);
  665         cs_writereg(sc, PP_BufCFG, READY_FOR_TX_ENBL |
  666                     RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL |
  667                     TX_UNDERRUN_ENBL /*| RX_DMA_ENBL*/);
  668 
  669         /* Write MAC address into IA filter */
  670         for (i=0; i<ETHER_ADDR_LEN/2; i++)
  671                 cs_writereg(sc, PP_IA + i * 2,
  672                     sc->enaddr[i * 2] |
  673                     (sc->enaddr[i * 2 + 1] << 8) );
  674 
  675         /*
  676          * Now enable everything
  677          */
  678 /*
  679 #ifdef  CS_USE_64K_DMA
  680         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ | RX_DMA_SIZE_64K);
  681 #else
  682         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ);
  683 #endif
  684 */
  685         cs_writereg(sc, PP_BusCTL, ENABLE_IRQ);
  686         
  687         /*
  688          * Set running and clear output active flags
  689          */
  690         sc->ifp->if_drv_flags |= IFF_DRV_RUNNING;
  691         sc->ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  692         callout_reset(&sc->timer, hz, cs_watchdog, sc);
  693 
  694         /*
  695          * Start sending process
  696          */
  697         cs_start_locked(ifp);
  698 }
  699 
  700 /*
  701  * Get the packet from the board and send it to the upper layer.
  702  */
  703 static int
  704 cs_get_packet(struct cs_softc *sc)
  705 {
  706         struct ifnet *ifp = sc->ifp;
  707         int iobase = sc->nic_addr, status, length;
  708         struct ether_header *eh;
  709         struct mbuf *m;
  710 
  711 #ifdef CS_DEBUG
  712         int i;
  713 #endif
  714 
  715         status = cs_inw(sc, RX_FRAME_PORT);
  716         length = cs_inw(sc, RX_FRAME_PORT);
  717 
  718 #ifdef CS_DEBUG
  719         device_printf(sc->dev, "rcvd: stat %x, len %d\n",
  720                 status, length);
  721 #endif
  722 
  723         if (!(status & RX_OK)) {
  724 #ifdef CS_DEBUG
  725                 device_printf(sc->dev, "bad pkt stat %x\n", status);
  726 #endif
  727                 ifp->if_ierrors++;
  728                 return (-1);
  729         }
  730 
  731         MGETHDR(m, M_DONTWAIT, MT_DATA);
  732         if (m==NULL)
  733                 return (-1);
  734 
  735         if (length > MHLEN) {
  736                 MCLGET(m, M_DONTWAIT);
  737                 if (!(m->m_flags & M_EXT)) {
  738                         m_freem(m);
  739                         return (-1);
  740                 }
  741         }
  742 
  743         /* Initialize packet's header info */
  744         m->m_pkthdr.rcvif = ifp;
  745         m->m_pkthdr.len = length;
  746         m->m_len = length;
  747 
  748         /* Get the data */
  749         insw(iobase + RX_FRAME_PORT, m->m_data, (length+1)>>1);
  750 
  751         eh = mtod(m, struct ether_header *);
  752 
  753 #ifdef CS_DEBUG
  754         for (i=0;i<length;i++)
  755              printf(" %02x",(unsigned char)*((char *)(m->m_data+i)));
  756         printf( "\n" );
  757 #endif
  758 
  759         if (status & (RX_IA | RX_BROADCAST) || 
  760             (ifp->if_flags & IFF_MULTICAST && status & RX_HASHED)) {
  761                 /* Feed the packet to the upper layer */
  762                 (*ifp->if_input)(ifp, m);
  763                 ifp->if_ipackets++;
  764                 if (length == ETHER_MAX_LEN-ETHER_CRC_LEN)
  765                         DELAY(cs_recv_delay);
  766         } else {
  767                 m_freem(m);
  768         }
  769 
  770         return (0);
  771 }
  772 
  773 /*
  774  * Handle interrupts
  775  */
  776 void
  777 csintr(void *arg)
  778 {
  779         struct cs_softc *sc = (struct cs_softc*) arg;
  780         struct ifnet *ifp = sc->ifp;
  781         int status;
  782 
  783 #ifdef CS_DEBUG
  784         device_printf(sc->dev, "Interrupt.\n");
  785 #endif
  786 
  787         CS_LOCK(sc);
  788         while ((status=cs_inw(sc, ISQ_PORT))) {
  789 
  790 #ifdef CS_DEBUG
  791                 device_printf(sc->dev, "from ISQ: %04x\n", status);
  792 #endif
  793 
  794                 switch (status & ISQ_EVENT_MASK) {
  795                 case ISQ_RECEIVER_EVENT:
  796                         cs_get_packet(sc);
  797                         break;
  798 
  799                 case ISQ_TRANSMITTER_EVENT:
  800                         if (status & TX_OK)
  801                                 ifp->if_opackets++;
  802                         else
  803                                 ifp->if_oerrors++;
  804                         ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  805                         sc->tx_timeout = 0;
  806                         break;
  807 
  808                 case ISQ_BUFFER_EVENT:
  809                         if (status & READY_FOR_TX) {
  810                                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  811                                 sc->tx_timeout = 0;
  812                         }
  813 
  814                         if (status & TX_UNDERRUN) {
  815                                 ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
  816                                 sc->tx_timeout = 0;
  817                                 ifp->if_oerrors++;
  818                         }
  819                         break;
  820 
  821                 case ISQ_RX_MISS_EVENT:
  822                         ifp->if_ierrors+=(status>>6);
  823                         break;
  824 
  825                 case ISQ_TX_COL_EVENT:
  826                         ifp->if_collisions+=(status>>6);
  827                         break;
  828                 }
  829         }
  830 
  831         if (!(ifp->if_drv_flags & IFF_DRV_OACTIVE)) {
  832                 cs_start_locked(ifp);
  833         }
  834         CS_UNLOCK(sc);
  835 }
  836 
  837 /*
  838  * Save the data in buffer
  839  */
  840 
  841 static void
  842 cs_write_mbufs( struct cs_softc *sc, struct mbuf *m )
  843 {
  844         int len;
  845         struct mbuf *mp;
  846         unsigned char *data, *buf;
  847 
  848         for (mp=m, buf=sc->buffer, sc->buf_len=0; mp != NULL; mp=mp->m_next) {
  849                 len = mp->m_len;
  850 
  851                 /*
  852                  * Ignore empty parts
  853                  */
  854                 if (!len)
  855                 continue;
  856 
  857                 /*
  858                  * Find actual data address
  859                  */
  860                 data = mtod(mp, caddr_t);
  861 
  862                 bcopy((caddr_t) data, (caddr_t) buf, len);
  863                 buf += len;
  864                 sc->buf_len += len;
  865         }
  866 }
  867 
  868 
  869 static void
  870 cs_xmit_buf( struct cs_softc *sc )
  871 {
  872         outsw(sc->nic_addr+TX_FRAME_PORT, sc->buffer, (sc->buf_len+1)>>1);
  873         sc->buf_len = 0;
  874 }
  875 
  876 static void
  877 cs_start(struct ifnet *ifp)
  878 {
  879         struct cs_softc *sc = ifp->if_softc;
  880 
  881         CS_LOCK(sc);
  882         cs_start_locked(ifp);
  883         CS_UNLOCK(sc);
  884 }
  885 
  886 static void
  887 cs_start_locked(struct ifnet *ifp)
  888 {
  889         int length;
  890         struct mbuf *m, *mp;
  891         struct cs_softc *sc = ifp->if_softc;
  892 
  893         for (;;) {
  894                 if (sc->buf_len)
  895                         length = sc->buf_len;
  896                 else {
  897                         IF_DEQUEUE( &ifp->if_snd, m );
  898 
  899                         if (m==NULL) {
  900                                 return;
  901                         }
  902 
  903                         for (length=0, mp=m; mp != NULL; mp=mp->m_next)
  904                                 length += mp->m_len;
  905 
  906                         /* Skip zero-length packets */
  907                         if (length == 0) {
  908                                 m_freem(m);
  909                                 continue;
  910                         }
  911 
  912                         cs_write_mbufs(sc, m);
  913 
  914                         BPF_MTAP(ifp, m);
  915 
  916                         m_freem(m);
  917                 }
  918 
  919                 /*
  920                  * Issue a SEND command
  921                  */
  922                 cs_outw(sc, TX_CMD_PORT, sc->send_cmd);
  923                 cs_outw(sc, TX_LEN_PORT, length );
  924 
  925                 /*
  926                  * If there's no free space in the buffer then leave
  927                  * this packet for the next time: indicate output active
  928                  * and return.
  929                  */
  930                 if (!(cs_readreg(sc, PP_BusST) & READY_FOR_TX_NOW)) {
  931                         sc->tx_timeout = sc->buf_len;
  932                         ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  933                         return;
  934                 }
  935 
  936                 cs_xmit_buf(sc);
  937 
  938                 /*
  939                  * Set the watchdog timer in case we never hear
  940                  * from board again. (I don't know about correct
  941                  * value for this timeout)
  942                  */
  943                 sc->tx_timeout = length;
  944 
  945                 ifp->if_drv_flags |= IFF_DRV_OACTIVE;
  946                 return;
  947         }
  948 }
  949 
  950 /*
  951  * Stop everything on the interface
  952  */
  953 static void
  954 cs_stop(struct cs_softc *sc)
  955 {
  956 
  957         CS_ASSERT_LOCKED(sc);
  958         cs_writereg(sc, PP_RxCFG, 0);
  959         cs_writereg(sc, PP_TxCFG, 0);
  960         cs_writereg(sc, PP_BufCFG, 0);
  961         cs_writereg(sc, PP_BusCTL, 0);
  962 
  963         sc->ifp->if_drv_flags &= ~(IFF_DRV_RUNNING | IFF_DRV_OACTIVE);
  964         sc->tx_timeout = 0;
  965         callout_stop(&sc->timer);
  966 }
  967 
  968 /*
  969  * Reset the interface
  970  */
  971 static void
  972 cs_reset(struct cs_softc *sc)
  973 {
  974 
  975         CS_ASSERT_LOCKED(sc);
  976         cs_stop(sc);
  977         cs_init_locked(sc);
  978 }
  979 
  980 static uint16_t
  981 cs_hash_index(struct sockaddr_dl *addr)
  982 {
  983         uint32_t crc;
  984         uint16_t idx;
  985         caddr_t lla;
  986 
  987         lla = LLADDR(addr);
  988         crc = ether_crc32_le(lla, ETHER_ADDR_LEN);
  989         idx = crc >> 26;
  990 
  991         return (idx);
  992 }
  993 
  994 static void
  995 cs_setmode(struct cs_softc *sc)
  996 {
  997         int rx_ctl;
  998         uint16_t af[4];
  999         uint16_t port, mask, index;
 1000         struct ifnet *ifp = sc->ifp;
 1001         struct ifmultiaddr *ifma;
 1002 
 1003         /* Stop the receiver while changing filters */
 1004         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) & ~SERIAL_RX_ON);
 1005 
 1006         if (ifp->if_flags & IFF_PROMISC) {
 1007                 /* Turn on promiscuous mode. */
 1008                 rx_ctl = RX_OK_ACCEPT | RX_PROM_ACCEPT;
 1009         } else if (ifp->if_flags & IFF_MULTICAST) {
 1010                 /* Allow receiving frames with multicast addresses */
 1011                 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
 1012                          RX_OK_ACCEPT | RX_MULTCAST_ACCEPT;
 1013 
 1014                 /* Start with an empty filter */
 1015                 af[0] = af[1] = af[2] = af[3] = 0x0000;
 1016 
 1017                 if (ifp->if_flags & IFF_ALLMULTI) {
 1018                         /* Accept all multicast frames */
 1019                         af[0] = af[1] = af[2] = af[3] = 0xffff;
 1020                 } else {
 1021                         /* 
 1022                          * Set up the filter to only accept multicast
 1023                          * frames we're interested in.
 1024                          */
 1025                         if_maddr_rlock(ifp);
 1026                         TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) {
 1027                                 struct sockaddr_dl *dl =
 1028                                     (struct sockaddr_dl *)ifma->ifma_addr;
 1029 
 1030                                 index = cs_hash_index(dl);
 1031                                 port = (u_int16_t) (index >> 4);
 1032                                 mask = (u_int16_t) (1 << (index & 0xf));
 1033                                 af[port] |= mask;
 1034                         }
 1035                         if_maddr_runlock(ifp);
 1036                 }
 1037 
 1038                 cs_writereg(sc, PP_LAF + 0, af[0]);
 1039                 cs_writereg(sc, PP_LAF + 2, af[1]);
 1040                 cs_writereg(sc, PP_LAF + 4, af[2]);
 1041                 cs_writereg(sc, PP_LAF + 6, af[3]);
 1042         } else {
 1043                 /*
 1044                  * Receive only good frames addressed for us and
 1045                  * good broadcasts.
 1046                  */
 1047                 rx_ctl = RX_IA_ACCEPT | RX_BROADCAST_ACCEPT |
 1048                          RX_OK_ACCEPT;
 1049         }
 1050 
 1051         /* Set up the filter */
 1052         cs_writereg(sc, PP_RxCTL, RX_DEF_ACCEPT | rx_ctl);
 1053 
 1054         /* Turn on receiver */
 1055         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) | SERIAL_RX_ON);
 1056 }
 1057 
 1058 static int
 1059 cs_ioctl(register struct ifnet *ifp, u_long command, caddr_t data)
 1060 {
 1061         struct cs_softc *sc=ifp->if_softc;
 1062         struct ifreq *ifr = (struct ifreq *)data;
 1063         int error=0;
 1064 
 1065 #ifdef CS_DEBUG
 1066         if_printf(ifp, "%s command=%lx\n", __func__, command);
 1067 #endif
 1068 
 1069         switch (command) {
 1070         case SIOCSIFFLAGS:
 1071                 /*
 1072                  * Switch interface state between "running" and
 1073                  * "stopped", reflecting the UP flag.
 1074                  */
 1075                 CS_LOCK(sc);
 1076                 if (sc->ifp->if_flags & IFF_UP) {
 1077                         if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)==0) {
 1078                                 cs_init_locked(sc);
 1079                         }
 1080                 } else {
 1081                         if ((sc->ifp->if_drv_flags & IFF_DRV_RUNNING)!=0) {
 1082                                 cs_stop(sc);
 1083                         }
 1084                 }               
 1085                 /*
 1086                  * Promiscuous and/or multicast flags may have changed,
 1087                  * so reprogram the multicast filter and/or receive mode.
 1088                  *
 1089                  * See note about multicasts in cs_setmode
 1090                  */
 1091                 cs_setmode(sc);
 1092                 CS_UNLOCK(sc);
 1093                 break;
 1094 
 1095         case SIOCADDMULTI:
 1096         case SIOCDELMULTI:
 1097             /*
 1098              * Multicast list has changed; set the hardware filter
 1099              * accordingly.
 1100              *
 1101              * See note about multicasts in cs_setmode
 1102              */
 1103             CS_LOCK(sc);
 1104             cs_setmode(sc);
 1105             CS_UNLOCK(sc);
 1106             error = 0;
 1107             break;
 1108 
 1109         case SIOCSIFMEDIA:
 1110         case SIOCGIFMEDIA:
 1111                 error = ifmedia_ioctl(ifp, ifr, &sc->media, command);
 1112                 break;
 1113 
 1114         default:
 1115                 error = ether_ioctl(ifp, command, data);
 1116                 break;
 1117         }
 1118 
 1119         return (error);
 1120 }
 1121 
 1122 /*
 1123  * Device timeout/watchdog routine. Entered if the device neglects to
 1124  * generate an interrupt after a transmit has been started on it.
 1125  */
 1126 static void
 1127 cs_watchdog(void *arg)
 1128 {
 1129         struct cs_softc *sc = arg;
 1130         struct ifnet *ifp = sc->ifp;
 1131 
 1132         CS_ASSERT_LOCKED(sc);
 1133         if (sc->tx_timeout && --sc->tx_timeout == 0) {
 1134                 ifp->if_oerrors++;
 1135                 log(LOG_ERR, "%s: device timeout\n", ifp->if_xname);
 1136 
 1137                 /* Reset the interface */
 1138                 if (ifp->if_flags & IFF_UP)
 1139                         cs_reset(sc);
 1140                 else
 1141                         cs_stop(sc);
 1142         }
 1143         callout_reset(&sc->timer, hz, cs_watchdog, sc);
 1144 }
 1145 
 1146 static int
 1147 cs_mediachange(struct ifnet *ifp)
 1148 {
 1149         struct cs_softc *sc = ifp->if_softc;
 1150         struct ifmedia *ifm = &sc->media;
 1151         int error;
 1152 
 1153         if (IFM_TYPE(ifm->ifm_media) != IFM_ETHER)
 1154                 return (EINVAL);
 1155 
 1156         CS_LOCK(sc);
 1157         error = cs_mediaset(sc, ifm->ifm_media);
 1158         CS_UNLOCK(sc);
 1159         return (error);
 1160 }
 1161 
 1162 static void
 1163 cs_mediastatus(struct ifnet *ifp, struct ifmediareq *ifmr)
 1164 {
 1165         int line_status;
 1166         struct cs_softc *sc = ifp->if_softc;
 1167 
 1168         CS_LOCK(sc);
 1169         ifmr->ifm_active = IFM_ETHER;
 1170         line_status = cs_readreg(sc, PP_LineST);
 1171         if (line_status & TENBASET_ON) {
 1172                 ifmr->ifm_active |= IFM_10_T;
 1173                 if (sc->chip_type != CS8900) {
 1174                         if (cs_readreg(sc, PP_AutoNegST) & FDX_ACTIVE)
 1175                                 ifmr->ifm_active |= IFM_FDX;
 1176                         if (cs_readreg(sc, PP_AutoNegST) & HDX_ACTIVE)
 1177                                 ifmr->ifm_active |= IFM_HDX;
 1178                 }
 1179                 ifmr->ifm_status = IFM_AVALID;
 1180                 if (line_status & LINK_OK)
 1181                         ifmr->ifm_status |= IFM_ACTIVE;
 1182         } else {
 1183                 if (line_status & AUI_ON) {
 1184                         cs_writereg(sc, PP_SelfCTL, cs_readreg(sc, PP_SelfCTL) |
 1185                             HCB1_ENBL);
 1186                         if (((sc->adapter_cnf & A_CNF_DC_DC_POLARITY)!=0)^
 1187                             (cs_readreg(sc, PP_SelfCTL) & HCB1))
 1188                                 ifmr->ifm_active |= IFM_10_2;
 1189                         else
 1190                                 ifmr->ifm_active |= IFM_10_5;
 1191                 }
 1192         }
 1193         CS_UNLOCK(sc);
 1194 }
 1195 
 1196 static int
 1197 cs_mediaset(struct cs_softc *sc, int media)
 1198 {
 1199         int error = 0;
 1200 
 1201         /* Stop the receiver & transmitter */
 1202         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) &
 1203             ~(SERIAL_RX_ON | SERIAL_TX_ON));
 1204 
 1205 #ifdef CS_DEBUG
 1206         device_printf(sc->dev, "%s media=%x\n", __func__, media);
 1207 #endif
 1208 
 1209         switch (IFM_SUBTYPE(media)) {
 1210         default:
 1211         case IFM_AUTO:
 1212                 /*
 1213                  * This chip makes it a little hard to support this, so treat
 1214                  * it as IFM_10_T, auto duplex.
 1215                  */
 1216                 enable_tp(sc);
 1217                 cs_duplex_auto(sc);
 1218                 break;
 1219         case IFM_10_T:
 1220                 enable_tp(sc);
 1221                 if (media & IFM_FDX)
 1222                         cs_duplex_full(sc);
 1223                 else if (media & IFM_HDX)
 1224                         cs_duplex_half(sc);
 1225                 else
 1226                         error = cs_duplex_auto(sc);
 1227                 break;
 1228         case IFM_10_2:
 1229                 enable_bnc(sc);
 1230                 break;
 1231         case IFM_10_5:
 1232                 enable_aui(sc);
 1233                 break;
 1234         }
 1235 
 1236         /*
 1237          * Turn the transmitter & receiver back on
 1238          */
 1239         cs_writereg(sc, PP_LineCTL, cs_readreg(sc, PP_LineCTL) |
 1240             SERIAL_RX_ON | SERIAL_TX_ON); 
 1241 
 1242         return (error);
 1243 }

Cache object: b5c0bb4ef11e3d3a88af3a46a6c5f33a


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