Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 9c17d615

History | View | Annotate | Download (54.5 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
/*
31
 * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also
32
 * produced as NCR89C100. See
33
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
34
 * and
35
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
36
 */
37

    
38
#include "qdev.h"
39
#include "net/net.h"
40
#include "qemu/timer.h"
41
#include "qemu/sockets.h"
42
#include "sysemu/sysemu.h"
43

    
44
#include "pcnet.h"
45

    
46
//#define PCNET_DEBUG
47
//#define PCNET_DEBUG_IO
48
//#define PCNET_DEBUG_BCR
49
//#define PCNET_DEBUG_CSR
50
//#define PCNET_DEBUG_RMD
51
//#define PCNET_DEBUG_TMD
52
//#define PCNET_DEBUG_MATCH
53

    
54

    
55
struct qemu_ether_header {
56
    uint8_t ether_dhost[6];
57
    uint8_t ether_shost[6];
58
    uint16_t ether_type;
59
};
60

    
61
#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
62
#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
63
#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
64
#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
65
#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
66
#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
67
#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
68
#define CSR_BSWP(S)      !!(((S)->csr[3])&0x0004)
69
#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
70
#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
71
#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
72
#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
73
#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
74
#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
75
#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
76
#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
77
#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
78
#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
79
#define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
80
#define CSR_INTL(S)      !!(((S)->csr[15])&0x0040)
81
#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
82
#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
83
#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
84

    
85
#define CSR_CRBC(S)      ((S)->csr[40])
86
#define CSR_CRST(S)      ((S)->csr[41])
87
#define CSR_CXBC(S)      ((S)->csr[42])
88
#define CSR_CXST(S)      ((S)->csr[43])
89
#define CSR_NRBC(S)      ((S)->csr[44])
90
#define CSR_NRST(S)      ((S)->csr[45])
91
#define CSR_POLL(S)      ((S)->csr[46])
92
#define CSR_PINT(S)      ((S)->csr[47])
93
#define CSR_RCVRC(S)     ((S)->csr[72])
94
#define CSR_XMTRC(S)     ((S)->csr[74])
95
#define CSR_RCVRL(S)     ((S)->csr[76])
96
#define CSR_XMTRL(S)     ((S)->csr[78])
97
#define CSR_MISSC(S)     ((S)->csr[112])
98

    
99
#define CSR_IADR(S)      ((S)->csr[ 1] | ((uint32_t)(S)->csr[ 2] << 16))
100
#define CSR_CRBA(S)      ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16))
101
#define CSR_CXBA(S)      ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16))
102
#define CSR_NRBA(S)      ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16))
103
#define CSR_BADR(S)      ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16))
104
#define CSR_NRDA(S)      ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16))
105
#define CSR_CRDA(S)      ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16))
106
#define CSR_BADX(S)      ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16))
107
#define CSR_NXDA(S)      ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16))
108
#define CSR_CXDA(S)      ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16))
109
#define CSR_NNRD(S)      ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16))
110
#define CSR_NNXD(S)      ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16))
111
#define CSR_PXDA(S)      ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16))
112
#define CSR_NXBA(S)      ((S)->csr[64] | ((uint32_t)(S)->csr[65] << 16))
113

    
114
#define PHYSADDR(S,A) \
115
  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
116

    
117
struct pcnet_initblk16 {
118
    uint16_t mode;
119
    uint16_t padr[3];
120
    uint16_t ladrf[4];
121
    uint32_t rdra;
122
    uint32_t tdra;
123
};
124

    
125
struct pcnet_initblk32 {
126
    uint16_t mode;
127
    uint8_t rlen;
128
    uint8_t tlen;
129
    uint16_t padr[3];
130
    uint16_t _res;
131
    uint16_t ladrf[4];
132
    uint32_t rdra;
133
    uint32_t tdra;
134
};
135

    
136
struct pcnet_TMD {
137
    uint32_t tbadr;
138
    int16_t length;
139
    int16_t status;
140
    uint32_t misc;
141
    uint32_t res;
142
};
143

    
144
#define TMDL_BCNT_MASK  0x0fff
145
#define TMDL_BCNT_SH    0
146
#define TMDL_ONES_MASK  0xf000
147
#define TMDL_ONES_SH    12
148

    
149
#define TMDS_BPE_MASK   0x0080
150
#define TMDS_BPE_SH     7
151
#define TMDS_ENP_MASK   0x0100
152
#define TMDS_ENP_SH     8
153
#define TMDS_STP_MASK   0x0200
154
#define TMDS_STP_SH     9
155
#define TMDS_DEF_MASK   0x0400
156
#define TMDS_DEF_SH     10
157
#define TMDS_ONE_MASK   0x0800
158
#define TMDS_ONE_SH     11
159
#define TMDS_LTINT_MASK 0x1000
160
#define TMDS_LTINT_SH   12
161
#define TMDS_NOFCS_MASK 0x2000
162
#define TMDS_NOFCS_SH   13
163
#define TMDS_ADDFCS_MASK TMDS_NOFCS_MASK
164
#define TMDS_ADDFCS_SH  TMDS_NOFCS_SH
165
#define TMDS_ERR_MASK   0x4000
166
#define TMDS_ERR_SH     14
167
#define TMDS_OWN_MASK   0x8000
168
#define TMDS_OWN_SH     15
169

    
170
#define TMDM_TRC_MASK   0x0000000f
171
#define TMDM_TRC_SH     0
172
#define TMDM_TDR_MASK   0x03ff0000
173
#define TMDM_TDR_SH     16
174
#define TMDM_RTRY_MASK  0x04000000
175
#define TMDM_RTRY_SH    26
176
#define TMDM_LCAR_MASK  0x08000000
177
#define TMDM_LCAR_SH    27
178
#define TMDM_LCOL_MASK  0x10000000
179
#define TMDM_LCOL_SH    28
180
#define TMDM_EXDEF_MASK 0x20000000
181
#define TMDM_EXDEF_SH   29
182
#define TMDM_UFLO_MASK  0x40000000
183
#define TMDM_UFLO_SH    30
184
#define TMDM_BUFF_MASK  0x80000000
185
#define TMDM_BUFF_SH    31
186

    
187
struct pcnet_RMD {
188
    uint32_t rbadr;
189
    int16_t buf_length;
190
    int16_t status;
191
    uint32_t msg_length;
192
    uint32_t res;
193
};
194

    
195
#define RMDL_BCNT_MASK  0x0fff
196
#define RMDL_BCNT_SH    0
197
#define RMDL_ONES_MASK  0xf000
198
#define RMDL_ONES_SH    12
199

    
200
#define RMDS_BAM_MASK   0x0010
201
#define RMDS_BAM_SH     4
202
#define RMDS_LFAM_MASK  0x0020
203
#define RMDS_LFAM_SH    5
204
#define RMDS_PAM_MASK   0x0040
205
#define RMDS_PAM_SH     6
206
#define RMDS_BPE_MASK   0x0080
207
#define RMDS_BPE_SH     7
208
#define RMDS_ENP_MASK   0x0100
209
#define RMDS_ENP_SH     8
210
#define RMDS_STP_MASK   0x0200
211
#define RMDS_STP_SH     9
212
#define RMDS_BUFF_MASK  0x0400
213
#define RMDS_BUFF_SH    10
214
#define RMDS_CRC_MASK   0x0800
215
#define RMDS_CRC_SH     11
216
#define RMDS_OFLO_MASK  0x1000
217
#define RMDS_OFLO_SH    12
218
#define RMDS_FRAM_MASK  0x2000
219
#define RMDS_FRAM_SH    13
220
#define RMDS_ERR_MASK   0x4000
221
#define RMDS_ERR_SH     14
222
#define RMDS_OWN_MASK   0x8000
223
#define RMDS_OWN_SH     15
224

    
225
#define RMDM_MCNT_MASK  0x00000fff
226
#define RMDM_MCNT_SH    0
227
#define RMDM_ZEROS_MASK 0x0000f000
228
#define RMDM_ZEROS_SH   12
229
#define RMDM_RPC_MASK   0x00ff0000
230
#define RMDM_RPC_SH     16
231
#define RMDM_RCC_MASK   0xff000000
232
#define RMDM_RCC_SH     24
233

    
234
#define SET_FIELD(regp, name, field, value)             \
235
  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
236
             | ((value) << name ## _ ## field ## _SH))
237

    
238
#define GET_FIELD(reg, name, field)                     \
239
  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
240

    
241
#define PRINT_TMD(T) printf(                            \
242
        "TMD0 : TBADR=0x%08x\n"                         \
243
        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
244
        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
245
        "       BPE=%d, BCNT=%d\n"                      \
246
        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
247
        "LCA=%d, RTR=%d,\n"                             \
248
        "       TDR=%d, TRC=%d\n",                      \
249
        (T)->tbadr,                                     \
250
        GET_FIELD((T)->status, TMDS, OWN),              \
251
        GET_FIELD((T)->status, TMDS, ERR),              \
252
        GET_FIELD((T)->status, TMDS, NOFCS),            \
253
        GET_FIELD((T)->status, TMDS, LTINT),            \
254
        GET_FIELD((T)->status, TMDS, ONE),              \
255
        GET_FIELD((T)->status, TMDS, DEF),              \
256
        GET_FIELD((T)->status, TMDS, STP),              \
257
        GET_FIELD((T)->status, TMDS, ENP),              \
258
        GET_FIELD((T)->status, TMDS, BPE),              \
259
        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
260
        GET_FIELD((T)->misc, TMDM, BUFF),               \
261
        GET_FIELD((T)->misc, TMDM, UFLO),               \
262
        GET_FIELD((T)->misc, TMDM, EXDEF),              \
263
        GET_FIELD((T)->misc, TMDM, LCOL),               \
264
        GET_FIELD((T)->misc, TMDM, LCAR),               \
265
        GET_FIELD((T)->misc, TMDM, RTRY),               \
266
        GET_FIELD((T)->misc, TMDM, TDR),                \
267
        GET_FIELD((T)->misc, TMDM, TRC))
268

    
269
#define PRINT_RMD(R) printf(                            \
270
        "RMD0 : RBADR=0x%08x\n"                         \
271
        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
272
        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
273
        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
274
        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
275
        (R)->rbadr,                                     \
276
        GET_FIELD((R)->status, RMDS, OWN),              \
277
        GET_FIELD((R)->status, RMDS, ERR),              \
278
        GET_FIELD((R)->status, RMDS, FRAM),             \
279
        GET_FIELD((R)->status, RMDS, OFLO),             \
280
        GET_FIELD((R)->status, RMDS, CRC),              \
281
        GET_FIELD((R)->status, RMDS, BUFF),             \
282
        GET_FIELD((R)->status, RMDS, STP),              \
283
        GET_FIELD((R)->status, RMDS, ENP),              \
284
        GET_FIELD((R)->status, RMDS, BPE),              \
285
        GET_FIELD((R)->status, RMDS, PAM),              \
286
        GET_FIELD((R)->status, RMDS, LFAM),             \
287
        GET_FIELD((R)->status, RMDS, BAM),              \
288
        GET_FIELD((R)->buf_length, RMDL, ONES),         \
289
        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
290
        GET_FIELD((R)->msg_length, RMDM, RCC),          \
291
        GET_FIELD((R)->msg_length, RMDM, RPC),          \
292
        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
293
        GET_FIELD((R)->msg_length, RMDM, ZEROS))
