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