Statistics
| Branch: | Revision:

root / hw / pcnet.c @ e3c2613f

History | View | Annotate | Download (53.8 kB)

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
/* XXX: suppress those headers */
33
#include <sys/times.h>
34
#include <arpa/inet.h>
35
#include <net/ethernet.h>
36

    
37
//#define PCNET_DEBUG
38
//#define PCNET_DEBUG_IO
39
//#define PCNET_DEBUG_BCR
40
//#define PCNET_DEBUG_CSR
41
//#define PCNET_DEBUG_RMD
42
//#define PCNET_DEBUG_TMD
43
//#define PCNET_DEBUG_MATCH
44

    
45

    
46
#define PCNET_IOPORT_SIZE       0x20
47
#define PCNET_PNPMMIO_SIZE      0x20
48

    
49

    
50
typedef struct PCNetState_st PCNetState;
51

    
52
struct PCNetState_st {
53
    PCIDevice dev;
54
    VLANClientState *vc;
55
    NICInfo *nd;
56
    QEMUTimer *poll_timer;
57
    int mmio_io_addr, rap, isr, lnkst;
58
    target_phys_addr_t rdra, tdra;
59
    uint8_t prom[16];
60
    uint16_t csr[128];
61
    uint16_t bcr[32];
62
    uint64_t timer;
63
    int xmit_pos, recv_pos;
64
    uint8_t buffer[4096];
65
};
66

    
67
#ifdef __GNUC__
68
#define PACKED(A) A __attribute__ ((packed))
69
#else
70
#error FixMe
71
#endif
72

    
73
/* BUS CONFIGURATION REGISTERS */
74
#define BCR_MSRDA    0
75
#define BCR_MSWRA    1
76
#define BCR_MC       2
77
#define BCR_LNKST    4
78
#define BCR_LED1     5
79
#define BCR_LED2     6
80
#define BCR_LED3     7
81
#define BCR_FDC      9
82
#define BCR_BSBC     18
83
#define BCR_EECAS    19
84
#define BCR_SWS      20
85
#define BCR_PLAT     22
86

    
87
#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
88
#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
89
#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
90

    
91
#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
92
#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
93
#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
94
#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
95
#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
96
#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
97
#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
98
#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
99
#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
100
#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
101
#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
102
#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
103
#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
104
#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
105
#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
106
#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
107
#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
108
#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
109
#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
110
#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
111

    
112
#define CSR_CRBC(S)      ((S)->csr[40])
113
#define CSR_CRST(S)      ((S)->csr[41])
114
#define CSR_CXBC(S)      ((S)->csr[42])
115
#define CSR_CXST(S)      ((S)->csr[43])
116
#define CSR_NRBC(S)      ((S)->csr[44])
117
#define CSR_NRST(S)      ((S)->csr[45])
118
#define CSR_POLL(S)      ((S)->csr[46])
119
#define CSR_PINT(S)      ((S)->csr[47])
120
#define CSR_RCVRC(S)     ((S)->csr[72])
121
#define CSR_XMTRC(S)     ((S)->csr[74])
122
#define CSR_RCVRL(S)     ((S)->csr[76])
123
#define CSR_XMTRL(S)     ((S)->csr[78])
124
#define CSR_MISSC(S)     ((S)->csr[112])
125

    
126
#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
127
#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
128
#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
129
#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
130
#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
131
#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
132
#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
133
#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
134
#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
135
#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
136
#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
137
#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
138
#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
139
#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
140

    
141
#define PHYSADDR(S,A) \
142
  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
143

    
144
struct pcnet_initblk16 {
145
    uint16_t mode;
146
    uint16_t padr1;
147
    uint16_t padr2;
148
    uint16_t padr3;
149
    uint16_t ladrf1;
150
    uint16_t ladrf2;
151
    uint16_t ladrf3;
152
    uint16_t ladrf4;
153
    unsigned PACKED(rdra:24);
154
    unsigned PACKED(res1:5);
155
    unsigned PACKED(rlen:3);
156
    unsigned PACKED(tdra:24);
157
    unsigned PACKED(res2:5);
158
    unsigned PACKED(tlen:3);
159
};
160

    
161
struct pcnet_initblk32 {
162
    uint16_t mode;
163
    unsigned PACKED(res1:4);
164
    unsigned PACKED(rlen:4);
165
    unsigned PACKED(res2:4);
166
    unsigned PACKED(tlen:4);
167
    uint16_t padr1;
168
    uint16_t padr2;
169
    uint16_t padr3;
170
    uint16_t _res;
171
    uint16_t ladrf1;
172
    uint16_t ladrf2;
173
    uint16_t ladrf3;
174
    uint16_t ladrf4;
175
    uint32_t rdra;
176
    uint32_t tdra;
177
};
178

    
179
struct pcnet_TMD {
180
    struct {
181
        unsigned tbadr:32;
182
    } tmd0;
183
    struct {
184
        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:7), PACKED(bpe:1);
185
        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(def:1), PACKED(one:1);
186
        unsigned PACKED(ltint:1), PACKED(nofcs:1), PACKED(err:1), PACKED(own:1);
187
    } tmd1;
188
    struct {
189
        unsigned PACKED(trc:4), PACKED(res:12);
190
        unsigned PACKED(tdr:10), PACKED(rtry:1), PACKED(lcar:1);
191
        unsigned PACKED(lcol:1), PACKED(exdef:1), PACKED(uflo:1), PACKED(buff:1);
192
    } tmd2;
193
    struct {
194
        unsigned res:32;
195
    } tmd3;    
196
};
197

    
198
struct pcnet_RMD {
199
    struct {
200
        unsigned rbadr:32;
201
    } rmd0;
202
    struct {
203
        unsigned PACKED(bcnt:12), PACKED(ones:4), PACKED(res:4);
204
        unsigned PACKED(bam:1), PACKED(lafm:1), PACKED(pam:1), PACKED(bpe:1);
205
        unsigned PACKED(enp:1), PACKED(stp:1), PACKED(buff:1), PACKED(crc:1);
206
        unsigned PACKED(oflo:1), PACKED(fram:1), PACKED(err:1), PACKED(own:1);
207
    } rmd1;
208
    struct {
209
        unsigned PACKED(mcnt:12), PACKED(zeros:4);
210
        unsigned PACKED(rpc:8), PACKED(rcc:8);
211
    } rmd2;    
212
    struct {
213
        unsigned res:32;
214
    } rmd3;    
215
};
216

    
217

    
218
#define PRINT_TMD(T) printf(    \
219
        "TMD0 : TBADR=0x%08x\n" \
220
        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
221
        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
222
        "       BPE=%d, BCNT=%d\n"                      \
223
        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
224
        "LCA=%d, RTR=%d,\n"                             \
225
        "       TDR=%d, TRC=%d\n",                      \
226
        (T)->tmd0.tbadr,                                \