294

    
295
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
296
                                  hwaddr addr)
297
{
298
    if (!BCR_SSIZE32(s)) {
299
        struct {
300
            uint32_t tbadr;
301
            int16_t length;
302
            int16_t status;
303
        } xda;
304
        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
305
        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
306
        tmd->length = le16_to_cpu(xda.length);
307
        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
308
        tmd->misc = le16_to_cpu(xda.status) << 16;
309
        tmd->res = 0;
310
    } else {
311
        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
312
        le32_to_cpus(&tmd->tbadr);
313
        le16_to_cpus((uint16_t *)&tmd->length);
314
        le16_to_cpus((uint16_t *)&tmd->status);
315
        le32_to_cpus(&tmd->misc);
316
        le32_to_cpus(&tmd->res);
317
        if (BCR_SWSTYLE(s) == 3) {
318
            uint32_t tmp = tmd->tbadr;
319
            tmd->tbadr = tmd->misc;
320
            tmd->misc = tmp;
321
        }
322
    }
323
}
324

    
325
static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
326
                                   hwaddr addr)
327
{
328
    if (!BCR_SSIZE32(s)) {
329
        struct {
330
            uint32_t tbadr;
331
            int16_t length;
332
            int16_t status;
333
        } xda;
334
        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
335
                                ((tmd->status & 0xff00) << 16));
336
        xda.length = cpu_to_le16(tmd->length);
337
        xda.status = cpu_to_le16(tmd->misc >> 16);
338
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
339
    } else {
340
        struct {
341
            uint32_t tbadr;
342
            int16_t length;
343
            int16_t status;
344
            uint32_t misc;
345
            uint32_t res;
346
        } xda;
347
        xda.tbadr = cpu_to_le32(tmd->tbadr);
348
        xda.length = cpu_to_le16(tmd->length);
349
        xda.status = cpu_to_le16(tmd->status);
350
        xda.misc = cpu_to_le32(tmd->misc);
351
        xda.res = cpu_to_le32(tmd->res);
352
        if (BCR_SWSTYLE(s) == 3) {
353
            uint32_t tmp = xda.tbadr;
354
            xda.tbadr = xda.misc;
355
            xda.misc = tmp;
356
        }
357
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
358
    }
359
}
360

    
361
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
362
                                  hwaddr addr)
363
{
364
    if (!BCR_SSIZE32(s)) {
365
        struct {
366
            uint32_t rbadr;
367
            int16_t buf_length;
368
            int16_t msg_length;
369
        } rda;
370
        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
371
        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
372
        rmd->buf_length = le16_to_cpu(rda.buf_length);
373
        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
374
        rmd->msg_length = le16_to_cpu(rda.msg_length);
375
        rmd->res = 0;
376
    } else {
377
        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
378
        le32_to_cpus(&rmd->rbadr);
379
        le16_to_cpus((uint16_t *)&rmd->buf_length);
380
        le16_to_cpus((uint16_t *)&rmd->status);
381
        le32_to_cpus(&rmd->msg_length);
382
        le32_to_cpus(&rmd->res);
383
        if (BCR_SWSTYLE(s) == 3) {
384
            uint32_t tmp = rmd->rbadr;
385
            rmd->rbadr = rmd->msg_length;
386
            rmd->msg_length = tmp;
387
        }
388
    }
389
}
390

    
391
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
392
                                   hwaddr addr)
