Changeset ff1c613 in rtems


Ignore:
Timestamp:
Nov 21, 2014, 7:11:57 PM (5 years ago)
Author:
Joel Sherrill <joel.sherrill@…>
Branches:
4.11, master
Children:
89be4e7
Parents:
502609c8
git-author:
Joel Sherrill <joel.sherrill@…> (11/21/14 19:11:57)
git-committer:
Joel Sherrill <joel.sherrill@…> (11/21/14 19:47:43)
Message:

powerpc/haleakala: Fix warnings

Location:
c/src/lib/libbsp/powerpc/haleakala
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • c/src/lib/libbsp/powerpc/haleakala/mmu/mmu_405.c

    r502609c8 rff1c613  
    1515
    1616
    17 /*--------------------------------- TLB handling ------------------------------------- */
     17/*----------------------------- TLB handling -------------------------------- */
    1818/* The following are in assembler in mmu_405asm.S  */
    1919extern  void MMU_GetTLBEntry(uint8_t index, uint32_t* tagword, uint32_t* dataword, uint8_t* pid);
    2020extern  void MMU_SetTLBEntry(uint8_t index, uint32_t hiword, uint32_t loword, uint8_t pid);
    21 extern  void MMU_ClearTLBs();
     21extern  void MMU_ClearTLBs(void);
    2222extern  int16_t MMU_FindTLBEntry(uint32_t address);
    2323
    2424
    25 enum { kNTLBs = 64 };           /* for 403GCX and 405 */
    26 
    27 static bool             sFreeTLBs[kNTLBs];
    28 static uint8_t  sLastIndex = 0;
    29 static int              sNInUse = 0;
     25enum { kNTLBs = 64 };    /* for 403GCX and 405 */
     26
     27static bool    sFreeTLBs[kNTLBs];
     28static uint8_t  sLastIndex = 0;
     29static int    sNInUse = 0;
    3030
    3131static void MMUFault(const char* what)
    3232/* Used for all setup faults; these can't really be ignored */
    3333{
    34         printk("\n>>>MMU fatal error %s\n",what);
    35         rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
    36 }
    37 
    38 static uint8_t AllocTLB()
    39 {
    40         uint8_t index;
    41        
    42         index = sLastIndex;
    43         do {
    44                 index++;
    45                 if (index == kNTLBs)
    46                         index = 0;
    47                 if (index == sLastIndex)
    48                         MMUFault("TLB table full");
    49         } while (! sFreeTLBs[index]);
    50         sFreeTLBs[index] = false;
    51         sLastIndex = index;
    52         sNInUse++;
    53         return index;
     34  printk("\n>>>MMU fatal error %s\n",what);
     35  rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);
     36}
     37
     38static uint8_t AllocTLB(void)
     39{
     40  uint8_t index;
     41 
     42  index = sLastIndex;
     43  do {
     44    index++;
     45    if (index == kNTLBs)
     46      index = 0;
     47    if (index == sLastIndex)
     48      MMUFault("TLB table full");
     49  } while (! sFreeTLBs[index]);
     50  sFreeTLBs[index] = false;
     51  sLastIndex = index;
     52  sNInUse++;
     53  return index;
    5454}
    5555
    5656static void FreeTLB(uint8_t index)
    5757{
    58         MMU_SetTLBEntry(index,0,0,0);
    59         sFreeTLBs[index] = true;
    60         sLastIndex = index-1;
    61         sNInUse--;
     58  MMU_SetTLBEntry(index,0,0,0);
     59  sFreeTLBs[index] = true;
     60  sLastIndex = index-1;
     61  sNInUse--;
    6262}
    6363
     
    6868int InstructionMissException(BSP_Exception_frame *f, unsigned int vector);
    6969int InstructionFetchException(BSP_Exception_frame *f, unsigned int vector);
     70void mmu_initialise(void);
     71int mmu_get_tlb_count(void);
     72uint8_t  mmu_new_processID(void);
     73uint8_t mmu_current_processID(void);
    7074
    7175void
    72 mmu_initialise()
     76mmu_initialise(void)
    7377/* Clear the TLBs and set up exception handlers for the MMU miss handlers */
    7478{
    75         int i;
    76        
    77         MMU_ClearTLBs();
    78         for (i=0; i<kNTLBs; i++) {
    79                 sFreeTLBs[i] = true;
    80                 MMU_SetTLBEntry(i,0,0,0xFF);
    81         }
    82         ppc_exc_set_handler(ASM_ISI_VECTOR ,InstructionFetchException);
    83         ppc_exc_set_handler(ASM_BOOKE_ITLBMISS_VECTOR ,DataMissException);
    84         ppc_exc_set_handler(ASM_BOOKE_DTLBMISS_VECTOR ,InstructionMissException);
     79  int i;
     80 
     81  MMU_ClearTLBs();
     82  for (i=0; i<kNTLBs; i++) {
     83    sFreeTLBs[i] = true;
     84    MMU_SetTLBEntry(i,0,0,0xFF);
     85  }
     86  ppc_exc_set_handler(ASM_ISI_VECTOR ,InstructionFetchException);
     87  ppc_exc_set_handler(ASM_BOOKE_ITLBMISS_VECTOR ,DataMissException);
     88  ppc_exc_set_handler(ASM_BOOKE_DTLBMISS_VECTOR ,InstructionMissException);
    8589}
    8690
     
    8892MakeTLBEntries(uint32_t startAt, uint32_t nBytes, bool EX, bool WR, bool I, uint8_t PID)
    8993{
    90         uint32_t mask, options, tagWord, dataWord;
    91         uint8_t index, sizeCode, pid;
    92        
    93         if ((startAt & 0x3FF) != 0)
    94                 MMUFault("TLB entry not on 1K boundary");
    95         if ((nBytes & 0x3FF) != 0)
    96                 MMUFault("TLB size not on 1K boundary");
    97                
    98         options = 0;
    99         if (EX) options += 0x200;
    100         if (WR) options += 0x100;
    101         if (I) options += 5;
    102        
    103         #ifdef qLogTLB
    104                 printk("TLB: make entries for $%X bytes from $%X..$%X PID %d",nBytes, startAt, startAt+nBytes-1, PID);
    105                 if (EX) printk(" EX");
    106                 if (WR) printk(" WR");
    107                 if (I) printk(" I");
    108                 printk("\n");
    109         #endif
    110        
    111         while (nBytes > 0) {
    112                 /* Find the largest block we can base on this address */
    113                 mask = 0x3FF;
    114                 sizeCode = 0;
    115                 while (mask < nBytes && ((startAt & mask)==0) && sizeCode < 8) {
    116                         mask = (mask<<2) + 3;
    117                         sizeCode++;
    118                 }
    119                 mask >>= 2;
    120                 sizeCode--;
    121                
    122                 /* Make a TLB entry describing this, ZSEL=0 */
    123                 tagWord = startAt | (sizeCode<<7) | 0x40;
    124                 dataWord = startAt | options;
    125                 index = AllocTLB();
    126                 MMU_SetTLBEntry( index , tagWord, dataWord, PID);
    127                
    128                 {
    129                         /* Paranoia: check that we can read that back... */
    130                         uint8_t tdex, oldpid;
    131                        
    132                         oldpid = mmu_current_processID();
    133                         mmu_set_processID(PID);
    134                         tdex = MMU_FindTLBEntry(startAt);
    135                         mmu_set_processID(oldpid);
    136                        
    137                         if (tdex != index) {
    138                                 printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X  ",index, startAt, mask+1,sizeCode,tagWord);
    139                                 printk(" -- find failed, %d/%d!\n",tdex,index);
    140                                 MMU_GetTLBEntry(index, &tagWord, &dataWord, &pid);
    141                                 printk(" -- reads back $%X : $%X, PID %d\n",tagWord,dataWord,pid);
    142                         } else {
    143                                 #ifdef qLogTLBDetails
    144                                 printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X\n",index, startAt, mask+1,sizeCode,tagWord);
    145                                 #endif
    146                         }
    147                 }
    148        
    149                 /* Subtract block from startAddr and nBytes */
    150                 mask++;         /* Convert to a byte count */
    151                 startAt += mask;
    152                 nBytes -= mask;
    153         }
    154         #ifdef qLogTLB
    155                 printk(" %d in use\n",sNInUse);
    156         #endif
     94  uint32_t mask, options, tagWord, dataWord;
     95  uint8_t  index, sizeCode, pid;
     96 
     97  if ((startAt & 0x3FF) != 0)
     98    MMUFault("TLB entry not on 1K boundary");
     99  if ((nBytes & 0x3FF) != 0)
     100    MMUFault("TLB size not on 1K boundary");
     101   
     102  options = 0;
     103  if (EX) options += 0x200;
     104  if (WR) options += 0x100;
     105  if (I) options += 5;
     106 
     107  #ifdef qLogTLB
     108    printk("TLB: make entries for $%X bytes from $%X..$%X PID %d",nBytes, startAt, startAt+nBytes-1, PID);
     109    if (EX) printk(" EX");
     110    if (WR) printk(" WR");
     111    if (I) printk(" I");
     112    printk("\n");
     113  #endif
     114 
     115  while (nBytes > 0) {
     116    /* Find the largest block we can base on this address */
     117    mask = 0x3FF;
     118    sizeCode = 0;
     119    while (mask < nBytes && ((startAt & mask)==0) && sizeCode < 8) {
     120      mask = (mask<<2) + 3;
     121      sizeCode++;
     122    }
     123    mask >>= 2;
     124    sizeCode--;
     125   
     126    /* Make a TLB entry describing this, ZSEL=0 */
     127    tagWord = startAt | (sizeCode<<7) | 0x40;
     128    dataWord = startAt | options;
     129    index = AllocTLB();
     130    MMU_SetTLBEntry( index , tagWord, dataWord, PID);
     131   
     132    {
     133      /* Paranoia: check that we can read that back... */
     134      uint8_t tdex, oldpid;
     135     
     136      oldpid = mmu_current_processID();
     137      mmu_set_processID(PID);
     138      tdex = MMU_FindTLBEntry(startAt);
     139      mmu_set_processID(oldpid);
     140     
     141      if (tdex != index) {
     142        printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X  ",index, startAt, mask+1,sizeCode,tagWord);
     143        printk(" -- find failed, %d/%d!\n",tdex,index);
     144        MMU_GetTLBEntry(index, &tagWord, &dataWord, &pid);
     145        printk(" -- reads back $%X : $%X, PID %d\n",tagWord,dataWord,pid);
     146      } else {
     147        #ifdef qLogTLBDetails
     148        printk(" Add TLB %d: At %X for $%X sizecode %d tagWord $%X\n",index, startAt, mask+1,sizeCode,tagWord);
     149        #endif
     150      }
     151    }
     152 
     153    /* Subtract block from startAddr and nBytes */
     154    mask++;    /* Convert to a byte count */
     155    startAt += mask;
     156    nBytes -= mask;
     157  }
     158  #ifdef qLogTLB
     159    printk(" %d in use\n",sNInUse);
     160  #endif
    157161}
    158162
     
    160164mmu_remove_space(uint32_t startAt, uint32_t endAt)
    161165{
    162         int16_t index;
    163         int32_t size;
    164         uint32_t tagword, dataword, nBytes;
    165         uint8_t  pid, sCode;
    166        
    167         nBytes = endAt - startAt;
    168        
    169         #ifdef qLogTLB
    170         printk("TLB: delete entries for $%X bytes from $%X\n",nBytes,startAt);
    171         #endif
    172        
    173         while (nBytes > 0) {
    174                 index = MMU_FindTLBEntry( (uint32_t)startAt );
    175                 size = 1024;
    176                 if (index >= 0) {
    177                         MMU_GetTLBEntry(index, &tagword, &dataword, &pid);
    178                         if ((tagword & 0x40) == 0)
    179                                 MMUFault("Undefine failed: redundant entries?");
    180                         if ((tagword & 0xFFFFFC00) != (uint32_t)startAt)
    181                                 MMUFault("Undefine not on TLB boundary");
    182                         FreeTLB(index);
    183                         sCode = (tagword >> 7) & 7;
    184                         while (sCode > 0) {
    185                                 size <<= 2;
    186                                 sCode--;
    187                         }
    188                         #ifdef qLogTLBDetails
    189                         printk(" Free TLB %d: At %X for $%X\n",index, startAt, size);
    190                         #endif
    191                 }
    192                 startAt += size;
    193                 nBytes -= size;
    194         }
     166  int16_t index;
     167  int32_t size;
     168  uint32_t tagword, dataword, nBytes;
     169  uint8_t  pid, sCode;
     170 
     171  nBytes = endAt - startAt;
     172 
     173  #ifdef qLogTLB
     174  printk("TLB: delete entries for $%X bytes from $%X\n",nBytes,startAt);
     175  #endif
     176 
     177  while (nBytes > 0) {
     178    index = MMU_FindTLBEntry( (uint32_t)startAt );
     179    size = 1024;
     180    if (index >= 0) {
     181      MMU_GetTLBEntry(index, &tagword, &dataword, &pid);
     182      if ((tagword & 0x40) == 0)
     183        MMUFault("Undefine failed: redundant entries?");
     184      if ((tagword & 0xFFFFFC00) != (uint32_t)startAt)
     185        MMUFault("Undefine not on TLB boundary");
     186      FreeTLB(index);
     187      sCode = (tagword >> 7) & 7;
     188      while (sCode > 0) {
     189        size <<= 2;
     190        sCode--;
     191      }
     192      #ifdef qLogTLBDetails
     193      printk(" Free TLB %d: At %X for $%X\n",index, startAt, size);
     194      #endif
     195    }
     196    startAt += size;
     197    nBytes -= size;
     198  }
    195199}
    196200
     
    199203/* Convert accesstype to write-enable, executable, and cache-inhibit bits */
    200204{
    201         bool EX, WR, I;
    202        
    203         EX = false;
    204         WR = false;
    205         I = false;
    206         switch (permissions) {
    207                 case executable                 : EX = true;  break;
    208                 case readOnlyData               : break;
    209                 case readOnlyNoCache    : I = true; break;
    210                 case readWriteData              : WR = true; break;
    211                 case readWriteNoCache   : WR = true; I= true; break;
    212                 case readWriteExecutable: WR = true; EX = true; break;
    213         }
    214         MakeTLBEntries( (uint32_t)startAddr, (uint32_t)(endAddr-startAddr+1), EX, WR, I, processID);
     205  bool EX, WR, I;
     206 
     207  EX = false;
     208  WR = false;
     209  I = false;
     210  switch (permissions) {
     211    case executable     : EX = true;  break;
     212    case readOnlyData     : break;
     213    case readOnlyNoCache   : I = true; break;
     214    case readWriteData     : WR = true; break;
     215    case readWriteNoCache   : WR = true; I= true; break;
     216    case readWriteExecutable: WR = true; EX = true; break;
     217  }
     218  MakeTLBEntries( (uint32_t)startAddr, (uint32_t)(endAddr-startAddr+1), EX, WR, I, processID);
    215219}
    216220
    217221int
    218 mmu_get_tlb_count()
    219 {
    220         return sNInUse;
     222mmu_get_tlb_count(void)
     223{
     224  return sNInUse;
    221225}
    222226
     
    227231static uint8_t sNextPID = 1;
    228232
    229 #define SPR_PID         0x3B1
    230 
    231 uint8_t mmu_new_processID()
    232 {
    233         return sNextPID++;
     233#define SPR_PID    0x3B1
     234
     235uint8_t  mmu_new_processID(void)
     236{
     237  return sNextPID++;
    234238}
    235239
     
    238242}
    239243
    240 uint8_t mmu_current_processID()
    241 {
    242         return PPC_SPECIAL_PURPOSE_REGISTER(SPR_PID);
     244uint8_t mmu_current_processID(void)
     245{
     246  return PPC_SPECIAL_PURPOSE_REGISTER(SPR_PID);
    243247}
    244248
    245249uint8_t mmu_set_processID(uint8_t newID)
    246250{
    247         uint8_t prev = mmu_current_processID();
    248         PPC_SET_SPECIAL_PURPOSE_REGISTER(SPR_PID,newID);
    249         return prev;
     251  uint8_t prev = mmu_current_processID();
     252  PPC_SET_SPECIAL_PURPOSE_REGISTER(SPR_PID,newID);
     253  return prev;
    250254}
    251255
     
    253257/* ------------------ Fault handlers ------------------ */
    254258
    255 #define SPR_ESR         0x3D4
    256 #define SPR_DEAR        0x3D5
     259#define SPR_ESR    0x3D4
     260#define SPR_DEAR  0x3D5
    257261
    258262enum { kESR_DST = 0x00800000 };
     
    260264int DataMissException(BSP_Exception_frame *f, unsigned int vector)
    261265{
    262         uint32_t addr, excSyn;
    263        
    264         addr = PPC_SPECIAL_PURPOSE_REGISTER(SPR_DEAR);
    265         excSyn  = PPC_SPECIAL_PURPOSE_REGISTER(SPR_ESR);
    266         if (excSyn & kESR_DST) printk("\n---Data write to $%X attempted at $%X\n",addr,f->EXC_SRR0);
    267                                           else printk("\n---Data read from $%X attempted at $%X\n",addr,f->EXC_SRR0);
    268         return -1;
     266  uint32_t addr, excSyn;
     267 
     268  addr = PPC_SPECIAL_PURPOSE_REGISTER(SPR_DEAR);
     269  excSyn  = PPC_SPECIAL_PURPOSE_REGISTER(SPR_ESR);
     270  if (excSyn & kESR_DST) printk("\n---Data write to $%X attempted at $%X\n",addr,f->EXC_SRR0);
     271            else printk("\n---Data read from $%X attempted at $%X\n",addr,f->EXC_SRR0);
     272  return -1;
    269273}
    270274
    271275int InstructionMissException(BSP_Exception_frame *f, unsigned int vector)
    272276{
    273         printk("\n---Instruction fetch attempted from $%X, no TLB exists\n",f->EXC_SRR0);
    274         return -1;
     277  printk("\n---Instruction fetch attempted from $%X, no TLB exists\n",f->EXC_SRR0);
     278  return -1;
    275279}
    276280
    277281int InstructionFetchException(BSP_Exception_frame *f, unsigned int vector)
    278282{
    279         printk("\n---Instruction fetch attempted from $%X, TLB is no-execute\n",f->EXC_SRR0);
    280         return -1;
    281 }
     283  printk("\n---Instruction fetch attempted from $%X, TLB is no-execute\n",f->EXC_SRR0);
     284  return -1;
     285}
  • c/src/lib/libbsp/powerpc/haleakala/network/network.c

    r502609c8 rff1c613  
    1919#include <rtems/rtems_bsdnet.h>
    2020#include <rtems/rtems_mii_ioctl.h>
     21#include <rtems/score/assert.h>
    2122
    2223#include <sys/param.h>
     
    3940#include <ppc4xx/ppc405ex.h>
    4041
    41 #define qDebug          /* General printf debugging */
    42 /* #define qMultiDebug */       /* Debugging for the multicast hardware filter */
     42#define qDebug     /* General printf debugging */
     43/* #define qMultiDebug */  /* Debugging for the multicast hardware filter */
    4344
    4445/*---------------------------- Hardware definitions -------------------------- */
     
    4647/* PHY addresses for Kilauea & Haleakala; defined by hardware */
    4748enum {
    48         kPHY0 = 1,
    49         kPHY1 = 2,
    50         kMaxEMACs = 2
     49  kPHY0 = 1,
     50  kPHY1 = 2,
     51  kMaxEMACs = 2
    5152};
    5253
    5354enum {
    54         kMaxRxBuffers = 256,
    55         kNXmtDescriptors = 256, /* May as well use all of them */
    56         kNoXmtBusy = 666                /* Arbitrary flag value outside 0..kNXmtDescriptors */
     55  kMaxRxBuffers = 256,
     56  kNXmtDescriptors = 256,  /* May as well use all of them */
     57  kNoXmtBusy = 666    /* Arbitrary flag value outside 0..kNXmtDescriptors */
    5758};
    5859
     
    6162
    6263typedef struct MALDescriptor {
    63         uint16_t ctrlBits;
    64         uint16_t adrDataSize;   /* 4 bits of high address, 12 bits of length */
    65         uint8_t* ptr;
     64  uint16_t ctrlBits;
     65  uint16_t adrDataSize;  /* 4 bits of high address, 12 bits of length */
     66  uint8_t* ptr;
    6667} MALDescriptor;
    6768
     
    6970    struct arpcom  arpcom;
    7071
    71         /* Pointer to memory-mapped hardware */
    72         volatile EthernetRegisters_GP*  EMAC;
    73        
     72  /* Pointer to memory-mapped hardware */
     73  volatile EthernetRegisters_GP*  EMAC;
     74 
    7475    /* Transmit and receive task references */
    75     rtems_id            rxDaemonTid;
    76         rtems_id                txDaemonTid;
    77         int                             nRxBuffers;
    78         int                             xmtFreeIndex;
    79         int                             xmtBusyIndex;
    80         MALDescriptor*  xmtDescTable;
    81         MALDescriptor*  rcvDescTable;
    82        
    83         struct mbuf* rxMBufs[kMaxRxBuffers];
    84         struct mbuf* txMBufs[kNXmtDescriptors];
    85        
    86         int                     phyAddr,        /* PHY address */
    87                                 phyState,       /* Last link state */
    88                                 phyOUI,         /* Cached PHY type info */
    89                                 phyModel,
    90                                 phyRev;
    91 
    92         /* Statistics */
    93         uint32_t   rxInterrupts;
    94         uint32_t   rxOverrun;
    95         uint32_t   rxRunt;
    96         uint32_t   rxBadCRC;
    97         uint32_t   rxNonOctet;
    98         uint32_t   rxGiant;
    99        
    100         uint32_t        txInterrupts;
    101        
    102         uint32_t        txLostCarrier;
    103         uint32_t        txDeferred;
    104         uint32_t        txOneCollision;
    105         uint32_t        txMultiCollision;
    106         uint32_t        txTooManyCollision;
    107         uint32_t        txLateCollision;
    108         uint32_t        txUnderrun;
    109         uint32_t        txPoorSignal;
     76    rtems_id    rxDaemonTid;
     77  rtems_id    txDaemonTid;
     78  int        nRxBuffers;
     79  int        xmtFreeIndex;
     80  int        xmtBusyIndex;
     81  MALDescriptor*  xmtDescTable;
     82  MALDescriptor*  rcvDescTable;
     83 
     84  struct mbuf* rxMBufs[kMaxRxBuffers];
     85  struct mbuf* txMBufs[kNXmtDescriptors];
     86 
     87  int      phyAddr,  /* PHY address */
     88        phyState,  /* Last link state */
     89        phyOUI,    /* Cached PHY type info */
     90        phyModel,
     91        phyRev;
     92
     93  /* Statistics */
     94  uint32_t   rxInterrupts;
     95  uint32_t   rxOverrun;
     96  uint32_t   rxRunt;
     97  uint32_t   rxBadCRC;
     98  uint32_t   rxNonOctet;
     99  uint32_t   rxGiant;
     100 
     101  uint32_t  txInterrupts;
     102 
     103  uint32_t  txLostCarrier;
     104  uint32_t  txDeferred;
     105  uint32_t  txOneCollision;
     106  uint32_t  txMultiCollision;
     107  uint32_t  txTooManyCollision;
     108  uint32_t  txLateCollision;
     109  uint32_t  txUnderrun;
     110  uint32_t  txPoorSignal;
    110111} EMACLocals;
    111112
    112113
    113114EMACLocals gEmacs[kMaxEMACs];
     115
     116int ppc405_emac_phy_adapt(EMACLocals* ep);
    114117
    115118/*----------------------------------- Globals --------------------------------------*/
     
    123126   with uncached MMU attrributes in bspstart.c */
    124127
    125 LINKER_SYMBOL(_enet_bdesc_start);               /* start of buffer descriptor space, from linkcmds */
    126 LINKER_SYMBOL(_enet_bdesc_end);                 /* top limit, from linkcmds */
     128LINKER_SYMBOL(_enet_bdesc_start);    /* start of buffer descriptor space, from linkcmds */
     129LINKER_SYMBOL(_enet_bdesc_end);      /* top limit, from linkcmds */
    127130
    128131static MALDescriptor* gTx0Descs = NULL;
    129132static MALDescriptor* gRx0Descs = NULL;
    130 static MALDescriptor* gTx1Descs = NULL; 
     133static MALDescriptor* gTx1Descs = NULL; 
    131134static MALDescriptor* gRx1Descs = NULL;
    132135
     
    138141 * This must not be any of the events used by the network task synchronization.
    139142 */
    140 #define INTERRUPT_EVENT                 RTEMS_EVENT_1
     143#define INTERRUPT_EVENT      RTEMS_EVENT_1
    141144
    142145/*
     
    144147 * This must not be the same as INTERRUPT_EVENT.
    145148 */
    146 #define START_TRANSMIT_EVENT    RTEMS_EVENT_2
     149#define START_TRANSMIT_EVENT  RTEMS_EVENT_2
    147150
    148151#define _sync    __asm__ volatile ("sync\n"::)
    149152
    150 #define kCacheLineMask  (PPC_CACHE_ALIGNMENT - 1)
     153#define  kCacheLineMask  (PPC_CACHE_ALIGNMENT - 1)
    151154
    152155
     
    154157
    155158static void InstallIRQHandler(rtems_irq_number id,
    156                                                           rtems_irq_hdl handler,
    157                                                           rtems_irq_enable turnOn,
    158                                                           rtems_irq_disable turnOff)
    159 {
    160         rtems_irq_connect_data params;
    161        
    162         params.name = id;
    163         params.hdl = handler;
    164         params.on = turnOn;
    165         params.off = turnOff;
    166         params.isOn = NULL;
    167         params.handle = NULL;
    168         if (! BSP_install_rtems_irq_handler(&params))
    169                 rtems_panic ("Can't install interrupt handler");
     159                rtems_irq_hdl handler,
     160                rtems_irq_enable turnOn,
     161                rtems_irq_disable turnOff)
     162{
     163  rtems_irq_connect_data params;
     164 
     165  params.name = id;
     166  params.hdl = handler;
     167  params.on = turnOn;
     168  params.off = turnOff;
     169  params.isOn = NULL;
     170  params.handle = NULL;
     171  if (! BSP_install_rtems_irq_handler(&params))
     172    rtems_panic ("Can't install interrupt handler");
    170173}
    171174
     
    173176NoAction(const rtems_irq_connect_data* unused)
    174177{
    175         /* printf("NoAction %d\n",unused->name); */
     178  /* printf("NoAction %d\n",unused->name); */
    176179}
    177180
     
    182185   
    183186enum {
    184         kPHYControl = 0,
    185         kPHYReset = 0x8000,
    186         kPHYStatus = 1,
    187         kPHYLinkStatus = 0x0004,
    188         kPHYID1 = 2,
    189         kPHYID2 = 3,
    190         kPHYAutoNegExp = 6,
    191         kPHY1000BaseTCtl = 9,
    192         kPHYExtStatus = 15,
    193        
    194         /* 88E1111 identification */
    195         kMarvellOUI = 0x5043,
    196         k88E1111Part = 0x0C,
    197 
    198         /* 88E1111 register addresses */
    199         k8PHYSpecStatus = 17,
    200                 k8PHYSpeedShift = 14,
    201                 k8PHYDuplex    = 0x2000,
    202                 k8PHYResolved  = 0x0800,
    203                 k8PHYLinkUp    = 0x0400,
    204         k8IntStatus = 19,
    205         k8IntEnable = 18,
    206         k8AutoNegComplete = 0x0800,
    207         k8LinkStateChanged = 0x0400,
    208         k8ExtCtlReg = 20,
    209                 k8RcvTimingDelay = 0x0080,
    210                 k8XmtTimingDelay = 0x0002,
    211                 k8XmtEnable      = 0x0001,
    212         k8LEDCtlReg = 24,
    213         k8ExtStatusReg = 27,
     187  kPHYControl = 0,
     188  kPHYReset = 0x8000,
     189  kPHYStatus = 1,
     190  kPHYLinkStatus = 0x0004,
     191  kPHYID1 = 2,
     192  kPHYID2 = 3,
     193  kPHYAutoNegExp = 6,
     194  kPHY1000BaseTCtl = 9,
     195  kPHYExtStatus = 15,
     196 
     197  /* 88E1111 identification */
     198  kMarvellOUI = 0x5043,
     199  k88E1111Part = 0x0C,
     200
     201  /* 88E1111 register addresses */
     202  k8PHYSpecStatus = 17,
     203    k8PHYSpeedShift = 14,
     204    k8PHYDuplex    = 0x2000,
     205    k8PHYResolved  = 0x0800,
     206    k8PHYLinkUp    = 0x0400,
     207  k8IntStatus = 19,
     208  k8IntEnable = 18,
     209  k8AutoNegComplete = 0x0800,
     210  k8LinkStateChanged = 0x0400,
     211  k8ExtCtlReg = 20,
     212    k8RcvTimingDelay = 0x0080,
     213    k8XmtTimingDelay = 0x0002,
     214    k8XmtEnable      = 0x0001,
     215  k8LEDCtlReg = 24,
     216  k8ExtStatusReg = 27,
    214217};
    215218
     
    217220static uint16_t ReadPHY(EMACLocals* ep, uint8_t reg)
    218221{
    219         int n = 0;
    220         uint32_t t;
    221        
    222         reg &= 0x1F;
    223        
    224         /* 405EX-specific! */
    225         while ((ep->EMAC->STAcontrol & keSTARun) != 0)
    226                 { ; }
    227         ep->EMAC->STAcontrol = keSTADirectRd + (ep->phyAddr<<5) + reg;
    228         ep->EMAC->STAcontrol |= keSTARun;
    229         /* Wait for the read to complete, should take ~25usec */
    230         do {
    231                 t = ep->EMAC->STAcontrol;
    232                 if (++n > 200000)
    233                         rtems_panic("PHY read timed out");
    234         } while ((t & keSTARun) != 0);
    235        
    236         if (t & kSTAErr)
    237                 rtems_panic("PHY read failed");
    238         return t >> 16;
     222  int n = 0;
     223  uint32_t t;
     224 
     225  reg &= 0x1F;
     226 
     227  /* 405EX-specific! */
     228  while ((ep->EMAC->STAcontrol & keSTARun) != 0)
     229    { ; }
     230  ep->EMAC->STAcontrol = keSTADirectRd + (ep->phyAddr<<5) + reg;
     231  ep->EMAC->STAcontrol |= keSTARun;
     232  /* Wait for the read to complete, should take ~25usec */
     233  do {
     234    t = ep->EMAC->STAcontrol;
     235    if (++n > 200000)
     236      rtems_panic("PHY read timed out");
     237  } while ((t & keSTARun) != 0);
     238 
     239  if (t & kSTAErr)
     240    rtems_panic("PHY read failed");
     241  return t >> 16;
    239242}
    240243
     
    242245{
    243246
    244         reg &= 0x1F;
    245        
    246         /* 405EX-specific */
    247         while ((ep->EMAC->STAcontrol & keSTARun) != 0)
    248                 { ; }
    249         ep->EMAC->STAcontrol = (value<<16) | keSTADirectWr | (ep->phyAddr<<5) | reg;
    250         ep->EMAC->STAcontrol |= keSTARun;
     247  reg &= 0x1F;
     248 
     249  /* 405EX-specific */
     250  while ((ep->EMAC->STAcontrol & keSTARun) != 0)
     251    { ; }
     252  ep->EMAC->STAcontrol = (value<<16) | keSTADirectWr | (ep->phyAddr<<5) | reg;
     253  ep->EMAC->STAcontrol |= keSTARun;
    251254}
    252255
    253256static void ResetPHY(EMACLocals* ep)
    254257{
    255         int n;
    256        
    257         n = ReadPHY(ep, kPHYControl);
    258         n |= kPHYReset;
    259         WritePHY(ep, kPHYControl, n);
    260         do {
    261                 rtems_task_wake_after( (rtems_bsdnet_ticks_per_second/20) + 1 );
    262                 n = ReadPHY(ep, kPHYControl);
    263         } while ((n & kPHYReset)!=0);
     258  int n;
     259 
     260  n = ReadPHY(ep, kPHYControl);
     261  n |= kPHYReset;
     262  WritePHY(ep, kPHYControl, n);
     263  do {
     264    rtems_task_wake_after( (rtems_bsdnet_ticks_per_second/20) + 1 );
     265    n = ReadPHY(ep, kPHYControl);
     266  } while ((n & kPHYReset)!=0);
    264267}
    265268
    266269enum {
    267         kELinkUp = 0x80,
    268         kELinkFullDuplex = 0x40,
    269         kELinkSpeed10 = 0,
    270         kELinkSpeed100 = 1,
    271         kELinkSpeed1000 = 2,
    272         kELinkSpeedMask = 3
     270  kELinkUp = 0x80,
     271  kELinkFullDuplex = 0x40,
     272  kELinkSpeed10 = 0,
     273  kELinkSpeed100 = 1,
     274  kELinkSpeed1000 = 2,
     275  kELinkSpeedMask = 3
    273276};
    274277
     
    276279/* Return link state (up/speed/duplex) as a set of flags */
    277280{
    278         int state, result;
    279        
    280         /* if (ep->phyOUI==kMarvellOUI) */
    281         result = 0;
    282         state = ReadPHY(ep,k8PHYSpecStatus);
    283         if ((state & k8PHYLinkUp) && (state & k8PHYResolved)) {
    284                 result |= kELinkUp;
    285                 if (state & k8PHYDuplex) result |= kELinkFullDuplex;
    286                 result |= ((state >> k8PHYSpeedShift) & 3);
    287         }
    288         return result;
     281  int state, result;
     282 
     283  /* if (ep->phyOUI==kMarvellOUI) */
     284  result = 0;
     285  state = ReadPHY(ep,k8PHYSpecStatus);
     286  if ((state & k8PHYLinkUp) && (state & k8PHYResolved)) {
     287    result |= kELinkUp;
     288    if (state & k8PHYDuplex) result |= kELinkFullDuplex;
     289    result |= ((state >> k8PHYSpeedShift) & 3);
     290  }
     291  return result;
    289292}
    290293
     
    294297static void InitPHY(EMACLocals* ep)
    295298{
    296         int id,id2,n;
    297        
    298         id = ReadPHY(ep,kPHYID1);
    299         id2 = ReadPHY(ep,kPHYID2);
    300         ep->phyOUI = (id<<6) + (id2>>10);
    301         ep->phyModel = (id2>>4) & 0x1F;
    302         ep->phyRev = id2 & 0xF;
    303        
    304         #ifdef qDebug
    305                 printf("PHY %d maker $%X model %d revision %d\n",ep->phyAddr,ep->phyOUI,ep->phyModel,ep->phyRev);
    306         #endif
    307        
    308         /* Test for PHYs that we understand; insert new PHY types initialisation here */
    309         if (ep->phyOUI == kMarvellOUI || ep->phyModel == k88E1111Part) {
    310                 /* 88E111-specific: Enable RxTx timing control, enable transmitter */
    311                 n = ReadPHY(ep, k8ExtCtlReg);
    312                 n |= k8RcvTimingDelay + k8XmtTimingDelay + k8XmtEnable;         
    313                 WritePHY(ep, k8ExtCtlReg, n);
    314                
    315                 /* Set LED mode; Haleakala has LINK10 and TX LEDs only. Set up to do 100/1000 and link up/active*/
    316                 WritePHY(ep, k8LEDCtlReg, 0x4109);
    317                
    318                 /* Need to do a reset after fiddling with registers*/
    319                 ResetPHY(ep);
    320         } else
    321                 rtems_panic("Unknown PHY type");
     299  int id,id2,n;
     300 
     301  id = ReadPHY(ep,kPHYID1);
     302  id2 = ReadPHY(ep,kPHYID2);
     303  ep->phyOUI = (id<<6) + (id2>>10);
     304  ep->phyModel = (id2>>4) & 0x1F;
     305  ep->phyRev = id2 & 0xF;
     306 
     307  #ifdef qDebug
     308    printf("PHY %d maker $%X model %d revision %d\n",ep->phyAddr,ep->phyOUI,ep->phyModel,ep->phyRev);
     309  #endif
     310 
     311  /* Test for PHYs that we understand; insert new PHY types initialisation here */
     312  if (ep->phyOUI == kMarvellOUI || ep->phyModel == k88E1111Part) {
     313    /* 88E111-specific: Enable RxTx timing control, enable transmitter */
     314    n = ReadPHY(ep, k8ExtCtlReg);
     315    n |= k8RcvTimingDelay + k8XmtTimingDelay + k8XmtEnable;   
     316    WritePHY(ep, k8ExtCtlReg, n);
     317   
     318    /* Set LED mode; Haleakala has LINK10 and TX LEDs only. Set up to do 100/1000 and link up/active*/
     319    WritePHY(ep, k8LEDCtlReg, 0x4109);
     320   
     321    /* Need to do a reset after fiddling with registers*/
     322    ResetPHY(ep);
     323  } else
     324    rtems_panic("Unknown PHY type");
    322325}
    323326
     
    328331MALTXDone_handler(rtems_irq_hdl_param param)
    329332{
    330         int n;
    331        
    332         n = PPC_DEVICE_CONTROL_REGISTER(MAL0_TXEOBISR);
    333         if (n & kMALChannel0) {
    334                 gEmacs[0].txInterrupts++;
    335                 rtems_event_send (gEmacs[0].txDaemonTid, INTERRUPT_EVENT);
    336         }
    337         if (n & kMALChannel1) {
    338                 gEmacs[1].txInterrupts++;
    339                 rtems_event_send (gEmacs[1].txDaemonTid, INTERRUPT_EVENT);
    340         }
    341         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXEOBISR,n);
     333  int n;
     334 
     335  n = PPC_DEVICE_CONTROL_REGISTER(MAL0_TXEOBISR);
     336  if (n & kMALChannel0) {
     337    gEmacs[0].txInterrupts++;
     338    rtems_event_send (gEmacs[0].txDaemonTid, INTERRUPT_EVENT);
     339  }
     340  if (n & kMALChannel1) {
     341    gEmacs[1].txInterrupts++;
     342    rtems_event_send (gEmacs[1].txDaemonTid, INTERRUPT_EVENT);
     343  }
     344  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXEOBISR,n);
    342345}
    343346
     
    345348MALRXDone_handler (rtems_irq_hdl_param param)
    346349{
    347         int n;
    348        
    349         n = PPC_DEVICE_CONTROL_REGISTER(MAL0_RXEOBISR);
    350         if (n & kMALChannel0) {
    351                 gEmacs[0].rxInterrupts++;
    352                 rtems_event_send (gEmacs[0].rxDaemonTid, INTERRUPT_EVENT);
    353         }
    354         if (n & kMALChannel1) {
    355                 gEmacs[1].rxInterrupts++;
    356                 rtems_event_send (gEmacs[1].rxDaemonTid, INTERRUPT_EVENT);
    357         }
    358         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXEOBISR,n);       /* Write back to clear interrupt */
     350  int n;
     351 
     352  n = PPC_DEVICE_CONTROL_REGISTER(MAL0_RXEOBISR);
     353  if (n & kMALChannel0) {
     354    gEmacs[0].rxInterrupts++;
     355    rtems_event_send (gEmacs[0].rxDaemonTid, INTERRUPT_EVENT);
     356  }
     357  if (n & kMALChannel1) {
     358    gEmacs[1].rxInterrupts++;
     359    rtems_event_send (gEmacs[1].rxDaemonTid, INTERRUPT_EVENT);
     360  }
     361  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXEOBISR,n);  /* Write back to clear interrupt */
    359362}
    360363
     
    364367MALErr_handler (rtems_irq_hdl_param param)
    365368{
    366         uint32_t errCause;
    367        
    368         errCause = PPC_DEVICE_CONTROL_REGISTER(MAL0_ESR);
    369         /* Clear the error */
    370         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_ESR,errCause);
    371 }
    372        
     369  uint32_t errCause;
     370 
     371  errCause = PPC_DEVICE_CONTROL_REGISTER(MAL0_ESR);
     372  /* Clear the error */
     373  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_ESR,errCause);
     374}
     375 
    373376static void
    374377EMAC0Err_handler (rtems_irq_hdl_param param)
    375378{
    376         uint32_t errCause;
    377        
    378         errCause = gEmacs[0].EMAC->intStatus;
    379         /* Clear error by writing back */
    380         gEmacs[0].EMAC->intStatus = errCause;
     379  uint32_t errCause;
     380 
     381  errCause = gEmacs[0].EMAC->intStatus;
     382  /* Clear error by writing back */
     383  gEmacs[0].EMAC->intStatus = errCause;
    381384}
    382385
     
    384387EMAC1Err_handler (rtems_irq_hdl_param param)
    385388{
    386         uint32_t errCause;
    387        
    388         errCause = gEmacs[1].EMAC->intStatus;
    389         /* Clear error by writing back */
    390         gEmacs[1].EMAC->intStatus = errCause;
     389  uint32_t errCause;
     390 
     391  errCause = gEmacs[1].EMAC->intStatus;
     392  /* Clear error by writing back */
     393  gEmacs[1].EMAC->intStatus = errCause;
    391394}
    392395
     
    398401static void
    399402mal_initialise(void)
    400 {       
    401         uint32_t bdescbase;
    402         int nBytes, ntables;
    403        
    404         /*------------------- Initialise the MAL for both channels ---------------------- */
    405                        
    406         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALReset);
    407         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCARR, kMALChannel0 | kMALChannel1);
    408         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCARR, kMALChannel0 | kMALChannel1);
    409 
    410         /* Acquire MAL interrupts */
    411         InstallIRQHandler(BSP_UIC_MALTXEOB, MALTXDone_handler, NoAction, NoAction);
    412         InstallIRQHandler(BSP_UIC_MALRXEOB, MALRXDone_handler, NoAction, NoAction);
    413         InstallIRQHandler(BSP_UIC_MALSERR, MALErr_handler, NoAction, NoAction);
    414                
    415         /* Set up the buffer descriptor tables */
    416         bdescbase = (uint32_t)(_enet_bdesc_start);
    417         nBytes = sizeof(MALDescriptor) * 256;
    418         ntables = 4;
    419         if (get_ppc_cpu_type() != PPC_405EX) {
    420                 /* The 405GP/GPr requires table bases to be 4K-aligned and can use two tx channels on one EMAC */
    421                 nBytes = (nBytes + 0x0FFF) & ~0x0FFF;
    422                 bdescbase = (bdescbase + 0x0FFF) & ~0x0FFF;
    423                 ntables = 3;
    424         }
    425        
    426         /* printf("Buffer descriptors at $%X..$%X, code from $%X\n",bdescbase, bdescbase + nBytes*ntables - 1,(uint32_t)&_text_start); */
    427        
    428         /* Check that we have been given enough space and the buffers don't run past the enet_bdesc_end address */
    429         if (bdescbase + nBytes*ntables > (uint32_t)_enet_bdesc_end)
    430                 rtems_panic("Ethernet descriptor space insufficient!");
    431                
    432         gTx0Descs = (MALDescriptor*)bdescbase;
    433         gTx1Descs = (MALDescriptor*)(bdescbase + nBytes);
    434         gRx0Descs = (MALDescriptor*)(bdescbase + nBytes*2);
    435         /* Clear the buffer descriptor tables */
    436         memset(gTx0Descs, 0, sizeof(MALDescriptor)*256);
    437         memset(gTx1Descs, 0, sizeof(MALDescriptor)*256);
    438         memset(gRx0Descs, 0, sizeof(MALDescriptor)*256);
    439         if (get_ppc_cpu_type() == PPC_405EX) {
    440                 gRx1Descs = (MALDescriptor*)(bdescbase + nBytes*3);
    441                 memset(gRx1Descs, 0, sizeof(MALDescriptor)*256);
    442         }
    443        
    444         /* Set up the MAL registers */
    445         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCTP0R,gTx0Descs);
    446         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCTP1R,gTx1Descs);
    447         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCTP0R,gRx0Descs);
    448         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RCBS0, (MCLBYTES-16)>>4);          /* The hardware writes directly to the mbuf clusters, so it can write MCLBYTES */
    449         if (get_ppc_cpu_type() == PPC_405EX) {
    450                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALMedHiPriority + keMALRdMaxBurst32 + keMALWrMedHiPriority + keMALWrMaxBurst32 +
    451                                                                                         kMALLocksOPB + kMALLocksErrs + kMALCanBurst);
    452                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCTP1R,gRx1Descs);
    453                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RCBS1, (MCLBYTES-16)>>4);
    454                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_IER,0xF7);         /* Enable all MAL interrupts */
    455         } else {
    456                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALMedHiPriority + kMALLocksOPB + kMALLocksErrs + kMALCanBurst + kMALLatency8);
    457                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_IER,0x1F);         /* Enable all MAL interrupts */
    458         }
     403{ 
     404  uint32_t bdescbase;
     405  int nBytes, ntables;
     406 
     407  /*------------------- Initialise the MAL for both channels ---------------------- */
     408     
     409  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALReset);
     410  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCARR, kMALChannel0 | kMALChannel1);
     411  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCARR, kMALChannel0 | kMALChannel1);
     412
     413  /* Acquire MAL interrupts */
     414  InstallIRQHandler(BSP_UIC_MALTXEOB, MALTXDone_handler, NoAction, NoAction);
     415  InstallIRQHandler(BSP_UIC_MALRXEOB, MALRXDone_handler, NoAction, NoAction);
     416  InstallIRQHandler(BSP_UIC_MALSERR, MALErr_handler, NoAction, NoAction);
     417   
     418  /* Set up the buffer descriptor tables */
     419  bdescbase = (uint32_t)(_enet_bdesc_start);
     420  nBytes = sizeof(MALDescriptor) * 256;
     421  ntables = 4;
     422  if (get_ppc_cpu_type() != PPC_405EX) {
     423    /* The 405GP/GPr requires table bases to be 4K-aligned and can use two tx channels on one EMAC */
     424    nBytes = (nBytes + 0x0FFF) & ~0x0FFF;
     425    bdescbase = (bdescbase + 0x0FFF) & ~0x0FFF;
     426    ntables = 3;
     427  }
     428 
     429  /* printf("Buffer descriptors at $%X..$%X, code from $%X\n",bdescbase, bdescbase + nBytes*ntables - 1,(uint32_t)&_text_start); */
     430 
     431  /* Check that we have been given enough space and the buffers don't run past the enet_bdesc_end address */
     432  if (bdescbase + nBytes*ntables > (uint32_t)_enet_bdesc_end)
     433    rtems_panic("Ethernet descriptor space insufficient!");
     434   
     435  gTx0Descs = (MALDescriptor*)bdescbase;
     436  gTx1Descs = (MALDescriptor*)(bdescbase + nBytes);
     437  gRx0Descs = (MALDescriptor*)(bdescbase + nBytes*2);
     438  /* Clear the buffer descriptor tables */
     439  memset(gTx0Descs, 0, sizeof(MALDescriptor)*256);
     440  memset(gTx1Descs, 0, sizeof(MALDescriptor)*256);
     441  memset(gRx0Descs, 0, sizeof(MALDescriptor)*256);
     442  if (get_ppc_cpu_type() == PPC_405EX) {
     443    gRx1Descs = (MALDescriptor*)(bdescbase + nBytes*3);
     444    memset(gRx1Descs, 0, sizeof(MALDescriptor)*256);
     445  }
     446 
     447  /* Set up the MAL registers */
     448  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCTP0R,gTx0Descs);
     449  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCTP1R,gTx1Descs);
     450  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCTP0R,gRx0Descs);
     451  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RCBS0, (MCLBYTES-16)>>4);    /* The hardware writes directly to the mbuf clusters, so it can write MCLBYTES */
     452  if (get_ppc_cpu_type() == PPC_405EX) {
     453    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALMedHiPriority + keMALRdMaxBurst32 + keMALWrMedHiPriority + keMALWrMaxBurst32 +
     454                      kMALLocksOPB + kMALLocksErrs + kMALCanBurst);
     455    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCTP1R,gRx1Descs);
     456    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RCBS1, (MCLBYTES-16)>>4);
     457    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_IER,0xF7);    /* Enable all MAL interrupts */
     458  } else {
     459    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_CFG,kMALMedHiPriority + kMALLocksOPB + kMALLocksErrs + kMALCanBurst + kMALLatency8);
     460    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_IER,0x1F);    /* Enable all MAL interrupts */
     461  }
    459462}
    460463
     
    464467static void printaddr(uint8_t* enetaddr)
    465468{
    466         printf("%02X.%02X.%02X.%02X.%02X.%02X",enetaddr[0],enetaddr[1],enetaddr[2],enetaddr[3],enetaddr[4],enetaddr[5]);
     469  printf("%02X.%02X.%02X.%02X.%02X.%02X",enetaddr[0],enetaddr[1],enetaddr[2],enetaddr[3],enetaddr[4],enetaddr[5]);
    467470}
    468471#endif
    469472
    470473static bool gMALInited = FALSE;
    471        
     474 
    472475static void
    473476ppc405_emac_initialize_hardware(EMACLocals* ep)
    474477{
    475478
    476         int  n,mfr;
    477         int  unitnum = ep->arpcom.ac_if.if_unit;
    478        
    479         if (get_ppc_cpu_type() == PPC_405EX) {
    480                 /* PPC405EX: configure the RGMII bridge and clocks */
    481                 RGMIIRegisters* rgmp = (RGMIIRegisters*)RGMIIAddress;
    482                 rgmp->FER = 0x00080055; /* Both EMACs RGMII */
    483                 rgmp->SSR = 0x00000044; /* Both EMACs 1000Mbps */
    484                 /* Configure the TX clock to be external */
    485                 mfsdr(SDR0_MFR,mfr);
    486                 mfr &= ~0x0C000000;             /* Switches both PHYs */
    487                 mtsdr(SDR0_MFR,mfr);
    488         }
    489        
    490         /* Reset the EMAC */
    491         n = 0;
    492         ep->EMAC->mode0 = kEMACSoftRst;                                                 
    493         while ((ep->EMAC->mode0 & kEMACSoftRst) != 0)
    494                 n++;            /* Wait for it to complete */
    495        
    496         /* Set up so we can talk to the PHY */
    497         ep->EMAC->mode1 = keEMACIPHYAddr4 |  keEMACOPB100MHz;
    498        
    499         /* Initialise the PHY  */
    500         InitPHY(ep);
    501        
    502         /* Initialise the MAL (once only) */
    503         if ( ! gMALInited) {
    504                 mal_initialise();
    505                 gMALInited = TRUE;
    506         }
    507 
    508         /* Set up IRQ handlers and enable the MAL channels for this port */
    509         if (unitnum==0) {
    510                 ep->xmtDescTable = gTx0Descs;
    511                 ep->rcvDescTable = gRx0Descs;
    512                 InstallIRQHandler(BSP_UIC_EMAC0, EMAC0Err_handler, NoAction, NoAction);
    513                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCASR,kMALChannel0);
    514                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCASR,kMALChannel0);
    515         } else {
    516                 ep->xmtDescTable = gTx1Descs;
    517                 ep->rcvDescTable = gRx1Descs;
    518                 InstallIRQHandler(BSP_UIC_EMAC1, EMAC1Err_handler, NoAction, NoAction);
    519                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCASR,kMALChannel1);
    520                 PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCASR,kMALChannel1);
    521         }
    522        
    523         /* The rest of the EMAC initialisation is done in emac_phy_adapt
    524            when we know what the characteristics of the link are */
     479  int  n,mfr;
     480  int  unitnum = ep->arpcom.ac_if.if_unit;
     481 
     482  if (get_ppc_cpu_type() == PPC_405EX) {
     483    /* PPC405EX: configure the RGMII bridge and clocks */
     484    RGMIIRegisters* rgmp = (RGMIIRegisters*)RGMIIAddress;
     485    rgmp->FER = 0x00080055;  /* Both EMACs RGMII */
     486    rgmp->SSR = 0x00000044;  /* Both EMACs 1000Mbps */
     487    /* Configure the TX clock to be external */
     488    mfsdr(SDR0_MFR,mfr);
     489    mfr &= ~0x0C000000;    /* Switches both PHYs */
     490    mtsdr(SDR0_MFR,mfr);
     491  }
     492 
     493  /* Reset the EMAC */
     494  n = 0;
     495  ep->EMAC->mode0 = kEMACSoftRst;             
     496  while ((ep->EMAC->mode0 & kEMACSoftRst) != 0)
     497    n++;    /* Wait for it to complete */
     498 
     499  /* Set up so we can talk to the PHY */
     500  ep->EMAC->mode1 = keEMACIPHYAddr4 |  keEMACOPB100MHz;
     501 
     502  /* Initialise the PHY  */
     503  InitPHY(ep);
     504 
     505  /* Initialise the MAL (once only) */
     506  if ( ! gMALInited) {
     507    mal_initialise();
     508    gMALInited = TRUE;
     509  }
     510
     511  /* Set up IRQ handlers and enable the MAL channels for this port */
     512  if (unitnum==0) {
     513    ep->xmtDescTable = gTx0Descs;
     514    ep->rcvDescTable = gRx0Descs;
     515    InstallIRQHandler(BSP_UIC_EMAC0, EMAC0Err_handler, NoAction, NoAction);
     516    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCASR,kMALChannel0);
     517    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCASR,kMALChannel0);
     518  } else {
     519    ep->xmtDescTable = gTx1Descs;
     520    ep->rcvDescTable = gRx1Descs;
     521    InstallIRQHandler(BSP_UIC_EMAC1, EMAC1Err_handler, NoAction, NoAction);
     522    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCASR,kMALChannel1);
     523    PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCASR,kMALChannel1);
     524  }
     525 
     526  /* The rest of the EMAC initialisation is done in emac_phy_adapt
     527     when we know what the characteristics of the link are */
    525528}
    526529
     
    531534int ppc405_emac_phy_adapt(EMACLocals* ep)
    532535{
    533         int linkState = GetPHYLinkState(ep);
    534         int spd;
    535        
    536         if ((linkState & kELinkUp) && (linkState != ep->phyState)) {
    537                 /* Reset the EMAC and set registers according to PHY state */
    538                 int i,n = 0;
    539                 uint32_t mode, rmode;
    540                
    541                 ep->EMAC->mode0 = kEMACSoftRst;                                                 
    542                 while ((ep->EMAC->mode0 & kEMACSoftRst) != 0)
    543                         n++;            /* Wait for it to complete */
    544                 spd = linkState & kELinkSpeedMask;
    545                 mode = (spd<<22) | kgEMACTx0Multi;
    546                 if (get_ppc_cpu_type() == PPC_405EX)
    547                         mode |= (keEMAC16KRxFIFO | keEMAC16KTxFIFO | keEMACIPHYAddr4 | keEMACOPB100MHz );
    548                 else
    549                         mode |= (kgEMAC4KRxFIFO | kgEMAC2KTxFIFO);
    550                 if (linkState & kELinkFullDuplex)
    551                         mode |= kEMACFullDuplex + kEMACDoFlowControl;
    552                 if ( (linkState & kELinkFullDuplex) || (spd > kELinkSpeed10) )
    553                         mode |= kEMACIgnoreSQE;
    554        
    555                
    556                 if (spd==kELinkSpeed1000) {
    557                         /* Gigabit, so we support jumbo frames. Take appropriate measures: adjust the if_mtu */
    558                         /* Note that we do this here because changing it later doesn't work very well : see
    559                            the SIOCSIFMTU discussion below */
    560                         struct ifnet* ifp = &ep->arpcom.ac_if;
    561                         ifp->if_mtu = ETHERMTU_JUMBO;
    562                         mode |= keEMACJumbo;
    563                 }
    564                
    565                
    566                 ep->phyState = linkState;
    567                 ep->EMAC->mode1 = mode;
    568                
    569                 /* Install 48-bit hardware address that we have been given */
    570                 ep->EMAC->addrHi = (ep->arpcom.ac_enaddr[0]<<8) + ep->arpcom.ac_enaddr[1];
    571                 ep->EMAC->addrLo = (ep->arpcom.ac_enaddr[2]<<24) + (ep->arpcom.ac_enaddr[3]<<16)
    572                                                 + (ep->arpcom.ac_enaddr[4]<<8) + (ep->arpcom.ac_enaddr[5] );
    573                
    574                 /* Set receive mode appropriately */
    575                 rmode = kEMACStripPadding + kEMACStripFCS + kEMACBrcastRcv;
    576                
    577                 if (ep->arpcom.ac_if.if_flags & IFF_PROMISC) rmode |= kEMACPromiscRcv;
    578                                                                                                 else rmode |= kEMACIndivRcv;
    579                 if (get_ppc_cpu_type() == PPC_405EX)
    580                         rmode |= keEMACRxFIFOAFMax;     
    581                 if ((ep->arpcom.ac_if.if_flags & IFF_ALLMULTI) != 0)
    582                         rmode |= kEMACPromMultRcv;
    583                 else if ((ep->arpcom.ac_if.if_flags & IFF_MULTICAST) != 0)
    584                         rmode |= kEMACMultcastRcv;
    585                
    586                 ep->EMAC->rcvMode = rmode;
    587 
    588                 if (get_ppc_cpu_type() == PPC_405EX)
    589                         for (i=0; i<8; i++)
    590                                 ep->EMAC->e_groupHash[i] = 0;
    591                 else
    592                         for (i=0; i<4; i++)
    593                                 ep->EMAC->g_groupHash[i] = 0;
    594 
    595                 if (get_ppc_cpu_type() == PPC_405EX) {
    596                         /* Rcv low watermark, must be < mode1 Rcv FIFO size and > MAL burst length (default 64x4 bytes), 16-byte units
    597                            High watermark must be > low and < RcvFIFO size */
    598                         ep->EMAC->rcvWatermarks = (16<<22) + (768<<6);
    599                         /* Xmt low request must be >= 17 FIFO entries, Xmt urgent must be > low */
    600                         ep->EMAC->xmtMode1 = (17<<27) + (68<<14);                       /* TLR = 17, TUR = 68 */
    601                         /* Xmt partial packet request threshold */
    602                         ep->EMAC->xmtReqThreshold = ((1000>>2)-1) << 24;        /* TRTR[TRT] = 1000 FIFO entries */
    603                 } else {
    604                         ep->EMAC->rcvWatermarks = (15<<24) + (32<<8);
    605                         ep->EMAC->xmtReqThreshold = ((1448>>6)-1) << 26;        /* TRT = 1024b */
    606                         ep->EMAC->xmtMode1 = 0x40200000;                                        /* TLR = 8w=32b, TUR=32w=128b */
    607                 }
    608                        
    609                 ep->EMAC->IPGap = 8;
    610                
    611                 /* Want EMAC interrupts for error logging & statistics */
    612                 ep->EMAC->intEnable = kEMACIOverrun + kEMACIPause + kEMACIBadPkt + kEMACIRuntPkt + kEMACIShortEvt
    613                                                         + kEMACIAlignErr + kEMACIBadFCS + kEMACIOverSize + kEMACILLCRange + kEMACISQEErr
    614                                                         + kEMACITxErr;
    615                                                
    616                 /* Start it running */
    617                 ep->EMAC->mode0 = kEMACRxEnable + kEMACTxEnable;               
    618                 return 0;
    619         } else
    620                 return -1;
     536  int linkState = GetPHYLinkState(ep);
     537  int spd;
     538 
     539  if ((linkState & kELinkUp) && (linkState != ep->phyState)) {
     540    /* Reset the EMAC and set registers according to PHY state */
     541    int i,n = 0;
     542    uint32_t mode, rmode;
     543   
     544    ep->EMAC->mode0 = kEMACSoftRst;             
     545    while ((ep->EMAC->mode0 & kEMACSoftRst) != 0)
     546      n++;    /* Wait for it to complete */
     547    spd = linkState & kELinkSpeedMask;
     548    mode = (spd<<22) | kgEMACTx0Multi;
     549    if (get_ppc_cpu_type() == PPC_405EX)
     550      mode |= (keEMAC16KRxFIFO | keEMAC16KTxFIFO | keEMACIPHYAddr4 | keEMACOPB100MHz );
     551    else
     552      mode |= (kgEMAC4KRxFIFO | kgEMAC2KTxFIFO);
     553    if (linkState & kELinkFullDuplex)
     554      mode |= kEMACFullDuplex + kEMACDoFlowControl;
     555    if ( (linkState & kELinkFullDuplex) || (spd > kELinkSpeed10) )
     556      mode |= kEMACIgnoreSQE;
     557 
     558   
     559    if (spd==kELinkSpeed1000) {
     560      /* Gigabit, so we support jumbo frames. Take appropriate measures: adjust the if_mtu */
     561      /* Note that we do this here because changing it later doesn't work very well : see
     562         the SIOCSIFMTU discussion below */
     563      struct ifnet* ifp = &ep->arpcom.ac_if;
     564      ifp->if_mtu = ETHERMTU_JUMBO;
     565      mode |= keEMACJumbo;
     566    }
     567   
     568   
     569    ep->phyState = linkState;
     570    ep->EMAC->mode1 = mode;
     571   
     572    /* Install 48-bit hardware address that we have been given */
     573    ep->EMAC->addrHi = (ep->arpcom.ac_enaddr[0]<<8) + ep->arpcom.ac_enaddr[1];
     574    ep->EMAC->addrLo = (ep->arpcom.ac_enaddr[2]<<24) + (ep->arpcom.ac_enaddr[3]<<16)
     575            + (ep->arpcom.ac_enaddr[4]<<8) + (ep->arpcom.ac_enaddr[5] );
     576   
     577    /* Set receive mode appropriately */
     578    rmode = kEMACStripPadding + kEMACStripFCS + kEMACBrcastRcv;
     579   
     580    if (ep->arpcom.ac_if.if_flags & IFF_PROMISC) rmode |= kEMACPromiscRcv;
     581                        else rmode |= kEMACIndivRcv;
     582    if (get_ppc_cpu_type() == PPC_405EX)
     583      rmode |= keEMACRxFIFOAFMax; 
     584    if ((ep->arpcom.ac_if.if_flags & IFF_ALLMULTI) != 0)
     585      rmode |= kEMACPromMultRcv;
     586    else if ((ep->arpcom.ac_if.if_flags & IFF_MULTICAST) != 0)
     587      rmode |= kEMACMultcastRcv;
     588   
     589    ep->EMAC->rcvMode = rmode;
     590
     591    if (get_ppc_cpu_type() == PPC_405EX)
     592      for (i=0; i<8; i++)
     593        ep->EMAC->e_groupHash[i] = 0;
     594    else
     595      for (i=0; i<4; i++)
     596        ep->EMAC->g_groupHash[i] = 0;
     597
     598    if (get_ppc_cpu_type() == PPC_405EX) {
     599      /* Rcv low watermark, must be < mode1 Rcv FIFO size and > MAL burst length (default 64x4 bytes), 16-byte units
     600         High watermark must be > low and < RcvFIFO size */
     601      ep->EMAC->rcvWatermarks = (16<<22) + (768<<6);
     602      /* Xmt low request must be >= 17 FIFO entries, Xmt urgent must be > low */
     603      ep->EMAC->xmtMode1 = (17<<27) + (68<<14);      /* TLR = 17, TUR = 68 */
     604      /* Xmt partial packet request threshold */
     605      ep->EMAC->xmtReqThreshold = ((1000>>2)-1) << 24;  /* TRTR[TRT] = 1000 FIFO entries */
     606    } else {
     607      ep->EMAC->rcvWatermarks = (15<<24) + (32<<8);
     608      ep->EMAC->xmtReqThreshold = ((1448>>6)-1) << 26;  /* TRT = 1024b */
     609      ep->EMAC->xmtMode1 = 0x40200000;          /* TLR = 8w=32b, TUR=32w=128b */
     610    }
     611     
     612    ep->EMAC->IPGap = 8;
     613   
     614    /* Want EMAC interrupts for error logging & statistics */
     615    ep->EMAC->intEnable = kEMACIOverrun + kEMACIPause + kEMACIBadPkt + kEMACIRuntPkt + kEMACIShortEvt
     616              + kEMACIAlignErr + kEMACIBadFCS + kEMACIOverSize + kEMACILLCRange + kEMACISQEErr
     617              + kEMACITxErr;
     618           
     619    /* Start it running */
     620    ep->EMAC->mode0 = kEMACRxEnable + kEMACTxEnable;   
     621    return 0;
     622  } else
     623    return -1;
    621624}
    622625
     
    626629/* Disable the EMAC channels so we stop running and processing interrupts */
    627630{
    628         ep->EMAC->mode0 = 0;
     631  ep->EMAC->mode0 = 0;
    629632}
    630633
     
    633636/* Start the transmitter: set TMR0[GNP] */
    634637{
    635         ep->EMAC->xmtMode0 = kEMACNewPacket0 + 7;               /* *** TFAE value for EX */
     638  ep->EMAC->xmtMode0 = kEMACNewPacket0 + 7;    /* *** TFAE value for EX */
    636639}
    637640
     
    640643   until we get a valid link */
    641644{
    642         EMACLocals* ep = ifp->if_softc;
    643        
    644         if (ppc405_emac_phy_adapt(ep)==0) {
    645                 ep->arpcom.ac_if.if_flags |= IFF_RUNNING;
    646                 ifp->if_timer = 0;              /* No longer needed */
    647         } else
    648                 ifp->if_timer = 1;              /* reschedule, once a second */
     645  EMACLocals* ep = ifp->if_softc;
     646 
     647  if (ppc405_emac_phy_adapt(ep)==0) {
     648    ep->arpcom.ac_if.if_flags |= IFF_RUNNING;
     649    ifp->if_timer = 0;    /* No longer needed */
     650  } else
     651    ifp->if_timer = 1;    /* reschedule, once a second */
    649652}
    650653
     
    659662/* point at has all gone */
    660663{
    661         uint16_t scan, status;
    662        
    663         if (ep->xmtBusyIndex != kNoXmtBusy) {
    664                 scan = ep->xmtBusyIndex;
    665                 while (TRUE) {
    666                         /* Scan forward through the descriptors */
    667                         status = ep->xmtDescTable[scan].ctrlBits;
    668                         if (++scan >= kNXmtDescriptors)
    669                                 scan = 0;
    670                         /* If we find a ready (i.e not-yet-sent) descriptor, stop */
    671                         if ((status & kMALTxReady) != 0)
    672                                 break;
    673                         /* If we find a last descriptor, we can free all the buffers up to and including it */
    674                         if ((status & kMALLast) != 0) {
    675                                 /* End of packet and it has been sent or abandoned; advance xmtBusyIndex to  */
    676                                 /* the next buffer and free buffers. */
    677                                 if ((status & kEMACErrMask) != 0) {
    678                                         /* Transmit error of some kind */
    679                                        
    680                                         if ((status & kEMACDeferred) != 0)
    681                                                 ep->txDeferred++;
    682                                         if ((status & kEMACLostCarrier) != 0)
    683                                                 ep->txLostCarrier++;    /* *** Perhaps more serious reaction needed... */
    684                                        
    685                                         if ((status & kEMACLateColl) != 0)
    686                                                 ep->txLateCollision++;
    687                                         if ((status & kEMACOneColl) != 0)
    688                                                 ep->txOneCollision++;
    689                                         if ((status & kEMACMultColl) != 0)
    690                                                 ep->txMultiCollision++;
    691                                         if ((status & kEMACCollFail) != 0)
    692                                                 ep->txTooManyCollision++;
    693                                        
    694                                         if ((status & kEMACSQEFail) != 0)
    695                                                 ep->txPoorSignal++;
    696                                         if ((status & kEMACUnderrun) != 0)
    697                                                 ep->txUnderrun++;
    698                                 }
    699                                 while (ep->xmtBusyIndex != scan) {
    700                                         m_free(ep->txMBufs[ep->xmtBusyIndex]);
    701                                         if (++ep->xmtBusyIndex >= kNXmtDescriptors) ep->xmtBusyIndex = 0;
    702                                 }
    703                                 if (ep->xmtBusyIndex == ep->xmtFreeIndex) {
    704                                         /* Nothing is busy */
    705                                         ep->xmtBusyIndex = kNoXmtBusy;
    706                                         break;
    707                                 }
    708                         }
    709                 }
    710         }
     664  uint16_t scan, status;
     665 
     666  if (ep->xmtBusyIndex != kNoXmtBusy) {
     667    scan = ep->xmtBusyIndex;
     668    while (TRUE) {
     669      /* Scan forward through the descriptors */
     670      status = ep->xmtDescTable[scan].ctrlBits;
     671      if (++scan >= kNXmtDescriptors)
     672        scan = 0;
     673      /* If we find a ready (i.e not-yet-sent) descriptor, stop */
     674      if ((status & kMALTxReady) != 0)
     675        break;
     676      /* If we find a last descriptor, we can free all the buffers up to and including it */
     677      if ((status & kMALLast) != 0) {
     678        /* End of packet and it has been sent or abandoned; advance xmtBusyIndex to  */
     679        /* the next buffer and free buffers. */
     680        if ((status & kEMACErrMask) != 0) {
     681          /* Transmit error of some kind */
     682         
     683          if ((status & kEMACDeferred) != 0)
     684            ep->txDeferred++;
     685          if ((status & kEMACLostCarrier) != 0)
     686            ep->txLostCarrier++;  /* *** Perhaps more serious reaction needed... */
     687         
     688          if ((status & kEMACLateColl) != 0)
     689            ep->txLateCollision++;
     690          if ((status & kEMACOneColl) != 0)
     691            ep->txOneCollision++;
     692          if ((status & kEMACMultColl) != 0)
     693            ep->txMultiCollision++;
     694          if ((status & kEMACCollFail) != 0)
     695            ep->txTooManyCollision++;
     696         
     697          if ((status & kEMACSQEFail) != 0)
     698            ep->txPoorSignal++;
     699          if ((status & kEMACUnderrun) != 0)
     700            ep->txUnderrun++;
     701        }
     702        while (ep->xmtBusyIndex != scan) {
     703          m_free(ep->txMBufs[ep->xmtBusyIndex]);
     704          if (++ep->xmtBusyIndex >= kNXmtDescriptors) ep->xmtBusyIndex = 0;
     705        }
     706        if (ep->xmtBusyIndex == ep->xmtFreeIndex) {
     707          /* Nothing is busy */
     708          ep->xmtBusyIndex = kNoXmtBusy;
     709          break;
     710        }
     711      }
     712    }
     713  }
    711714}
    712715
     
    716719/* Given a chain of mbufs, set up a transmit description and fire it off */
    717720{
    718         int nAdded, index, lastidx, totalbytes;
    719         uint16_t status;
    720         struct mbuf* lastAdded;
    721        
    722         nAdded = 0;
    723         totalbytes = 0;
    724         lastAdded = NULL;
    725         index = ep->xmtFreeIndex;
    726        
    727         /* Go through the chain of mbufs setting up descriptors for each */
    728         while (m != NULL) {
    729                                        
    730                 if (m->m_len == 0) {
    731                         /* Can be empty: dispose and unlink from chain */
    732                         m = m_free(m);
    733                         if (lastAdded!=NULL) lastAdded->m_next = m;
    734                 } else {
    735                         /* Make sure the mbuf has been written to memory */
    736                         rtems_cache_flush_multiple_data_lines(mtod (m, void *), m->m_len);
    737                         /* If there are no descriptors available wait until there are */
    738                         while (index == ep->xmtBusyIndex) {
    739                                 rtems_event_set events;
    740                                 ifp->if_timer = 2;
    741                                 /* Then check for free descriptors, followed by: */
    742                                 rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events);
    743                                 FreeTxDescriptors(ep);
    744                         }
    745                                
    746                         /* Fill in a descriptor for this mbuf and record it */
    747                         ep->txMBufs[index] = m;
    748                         ep->xmtDescTable[index].ptr = mtod (m, void *);
    749                         ep->xmtDescTable[index].adrDataSize = m->m_len;
    750                         /* Fill in ctrlBits as we go but don't mark the first one as ready yet */
    751                         status = kEMACGenFCS + kEMACGenPad + kEMACRepSrcAddr;
    752                         if (nAdded > 0)
    753                                 status |= kMALTxReady;
    754                         if (index==kNXmtDescriptors-1)
    755                                 status |= kMALWrap;
    756                         ep->xmtDescTable[index].ctrlBits = status;
    757                         lastidx = index;
    758                                        
    759                         totalbytes += m->m_len;
    760                         lastAdded = m;
    761                         m = m->m_next;
    762                         nAdded++;
    763                        
    764                         index += 1;
    765                         if (index==kNXmtDescriptors)
    766                                 index = 0;
    767                        
    768                         if (nAdded==kNXmtDescriptors)
    769                                 rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);               /* This is impossible, of course... */
    770                 }
    771         }
    772        
    773         if (nAdded > 0) {
    774                 /* Done and we added some buffers */
    775                 /* Label the last buffer and ask for an interrupt */
    776                 ep->xmtDescTable[lastidx].ctrlBits |= kMALLast + kMALInterrupt;
    777                 /* Finally set the ready bit on the first buffer */
    778                 ep->xmtDescTable[ep->xmtFreeIndex].ctrlBits |= kMALTxReady;
    779                 /* Make sure this has been written */
    780                 _sync;
    781                 if (ep->xmtBusyIndex == kNoXmtBusy)
    782                         ep->xmtBusyIndex = ep->xmtFreeIndex;
    783                 ep->xmtFreeIndex = index;
    784                 /* Poke the EMAC to get it started (which may not be needed if its already running */
    785                 ppc405_emac_startxmt(ep);
    786                 ifp->if_timer = 2;
    787         }
     721  int nAdded, index, lastidx = -1, totalbytes;
     722  uint16_t status;
     723  struct mbuf* lastAdded;
     724 
     725  nAdded = 0;
     726  totalbytes = 0;
     727  lastAdded = NULL;
     728  index = ep->xmtFreeIndex;
     729 
     730  /* Go through the chain of mbufs setting up descriptors for each */
     731  while (m != NULL) {
     732         
     733    if (m->m_len == 0) {
     734      /* Can be empty: dispose and unlink from chain */
     735      m = m_free(m);
     736      if (lastAdded!=NULL) lastAdded->m_next = m;
     737    } else {
     738      /* Make sure the mbuf has been written to memory */
     739      rtems_cache_flush_multiple_data_lines(mtod (m, void *), m->m_len);
     740      /* If there are no descriptors available wait until there are */
     741      while (index == ep->xmtBusyIndex) {
     742        rtems_event_set events;
     743        ifp->if_timer = 2;
     744        /* Then check for free descriptors, followed by: */
     745        rtems_bsdnet_event_receive (INTERRUPT_EVENT, RTEMS_WAIT | RTEMS_EVENT_ANY, RTEMS_NO_TIMEOUT, &events);
     746        FreeTxDescriptors(ep);
     747      }
     748       
     749      /* Fill in a descriptor for this mbuf and record it */
     750      ep->txMBufs[index] = m;
     751      ep->xmtDescTable[index].ptr = mtod (m, void *);
     752      ep->xmtDescTable[index].adrDataSize = m->m_len;
     753      /* Fill in ctrlBits as we go but don't mark the first one as ready yet */
     754      status = kEMACGenFCS + kEMACGenPad + kEMACRepSrcAddr;
     755      if (nAdded > 0)
     756        status |= kMALTxReady;
     757      if (index==kNXmtDescriptors-1)
     758        status |= kMALWrap;
     759      ep->xmtDescTable[index].ctrlBits = status;
     760      lastidx = index;
     761         
     762      totalbytes += m->m_len;
     763      lastAdded = m;
     764      m = m->m_next;
     765      nAdded++;
     766     
     767      index += 1;
     768      if (index==kNXmtDescriptors)
     769        index = 0;
     770     
     771      if (nAdded==kNXmtDescriptors)
     772        rtems_fatal_error_occurred(RTEMS_INTERNAL_ERROR);    /* This is impossible, of course... */
     773    }
     774  }
     775
     776  _Assert( lastidx != -1 );
     777
     778  if (nAdded > 0) {
     779    /* Done and we added some buffers */
     780    /* Label the last buffer and ask for an interrupt */
     781    ep->xmtDescTable[lastidx].ctrlBits |= kMALLast + kMALInterrupt;
     782    /* Finally set the ready bit on the first buffer */
     783    ep->xmtDescTable[ep->xmtFreeIndex].ctrlBits |= kMALTxReady;
     784    /* Make sure this has been written */
     785    _sync;
     786    if (ep->xmtBusyIndex == kNoXmtBusy)
     787      ep->xmtBusyIndex = ep->xmtFreeIndex;
     788    ep->xmtFreeIndex = index;
     789    /* Poke the EMAC to get it started (which may not be needed if its already running */
     790    ppc405_emac_startxmt(ep);
     791    ifp->if_timer = 2;
     792  }
    788793}
    789794
     
    791796ppc405_emac_txDaemon (void* param)
    792797{
    793         EMACLocals* ep = param;
    794         struct ifnet *ifp = &ep->arpcom.ac_if;
    795         struct mbuf *m;
    796         rtems_event_set events;
    797 
    798         ep->xmtFreeIndex = 0;
    799         ep->xmtBusyIndex = kNoXmtBusy;
    800         while (TRUE) {
    801                 /* Wait for someone wanting to transmit */
    802                 rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT,
    803                                                                         RTEMS_EVENT_ANY | RTEMS_WAIT,
    804                                                                         RTEMS_NO_TIMEOUT,
    805                                                                         &events);
    806                 if (events & INTERRUPT_EVENT)
    807                         ifp->if_timer = 0;
    808                 /* Grab packets and send until empty */
    809                 /* Note that this doesn't (at the time of writing, RTEMS 4.9.1), ever get asked to send more than
    810                    one header mbuf and one data mbuf cluster, regardless of the MTU. This is because sosend() in the FreeBSD
    811                    stack only passes one mbuf at a time across to tcp_send, which immediately sends it */
    812                 while (TRUE) {
    813                         FreeTxDescriptors(ep);
    814                         IF_DEQUEUE(&ifp->if_snd, m);
    815                         if (m == NULL)
    816                                 break;
    817                         SendPacket (ep, ifp, m);
    818                 }
    819                 ifp->if_flags &= ~IFF_OACTIVE;
    820         }
     798  EMACLocals* ep = param;
     799  struct ifnet *ifp = &ep->arpcom.ac_if;
     800  struct mbuf *m;
     801  rtems_event_set events;
     802
     803  ep->xmtFreeIndex = 0;
     804  ep->xmtBusyIndex = kNoXmtBusy;
     805  while (TRUE) {
     806    /* Wait for someone wanting to transmit */
     807    rtems_bsdnet_event_receive (START_TRANSMIT_EVENT | INTERRUPT_EVENT,
     808                  RTEMS_EVENT_ANY | RTEMS_WAIT,
     809                  RTEMS_NO_TIMEOUT,
     810                  &events);
     811    if (events & INTERRUPT_EVENT)
     812      ifp->if_timer = 0;
     813    /* Grab packets and send until empty */
     814    /* Note that this doesn't (at the time of writing, RTEMS 4.9.1), ever get asked to send more than
     815       one header mbuf and one data mbuf cluster, regardless of the MTU. This is because sosend() in the FreeBSD
     816       stack only passes one mbuf at a time across to tcp_send, which immediately sends it */
     817    while (TRUE) {
     818      FreeTxDescriptors(ep);
     819      IF_DEQUEUE(&ifp->if_snd, m);
     820      if (m == NULL)
     821        break;
     822      SendPacket (ep, ifp, m);
     823    }
     824    ifp->if_flags &= ~IFF_OACTIVE;
     825  }
    821826}
    822827
     
    826831MakeRxBuffer(EMACLocals* ep, int index)
    827832{
    828         struct mbuf*    m;
    829        
    830         /* Allocate an mbuf, wait if necessary, label as dynamic data, start of record */
    831         MGETHDR (m, M_WAIT, MT_DATA);
    832         /* Allocate a cluster buffer to this mbuf, waiting if necessary */
    833         MCLGET (m, M_WAIT);
    834         /* Set up reference to the interface the packet will be received on */
    835         m->m_pkthdr.rcvif = &ep->arpcom.ac_if;
    836         ep->rxMBufs[index] = m;
    837         ep->rcvDescTable[index].ptr = mtod (m, uint8_t*);
    838         ep->rcvDescTable[index].adrDataSize = 0x0EEE;           /* Precaution */
    839         if (index==ep->nRxBuffers-1)
    840                 ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt + kMALWrap;
    841         else
    842                 ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt;
     833  struct mbuf*   m;
     834 
     835  /* Allocate an mbuf, wait if necessary, label as dynamic data, start of record */
     836  MGETHDR (m, M_WAIT, MT_DATA);
     837  /* Allocate a cluster buffer to this mbuf, waiting if necessary */
     838  MCLGET (m, M_WAIT);
     839  /* Set up reference to the interface the packet will be received on */
     840  m->m_pkthdr.rcvif = &ep->arpcom.ac_if;
     841  ep->rxMBufs[index] = m;
     842  ep->rcvDescTable[index].ptr = mtod (m, uint8_t*);
     843  ep->rcvDescTable[index].adrDataSize = 0x0EEE;    /* Precaution */
     844  if (index==ep->nRxBuffers-1)
     845    ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt + kMALWrap;
     846  else
     847    ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt;
    843848}
    844849
     
    848853ppc405_emac_rxDaemon (void* param)
    849854{
    850         EMACLocals* ep = param;
    851         int             index,n,mdex;
    852         struct mbuf*    m;
    853         struct mbuf*    mstart = NULL;
    854         struct mbuf*    mlast = NULL;
    855         struct ifnet*   ifp;
    856         struct ether_header* eh = NULL;
    857         rtems_event_set events;
    858        
    859         /* Startup : allocate a bunch of receive buffers and point the descriptor table entries at them */
    860         ifp = &ep->arpcom.ac_if;
    861         index = 0;
    862         while (index < ep->nRxBuffers) {
    863                 MakeRxBuffer(ep,index);
    864                 index += 1;
    865         }
    866         index = 0;
    867         mdex = 0;
    868        
    869         /* Loop waiting for frames to arrive */
    870         while (TRUE) {
    871                 rtems_bsdnet_event_receive (INTERRUPT_EVENT,
    872                                                                                         RTEMS_WAIT | RTEMS_EVENT_ANY,
    873                                                                                         RTEMS_NO_TIMEOUT,
    874                                                                                         &events);
    875                 while ((ep->rcvDescTable[index].ctrlBits & kMALRxEmpty) == 0) {
    876                         /* Got a frame */
    877                         uint16_t flags = ep->rcvDescTable[index].ctrlBits;
    878                         if ((flags & kEMACErrMask) != 0) {
    879                                 /* It has errors. Update statistics */
    880                                 if ((flags & kEMACOverrun) != 0)
    881                                         ep->rxOverrun++;
    882                                 if ((flags & kEMACRuntPkt) != 0)
    883                                         ep->rxRunt++;
    884                                 if ((flags & kEMACBadFCS) != 0)
    885                                         ep->rxBadCRC++;
    886                                 if ((flags & kEMACAlignErr) != 0)
    887                                         ep->rxNonOctet++;
    888                                 if ((flags & kEMACPktLong) != 0)
    889                                         ep->rxGiant++;
    890                                 /* and reset descriptor to empty */
    891                                
    892                                 /* No need to get new mbufs, just reset */
    893                                 ep->rcvDescTable[index].adrDataSize = 0x0EEE;
    894                                 if (index==ep->nRxBuffers-1)
    895                                         ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt + kMALWrap;
    896                                 else
    897                                         ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt;
    898                                
    899                         } else {
    900                                 /* Seems to be OK. Invalidate cache over the size we received */
    901                                 n = ep->rcvDescTable[index].adrDataSize & 0x0FFF;
    902                                 m = ep->rxMBufs[index];
    903                                 rtems_cache_invalidate_multiple_data_lines(m->m_data, (n + kCacheLineMask) & ~kCacheLineMask);
    904                                
    905                                 /* Consider copying small packets out of the cluster into m_pktdat to save clusters? */
    906                                 m->m_len = n;
    907                                        
    908                                 /* Jumbo packets will span multiple mbufs; chain them together and submit when we get the last one */
    909                                 if (flags & kMALRxFirst) {
    910                                         /* First mbuf in the packet */
    911                                         if (mstart!=NULL)
    912                                                 rtems_panic("first, no last");
    913                                        
    914                                         /* Adjust the mbuf pointers to skip the header and set eh to point to it */
    915                                         m->m_len -= sizeof(struct ether_header);
    916                                         m->m_pkthdr.len = m->m_len;
    917                                         eh = mtod (m, struct ether_header *);
    918                                         m->m_data += sizeof(struct ether_header);
    919                                         mstart = m;
    920                                         mlast = m;
    921                                         mdex = index;
    922                                 } else {
    923                                         /* Chain onto mstart: add length to pkthdr.len */
    924                                         if (mstart == NULL)
    925                                                 rtems_panic("last, no first");
    926                                        
    927                                         mstart->m_pkthdr.len += n;
    928                                         m->m_flags &= ~M_PKTHDR;
    929                                         mlast->m_next = m;
    930                                         mlast = m;
    931                                 }
    932                                
    933                                 if (flags & kMALLast) {
    934                                         /* Last mbuf in the packet: pass base of the chain to a higher level */
    935                                         ether_input (ifp, eh, mstart);
    936                                        
    937                                         /* ether_input took the chain, set up new mbufs in the slots we used */
    938                                         mdex -= 1;
    939                                         do {
    940                                                 if (++mdex==ep->nRxBuffers) mdex = 0;
    941                                                 MakeRxBuffer(ep,mdex);
    942                                         } while (mdex != index);
    943                                         mstart = NULL;
    944                                         mlast = NULL;
    945                                         eh = NULL;
    946                                 }
    947                         }
    948                         index += 1;
    949                         if (index == ep->nRxBuffers) index = 0;
    950                 }
    951         }
     855  EMACLocals* ep = param;
     856  int     index,n,mdex;
     857  struct mbuf*   m;
     858  struct mbuf*    mstart = NULL;
     859  struct mbuf*    mlast = NULL;
     860  struct ifnet*  ifp;
     861  struct ether_header* eh = NULL;
     862  rtems_event_set events;
     863 
     864  /* Startup : allocate a bunch of receive buffers and point the descriptor table entries at them */
     865  ifp = &ep->arpcom.ac_if;
     866  index = 0;
     867  while (index < ep->nRxBuffers) {
     868    MakeRxBuffer(ep,index);
     869    index += 1;
     870  }
     871  index = 0;
     872  mdex = 0;
     873 
     874  /* Loop waiting for frames to arrive */
     875  while (TRUE) {
     876    rtems_bsdnet_event_receive (INTERRUPT_EVENT,
     877                      RTEMS_WAIT | RTEMS_EVENT_ANY,
     878                      RTEMS_NO_TIMEOUT,
     879                      &events);
     880    while ((ep->rcvDescTable[index].ctrlBits & kMALRxEmpty) == 0) {
     881      /* Got a frame */
     882      uint16_t flags = ep->rcvDescTable[index].ctrlBits;
     883      if ((flags & kEMACErrMask) != 0) {
     884        /* It has errors. Update statistics */
     885        if ((flags & kEMACOverrun) != 0)
     886          ep->rxOverrun++;
     887        if ((flags & kEMACRuntPkt) != 0)
     888          ep->rxRunt++;
     889        if ((flags & kEMACBadFCS) != 0)
     890          ep->rxBadCRC++;
     891        if ((flags & kEMACAlignErr) != 0)
     892          ep->rxNonOctet++;
     893        if ((flags & kEMACPktLong) != 0)
     894          ep->rxGiant++;
     895        /* and reset descriptor to empty */
     896       
     897        /* No need to get new mbufs, just reset */
     898        ep->rcvDescTable[index].adrDataSize = 0x0EEE;
     899        if (index==ep->nRxBuffers-1)
     900          ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt + kMALWrap;
     901        else
     902          ep->rcvDescTable[index].ctrlBits = kMALRxEmpty + kMALInterrupt;
     903       
     904      } else {
     905        /* Seems to be OK. Invalidate cache over the size we received */
     906        n = ep->rcvDescTable[index].adrDataSize & 0x0FFF;
     907        m = ep->rxMBufs[index];
     908        rtems_cache_invalidate_multiple_data_lines(m->m_data, (n + kCacheLineMask) & ~kCacheLineMask);
     909       
     910        /* Consider copying small packets out of the cluster into m_pktdat to save clusters? */
     911        m->m_len = n;
     912         
     913        /* Jumbo packets will span multiple mbufs; chain them together and submit when we get the last one */
     914        if (flags & kMALRxFirst) {
     915          /* First mbuf in the packet */
     916          if (mstart!=NULL)
     917            rtems_panic("first, no last");
     918         
     919          /* Adjust the mbuf pointers to skip the header and set eh to point to it */
     920          m->m_len -= sizeof(struct ether_header);
     921          m->m_pkthdr.len = m->m_len;
     922          eh = mtod (m, struct ether_header *);
     923          m->m_data += sizeof(struct ether_header);
     924          mstart = m;
     925          mlast = m;
     926          mdex = index;
     927        } else {
     928          /* Chain onto mstart: add length to pkthdr.len */
     929          if (mstart == NULL)
     930            rtems_panic("last, no first");
     931         
     932          mstart->m_pkthdr.len += n;
     933          m->m_flags &= ~M_PKTHDR;
     934          mlast->m_next = m;
     935          mlast = m;
     936        }
     937       
     938        if (flags & kMALLast) {
     939          /* Last mbuf in the packet: pass base of the chain to a higher level */
     940          ether_input (ifp, eh, mstart);
     941         
     942          /* ether_input took the chain, set up new mbufs in the slots we used */
     943          mdex -= 1;
     944          do {
     945            if (++mdex==ep->nRxBuffers) mdex = 0;
     946            MakeRxBuffer(ep,mdex);
     947          } while (mdex != index);
     948          mstart = NULL;
     949          mlast = NULL;
     950          eh = NULL;
     951        }
     952      }
     953      index += 1;
     954      if (index == ep->nRxBuffers) index = 0;
     955    }
     956  }
    952957}
    953958
     
    957962/* Initialise the hardware, create and start the transmit and receive tasks */
    958963{
    959         char txName[] = "ETx0";
    960         char rxName[] = "ERx0";
    961        
    962         EMACLocals* ep = (EMACLocals*)p;
    963         if (ep->txDaemonTid == 0) {
    964                 ppc405_emac_initialize_hardware(ep);
    965                 rxName[3] += ep->phyAddr;
    966                 ep->rxDaemonTid = rtems_bsdnet_newproc (rxName, 4096, ppc405_emac_rxDaemon, ep);
    967                 txName[3] += ep->phyAddr;
    968                 ep->txDaemonTid = rtems_bsdnet_newproc (txName, 4096, ppc405_emac_txDaemon, ep);
    969         }
    970         /* Only set IFF_RUNNING if the PHY is ready. If not set the watchdog timer running so we check it */
    971         if ( GetPHYLinkState(ep) & kELinkUp )
    972                 ep->arpcom.ac_if.if_flags |= IFF_RUNNING;
    973         else
    974                 ep->arpcom.ac_if.if_timer = 1;
     964  char txName[] = "ETx0";
     965  char rxName[] = "ERx0";
     966 
     967  EMACLocals* ep = (EMACLocals*)p;
     968  if (ep->txDaemonTid == 0) {
     969    ppc405_emac_initialize_hardware(ep);
     970    rxName[3] += ep->phyAddr;
     971    ep->rxDaemonTid = rtems_bsdnet_newproc (rxName, 4096, ppc405_emac_rxDaemon, ep);
     972    txName[3] += ep->phyAddr;
     973    ep->txDaemonTid = rtems_bsdnet_newproc (txName, 4096, ppc405_emac_txDaemon, ep);
     974  }
     975  /* Only set IFF_RUNNING if the PHY is ready. If not set the watchdog timer running so we check it */
     976  if ( GetPHYLinkState(ep) & kELinkUp )
     977    ep->arpcom.ac_if.if_flags |= IFF_RUNNING;
     978  else
     979    ep->arpcom.ac_if.if_timer = 1;
    975980}
    976981
     
    978983/* Send a packet: send an event to the transmit task, waking it up */
    979984{
    980         EMACLocals* ep = ifp->if_softc;
    981         rtems_event_send (ep->txDaemonTid, START_TRANSMIT_EVENT);
    982         ifp->if_flags |= IFF_OACTIVE;
     985  EMACLocals* ep = ifp->if_softc;
     986  rtems_event_send (ep->txDaemonTid, START_TRANSMIT_EVENT);
     987  ifp->if_flags |= IFF_OACTIVE;
    983988}
    984989
    985990static void ppc405_emac_stop (EMACLocals* ep)
    986991{
    987         uint32_t mask;
    988        
    989         mask = 0x80000000 >> ep->arpcom.ac_if.if_unit;
    990         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCARR,mask);
    991         PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCARR,mask);
    992         ppc405_emac_disable(ep);
    993         /* *** delete daemons, or do they exit themselves? */
    994         ep->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
     992  uint32_t mask;
     993 
     994  mask = 0x80000000 >> ep->arpcom.ac_if.if_unit;
     995  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_TXCARR,mask);
     996  PPC_SET_DEVICE_CONTROL_REGISTER(MAL0_RXCARR,mask);
     997  ppc405_emac_disable(ep);
     998  /* *** delete daemons, or do they exit themselves? */
     999  ep->arpcom.ac_if.if_flags &= ~IFF_RUNNING;
    9951000}
    9961001
     
    9991004{
    10001005
    1001         printf ("  Rx Interrupts:%-8lu", ep->rxInterrupts);
    1002         printf ("          Giant:%-8lu", ep->rxGiant);
    1003         printf ("           Runt:%-8lu\n", ep->rxRunt);
    1004         printf ("      Non-octet:%-8lu", ep->rxNonOctet);
    1005         printf ("        Bad CRC:%-8lu", ep->rxBadCRC);
    1006         printf ("        Overrun:%-8lu\n", ep->rxOverrun);
    1007 
    1008         printf ("    Tx Interrupts:%-8lu", ep->txInterrupts);
    1009         printf ("    Long deferral:%-8lu", ep->txDeferred);
    1010         printf ("       No Carrier:%-8lu\n", ep->txLostCarrier);
    1011         printf ("   Late collision:%-8lu", ep->txLateCollision);
    1012         printf ("    One collision:%-8lu", ep->txOneCollision);
    1013         printf ("  Many collisions:%-8lu\n", ep->txMultiCollision);
    1014         printf ("Excess collisions:%-8lu", ep->txTooManyCollision);
    1015         printf ("         Underrun:%-8lu", ep->txUnderrun);
    1016         printf ("      Poor signal:%-8lu\n", ep->txPoorSignal);
     1006  printf ("  Rx Interrupts:%-8lu", ep->rxInterrupts);
     1007  printf ("          Giant:%-8lu", ep->rxGiant);
     1008  printf ("           Runt:%-8lu\n", ep->rxRunt);
     1009  printf ("      Non-octet:%-8lu", ep->rxNonOctet);
     1010  printf ("        Bad CRC:%-8lu", ep->rxBadCRC);
     1011  printf ("        Overrun:%-8lu\n", ep->rxOverrun);
     1012
     1013  printf ("    Tx Interrupts:%-8lu", ep->txInterrupts);
     1014  printf ("    Long deferral:%-8lu", ep->txDeferred);
     1015  printf ("       No Carrier:%-8lu\n", ep->txLostCarrier);
     1016  printf ("   Late collision:%-8lu", ep->txLateCollision);
     1017  printf ("    One collision:%-8lu", ep->txOneCollision);
     1018  printf ("  Many collisions:%-8lu\n", ep->txMultiCollision);
     1019  printf ("Excess collisions:%-8lu", ep->txTooManyCollision);
     1020  printf ("         Underrun:%-8lu", ep->txUnderrun);
     1021  printf ("      Poor signal:%-8lu\n", ep->txPoorSignal);
    10171022}
    10181023#endif
     
    10201025static int UpdateMulticast(EMACLocals* ep)
    10211026{
    1022         /* Traverse list of multicast addresses and update hardware hash filter. This is just a work-reduction */
    1023         /* step; the filter uses a hash of the hardware address and therefore doesn't catch all unwanted packets */
    1024         /* We have to do other checks in software. */
    1025         /* 405GP/GPr has 4x16-bit hash registers, 405EX/EXr has 8x32-bit */
    1026        
    1027         struct ether_multi* enm;
    1028         struct ether_multistep step;
    1029         uint32_t hash;
    1030        
    1031         #ifdef qMultiDebug
    1032                 printf("\nMulticast etheraddrs:\n");
    1033         #endif
    1034        
    1035         ETHER_FIRST_MULTI(step, &ep->arpcom, enm);
    1036         while (enm != NULL) {
    1037                
    1038                 /* *** Doesn't implement ranges */
    1039                                
    1040                 hash = ether_crc32_be( (uint8_t*)&enm->enm_addrlo, sizeof(enm->enm_addrlo) );
    1041                 if (get_ppc_cpu_type() == PPC_405EX) {
    1042                         hash >>= 24;    /* Upper 8 bits, split 3/5 */
    1043                         /* This has been experimentally verified against the hardware */
    1044                         ep->EMAC->e_groupHash[7-(hash>>5)] |= (1 << (hash & 0x1F));
    1045                 } else {
    1046                         hash >>= 26;    /* Upper 6 bits, split 2/4 */
    1047                         /* This has not been checked */
    1048                         ep->EMAC->g_groupHash[3-(hash>>6)] |= (1 << (hash & 0xF));
    1049                 }
    1050                
    1051                 #ifdef qMultiDebug
    1052                         printf("  ");
    1053                         printaddr(enm->enm_addrlo);
    1054                         printf(" = bit %d",hash);
    1055                         if (memcmp(&enm->enm_addrlo, &enm->enm_addrhi, 6) != 0) {
    1056                                 printf(" - ");
    1057                                 printaddr(enm->enm_addrhi);
    1058                                 printf(" [not supported]");
    1059                         }
    1060                         printf("\n");
    1061                 #endif
    1062                
    1063                 ETHER_NEXT_MULTI(step, enm);
    1064         }
    1065         #ifdef qMultiDebug
    1066         {
    1067                 int i;
    1068                 printf(" Grouphash is ");
    1069                 for (i=0; i<8; i++)
    1070                         printf("%08X:",(int)ep->EMAC->e_groupHash[i]);
    1071                 printf("\n");
    1072         }
    1073         #endif
    1074         return 0;
     1027  /* Traverse list of multicast addresses and update hardware hash filter. This is just a work-reduction */
     1028  /* step; the filter uses a hash of the hardware address and therefore doesn't catch all unwanted packets */
     1029  /* We have to do other checks in software. */
     1030  /* 405GP/GPr has 4x16-bit hash registers, 405EX/EXr has 8x32-bit */
     1031 
     1032  struct ether_multi* enm;
     1033  struct ether_multistep step;
     1034  uint32_t hash;
     1035 
     1036  #ifdef qMultiDebug
     1037    printf("\nMulticast etheraddrs:\n");
     1038  #endif
     1039 
     1040  ETHER_FIRST_MULTI(step, &ep->arpcom, enm);
     1041  while (enm != NULL) {
     1042   
     1043    /* *** Doesn't implement ranges */
     1044       
     1045    hash = ether_crc32_be( (uint8_t*)&enm->enm_addrlo, sizeof(enm->enm_addrlo) );
     1046    if (get_ppc_cpu_type() == PPC_405EX) {
     1047      hash >>= 24;  /* Upper 8 bits, split 3/5 */
     1048      /* This has been experimentally verified against the hardware */
     1049      ep->EMAC->e_groupHash[7-(hash>>5)] |= (1 << (hash & 0x1F));
     1050    } else {
     1051      hash >>= 26;  /* Upper 6 bits, split 2/4 */
     1052      /* This has not been checked */
     1053      ep->EMAC->g_groupHash[3-(hash>>6)] |= (1 << (hash & 0xF));
     1054    }
     1055   
     1056    #ifdef qMultiDebug
     1057      printf("  ");
     1058      printaddr(enm->enm_addrlo);
     1059      printf(" = bit %d",hash);
     1060      if (memcmp(&enm->enm_addrlo, &enm->enm_addrhi, 6) != 0) {
     1061        printf(" - ");
     1062        printaddr(enm->enm_addrhi);
     1063        printf(" [not supported]");
     1064      }
     1065      printf("\n");
     1066    #endif
     1067   
     1068    ETHER_NEXT_MULTI(step, enm);
     1069  }
     1070  #ifdef qMultiDebug
     1071  {
     1072    int i;
     1073    printf(" Grouphash is ");
     1074    for (i=0; i<8; i++)
     1075      printf("%08X:",(int)ep->EMAC->e_groupHash[i]);
     1076    printf("\n");
     1077  }
     1078  #endif
     1079  return 0;
    10751080}
    10761081
     
    10781083static int ppc405_emac_ioctl (struct ifnet *ifp, ioctl_command_t command, caddr_t data)
    10791084{
    1080         int error = 0;
    1081         EMACLocals* ep = ifp->if_softc;
    1082         struct ifreq* reqP = (struct ifreq *) data;
    1083                
    1084         switch (command) {
    1085        
    1086                 case SIOCSIFFLAGS:
    1087                         switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
    1088                                 case IFF_RUNNING:
    1089                                         ppc405_emac_stop(ep);
    1090                                         break;
    1091                
    1092                                 case IFF_UP:
    1093                                         ppc405_emac_init(ep);
    1094                                         break;
    1095                
    1096                                 case IFF_UP | IFF_RUNNING:
    1097                                         ppc405_emac_stop(ep);
    1098                                         ppc405_emac_init(ep);
    1099                                         break;
    1100                
    1101                                 default:
    1102                                         break;
    1103                         }
    1104                         break;
    1105        
    1106                 case SIOCADDMULTI: {
    1107                                 error = ether_addmulti( reqP, &ep->arpcom);
    1108                                 if (error==ENETRESET)
    1109                                         error = UpdateMulticast(ep);
    1110                         } break;
    1111                        
    1112                 case SIOCDELMULTI:
    1113                         error = ether_delmulti( (struct ifreq *) data, &ep->arpcom);
    1114                         if (error==ENETRESET)
    1115                                 error = UpdateMulticast(ep);
    1116                         break;
    1117                        
    1118                 case SIOCSIFMTU: {
    1119                                 /* Note that this may not do what you want; setting the interface MTU doesn't touch the route MTUs,
    1120                                    and new routes are sometimes made by cloning old ones. So this won't change the MTU to known hosts
    1121                                    and may not change the MTU to new ones either... */
    1122                                 int max;
    1123                                 if ( get_ppc_cpu_type() == PPC_405EX && (ep->EMAC->mode1 & keEMACJumbo) != 0 )
    1124                                         max = ETHER_MAX_LEN_JUMBO;
    1125                                 else
    1126                                         max = ETHER_MAX_LEN;
    1127                                 if (reqP->ifr_mtu > max - ETHER_HDR_LEN - ETHER_CRC_LEN)
    1128                                         error = EINVAL;
    1129                                 else
    1130                                         ifp->if_mtu = reqP->ifr_mtu;
    1131                         } break;
    1132                        
    1133                 case SIO_RTEMS_SHOW_STATS:
    1134                         #ifdef qDebug
    1135                                 ppc405_emac_stats(ep);
    1136                         #endif
    1137                         break;
    1138                        
    1139                 default:
    1140                         /* Not handled here, pass to generic */
    1141                         error = ether_ioctl(ifp,command,data);
    1142                         break;
    1143         }
    1144        
    1145         #ifdef qDebug
    1146         if (error != 0)
    1147                 printf("--- Ethernet ioctl %d failed %d\n",(int)command,error);
    1148         #endif
    1149        
    1150         return error;
    1151 }
    1152 
    1153        
     1085  int error = 0;
     1086  EMACLocals* ep = ifp->if_softc;
     1087  struct ifreq* reqP = (struct ifreq *) data;
     1088   
     1089  switch (command) {
     1090 
     1091    case SIOCSIFFLAGS:
     1092      switch (ifp->if_flags & (IFF_UP | IFF_RUNNING)) {
     1093        case IFF_RUNNING:
     1094          ppc405_emac_stop(ep);
     1095          break;
     1096   
     1097        case IFF_UP:
     1098          ppc405_emac_init(ep);
     1099          break;
     1100   
     1101        case IFF_UP | IFF_RUNNING:
     1102          ppc405_emac_stop(ep);
     1103          ppc405_emac_init(ep);
     1104          break;
     1105   
     1106        default:
     1107          break;
     1108      }
     1109      break;
     1110 
     1111    case SIOCADDMULTI: {
     1112        error = ether_addmulti( reqP, &ep->arpcom);
     1113        if (error==ENETRESET)
     1114          error = UpdateMulticast(ep);
     1115      } break;
     1116     
     1117    case SIOCDELMULTI:
     1118      error = ether_delmulti( (struct ifreq *) data, &ep->arpcom);
     1119      if (error==ENETRESET)
     1120        error = UpdateMulticast(ep);
     1121      break;
     1122     
     1123    case SIOCSIFMTU: {
     1124        /* Note that this may not do what you want; setting the interface MTU doesn't touch the route MTUs,
     1125           and new routes are sometimes made by cloning old ones. So this won't change the MTU to known hosts
     1126           and may not change the MTU to new ones either... */
     1127        int max;
     1128        if ( get_ppc_cpu_type() == PPC_405EX && (ep->EMAC->mode1 & keEMACJumbo) != 0 )
     1129          max = ETHER_MAX_LEN_JUMBO;
     1130        else
     1131          max = ETHER_MAX_LEN;
     1132        if (reqP->ifr_mtu > max - ETHER_HDR_LEN - ETHER_CRC_LEN)
     1133          error = EINVAL;
     1134        else
     1135          ifp->if_mtu = reqP->ifr_mtu;
     1136      } break;
     1137     
     1138    case SIO_RTEMS_SHOW_STATS:
     1139      #ifdef qDebug
     1140        ppc405_emac_stats(ep);
     1141      #endif
     1142      break;
     1143     
     1144    default:
     1145      /* Not handled here, pass to generic */
     1146      error = ether_ioctl(ifp,command,data);
     1147      break;
     1148  }
     1149 
     1150  #ifdef qDebug
     1151  if (error != 0)
     1152    printf("--- Ethernet ioctl %d failed %d\n",(int)command,error);
     1153  #endif
     1154 
     1155  return error;
     1156}
     1157
     1158 
    11541159/*----------------------- External attach function --------------------------
    11551160 * 
     
    11621167rtems_emac_driver_attach(struct rtems_bsdnet_ifconfig* config, int attaching)
    11631168{
    1164         int     unitNumber, nUnits;
    1165         char*   unitName;
    1166         struct  ifnet* ifp;
    1167         EMACLocals* ep;
    1168        
    1169         if (attaching==0) {
    1170                 printk ("EMAC: driver cannot be detached.\n");
    1171                 return 0;
    1172         }
    1173        
    1174         nUnits = 1;
    1175         if (get_ppc_cpu_type()==PPC_405EX && get_ppc_cpu_revision() > 0x1474)
    1176                 nUnits = 2;     /* PPC405EX has two interfaces, EXr has one */
    1177        
    1178         unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName);
     1169  int   unitNumber, nUnits;
     1170  char*  unitName;
     1171  struct  ifnet* ifp;
     1172  EMACLocals* ep;
     1173 
     1174  if (attaching==0) {
     1175    printk ("EMAC: driver cannot be detached.\n");
     1176    return 0;
     1177  }
     1178 
     1179  nUnits = 1;
     1180  if (get_ppc_cpu_type()==PPC_405EX && get_ppc_cpu_revision() > 0x1474)
     1181    nUnits = 2;  /* PPC405EX has two interfaces, EXr has one */
     1182 
     1183  unitNumber = rtems_bsdnet_parse_driver_name (config, &unitName);
    11791184    if (unitNumber < 0 || unitNumber > nUnits-1) {
    1180                 printk ("EMAC: bad unit number %d.\n",unitNumber);
    1181                 return 0;
    1182         }
    1183        
    1184         ep = &gEmacs[unitNumber];
    1185        
    1186         if (get_ppc_cpu_type()==PPC_405EX) {
    1187                 if (unitNumber==0) ep->EMAC = (EthernetRegisters_EX*)EMAC0EXAddress;
    1188                                           else ep->EMAC = (EthernetRegisters_GP*)EMAC1EXAddress;
    1189         } else
    1190                 ep->EMAC = (EthernetRegisters_GP*)EMAC0GPAddress;
    1191                
    1192         ifp = &ep->arpcom.ac_if;
    1193         if (ifp->if_softc != NULL) {
    1194                 printk ("EMAC: driver already in use.\n");
    1195                 return 0;
    1196         }
    1197         ifp->if_softc = ep;
    1198        
    1199         if (config->hardware_address == 0)
    1200                 rtems_panic("No Ethernet MAC address specified!");
    1201         memcpy (ep->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
    1202        
    1203         ifp->if_name = unitName;
    1204         ifp->if_unit = unitNumber;
    1205        
    1206         if (config->mtu != 0)
    1207                 ifp->if_mtu = config->mtu;
    1208         else
    1209                 ifp->if_mtu = ETHERMTU;         /* May be adjusted later by ppc405_emac_phy_adapt() */
    1210                
    1211         ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
    1212         if (ifp->if_snd.ifq_maxlen == 0)
    1213                 ifp->if_snd.ifq_maxlen = ifqmaxlen;
    1214         ifp->if_init = &ppc405_emac_init;
    1215         ifp->if_ioctl = ppc405_emac_ioctl;
    1216         ifp->if_start = ppc405_emac_start;
    1217         ifp->if_output = ether_output;
    1218         ifp->if_watchdog = ppc405_emac_watchdog;
    1219         ifp->if_timer    = 0;
    1220        
    1221         if (config->rbuf_count != 0) {
    1222                 if (config->rbuf_count > 256) ep->nRxBuffers = 256;
    1223                                                                 else ep->nRxBuffers = config->rbuf_count;
    1224         } else
    1225                 ep->nRxBuffers = nmbclusters/2;
    1226                
    1227         ep->phyAddr = unitNumber+1;
    1228         ep->phyState = 0;
    1229        
    1230         #ifdef qDebug
    1231                 printf("\n  Setting up EMAC %d of %d\n",unitNumber+1,nUnits);
    1232                 printf("  MAC address is ");
    1233                 printaddr(ep->arpcom.ac_enaddr);
    1234                 printf("  MHLEN = %d, MINCLSIZE = %d MCLBYTES = %d\n",MHLEN,MINCLSIZE,MCLBYTES);
    1235                 printf("  ticks/sec = %d, usec/tick = %d\n", rtems_bsdnet_ticks_per_second, rtems_bsdnet_microseconds_per_tick);
    1236         #endif
    1237        
    1238         if_attach (ifp);
    1239         ether_ifattach (ifp);
    1240 
    1241         return 1;
    1242 }
    1243 
     1185    printk ("EMAC: bad unit number %d.\n",unitNumber);
     1186    return 0;
     1187  }
     1188 
     1189  ep = &gEmacs[unitNumber];
     1190 
     1191  if (get_ppc_cpu_type()==PPC_405EX) {
     1192    if (unitNumber==0) ep->EMAC = (EthernetRegisters_EX*)EMAC0EXAddress;
     1193            else ep->EMAC = (EthernetRegisters_GP*)EMAC1EXAddress;
     1194  } else
     1195    ep->EMAC = (EthernetRegisters_GP*)EMAC0GPAddress;
     1196   
     1197  ifp = &ep->arpcom.ac_if;
     1198  if (ifp->if_softc != NULL) {
     1199    printk ("EMAC: driver already in use.\n");
     1200    return 0;
     1201  }
     1202  ifp->if_softc = ep;
     1203 
     1204  if (config->hardware_address == 0)
     1205    rtems_panic("No Ethernet MAC address specified!");
     1206  memcpy (ep->arpcom.ac_enaddr, config->hardware_address, ETHER_ADDR_LEN);
     1207 
     1208  ifp->if_name = unitName;
     1209  ifp->if_unit = unitNumber;
     1210 
     1211  if (config->mtu != 0)
     1212    ifp->if_mtu = config->mtu;
     1213  else
     1214    ifp->if_mtu = ETHERMTU;    /* May be adjusted later by ppc405_emac_phy_adapt() */
     1215   
     1216  ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST;
     1217  if (ifp->if_snd.ifq_maxlen == 0)
     1218    ifp->if_snd.ifq_maxlen = ifqmaxlen;
     1219  ifp->if_init = &ppc405_emac_init;
     1220  ifp->if_ioctl = ppc405_emac_ioctl;
     1221  ifp->if_start = ppc405_emac_start;
     1222  ifp->if_output = ether_output;
     1223  ifp->if_watchdog = ppc405_emac_watchdog;
     1224  ifp->if_timer  = 0;
     1225 
     1226  if (config->rbuf_count != 0) {
     1227    if (config->rbuf_count > 256) ep->nRxBuffers = 256;
     1228                else ep->nRxBuffers = config->rbuf_count;
     1229  } else
     1230    ep->nRxBuffers = nmbclusters/2;
     1231   
     1232  ep->phyAddr = unitNumber+1;
     1233  ep->phyState = 0;
     1234 
     1235  #ifdef qDebug
     1236    printf("\n  Setting up EMAC %d of %d\n",unitNumber+1,nUnits);
     1237    printf("  MAC address is ");
     1238    printaddr(ep->arpcom.ac_enaddr);
     1239    printf("  MHLEN = %d, MINCLSIZE = %d MCLBYTES = %d\n",MHLEN,MINCLSIZE,MCLBYTES);
     1240    printf("  ticks/sec = %d, usec/tick = %d\n", rtems_bsdnet_ticks_per_second, rtems_bsdnet_microseconds_per_tick);
     1241   #endif
     1242 
     1243   if_attach (ifp);
     1244  ether_ifattach (ifp);
     1245
     1246  return 1;
     1247}
     1248
Note: See TracChangeset for help on using the changeset viewer.