227
        (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs,  \
228
        (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def,  \
229
        (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe,    \
230
        4096-(T)->tmd1.bcnt,                            \
231
        (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
232
        (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
233
        (T)->tmd2.tdr, (T)->tmd2.trc)
234

    
235
#define PRINT_RMD(R) printf(    \
236
        "RMD0 : RBADR=0x%08x\n" \
237
        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
238
        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
239
        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n"    \
240
        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
241
        (R)->rmd0.rbadr,                                \
242
        (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram,   \
243
        (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff,  \
244
        (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe,    \
245
        (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam,   \
246
        (R)->rmd1.ones, 4096-(R)->rmd1.bcnt,            \
247
        (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt,   \
248
        (R)->rmd2.zeros)
249

    
250
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
251
{
252
    if (!BCR_SWSTYLE(s)) {
253
        uint16_t xda[4];
254
        cpu_physical_memory_read(addr,
255
                (void *)&xda[0], sizeof(xda));
256
        ((uint32_t *)tmd)[0] = (xda[0]&0xffff) |
257
                ((xda[1]&0x00ff) << 16);
258
        ((uint32_t *)tmd)[1] = (xda[2]&0xffff)|
259
                ((xda[1] & 0xff00) << 16);
260
        ((uint32_t *)tmd)[2] =
261
                (xda[3] & 0xffff) << 16;
262
        ((uint32_t *)tmd)[3] = 0;
263
    }
264
    else
265
    if (BCR_SWSTYLE(s) != 3)
266
        cpu_physical_memory_read(addr, (void *)tmd, 16);
267
    else {
268
        uint32_t xda[4];
269
        cpu_physical_memory_read(addr,
270
                (void *)&xda[0], sizeof(xda));
271
        ((uint32_t *)tmd)[0] = xda[2];
272
        ((uint32_t *)tmd)[1] = xda[1];
273
        ((uint32_t *)tmd)[2] = xda[0];
274
        ((uint32_t *)tmd)[3] = xda[3];
275
    }
276
}
277

    
278
static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_phys_addr_t addr)
279
{
280
    if (!BCR_SWSTYLE(s)) {
281
        uint16_t xda[4];
282
        xda[0] = ((uint32_t *)tmd)[0] & 0xffff;
283
        xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) |
284
            ((((uint32_t *)tmd)[1]>>16)&0xff00);
285
        xda[2] = ((uint32_t *)tmd)[1] & 0xffff;
286
        xda[3] = ((uint32_t *)tmd)[2] >> 16;
287
        cpu_physical_memory_write(addr,
288
                (void *)&xda[0], sizeof(xda));
289
    }
290
    else {
291
        if (BCR_SWSTYLE(s) != 3)
292
            cpu_physical_memory_write(addr, (void *)tmd, 16);
293
        else {
294
            uint32_t xda[4];
295
            xda[0] = ((uint32_t *)tmd)[2];
296
            xda[1] = ((uint32_t *)tmd)[1];
297
            xda[2] = ((uint32_t *)tmd)[0];
298
            xda[3] = ((uint32_t *)tmd)[3];
299
            cpu_physical_memory_write(addr,
300
                    (void *)&xda[0], sizeof(xda));
301
        }
302
    }
303
}
304

    
305
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
306
{
307
    if (!BCR_SWSTYLE(s)) {
308
        uint16_t rda[4];
309
        cpu_physical_memory_read(addr,
310
                (void *)&rda[0], sizeof(rda));
311
        ((uint32_t *)rmd)[0] = (rda[0]&0xffff)|
312
                ((rda[1] & 0x00ff) << 16);
313
        ((uint32_t *)rmd)[1] = (rda[2]&0xffff)|
314
                ((rda[1] & 0xff00) << 16);
315
        ((uint32_t *)rmd)[2] = rda[3] & 0xffff;
316
        ((uint32_t *)rmd)[3] = 0;
317
    }
318
    else
319
    if (BCR_SWSTYLE(s) != 3)
320
        cpu_physical_memory_read(addr, (void *)rmd, 16);
321
    else {
322
        uint32_t rda[4];
323
        cpu_physical_memory_read(addr,
324
                (void *)&rda[0], sizeof(rda));
325
        ((uint32_t *)rmd)[0] = rda[2];
326
        ((uint32_t *)rmd)[1] = rda[1];
327
        ((uint32_t *)rmd)[2] = rda[0];
328
        ((uint32_t *)rmd)[3] = rda[3];
329
    }
330
}
331

    
332
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr)
333
{
334
    if (!BCR_SWSTYLE(s)) {
335
        uint16_t rda[4];                        \
336
        rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \
337
        rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\
338
            ((((uint32_t *)rmd)[1]>>16)&0xff00);\
339
        rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \
340
        rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \
341
        cpu_physical_memory_write(addr,         \
342
                (void *)&rda[0], sizeof(rda));  \
343
    }
344
    else {
345
        if (BCR_SWSTYLE(s) != 3)
346
            cpu_physical_memory_write(addr, (void *)rmd, 16);
347
        else {
348
            uint32_t rda[4];
349
            rda[0] = ((uint32_t *)rmd)[2];
350
            rda[1] = ((uint32_t *)rmd)[1];
351
            rda[2] = ((uint32_t *)rmd)[0];
352
            rda[3] = ((uint32_t *)rmd)[3];
353
            cpu_physical_memory_write(addr,
354
                    (void *)&rda[0], sizeof(rda));
355
        }
356
    }
357
}
358

    
359

    
360
#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
361

    
362
#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
363

    
364
#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
365

    
366
#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
367

    
368
#if 1
369

    
370
#define CHECK_RMD(ADDR,RES) do {                \
371
    struct pcnet_RMD rmd;                       \
372
    RMDLOAD(&rmd,(ADDR));                       \
373
    (RES) |= (rmd.rmd1.ones != 15)              \
374
          || (rmd.rmd2.zeros != 0);             \
375
} while (0)
376

    
377
#define CHECK_TMD(ADDR,RES) do {                \
378
    struct pcnet_TMD tmd;                       \
379
    TMDLOAD(&tmd,(ADDR));                       \
380
    (RES) |= (tmd.tmd1.ones != 15);             \
381
} while (0)
382

    
383
#else
384

    
385
#define CHECK_RMD(ADDR,RES) do {                \
386
    switch (BCR_SWSTYLE(s)) {                   \
387
    case 0x00:                                  \
388
        do {                                    \
389
            uint16_t rda[4];                    \
390
            cpu_physical_memory_read((ADDR),    \
391
                (void *)&rda[0], sizeof(rda));  \
392
            (RES) |= (rda[2] & 0xf000)!=0xf000; \
393
            (RES) |= (rda[3] & 0xf000)!=0x0000; \
394
        } while (0);                            \
395
        break;                                  \
396
    case 0x01:                                  \
397
    case 0x02:                                  \
398
        do {                                    \
399
            uint32_t rda[4];                    \
400
            cpu_physical_memory_read((ADDR),    \
401
                (void *)&rda[0], sizeof(rda)); \
402
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
403
            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
404
        } while (0);                            \
405
        break;                                  \
406
    case 0x03:                                  \
407
        do {                                    \
408
            uint32_t rda[4];                    \
409
            cpu_physical_memory_read((ADDR),    \
410
                (void *)&rda[0], sizeof(rda)); \
411
            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
412
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
413
        } while (0);                            \
414
        break;                                  \
415
    }                                           \
416
} while (0)
417

    
418
#define CHECK_TMD(ADDR,RES) do {                \
419
    switch (BCR_SWSTYLE(s)) {                   \
420
    case 0x00:                                  \
421
        do {                                    \
422
            uint16_t xda[4];                    \
423
            cpu_physical_memory_read((ADDR),    \
424
                (void *)&xda[0], sizeof(xda));  \
425
            (RES) |= (xda[2] & 0xf000)!=0xf000;\
426
        } while (0);                            \
427
        break;                                  \
428
    case 0x01:                                  \
429
    case 0x02:                                  \
430
    case 0x03:                                  \
431
        do {                                    \
432
            uint32_t xda[4];                    \
433
            cpu_physical_memory_read((ADDR),    \
434
                (void *)&xda[0], sizeof(xda));  \
435
            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
436
        } while (0);                            \
437
        break;                                  \
438
    }                                           \
439
} while (0)
440

    
441
#endif
442

    
443
#define PRINT_PKTHDR(BUF) do {                  \
444
    struct ether_header *hdr = (void *)(BUF);   \
445
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "       \
446
           "shost=%02x:%02x:%02x:%02x:%02x:%02x, "              \
447
           "type=0x%04x (bcast=%d)\n",                          \
448
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
449
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
450
           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
451
           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
452
           htons(hdr->ether_type),                                      \
453
           !!ETHER_IS_MULTICAST(hdr->ether_dhost));                     \
