]>
Commit | Line | Data |
---|---|---|
c609719b WD |
1 | #include <common.h> |
2 | #include <malloc.h> | |
3 | #include <galileo/gt64260R.h> | |
4 | #include <galileo/core.h> | |
5 | #include <asm/cache.h> | |
6 | #include "eth.h" | |
7 | #include "eth_addrtbl.h" | |
8 | ||
9 | #define TRUE 1 | |
10 | #define FALSE 0 | |
11 | ||
12 | #define PRINTF printf | |
13 | ||
14 | #ifdef CONFIG_GT_USE_MAC_HASH_TABLE | |
15 | ||
bf9e3b38 WD |
16 | static u32 addressTableHashMode[GAL_ETH_DEVS] = { 0, }; |
17 | static u32 addressTableHashSize[GAL_ETH_DEVS] = { 0, }; | |
18 | static addrTblEntry *addressTableBase[GAL_ETH_DEVS] = { 0, }; | |
19 | static void *realAddrTableBase[GAL_ETH_DEVS] = { 0, }; | |
20 | ||
21 | static const u32 hashLength[2] = { | |
22 | (0x8000), /* 8K * 4 entries */ | |
23 | (0x8000 / 16), /* 512 * 4 entries */ | |
c609719b WD |
24 | }; |
25 | ||
26 | /* Initialize the address table for a port, if needed */ | |
bf9e3b38 | 27 | unsigned int initAddressTable (u32 port, u32 hashMode, u32 hashSizeSelector) |
c609719b | 28 | { |
bf9e3b38 | 29 | unsigned int tableBase; |
c609719b | 30 | |
bf9e3b38 WD |
31 | if (port < 0 || port >= GAL_ETH_DEVS) { |
32 | printf ("%s: Invalid port number %d\n", __FUNCTION__, port); | |
c609719b WD |
33 | return 0; |
34 | } | |
35 | ||
36 | if (hashMode > 1) { | |
bf9e3b38 | 37 | printf ("%s: Invalid Hash Mode %d\n", __FUNCTION__, port); |
c609719b WD |
38 | return 0; |
39 | } | |
40 | ||
bf9e3b38 WD |
41 | if (realAddrTableBase[port] && |
42 | (addressTableHashSize[port] != hashSizeSelector)) { | |
c609719b WD |
43 | /* we have been here before, |
44 | * but now we want a different sized table | |
45 | */ | |
bf9e3b38 | 46 | free (realAddrTableBase[port]); |
c609719b WD |
47 | realAddrTableBase[port] = 0; |
48 | addressTableBase[port] = 0; | |
49 | ||
50 | } | |
51 | ||
bf9e3b38 | 52 | tableBase = (unsigned int) addressTableBase[port]; |
c609719b | 53 | /* we get called for every probe, so only do this once */ |
bf9e3b38 WD |
54 | if (!tableBase) { |
55 | int bytes = | |
56 | hashLength[hashSizeSelector] * sizeof (addrTblEntry); | |
c609719b | 57 | |
77ddac94 | 58 | realAddrTableBase[port] = |
bf9e3b38 | 59 | malloc (bytes + 64); |
77ddac94 | 60 | tableBase = (unsigned int)realAddrTableBase; |
c609719b | 61 | |
bf9e3b38 WD |
62 | if (!tableBase) { |
63 | printf ("%s: alloc memory failed \n", __FUNCTION__); | |
c609719b WD |
64 | return 0; |
65 | } | |
66 | ||
bf9e3b38 WD |
67 | /* align to octal byte */ |
68 | if (tableBase & 63) | |
69 | tableBase = (tableBase + 63) & ~63; | |
c609719b | 70 | |
bf9e3b38 WD |
71 | addressTableHashMode[port] = hashMode; |
72 | addressTableHashSize[port] = hashSizeSelector; | |
73 | addressTableBase[port] = (addrTblEntry *) tableBase; | |
c609719b | 74 | |
bf9e3b38 | 75 | memset ((void *) tableBase, 0, bytes); |
c609719b WD |
76 | } |
77 | ||
bf9e3b38 | 78 | return tableBase; |
c609719b WD |
79 | } |
80 | ||
81 | /* | |
82 | * ---------------------------------------------------------------------------- | |
83 | * This function will calculate the hash function of the address. | |
84 | * depends on the hash mode and hash size. | |
85 | * Inputs | |
86 | * macH - the 2 most significant bytes of the MAC address. | |
87 | * macL - the 4 least significant bytes of the MAC address. | |
88 | * hashMode - hash mode 0 or hash mode 1. | |
89 | * hashSizeSelector - indicates number of hash table entries (0=0x8000,1=0x800) | |
90 | * Outputs | |
91 | * return the calculated entry. | |
92 | */ | |
bf9e3b38 | 93 | u32 hashTableFunction (u32 macH, u32 macL, u32 HashSize, u32 hash_mode) |
c609719b | 94 | { |
bf9e3b38 WD |
95 | u32 hashResult; |
96 | u32 addrH; | |
97 | u32 addrL; | |
98 | u32 addr0; | |
99 | u32 addr1; | |
100 | u32 addr2; | |
101 | u32 addr3; | |
102 | u32 addrHSwapped; | |
103 | u32 addrLSwapped; | |
104 | ||
105 | ||
106 | addrH = NIBBLE_SWAPPING_16_BIT (macH); | |
107 | addrL = NIBBLE_SWAPPING_32_BIT (macL); | |
108 | ||
109 | addrHSwapped = FLIP_4_BITS (addrH & 0xf) | |
110 | + ((FLIP_4_BITS ((addrH >> 4) & 0xf)) << 4) | |
111 | + ((FLIP_4_BITS ((addrH >> 8) & 0xf)) << 8) | |
112 | + ((FLIP_4_BITS ((addrH >> 12) & 0xf)) << 12); | |
113 | ||
114 | addrLSwapped = FLIP_4_BITS (addrL & 0xf) | |
115 | + ((FLIP_4_BITS ((addrL >> 4) & 0xf)) << 4) | |
116 | + ((FLIP_4_BITS ((addrL >> 8) & 0xf)) << 8) | |
117 | + ((FLIP_4_BITS ((addrL >> 12) & 0xf)) << 12) | |
118 | + ((FLIP_4_BITS ((addrL >> 16) & 0xf)) << 16) | |
119 | + ((FLIP_4_BITS ((addrL >> 20) & 0xf)) << 20) | |
120 | + ((FLIP_4_BITS ((addrL >> 24) & 0xf)) << 24) | |
121 | + ((FLIP_4_BITS ((addrL >> 28) & 0xf)) << 28); | |
122 | ||
123 | addrH = addrHSwapped; | |
124 | addrL = addrLSwapped; | |
125 | ||
126 | if (hash_mode == 0) { | |
127 | addr0 = (addrL >> 2) & 0x03f; | |
128 | addr1 = (addrL & 0x003) | ((addrL >> 8) & 0x7f) << 2; | |
129 | addr2 = (addrL >> 15) & 0x1ff; | |
130 | addr3 = ((addrL >> 24) & 0x0ff) | ((addrH & 1) << 8); | |
131 | } else { | |
132 | addr0 = FLIP_6_BITS (addrL & 0x03f); | |
133 | addr1 = FLIP_9_BITS (((addrL >> 6) & 0x1ff)); | |
134 | addr2 = FLIP_9_BITS ((addrL >> 15) & 0x1ff); | |
135 | addr3 = FLIP_9_BITS ((((addrL >> 24) & 0x0ff) | | |
136 | ((addrH & 0x1) << 8))); | |
137 | } | |
138 | ||
139 | hashResult = (addr0 << 9) | (addr1 ^ addr2 ^ addr3); | |
140 | ||
141 | if (HashSize == _8K_TABLE) { | |
142 | hashResult = hashResult & 0xffff; | |
143 | } else { | |
144 | hashResult = hashResult & 0x07ff; | |
145 | } | |
146 | ||
147 | return (hashResult); | |
c609719b WD |
148 | } |
149 | ||
150 | ||
151 | /* | |
152 | * ---------------------------------------------------------------------------- | |
153 | * This function will add an entry to the address table. | |
154 | * depends on the hash mode and hash size that was initialized. | |
155 | * Inputs | |
156 | * port - ETHERNET port number. | |
157 | * macH - the 2 most significant bytes of the MAC address. | |
158 | * macL - the 4 least significant bytes of the MAC address. | |
159 | * skip - if 1, skip this address. | |
160 | * rd - the RD field in the address table. | |
161 | * Outputs | |
162 | * address table entry is added. | |
163 | * TRUE if success. | |
164 | * FALSE if table full | |
165 | */ | |
bf9e3b38 | 166 | int addAddressTableEntry (u32 port, u32 macH, u32 macL, u32 rd, u32 skip) |
c609719b | 167 | { |
bf9e3b38 WD |
168 | addrTblEntry *entry; |
169 | u32 newHi; | |
170 | u32 newLo; | |
171 | u32 i; | |
172 | ||
173 | newLo = (((macH >> 4) & 0xf) << 15) | |
174 | | (((macH >> 0) & 0xf) << 11) | |
175 | | (((macH >> 12) & 0xf) << 7) | |
176 | | (((macH >> 8) & 0xf) << 3) | |
177 | | (((macL >> 20) & 0x1) << 31) | |
178 | | (((macL >> 16) & 0xf) << 27) | |
179 | | (((macL >> 28) & 0xf) << 23) | |
180 | | (((macL >> 24) & 0xf) << 19) | |
181 | | (skip << SKIP_BIT) | (rd << 2) | VALID; | |
182 | ||
183 | newHi = (((macL >> 4) & 0xf) << 15) | |
184 | | (((macL >> 0) & 0xf) << 11) | |
185 | | (((macL >> 12) & 0xf) << 7) | |
186 | | (((macL >> 8) & 0xf) << 3) | |
187 | | (((macL >> 21) & 0x7) << 0); | |
188 | ||
189 | /* | |
190 | * Pick the appropriate table, start scanning for free/reusable | |
191 | * entries at the index obtained by hashing the specified MAC address | |
192 | */ | |
193 | entry = addressTableBase[port]; | |
194 | entry += hashTableFunction (macH, macL, addressTableHashSize[port], | |
195 | addressTableHashMode[port]); | |
196 | for (i = 0; i < HOP_NUMBER; i++, entry++) { | |
197 | if (!(entry->lo & VALID) /*|| (entry->lo & SKIP) */ ) { | |
198 | break; | |
199 | } else { /* if same address put in same position */ | |
200 | if (((entry->lo & 0xfffffff8) == (newLo & 0xfffffff8)) | |
201 | && (entry->hi == newHi)) { | |
202 | break; | |
203 | } | |
204 | } | |
205 | } | |
206 | ||
207 | if (i == HOP_NUMBER) { | |
208 | PRINTF ("addGT64260addressTableEntry: table section is full\n"); | |
209 | return (FALSE); | |
8bde7f77 | 210 | } |
bf9e3b38 WD |
211 | |
212 | /* | |
213 | * Update the selected entry | |
214 | */ | |
215 | entry->hi = newHi; | |
216 | entry->lo = newLo; | |
217 | DCACHE_FLUSH_N_SYNC ((u32) entry, MAC_ENTRY_SIZE); | |
218 | return (TRUE); | |
c609719b WD |
219 | } |
220 | ||
221 | #endif /* CONFIG_GT_USE_MAC_HASH_TABLE */ |