|
|
1.1 ! root 1: /* ! 2: * Copyright (c) 2000 Apple Computer, Inc. All rights reserved. ! 3: * ! 4: * @APPLE_LICENSE_HEADER_START@ ! 5: * ! 6: * The contents of this file constitute Original Code as defined in and ! 7: * are subject to the Apple Public Source License Version 1.1 (the ! 8: * "License"). You may not use this file except in compliance with the ! 9: * License. Please obtain a copy of the License at ! 10: * http://www.apple.com/publicsource and read it before using this file. ! 11: * ! 12: * This Original Code and all software distributed under the License are ! 13: * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER ! 14: * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, ! 15: * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, ! 16: * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the ! 17: * License for the specific language governing rights and limitations ! 18: * under the License. ! 19: * ! 20: * @APPLE_LICENSE_HEADER_END@ ! 21: */ ! 22: /* ! 23: * MACE Device-dependent code (some still lives in if_en.c): ! 24: * ! 25: * MACE Multicast Address scheme - ! 26: * Compute Enet CRC for each Mcast address; take high 6 bits of 32-bit ! 27: * crc, giving a "bit index" into a 64-bit register. On packet receipt, ! 28: * if corresponding bit is set, accept packet. ! 29: * We keep track of requests in a per-hash-value table (16-bit counters ! 30: * should be sufficient). Since we're hashing, we only care about the ! 31: * hash value of each address. ! 32: * ! 33: * Apple Confidential ! 34: * ! 35: * (C) COPYRIGHT Apple Computer, Inc., 1994-1997 ! 36: * All Rights Reserved ! 37: * ! 38: * Justin C. Walker ! 39: */ ! 40: #include <machdep/ppc/dbdma.h> ! 41: ! 42: #import <sys/types.h> ! 43: #import <sys/param.h> ! 44: #import <sys/errno.h> ! 45: #import <sys/socket.h> ! 46: #import <net/if.h> ! 47: #import <net/etherdefs.h> ! 48: #import <netinet/if_ether.h> ! 49: #import <sys/sockio.h> ! 50: #import <netinet/in_var.h> ! 51: #import <netinet/in.h> ! 52: #import <sys/mbuf.h> ! 53: #import <mach/mach_types.h> ! 54: #import <ppc/powermac.h> ! 55: #import <ppc/interrupts.h> ! 56: #import <ppc/proc_reg.h> ! 57: #include <libkern/libkern.h> ! 58: #import "if_en.h" ! 59: #import "mace.h" ! 60: ! 61: extern mace_t mace; ! 62: ! 63: #define ENET_CRCPOLY 0x04c11db7 ! 64: ! 65: /* Real fast bit-reversal algorithm, 6-bit values */ ! 66: int reverse6[] = ! 67: { 0x0,0x20,0x10,0x30,0x8,0x28,0x18,0x38, ! 68: 0x4,0x24,0x14,0x34,0xc,0x2c,0x1c,0x3c, ! 69: 0x2,0x22,0x12,0x32,0xa,0x2a,0x1a,0x3a, ! 70: 0x6,0x26,0x16,0x36,0xe,0x2e,0x1e,0x3e, ! 71: 0x1,0x21,0x11,0x31,0x9,0x29,0x19,0x39, ! 72: 0x5,0x25,0x15,0x35,0xd,0x2d,0x1d,0x3d, ! 73: 0x3,0x23,0x13,0x33,0xb,0x2b,0x1b,0x3b, ! 74: 0x7,0x27,0x17,0x37,0xf,0x2f,0x1f,0x3f ! 75: }; ! 76: ! 77: unsigned int crc416(current, nxtval) ! 78: register unsigned int current; ! 79: register unsigned short nxtval; ! 80: { register unsigned int counter; ! 81: register int highCRCBitSet, lowDataBitSet; ! 82: ! 83: /* Swap bytes */ ! 84: nxtval = ((nxtval & 0x00FF) << 8) | (nxtval >> 8); ! 85: ! 86: /* Compute bit-by-bit */ ! 87: for (counter = 0; counter != 16; ++counter) ! 88: { /* is high CRC bit set? */ ! 89: if ((current & 0x80000000) == NULL) ! 90: highCRCBitSet = 0; ! 91: else ! 92: highCRCBitSet = 1; ! 93: ! 94: current = current << 1; ! 95: ! 96: if ((nxtval & 0x0001) == NULL) ! 97: lowDataBitSet = 0; ! 98: else ! 99: lowDataBitSet = 1; ! 100: ! 101: nxtval = nxtval >> 1; ! 102: ! 103: /* do the XOR */ ! 104: if (highCRCBitSet ^ lowDataBitSet) ! 105: current = current ^ ENET_CRCPOLY; ! 106: } ! 107: return current; ! 108: } ! 109: ! 110: unsigned int mace_crc(unsigned short *address) ! 111: { register unsigned int newcrc; ! 112: ! 113: newcrc = crc416(0xffffffff, *address); /* address bits 47 - 32 */ ! 114: newcrc = crc416(newcrc, address[1]); /* address bits 31 - 16 */ ! 115: newcrc = crc416(newcrc, address[2]); /* address bits 15 - 0 */ ! 116: ! 117: return(newcrc); ! 118: } ! 119: ! 120: /* ! 121: * Add requested mcast addr to Mace's filter. Assume that the first ! 122: * address in the arpcom ac_multiaddrs list is the one we're interested in. ! 123: */ ! 124: int ! 125: mace_addmulti(register struct ifreq *ifr, register struct arpcom *ar) ! 126: { register unsigned char *addr; ! 127: unsigned int crc; ! 128: unsigned char mask; ! 129: ! 130: addr = ar->ac_multiaddrs->enm_addrlo; ! 131: ! 132: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 133: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 134: if (mace.multi_use[crc]++) ! 135: return(0); /* This bit is already set */ ! 136: mask = crc % 8; ! 137: mask = (unsigned char)1 << mask; ! 138: mace.multi_mask[crc/8] |= mask; ! 139: return(1); ! 140: } ! 141: ! 142: int ! 143: mace_delmulti(register struct ifreq *ifr, register struct arpcom *ar, ! 144: struct ether_addr * enaddr) ! 145: { register unsigned char *addr; ! 146: unsigned int crc; ! 147: unsigned char mask; ! 148: ! 149: addr = (char *)enaddr; /* XXX assumes addrlo == addrhi */ ! 150: ! 151: /* Now, delete the address from the filter copy, as indicated */ ! 152: crc = mace_crc((unsigned short *)addr)&0x3f; /* Big-endian alert! */ ! 153: crc = reverse6[crc]; /* Hyperfast bit-reversing algorithm */ ! 154: if (mace.multi_use[crc] == 0) ! 155: return(EINVAL); /* That bit wasn't in use! */ ! 156: ! 157: if (--mace.multi_use[crc]) ! 158: return(0); /* That bit is still in use */ ! 159: ! 160: mask = crc % 8; ! 161: mask = ((unsigned char)1 << mask) ^ 0xff; /* To turn off bit */ ! 162: mace.multi_mask[crc/8] &= mask; ! 163: return(1); ! 164: } ! 165: ! 166: /* ! 167: * Sync the adapter with the software copy of the multicast mask ! 168: * (logical address filter). ! 169: * If we want all m-cast addresses, we just blast 1's into the filter. ! 170: * When we reverse this, we can use the current state of the (software) ! 171: * filter, which should have been kept up to date. ! 172: */ ! 173: void ! 174: mace_sync_mcast(register struct ifnet * ifp) ! 175: { register unsigned long temp, temp1; ! 176: register int i; ! 177: register char *p; ! 178: register struct mace_board *ereg = mace.ereg; ! 179: ! 180: temp = ereg->maccc; ! 181: ! 182: /* ! 183: * Have to deal with early rev of chip for updating LAF ! 184: * Don't know if any MacOSX systems still run this rev. ! 185: */ ! 186: if (mace.chip_id == MACERevA2) ! 187: { /* First, turn off receiver */ ! 188: temp1 = temp&~MACCC_ENRCV; ! 189: ereg->maccc = temp1; ! 190: eieio(); ! 191: ! 192: /* Then, check FIFO - frame being received will complete */ ! 193: temp1 = ereg->fifofc; ! 194: ! 195: mace.ereg->iac = IAC_LOGADDR; ! 196: eieio(); ! 197: } else ! 198: { ereg->iac = IAC_ADDRCHG|IAC_LOGADDR; ! 199: eieio(); ! 200: ! 201: while (temp1 = ereg->iac) ! 202: { eieio(); ! 203: if ((temp1&IAC_ADDRCHG) == 0) ! 204: break; ! 205: } ! 206: } ! 207: ! 208: if (ifp->if_flags & IFF_ALLMULTI) /* Then want ALL m-cast pkts */ ! 209: { /* set mask to all 1's */ ! 210: for (i=0;i<8;i++) ! 211: { ereg->ladrf = 0xff; ! 212: eieio(); ! 213: } ! 214: } else ! 215: { ! 216: /* Assuming everything is big-endian */ ! 217: for (i=0, p = &mace.multi_mask[0];i<8;i++) ! 218: { ereg->ladrf = *p++; ! 219: eieio(); ! 220: } ! 221: } ! 222: ! 223: ereg->maccc = temp; /* Reset config ctrlr */ ! 224: eieio(); ! 225: ! 226: } ! 227: ! 228: void ! 229: mace_sync_promisc(register struct ifnet *ifp) ! 230: { ! 231: register u_long o_maccc, n_maccc; ! 232: register struct mace_board *ereg = mace.ereg; ! 233: ! 234: /* ! 235: * Save current state and disable receive. ! 236: */ ! 237: o_maccc = ereg->maccc; ! 238: n_maccc = o_maccc & ~MACCC_ENRCV; ! 239: ereg->maccc = n_maccc; ! 240: eieio(); ! 241: ! 242: /* ! 243: * Calculate new desired state ! 244: */ ! 245: if (ifp->if_flags & IFF_PROMISC) { ! 246: /* set PROMISC bit */ ! 247: o_maccc |= MACCC_PROM; ! 248: } else { ! 249: /* clear PROMISC bit */ ! 250: o_maccc &= ~MACCC_PROM; ! 251: } ! 252: ! 253: /* ! 254: * Note that the "old" mode includes the new promiscuous state now. ! 255: */ ! 256: ereg->maccc = o_maccc; ! 257: eieio(); ! 258: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.