454
} while (0)
455

    
456
#define MULTICAST_FILTER_LEN 8
457

    
458
static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
459
{
460
#define LNC_POLYNOMIAL          0xEDB88320UL
461
    uint32_t crc = 0xFFFFFFFF;
462
    int idx, bit;
463
    uint8_t data;
464

    
465
    for (idx = 0; idx < ETHER_ADDR_LEN; idx++) {
466
        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
467
            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
468
            data >>= 1;
469
        }
470
    }
471
    return crc;
472
#undef LNC_POLYNOMIAL
473
}
474

    
475
#define CRC(crc, ch)         (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
476

    
477
/* generated using the AUTODIN II polynomial
478
 *        x^32 + x^26 + x^23 + x^22 + x^16 +
479
 *        x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
480
 */
481
static const uint32_t crctab[256] = {
482
        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
483
        0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
484
        0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
485
        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
486
        0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
487
        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
488
        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
489
        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
490
        0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
491
        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
492
        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
493
        0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
494
        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
495
        0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
496
        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
497
        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
498
        0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
499
        0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
500
        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
501
        0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
502
        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
503
        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
504
        0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
505
        0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
506
        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
507
        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
508
        0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
509
        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
510
        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
511
        0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
512
        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
513
        0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
514
        0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
515
        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
516
        0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
517
        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
518
        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
519
        0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
520
        0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
521
        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
522
        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
523
        0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
524
        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
525
        0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
526
        0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
527
        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
528
        0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
529
        0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
530
        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
531
        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
532
        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
533
        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
534
        0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
535
        0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
536
        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
537
        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
538
        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
539
        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
540
        0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
541
        0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
542
        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
543
        0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
544
        0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
545
        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
546
};
547

    
548
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
549
{
550
    struct ether_header *hdr = (void *)buf;
551
    uint8_t padr[6] = { 
552
        s->csr[12] & 0xff, s->csr[12] >> 8,
553
        s->csr[13] & 0xff, s->csr[13] >> 8,
554
        s->csr[14] & 0xff, s->csr[14] >> 8 
555
    };
556
    int result = (!CSR_DRCVPA(s)) && !bcmp(hdr->ether_dhost, padr, 6);
557
#ifdef PCNET_DEBUG_MATCH
558
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
559
           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
560
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
561
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
562
           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
563
    printf("padr_match result=%d\n", result);
564
#endif
565
    return result;
566
}
567

    
568
static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
569
{
570
    static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
571
    struct ether_header *hdr = (void *)buf;
572
    int result = !CSR_DRCVBC(s) && !bcmp(hdr->ether_dhost, BCAST, 6);
573
#ifdef PCNET_DEBUG_MATCH
574
    printf("padr_bcast result=%d\n", result);
575
#endif
576
    return result;
577
}
578

    
579
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
580
{
581
    struct ether_header *hdr = (void *)buf;
582
    if ((*(hdr->ether_dhost)&0x01) && 
583
        ((uint64_t *)&s->csr[8])[0] != 0LL) {
584
        uint8_t ladr[8] = { 
585
            s->csr[8] & 0xff, s->csr[8] >> 8,
586
            s->csr[9] & 0xff, s->csr[9] >> 8,
587
            s->csr[10] & 0xff, s->csr[10] >> 8, 
588
            s->csr[11] & 0xff, s->csr[11] >> 8 
589
        };
590
        int index = lnc_mchash(hdr->ether_dhost) >> 26;
591
        return !!(ladr[index >> 3] & (1 << (index & 7)));
592
    }
593
    return 0;
594
}
595

    
596
static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx) 
597
{
598
    while (idx < 1) idx += CSR_RCVRL(s);
599
    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
600
}
601

    
602
static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
603
{
604
    int64_t next_time = current_time + 
605
        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)), 
606
                 ticks_per_sec, 33000000L);
607
    if (next_time <= current_time)
608
        next_time = current_time + 1;
609
    return next_time;
610
}
611

    
612
static void pcnet_poll(PCNetState *s);
613
static void pcnet_poll_timer(void *opaque);
614

    
615
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
616
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
617
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
618
static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
619

    
620
static void pcnet_s_reset(PCNetState *s)
621
{
622
#ifdef PCNET_DEBUG
623
    printf("pcnet_s_reset\n");
624
#endif
625

    
626
    s->lnkst = 0x40;
627
    s->rdra = 0;
628
    s->tdra = 0;
629
    s->rap = 0;
630
    
631
    s->bcr[BCR_BSBC] &= ~0x0080;
632

    
633
    s->csr[0]   = 0x0004;
634
    s->csr[3]   = 0x0000;
635
    s->csr[4]   = 0x0115;
636
    s->csr[5]   = 0x0000;
637
    s->csr[6]   = 0x0000;
638
    s->csr[8]   = 0;
639
    s->csr[9]   = 0;
640
    s->csr[10]  = 0;
641
    s->csr[11]  = 0;
642
    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
643
    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
644
    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
645
    s->csr[15] &= 0x21c4;
646
    s->csr[72]  = 1;
647
    s->csr[74]  = 1;
648
    s->csr[76]  = 1;
649
    s->csr[78]  = 1;
650
    s->csr[80]  = 0x1410;
651
    s->csr[88]  = 0x1003;
652
    s->csr[89]  = 0x0262;
653
    s->csr[94]  = 0x0000;
654
    s->csr[100] = 0x0200;
655
    s->csr[103] = 0x0105;
656
    s->csr[103] = 0x0105;
657
    s->csr[112] = 0x0000;
658
    s->csr[114] = 0x0000;
659
    s->csr[122] = 0x0000;
660
    s->csr[124] = 0x0000;
661
}
662

    
663
static void pcnet_update_irq(PCNetState *s)
664
{
665
    int isr = 0;
666
    s->csr[0] &= ~0x0080;
667
    
668
#if 1
669
    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
670
        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
671
        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
672
#else
673
    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
674
        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
675
        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
676
        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
677
        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
678
        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
679
        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
680
        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
681
        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
682
        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
683
        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
684
        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
685
#endif
686
    {
687
       
688
        isr = CSR_INEA(s);
689
        s->csr[0] |= 0x0080;
690
    }
691
    
692
    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
693
        s->csr[4] &= ~0x0080;
694
        s->csr[4] |= 0x0040;
695
        s->csr[0] |= 0x0080;
696
        isr = 1;
697
#ifdef PCNET_DEBUG
698
        printf("pcnet user int\n");
699
#endif
700
    }