393
{
394
    if (!BCR_SSIZE32(s)) {
395
        struct {
396
            uint32_t rbadr;
397
            int16_t buf_length;
398
            int16_t msg_length;
399
        } rda;
400
        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
401
                                ((rmd->status & 0xff00) << 16));
402
        rda.buf_length = cpu_to_le16(rmd->buf_length);
403
        rda.msg_length = cpu_to_le16(rmd->msg_length);
404
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
405
    } else {
406
        struct {
407
            uint32_t rbadr;
408
            int16_t buf_length;
409
            int16_t status;
410
            uint32_t msg_length;
411
            uint32_t res;
412
        } rda;
413
        rda.rbadr = cpu_to_le32(rmd->rbadr);
414
        rda.buf_length = cpu_to_le16(rmd->buf_length);
415
        rda.status = cpu_to_le16(rmd->status);
416
        rda.msg_length = cpu_to_le32(rmd->msg_length);
417
        rda.res = cpu_to_le32(rmd->res);
418
        if (BCR_SWSTYLE(s) == 3) {
419
            uint32_t tmp = rda.rbadr;
420
            rda.rbadr = rda.msg_length;
421
            rda.msg_length = tmp;
422
        }
423
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
424
    }
425
}
426

    
427

    
428
#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
429

    
430
#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
431

    
432
#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
433

    
434
#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
435

    
436
#if 1
437

    
438
#define CHECK_RMD(ADDR,RES) do {                \
439
    struct pcnet_RMD rmd;                       \
440
    RMDLOAD(&rmd,(ADDR));                       \
441
    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
442
          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
443
} while (0)
444

    
445
#define CHECK_TMD(ADDR,RES) do {                \
446
    struct pcnet_TMD tmd;                       \
447
    TMDLOAD(&tmd,(ADDR));                       \
448
    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
449
} while (0)
450

    
451
#else
452

    
453
#define CHECK_RMD(ADDR,RES) do {                \
454
    switch (BCR_SWSTYLE(s)) {                   \
455
    case 0x00:                                  \
456
        do {                                    \
457
            uint16_t rda[4];                    \
458
            s->phys_mem_read(s->dma_opaque, (ADDR), \
459
                (void *)&rda[0], sizeof(rda), 0); \
460
            (RES) |= (rda[2] & 0xf000)!=0xf000; \
461
            (RES) |= (rda[3] & 0xf000)!=0x0000; \
462
        } while (0);                            \
463
        break;                                  \
464
    case 0x01:                                  \
465
    case 0x02:                                  \
466
        do {                                    \
467
            uint32_t rda[4];                    \
468
            s->phys_mem_read(s->dma_opaque, (ADDR), \
469
                (void *)&rda[0], sizeof(rda), 0); \
470
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
471
            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
472
        } while (0);                            \
473
        break;                                  \
474
    case 0x03:                                  \
475
        do {                                    \
476
            uint32_t rda[4];                    \
477
            s->phys_mem_read(s->dma_opaque, (ADDR), \
478
                (void *)&rda[0], sizeof(rda), 0); \
479
            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
480
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
481
        } while (0);                            \
482
        break;                                  \
483
    }                                           \
484
} while (0)
485

    
486
#define CHECK_TMD(ADDR,RES) do {                \
487
    switch (BCR_SWSTYLE(s)) {                   \
488
    case 0x00:                                  \
489
        do {                                    \
490
            uint16_t xda[4];                    \
491
            s->phys_mem_read(s->dma_opaque, (ADDR), \
492
                (void *)&xda[0], sizeof(xda), 0); \
493
            (RES) |= (xda[2] & 0xf000)!=0xf000; \
494
        } while (0);                            \
495
        break;                                  \
496
    case 0x01:                                  \
497
    case 0x02:                                  \
498
    case 0x03:                                  \
499
        do {                                    \
500
            uint32_t xda[4];                    \
501
            s->phys_mem_read(s->dma_opaque, (ADDR), \
502
                (void *)&xda[0], sizeof(xda), 0); \
503
            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
504
        } while (0);                            \
505
        break;                                  \
506
    }                                           \
507
} while (0)
508

    
509
#endif
510

    
511
#define PRINT_PKTHDR(BUF) do {                  \
512
    struct qemu_ether_header *hdr = (void *)(BUF); \
513
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
514
           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
515
           "type=0x%04x\n",                     \
516
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
517
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
518
           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
519
           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
520
           be16_to_cpu(hdr->ether_type));       \
521
} while (0)
522

    
523
#define MULTICAST_FILTER_LEN 8
524

    
525
static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
526
{
527
#define LNC_POLYNOMIAL          0xEDB88320UL
528
    uint32_t crc = 0xFFFFFFFF;
529
    int idx, bit;
530
    uint8_t data;
531

    
532
    for (idx = 0; idx < 6; idx++) {
533
        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
534
            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
535
            data >>= 1;
536
        }
537
    }
538
    return crc;
539
#undef LNC_POLYNOMIAL
540
}
541

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

    
544
/* generated using the AUTODIN II polynomial
545
 *        x^32 + x^26 + x^23 + x^22 + x^16 +
546
 *        x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
547
 */
548
static const uint32_t crctab[256] = {
549
        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
550
        0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
551
        0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
552
        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
553
        0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
554
        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
555
        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
556
        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
557
        0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
558
        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
559
        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
560
        0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
561
        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
562
        0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
563
        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
564
        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
565
        0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
566
        0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
567
        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
568
        0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
569
        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
570
        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
571
        0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
572
        0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
573
        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
574
        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
575
        0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
576
        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
577
        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
578
        0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
579
        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
580
        0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
581
        0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
582
        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
583
        0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
584
        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
585
        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
586
        0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
587
        0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
588
        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
589
        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
590
        0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
591
        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
592
        0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
593
        0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
594
        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
595
        0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
596
        0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
597
        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
598
        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
599
        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
600
        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
601
        0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
602
        0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
603
        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
604
        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
605
        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
606
        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
607
        0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
608
        0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
609
        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
610
        0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
611
        0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
612
        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
613
};
614

    
615
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
616
{
617
    struct qemu_ether_header *hdr = (void *)buf;
618
    uint8_t padr[6] = {
619
        s->csr[12] & 0xff, s->csr[12] >> 8,
620
        s->csr[13] & 0xff, s->csr[13] >> 8,
621
        s->csr[14] & 0xff, s->csr[14] >> 8
622
    };
623
    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
624
#ifdef PCNET_DEBUG_MATCH
625
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
626
           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
627
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
628
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
629
           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
630
    printf("padr_match result=%d\n", result);
631
#endif
632
    return result;
633
}
634

    
635
static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
636
{
637
    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
638
    struct qemu_ether_header *hdr = (void *)buf;
639
    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
640
#ifdef PCNET_DEBUG_MATCH
641
    printf("padr_bcast result=%d\n", result);
642
#endif
643
    return result;
644
}
645

    
646
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
647
{
648
    struct qemu_ether_header *hdr = (void *)buf;
649
    if ((*(hdr->ether_dhost)&0x01) &&
650
        ((uint64_t *)&s->csr[8])[0] != 0LL) {
651
        uint8_t ladr[8] = {
652
            s->csr[8] & 0xff, s->csr[8] >> 8,
653
            s->csr[9] & 0xff, s->csr[9] >> 8,
654
            s->csr[10] & 0xff, s->csr[10] >> 8,
655
            s->csr[11] & 0xff, s->csr[11] >> 8
656
        };
657
        int index = lnc_mchash(hdr->ether_dhost) >> 26;
658
        return !!(ladr[index >> 3] & (1 << (index & 7)));
659
    }
660
    return 0;
661
}
662

    
663
static inline hwaddr pcnet_rdra_addr(PCNetState *s, int idx)
664
{
665
    while (idx < 1) idx += CSR_RCVRL(s);
666
    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
667
}
668

    
669
static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
670
{
671
    int64_t next_time = current_time +
672
        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
673
                 get_ticks_per_sec(), 33000000L);
