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/pc/ether589.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  * 3C589 and 3C562.
    3  * To do:
    4  *      check xcvr10Base2 still works (is GlobalReset necessary?).
    5  */
    6 #include "u.h"
    7 #include "../port/lib.h"
    8 #include "mem.h"
    9 #include "dat.h"
   10 #include "fns.h"
   11 #include "io.h"
   12 #include "../port/error.h"
   13 #include "../port/netif.h"
   14 
   15 #include "etherif.h"
   16 
   17 enum {                                          /* all windows */
   18         CommandR                = 0x000E,
   19         IntStatusR              = 0x000E,
   20 };
   21 
   22 enum {                                          /* Commands */
   23         GlobalReset             = 0x0000,
   24         SelectRegisterWindow    = 0x0001,
   25         RxReset                 = 0x0005,
   26         TxReset                 = 0x000B,
   27         AcknowledgeInterrupt    = 0x000D,
   28 };
   29 
   30 enum {                                          /* IntStatus bits */
   31         commandInProgress       = 0x1000,
   32 };
   33 
   34 #define COMMAND(port, cmd, a)   outs((port)+CommandR, ((cmd)<<11)|(a))
   35 #define STATUS(port)            ins((port)+IntStatusR)
   36 
   37 enum {                                          /* Window 0 - setup */
   38         Wsetup                  = 0x0000,
   39                                                 /* registers */
   40         ManufacturerID          = 0x0000,       /* 3C5[08]*, 3C59[27] */
   41         ProductID               = 0x0002,       /* 3C5[08]*, 3C59[27] */
   42         ConfigControl           = 0x0004,       /* 3C5[08]*, 3C59[27] */
   43         AddressConfig           = 0x0006,       /* 3C5[08]*, 3C59[27] */
   44         ResourceConfig          = 0x0008,       /* 3C5[08]*, 3C59[27] */
   45         EepromCommand           = 0x000A,
   46         EepromData              = 0x000C,
   47                                                 /* AddressConfig Bits */
   48         autoSelect9             = 0x0080,
   49         xcvrMask9               = 0xC000,
   50                                                 /* ConfigControl bits */
   51         Ena                     = 0x0001,
   52         base10TAvailable9       = 0x0200,
   53         coaxAvailable9          = 0x1000,
   54         auiAvailable9           = 0x2000,
   55                                                 /* EepromCommand bits */
   56         EepromReadRegister      = 0x0080,
   57         EepromBusy              = 0x8000,
   58 };
   59 
   60 enum {                                          /* Window 1 - operating set */
   61         Wop                     = 0x0001,
   62 };
   63 
   64 enum {                                          /* Window 3 - FIFO management */
   65         Wfifo                   = 0x0003,
   66                                                 /* registers */
   67         InternalConfig          = 0x0000,       /* 3C509B, 3C589, 3C59[0257] */
   68                                                 /* InternalConfig bits */
   69         xcvr10BaseT             = 0x00000000,
   70         xcvr10Base2             = 0x00300000,
   71 };
   72 
   73 enum {                                          /* Window 4 - diagnostic */
   74         Wdiagnostic             = 0x0004,
   75                                                 /* registers */
   76         MediaStatus             = 0x000A,
   77                                                 /* MediaStatus bits */
   78         linkBeatDetect          = 0x0800,
   79 };
   80 
   81 extern int etherelnk3reset(Ether*);
   82 
   83 static char *tcmpcmcia[] = {
   84         "3C589",                        /* 3COM 589[ABCD] */
   85         "3C562",                        /* 3COM 562 */
   86         "589E",                         /* 3COM Megahertz 589E */
   87         nil,
   88 };
   89 
   90 static int
   91 configASIC(Ether* ether, int port, int xcvr)
   92 {
   93         int x;
   94 
   95         /* set Window 0 configuration registers */
   96         COMMAND(port, SelectRegisterWindow, Wsetup);
   97         outs(port+ConfigControl, Ena);
   98 
   99         /* IRQ must be 3 on 3C589/3C562 */
  100         outs(port + ResourceConfig, 0x3F00);
  101 
  102         x = ins(port+AddressConfig) & ~xcvrMask9;
  103         x |= (xcvr>>20)<<14;
  104         outs(port+AddressConfig, x);
  105 
  106         COMMAND(port, TxReset, 0);
  107         while(STATUS(port) & commandInProgress)
  108                 ;
  109         COMMAND(port, RxReset, 0);
  110         while(STATUS(port) & commandInProgress)
  111                 ;
  112 
  113         return etherelnk3reset(ether);
  114 }
  115 
  116 static int
  117 reset(Ether* ether)
  118 {
  119         int i, t, slot;
  120         char *type;
  121         int port;
  122         enum { WantAny, Want10BT, Want10B2 };
  123         int want;
  124         uchar ea[6];
  125         char *p;
  126 
  127         if(ether->irq == 0)
  128                 ether->irq = 10;
  129         if(ether->port == 0)
  130                 ether->port = 0x240;
  131         port = ether->port;
  132 
  133         if(ioalloc(port, 0x10, 0, "3C589") < 0)
  134                 return -1;
  135 
  136         type = nil;
  137         slot = -1;
  138         for(i = 0; tcmpcmcia[i] != nil; i++){
  139                 type = tcmpcmcia[i];
  140                 if((slot = pcmspecial(type, ether)) >= 0)
  141                         break;
  142         }
  143         ether->type = type;     /* must be set before calling configASIC */
  144         if(slot < 0){
  145                 iofree(port);
  146                 return -1;
  147         }
  148 
  149         /*
  150          * Read Ethernet address from card memory
  151          * on 3C562, but only if the user has not 
  152          * overridden it.
  153          */
  154         memset(ea, 0, sizeof ea);
  155         if(memcmp(ea, ether->ea, 6) == 0 && strcmp(type, "3C562") == 0) {
  156                 if(pcmcistuple(slot, 0x88, -1, ea, 6) == 6) {
  157                         for(i = 0; i < 6; i += 2){
  158                                 t = ea[i];
  159                                 ea[i] = ea[i+1];
  160                                 ea[i+1] = t;
  161                         }
  162                         memmove(ether->ea, ea, 6);
  163                 }
  164         }
  165         /*
  166          * Allow user to specify desired media in plan9.ini
  167          */
  168         want = WantAny;
  169         for(i = 0; i < ether->nopt; i++){
  170                 if(cistrncmp(ether->opt[i], "media=", 6) != 0)
  171                         continue;
  172                 p = ether->opt[i]+6;
  173                 if(cistrcmp(p, "10base2") == 0)
  174                         want = Want10B2;
  175                 else if(cistrcmp(p, "10baseT") == 0)
  176                         want = Want10BT;
  177         }
  178         
  179         /* try configuring as a 10BaseT */
  180         if(want==WantAny || want==Want10BT){
  181                 if(configASIC(ether, port, xcvr10BaseT) < 0){
  182                         pcmspecialclose(slot);
  183                         iofree(port);
  184                         return -1;
  185                 }
  186                 delay(100);
  187                 COMMAND(port, SelectRegisterWindow, Wdiagnostic);
  188                 if((ins(port+MediaStatus)&linkBeatDetect) || want==Want10BT){
  189                         COMMAND(port, SelectRegisterWindow, Wop);
  190                         print("#l%d: xcvr10BaseT %s\n", ether->ctlrno, type);
  191                         return 0;
  192                 }
  193         }
  194 
  195         /* try configuring as a 10base2 */
  196         if(want==WantAny || want==Want10B2){
  197                 COMMAND(port, GlobalReset, 0);
  198                 if(configASIC(ether, port, xcvr10Base2) < 0){
  199                         pcmspecialclose(slot);
  200                         iofree(port);
  201                         return -1;
  202                 }
  203                 print("#l%d: xcvr10Base2 %s\n", ether->ctlrno, type);
  204                 return 0;
  205         }
  206         return -1;              /* not reached */
  207 }
  208 
  209 void
  210 ether589link(void)
  211 {
  212         addethercard("3C589", reset);
  213         addethercard("3C562", reset);
  214         addethercard("589E", reset);
  215 }

Cache object: 2bf13c6c7ee29d2616c82ebd22a29d84


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