701

    
702
#if 1
703
    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500) 
704
#else
705
    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
706
        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
707
#endif
708
    {
709
        isr = 1;
710
        s->csr[0] |= 0x0080;
711
    }
712

    
713
    if (isr != s->isr) {
714
#ifdef PCNET_DEBUG
715
        printf("pcnet: INTA=%d\n", isr);
716
#endif
717
    }
718
        pci_set_irq(&s->dev, 0, isr);
719
        s->isr = isr;
720
}
721

    
722
static void pcnet_init(PCNetState *s)
723
{
724
#ifdef PCNET_DEBUG
725
    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
726
#endif
727
    
728
#define PCNET_INIT() do { \
729
        cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)),       \
730
                (uint8_t *)&initblk, sizeof(initblk));          \
731
        s->csr[15] = le16_to_cpu(initblk.mode);                 \
732
        CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512;  \
733
        CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512;  \
734
        s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8);        \
735
        s->csr[ 8] = le16_to_cpu(initblk.ladrf1);                       \
736
        s->csr[ 9] = le16_to_cpu(initblk.ladrf2);                       \
737
        s->csr[10] = le16_to_cpu(initblk.ladrf3);                       \
738
        s->csr[11] = le16_to_cpu(initblk.ladrf4);                       \
739
        s->csr[12] = le16_to_cpu(initblk.padr1);                        \
740
        s->csr[13] = le16_to_cpu(initblk.padr2);                        \
741
        s->csr[14] = le16_to_cpu(initblk.padr3);                        \
742
        s->rdra = PHYSADDR(s,initblk.rdra);                             \
743
        s->tdra = PHYSADDR(s,initblk.tdra);                             \
744
} while (0)
745
    
746
    if (BCR_SSIZE32(s)) {
747
        struct pcnet_initblk32 initblk;
748
        PCNET_INIT();
749
#ifdef PCNET_DEBUG
750
        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
751
                initblk.rlen, initblk.tlen);
752
#endif
753
    } else {
754
        struct pcnet_initblk16 initblk;
755
        PCNET_INIT();
756
#ifdef PCNET_DEBUG
757
        printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n",
758
                initblk.rlen, initblk.tlen);
759
#endif
760
    }
761

    
762
#undef PCNET_INIT
763

    
764
    CSR_RCVRC(s) = CSR_RCVRL(s);
765
    CSR_XMTRC(s) = CSR_XMTRL(s);
766

    
767
#ifdef PCNET_DEBUG
768
    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n", 
769
        BCR_SSIZE32(s),
770
        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
771
#endif
772

    
773
    s->csr[0] |= 0x0101;    
774
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
775
}
776

    
777
static void pcnet_start(PCNetState *s)
778
{
779
#ifdef PCNET_DEBUG
780
    printf("pcnet_start\n");
781
#endif
782

    
783
    if (!CSR_DTX(s))
784
        s->csr[0] |= 0x0010;    /* set TXON */
785
        
786
    if (!CSR_DRX(s))
787
        s->csr[0] |= 0x0020;    /* set RXON */
788

    
789
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
790
    s->csr[0] |= 0x0002;
791
}
792

    
793
static void pcnet_stop(PCNetState *s)
794
{
795
#ifdef PCNET_DEBUG
796
    printf("pcnet_stop\n");
797
#endif
798
    s->csr[0] &= ~0x7feb;
799
    s->csr[0] |= 0x0014;
800
    s->csr[4] &= ~0x02c2;
801
    s->csr[5] &= ~0x0011;
802
    pcnet_poll_timer(s);
803
}
804

    
805
static void pcnet_rdte_poll(PCNetState *s)
806
{
807
    s->csr[28] = s->csr[29] = 0;
808
    if (s->rdra) {
809
        int bad = 0;
810
#if 1
811
        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
812
        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
813
        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
814
#else
815
        target_phys_addr_t crda = s->rdra + 
816
            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
817
            (BCR_SWSTYLE(s) ? 16 : 8 );
818
        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
819
        target_phys_addr_t nrda = s->rdra + 
820
            (CSR_RCVRL(s) - nrdc) *
821
            (BCR_SWSTYLE(s) ? 16 : 8 );
822
        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
823
        target_phys_addr_t nnrd = s->rdra + 
824
            (CSR_RCVRL(s) - nnrc) *
825
            (BCR_SWSTYLE(s) ? 16 : 8 );
826
#endif
827

    
828
        CHECK_RMD(PHYSADDR(s,crda), bad);
829
        if (!bad) {
830
            CHECK_RMD(PHYSADDR(s,nrda), bad);
831
            if (bad || (nrda == crda)) nrda = 0;
832
            CHECK_RMD(PHYSADDR(s,nnrd), bad);
833
            if (bad || (nnrd == crda)) nnrd = 0;
834

    
835
            s->csr[28] = crda & 0xffff;
836
            s->csr[29] = crda >> 16;
837
            s->csr[26] = nrda & 0xffff;
838
            s->csr[27] = nrda >> 16;
839
            s->csr[36] = nnrd & 0xffff;
840
            s->csr[37] = nnrd >> 16;
841
#ifdef PCNET_DEBUG
842
            if (bad) {
843
                printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
844
                       PHYSADDR(s,crda));
845
            }
846
        } else {
847
            printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
848
#endif
849
        }
850
    }
851
    
852
    if (CSR_CRDA(s)) {
853
        struct pcnet_RMD rmd;
854
        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
855
        CSR_CRBC(s) = rmd.rmd1.bcnt;
856
        CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
857
#ifdef PCNET_DEBUG_RMD_X
858
        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
859
                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
860
                ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
861
        PRINT_RMD(&rmd);
862
#endif
863
    } else {
864
        CSR_CRBC(s) = CSR_CRST(s) = 0;
865
    }
866
    
867
    if (CSR_NRDA(s)) {
868
        struct pcnet_RMD rmd;
869
        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
870
        CSR_NRBC(s) = rmd.rmd1.bcnt;
871
        CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
872
    } else {
873
        CSR_NRBC(s) = CSR_NRST(s) = 0;
874
    }