674
    if (next_time <= current_time)
675
        next_time = current_time + 1;
676
    return next_time;
677
}
678

    
679
static void pcnet_poll(PCNetState *s);
680
static void pcnet_poll_timer(void *opaque);
681

    
682
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
683
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
684
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
685

    
686
static void pcnet_s_reset(PCNetState *s)
687
{
688
#ifdef PCNET_DEBUG
689
    printf("pcnet_s_reset\n");
690
#endif
691

    
692
    s->rdra = 0;
693
    s->tdra = 0;
694
    s->rap = 0;
695

    
696
    s->bcr[BCR_BSBC] &= ~0x0080;
697

    
698
    s->csr[0]   = 0x0004;
699
    s->csr[3]   = 0x0000;
700
    s->csr[4]   = 0x0115;
701
    s->csr[5]   = 0x0000;
702
    s->csr[6]   = 0x0000;
703
    s->csr[8]   = 0;
704
    s->csr[9]   = 0;
705
    s->csr[10]  = 0;
706
    s->csr[11]  = 0;
707
    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
708
    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
709
    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
710
    s->csr[15] &= 0x21c4;
711
    s->csr[72]  = 1;
712
    s->csr[74]  = 1;
713
    s->csr[76]  = 1;
714
    s->csr[78]  = 1;
715
    s->csr[80]  = 0x1410;
716
    s->csr[88]  = 0x1003;
717
    s->csr[89]  = 0x0262;
718
    s->csr[94]  = 0x0000;
719
    s->csr[100] = 0x0200;
720
    s->csr[103] = 0x0105;
721
    s->csr[103] = 0x0105;
722
    s->csr[112] = 0x0000;
723
    s->csr[114] = 0x0000;
724
    s->csr[122] = 0x0000;
725
    s->csr[124] = 0x0000;
726

    
727
    s->tx_busy = 0;
728
}
729

    
730
static void pcnet_update_irq(PCNetState *s)
731
{
732
    int isr = 0;
733
    s->csr[0] &= ~0x0080;
734

    
735
#if 1
736
    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
737
        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
738
        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
739
#else
740
    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
741
        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
742
        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
743
        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
744
        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
745
        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
746
        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
747
        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
748
        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
749
        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
750
        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
751
        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
752
#endif
753
    {
754

    
755
        isr = CSR_INEA(s);
756
        s->csr[0] |= 0x0080;
757
    }
758

    
759
    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
760
        s->csr[4] &= ~0x0080;
761
        s->csr[4] |= 0x0040;
762
        s->csr[0] |= 0x0080;
763
        isr = 1;
764
#ifdef PCNET_DEBUG
765
        printf("pcnet user int\n");
766
#endif
767
    }
768

    
769
#if 1
770
    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
771
#else
772
    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
773
        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
774
#endif
775
    {
776
        isr = 1;
777
        s->csr[0] |= 0x0080;
778
    }
779

    
780
    if (isr != s->isr) {
781
#ifdef PCNET_DEBUG
782
        printf("pcnet: INTA=%d\n", isr);
783
#endif
784
    }
785
    qemu_set_irq(s->irq, isr);
786
    s->isr = isr;
787
}
788

    
789
static void pcnet_init(PCNetState *s)
790
{
791
    int rlen, tlen;
792
    uint16_t padr[3], ladrf[4], mode;
793
    uint32_t rdra, tdra;
794

    
795
#ifdef PCNET_DEBUG
796
    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
797
#endif
798

    
799
    if (BCR_SSIZE32(s)) {
800
        struct pcnet_initblk32 initblk;
801
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
802
                (uint8_t *)&initblk, sizeof(initblk), 0);
803
        mode = le16_to_cpu(initblk.mode);
804
        rlen = initblk.rlen >> 4;
805
        tlen = initblk.tlen >> 4;
806
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
807
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
808
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
809
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
810
        padr[0] = le16_to_cpu(initblk.padr[0]);
811
        padr[1] = le16_to_cpu(initblk.padr[1]);
812
        padr[2] = le16_to_cpu(initblk.padr[2]);
813
        rdra = le32_to_cpu(initblk.rdra);
814
        tdra = le32_to_cpu(initblk.tdra);
815
    } else {
816
        struct pcnet_initblk16 initblk;
817
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
818
                (uint8_t *)&initblk, sizeof(initblk), 0);
819
        mode = le16_to_cpu(initblk.mode);
820
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
821
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
822
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
823
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
824
        padr[0] = le16_to_cpu(initblk.padr[0]);
825
        padr[1] = le16_to_cpu(initblk.padr[1]);
826
        padr[2] = le16_to_cpu(initblk.padr[2]);
827
        rdra = le32_to_cpu(initblk.rdra);
828
        tdra = le32_to_cpu(initblk.tdra);
829
        rlen = rdra >> 29;
830
        tlen = tdra >> 29;
831
        rdra &= 0x00ffffff;
832
        tdra &= 0x00ffffff;
833
    }
834

    
835
#if defined(PCNET_DEBUG)
836
    printf("rlen=%d tlen=%d\n", rlen, tlen);
837
#endif
838

    
839
    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
840
    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
841
    s->csr[ 6] = (tlen << 12) | (rlen << 8);
842
    s->csr[15] = mode;
843
    s->csr[ 8] = ladrf[0];
844
    s->csr[ 9] = ladrf[1];
845
    s->csr[10] = ladrf[2];
846
    s->csr[11] = ladrf[3];
847
    s->csr[12] = padr[0];
848
    s->csr[13] = padr[1];
849
    s->csr[14] = padr[2];
850
    s->rdra = PHYSADDR(s, rdra);
851
    s->tdra = PHYSADDR(s, tdra);
852

    
853
    CSR_RCVRC(s) = CSR_RCVRL(s);
854
    CSR_XMTRC(s) = CSR_XMTRL(s);
855

    
856
#ifdef PCNET_DEBUG
857
    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
858
        BCR_SSIZE32(s),
859
        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
860
#endif
861

    
862
    s->csr[0] |= 0x0101;
