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

Cache object: a74c66f18a21053929519909b68e5b77


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