#include <machdep/ppc/dbdma.h>
#include <sys/types.h>
#include <sys/param.h>
#include <sys/errno.h>
#include <sys/socket.h>
#include <net/if.h>
#include <net/etherdefs.h>
#include <netinet/if_ether.h>
#include <sys/sockio.h>
#include <netinet/in_var.h>
#include <netinet/in.h>
#include <sys/mbuf.h>
#include <mach/mach_types.h>
#include <ppc/powermac.h>
#include <ppc/interrupts.h>
#include <ppc/proc_reg.h>
#include <libkern/libkern.h>
#include "if_en.h"
#include "mace.h"
extern mace_t mace;
#define ENET_CRCPOLY 0x04c11db7
int reverse6[] =
{ 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38,
0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c,
0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a,
0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e,
0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39,
0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d,
0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b,
0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f
};
unsigned int crc416(current, nxtval)
register unsigned int current;
register unsigned short nxtval;
{ register unsigned int counter;
register int highCRCBitSet, lowDataBitSet;
nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8);
for (counter = 0; counter != 16; ++counter)
{
if ((current & 0x80000000) == NULL)
highCRCBitSet = 0;
else
highCRCBitSet = 1;
current = current << 1;
if ((nxtval & 0x0001) == NULL)
lowDataBitSet = 0;
else
lowDataBitSet = 1;
nxtval = nxtval >> 1;
if (highCRCBitSet ^ lowDataBitSet)
current = current ^ ENET_CRCPOLY;
}
return current;
}
unsigned int mace_crc(unsigned short *address)
{ register unsigned int newcrc;
newcrc = crc416(0xffffffff, *address);
newcrc = crc416(newcrc, address[1]);
newcrc = crc416(newcrc, address[2]);
return(newcrc);
}
int
mace_addmulti(register struct ifreq *ifr, register struct arpcom *ar)
{ register unsigned char *addr;
unsigned int crc;
unsigned char mask;
addr = ar->ac_multiaddrs->enm_addrlo;
crc = mace_crc((unsigned short *)addr)&0x3f;
crc = reverse6[crc];
if (mace.multi_use[crc]++)
return(0);
mask = crc % 8;
mask = (unsigned char)1 << mask;
mace.multi_mask[crc/8] |= mask;
return(1);
}
int
mace_delmulti(register struct ifreq *ifr, register struct arpcom *ar,
struct ether_addr * enaddr)
{ register unsigned char *addr;
unsigned int crc;
unsigned char mask;
addr = (char *)enaddr;
crc = mace_crc((unsigned short *)addr)&0x3f;
crc = reverse6[crc];
if (mace.multi_use[crc] == 0)
return(EINVAL);
if (--mace.multi_use[crc])
return(0);
mask = crc % 8;
mask = ((unsigned char)1 << mask) ^ 0xff;
mace.multi_mask[crc/8] &= mask;
return(1);
}
void
mace_sync_mcast(register struct ifnet * ifp)
{ register unsigned long temp, temp1;
register int i;
register char *p;
register struct mace_board *ereg = mace.ereg;
temp = ereg->maccc;
if (mace.chip_id == MACERevA2)
{
temp1 = temp&~MACCC_ENRCV;
ereg->maccc = temp1;
eieio();
temp1 = ereg->fifofc;
mace.ereg->iac = IAC_LOGADDR;
eieio();
} else
{ ereg->iac = IAC_ADDRCHG|IAC_LOGADDR;
eieio();
while (temp1 = ereg->iac)
{ eieio();
if ((temp1&IAC_ADDRCHG) == 0)
break;
}
}
if (ifp->if_flags & IFF_ALLMULTI)
{
for (i=0;i<8;i++)
{ ereg->ladrf = 0xff;
eieio();
}
} else
{
for (i=0, p = &mace.multi_mask[0];i<8;i++)
{ ereg->ladrf = *p++;
eieio();
}
}
ereg->maccc = temp;
eieio();
}
void
mace_sync_promisc(register struct ifnet *ifp)
{
register u_long o_maccc, n_maccc;
register struct mace_board *ereg = mace.ereg;
o_maccc = ereg->maccc;
n_maccc = o_maccc & ~MACCC_ENRCV;
ereg->maccc = n_maccc;
eieio();
if (ifp->if_flags & IFF_PROMISC) {
o_maccc |= MACCC_PROM;
} else {
o_maccc &= ~MACCC_PROM;
}
ereg->maccc = o_maccc;
eieio();
}