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

Cache object: eaf7ffd3372316f8a7593361705ac97d


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