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/ppc/ethersaturn.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 #include "u.h"
    2 #include "../port/lib.h"
    3 #include "mem.h"
    4 #include "dat.h"
    5 #include "fns.h"
    6 #include "io.h"
    7 #include "../port/error.h"
    8 #include "../port/netif.h"
    9 #include "msaturn.h"
   10 
   11 #include "etherif.h"
   12 
   13 enum{
   14         Etcr = Saturn + 0x0c00,
   15         Etsr = Saturn + 0x0c02,
   16         Ercr = Saturn + 0x0c04,
   17         Ersr = Saturn + 0x0c06,
   18         Eisr = Saturn + 0x0d04,
   19         Eimr = Saturn + 0x0d06,
   20         Emacaddr0 = Saturn + 0x0e02,
   21         Miicr = Saturn + 0x0f02,
   22         Miiwdr = Saturn + 0x0f04,
   23         Miirdr = Saturn + 0x0f06,
   24 
   25         Ethermem = 0xf2c00000,
   26         Etherfsize = 0x2000,
   27         Nrx = 14,
   28         Ntx = 2,                // Nrx + Ntx must be 16
   29 
   30         Ersr_rxfpmask = 0xf,
   31         Ersr_rxevent = RBIT(0, ushort),
   32         Etcr_txfpmask = 0xf,
   33         Ercr_rxenab = RBIT(0, ushort),
   34         Ercr_auienab = RBIT(2, ushort),
   35         Etcr_txstart = RBIT(1, ushort),
   36         Etcr_retries = 0xf<<8,
   37         Ei_txecall = RBIT(0, ushort),
   38         Ei_txretry = RBIT(2, ushort),
   39         Ei_txdefer = RBIT(3, ushort),
   40         Ei_txcrs = RBIT(4, ushort),
   41         Ei_txdone = RBIT(5, ushort),
   42         Ei_rxcrcerr = RBIT(8, ushort),
   43         Ei_rxdrib = RBIT(9, ushort),
   44         Ei_rxdone = RBIT(10, ushort),
   45         Ei_rxshort = RBIT(11, ushort),
   46         Ei_rxlong = RBIT(12, ushort),
   47 
   48         Miicr_regshift = 6,
   49         Miicr_read = RBIT(10, ushort),
   50         Miicr_preambledis = RBIT(12, ushort),
   51         Miicr_accack = RBIT(14, ushort),
   52         Miicr_accbsy = RBIT(15, ushort),
   53 };
   54 
   55 typedef struct {
   56         Lock;
   57         int             txbusy;
   58         int             txempty;
   59         int             txfull;
   60         int             ntx;                    /* number of entries in transmit ring */
   61         int             rxlast;
   62 
   63         int             active;
   64         ulong   interrupts;     /* statistics */
   65         ulong   overflows;
   66 } Ctlr;
   67 
   68 static ushort*etcr=(ushort*)Etcr;
   69 static ushort*etsr=(ushort*)Etsr;
   70 static ushort*ercr=(ushort*)Ercr;
   71 static ushort*ersr=(ushort*)Ersr;
   72 static ushort*eimr=(ushort*)Eimr;
   73 static ushort*eisr=(ushort*)Eisr;
   74 static ushort*miicr=(ushort*)Miicr;
   75 static ushort*miirdr=(ushort*)Miirdr;
   76 
   77 static void
   78 txfill(Ether*ether, Ctlr*ctlr)
   79 {
   80         int len;
   81         Block *b;
   82         ushort*dst;
   83 
   84         while(ctlr->ntx<Ntx){
   85                 if((b=qget(ether->oq)) == nil)
   86                         break;
   87 
   88                 len = BLEN(b);
   89                 dst = (ushort*)(Ethermem+(ctlr->txempty+Nrx)*Etherfsize);
   90                 *dst = len;
   91                 memmove(&dst[1], b->rp, len);
   92                 ctlr->ntx++;
   93                 ctlr->txempty++;
   94                 if(ctlr->txempty==Ntx)
   95                         ctlr->txempty = 0;
   96                 freeb(b);
   97         }
   98 }
   99 
  100 static void
  101 txrestart(Ctlr*ctlr)
  102 {
  103         if(ctlr->ntx==0 || ctlr->txbusy)
  104                 return;
  105         ctlr->txbusy = 1;
  106         *etcr = Etcr_txstart|Etcr_retries|(ctlr->txfull+Nrx);
  107 }
  108 
  109 static void interrupt(Ureg*, void*);
  110 
  111 static void
  112 transmit(Ether*ether)
  113 {
  114         Ctlr *ctlr;
  115 
  116         ctlr = ether->ctlr;
  117         ilock(ctlr);
  118         txfill(ether, ctlr);
  119         txrestart(ctlr);
  120         iunlock(ctlr);
  121 
  122 }
  123 
  124 static void
  125 interrupt(Ureg*, void*arg)
  126 {
  127         Ctlr*ctlr;
  128         Ether*ether = arg;
  129         Etherpkt*pkt;
  130         ushort ie;
  131         int rx, len;
  132         Block *b;
  133 
  134         ctlr = ether->ctlr;
  135         if(!ctlr->active)
  136                 return; /* not ours */
  137         ctlr->interrupts++;
  138 
  139         ilock(ctlr);
  140         ie = *eisr;
  141         *eisr = ie;
  142         intack();
  143 
  144         if(ie==0)
  145                 iprint("interrupt: no interrupt source?\n");
  146 
  147         if(ie&Ei_txdone){
  148                 if((*etcr&Etcr_txstart)==0){
  149                         if(ctlr->txbusy){
  150                                 ctlr->txbusy = 0;
  151                                 ctlr->ntx--;
  152                                 ctlr->txfull++;
  153                                 if(ctlr->txfull==Ntx)
  154                                         ctlr->txfull = 0;
  155                         }
  156                         txrestart(ctlr);
  157                         txfill(ether, ctlr);
  158                         txrestart(ctlr);
  159                 }
  160                 else
  161                         iprint("interrupt: bogus tx interrupt\n");
  162                 ie &= ~Ei_txdone;
  163         }
  164 
  165         if(ie&Ei_rxdone){
  166                 rx=*ersr&Ersr_rxfpmask;
  167                 while(ctlr->rxlast!=rx){
  168 
  169                         ctlr->rxlast++;
  170                         if(ctlr->rxlast >= Nrx)
  171                                 ctlr->rxlast = 0;
  172 
  173                         pkt = (Etherpkt*)(Ethermem+ctlr->rxlast*Etherfsize);
  174                         len = *(ushort*)pkt;
  175                         if((b = iallocb(len+sizeof(ushort))) != nil){
  176                                 memmove(b->wp, pkt, len+sizeof(ushort));
  177                                 b->rp += sizeof(ushort);
  178                                 b->wp = b->rp + len;
  179                                 etheriq(ether, b, 1);
  180                         }else
  181                                 ether->soverflows++;
  182                         rx=*ersr&Ersr_rxfpmask;
  183                 }
  184                 ie &= ~Ei_rxdone;
  185         }
  186 
  187         if(ie&Ei_txretry){
  188                 iprint("ethersaturn: txretry!\n");
  189                 ie &= ~Ei_txretry;
  190                 ctlr->txbusy = 0;
  191                 txrestart(ctlr);
  192         }
  193 
  194         ie &= ~Ei_txcrs;
  195         if(ie)
  196                 iprint("interrupt: unhandled interrupts %.4uX\n", ie);
  197         iunlock(ctlr);
  198 }
  199 
  200 static int
  201 reset(Ether* ether)
  202 {
  203         Ctlr*ctlr;
  204 
  205         *ercr = 0;
  206         ctlr = malloc(sizeof(*ctlr));
  207         memset(ctlr, 0, sizeof(*ctlr));
  208         ctlr->active = 1;
  209 
  210         ether->ctlr = ctlr;
  211         ether->transmit = transmit;
  212         ether->interrupt = interrupt;
  213         ether->irq = Vecether;
  214         ether->arg = ether;
  215         memmove(ether->ea, (ushort*)Emacaddr0, Eaddrlen);
  216 
  217         *ercr = Ercr_rxenab|Ercr_auienab|(Nrx-1);
  218         *eimr = Ei_rxdone|Ei_txretry|Ei_txdone;
  219         
  220         iprint("reset: ercr %.4uX\n", *ercr);
  221         return 0;
  222 }
  223 
  224 void
  225 ethersaturnlink(void)
  226 {
  227         addethercard("saturn", reset);
  228 }
  229 

Cache object: 5c7b5df719f249130305a955e230f202


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