875

    
876
}
877

    
878
static int pcnet_tdte_poll(PCNetState *s)
879
{
880
    s->csr[34] = s->csr[35] = 0;
881
    if (s->tdra) {
882
        target_phys_addr_t cxda = s->tdra + 
883
            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
884
            (BCR_SWSTYLE(s) ? 16 : 8 );
885
        int bad = 0;
886
        CHECK_TMD(PHYSADDR(s, cxda),bad);
887
        if (!bad) {
888
            if (CSR_CXDA(s) != cxda) {
889
                s->csr[60] = s->csr[34];
890
                s->csr[61] = s->csr[35];
891
                s->csr[62] = CSR_CXBC(s);
892
                s->csr[63] = CSR_CXST(s);
893
            }
894
            s->csr[34] = cxda & 0xffff;
895
            s->csr[35] = cxda >> 16;
896
#ifdef PCNET_DEBUG
897
        } else {
898
            printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
899
#endif
900
        }
901
    }
902

    
903
    if (CSR_CXDA(s)) {
904
        struct pcnet_TMD tmd;
905

    
906
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
907

    
908
        CSR_CXBC(s) = tmd.tmd1.bcnt;
909
        CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
910
    } else {
911
        CSR_CXBC(s) = CSR_CXST(s) = 0;
912
    }
913
    
914
    return !!(CSR_CXST(s) & 0x8000);
915
}
916

    
917
static int pcnet_can_receive(void *opaque)
918
{
919
    PCNetState *s = opaque;
920
    if (CSR_STOP(s) || CSR_SPND(s))
921
        return 0;
922
        
923
    if (s->recv_pos > 0)
924
        return 0;
925

    
926
    return sizeof(s->buffer)-16;
927
}
928

    
929
#define MIN_BUF_SIZE 60
930

    
931
static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
932
{
933
    PCNetState *s = opaque;
934
    int is_padr = 0, is_bcast = 0, is_ladr = 0;
935
    uint8_t buf1[60];
936

    
937
    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
938
        return;
939

    
940
#ifdef PCNET_DEBUG
941
    printf("pcnet_receive size=%d\n", size);
942
#endif
943

    
944
    /* if too small buffer, then expand it */
945
    if (size < MIN_BUF_SIZE) {
946
        memcpy(buf1, buf, size);
947
        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
948
        buf = buf1;
949
        size = MIN_BUF_SIZE;
950
    }
951

    
952
    if (CSR_PROM(s) 
953
        || (is_padr=padr_match(s, buf, size)) 
954
        || (is_bcast=padr_bcast(s, buf, size))
955
        || (is_ladr=ladr_match(s, buf, size))) {
956

    
957
        pcnet_rdte_poll(s);
958

    
959
        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
960
            struct pcnet_RMD rmd;
961
            int rcvrc = CSR_RCVRC(s)-1,i;
962
            target_phys_addr_t nrda;
963
            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
964
                if (rcvrc <= 1)
965
                    rcvrc = CSR_RCVRL(s);
966
                nrda = s->rdra +
967
                    (CSR_RCVRL(s) - rcvrc) *
968
                    (BCR_SWSTYLE(s) ? 16 : 8 );
969
                RMDLOAD(&rmd, PHYSADDR(s,nrda));                  
970
                if (rmd.rmd1.own) {                
971
#ifdef PCNET_DEBUG_RMD
972
                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n", 
973
                                rcvrc, CSR_RCVRC(s));
974
#endif
975
                    CSR_RCVRC(s) = rcvrc;
976
                    pcnet_rdte_poll(s);
977
                    break;
978
                }
979
            }
980
        }
981

    
982
        if (!(CSR_CRST(s) & 0x8000)) {
983
#ifdef PCNET_DEBUG_RMD
984
            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
985
#endif
986
            s->csr[0] |= 0x1000; /* Set MISS flag */
987
            CSR_MISSC(s)++;
988
        } else {
989
            uint8_t *src = &s->buffer[8];
990
            target_phys_addr_t crda = CSR_CRDA(s);
991
            struct pcnet_RMD rmd;
992
            int pktcount = 0;
993

    
994
            memcpy(src, buf, size);
995
            
996
            /* XXX: avoid CRC generation */
997
            if (!CSR_ASTRP_RCV(s)) {
998
                uint32_t fcs = ~0;
999
#if 0            
1000
                uint8_t *p = s->buffer;
1001
                
1002
                ((uint32_t *)p)[0] = ((uint32_t *)p)[1] = 0xaaaaaaaa;
1003
                p[7] = 0xab;
1004
#else
1005
                uint8_t *p = src;
1006
#endif
1007

    
1008
                while (size < 46) {
1009
                    src[size++] = 0;
1010
                }
1011
                
1012
                while (p != &src[size]) {
1013
                    CRC(fcs, *p++);
1014
                }
1015
                ((uint32_t *)&src[size])[0] = htonl(fcs);
1016
                size += 4; /* FCS at end of packet */
1017
            } else size += 4;
1018

    
1019
#ifdef PCNET_DEBUG_MATCH
1020
            PRINT_PKTHDR(buf);
1021
#endif
1022

    
1023
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1024
            /*if (!CSR_LAPPEN(s))*/
1025
                rmd.rmd1.stp = 1;
1026

    
1027
#define PCNET_RECV_STORE() do {                                 \
1028
    int count = MIN(4096 - rmd.rmd1.bcnt,size);                 \
1029
    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr);     \
1030
    cpu_physical_memory_write(rbadr, src, count);               \
1031
    src += count; size -= count;                                \
1032
    rmd.rmd2.mcnt = count; rmd.rmd1.own = 0;                    \
1033
    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1034
    pktcount++;                                                 \
1035
} while (0)
1036

    
1037
            PCNET_RECV_STORE();
1038
            if ((size > 0) && CSR_NRDA(s)) {
1039
                target_phys_addr_t nrda = CSR_NRDA(s);
1040
                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1041
                if (rmd.rmd1.own) {
1042
                    crda = nrda;
1043
                    PCNET_RECV_STORE();
1044
                    if ((size > 0) && (nrda=CSR_NNRD(s))) {
1045
                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1046
                        if (rmd.rmd1.own) {
1047
                            crda = nrda;
1048
                            PCNET_RECV_STORE();
1049
                        }
1050
                    }
1051
                }                
1052
            }
1053

    
1054
#undef PCNET_RECV_STORE
1055

    
1056
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1057
            if (size == 0) {
1058
                rmd.rmd1.enp = 1;
1059
                rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
1060
                rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
1061
                rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
1062
            } else {
1063
                rmd.rmd1.oflo = 1;
1064
                rmd.rmd1.buff = 1;
1065
                rmd.rmd1.err = 1;
1066
            }
1067
            RMDSTORE(&rmd, PHYSADDR(s,crda));
1068
            s->csr[0] |= 0x0400;
1069

    
1070
#ifdef PCNET_DEBUG
1071
            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n", 
1072
                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1073
#endif
1074
#ifdef PCNET_DEBUG_RMD
1075
            PRINT_RMD(&rmd);
