ia64/xen-unstable

view tools/ioemu/hw/pcnet.h @ 9339:a8b1d4fad72d

Fix a protocol violation in the pcnet emulation. Tested on at least
two systems and fixes the 'corrupt MAC' with scp or sftp. See bug 574
for more information.

Signed-off-by: Don Fry <brazilnut@us.ibm.com>
author kaf24@firebug.cl.cam.ac.uk
date Mon Mar 20 12:01:32 2006 +0100 (2006-03-20)
parents b92a36713192
children c848b80c0b20
line source
1 /*
2 * QEMU AMD PC-Net II (Am79C970A) emulation
3 *
4 * Copyright (c) 2004 Antony T Curtis
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 * THE SOFTWARE.
23 */
25 /* This software was written to be compatible with the specification:
26 * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
27 * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000
28 */
30 #ifdef __GNUC__
31 #define PACKED(A) A __attribute__ ((packed))
32 #else
33 #error FixMe
34 #endif
36 /* BUS CONFIGURATION REGISTERS */
37 #define BCR_MSRDA 0
38 #define BCR_MSWRA 1
39 #define BCR_MC 2
40 #define BCR_LNKST 4
41 #define BCR_LED1 5
42 #define BCR_LED2 6
43 #define BCR_LED3 7
44 #define BCR_FDC 9
45 #define BCR_BSBC 18
46 #define BCR_EECAS 19
47 #define BCR_SWS 20
48 #define BCR_PLAT 22
50 #define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080)
51 #define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100)
52 #define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF)
54 #define CSR_INIT(S) !!(((S)->csr[0])&0x0001)
55 #define CSR_STRT(S) !!(((S)->csr[0])&0x0002)
56 #define CSR_STOP(S) !!(((S)->csr[0])&0x0004)
57 #define CSR_TDMD(S) !!(((S)->csr[0])&0x0008)
58 #define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
59 #define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
60 #define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
61 #define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
62 #define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
63 #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
64 #define CSR_DPOLL(S) !!(((S)->csr[4])&0x1000)
65 #define CSR_SPND(S) !!(((S)->csr[5])&0x0001)
66 #define CSR_LTINTEN(S) !!(((S)->csr[5])&0x4000)
67 #define CSR_TOKINTD(S) !!(((S)->csr[5])&0x8000)
68 #define CSR_DRX(S) !!(((S)->csr[15])&0x0001)
69 #define CSR_DTX(S) !!(((S)->csr[15])&0x0002)
70 #define CSR_LOOP(S) !!(((S)->csr[15])&0x0004)
71 #define CSR_DRCVPA(S) !!(((S)->csr[15])&0x2000)
72 #define CSR_DRCVBC(S) !!(((S)->csr[15])&0x4000)
73 #define CSR_PROM(S) !!(((S)->csr[15])&0x8000)
75 #define CSR_CRBC(S) ((S)->csr[40])
76 #define CSR_CRST(S) ((S)->csr[41])
77 #define CSR_CXBC(S) ((S)->csr[42])
78 #define CSR_CXST(S) ((S)->csr[43])
79 #define CSR_NRBC(S) ((S)->csr[44])
80 #define CSR_NRST(S) ((S)->csr[45])
81 #define CSR_POLL(S) ((S)->csr[46])
82 #define CSR_PINT(S) ((S)->csr[47])
83 #define CSR_RCVRC(S) ((S)->csr[72])
84 #define CSR_XMTRC(S) ((S)->csr[74])
85 #define CSR_RCVRL(S) ((S)->csr[76])
86 #define CSR_XMTRL(S) ((S)->csr[78])
87 #define CSR_MISSC(S) ((S)->csr[112])
89 #define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
90 #define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16))
91 #define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16))
92 #define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16))
93 #define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16))
94 #define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16))
95 #define CSR_CRDA(S) ((S)->csr[28] | (((uint32_t)((S)->csr[29])) << 16))
96 #define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16))
97 #define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16))
98 #define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16))
99 #define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16))
100 #define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16))
101 #define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16))
102 #define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16))
104 #define PHYSADDR(S,A) \
105 (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
107 struct pcnet_initblk16 {
108 uint16_t mode;
109 uint16_t padr1;
110 uint16_t padr2;
111 uint16_t padr3;
112 uint16_t ladrf1;
113 uint16_t ladrf2;
114 uint16_t ladrf3;
115 uint16_t ladrf4;
116 unsigned PACKED(rdra:24);
117 unsigned PACKED(res1:5);
118 unsigned PACKED(rlen:3);
119 unsigned PACKED(tdra:24);
120 unsigned PACKED(res2:5);
121 unsigned PACKED(tlen:3);
122 };
124 struct pcnet_initblk32 {
125 uint16_t mode;
126 unsigned PACKED(res1:4);
127 unsigned PACKED(rlen:4);
128 unsigned PACKED(res2:4);
129 unsigned PACKED(tlen:4);
130 uint16_t padr1;
131 uint16_t padr2;
132 uint16_t padr3;
133 uint16_t _res;
134 uint16_t ladrf1;
135 uint16_t ladrf2;
136 uint16_t ladrf3;
137 uint16_t ladrf4;
138 uint32_t rdra;
139 uint32_t tdra;
140 };
142 struct pcnet_TMD {
143 struct {
144 unsigned tbadr:32;
145 } tmd0;
146 struct {
147 unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:7), PACKED(bpe:1);
148 unsigned PACKED(enp:1), PACKED(stp:1), PACKED(def:1), PACKED(one:1);
149 unsigned PACKED(ltint:1), PACKED(nofcs:1), PACKED(err:1), PACKED(own:1);
150 } tmd1;
151 struct {
152 unsigned PACKED(trc:4), PACKED(res:12);
153 unsigned PACKED(tdr:10), PACKED(rtry:1), PACKED(lcar:1);
154 unsigned PACKED(lcol:1), PACKED(exdef:1), PACKED(uflo:1), PACKED(buff:1);
155 } tmd2;
156 struct {
157 unsigned res:32;
158 } tmd3;
159 };
161 struct pcnet_RMD {
162 struct {
163 unsigned rbadr:32;
164 } rmd0;
165 struct {
166 unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:4);
167 unsigned PACKED(bam:1), PACKED(lafm:1), PACKED(pam:1), PACKED(bpe:1);
168 unsigned PACKED(enp:1), PACKED(stp:1), PACKED(buff:1), PACKED(crc:1);
169 unsigned PACKED(oflo:1), PACKED(fram:1), PACKED(err:1), PACKED(own:1);
170 } rmd1;
171 struct {
172 unsigned PACKED(mcnt:12), PACKED(zeros:4);
173 unsigned PACKED(rpc:8), PACKED(rcc:8);
174 } rmd2;
175 struct {
176 unsigned res:32;
177 } rmd3;
178 };
181 #define PRINT_TMD(T) printf( \
182 "TMD0 : TBADR=0x%08x\n" \
183 "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, " \
184 "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n" \
185 " BPE=%d, BCNT=%d\n" \
186 "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, " \
187 "LCA=%d, RTR=%d,\n" \
188 " TDR=%d, TRC=%d\n", \
189 (T)->tmd0.tbadr, \
190 (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs, \
191 (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def, \
192 (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe, \
193 4096-(T)->tmd1.bcnt, \
194 (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
195 (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
196 (T)->tmd2.tdr, (T)->tmd2.trc)
198 #define PRINT_RMD(R) printf( \
199 "RMD0 : RBADR=0x%08x\n" \
200 "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, " \
201 "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n " \
202 "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
203 "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n", \
204 (R)->rmd0.rbadr, \
205 (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram, \
206 (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff, \
207 (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe, \
208 (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam, \
209 (R)->rmd1.ones, 4096-(R)->rmd1.bcnt, \
210 (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
211 (R)->rmd2.zeros)
213 static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
214 {
215 if (!BCR_SWSTYLE(s)) {
216 uint16_t xda[4];
217 cpu_physical_memory_read(addr,
218 (void *)&xda[0], sizeof(xda));
219 ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
220 ((xda[1]&0x00ff) << 16);
221 ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
222 ((xda[1] & 0xff00) << 16);
223 ((uint32_t *)tmd)[2] =
224 (xda[3] & 0xffff) << 16;
225 ((uint32_t *)tmd)[3] = 0;
226 }
227 else
228 if (BCR_SWSTYLE(s) != 3) {
229 ((uint32_t *)tmd)[2] = 0;
230 cpu_physical_memory_read(addr+4, (void *)&tmd->tmd1, 4);
231 cpu_physical_memory_read(addr, (void *)&tmd->tmd0, 4);
232 } else {
233 uint32_t xda[4];
234 cpu_physical_memory_read(addr,
235 (void *)&xda[0], sizeof(xda));
236 ((uint32_t *)tmd)[0] = xda[2];
237 ((uint32_t *)tmd)[1] = xda[1];
238 ((uint32_t *)tmd)[2] = xda[0];
239 ((uint32_t *)tmd)[3] = xda[3];
240 }
241 }
243 static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
244 {
245 cpu_physical_memory_set_dirty(addr);
246 if (!BCR_SWSTYLE(s)) {
247 uint16_t xda[4];
248 xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
249 xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
250 ((((uint32_t *)tmd)[1]>>16)&0xff00);
251 xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
252 xda[3] = ((uint32_t *)tmd)[2] >> 16;
253 cpu_physical_memory_write(addr,
254 (void *)&xda[0], sizeof(xda));
255 cpu_physical_memory_set_dirty(addr+7);
256 }
257 else {
258 if (BCR_SWSTYLE(s) != 3) {
259 cpu_physical_memory_write(addr+8, (void *)&tmd->tmd2, 4);
260 cpu_physical_memory_write(addr+4, (void *)&tmd->tmd1, 4);
261 } else {
262 uint32_t xda[4];
263 xda[0] = ((uint32_t *)tmd)[2];
264 xda[1] = ((uint32_t *)tmd)[1];
265 xda[2] = ((uint32_t *)tmd)[0];
266 xda[3] = ((uint32_t *)tmd)[3];
267 cpu_physical_memory_write(addr,
268 (void *)&xda[0], sizeof(xda));
269 }
270 cpu_physical_memory_set_dirty(addr+15);
271 }
272 }
274 static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
275 {
276 if (!BCR_SWSTYLE(s)) {
277 uint16_t rda[4];
278 cpu_physical_memory_read(addr,
279 (void *)&rda[0], sizeof(rda));
280 ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
281 ((rda[1] & 0x00ff) << 16);
282 ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
283 ((rda[1] & 0xff00) << 16);
284 ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
285 ((uint32_t *)rmd)[3] = 0;
286 }
287 else
288 if (BCR_SWSTYLE(s) != 3) {
289 rmd->rmd2.zeros = 0;
290 cpu_physical_memory_read(addr+4, (void *)&rmd->rmd1, 4);
291 cpu_physical_memory_read(addr, (void *)&rmd->rmd0, 4);
292 } else {
293 uint32_t rda[4];
294 cpu_physical_memory_read(addr,
295 (void *)&rda[0], sizeof(rda));
296 ((uint32_t *)rmd)[0] = rda[2];
297 ((uint32_t *)rmd)[1] = rda[1];
298 ((uint32_t *)rmd)[2] = rda[0];
299 ((uint32_t *)rmd)[3] = rda[3];
300 }
301 }
303 static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
304 {
305 cpu_physical_memory_set_dirty(addr);
306 if (!BCR_SWSTYLE(s)) {
307 uint16_t rda[4]; \
308 rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
309 rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
310 ((((uint32_t *)rmd)[1]>>16)&0xff00);\
311 rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
312 rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
313 cpu_physical_memory_write(addr, \
314 (void *)&rda[0], sizeof(rda)); \
315 cpu_physical_memory_set_dirty(addr+7);
316 }
317 else {
318 if (BCR_SWSTYLE(s) != 3) {
319 cpu_physical_memory_write(addr+8, (void *)&rmd->rmd2, 4);
320 cpu_physical_memory_write(addr+4, (void *)&rmd->rmd1, 4);
321 } else {
322 uint32_t rda[4];
323 rda[0] = ((uint32_t *)rmd)[2];
324 rda[1] = ((uint32_t *)rmd)[1];
325 rda[2] = ((uint32_t *)rmd)[0];
326 rda[3] = ((uint32_t *)rmd)[3];
327 cpu_physical_memory_write(addr,
328 (void *)&rda[0], sizeof(rda));
329 }
330 cpu_physical_memory_set_dirty(addr+15);
331 }
332 }
335 #define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
337 #define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
339 #define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
341 #define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
343 #if 1
345 #define CHECK_RMD(ADDR,RES) do { \
346 struct pcnet_RMD rmd; \
347 RMDLOAD(&rmd,(ADDR)); \
348 (RES) |= (rmd.rmd1.ones != 15); \
349 } while (0)
351 #define CHECK_TMD(ADDR,RES) do { \
352 struct pcnet_TMD tmd; \
353 TMDLOAD(&tmd,(ADDR)); \
354 (RES) |= (tmd.tmd1.ones != 15); \
355 } while (0)
357 #else
359 #define CHECK_RMD(ADDR,RES) do { \
360 switch (BCR_SWSTYLE(s)) { \
361 case 0x00: \
362 do { \
363 uint16_t rda[4]; \
364 cpu_physical_memory_read((ADDR), \
365 (void *)&rda[0], sizeof(rda)); \
366 (RES) |= (rda[2] & 0xf000)!=0xf000; \
367 (RES) |= (rda[3] & 0xf000)!=0x0000; \
368 } while (0); \
369 break; \
370 case 0x01: \
371 case 0x02: \
372 do { \
373 uint32_t rda[4]; \
374 cpu_physical_memory_read((ADDR), \
375 (void *)&rda[0], sizeof(rda)); \
376 (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
377 (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
378 } while (0); \
379 break; \
380 case 0x03: \
381 do { \
382 uint32_t rda[4]; \
383 cpu_physical_memory_read((ADDR), \
384 (void *)&rda[0], sizeof(rda)); \
385 (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
386 (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
387 } while (0); \
388 break; \
389 } \
390 } while (0)
392 #define CHECK_TMD(ADDR,RES) do { \
393 switch (BCR_SWSTYLE(s)) { \
394 case 0x00: \
395 do { \
396 uint16_t xda[4]; \
397 cpu_physical_memory_read((ADDR), \
398 (void *)&xda[0], sizeof(xda)); \
399 (RES) |= (xda[2] & 0xf000)!=0xf000;\
400 } while (0); \
401 break; \
402 case 0x01: \
403 case 0x02: \
404 case 0x03: \
405 do { \
406 uint32_t xda[4]; \
407 cpu_physical_memory_read((ADDR), \
408 (void *)&xda[0], sizeof(xda)); \
409 (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
410 } while (0); \
411 break; \
412 } \
413 } while (0)
415 #endif
417 #define PRINT_PKTHDR(BUF) do { \
418 struct ether_header *hdr = (void *)(BUF); \
419 printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
420 "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
421 "type=0x%04x (bcast=%d)\n", \
422 hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
423 hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
424 hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
425 hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
426 htons(hdr->ether_type), \
427 !!ETHER_IS_MULTICAST(hdr->ether_dhost)); \
428 } while (0)
430 #define MULTICAST_FILTER_LEN 8
432 static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
433 {
434 #define LNC_POLYNOMIAL 0xEDB88320UL
435 uint32_t crc = 0xFFFFFFFF;
436 int idx, bit;
437 uint8_t data;
439 for (idx = 0; idx < ETHER_ADDR_LEN; idx++) {
440 for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
441 crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
442 data >>= 1;
443 }
444 }
445 return crc;
446 #undef LNC_POLYNOMIAL
447 }
449 #define MIN(X,Y) ((X>Y) ? (Y) : (X))
451 #define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
453 /* generated using the AUTODIN II polynomial
454 * x^32 + x^26 + x^23 + x^22 + x^16 +
455 * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
456 */
457 static const uint32_t crctab[256] = {
458 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
459 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
460 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
461 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
462 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
463 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
464 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
465 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
466 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
467 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
468 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
469 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
470 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
471 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
472 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
473 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
474 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
475 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
476 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
477 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
478 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
479 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
480 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
481 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
482 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
483 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
484 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
485 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
486 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
487 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
488 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
489 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
490 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
491 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
492 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
493 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
494 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
495 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
496 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
497 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
498 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
499 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
500 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
501 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
502 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
503 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
504 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
505 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
506 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
507 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
508 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
509 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
510 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
511 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
512 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
513 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
514 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
515 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
516 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
517 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
518 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
519 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
520 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
521 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
522 };
524 static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
525 {
526 struct ether_header *hdr = (void *)buf;
527 uint8_t padr[6] = {
528 s->csr[12] & 0xff, s->csr[12] >> 8,
529 s->csr[13] & 0xff, s->csr[13] >> 8,
530 s->csr[14] & 0xff, s->csr[14] >> 8
531 };
532 int result = (!CSR_DRCVPA(s)) && !bcmp(hdr->ether_dhost, padr, 6);
533 #ifdef PCNET_DEBUG_MATCH
534 printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
535 "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
536 hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
537 hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
538 padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
539 printf("padr_match result=%d\n", result);
540 #endif
541 return result;
542 }
544 static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
545 {
546 static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
547 struct ether_header *hdr = (void *)buf;
548 int result = !CSR_DRCVBC(s) && !bcmp(hdr->ether_dhost, BCAST, 6);
549 #ifdef PCNET_DEBUG_MATCH
550 printf("padr_bcast result=%d\n", result);
551 #endif
552 return result;
553 }
555 static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
556 {
557 struct ether_header *hdr = (void *)buf;
558 if ((*(hdr->ether_dhost)&0x01) &&
559 ((uint64_t *)&s->csr[8])[0] != 0LL) {
560 uint8_t ladr[8] = {
561 s->csr[8] & 0xff, s->csr[8] >> 8,
562 s->csr[9] & 0xff, s->csr[9] >> 8,
563 s->csr[10] & 0xff, s->csr[10] >> 8,
564 s->csr[11] & 0xff, s->csr[11] >> 8
565 };
566 int index = lnc_mchash(hdr->ether_dhost) >> 26;
567 return !!(ladr[index >> 3] & (1 << (index & 7)));
568 }
569 return 0;
570 }
572 static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
573 {
574 while (idx < 1) idx += CSR_RCVRL(s);
575 return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
576 }
578 static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
579 {
580 int64_t next_time = current_time +
581 muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
582 ticks_per_sec, 33000000L);
583 if (next_time <= current_time)
584 next_time = current_time + 1;
585 return next_time;
586 }