863
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
864
}
865

    
866
static void pcnet_start(PCNetState *s)
867
{
868
#ifdef PCNET_DEBUG
869
    printf("pcnet_start\n");
870
#endif
871

    
872
    if (!CSR_DTX(s))
873
        s->csr[0] |= 0x0010;    /* set TXON */
874

    
875
    if (!CSR_DRX(s))
876
        s->csr[0] |= 0x0020;    /* set RXON */
877

    
878
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
879
    s->csr[0] |= 0x0002;
880
    pcnet_poll_timer(s);
881
}
882

    
883
static void pcnet_stop(PCNetState *s)
884
{
885
#ifdef PCNET_DEBUG
886
    printf("pcnet_stop\n");
887
#endif
888
    s->csr[0] &= ~0xffeb;
889
    s->csr[0] |= 0x0014;
890
    s->csr[4] &= ~0x02c2;
891
    s->csr[5] &= ~0x0011;
892
    pcnet_poll_timer(s);
893
}
894

    
895
static void pcnet_rdte_poll(PCNetState *s)
896
{
897
    s->csr[28] = s->csr[29] = 0;
898
    if (s->rdra) {
899
        int bad = 0;
900
#if 1
901
        hwaddr crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
902
        hwaddr nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
903
        hwaddr nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
904
#else
905
        hwaddr crda = s->rdra +
906
            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
907
            (BCR_SWSTYLE(s) ? 16 : 8 );
908
        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
909
        hwaddr nrda = s->rdra +
910
            (CSR_RCVRL(s) - nrdc) *
911
            (BCR_SWSTYLE(s) ? 16 : 8 );
912
        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
913
        hwaddr nnrd = s->rdra +
914
            (CSR_RCVRL(s) - nnrc) *
915
            (BCR_SWSTYLE(s) ? 16 : 8 );
916
#endif
917

    
918
        CHECK_RMD(crda, bad);
919
        if (!bad) {
920
            CHECK_RMD(nrda, bad);
921
            if (bad || (nrda == crda)) nrda = 0;
922
            CHECK_RMD(nnrd, bad);
923
            if (bad || (nnrd == crda)) nnrd = 0;
924

    
925
            s->csr[28] = crda & 0xffff;
926
            s->csr[29] = crda >> 16;
927
            s->csr[26] = nrda & 0xffff;
928
            s->csr[27] = nrda >> 16;
929
            s->csr[36] = nnrd & 0xffff;
930
            s->csr[37] = nnrd >> 16;
931
#ifdef PCNET_DEBUG
932
            if (bad) {
933
                printf("pcnet: BAD RMD RECORDS AFTER 0x" TARGET_FMT_plx "\n",
934
                       crda);
935
            }
936
        } else {
937
            printf("pcnet: BAD RMD RDA=0x" TARGET_FMT_plx "\n",
938
                   crda);
939
#endif
940
        }
941
    }
942

    
943
    if (CSR_CRDA(s)) {
944
        struct pcnet_RMD rmd;
945
        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
946
        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
947
        CSR_CRST(s) = rmd.status;
948
#ifdef PCNET_DEBUG_RMD_X
949
        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
950
                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
951
                rmd.buf_length, rmd.status, rmd.msg_length);
952
        PRINT_RMD(&rmd);
953
#endif
954
    } else {
955
        CSR_CRBC(s) = CSR_CRST(s) = 0;
956
    }
957

    
958
    if (CSR_NRDA(s)) {
959
        struct pcnet_RMD rmd;
960
        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
961
        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
962
        CSR_NRST(s) = rmd.status;
963
    } else {
964
        CSR_NRBC(s) = CSR_NRST(s) = 0;
965
    }
966

    
967
}
968

    
969
static int pcnet_tdte_poll(PCNetState *s)
970
{
971
    s->csr[34] = s->csr[35] = 0;
972
    if (s->tdra) {
973
        hwaddr cxda = s->tdra +
974
            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
975
            (BCR_SWSTYLE(s) ? 16 : 8);
976
        int bad = 0;
977
        CHECK_TMD(cxda, bad);
978
        if (!bad) {
979
            if (CSR_CXDA(s) != cxda) {
980
                s->csr[60] = s->csr[34];
981
                s->csr[61] = s->csr[35];
982
                s->csr[62] = CSR_CXBC(s);
983
                s->csr[63] = CSR_CXST(s);
984
            }
985
            s->csr[34] = cxda & 0xffff;
986
            s->csr[35] = cxda >> 16;
987
#ifdef PCNET_DEBUG_X
988
            printf("pcnet: BAD TMD XDA=0x%08x\n", cxda);
989
#endif
990
        }
991
    }
992

    
993
    if (CSR_CXDA(s)) {
994
        struct pcnet_TMD tmd;
995

    
996
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
997

    
998
        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
999
        CSR_CXST(s) = tmd.status;
1000
    } else {
1001
        CSR_CXBC(s) = CSR_CXST(s) = 0;
1002
    }
1003

    
1004
    return !!(CSR_CXST(s) & 0x8000);
1005
}
1006

    
1007
int pcnet_can_receive(NetClientState *nc)
1008
{
1009
    PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1010
    if (CSR_STOP(s) || CSR_SPND(s))
1011
        return 0;
1012

    
1013
    return sizeof(s->buffer)-16;
1014
}
1015

    
1016
#define MIN_BUF_SIZE 60
1017

    
1018
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
1019
{
1020
    PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1021
    int is_padr = 0, is_bcast = 0, is_ladr = 0;
1022
    uint8_t buf1[60];
1023
    int remaining;
1024
    int crc_err = 0;
1025
    int size = size_;
1026

    
1027
    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
1028
        (CSR_LOOP(s) && !s->looptest)) {
1029
        return -1;
1030
    }
1031
#ifdef PCNET_DEBUG
1032
    printf("pcnet_receive size=%d\n", size);
1033
#endif
1034

    
1035
    /* if too small buffer, then expand it */
1036
    if (size < MIN_BUF_SIZE) {
1037
        memcpy(buf1, buf, size);
1038
        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1039
        buf = buf1;
1040
        size = MIN_BUF_SIZE;
1041
    }
1042

    
1043
    if (CSR_PROM(s)
1044
        || (is_padr=padr_match(s, buf, size))
1045
        || (is_bcast=padr_bcast(s, buf, size))
1046
        || (is_ladr=ladr_match(s, buf, size))) {
1047

    
1048
        pcnet_rdte_poll(s);
1049

    
1050
        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1051
            struct pcnet_RMD rmd;
1052
            int rcvrc = CSR_RCVRC(s)-1,i;
1053
            hwaddr nrda;
1054
            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1055
                if (rcvrc <= 1)
1056
                    rcvrc = CSR_RCVRL(s);
1057
                nrda = s->rdra +
1058
                    (CSR_RCVRL(s) - rcvrc) *
1059
                    (BCR_SWSTYLE(s) ? 16 : 8 );
1060
                RMDLOAD(&rmd, nrda);
1061
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1062
#ifdef PCNET_DEBUG_RMD
1063
                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1064
                                rcvrc, CSR_RCVRC(s));
1065
#endif
1066
                    CSR_RCVRC(s) = rcvrc;
1067
                    pcnet_rdte_poll(s);
1068
                    break;
1069
                }
1070
            }
1071
        }
