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

Cache object: edc0fb117ee1dd0a6948f1b1af0f9e8f


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