ia64/xen-unstable

view tools/ioemu/hw/pcnet.c @ 6736:4b2c87242ad3

Fix bug that service os & vmx guest can't communicate with
each other. The bug was physical packets smaller than
minimal packet size of 60 bytes were gettign thrown away.
Hence ARP traffic for example was dropped.

Signed-off-by: Edwin Zhai <edwin.zhai@intel.com>
Signed-off-by: Xiaofeng Ling <xiaofeng.ling@intel.com>
author kaf24@firebug.cl.cam.ac.uk
date Sat Sep 10 14:17:02 2005 +0000 (2005-09-10)
parents b6c98fe62e1a
children 4d899a738d59 8ca0f98ba8e2
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 #include "vl.h"
31 #include <sys/times.h>
32 #include <arpa/inet.h>
33 #include <net/ethernet.h>
35 //#define PCNET_DEBUG
36 //#define PCNET_DEBUG_IO
37 //#define PCNET_DEBUG_BCR
38 //#define PCNET_DEBUG_CSR
39 //#define PCNET_DEBUG_RMD
40 //#define PCNET_DEBUG_TMD
41 //#define PCNET_DEBUG_MATCH
44 #define PCNET_IOPORT_SIZE 0x20
45 #define PCNET_PNPMMIO_SIZE 0x20
48 typedef struct PCNetState_st PCNetState;
50 struct PCNetState_st {
51 PCIDevice dev;
52 NetDriverState *nd;
53 QEMUTimer *poll_timer;
54 int mmio_io_addr, rap, isr, lnkst;
55 target_phys_addr_t rdra, tdra;
56 uint8_t prom[16];
57 uint16_t csr[128];
58 uint16_t bcr[32];
59 uint64_t timer;
60 int xmit_pos, recv_pos;
61 uint8_t buffer[4096];
62 };
64 #include "pcnet.h"
66 static void pcnet_poll(PCNetState *s);
67 static void pcnet_poll_timer(void *opaque);
69 static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
70 static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
71 static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
72 static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
74 static void pcnet_s_reset(PCNetState *s)
75 {
76 #ifdef PCNET_DEBUG
77 printf("pcnet_s_reset\n");
78 #endif
80 s->lnkst = 0x40;
81 s->rdra = 0;
82 s->tdra = 0;
83 s->rap = 0;
85 s->bcr[BCR_BSBC] &= ~0x0080;
87 s->csr[0] = 0x0004;
88 s->csr[3] = 0x0000;
89 s->csr[4] = 0x0115;
90 s->csr[5] = 0x0000;
91 s->csr[6] = 0x0000;
92 s->csr[8] = 0;
93 s->csr[9] = 0;
94 s->csr[10] = 0;
95 s->csr[11] = 0;
96 s->csr[12] = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
97 s->csr[13] = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
98 s->csr[14] = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
99 s->csr[15] &= 0x21c4;
100 s->csr[72] = 1;
101 s->csr[74] = 1;
102 s->csr[76] = 1;
103 s->csr[78] = 1;
104 s->csr[80] = 0x1410;
105 s->csr[88] = 0x1003;
106 s->csr[89] = 0x0262;
107 s->csr[94] = 0x0000;
108 s->csr[100] = 0x0200;
109 s->csr[103] = 0x0105;
110 s->csr[103] = 0x0105;
111 s->csr[112] = 0x0000;
112 s->csr[114] = 0x0000;
113 s->csr[122] = 0x0000;
114 s->csr[124] = 0x0000;
115 }
117 static void pcnet_update_irq(PCNetState *s)
118 {
119 int isr = 0;
120 s->csr[0] &= ~0x0080;
122 #if 1
123 if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
124 (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
125 (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
126 #else
127 if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
128 (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
129 (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
130 (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
131 (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
132 (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
133 (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
134 (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
135 (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
136 (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
137 (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
138 (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
139 #endif
140 {
142 isr = CSR_INEA(s);
143 s->csr[0] |= 0x0080;
144 }
146 if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
147 s->csr[4] &= ~0x0080;
148 s->csr[4] |= 0x0040;
149 s->csr[0] |= 0x0080;
150 isr = 1;
151 #ifdef PCNET_DEBUG
152 printf("pcnet user int\n");
153 #endif
154 }
156 #if 1
157 if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
158 #else
159 if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
160 (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
161 #endif
162 {
163 isr = 1;
164 s->csr[0] |= 0x0080;
165 }
167 if (isr != s->isr) {
168 #ifdef PCNET_DEBUG
169 printf("pcnet: INTA=%d\n", isr);
170 #endif
171 }
172 pci_set_irq(&s->dev, 0, isr);
173 s->isr = isr;
174 }
176 static void pcnet_init(PCNetState *s)
177 {
178 #ifdef PCNET_DEBUG
179 printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
180 #endif
182 #define PCNET_INIT() do { \
183 cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \
184 (uint8_t *)&initblk, sizeof(initblk)); \
185 s->csr[15] = le16_to_cpu(initblk.mode); \
186 CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \
187 CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \
188 s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \
189 s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \
190 s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \
191 s->csr[10] = le16_to_cpu(initblk.ladrf3); \
192 s->csr[11] = le16_to_cpu(initblk.ladrf4); \
193 s->csr[12] = le16_to_cpu(initblk.padr1); \
194 s->csr[13] = le16_to_cpu(initblk.padr2); \
195 s->csr[14] = le16_to_cpu(initblk.padr3); \
196 s->rdra = PHYSADDR(s,initblk.rdra); \
197 s->tdra = PHYSADDR(s,initblk.tdra); \
198 } while (0)
200 if (BCR_SSIZE32(s)) {
201 struct pcnet_initblk32 initblk;
202 PCNET_INIT();
203 #ifdef PCNET_DEBUG
204 printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
205 initblk.rlen, initblk.tlen);
206 #endif
207 } else {
208 struct pcnet_initblk16 initblk;
209 PCNET_INIT();
210 #ifdef PCNET_DEBUG
211 printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
212 initblk.rlen, initblk.tlen);
213 #endif
214 }
216 #undef PCNET_INIT
218 CSR_RCVRC(s) = CSR_RCVRL(s);
219 CSR_XMTRC(s) = CSR_XMTRL(s);
221 #ifdef PCNET_DEBUG
222 printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
223 BCR_SSIZE32(s),
224 s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
225 #endif
227 s->csr[0] |= 0x0101;
228 s->csr[0] &= ~0x0004; /* clear STOP bit */
229 }
231 static void pcnet_start(PCNetState *s)
232 {
233 #ifdef PCNET_DEBUG
234 printf("pcnet_start\n");
235 #endif
237 if (!CSR_DTX(s))
238 s->csr[0] |= 0x0010; /* set TXON */
240 if (!CSR_DRX(s))
241 s->csr[0] |= 0x0020; /* set RXON */
243 s->csr[0] &= ~0x0004; /* clear STOP bit */
244 s->csr[0] |= 0x0002;
245 }
247 static void pcnet_stop(PCNetState *s)
248 {
249 #ifdef PCNET_DEBUG
250 printf("pcnet_stop\n");
251 #endif
252 s->csr[0] &= ~0x7feb;
253 s->csr[0] |= 0x0014;
254 s->csr[4] &= ~0x02c2;
255 s->csr[5] &= ~0x0011;
256 pcnet_poll_timer(s);
257 }
259 static void pcnet_rdte_poll(PCNetState *s)
260 {
261 s->csr[28] = s->csr[29] = 0;
262 if (s->rdra) {
263 int bad = 0;
264 #if 1
265 target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
266 target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
267 target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
268 #else
269 target_phys_addr_t crda = s->rdra +
270 (CSR_RCVRL(s) - CSR_RCVRC(s)) *
271 (BCR_SWSTYLE(s) ? 16 : 8 );
272 int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
273 target_phys_addr_t nrda = s->rdra +
274 (CSR_RCVRL(s) - nrdc) *
275 (BCR_SWSTYLE(s) ? 16 : 8 );
276 int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
277 target_phys_addr_t nnrd = s->rdra +
278 (CSR_RCVRL(s) - nnrc) *
279 (BCR_SWSTYLE(s) ? 16 : 8 );
280 #endif
282 CHECK_RMD(PHYSADDR(s,crda), bad);
283 if (!bad) {
284 CHECK_RMD(PHYSADDR(s,nrda), bad);
285 if (bad || (nrda == crda)) nrda = 0;
286 CHECK_RMD(PHYSADDR(s,nnrd), bad);
287 if (bad || (nnrd == crda)) nnrd = 0;
289 s->csr[28] = crda & 0xffff;
290 s->csr[29] = crda >> 16;
291 s->csr[26] = nrda & 0xffff;
292 s->csr[27] = nrda >> 16;
293 s->csr[36] = nnrd & 0xffff;
294 s->csr[37] = nnrd >> 16;
295 #ifdef PCNET_DEBUG
296 if (bad) {
297 printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
298 PHYSADDR(s,crda));
299 }
300 } else {
301 printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
302 #endif
303 }
304 }
306 if (CSR_CRDA(s)) {
307 struct pcnet_RMD rmd;
308 RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
309 CSR_CRBC(s) = rmd.rmd1.bcnt;
310 CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
311 #ifdef PCNET_DEBUG_RMD_X
312 printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
313 PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
314 ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
315 PRINT_RMD(&rmd);
316 #endif
317 } else {
318 CSR_CRBC(s) = CSR_CRST(s) = 0;
319 }
321 if (CSR_NRDA(s)) {
322 struct pcnet_RMD rmd;
323 RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
324 CSR_NRBC(s) = rmd.rmd1.bcnt;
325 CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
326 } else {
327 CSR_NRBC(s) = CSR_NRST(s) = 0;
328 }
330 }
332 static int pcnet_tdte_poll(PCNetState *s)
333 {
334 s->csr[34] = s->csr[35] = 0;
335 if (s->tdra) {
336 target_phys_addr_t cxda = s->tdra +
337 (CSR_XMTRL(s) - CSR_XMTRC(s)) *
338 (BCR_SWSTYLE(s) ? 16 : 8 );
339 int bad = 0;
340 CHECK_TMD(PHYSADDR(s, cxda),bad);
341 if (!bad) {
342 if (CSR_CXDA(s) != cxda) {
343 s->csr[60] = s->csr[34];
344 s->csr[61] = s->csr[35];
345 s->csr[62] = CSR_CXBC(s);
346 s->csr[63] = CSR_CXST(s);
347 }
348 s->csr[34] = cxda & 0xffff;
349 s->csr[35] = cxda >> 16;
350 #ifdef PCNET_DEBUG
351 } else {
352 printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
353 #endif
354 }
355 }
357 if (CSR_CXDA(s)) {
358 struct pcnet_TMD tmd;
360 TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
362 CSR_CXBC(s) = tmd.tmd1.bcnt;
363 CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
364 } else {
365 CSR_CXBC(s) = CSR_CXST(s) = 0;
366 }
368 return !!(CSR_CXST(s) & 0x8000);
369 }
371 static int pcnet_can_receive(void *opaque)
372 {
373 PCNetState *s = opaque;
374 if (CSR_STOP(s) || CSR_SPND(s))
375 return 0;
377 if (s->recv_pos > 0)
378 return 0;
380 return sizeof(s->buffer)-16;
381 }
383 #define MIN_BUF_SIZE 60
385 static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
386 {
387 PCNetState *s = opaque;
388 int is_padr = 0, is_bcast = 0, is_ladr = 0;
389 uint8_t buf1[60];
391 if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
392 return;
394 #ifdef PCNET_DEBUG
395 printf("pcnet_receive size=%d\n", size);
396 #endif
398 /* if too small buffer, then expand it */
399 if (size < MIN_BUF_SIZE) {
400 memcpy(buf1, buf, size);
401 memset(buf1 + size, 0, MIN_BUF_SIZE - size);
402 buf = buf1;
403 size = MIN_BUF_SIZE;
404 }
406 if (CSR_PROM(s)
407 || (is_padr=padr_match(s, buf, size))
408 || (is_bcast=padr_bcast(s, buf, size))
409 || (is_ladr=ladr_match(s, buf, size))) {
411 pcnet_rdte_poll(s);
413 if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
414 struct pcnet_RMD rmd;
415 int rcvrc = CSR_RCVRC(s)-1,i;
416 target_phys_addr_t nrda;
417 for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
418 if (rcvrc <= 1)
419 rcvrc = CSR_RCVRL(s);
420 nrda = s->rdra +
421 (CSR_RCVRL(s) - rcvrc) *
422 (BCR_SWSTYLE(s) ? 16 : 8 );
423 RMDLOAD(&rmd, PHYSADDR(s,nrda));
424 if (rmd.rmd1.own) {
425 #ifdef PCNET_DEBUG_RMD
426 printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
427 rcvrc, CSR_RCVRC(s));
428 #endif
429 CSR_RCVRC(s) = rcvrc;
430 pcnet_rdte_poll(s);
431 break;
432 }
433 }
434 }
436 if (!(CSR_CRST(s) & 0x8000)) {
437 #ifdef PCNET_DEBUG_RMD
438 printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
439 #endif
440 s->csr[0] |= 0x1000; /* Set MISS flag */
441 CSR_MISSC(s)++;
442 } else {
443 uint8_t *src = &s->buffer[8];
444 target_phys_addr_t crda = CSR_CRDA(s);
445 struct pcnet_RMD rmd;
446 int pktcount = 0;
448 memcpy(src, buf, size);
450 if (!CSR_ASTRP_RCV(s)) {
451 uint32_t fcs = ~0;
452 #if 0
453 uint8_t *p = s->buffer;
455 ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa;
456 p[7] = 0xab;
457 #else
458 uint8_t *p = src;
459 #endif
461 while (size < 46) {
462 src[size++] = 0;
463 }
465 while (p != &src[size]) {
466 CRC(fcs, *p++);
467 }
468 ((uint32_t *)&src[size])[0] = htonl(fcs);
469 size += 4; /* FCS at end of packet */
470 } else size += 4;
472 #ifdef PCNET_DEBUG_MATCH
473 PRINT_PKTHDR(buf);
474 #endif
476 RMDLOAD(&rmd, PHYSADDR(s,crda));
477 /*if (!CSR_LAPPEN(s))*/
478 rmd.rmd1.stp = 1;
480 #define PCNET_RECV_STORE() do { \
481 int count = MIN(4096 - rmd.rmd1.bcnt,size); \
482 target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
483 cpu_physical_memory_write(rbadr, src, count); \
484 cpu_physical_memory_set_dirty(rbadr); \
485 cpu_physical_memory_set_dirty(rbadr+count); \
486 src += count; size -= count; \
487 rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
488 RMDSTORE(&rmd, PHYSADDR(s,crda)); \
489 pktcount++; \
490 } while (0)
492 PCNET_RECV_STORE();
493 if ((size > 0) && CSR_NRDA(s)) {
494 target_phys_addr_t nrda = CSR_NRDA(s);
495 RMDLOAD(&rmd, PHYSADDR(s,nrda));
496 if (rmd.rmd1.own) {
497 crda = nrda;
498 PCNET_RECV_STORE();
499 if ((size > 0) && (nrda=CSR_NNRD(s))) {
500 RMDLOAD(&rmd, PHYSADDR(s,nrda));
501 if (rmd.rmd1.own) {
502 crda = nrda;
503 PCNET_RECV_STORE();
504 }
505 }
506 }
507 }
509 #undef PCNET_RECV_STORE
511 RMDLOAD(&rmd, PHYSADDR(s,crda));
512 if (size == 0) {
513 rmd.rmd1.enp = 1;
514 rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
515 rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
516 rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
517 } else {
518 rmd.rmd1.oflo = 1;
519 rmd.rmd1.buff = 1;
520 rmd.rmd1.err = 1;
521 }
522 RMDSTORE(&rmd, PHYSADDR(s,crda));
523 s->csr[0] |= 0x0400;
525 #ifdef PCNET_DEBUG
526 printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
527 CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
528 #endif
529 #ifdef PCNET_DEBUG_RMD
530 PRINT_RMD(&rmd);
531 #endif
533 while (pktcount--) {
534 if (CSR_RCVRC(s) <= 1)
535 CSR_RCVRC(s) = CSR_RCVRL(s);
536 else
537 CSR_RCVRC(s)--;
538 }
540 pcnet_rdte_poll(s);
542 }
543 }
545 pcnet_poll(s);
546 pcnet_update_irq(s);
547 }
549 static void pcnet_transmit(PCNetState *s)
550 {
551 target_phys_addr_t xmit_cxda = 0;
552 int count = CSR_XMTRL(s)-1;
553 s->xmit_pos = -1;
555 if (!CSR_TXON(s)) {
556 s->csr[0] &= ~0x0008;
557 return;
558 }
560 txagain:
561 if (pcnet_tdte_poll(s)) {
562 struct pcnet_TMD tmd;
564 TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
566 #ifdef PCNET_DEBUG_TMD
567 printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
568 PRINT_TMD(&tmd);
569 #endif
570 if (tmd.tmd1.stp) {
571 s->xmit_pos = 0;
572 if (!tmd.tmd1.enp) {
573 cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
574 s->buffer, 4096 - tmd.tmd1.bcnt);
575 s->xmit_pos += 4096 - tmd.tmd1.bcnt;
576 }
577 xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
578 }
579 if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
580 cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
581 s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
582 s->xmit_pos += 4096 - tmd.tmd1.bcnt;
584 tmd.tmd1.own = 0;
585 TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
587 #ifdef PCNET_DEBUG
588 printf("pcnet_transmit size=%d\n", s->xmit_pos);
589 #endif
590 if (CSR_LOOP(s))
591 pcnet_receive(s, s->buffer, s->xmit_pos);
592 else
593 qemu_send_packet(s->nd, s->buffer, s->xmit_pos);
595 s->csr[0] &= ~0x0008; /* clear TDMD */
596 s->csr[4] |= 0x0004; /* set TXSTRT */
597 s->xmit_pos = -1;
598 } else {
599 tmd.tmd1.own = 0;
600 TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
601 }
602 if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
603 s->csr[0] |= 0x0200; /* set TINT */
605 if (CSR_XMTRC(s)<=1)
606 CSR_XMTRC(s) = CSR_XMTRL(s);
607 else
608 CSR_XMTRC(s)--;
609 if (count--)
610 goto txagain;
612 } else
613 if (s->xmit_pos >= 0) {
614 struct pcnet_TMD tmd;
615 TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
616 tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
617 tmd.tmd1.own = 0;
618 TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
619 s->csr[0] |= 0x0200; /* set TINT */
620 if (!CSR_DXSUFLO(s)) {
621 s->csr[0] &= ~0x0010;
622 } else
623 if (count--)
624 goto txagain;
625 }
626 }
628 static void pcnet_poll(PCNetState *s)
629 {
630 if (CSR_RXON(s)) {
631 pcnet_rdte_poll(s);
632 }
634 if (CSR_TDMD(s) ||
635 (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
636 pcnet_transmit(s);
637 }
639 static void pcnet_poll_timer(void *opaque)
640 {
641 PCNetState *s = opaque;
643 qemu_del_timer(s->poll_timer);
645 if (CSR_TDMD(s)) {
646 pcnet_transmit(s);
647 }
649 pcnet_update_irq(s);
651 if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
652 uint64_t now = qemu_get_clock(vm_clock) * 33;
653 if (!s->timer || !now)
654 s->timer = now;
655 else {
656 uint64_t t = now - s->timer + CSR_POLL(s);
657 if (t > 0xffffLL) {
658 pcnet_poll(s);
659 CSR_POLL(s) = CSR_PINT(s);
660 } else
661 CSR_POLL(s) = t;
662 }
663 qemu_mod_timer(s->poll_timer,
664 pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
665 }
666 }
669 static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
670 {
671 uint16_t val = new_value;
672 #ifdef PCNET_DEBUG_CSR
673 printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
674 #endif
675 switch (rap) {
676 case 0:
677 s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
679 s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
681 val = (val & 0x007f) | (s->csr[0] & 0x7f00);
683 /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
684 if ((val&7) == 7)
685 val &= ~3;
687 if (!CSR_STOP(s) && (val & 4))
688 pcnet_stop(s);
690 if (!CSR_INIT(s) && (val & 1))
691 pcnet_init(s);
693 if (!CSR_STRT(s) && (val & 2))
694 pcnet_start(s);
696 if (CSR_TDMD(s))
697 pcnet_transmit(s);
699 return;
700 case 1:
701 case 2:
702 case 8:
703 case 9:
704 case 10:
705 case 11:
706 case 12:
707 case 13:
708 case 14:
709 case 15:
710 case 18: /* CRBAL */
711 case 19: /* CRBAU */
712 case 20: /* CXBAL */
713 case 21: /* CXBAU */
714 case 22: /* NRBAU */
715 case 23: /* NRBAU */
716 case 24:
717 case 25:
718 case 26:
719 case 27:
720 case 28:
721 case 29:
722 case 30:
723 case 31:
724 case 32:
725 case 33:
726 case 34:
727 case 35:
728 case 36:
729 case 37:
730 case 38:
731 case 39:
732 case 40: /* CRBC */
733 case 41:
734 case 42: /* CXBC */
735 case 43:
736 case 44:
737 case 45:
738 case 46: /* POLL */
739 case 47: /* POLLINT */
740 case 72:
741 case 74:
742 case 76: /* RCVRL */
743 case 78: /* XMTRL */
744 case 112:
745 if (CSR_STOP(s) || CSR_SPND(s))
746 break;
747 return;
748 case 3:
749 break;
750 case 4:
751 s->csr[4] &= ~(val & 0x026a);
752 val &= ~0x026a; val |= s->csr[4] & 0x026a;
753 break;
754 case 5:
755 s->csr[5] &= ~(val & 0x0a90);
756 val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
757 break;
758 case 16:
759 pcnet_csr_writew(s,1,val);
760 return;
761 case 17:
762 pcnet_csr_writew(s,2,val);
763 return;
764 case 58:
765 pcnet_bcr_writew(s,BCR_SWS,val);
766 break;
767 default:
768 return;
769 }
770 s->csr[rap] = val;
771 }
773 static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
774 {
775 uint32_t val;
776 switch (rap) {
777 case 0:
778 pcnet_update_irq(s);
779 val = s->csr[0];
780 val |= (val & 0x7800) ? 0x8000 : 0;
781 break;
782 case 16:
783 return pcnet_csr_readw(s,1);
784 case 17:
785 return pcnet_csr_readw(s,2);
786 case 58:
787 return pcnet_bcr_readw(s,BCR_SWS);
788 case 88:
789 val = s->csr[89];
790 val <<= 16;
791 val |= s->csr[88];
792 break;
793 default:
794 val = s->csr[rap];
795 }
796 #ifdef PCNET_DEBUG_CSR
797 printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
798 #endif
799 return val;
800 }
802 static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
803 {
804 rap &= 127;
805 #ifdef PCNET_DEBUG_BCR
806 printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
807 #endif
808 switch (rap) {
809 case BCR_SWS:
810 if (!(CSR_STOP(s) || CSR_SPND(s)))
811 return;
812 val &= ~0x0300;
813 switch (val & 0x00ff) {
814 case 0:
815 val |= 0x0200;
816 break;
817 case 1:
818 val |= 0x0100;
819 break;
820 case 2:
821 case 3:
822 val |= 0x0300;
823 break;
824 default:
825 printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
826 val = 0x0200;
827 break;
828 }
829 #ifdef PCNET_DEBUG
830 printf("BCR_SWS=0x%04x\n", val);
831 #endif
832 case BCR_LNKST:
833 case BCR_LED1:
834 case BCR_LED2:
835 case BCR_LED3:
836 case BCR_MC:
837 case BCR_FDC:
838 case BCR_BSBC:
839 case BCR_EECAS:
840 case BCR_PLAT:
841 s->bcr[rap] = val;
842 break;
843 default:
844 break;
845 }
846 }
848 static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
849 {
850 uint32_t val;
851 rap &= 127;
852 switch (rap) {
853 case BCR_LNKST:
854 case BCR_LED1:
855 case BCR_LED2:
856 case BCR_LED3:
857 val = s->bcr[rap] & ~0x8000;
858 val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
859 break;
860 default:
861 val = rap < 32 ? s->bcr[rap] : 0;
862 break;
863 }
864 #ifdef PCNET_DEBUG_BCR
865 printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
866 #endif
867 return val;
868 }
870 static void pcnet_h_reset(PCNetState *s)
871 {
872 int i;
873 uint16_t checksum;
875 /* Initialize the PROM */
877 memcpy(s->prom, s->nd->macaddr, 6);
878 s->prom[12] = s->prom[13] = 0x00;
879 s->prom[14] = s->prom[15] = 0x57;
881 for (i = 0,checksum = 0; i < 16; i++)
882 checksum += s->prom[i];
883 *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
886 s->bcr[BCR_MSRDA] = 0x0005;
887 s->bcr[BCR_MSWRA] = 0x0005;
888 s->bcr[BCR_MC ] = 0x0002;
889 s->bcr[BCR_LNKST] = 0x00c0;
890 s->bcr[BCR_LED1 ] = 0x0084;
891 s->bcr[BCR_LED2 ] = 0x0088;
892 s->bcr[BCR_LED3 ] = 0x0090;
893 s->bcr[BCR_FDC ] = 0x0000;
894 s->bcr[BCR_BSBC ] = 0x9001;
895 s->bcr[BCR_EECAS] = 0x0002;
896 s->bcr[BCR_SWS ] = 0x0200;
897 s->bcr[BCR_PLAT ] = 0xff06;
899 pcnet_s_reset(s);
900 }
902 static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
903 {
904 PCNetState *s = opaque;
905 #ifdef PCNET_DEBUG
906 printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
907 #endif
908 /* Check APROMWE bit to enable write access */
909 if (pcnet_bcr_readw(s,2) & 0x80)
910 s->prom[addr & 15] = val;
911 }
913 static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
914 {
915 PCNetState *s = opaque;
916 uint32_t val = s->prom[addr &= 15];
917 #ifdef PCNET_DEBUG
918 printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
919 #endif
920 return val;
921 }
923 static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
924 {
925 PCNetState *s = opaque;
926 pcnet_poll_timer(s);
927 #ifdef PCNET_DEBUG_IO
928 printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
929 #endif
930 if (!BCR_DWIO(s)) {
931 switch (addr & 0x0f) {
932 case 0x00: /* RDP */
933 pcnet_csr_writew(s, s->rap, val);
934 break;
935 case 0x02:
936 s->rap = val & 0x7f;
937 break;
938 case 0x06:
939 pcnet_bcr_writew(s, s->rap, val);
940 break;
941 }
942 }
943 pcnet_update_irq(s);
944 }
946 static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
947 {
948 PCNetState *s = opaque;
949 uint32_t val = -1;
950 pcnet_poll_timer(s);
951 if (!BCR_DWIO(s)) {
952 switch (addr & 0x0f) {
953 case 0x00: /* RDP */
954 val = pcnet_csr_readw(s, s->rap);
955 break;
956 case 0x02:
957 val = s->rap;
958 break;
959 case 0x04:
960 pcnet_s_reset(s);
961 val = 0;
962 break;
963 case 0x06:
964 val = pcnet_bcr_readw(s, s->rap);
965 break;
966 }
967 }
968 pcnet_update_irq(s);
969 #ifdef PCNET_DEBUG_IO
970 printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
971 #endif
972 return val;
973 }
975 static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
976 {
977 PCNetState *s = opaque;
978 pcnet_poll_timer(s);
979 #ifdef PCNET_DEBUG_IO
980 printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
981 #endif
982 if (BCR_DWIO(s)) {
983 switch (addr & 0x0f) {
984 case 0x00: /* RDP */
985 pcnet_csr_writew(s, s->rap, val & 0xffff);
986 break;
987 case 0x04:
988 s->rap = val & 0x7f;
989 break;
990 case 0x0c:
991 pcnet_bcr_writew(s, s->rap, val & 0xffff);
992 break;
993 }
994 } else
995 if ((addr & 0x0f) == 0) {
996 /* switch device to dword i/o mode */
997 pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
998 #ifdef PCNET_DEBUG_IO
999 printf("device switched into dword i/o mode\n");
1000 #endif
1002 pcnet_update_irq(s);
1005 static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1007 PCNetState *s = opaque;
1008 uint32_t val = -1;
1009 pcnet_poll_timer(s);
1010 if (BCR_DWIO(s)) {
1011 switch (addr & 0x0f) {
1012 case 0x00: /* RDP */
1013 val = pcnet_csr_readw(s, s->rap);
1014 break;
1015 case 0x04:
1016 val = s->rap;
1017 break;
1018 case 0x08:
1019 pcnet_s_reset(s);
1020 val = 0;
1021 break;
1022 case 0x0c:
1023 val = pcnet_bcr_readw(s, s->rap);
1024 break;
1027 pcnet_update_irq(s);
1028 #ifdef PCNET_DEBUG_IO
1029 printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1030 #endif
1031 return val;
1034 static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
1035 uint32_t addr, uint32_t size, int type)
1037 PCNetState *d = (PCNetState *)pci_dev;
1039 #ifdef PCNET_DEBUG_IO
1040 printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
1041 #endif
1043 register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
1044 register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
1046 register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
1047 register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
1048 register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
1049 register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
1052 static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1054 PCNetState *d = opaque;
1055 #ifdef PCNET_DEBUG_IO
1056 printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
1057 #endif
1058 if (!(addr & 0x10))
1059 pcnet_aprom_writeb(d, addr & 0x0f, val);
1062 static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
1064 PCNetState *d = opaque;
1065 uint32_t val = -1;
1066 if (!(addr & 0x10))
1067 val = pcnet_aprom_readb(d, addr & 0x0f);
1068 #ifdef PCNET_DEBUG_IO
1069 printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
1070 #endif
1071 return val;
1074 static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1076 PCNetState *d = opaque;
1077 #ifdef PCNET_DEBUG_IO
1078 printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
1079 #endif
1080 if (addr & 0x10)
1081 pcnet_ioport_writew(d, addr & 0x0f, val);
1082 else {
1083 addr &= 0x0f;
1084 pcnet_aprom_writeb(d, addr, val & 0xff);
1085 pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1089 static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
1091 PCNetState *d = opaque;
1092 uint32_t val = -1;
1093 if (addr & 0x10)
1094 val = pcnet_ioport_readw(d, addr & 0x0f);
1095 else {
1096 addr &= 0x0f;
1097 val = pcnet_aprom_readb(d, addr+1);
1098 val <<= 8;
1099 val |= pcnet_aprom_readb(d, addr);
1101 #ifdef PCNET_DEBUG_IO
1102 printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
1103 #endif
1104 return val;
1107 static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1109 PCNetState *d = opaque;
1110 #ifdef PCNET_DEBUG_IO
1111 printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
1112 #endif
1113 if (addr & 0x10)
1114 pcnet_ioport_writel(d, addr & 0x0f, val);
1115 else {
1116 addr &= 0x0f;
1117 pcnet_aprom_writeb(d, addr, val & 0xff);
1118 pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1119 pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
1120 pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
1124 static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
1126 PCNetState *d = opaque;
1127 uint32_t val;
1128 if (addr & 0x10)
1129 val = pcnet_ioport_readl(d, addr & 0x0f);
1130 else {
1131 addr &= 0x0f;
1132 val = pcnet_aprom_readb(d, addr+3);
1133 val <<= 8;
1134 val |= pcnet_aprom_readb(d, addr+2);
1135 val <<= 8;
1136 val |= pcnet_aprom_readb(d, addr+1);
1137 val <<= 8;
1138 val |= pcnet_aprom_readb(d, addr);
1140 #ifdef PCNET_DEBUG_IO
1141 printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
1142 #endif
1143 return val;
1147 static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
1148 (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
1149 (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
1150 (CPUWriteMemoryFunc *)&pcnet_mmio_writel
1151 };
1153 static CPUReadMemoryFunc *pcnet_mmio_read[] = {
1154 (CPUReadMemoryFunc *)&pcnet_mmio_readb,
1155 (CPUReadMemoryFunc *)&pcnet_mmio_readw,
1156 (CPUReadMemoryFunc *)&pcnet_mmio_readl
1157 };
1159 static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
1160 uint32_t addr, uint32_t size, int type)
1162 PCNetState *d = (PCNetState *)pci_dev;
1164 #ifdef PCNET_DEBUG_IO
1165 printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
1166 #endif
1168 cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
1171 void pci_pcnet_init(PCIBus *bus, NetDriverState *nd)
1173 PCNetState *d;
1174 uint8_t *pci_conf;
1176 #if 0
1177 printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
1178 sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
1179 #endif
1181 d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
1182 -1, NULL, NULL);
1184 pci_conf = d->dev.config;
1186 *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
1187 *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
1188 *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
1189 *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
1190 pci_conf[0x08] = 0x10;
1191 pci_conf[0x09] = 0x00;
1192 pci_conf[0x0a] = 0x00; // ethernet network controller
1193 pci_conf[0x0b] = 0x02;
1194 pci_conf[0x0e] = 0x00; // header_type
1196 *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
1197 *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
1199 pci_conf[0x3d] = 1; // interrupt pin 0
1200 pci_conf[0x3e] = 0x06;
1201 pci_conf[0x3f] = 0xff;
1203 /* Handler for memory-mapped I/O */
1204 d->mmio_io_addr =
1205 cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
1207 pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
1208 PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
1210 pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
1211 PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
1213 d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
1215 d->nd = nd;
1217 pcnet_h_reset(d);
1219 qemu_add_read_packet(nd, pcnet_can_receive, pcnet_receive, d);