1076
#endif        
1077

    
1078
            while (pktcount--) {
1079
                if (CSR_RCVRC(s) <= 1)
1080
                    CSR_RCVRC(s) = CSR_RCVRL(s);
1081
                else
1082
                    CSR_RCVRC(s)--;            
1083
            }
1084
            
1085
            pcnet_rdte_poll(s);
1086

    
1087
        }        
1088
    }
1089

    
1090
    pcnet_poll(s);
1091
    pcnet_update_irq(s);    
1092
}
1093

    
1094
static void pcnet_transmit(PCNetState *s)
1095
{
1096
    target_phys_addr_t xmit_cxda = 0;
1097
    int count = CSR_XMTRL(s)-1;
1098
    s->xmit_pos = -1;
1099
    
1100
    if (!CSR_TXON(s)) {
1101
        s->csr[0] &= ~0x0008;
1102
        return;
1103
    }
1104
    
1105
    txagain:
1106
    if (pcnet_tdte_poll(s)) {
1107
        struct pcnet_TMD tmd;
1108

    
1109
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));                
1110

    
1111
#ifdef PCNET_DEBUG_TMD
1112
        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1113
        PRINT_TMD(&tmd);
1114
#endif
1115
        if (tmd.tmd1.stp) {
1116
            s->xmit_pos = 0;                
1117
            if (!tmd.tmd1.enp) {
1118
                cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
1119
                        s->buffer, 4096 - tmd.tmd1.bcnt);
1120
                s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1121
            } 
1122
            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1123
        }
1124
        if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
1125
            cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr),
1126
                    s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
1127
            s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1128
#ifdef PCNET_DEBUG
1129
            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1130
#endif            
1131
            if (CSR_LOOP(s))
1132
                pcnet_receive(s, s->buffer, s->xmit_pos);
1133
            else
1134
                qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
1135

    
1136
            s->csr[0] &= ~0x0008;   /* clear TDMD */
1137
            s->csr[4] |= 0x0004;    /* set TXSTRT */
1138
            s->xmit_pos = -1;
1139
        }
1140

    
1141
        tmd.tmd1.own = 0;
1142
        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1143
        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
1144
            s->csr[0] |= 0x0200;    /* set TINT */
1145

    
1146
        if (CSR_XMTRC(s)<=1)
1147
            CSR_XMTRC(s) = CSR_XMTRL(s);
1148
        else
1149
            CSR_XMTRC(s)--;
1150
        if (count--)
1151
            goto txagain;
1152

    
1153
    } else 
1154
    if (s->xmit_pos >= 0) {
1155
        struct pcnet_TMD tmd;
1156
        TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));                
1157
        tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
1158
        tmd.tmd1.own = 0;
1159
        TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
1160
        s->csr[0] |= 0x0200;    /* set TINT */
1161
        if (!CSR_DXSUFLO(s)) {
1162
            s->csr[0] &= ~0x0010;
1163
        } else
1164
        if (count--)
1165
          goto txagain;
1166
    }