1072

    
1073
        if (!(CSR_CRST(s) & 0x8000)) {
1074
#ifdef PCNET_DEBUG_RMD
1075
            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1076
#endif
1077
            s->csr[0] |= 0x1000; /* Set MISS flag */
1078
            CSR_MISSC(s)++;
1079
        } else {
1080
            uint8_t *src = s->buffer;
1081
            hwaddr crda = CSR_CRDA(s);
1082
            struct pcnet_RMD rmd;
1083
            int pktcount = 0;
1084

    
1085
            if (!s->looptest) {
1086
                memcpy(src, buf, size);
1087
                /* no need to compute the CRC */
1088
                src[size] = 0;
1089
                src[size + 1] = 0;
1090
                src[size + 2] = 0;
1091
                src[size + 3] = 0;
1092
                size += 4;
1093
            } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1094
                       !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1095
                uint32_t fcs = ~0;
1096
                uint8_t *p = src;
1097

    
1098
                while (p != &src[size])
1099
                    CRC(fcs, *p++);
1100
                *(uint32_t *)p = htonl(fcs);
1101
                size += 4;
1102
            } else {
1103
                uint32_t fcs = ~0;
1104
                uint8_t *p = src;
1105

    
1106
                while (p != &src[size-4])
1107
                    CRC(fcs, *p++);
1108
                crc_err = (*(uint32_t *)p != htonl(fcs));
1109
            }
1110

    
1111
#ifdef PCNET_DEBUG_MATCH
1112
            PRINT_PKTHDR(buf);
1113
#endif
1114

    
1115
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1116
            /*if (!CSR_LAPPEN(s))*/
1117
                SET_FIELD(&rmd.status, RMDS, STP, 1);
1118

    
1119
#define PCNET_RECV_STORE() do {                                 \
1120
    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1121
    hwaddr rbadr = PHYSADDR(s, rmd.rbadr);          \
1122
    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1123
    src += count; remaining -= count;                           \
1124
    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1125
    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1126
    pktcount++;                                                 \
1127
} while (0)
1128

    
1129
            remaining = size;
1130
            PCNET_RECV_STORE();
1131
            if ((remaining > 0) && CSR_NRDA(s)) {
1132
                hwaddr nrda = CSR_NRDA(s);
1133
#ifdef PCNET_DEBUG_RMD
1134
                PRINT_RMD(&rmd);
1135
#endif
1136
                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1137
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1138
                    crda = nrda;
1139
                    PCNET_RECV_STORE();
1140
#ifdef PCNET_DEBUG_RMD
1141
                    PRINT_RMD(&rmd);
1142
#endif
1143
                    if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1144
                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1145
                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
1146
                            crda = nrda;
1147
                            PCNET_RECV_STORE();
1148
                        }
1149
                    }
1150
                }
1151
            }
1152

    
1153
#undef PCNET_RECV_STORE
1154

    
1155
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1156
            if (remaining == 0) {
1157
                SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1158
                SET_FIELD(&rmd.status, RMDS, ENP, 1);
1159
                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1160
                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1161
                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1162
                if (crc_err) {
1163
                    SET_FIELD(&rmd.status, RMDS, CRC, 1);
1164
                    SET_FIELD(&rmd.status, RMDS, ERR, 1);
1165
                }
1166
            } else {
1167
                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1168
                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1169
                SET_FIELD(&rmd.status, RMDS, ERR, 1);
1170
            }
1171
            RMDSTORE(&rmd, PHYSADDR(s,crda));
1172
            s->csr[0] |= 0x0400;
1173

    
1174
#ifdef PCNET_DEBUG
1175
            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1176
                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1177
#endif
1178
#ifdef PCNET_DEBUG_RMD
1179
            PRINT_RMD(&rmd);
1180
#endif
1181

    
1182
            while (pktcount--) {
1183
                if (CSR_RCVRC(s) <= 1)
1184
                    CSR_RCVRC(s) = CSR_RCVRL(s);
1185
                else
1186
                    CSR_RCVRC(s)--;
1187
            }
1188

    
1189
            pcnet_rdte_poll(s);
1190

    
1191
        }
1192
    }
1193

    
1194
    pcnet_poll(s);
1195
    pcnet_update_irq(s);
1196

    
1197
    return size_;
1198
}
1199

    
1200
void pcnet_set_link_status(NetClientState *nc)
1201
{
1202
    PCNetState *d = DO_UPCAST(NICState, nc, nc)->opaque;
1203

    
1204
    d->lnkst = nc->link_down ? 0 : 0x40;
1205
}
1206

    
1207
static void pcnet_transmit(PCNetState *s)
1208
{
1209
    hwaddr xmit_cxda = 0;
1210
    int count = CSR_XMTRL(s)-1;
1211
    int add_crc = 0;
1212

    
1213
    s->xmit_pos = -1;
1214

    
1215
    if (!CSR_TXON(s)) {
1216
        s->csr[0] &= ~0x0008;
1217
        return;
1218
    }
1219

    
1220
    s->tx_busy = 1;
1221

    
1222
    txagain:
1223
    if (pcnet_tdte_poll(s)) {
1224
        struct pcnet_TMD tmd;
1225

    
1226
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1227

    
1228
#ifdef PCNET_DEBUG_TMD
1229
        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1230
        PRINT_TMD(&tmd);
1231
#endif
1232
        if (GET_FIELD(tmd.status, TMDS, STP)) {
1233
            s->xmit_pos = 0;
1234
            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1235
            if (BCR_SWSTYLE(s) != 1)
1236
                add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1237
        }
1238
        if (s->lnkst == 0 &&
1239
            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
1240
            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
1241
            SET_FIELD(&tmd.status, TMDS, ERR, 1);
1242
            SET_FIELD(&tmd.status, TMDS, OWN, 0);
1243
            s->csr[0] |= 0xa000; /* ERR | CERR */
1244
            s->xmit_pos = -1;
1245
            goto txdone;
1246
        }
1247
        if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1248
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1249
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1250
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1251
            s->xmit_pos += bcnt;
1252
        } else if (s->xmit_pos >= 0) {
1253
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1254
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1255
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1256
            s->xmit_pos += bcnt;
1257
#ifdef PCNET_DEBUG
1258
            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1259
#endif
1260
            if (CSR_LOOP(s)) {
1261
                if (BCR_SWSTYLE(s) == 1)
1262
                    add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1263
                s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1264
                pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos);
1265
                s->looptest = 0;
1266
            } else
1267
                if (s->nic)
1268
                    qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos);
1269

    
1270
            s->csr[0] &= ~0x0008;   /* clear TDMD */
1271
            s->csr[4] |= 0x0004;    /* set TXSTRT */
1272
            s->xmit_pos = -1;
1273
        }
1274

    
1275
    txdone:
1276
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1277
        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1278
        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1279
            s->csr[0] |= 0x0200;    /* set TINT */
1280

    
1281
        if (CSR_XMTRC(s)<=1)
1282
            CSR_XMTRC(s) = CSR_XMTRL(s);
1283
        else
1284
            CSR_XMTRC(s)--;
1285
        if (count--)
1286
            goto txagain;
1287

    
1288
    } else
1289
    if (s->xmit_pos >= 0) {
1290
        struct pcnet_TMD tmd;
1291
        TMDLOAD(&tmd, xmit_cxda);
1292
        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1293
        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1294
        SET_FIELD(&tmd.status, TMDS, ERR, 1);
1295
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1296
        TMDSTORE(&tmd, xmit_cxda);
1297
        s->csr[0] |= 0x0200;    /* set TINT */
1298
        if (!CSR_DXSUFLO(s)) {
1299
            s->csr[0] &= ~0x0010;
1300
        } else
1301
        if (count--)
1302
          goto txagain;
1303
    }
