]> git.saurik.com Git - apple/xnu.git/blob - bsd/if/ppc/mace.c
b66ddd3e982889106b8c0e221d4641dc9b1b8de2
[apple/xnu.git] / bsd / if / ppc / mace.c
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 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/errno.h>
45 #include <sys/socket.h>
46 #include <net/if.h>
47 #include <net/etherdefs.h>
48 #include <netinet/if_ether.h>
49 #include <sys/sockio.h>
50 #include <netinet/in_var.h>
51 #include <netinet/in.h>
52 #include <sys/mbuf.h>
53 #include <mach/mach_types.h>
54 #include <ppc/powermac.h>
55 #include <ppc/interrupts.h>
56 #include <ppc/proc_reg.h>
57 #include <libkern/libkern.h>
58 #include "if_en.h"
59 #include "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 }