1167
}
1168

    
1169
static void pcnet_poll(PCNetState *s)
1170
{
1171
    if (CSR_RXON(s)) {
1172
        pcnet_rdte_poll(s);
1173
    }
1174

    
1175
    if (CSR_TDMD(s) || 
1176
        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1177
        pcnet_transmit(s);
1178
}
1179

    
1180
static void pcnet_poll_timer(void *opaque)
1181
{
1182
    PCNetState *s = opaque;
1183

    
1184
    qemu_del_timer(s->poll_timer);
1185

    
1186
    if (CSR_TDMD(s)) {
1187
        pcnet_transmit(s);
1188
    }
1189

    
1190
    pcnet_update_irq(s);    
1191

    
1192
    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1193
        uint64_t now = qemu_get_clock(vm_clock) * 33;
1194
        if (!s->timer || !now)
1195
            s->timer = now;
1196
        else {
1197
            uint64_t t = now - s->timer + CSR_POLL(s);
1198
            if (t > 0xffffLL) {
1199
                pcnet_poll(s);
1200
                CSR_POLL(s) = CSR_PINT(s);
1201
            } else
1202
                CSR_POLL(s) = t;
1203
        }
1204
        qemu_mod_timer(s->poll_timer, 
1205
            pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
1206
    }
1207
}
1208

    
1209

    
1210
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1211
{
1212
    uint16_t val = new_value;
1213
#ifdef PCNET_DEBUG_CSR
1214
    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1215
#endif
1216
    switch (rap) {
1217
    case 0:
1218
        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1219

    
1220
        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1221

    
1222
        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1223

    
1224
        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1225
        if ((val&7) == 7)
1226
          val &= ~3;
1227

    
1228
        if (!CSR_STOP(s) && (val & 4))
1229
            pcnet_stop(s);
1230

    
1231
        if (!CSR_INIT(s) && (val & 1))
1232
            pcnet_init(s);
1233

    
1234
        if (!CSR_STRT(s) && (val & 2))
1235
            pcnet_start(s);
1236

    
1237
        if (CSR_TDMD(s)) 
1238
            pcnet_transmit(s);
1239

    
1240
        return;
1241
    case 1:
1242
    case 2:
1243
    case 8:
1244
    case 9:
1245
    case 10:
1246
    case 11:
1247
    case 12:
1248
    case 13:
1249
    case 14:
1250
    case 15:
1251
    case 18: /* CRBAL */
1252
    case 19: /* CRBAU */
1253
    case 20: /* CXBAL */
1254
    case 21: /* CXBAU */
1255
    case 22: /* NRBAU */
1256
    case 23: /* NRBAU */
1257
    case 24:
1258
    case 25:
1259
    case 26:
1260
    case 27:
1261
    case 28:
1262
    case 29:
1263
    case 30:
1264
    case 31:
1265
    case 32:
1266
    case 33:
1267
    case 34:
1268
    case 35:
1269
    case 36:
1270
    case 37:
1271
    case 38:
1272
    case 39:
1273
    case 40: /* CRBC */
1274
    case 41:
1275
    case 42: /* CXBC */
1276
    case 43:
1277
    case 44:
1278
    case 45:
1279
    case 46: /* POLL */
1280
    case 47: /* POLLINT */
1281
    case 72:
1282
    case 74:
1283
    case 76: /* RCVRL */
1284
    case 78: /* XMTRL */
1285
    case 112:
1286
       if (CSR_STOP(s) || CSR_SPND(s))
1287
           break;
1288
       return;
1289
    case 3:
1290
        break;
1291
    case 4:
1292
        s->csr[4] &= ~(val & 0x026a); 
1293
        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1294
        break;
1295
    case 5:
1296
        s->csr[5] &= ~(val & 0x0a90); 
1297
        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1298
        break;
1299
    case 16:
1300
        pcnet_csr_writew(s,1,val);
1301
        return;
1302
    case 17:
1303
        pcnet_csr_writew(s,2,val);
1304
        return;
1305
    case 58:
1306
        pcnet_bcr_writew(s,BCR_SWS,val);
1307
        break;
1308
    default:
1309
        return;
1310
    }
1311
    s->csr[rap] = val;
1312
}
1313

    
1314
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1315
{
1316
    uint32_t val;
1317
    switch (rap) {
1318
    case 0:
1319
        pcnet_update_irq(s);
1320
        val = s->csr[0];
1321
        val |= (val & 0x7800) ? 0x8000 : 0;
1322
        break;
1323
    case 16:
1324
        return pcnet_csr_readw(s,1);
1325
    case 17:
1326
        return pcnet_csr_readw(s,2);
1327
    case 58:
1328
        return pcnet_bcr_readw(s,BCR_SWS);
1329
    case 88:
1330
        val = s->csr[89];
1331
        val <<= 16;
1332
        val |= s->csr[88];
1333
        break;
1334
    default:
1335
        val = s->csr[rap];
1336
    }
1337
#ifdef PCNET_DEBUG_CSR
1338
    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1339
#endif
1340
    return val;
1341
}
1342

    
1343
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1344
{
1345
    rap &= 127;
1346
#ifdef PCNET_DEBUG_BCR
1347
    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1348
#endif
1349
    switch (rap) {
1350
    case BCR_SWS:
1351
        if (!(CSR_STOP(s) || CSR_SPND(s)))
1352
            return;
1353
        val &= ~0x0300;
1354
        switch (val & 0x00ff) {
1355
        case 0:
1356
            val |= 0x0200;
1357
            break;
1358
        case 1:
1359
            val |= 0x0100;
1360
            break;
1361
        case 2:
1362
        case 3:
1363
            val |= 0x0300;
1364
            break;
1365
        default:
1366
            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1367
            val = 0x0200;
1368
            break;
1369
        }
1370
#ifdef PCNET_DEBUG
1371
       printf("BCR_SWS=0x%04x\n", val);
1372
#endif
1373
    case BCR_LNKST:
1374
    case BCR_LED1:
1375
    case BCR_LED2:
1376
    case BCR_LED3:
1377
    case BCR_MC:
1378
    case BCR_FDC:
1379
    case BCR_BSBC:
1380
    case BCR_EECAS:
1381
    case BCR_PLAT:
1382
        s->bcr[rap] = val;
1383
        break;
1384
    default:
1385
        break;
1386
    }
1387
}
1388

    
1389
static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1390
{
1391
    uint32_t val;
1392
    rap &= 127;
1393
    switch (rap) {
1394
    case BCR_LNKST:
1395
    case BCR_LED1:
1396
    case BCR_LED2:
1397
    case BCR_LED3:
1398
        val = s->bcr[rap] & ~0x8000;
1399
        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1400
        break;
1401
    default:
1402
        val = rap < 32 ? s->bcr[rap] : 0;
1403
        break;
1404
    }
1405
#ifdef PCNET_DEBUG_BCR
1406
    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1407
#endif
1408
    return val;
1409
}
1410

    
1411
static void pcnet_h_reset(PCNetState *s)
1412
{
1413
    int i;
1414
    uint16_t checksum;
1415

    
1416
    /* Initialize the PROM */
1417

    
1418
    memcpy(s->prom, s->nd->macaddr, 6);
1419
    s->prom[12] = s->prom[13] = 0x00;
1420
    s->prom[14] = s->prom[15] = 0x57;
1421

    
1422
    for (i = 0,checksum = 0; i < 16; i++)
1423
        checksum += s->prom[i];
1424
    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1425

    
1426

    
1427
    s->bcr[BCR_MSRDA] = 0x0005;
1428
    s->bcr[BCR_MSWRA] = 0x0005;
1429
    s->bcr[BCR_MC   ] = 0x0002;
1430
    s->bcr[BCR_LNKST] = 0x00c0;
1431
    s->bcr[BCR_LED1 ] = 0x0084;
1432
    s->bcr[BCR_LED2 ] = 0x0088;
1433
    s->bcr[BCR_LED3 ] = 0x0090;
1434
    s->bcr[BCR_FDC  ] = 0x0000;
1435
    s->bcr[BCR_BSBC ] = 0x9001;
1436
    s->bcr[BCR_EECAS] = 0x0002;
1437
    s->bcr[BCR_SWS  ] = 0x0200;
1438
    s->bcr[BCR_PLAT ] = 0xff06;
1439

    
1440
    pcnet_s_reset(s);
1441
}
1442

    
1443
static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
1444
{
1445
    PCNetState *s = opaque;
1446
#ifdef PCNET_DEBUG
1447
    printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
1448
#endif    
1449
    /* Check APROMWE bit to enable write access */
1450
    if (pcnet_bcr_readw(s,2) & 0x80)
1451
        s->prom[addr & 15] = val;
1452
}       
1453

    
1454
static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
1455
{
1456
    PCNetState *s = opaque;
1457
    uint32_t val = s->prom[addr &= 15];
1458
#ifdef PCNET_DEBUG
1459
    printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
1460
#endif
1461
    return val;
1462
}
1463

    
1464
static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1465
{
1466
    PCNetState *s = opaque;
1467
    pcnet_poll_timer(s);
1468
#ifdef PCNET_DEBUG_IO
1469
    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1470
#endif
1471
    if (!BCR_DWIO(s)) {
1472
        switch (addr & 0x0f) {
1473
        case 0x00: /* RDP */
1474
            pcnet_csr_writew(s, s->rap, val);
1475
            break;
1476
        case 0x02:
1477
            s->rap = val & 0x7f;
1478
            break;
1479
        case 0x06:
1480
            pcnet_bcr_writew(s, s->rap, val);
1481
            break;
1482
        }
1483
    }
1484
    pcnet_update_irq(s);
1485
}
1486

    
1487
static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1488
{
1489
    PCNetState *s = opaque;
1490
    uint32_t val = -1;
1491
    pcnet_poll_timer(s);
1492
    if (!BCR_DWIO(s)) {
1493
        switch (addr & 0x0f) {
1494
        case 0x00: /* RDP */
1495
            val = pcnet_csr_readw(s, s->rap);
1496
            break;
1497
        case 0x02:
1498
            val = s->rap;
1499
            break;
1500
        case 0x04:
1501
            pcnet_s_reset(s);
1502
            val = 0;
1503
            break;
1504
        case 0x06:
1505
            val = pcnet_bcr_readw(s, s->rap);
1506
            break;
1507
        }
1508
    }
1509
    pcnet_update_irq(s);
1510
#ifdef PCNET_DEBUG_IO
1511
    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1512
#endif
1513
    return val;
1514
}
1515

    
1516
static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1517
{
1518
    PCNetState *s = opaque;
1519
    pcnet_poll_timer(s);
1520
#ifdef PCNET_DEBUG_IO
1521
    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1522
#endif
1523
    if (BCR_DWIO(s)) {
1524
        switch (addr & 0x0f) {
1525
        case 0x00: /* RDP */
1526
            pcnet_csr_writew(s, s->rap, val & 0xffff);
1527
            break;
1528
        case 0x04:
1529
            s->rap = val & 0x7f;
1530
            break;
1531
        case 0x0c:
1532
            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1533
            break;
1534
        }
1535
    } else
1536
    if ((addr & 0x0f) == 0) {
1537
        /* switch device to dword i/o mode */
1538
        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1539
#ifdef PCNET_DEBUG_IO
1540
        printf("device switched into dword i/o mode\n");
1541
#endif        
1542
    }
1543
    pcnet_update_irq(s);
1544
}
1545

    
1546
static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1547
{
1548
    PCNetState *s = opaque;
1549
    uint32_t val = -1;
1550
    pcnet_poll_timer(s);
1551
    if (BCR_DWIO(s)) {  
1552
        switch (addr & 0x0f) {
1553
        case 0x00: /* RDP */
1554
            val = pcnet_csr_readw(s, s->rap);
1555
            break;
1556
        case 0x04:
1557
            val = s->rap;
1558
            break;
1559
        case 0x08:
1560
            pcnet_s_reset(s);
1561
            val = 0;
1562
            break;
1563
        case 0x0c:
1564
            val = pcnet_bcr_readw(s, s->rap);
1565
            break;
1566
        }
1567
    }
1568
    pcnet_update_irq(s);
1569
#ifdef PCNET_DEBUG_IO
1570
    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1571
#endif
1572
    return val;
1573
}
1574

    
1575
static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num, 
1576
                             uint32_t addr, uint32_t size, int type)