1304

    
1305
    s->tx_busy = 0;
1306
}
1307

    
1308
static void pcnet_poll(PCNetState *s)
1309
{
1310
    if (CSR_RXON(s)) {
1311
        pcnet_rdte_poll(s);
1312
    }
1313

    
1314
    if (CSR_TDMD(s) ||
1315
        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1316
    {
1317
        /* prevent recursion */
1318
        if (s->tx_busy)
1319
            return;
1320

    
1321
        pcnet_transmit(s);
1322
    }
1323
}
1324

    
1325
static void pcnet_poll_timer(void *opaque)
1326
{
1327
    PCNetState *s = opaque;
1328

    
1329
    qemu_del_timer(s->poll_timer);
1330

    
1331
    if (CSR_TDMD(s)) {
1332
        pcnet_transmit(s);
1333
    }
1334

    
1335
    pcnet_update_irq(s);
1336

    
1337
    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1338
        uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
1339
        if (!s->timer || !now)
1340
            s->timer = now;
1341
        else {
1342
            uint64_t t = now - s->timer + CSR_POLL(s);
1343
            if (t > 0xffffLL) {
1344
                pcnet_poll(s);
1345
                CSR_POLL(s) = CSR_PINT(s);
1346
            } else
1347
                CSR_POLL(s) = t;
1348
        }
1349
        qemu_mod_timer(s->poll_timer,
1350
            pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
1351
    }
1352
}
1353

    
1354

    
1355
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1356
{
1357
    uint16_t val = new_value;
1358
#ifdef PCNET_DEBUG_CSR
1359
    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1360
#endif
1361
    switch (rap) {
1362
    case 0:
1363
        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1364

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

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

    
1369
        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1370
        if ((val&7) == 7)
1371
          val &= ~3;
1372

    
1373
        if (!CSR_STOP(s) && (val & 4))
1374
            pcnet_stop(s);
1375

    
1376
        if (!CSR_INIT(s) && (val & 1))
1377
            pcnet_init(s);
1378

    
1379
        if (!CSR_STRT(s) && (val & 2))
1380
            pcnet_start(s);
1381

    
1382
        if (CSR_TDMD(s))
1383
            pcnet_transmit(s);
1384

    
1385
        return;
1386
    case 1:
1387
    case 2:
1388
    case 8:
1389
    case 9:
1390
    case 10:
1391
    case 11:
1392
    case 12:
1393
    case 13:
1394
    case 14:
1395
    case 15:
1396
    case 18: /* CRBAL */
1397
    case 19: /* CRBAU */
1398
    case 20: /* CXBAL */
1399
    case 21: /* CXBAU */
1400
    case 22: /* NRBAU */
1401
    case 23: /* NRBAU */
1402
    case 24:
1403
    case 25:
1404
    case 26:
1405
    case 27:
1406
    case 28:
1407
    case 29:
1408
    case 30:
1409
    case 31:
1410
    case 32:
1411
    case 33:
1412
    case 34:
1413
    case 35:
1414
    case 36:
1415
    case 37:
1416
    case 38:
1417
    case 39:
1418
    case 40: /* CRBC */
1419
    case 41:
1420
    case 42: /* CXBC */
1421
    case 43:
1422
    case 44:
1423
    case 45:
1424
    case 46: /* POLL */
1425
    case 47: /* POLLINT */
1426
    case 72:
1427
    case 74:
1428
    case 76: /* RCVRL */
1429
    case 78: /* XMTRL */
1430
    case 112:
1431
       if (CSR_STOP(s) || CSR_SPND(s))
1432
           break;
1433
       return;
1434
    case 3:
1435
        break;
1436
    case 4:
1437
        s->csr[4] &= ~(val & 0x026a);
1438
        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1439
        break;
1440
    case 5:
1441
        s->csr[5] &= ~(val & 0x0a90);
1442
        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1443
        break;
1444
    case 16:
1445
        pcnet_csr_writew(s,1,val);
1446
        return;
1447
    case 17:
1448
        pcnet_csr_writew(s,2,val);
1449
        return;
1450
    case 58:
1451
        pcnet_bcr_writew(s,BCR_SWS,val);
1452
        break;
1453
    default:
1454
        return;
1455
    }
1456
    s->csr[rap] = val;
1457
}
1458

    
1459
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1460
{
1461
    uint32_t val;
1462
    switch (rap) {
1463
    case 0:
1464
        pcnet_update_irq(s);
1465
        val = s->csr[0];
1466
        val |= (val & 0x7800) ? 0x8000 : 0;
1467
        break;
1468
    case 16:
1469
        return pcnet_csr_readw(s,1);
1470
    case 17:
1471
        return pcnet_csr_readw(s,2);
1472
    case 58:
1473
        return pcnet_bcr_readw(s,BCR_SWS);
1474
    case 88:
1475
        val = s->csr[89];
1476
        val <<= 16;
1477
        val |= s->csr[88];
1478
        break;
1479
    default:
1480
        val = s->csr[rap];
1481
    }
1482
#ifdef PCNET_DEBUG_CSR
1483
    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1484
#endif
1485
    return val;
1486
}
1487

    
1488
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1489
{
1490
    rap &= 127;
1491
#ifdef PCNET_DEBUG_BCR
1492
    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1493
#endif
1494
    switch (rap) {
1495
    case BCR_SWS:
1496
        if (!(CSR_STOP(s) || CSR_SPND(s)))
1497
            return;
1498
        val &= ~0x0300;
1499
        switch (val & 0x00ff) {
1500
        case 0:
1501
            val |= 0x0200;
1502
            break;
1503
        case 1:
1504
            val |= 0x0100;
1505
            break;
1506
        case 2:
1507
        case 3:
1508
            val |= 0x0300;
1509
            break;
1510
        default:
1511
            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1512
            val = 0x0200;
1513
            break;
1514
        }
1515
#ifdef PCNET_DEBUG
1516
       printf("BCR_SWS=0x%04x\n", val);
1517
#endif
1518
        /* fall through */
1519
    case BCR_LNKST:
1520
    case BCR_LED1:
1521
    case BCR_LED2:
1522
    case BCR_LED3:
1523
    case BCR_MC:
1524
    case BCR_FDC:
1525
    case BCR_BSBC:
1526
    case BCR_EECAS:
1527
    case BCR_PLAT:
1528
        s->bcr[rap] = val;
1529
        break;
1530
    default:
1531
        break;
1532
    }
1533
}
1534

    
1535
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1536
{
1537
    uint32_t val;
1538
    rap &= 127;
1539
    switch (rap) {
1540
    case BCR_LNKST:
1541
    case BCR_LED1:
1542
    case BCR_LED2:
1543
    case BCR_LED3:
1544
        val = s->bcr[rap] & ~0x8000;
1545
        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1546
        break;
1547
    default:
1548
        val = rap < 32 ? s->bcr[rap] : 0;
1549
        break;
1550
    }
1551
#ifdef PCNET_DEBUG_BCR
1552
    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1553
#endif
1554
    return val;
1555
}
1556

    
1557
void pcnet_h_reset(void *opaque)
1558
{
1559
    PCNetState *s = opaque;
1560

    
1561
    s->bcr[BCR_MSRDA] = 0x0005;
1562
    s->bcr[BCR_MSWRA] = 0x0005;
1563
    s->bcr[BCR_MC   ] = 0x0002;
1564
    s->bcr[BCR_LNKST] = 0x00c0;
1565
    s->bcr[BCR_LED1 ] = 0x0084;
1566
    s->bcr[BCR_LED2 ] = 0x0088;
1567
    s->bcr[BCR_LED3 ] = 0x0090;
1568
    s->bcr[BCR_FDC  ] = 0x0000;
1569
    s->bcr[BCR_BSBC ] = 0x9001;
1570
    s->bcr[BCR_EECAS] = 0x0002;
1571
    s->bcr[BCR_SWS  ] = 0x0200;
1572
    s->bcr[BCR_PLAT ] = 0xff06;
1573

    
1574
    pcnet_s_reset(s);
1575
    pcnet_update_irq(s);
1576
    pcnet_poll_timer(s);
1577
}
1578

    
1579
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1580
{
1581
    PCNetState *s = opaque;
1582
    pcnet_poll_timer(s);
1583
#ifdef PCNET_DEBUG_IO
1584
    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1585
#endif
1586
    if (!BCR_DWIO(s)) {
1587
        switch (addr & 0x0f) {
1588
        case 0x00: /* RDP */
1589
            pcnet_csr_writew(s, s->rap, val);
1590
            break;
1591
        case 0x02:
1592
            s->rap = val & 0x7f;
1593
            break;
1594
        case 0x06:
1595
            pcnet_bcr_writew(s, s->rap, val);
1596
            break;
1597
        }
1598
    }
1599
    pcnet_update_irq(s);
1600
}
1601

    
1602
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1603
{
1604
    PCNetState *s = opaque;
1605
    uint32_t val = -1;
1606
    pcnet_poll_timer(s);
1607
    if (!BCR_DWIO(s)) {
1608
        switch (addr & 0x0f) {
1609
        case 0x00: /* RDP */
1610
            val = pcnet_csr_readw(s, s->rap);
1611
            break;
1612
        case 0x02:
1613
            val = s->rap;
1614
            break;
1615
        case 0x04:
1616
            pcnet_s_reset(s);
1617
            val = 0;
1618
            break;
1619
        case 0x06:
1620
            val = pcnet_bcr_readw(s, s->rap);
1621
            break;
1622
        }
1623
    }
1624
    pcnet_update_irq(s);
1625
#ifdef PCNET_DEBUG_IO
1626
    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1627
#endif
1628
    return val;
1629
}
1630

    
1631
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1632
{
1633
    PCNetState *s = opaque;
1634
    pcnet_poll_timer(s);
1635
#ifdef PCNET_DEBUG_IO
1636
    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1637
#endif
1638
    if (BCR_DWIO(s)) {
1639
        switch (addr & 0x0f) {
1640
        case 0x00: /* RDP */
1641
            pcnet_csr_writew(s, s->rap, val & 0xffff);
1642
            break;
1643
        case 0x04:
1644
            s->rap = val & 0x7f;
1645
            break;
1646
        case 0x0c:
1647
            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1648
            break;
1649
        }
1650
    } else
1651
    if ((addr & 0x0f) == 0) {
1652
        /* switch device to dword i/o mode */
1653
        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1654
#ifdef PCNET_DEBUG_IO
1655
        printf("device switched into dword i/o mode\n");
1656
#endif
1657
    }
1658
    pcnet_update_irq(s);
1659
}
1660

    
1661
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1662
{
1663
    PCNetState *s = opaque;
1664
    uint32_t val = -1;
1665
    pcnet_poll_timer(s);
1666
    if (BCR_DWIO(s)) {
1667
        switch (addr & 0x0f) {
1668
        case 0x00: /* RDP */
1669
            val = pcnet_csr_readw(s, s->rap);
1670
            break;
1671
        case 0x04:
1672
            val = s->rap;
1673
            break;
1674
        case 0x08:
1675
            pcnet_s_reset(s);
1676
            val = 0;
1677
            break;
1678
        case 0x0c:
1679
            val = pcnet_bcr_readw(s, s->rap);
1680
            break;
1681
        }
1682
    }
1683
    pcnet_update_irq(s);
1684
#ifdef PCNET_DEBUG_IO
1685
    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1686
#endif
1687
    return val;
1688
}
1689

    
1690
static bool is_version_2(void *opaque, int version_id)
1691
{
1692
    return version_id == 2;
1693
}
1694

    
1695
const VMStateDescription vmstate_pcnet = {
1696
    .name = "pcnet",
1697
    .version_id = 3,
1698
    .minimum_version_id = 2,
1699
    .minimum_version_id_old = 2,
1700
    .fields      = (VMStateField []) {
1701
        VMSTATE_INT32(rap, PCNetState),
1702
        VMSTATE_INT32(isr, PCNetState),
1703
        VMSTATE_INT32(lnkst, PCNetState),
1704
        VMSTATE_UINT32(rdra, PCNetState),
1705
        VMSTATE_UINT32(tdra, PCNetState),
1706
        VMSTATE_BUFFER(prom, PCNetState),
1707
        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1708
        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1709
        VMSTATE_UINT64(timer, PCNetState),
1710
        VMSTATE_INT32(xmit_pos, PCNetState),
1711
        VMSTATE_BUFFER(buffer, PCNetState),
1712
        VMSTATE_UNUSED_TEST(is_version_2, 4),
1713
        VMSTATE_INT32(tx_busy, PCNetState),
1714
        VMSTATE_TIMER(poll_timer, PCNetState),
1715
        VMSTATE_END_OF_LIST()
1716
    }
1717
};
1718

    
1719
void pcnet_common_cleanup(PCNetState *d)
1720
{
1721
    d->nic = NULL;
1722
}
1723

    
1724
int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1725
{
1726
    int i;
1727
    uint16_t checksum;
1728

    
1729
    s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
1730

    
1731
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1732
    s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
1733
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1734

    
1735
    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
1736

    
1737
    /* Initialize the PROM */
1738

    
1739
    /*
1740
      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1741
      page 95
1742
    */
1743
    memcpy(s->prom, s->conf.macaddr.a, 6);
1744
    /* Reserved Location: must be 00h */
1745
    s->prom[6] = s->prom[7] = 0x00;
1746
    /* Reserved Location: must be 00h */
1747
    s->prom[8] = 0x00;
1748
    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1749
    s->prom[9] = 0x11;
1750
    /* User programmable space, init with 0 */
1751
    s->prom[10] = s->prom[11] = 0x00;
1752
    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1753
       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1754
    s->prom[12] = s->prom[13] = 0x00;
1755
    /* Must be ASCII W (57h) if compatibility to AMD
1756
       driver software is desired */
1757
    s->prom[14] = s->prom[15] = 0x57;
1758

    
1759
    for (i = 0, checksum = 0; i < 16; i++) {
1760
        checksum += s->prom[i];
1761
    }
1762
    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1763

    
1764
    s->lnkst = 0x40; /* initial link state: up */
1765

    
1766
    return 0;
1767
}