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

Cache object: 54f6385a863bd0cc2955ffc26d6a6172


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