source: trunk/packages/xen-common/xen-common/tools/ioemu/hw/pcnet.c @ 34

Last change on this file since 34 was 34, checked in by hartmans, 17 years ago

Add xen and xen-common

File size: 56.0 KB
Line 
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 */
24 
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 */
29 
30#include "vl.h"
31
32//#define PCNET_DEBUG
33//#define PCNET_DEBUG_IO
34//#define PCNET_DEBUG_BCR
35//#define PCNET_DEBUG_CSR
36//#define PCNET_DEBUG_RMD
37//#define PCNET_DEBUG_TMD
38//#define PCNET_DEBUG_MATCH
39
40
41#define PCNET_IOPORT_SIZE       0x20
42#define PCNET_PNPMMIO_SIZE      0x20
43
44
45typedef struct PCNetState_st PCNetState;
46
47struct PCNetState_st {
48    PCIDevice dev;
49    VLANClientState *vc;
50    NICInfo *nd;
51    QEMUTimer *poll_timer;
52    int mmio_io_addr, rap, isr, lnkst;
53    target_phys_addr_t rdra, tdra;
54    uint8_t prom[16];
55    uint16_t csr[128];
56    uint16_t bcr[32];
57    uint64_t timer;
58    int xmit_pos, recv_pos;
59    uint8_t buffer[4096];
60    int tx_busy;
61};
62
63/* XXX: using bitfields for target memory structures is almost surely
64   not portable, so it should be suppressed ASAP */
65#ifdef __GNUC__
66#define PACKED_FIELD(A) A __attribute__ ((packed))
67#else
68#error FixMe
69#endif
70
71struct qemu_ether_header {
72    uint8_t ether_dhost[6];
73    uint8_t ether_shost[6];
74    uint16_t ether_type;
75};
76
77/* BUS CONFIGURATION REGISTERS */
78#define BCR_MSRDA    0
79#define BCR_MSWRA    1
80#define BCR_MC       2
81#define BCR_LNKST    4
82#define BCR_LED1     5
83#define BCR_LED2     6
84#define BCR_LED3     7
85#define BCR_FDC      9
86#define BCR_BSBC     18
87#define BCR_EECAS    19
88#define BCR_SWS      20
89#define BCR_PLAT     22
90
91#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
92#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
93#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
94
95#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
96#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
97#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
98#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
99#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
100#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
101#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
102#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
103#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
104#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
105#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
106#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
107#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
108#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
109#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
110#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
111#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
112#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
113#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
114#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
115
116#define CSR_CRBC(S)      ((S)->csr[40])
117#define CSR_CRST(S)      ((S)->csr[41])
118#define CSR_CXBC(S)      ((S)->csr[42])
119#define CSR_CXST(S)      ((S)->csr[43])
120#define CSR_NRBC(S)      ((S)->csr[44])
121#define CSR_NRST(S)      ((S)->csr[45])
122#define CSR_POLL(S)      ((S)->csr[46])
123#define CSR_PINT(S)      ((S)->csr[47])
124#define CSR_RCVRC(S)     ((S)->csr[72])
125#define CSR_XMTRC(S)     ((S)->csr[74])
126#define CSR_RCVRL(S)     ((S)->csr[76])
127#define CSR_XMTRL(S)     ((S)->csr[78])
128#define CSR_MISSC(S)     ((S)->csr[112])
129
130#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
131#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
132#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
133#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
134#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
135#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
136#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
137#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
138#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
139#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
140#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
141#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
142#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
143#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
144
145#define PHYSADDR(S,A) \
146  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
147
148struct pcnet_initblk16 {
149    uint16_t mode;
150    uint16_t padr1;
151    uint16_t padr2;
152    uint16_t padr3;
153    uint16_t ladrf1;
154    uint16_t ladrf2;
155    uint16_t ladrf3;
156    uint16_t ladrf4;
157    unsigned PACKED_FIELD(rdra:24);
158    unsigned PACKED_FIELD(res1:5);
159    unsigned PACKED_FIELD(rlen:3);
160    unsigned PACKED_FIELD(tdra:24);
161    unsigned PACKED_FIELD(res2:5);
162    unsigned PACKED_FIELD(tlen:3);
163};
164
165struct pcnet_initblk32 {
166    uint16_t mode;
167    unsigned PACKED_FIELD(res1:4);
168    unsigned PACKED_FIELD(rlen:4);
169    unsigned PACKED_FIELD(res2:4);
170    unsigned PACKED_FIELD(tlen:4);
171    uint16_t padr1;
172    uint16_t padr2;
173    uint16_t padr3;
174    uint16_t _res;
175    uint16_t ladrf1;
176    uint16_t ladrf2;
177    uint16_t ladrf3;
178    uint16_t ladrf4;
179    uint32_t rdra;
180    uint32_t tdra;
181};
182
183struct pcnet_TMD {
184    struct {
185        unsigned tbadr:32;
186    } tmd0;
187    struct {
188        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:7), PACKED_FIELD(bpe:1);
189        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(def:1), PACKED_FIELD(one:1);
190        unsigned PACKED_FIELD(ltint:1), PACKED_FIELD(nofcs:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
191    } tmd1;
192    struct {
193        unsigned PACKED_FIELD(trc:4), PACKED_FIELD(res:12);
194        unsigned PACKED_FIELD(tdr:10), PACKED_FIELD(rtry:1), PACKED_FIELD(lcar:1);
195        unsigned PACKED_FIELD(lcol:1), PACKED_FIELD(exdef:1), PACKED_FIELD(uflo:1), PACKED_FIELD(buff:1);
196    } tmd2;
197    struct {
198        unsigned res:32;
199    } tmd3;   
200};
201
202struct pcnet_RMD {
203    struct {
204        unsigned rbadr:32;
205    } rmd0;
206    struct {
207        unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:4);
208        unsigned PACKED_FIELD(bam:1), PACKED_FIELD(lafm:1), PACKED_FIELD(pam:1), PACKED_FIELD(bpe:1);
209        unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(buff:1), PACKED_FIELD(crc:1);
210        unsigned PACKED_FIELD(oflo:1), PACKED_FIELD(fram:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
211    } rmd1;
212    struct {
213        unsigned PACKED_FIELD(mcnt:12), PACKED_FIELD(zeros:4);
214        unsigned PACKED_FIELD(rpc:8), PACKED_FIELD(rcc:8);
215    } rmd2;   
216    struct {
217        unsigned res:32;
218    } rmd3;   
219};
220
221
222#define PRINT_TMD(T) printf(    \
223        "TMD0 : TBADR=0x%08x\n" \
224        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
225        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
226        "       BPE=%d, BCNT=%d\n"                      \
227        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
228        "LCA=%d, RTR=%d,\n"                             \
229        "       TDR=%d, TRC=%d\n",                      \
230        (T)->tmd0.tbadr,                                \
231        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
232        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
233        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
234        4096-(T)->tmd1.bcnt,                            \
235        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
236        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
237        (T)->tmd2.tdr, (T)->tmd2.trc)
238
239#define PRINT_RMD(R) printf(    \
240        "RMD0 : RBADR=0x%08x\n" \
241        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
242        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
243        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
244        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
245        (R)->rmd0.rbadr,                                \
246        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
247        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
248        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
249        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
250        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
251        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
252        (R)->rmd2.zeros)
253
254static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
255{
256    if (!BCR_SWSTYLE(s)) {
257        uint16_t xda[4];
258        cpu_physical_memory_read(addr,
259                (void *)&xda[0], sizeof(xda));
260        ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
261                ((xda[1]&0x00ff) << 16);
262        ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
263                ((xda[1] & 0xff00) << 16);
264        ((uint32_t *)tmd)[2] =
265                (xda[3] & 0xffff) << 16;
266        ((uint32_t *)tmd)[3] = 0;
267    }
268    else
269    if (BCR_SWSTYLE(s) != 3)
270        cpu_physical_memory_read(addr, (void *)tmd, 16);
271    else {
272        uint32_t xda[4];
273        cpu_physical_memory_read(addr,
274                (void *)&xda[0], sizeof(xda));
275        ((uint32_t *)tmd)[0] = xda[2];
276        ((uint32_t *)tmd)[1] = xda[1];
277        ((uint32_t *)tmd)[2] = xda[0];
278        ((uint32_t *)tmd)[3] = xda[3];
279    }
280}
281
282static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
283{
284    if (!BCR_SWSTYLE(s)) {
285        uint16_t xda[4];
286        xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
287        xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
288            ((((uint32_t *)tmd)[1]>>16)&0xff00);
289        xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
290        xda[3] = ((uint32_t *)tmd)[2] >> 16;
291        cpu_physical_memory_write(addr,
292                (void *)&xda[0], sizeof(xda));
293    }
294    else {
295        if (BCR_SWSTYLE(s) != 3)
296            cpu_physical_memory_write(addr, (void *)tmd, 16);
297        else {
298            uint32_t xda[4];
299            xda[0] = ((uint32_t *)tmd)[2];
300            xda[1] = ((uint32_t *)tmd)[1];
301            xda[2] = ((uint32_t *)tmd)[0];
302            xda[3] = ((uint32_t *)tmd)[3];
303            cpu_physical_memory_write(addr,
304                    (void *)&xda[0], sizeof(xda));
305        }
306    }
307}
308
309static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
310{
311    if (!BCR_SWSTYLE(s)) {
312        uint16_t rda[4];
313        cpu_physical_memory_read(addr,
314                (void *)&rda[0], sizeof(rda));
315        ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
316                ((rda[1] & 0x00ff) << 16);
317        ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
318                ((rda[1] & 0xff00) << 16);
319        ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
320        ((uint32_t *)rmd)[3] = 0;
321    }
322    else
323    if (BCR_SWSTYLE(s) != 3)
324        cpu_physical_memory_read(addr, (void *)rmd, 16);
325    else {
326        uint32_t rda[4];
327        cpu_physical_memory_read(addr,
328                (void *)&rda[0], sizeof(rda));
329        ((uint32_t *)rmd)[0] = rda[2];
330        ((uint32_t *)rmd)[1] = rda[1];
331        ((uint32_t *)rmd)[2] = rda[0];
332        ((uint32_t *)rmd)[3] = rda[3];
333    }
334}
335
336static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
337{
338    if (!BCR_SWSTYLE(s)) {
339        uint16_t rda[4];                        \
340        rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
341        rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
342            ((((uint32_t *)rmd)[1]>>16)&0xff00);\
343        rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
344        rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
345        cpu_physical_memory_write(addr,         \
346                (void *)&rda[0], sizeof(rda));  \
347    }
348    else {
349        if (BCR_SWSTYLE(s) != 3)
350            cpu_physical_memory_write(addr, (void *)rmd, 16);
351        else {
352            uint32_t rda[4];
353            rda[0] = ((uint32_t *)rmd)[2];
354            rda[1] = ((uint32_t *)rmd)[1];
355            rda[2] = ((uint32_t *)rmd)[0];
356            rda[3] = ((uint32_t *)rmd)[3];
357            cpu_physical_memory_write(addr,
358                    (void *)&rda[0], sizeof(rda));
359        }
360    }
361}
362
363
364#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
365
366#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
367
368#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
369
370#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
371
372#if 1
373
374#define CHECK_RMD(ADDR,RES) do {                \
375    struct pcnet_RMD rmd;                       \
376    RMDLOAD(&rmd,(ADDR));                       \
377    (RES) |= (rmd.rmd1.ones != 15)              \
378          || (rmd.rmd2.zeros != 0);             \
379} while (0)
380
381#define CHECK_TMD(ADDR,RES) do {                \
382    struct pcnet_TMD tmd;                       \
383    TMDLOAD(&tmd,(ADDR));                       \
384    (RES) |= (tmd.tmd1.ones != 15);             \
385} while (0)
386
387#else
388
389#define CHECK_RMD(ADDR,RES) do {                \
390    switch (BCR_SWSTYLE(s)) {                   \
391    case 0x00:                                  \
392        do {                                    \
393            uint16_t rda[4];                    \
394            cpu_physical_memory_read((ADDR),    \
395                (void *)&rda[0], sizeof(rda));  \
396            (RES) |= (rda[2] & 0xf000)!=0xf000; \
397            (RES) |= (rda[3] & 0xf000)!=0x0000; \
398        } while (0);                            \
399        break;                                  \
400    case 0x01:                                  \
401    case 0x02:                                  \
402        do {                                    \
403            uint32_t rda[4];                    \
404            cpu_physical_memory_read((ADDR),    \
405                (void *)&rda[0], sizeof(rda)); \
406            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
407            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
408        } while (0);                            \
409        break;                                  \
410    case 0x03:                                  \
411        do {                                    \
412            uint32_t rda[4];                    \
413            cpu_physical_memory_read((ADDR),    \
414                (void *)&rda[0], sizeof(rda)); \
415            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
416            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
417        } while (0);                            \
418        break;                                  \
419    }                                           \
420} while (0)
421
422#define CHECK_TMD(ADDR,RES) do {                \
423    switch (BCR_SWSTYLE(s)) {                   \
424    case 0x00:                                  \
425        do {                                    \
426            uint16_t xda[4];                    \
427            cpu_physical_memory_read((ADDR),    \
428                (void *)&xda[0], sizeof(xda));  \
429            (RES) |= (xda[2] & 0xf000)!=0xf000;\
430        } while (0);                            \
431        break;                                  \
432    case 0x01:                                  \
433    case 0x02:                                  \
434    case 0x03:                                  \
435        do {                                    \
436            uint32_t xda[4];                    \
437            cpu_physical_memory_read((ADDR),    \
438                (void *)&xda[0], sizeof(xda));  \
439            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
440        } while (0);                            \
441        break;                                  \
442    }                                           \
443} while (0)
444
445#endif
446
447#define PRINT_PKTHDR(BUF) do {                  \
448    struct qemu_ether_header *hdr = (void *)(BUF);   \
449    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
450           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
451           "type=0x%04x (bcast=%d)\n",                          \
452           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
453           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
454           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
455           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
456           be16_to_cpu(hdr->ether_type),                                \
457           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
458} while (0)
459
460#define MULTICAST_FILTER_LEN 8
461
462static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
463{
464#define LNC_POLYNOMIAL          0xEDB88320UL
465    uint32_t crc = 0xFFFFFFFF;
466    int idx, bit;
467    uint8_t data;
468
469    for (idx = 0; idx < 6; idx++) {
470        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
471            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
472            data >>= 1;
473        }
474    }
475    return crc;
476#undef LNC_POLYNOMIAL
477}
478
479#define CRC(crc, ch)     (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
480
481/* generated using the AUTODIN II polynomial
482 *      x^32 + x^26 + x^23 + x^22 + x^16 +
483 *      x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
484 */
485static const uint32_t crctab[256] = {
486        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
487        0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
488        0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
489        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
490        0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
491        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
492        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
493        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
494        0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
495        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
496        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
497        0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
498        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
499        0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
500        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
501        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
502        0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
503        0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
504        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
505        0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
506        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
507        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
508        0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
509        0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
510        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
511        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
512        0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
513        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
514        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
515        0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
516        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
517        0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
518        0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
519        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
520        0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
521        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
522        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
523        0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
524        0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
525        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
526        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
527        0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
528        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
529        0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
530        0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
531        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
532        0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
533        0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
534        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
535        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
536        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
537        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
538        0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
539        0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
540        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
541        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
542        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
543        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
544        0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
545        0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
546        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
547        0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
548        0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
549        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
550};
551
552static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
553{
554    struct qemu_ether_header *hdr = (void *)buf;
555    uint8_t padr[6] = { 
556        s->csr[12] & 0xff, s->csr[12] >> 8,
557        s->csr[13] & 0xff, s->csr[13] >> 8,
558        s->csr[14] & 0xff, s->csr[14] >> 8 
559    };
560    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
561#ifdef PCNET_DEBUG_MATCH
562    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
563           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
564           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
565           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
566           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
567    printf("padr_match result=%d\n", result);
568#endif
569    return result;
570}
571
572static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
573{
574    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
575    struct qemu_ether_header *hdr = (void *)buf;
576    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
577#ifdef PCNET_DEBUG_MATCH
578    printf("padr_bcast result=%d\n", result);
579#endif
580    return result;
581}
582
583static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
584{
585    struct qemu_ether_header *hdr = (void *)buf;
586    if ((*(hdr->ether_dhost)&0x01) && 
587        ((uint64_t *)&s->csr[8])[0] != 0LL) {
588        uint8_t ladr[8] = { 
589            s->csr[8] & 0xff, s->csr[8] >> 8,
590            s->csr[9] & 0xff, s->csr[9] >> 8,
591            s->csr[10] & 0xff, s->csr[10] >> 8, 
592            s->csr[11] & 0xff, s->csr[11] >> 8 
593        };
594        int index = lnc_mchash(hdr->ether_dhost) >> 26;
595        return !!(ladr[index >> 3] & (1 << (index & 7)));
596    }
597    return 0;
598}
599
600static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) 
601{
602    while (idx < 1) idx += CSR_RCVRL(s);
603    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
604}
605
606static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
607{
608    int64_t next_time = current_time + 
609        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), 
610                 ticks_per_sec, 33000000L);
611    if (next_time <= current_time)
612        next_time = current_time + 1;
613    return next_time;
614}
615
616static void pcnet_poll(PCNetState *s);
617static void pcnet_poll_timer(void *opaque);
618
619static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
620static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
621static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
622static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
623
624static void pcnet_s_reset(PCNetState *s)
625{
626#ifdef PCNET_DEBUG
627    printf("pcnet_s_reset\n");
628#endif
629
630    s->lnkst = 0x40;
631    s->rdra = 0;
632    s->tdra = 0;
633    s->rap = 0;
634   
635    s->bcr[BCR_BSBC] &= ~0x0080;
636
637    s->csr[0]   = 0x0004;
638    s->csr[3]   = 0x0000;
639    s->csr[4]   = 0x0115;
640    s->csr[5]   = 0x0000;
641    s->csr[6]   = 0x0000;
642    s->csr[8]   = 0;
643    s->csr[9]   = 0;
644    s->csr[10]  = 0;
645    s->csr[11]  = 0;
646    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
647    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
648    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
649    s->csr[15] &= 0x21c4;
650    s->csr[72]  = 1;
651    s->csr[74]  = 1;
652    s->csr[76]  = 1;
653    s->csr[78]  = 1;
654    s->csr[80]  = 0x1410;
655    s->csr[88]  = 0x1003;
656    s->csr[89]  = 0x0262;
657    s->csr[94]  = 0x0000;
658    s->csr[100] = 0x0200;
659    s->csr[103] = 0x0105;
660    s->csr[103] = 0x0105;
661    s->csr[112] = 0x0000;
662    s->csr[114] = 0x0000;
663    s->csr[122] = 0x0000;
664    s->csr[124] = 0x0000;
665
666    s->tx_busy = 0;
667}
668
669static void pcnet_update_irq(PCNetState *s)
670{
671    int isr = 0;
672    s->csr[0] &= ~0x0080;
673   
674#if 1
675    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
676        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
677        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
678#else
679    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
680        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
681        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
682        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
683        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
684        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
685        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
686        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
687        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
688        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
689        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
690        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
691#endif
692    {
693       
694        isr = CSR_INEA(s);
695        s->csr[0] |= 0x0080;
696    }
697   
698    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
699        s->csr[4] &= ~0x0080;
700        s->csr[4] |= 0x0040;
701        s->csr[0] |= 0x0080;
702        isr = 1;
703#ifdef PCNET_DEBUG
704        printf("pcnet user int\n");
705#endif
706    }
707
708#if 1
709    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500) 
710#else
711    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
712        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
713#endif
714    {
715        isr = 1;
716        s->csr[0] |= 0x0080;
717    }
718
719    if (isr != s->isr) {
720#ifdef PCNET_DEBUG
721        printf("pcnet: INTA=%d\n", isr);
722#endif
723    }
724        pci_set_irq(&s->dev, 0, isr);
725        s->isr = isr;
726}
727
728static void pcnet_init(PCNetState *s)
729{
730#ifdef PCNET_DEBUG
731    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
732#endif
733   
734#define PCNET_INIT() do { \
735        cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)),       \
736                (uint8_t *)&initblk, sizeof(initblk));          \
737        s->csr[15] = le16_to_cpu(initblk.mode);                 \
738        CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512;  \
739        CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512;  \
740        s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8);        \
741        s->csr[ 8] = le16_to_cpu(initblk.ladrf1);                       \
742        s->csr[ 9] = le16_to_cpu(initblk.ladrf2);                       \
743        s->csr[10] = le16_to_cpu(initblk.ladrf3);                       \
744        s->csr[11] = le16_to_cpu(initblk.ladrf4);                       \
745        s->csr[12] = le16_to_cpu(initblk.padr1);                        \
746        s->csr[13] = le16_to_cpu(initblk.padr2);                        \
747        s->csr[14] = le16_to_cpu(initblk.padr3);                        \
748        s->rdra = PHYSADDR(s,initblk.rdra);                             \
749        s->tdra = PHYSADDR(s,initblk.tdra);                             \
750} while (0)
751   
752    if (BCR_SSIZE32(s)) {
753        struct pcnet_initblk32 initblk;
754        PCNET_INIT();
755#ifdef PCNET_DEBUG
756        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
757                initblk.rlen, initblk.tlen);
758#endif
759    } else {
760        struct pcnet_initblk16 initblk;
761        PCNET_INIT();
762#ifdef PCNET_DEBUG
763        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
764                initblk.rlen, initblk.tlen);
765#endif
766    }
767
768#undef PCNET_INIT
769
770    CSR_RCVRC(s) = CSR_RCVRL(s);
771    CSR_XMTRC(s) = CSR_XMTRL(s);
772
773#ifdef PCNET_DEBUG
774    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", 
775        BCR_SSIZE32(s),
776        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
777#endif
778
779    s->csr[0] |= 0x0101;   
780    s->csr[0] &= ~0x0004;       /* clear STOP bit */
781}
782
783static void pcnet_start(PCNetState *s)
784{
785#ifdef PCNET_DEBUG
786    printf("pcnet_start\n");
787#endif
788
789    if (!CSR_DTX(s))
790        s->csr[0] |= 0x0010;    /* set TXON */
791       
792    if (!CSR_DRX(s))
793        s->csr[0] |= 0x0020;    /* set RXON */
794
795    s->csr[0] &= ~0x0004;       /* clear STOP bit */
796    s->csr[0] |= 0x0002;
797}
798
799static void pcnet_stop(PCNetState *s)
800{
801#ifdef PCNET_DEBUG
802    printf("pcnet_stop\n");
803#endif
804    s->csr[0] &= ~0x7feb;
805    s->csr[0] |= 0x0014;
806    s->csr[4] &= ~0x02c2;
807    s->csr[5] &= ~0x0011;
808    pcnet_poll_timer(s);
809}
810
811static void pcnet_rdte_poll(PCNetState *s)
812{
813    s->csr[28] = s->csr[29] = 0;
814    if (s->rdra) {
815        int bad = 0;
816#if 1
817        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
818        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
819        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
820#else
821        target_phys_addr_t crda = s->rdra + 
822            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
823            (BCR_SWSTYLE(s) ? 16 : 8 );
824        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
825        target_phys_addr_t nrda = s->rdra + 
826            (CSR_RCVRL(s) - nrdc) *
827            (BCR_SWSTYLE(s) ? 16 : 8 );
828        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
829        target_phys_addr_t nnrd = s->rdra + 
830            (CSR_RCVRL(s) - nnrc) *
831            (BCR_SWSTYLE(s) ? 16 : 8 );
832#endif
833
834        CHECK_RMD(PHYSADDR(s,crda), bad);
835        if (!bad) {
836            CHECK_RMD(PHYSADDR(s,nrda), bad);
837            if (bad || (nrda == crda)) nrda = 0;
838            CHECK_RMD(PHYSADDR(s,nnrd), bad);
839            if (bad || (nnrd == crda)) nnrd = 0;
840
841            s->csr[28] = crda & 0xffff;
842            s->csr[29] = crda >> 16;
843            s->csr[26] = nrda & 0xffff;
844            s->csr[27] = nrda >> 16;
845            s->csr[36] = nnrd & 0xffff;
846            s->csr[37] = nnrd >> 16;
847#ifdef PCNET_DEBUG
848            if (bad) {
849                printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
850                       PHYSADDR(s,crda));
851            }
852        } else {
853            printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
854#endif
855        }
856    }
857   
858    if (CSR_CRDA(s)) {
859        struct pcnet_RMD rmd;
860        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
861        CSR_CRBC(s) = rmd.rmd1.bcnt;
862        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
863#ifdef PCNET_DEBUG_RMD_X
864        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
865                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
866                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
867        PRINT_RMD(&rmd);
868#endif
869    } else {
870        CSR_CRBC(s) = CSR_CRST(s) = 0;
871    }
872   
873    if (CSR_NRDA(s)) {
874        struct pcnet_RMD rmd;
875        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
876        CSR_NRBC(s) = rmd.rmd1.bcnt;
877        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
878    } else {
879        CSR_NRBC(s) = CSR_NRST(s) = 0;
880    }
881
882}
883
884static int pcnet_tdte_poll(PCNetState *s)
885{
886    s->csr[34] = s->csr[35] = 0;
887    if (s->tdra) {
888        target_phys_addr_t cxda = s->tdra + 
889            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
890            (BCR_SWSTYLE(s) ? 16 : 8 );
891        int bad = 0;
892        CHECK_TMD(PHYSADDR(s, cxda),bad);
893        if (!bad) {
894            if (CSR_CXDA(s) != cxda) {
895                s->csr[60] = s->csr[34];
896                s->csr[61] = s->csr[35];
897                s->csr[62] = CSR_CXBC(s);
898                s->csr[63] = CSR_CXST(s);
899            }
900            s->csr[34] = cxda & 0xffff;
901            s->csr[35] = cxda >> 16;
902#ifdef PCNET_DEBUG
903        } else {
904            printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
905#endif
906        }
907    }
908
909    if (CSR_CXDA(s)) {
910        struct pcnet_TMD tmd;
911
912        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));               
913
914        CSR_CXBC(s) = tmd.tmd1.bcnt;
915        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
916    } else {
917        CSR_CXBC(s) = CSR_CXST(s) = 0;
918    }
919   
920    return !!(CSR_CXST(s) & 0x8000);
921}
922
923static int pcnet_can_receive(void *opaque)
924{
925    PCNetState *s = opaque;
926    if (CSR_STOP(s) || CSR_SPND(s))
927        return 0;
928       
929    if (s->recv_pos > 0)
930        return 0;
931
932    return sizeof(s->buffer)-16;
933}
934
935#define MIN_BUF_SIZE 60
936
937static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
938{
939    PCNetState *s = opaque;
940    int is_padr = 0, is_bcast = 0, is_ladr = 0;
941    uint8_t buf1[60];
942
943    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
944        return;
945
946#ifdef PCNET_DEBUG
947    printf("pcnet_receive size=%d\n", size);
948#endif
949
950    /* if too small buffer, then expand it */
951    if (size < MIN_BUF_SIZE) {
952        memcpy(buf1, buf, size);
953        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
954        buf = buf1;
955        size = MIN_BUF_SIZE;
956    }
957
958    if (CSR_PROM(s) 
959        || (is_padr=padr_match(s, buf, size)) 
960        || (is_bcast=padr_bcast(s, buf, size))
961        || (is_ladr=ladr_match(s, buf, size))) {
962
963        pcnet_rdte_poll(s);
964
965        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
966            struct pcnet_RMD rmd;
967            int rcvrc = CSR_RCVRC(s)-1,i;
968            target_phys_addr_t nrda;
969            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
970                if (rcvrc <= 1)
971                    rcvrc = CSR_RCVRL(s);
972                nrda = s->rdra +
973                    (CSR_RCVRL(s) - rcvrc) *
974                    (BCR_SWSTYLE(s) ? 16 : 8 );
975                RMDLOAD(&rmd, PHYSADDR(s,nrda));                 
976                if (rmd.rmd1.own) {               
977#ifdef PCNET_DEBUG_RMD
978                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
979                                rcvrc, CSR_RCVRC(s));
980#endif
981                    CSR_RCVRC(s) = rcvrc;
982                    pcnet_rdte_poll(s);
983                    break;
984                }
985            }
986        }
987
988        if (!(CSR_CRST(s) & 0x8000)) {
989#ifdef PCNET_DEBUG_RMD
990            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
991#endif
992            s->csr[0] |= 0x1000; /* Set MISS flag */
993            CSR_MISSC(s)++;
994        } else {
995            uint8_t *src = &s->buffer[8];
996            target_phys_addr_t crda = CSR_CRDA(s);
997            struct pcnet_RMD rmd;
998            int pktcount = 0;
999
1000            memcpy(src, buf, size);
1001           
1002#if 1
1003            /* no need to compute the CRC */
1004            src[size] = 0;
1005            src[size + 1] = 0;
1006            src[size + 2] = 0;
1007            src[size + 3] = 0;
1008            size += 4;
1009#else
1010            /* XXX: avoid CRC generation */
1011            if (!CSR_ASTRP_RCV(s)) {
1012                uint32_t fcs = ~0;
1013                uint8_t *p = src;
1014
1015                while (size < 46) {
1016                    src[size++] = 0;
1017                }
1018               
1019                while (p != &src[size]) {
1020                    CRC(fcs, *p++);
1021                }
1022                ((uint32_t *)&src[size])[0] = htonl(fcs);
1023                size += 4; /* FCS at end of packet */
1024            } else size += 4;
1025#endif
1026
1027#ifdef PCNET_DEBUG_MATCH
1028            PRINT_PKTHDR(buf);
1029#endif
1030
1031            RMDLOAD(&rmd, PHYSADDR(s,crda));
1032            /*if (!CSR_LAPPEN(s))*/
1033                rmd.rmd1.stp = 1;
1034
1035#define PCNET_RECV_STORE() do {                                 \
1036    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
1037    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
1038    cpu_physical_memory_write(rbadr, src, count);               \
1039    src += count; size -= count;                                \
1040    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
1041    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1042    pktcount++;                                                 \
1043} while (0)
1044
1045            PCNET_RECV_STORE();
1046            if ((size > 0) && CSR_NRDA(s)) {
1047                target_phys_addr_t nrda = CSR_NRDA(s);
1048                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1049                if (rmd.rmd1.own) {
1050                    crda = nrda;
1051                    PCNET_RECV_STORE();
1052                    if ((size > 0) && (nrda=CSR_NNRD(s))) {
1053                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1054                        if (rmd.rmd1.own) {
1055                            crda = nrda;
1056                            PCNET_RECV_STORE();
1057                        }
1058                    }
1059                }               
1060            }
1061
1062#undef PCNET_RECV_STORE
1063
1064            RMDLOAD(&rmd, PHYSADDR(s,crda));
1065            if (size == 0) {
1066                rmd.rmd1.enp = 1;
1067                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
1068                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
1069                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
1070            } else {
1071                rmd.rmd1.oflo = 1;
1072                rmd.rmd1.buff = 1;
1073                rmd.rmd1.err = 1;
1074            }
1075            RMDSTORE(&rmd, PHYSADDR(s,crda));
1076            s->csr[0] |= 0x0400;
1077
1078#ifdef PCNET_DEBUG
1079            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", 
1080                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1081#endif
1082#ifdef PCNET_DEBUG_RMD
1083            PRINT_RMD(&rmd);
1084#endif       
1085
1086            while (pktcount--) {
1087                if (CSR_RCVRC(s) <= 1)
1088                    CSR_RCVRC(s) = CSR_RCVRL(s);
1089                else
1090                    CSR_RCVRC(s)--;           
1091            }
1092           
1093            pcnet_rdte_poll(s);
1094
1095        }       
1096    }
1097
1098    pcnet_poll(s);
1099    pcnet_update_irq(s);   
1100}
1101
1102static void pcnet_transmit(PCNetState *s)
1103{
1104    target_phys_addr_t xmit_cxda = 0;
1105    int count = CSR_XMTRL(s)-1;
1106    s->xmit_pos = -1;
1107   
1108    if (!CSR_TXON(s)) {
1109        s->csr[0] &= ~0x0008;
1110        return;
1111    }
1112
1113    s->tx_busy = 1;
1114
1115    txagain:
1116    if (pcnet_tdte_poll(s)) {
1117        struct pcnet_TMD tmd;
1118
1119        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));               
1120
1121#ifdef PCNET_DEBUG_TMD
1122        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1123        PRINT_TMD(&tmd);
1124#endif
1125        if (tmd.tmd1.stp) {
1126            s->xmit_pos = 0;               
1127            if (!tmd.tmd1.enp) {
1128                cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
1129                        s->buffer, 4096 - tmd.tmd1.bcnt);
1130                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1131            } 
1132            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1133        }
1134        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
1135            cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
1136                    s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
1137            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1138#ifdef PCNET_DEBUG
1139            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1140#endif           
1141            if (CSR_LOOP(s))
1142                pcnet_receive(s, s->buffer, s->xmit_pos);
1143            else
1144                qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
1145
1146            s->csr[0] &= ~0x0008;   /* clear TDMD */
1147            s->csr[4] |= 0x0004;    /* set TXSTRT */
1148            s->xmit_pos = -1;
1149        }
1150
1151        tmd.tmd1.own = 0;
1152        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1153        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
1154            s->csr[0] |= 0x0200;    /* set TINT */
1155
1156        if (CSR_XMTRC(s)<=1)
1157            CSR_XMTRC(s) = CSR_XMTRL(s);
1158        else
1159            CSR_XMTRC(s)--;
1160        if (count--)
1161            goto txagain;
1162
1163    } else 
1164    if (s->xmit_pos >= 0) {
1165        struct pcnet_TMD tmd;
1166        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));               
1167        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
1168        tmd.tmd1.own = 0;
1169        TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
1170        s->csr[0] |= 0x0200;    /* set TINT */
1171        if (!CSR_DXSUFLO(s)) {
1172            s->csr[0] &= ~0x0010;
1173        } else
1174        if (count--)
1175          goto txagain;
1176    }
1177
1178    s->tx_busy = 0;
1179}
1180
1181static void pcnet_poll(PCNetState *s)
1182{
1183    if (CSR_RXON(s)) {
1184        pcnet_rdte_poll(s);
1185    }
1186
1187    if (CSR_TDMD(s) || 
1188        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1189    {
1190        /* prevent recursion */
1191        if (s->tx_busy)
1192            return;
1193
1194        pcnet_transmit(s);
1195    }
1196}
1197
1198static void pcnet_poll_timer(void *opaque)
1199{
1200    PCNetState *s = opaque;
1201
1202    qemu_del_timer(s->poll_timer);
1203
1204    if (CSR_TDMD(s)) {
1205        pcnet_transmit(s);
1206    }
1207
1208    pcnet_update_irq(s);   
1209
1210    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1211        uint64_t now = qemu_get_clock(vm_clock) * 33;
1212        if (!s->timer || !now)
1213            s->timer = now;
1214        else {
1215            uint64_t t = now - s->timer + CSR_POLL(s);
1216            if (t > 0xffffLL) {
1217                pcnet_poll(s);
1218                CSR_POLL(s) = CSR_PINT(s);
1219            } else
1220                CSR_POLL(s) = t;
1221        }
1222        qemu_mod_timer(s->poll_timer, 
1223            pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
1224    }
1225}
1226
1227
1228static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1229{
1230    uint16_t val = new_value;
1231#ifdef PCNET_DEBUG_CSR
1232    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1233#endif
1234    switch (rap) {
1235    case 0:
1236        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1237
1238        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1239
1240        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1241
1242        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1243        if ((val&7) == 7)
1244          val &= ~3;
1245
1246        if (!CSR_STOP(s) && (val & 4))
1247            pcnet_stop(s);
1248
1249        if (!CSR_INIT(s) && (val & 1))
1250            pcnet_init(s);
1251
1252        if (!CSR_STRT(s) && (val & 2))
1253            pcnet_start(s);
1254
1255        if (CSR_TDMD(s)) 
1256            pcnet_transmit(s);
1257
1258        return;
1259    case 1:
1260    case 2:
1261    case 8:
1262    case 9:
1263    case 10:
1264    case 11:
1265    case 12:
1266    case 13:
1267    case 14:
1268    case 15:
1269    case 18: /* CRBAL */
1270    case 19: /* CRBAU */
1271    case 20: /* CXBAL */
1272    case 21: /* CXBAU */
1273    case 22: /* NRBAU */
1274    case 23: /* NRBAU */
1275    case 24:
1276    case 25:
1277    case 26:
1278    case 27:
1279    case 28:
1280    case 29:
1281    case 30:
1282    case 31:
1283    case 32:
1284    case 33:
1285    case 34:
1286    case 35:
1287    case 36:
1288    case 37:
1289    case 38:
1290    case 39:
1291    case 40: /* CRBC */
1292    case 41:
1293    case 42: /* CXBC */
1294    case 43:
1295    case 44:
1296    case 45:
1297    case 46: /* POLL */
1298    case 47: /* POLLINT */
1299    case 72:
1300    case 74:
1301    case 76: /* RCVRL */
1302    case 78: /* XMTRL */
1303    case 112:
1304       if (CSR_STOP(s) || CSR_SPND(s))
1305           break;
1306       return;
1307    case 3:
1308        break;
1309    case 4:
1310        s->csr[4] &= ~(val & 0x026a); 
1311        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1312        break;
1313    case 5:
1314        s->csr[5] &= ~(val & 0x0a90); 
1315        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1316        break;
1317    case 16:
1318        pcnet_csr_writew(s,1,val);
1319        return;
1320    case 17:
1321        pcnet_csr_writew(s,2,val);
1322        return;
1323    case 58:
1324        pcnet_bcr_writew(s,BCR_SWS,val);
1325        break;
1326    default:
1327        return;
1328    }
1329    s->csr[rap] = val;
1330}
1331
1332static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1333{
1334    uint32_t val;
1335    switch (rap) {
1336    case 0:
1337        pcnet_update_irq(s);
1338        val = s->csr[0];
1339        val |= (val & 0x7800) ? 0x8000 : 0;
1340        break;
1341    case 16:
1342        return pcnet_csr_readw(s,1);
1343    case 17:
1344        return pcnet_csr_readw(s,2);
1345    case 58:
1346        return pcnet_bcr_readw(s,BCR_SWS);
1347    case 88:
1348        val = s->csr[89];
1349        val <<= 16;
1350        val |= s->csr[88];
1351        break;
1352    default:
1353        val = s->csr[rap];
1354    }
1355#ifdef PCNET_DEBUG_CSR
1356    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1357#endif
1358    return val;
1359}
1360
1361static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1362{
1363    rap &= 127;
1364#ifdef PCNET_DEBUG_BCR
1365    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1366#endif
1367    switch (rap) {
1368    case BCR_SWS:
1369        if (!(CSR_STOP(s) || CSR_SPND(s)))
1370            return;
1371        val &= ~0x0300;
1372        switch (val & 0x00ff) {
1373        case 0:
1374            val |= 0x0200;
1375            break;
1376        case 1:
1377            val |= 0x0100;
1378            break;
1379        case 2:
1380        case 3:
1381            val |= 0x0300;
1382            break;
1383        default:
1384            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1385            val = 0x0200;
1386            break;
1387        }
1388#ifdef PCNET_DEBUG
1389       printf("BCR_SWS=0x%04x\n", val);
1390#endif
1391    case BCR_LNKST:
1392    case BCR_LED1:
1393    case BCR_LED2:
1394    case BCR_LED3:
1395    case BCR_MC:
1396    case BCR_FDC:
1397    case BCR_BSBC:
1398    case BCR_EECAS:
1399    case BCR_PLAT:
1400        s->bcr[rap] = val;
1401        break;
1402    default:
1403        break;
1404    }
1405}
1406
1407static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1408{
1409    uint32_t val;
1410    rap &= 127;
1411    switch (rap) {
1412    case BCR_LNKST:
1413    case BCR_LED1:
1414    case BCR_LED2:
1415    case BCR_LED3:
1416        val = s->bcr[rap] & ~0x8000;
1417        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1418        break;
1419    default:
1420        val = rap < 32 ? s->bcr[rap] : 0;
1421        break;
1422    }
1423#ifdef PCNET_DEBUG_BCR
1424    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1425#endif
1426    return val;
1427}
1428
1429static void pcnet_h_reset(PCNetState *s)
1430{
1431    int i;
1432    uint16_t checksum;
1433
1434    /* Initialize the PROM */
1435
1436    memcpy(s->prom, s->nd->macaddr, 6);
1437    s->prom[12] = s->prom[13] = 0x00;
1438    s->prom[14] = s->prom[15] = 0x57;
1439
1440    for (i = 0,checksum = 0; i < 16; i++)
1441        checksum += s->prom[i];
1442    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1443
1444
1445    s->bcr[BCR_MSRDA] = 0x0005;
1446    s->bcr[BCR_MSWRA] = 0x0005;
1447    s->bcr[BCR_MC   ] = 0x0002;
1448    s->bcr[BCR_LNKST] = 0x00c0;
1449    s->bcr[BCR_LED1 ] = 0x0084;
1450    s->bcr[BCR_LED2 ] = 0x0088;
1451    s->bcr[BCR_LED3 ] = 0x0090;
1452    s->bcr[BCR_FDC  ] = 0x0000;
1453    s->bcr[BCR_BSBC ] = 0x9001;
1454    s->bcr[BCR_EECAS] = 0x0002;
1455    s->bcr[BCR_SWS  ] = 0x0200;
1456    s->bcr[BCR_PLAT ] = 0xff06;
1457
1458    pcnet_s_reset(s);
1459}
1460
1461static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
1462{
1463    PCNetState *s = opaque;
1464#ifdef PCNET_DEBUG
1465    printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
1466#endif   
1467    /* Check APROMWE bit to enable write access */
1468    if (pcnet_bcr_readw(s,2) & 0x80)
1469        s->prom[addr & 15] = val;
1470}       
1471
1472static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
1473{
1474    PCNetState *s = opaque;
1475    uint32_t val = s->prom[addr &= 15];
1476#ifdef PCNET_DEBUG
1477    printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
1478#endif
1479    return val;
1480}
1481
1482static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1483{
1484    PCNetState *s = opaque;
1485    pcnet_poll_timer(s);
1486#ifdef PCNET_DEBUG_IO
1487    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1488#endif
1489    if (!BCR_DWIO(s)) {
1490        switch (addr & 0x0f) {
1491        case 0x00: /* RDP */
1492            pcnet_csr_writew(s, s->rap, val);
1493            break;
1494        case 0x02:
1495            s->rap = val & 0x7f;
1496            break;
1497        case 0x06:
1498            pcnet_bcr_writew(s, s->rap, val);
1499            break;
1500        }
1501    }
1502    pcnet_update_irq(s);
1503}
1504
1505static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1506{
1507    PCNetState *s = opaque;
1508    uint32_t val = -1;
1509    pcnet_poll_timer(s);
1510    if (!BCR_DWIO(s)) {
1511        switch (addr & 0x0f) {
1512        case 0x00: /* RDP */
1513            val = pcnet_csr_readw(s, s->rap);
1514            break;
1515        case 0x02:
1516            val = s->rap;
1517            break;
1518        case 0x04:
1519            pcnet_s_reset(s);
1520            val = 0;
1521            break;
1522        case 0x06:
1523            val = pcnet_bcr_readw(s, s->rap);
1524            break;
1525        }
1526    }
1527    pcnet_update_irq(s);
1528#ifdef PCNET_DEBUG_IO
1529    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1530#endif
1531    return val;
1532}
1533
1534static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1535{
1536    PCNetState *s = opaque;
1537    pcnet_poll_timer(s);
1538#ifdef PCNET_DEBUG_IO
1539    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1540#endif
1541    if (BCR_DWIO(s)) {
1542        switch (addr & 0x0f) {
1543        case 0x00: /* RDP */
1544            pcnet_csr_writew(s, s->rap, val & 0xffff);
1545            break;
1546        case 0x04:
1547            s->rap = val & 0x7f;
1548            break;
1549        case 0x0c:
1550            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1551            break;
1552        }
1553    } else
1554    if ((addr & 0x0f) == 0) {
1555        /* switch device to dword i/o mode */
1556        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1557#ifdef PCNET_DEBUG_IO
1558        printf("device switched into dword i/o mode\n");
1559#endif       
1560    }
1561    pcnet_update_irq(s);
1562}
1563
1564static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1565{
1566    PCNetState *s = opaque;
1567    uint32_t val = -1;
1568    pcnet_poll_timer(s);
1569    if (BCR_DWIO(s)) { 
1570        switch (addr & 0x0f) {
1571        case 0x00: /* RDP */
1572            val = pcnet_csr_readw(s, s->rap);
1573            break;
1574        case 0x04:
1575            val = s->rap;
1576            break;
1577        case 0x08:
1578            pcnet_s_reset(s);
1579            val = 0;
1580            break;
1581        case 0x0c:
1582            val = pcnet_bcr_readw(s, s->rap);
1583            break;
1584        }
1585    }
1586    pcnet_update_irq(s);
1587#ifdef PCNET_DEBUG_IO
1588    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1589#endif
1590    return val;
1591}
1592
1593static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, 
1594                             uint32_t addr, uint32_t size, int type)
1595{
1596    PCNetState *d = (PCNetState *)pci_dev;
1597
1598#ifdef PCNET_DEBUG_IO
1599    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
1600#endif
1601
1602    register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
1603    register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
1604   
1605    register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
1606    register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
1607    register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
1608    register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
1609}
1610
1611static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1612{
1613    PCNetState *d = opaque;
1614#ifdef PCNET_DEBUG_IO
1615    printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
1616#endif
1617    if (!(addr & 0x10))
1618        pcnet_aprom_writeb(d, addr & 0x0f, val);
1619}
1620
1621static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) 
1622{
1623    PCNetState *d = opaque;
1624    uint32_t val = -1;
1625    if (!(addr & 0x10))
1626        val = pcnet_aprom_readb(d, addr & 0x0f);
1627#ifdef PCNET_DEBUG_IO
1628    printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
1629#endif
1630    return val;
1631}
1632
1633static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1634{
1635    PCNetState *d = opaque;
1636#ifdef PCNET_DEBUG_IO
1637    printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
1638#endif
1639    if (addr & 0x10)
1640        pcnet_ioport_writew(d, addr & 0x0f, val);
1641    else {
1642        addr &= 0x0f;
1643        pcnet_aprom_writeb(d, addr, val & 0xff);
1644        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1645    }
1646}
1647
1648static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) 
1649{
1650    PCNetState *d = opaque;
1651    uint32_t val = -1;
1652    if (addr & 0x10)
1653        val = pcnet_ioport_readw(d, addr & 0x0f);
1654    else {
1655        addr &= 0x0f;
1656        val = pcnet_aprom_readb(d, addr+1);
1657        val <<= 8;
1658        val |= pcnet_aprom_readb(d, addr);
1659    }
1660#ifdef PCNET_DEBUG_IO
1661    printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
1662#endif
1663    return val;
1664}
1665
1666static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1667{
1668    PCNetState *d = opaque;
1669#ifdef PCNET_DEBUG_IO
1670    printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
1671#endif
1672    if (addr & 0x10)
1673        pcnet_ioport_writel(d, addr & 0x0f, val);
1674    else {
1675        addr &= 0x0f;
1676        pcnet_aprom_writeb(d, addr, val & 0xff);
1677        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1678        pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
1679        pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
1680    }
1681}
1682
1683static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) 
1684{
1685    PCNetState *d = opaque;
1686    uint32_t val;
1687    if (addr & 0x10)
1688        val = pcnet_ioport_readl(d, addr & 0x0f);
1689    else {
1690        addr &= 0x0f;
1691        val = pcnet_aprom_readb(d, addr+3);
1692        val <<= 8;
1693        val |= pcnet_aprom_readb(d, addr+2);
1694        val <<= 8;
1695        val |= pcnet_aprom_readb(d, addr+1);
1696        val <<= 8;
1697        val |= pcnet_aprom_readb(d, addr);
1698    }
1699#ifdef PCNET_DEBUG_IO
1700    printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
1701#endif
1702    return val;
1703}
1704
1705
1706static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
1707    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
1708    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
1709    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
1710};
1711
1712static CPUReadMemoryFunc *pcnet_mmio_read[] = {
1713    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
1714    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
1715    (CPUReadMemoryFunc *)&pcnet_mmio_readl
1716};
1717
1718static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
1719                            uint32_t addr, uint32_t size, int type)
1720{
1721    PCNetState *d = (PCNetState *)pci_dev;
1722
1723#ifdef PCNET_DEBUG_IO
1724    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
1725#endif
1726
1727    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
1728}
1729
1730
1731static void pcnet_save(QEMUFile *f, void *opaque)
1732{
1733    PCNetState *s = opaque;
1734    unsigned int i;
1735
1736    qemu_put_be32s(f, &s->rap);
1737    qemu_put_be32s(f, &s->isr);
1738    qemu_put_be32s(f, &s->lnkst);
1739    qemu_put_be32s(f, &s->rdra);
1740    qemu_put_be32s(f, &s->tdra);
1741    qemu_put_buffer(f, s->prom, 16);
1742    for (i = 0; i < 128; i++)
1743        qemu_put_be16s(f, &s->csr[i]);
1744    for (i = 0; i < 32; i++)
1745        qemu_put_be16s(f, &s->bcr[i]);
1746    qemu_put_be64s(f, &s->timer);
1747    qemu_put_be32s(f, &s->xmit_pos);
1748    qemu_put_be32s(f, &s->recv_pos);
1749    qemu_put_buffer(f, s->buffer, 4096);
1750    qemu_put_be32s(f, &s->tx_busy);
1751    qemu_put_timer(f, s->poll_timer);
1752}
1753
1754static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
1755{
1756    PCNetState *s = opaque;
1757    int i, ret;
1758
1759    if (version_id != 1)
1760        return -EINVAL;
1761
1762    qemu_get_be32s(f, &s->rap);
1763    qemu_get_be32s(f, &s->isr);
1764    qemu_get_be32s(f, &s->lnkst);
1765    qemu_get_be32s(f, &s->rdra);
1766    qemu_get_be32s(f, &s->tdra);
1767    qemu_get_buffer(f, s->prom, 16);
1768    for (i = 0; i < 128; i++)
1769        qemu_get_be16s(f, &s->csr[i]);
1770    for (i = 0; i < 32; i++)
1771        qemu_get_be16s(f, &s->bcr[i]);
1772    qemu_get_be64s(f, &s->timer);
1773    qemu_get_be32s(f, &s->xmit_pos);
1774    qemu_get_be32s(f, &s->recv_pos);
1775    qemu_get_buffer(f, s->buffer, 4096);
1776    qemu_get_be32s(f, &s->tx_busy);
1777    qemu_get_timer(f, s->poll_timer);
1778
1779    return 0;
1780}
1781
1782void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
1783{
1784    PCNetState *d;
1785    uint8_t *pci_conf;
1786    int instance;
1787
1788#if 0
1789    printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
1790        sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
1791#endif
1792
1793    d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
1794                                          -1, NULL, NULL);
1795                                         
1796    pci_conf = d->dev.config;
1797   
1798    *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
1799    *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);   
1800    *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); 
1801    *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
1802    pci_conf[0x08] = 0x10;
1803    pci_conf[0x09] = 0x00;
1804    pci_conf[0x0a] = 0x00; // ethernet network controller
1805    pci_conf[0x0b] = 0x02;
1806    pci_conf[0x0e] = 0x00; // header_type
1807   
1808    *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
1809    *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
1810   
1811    pci_conf[0x3d] = 1; // interrupt pin 0
1812    pci_conf[0x3e] = 0x06;
1813    pci_conf[0x3f] = 0xff;
1814
1815    /* Handler for memory-mapped I/O */
1816    d->mmio_io_addr =
1817      cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
1818
1819    pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, 
1820                           PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
1821                           
1822    pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
1823                           PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
1824                           
1825    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
1826
1827    d->nd = nd;
1828
1829    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, 
1830                                 pcnet_can_receive, d);
1831
1832    instance = pci_bus_num(bus) << 8 | d->dev.devfn;
1833    register_savevm("pcnet", instance, 1, pcnet_save, pcnet_load, d);
1834    register_savevm("pcnet_pci", instance, 1, generic_pci_save,
1835                    generic_pci_load, &d->dev);
1836   
1837    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
1838             "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
1839             d->nd->macaddr[0],
1840             d->nd->macaddr[1],
1841             d->nd->macaddr[2],
1842             d->nd->macaddr[3],
1843             d->nd->macaddr[4],
1844             d->nd->macaddr[5]);
1845
1846    pcnet_h_reset(d);
1847}
Note: See TracBrowser for help on using the repository browser.