1577
{
1578
    PCNetState *d = (PCNetState *)pci_dev;
1579

    
1580
#ifdef PCNET_DEBUG_IO
1581
    printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
1582
#endif
1583

    
1584
    register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
1585
    register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
1586
    
1587
    register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
1588
    register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
1589
    register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
1590
    register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
1591
}
1592

    
1593
static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1594
{
1595
    PCNetState *d = opaque;
1596
#ifdef PCNET_DEBUG_IO
1597
    printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
1598
#endif
1599
    if (!(addr & 0x10))
1600
        pcnet_aprom_writeb(d, addr & 0x0f, val);
1601
}
1602

    
1603
static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr) 
1604
{
1605
    PCNetState *d = opaque;
1606
    uint32_t val = -1;
1607
    if (!(addr & 0x10))
1608
        val = pcnet_aprom_readb(d, addr & 0x0f);
1609
#ifdef PCNET_DEBUG_IO
1610
    printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
1611
#endif
1612
    return val;
1613
}
1614

    
1615
static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1616
{
1617
    PCNetState *d = opaque;
1618
#ifdef PCNET_DEBUG_IO
1619
    printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
1620
#endif
1621
    if (addr & 0x10)
1622
        pcnet_ioport_writew(d, addr & 0x0f, val);
1623
    else {
1624
        addr &= 0x0f;
1625
        pcnet_aprom_writeb(d, addr, val & 0xff);
1626
        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1627
    }
1628
}
1629

    
1630
static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr) 
1631
{
1632
    PCNetState *d = opaque;
1633
    uint32_t val = -1;
1634
    if (addr & 0x10)
1635
        val = pcnet_ioport_readw(d, addr & 0x0f);
1636
    else {
1637
        addr &= 0x0f;
1638
        val = pcnet_aprom_readb(d, addr+1);
1639
        val <<= 8;
1640
        val |= pcnet_aprom_readb(d, addr);
1641
    }
1642
#ifdef PCNET_DEBUG_IO
1643
    printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
1644
#endif
1645
    return val;
1646
}
1647

    
1648
static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1649
{
1650
    PCNetState *d = opaque;
1651
#ifdef PCNET_DEBUG_IO
1652
    printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
1653
#endif
1654
    if (addr & 0x10)
1655
        pcnet_ioport_writel(d, addr & 0x0f, val);
1656
    else {
1657
        addr &= 0x0f;
1658
        pcnet_aprom_writeb(d, addr, val & 0xff);
1659
        pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1660
        pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
1661
        pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
1662
    }
1663
}
1664

    
1665
static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) 
1666
{
1667
    PCNetState *d = opaque;
1668
    uint32_t val;
1669
    if (addr & 0x10)
1670
        val = pcnet_ioport_readl(d, addr & 0x0f);
1671
    else {
1672
        addr &= 0x0f;
1673
        val = pcnet_aprom_readb(d, addr+3);
1674
        val <<= 8;
1675
        val |= pcnet_aprom_readb(d, addr+2);
1676
        val <<= 8;
1677
        val |= pcnet_aprom_readb(d, addr+1);
1678
        val <<= 8;
1679
        val |= pcnet_aprom_readb(d, addr);
1680
    }
1681
#ifdef PCNET_DEBUG_IO
1682
    printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
1683
#endif
1684
    return val;
1685
}
1686

    
1687

    
1688
static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
1689
    (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
1690
    (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
1691
    (CPUWriteMemoryFunc *)&pcnet_mmio_writel
1692
};
1693

    
1694
static CPUReadMemoryFunc *pcnet_mmio_read[] = {
1695
    (CPUReadMemoryFunc *)&pcnet_mmio_readb,
1696
    (CPUReadMemoryFunc *)&pcnet_mmio_readw,
1697
    (CPUReadMemoryFunc *)&pcnet_mmio_readl
1698
};
1699

    
1700
static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, 
1701
                            uint32_t addr, uint32_t size, int type)
1702
{
1703
    PCNetState *d = (PCNetState *)pci_dev;
1704

    
1705
#ifdef PCNET_DEBUG_IO
1706
    printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
1707
#endif
1708

    
1709
    cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr);
1710
}
1711

    
1712
void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
1713
{
1714
    PCNetState *d;
1715
    uint8_t *pci_conf;
1716

    
1717
#if 0
1718
    printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n", 
1719
        sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
1720
#endif
1721

    
1722
    d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
1723
                                          -1, NULL, NULL);
1724
                                          
1725
    pci_conf = d->dev.config;
1726
    
1727
    *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
1728
    *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);    
1729
    *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007); 
1730
    *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
1731
    pci_conf[0x08] = 0x10;
1732
    pci_conf[0x09] = 0x00;
1733
    pci_conf[0x0a] = 0x00; // ethernet network controller 
1734
    pci_conf[0x0b] = 0x02;
1735
    pci_conf[0x0e] = 0x00; // header_type
1736
    
1737
    *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
1738
    *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
1739
    
1740
    pci_conf[0x3d] = 1; // interrupt pin 0
1741
    pci_conf[0x3e] = 0x06;
1742
    pci_conf[0x3f] = 0xff;
1743

    
1744
    /* Handler for memory-mapped I/O */
1745
    d->mmio_io_addr =
1746
      cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
1747

    
1748
    pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, 
1749
                           PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
1750
                           
1751
    pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, 
1752
                           PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
1753
                           
1754
    d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
1755

    
1756
    d->nd = nd;
1757

    
1758
    d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, 
1759
                                 pcnet_can_receive, d);
1760
    
1761
    snprintf(d->vc->info_str, sizeof(d->vc->info_str),
1762
             "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
1763
             d->nd->macaddr[0],
1764
             d->nd->macaddr[1],
1765
             d->nd->macaddr[2],
1766
             d->nd->macaddr[3],
1767
             d->nd->macaddr[4],
1768
             d->nd->macaddr[5]);
1769

    
1770
    pcnet_h_reset(d);
1771
}