Statistics
| Branch: | Revision:

root / hw / pcnet.c @ e7852674

History | View | Annotate | Download (54.2 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.h"
40
#include "qemu-timer.h"
41
#include "qemu_socket.h"
42
#include "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_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
81
#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
82
#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
83

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
426

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

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

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

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

    
435
#if 1
436

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

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

    
450
#else
451

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

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

    
508
#endif
509

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

    
522
#define MULTICAST_FILTER_LEN 8
523

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

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

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

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

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

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

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

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

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

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

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

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

    
691
    s->lnkst = 0x40;
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] &= ~0x7feb;
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
        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
902
        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
903
        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
904
#else
905
        target_phys_addr_t 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
        target_phys_addr_t 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
        target_phys_addr_t 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
        target_phys_addr_t 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(VLANClientState *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(VLANClientState *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
            target_phys_addr_t 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
            target_phys_addr_t 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
    target_phys_addr_t 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
                target_phys_addr_t 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(VLANClientState *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
    target_phys_addr_t 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 (!GET_FIELD(tmd.status, TMDS, ENP)) {
1239
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1240
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1241
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1242
            s->xmit_pos += bcnt;
1243
        } else if (s->xmit_pos >= 0) {
1244
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1245
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1246
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1247
            s->xmit_pos += bcnt;
1248
#ifdef PCNET_DEBUG
1249
            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1250
#endif
1251
            if (CSR_LOOP(s)) {
1252
                if (BCR_SWSTYLE(s) == 1)
1253
                    add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1254
                s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1255
                pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos);
1256
                s->looptest = 0;
1257
            } else
1258
                if (s->nic)
1259
                    qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos);
1260

    
1261
            s->csr[0] &= ~0x0008;   /* clear TDMD */
1262
            s->csr[4] |= 0x0004;    /* set TXSTRT */
1263
            s->xmit_pos = -1;
1264
        }
1265

    
1266
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1267
        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1268
        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1269
            s->csr[0] |= 0x0200;    /* set TINT */
1270

    
1271
        if (CSR_XMTRC(s)<=1)
1272
            CSR_XMTRC(s) = CSR_XMTRL(s);
1273
        else
1274
            CSR_XMTRC(s)--;
1275
        if (count--)
1276
            goto txagain;
1277

    
1278
    } else
1279
    if (s->xmit_pos >= 0) {
1280
        struct pcnet_TMD tmd;
1281
        TMDLOAD(&tmd, xmit_cxda);
1282
        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1283
        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1284
        SET_FIELD(&tmd.status, TMDS, ERR, 1);
1285
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1286
        TMDSTORE(&tmd, xmit_cxda);
1287
        s->csr[0] |= 0x0200;    /* set TINT */
1288
        if (!CSR_DXSUFLO(s)) {
1289
            s->csr[0] &= ~0x0010;
1290
        } else
1291
        if (count--)
1292
          goto txagain;
1293
    }
1294

    
1295
    s->tx_busy = 0;
1296
}
1297

    
1298
static void pcnet_poll(PCNetState *s)
1299
{
1300
    if (CSR_RXON(s)) {
1301
        pcnet_rdte_poll(s);
1302
    }
1303

    
1304
    if (CSR_TDMD(s) ||
1305
        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1306
    {
1307
        /* prevent recursion */
1308
        if (s->tx_busy)
1309
            return;
1310

    
1311
        pcnet_transmit(s);
1312
    }
1313
}
1314

    
1315
static void pcnet_poll_timer(void *opaque)
1316
{
1317
    PCNetState *s = opaque;
1318

    
1319
    qemu_del_timer(s->poll_timer);
1320

    
1321
    if (CSR_TDMD(s)) {
1322
        pcnet_transmit(s);
1323
    }
1324

    
1325
    pcnet_update_irq(s);
1326

    
1327
    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1328
        uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
1329
        if (!s->timer || !now)
1330
            s->timer = now;
1331
        else {
1332
            uint64_t t = now - s->timer + CSR_POLL(s);
1333
            if (t > 0xffffLL) {
1334
                pcnet_poll(s);
1335
                CSR_POLL(s) = CSR_PINT(s);
1336
            } else
1337
                CSR_POLL(s) = t;
1338
        }
1339
        qemu_mod_timer(s->poll_timer,
1340
            pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
1341
    }
1342
}
1343

    
1344

    
1345
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1346
{
1347
    uint16_t val = new_value;
1348
#ifdef PCNET_DEBUG_CSR
1349
    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1350
#endif
1351
    switch (rap) {
1352
    case 0:
1353
        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1354

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

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

    
1359
        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1360
        if ((val&7) == 7)
1361
          val &= ~3;
1362

    
1363
        if (!CSR_STOP(s) && (val & 4))
1364
            pcnet_stop(s);
1365

    
1366
        if (!CSR_INIT(s) && (val & 1))
1367
            pcnet_init(s);
1368

    
1369
        if (!CSR_STRT(s) && (val & 2))
1370
            pcnet_start(s);
1371

    
1372
        if (CSR_TDMD(s))
1373
            pcnet_transmit(s);
1374

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

    
1449
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1450
{
1451
    uint32_t val;
1452
    switch (rap) {
1453
    case 0:
1454
        pcnet_update_irq(s);
1455
        val = s->csr[0];
1456
        val |= (val & 0x7800) ? 0x8000 : 0;
1457
        break;
1458
    case 16:
1459
        return pcnet_csr_readw(s,1);
1460
    case 17:
1461
        return pcnet_csr_readw(s,2);
1462
    case 58:
1463
        return pcnet_bcr_readw(s,BCR_SWS);
1464
    case 88:
1465
        val = s->csr[89];
1466
        val <<= 16;
1467
        val |= s->csr[88];
1468
        break;
1469
    default:
1470
        val = s->csr[rap];
1471
    }
1472
#ifdef PCNET_DEBUG_CSR
1473
    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1474
#endif
1475
    return val;
1476
}
1477

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

    
1524
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1525
{
1526
    uint32_t val;
1527
    rap &= 127;
1528
    switch (rap) {
1529
    case BCR_LNKST:
1530
    case BCR_LED1:
1531
    case BCR_LED2:
1532
    case BCR_LED3:
1533
        val = s->bcr[rap] & ~0x8000;
1534
        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1535
        break;
1536
    default:
1537
        val = rap < 32 ? s->bcr[rap] : 0;
1538
        break;
1539
    }
1540
#ifdef PCNET_DEBUG_BCR
1541
    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1542
#endif
1543
    return val;
1544
}
1545

    
1546
void pcnet_h_reset(void *opaque)
1547
{
1548
    PCNetState *s = opaque;
1549

    
1550
    s->bcr[BCR_MSRDA] = 0x0005;
1551
    s->bcr[BCR_MSWRA] = 0x0005;
1552
    s->bcr[BCR_MC   ] = 0x0002;
1553
    s->bcr[BCR_LNKST] = 0x00c0;
1554
    s->bcr[BCR_LED1 ] = 0x0084;
1555
    s->bcr[BCR_LED2 ] = 0x0088;
1556
    s->bcr[BCR_LED3 ] = 0x0090;
1557
    s->bcr[BCR_FDC  ] = 0x0000;
1558
    s->bcr[BCR_BSBC ] = 0x9001;
1559
    s->bcr[BCR_EECAS] = 0x0002;
1560
    s->bcr[BCR_SWS  ] = 0x0200;
1561
    s->bcr[BCR_PLAT ] = 0xff06;
1562

    
1563
    pcnet_s_reset(s);
1564
    pcnet_update_irq(s);
1565
    pcnet_poll_timer(s);
1566
}
1567

    
1568
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1569
{
1570
    PCNetState *s = opaque;
1571
    pcnet_poll_timer(s);
1572
#ifdef PCNET_DEBUG_IO
1573
    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1574
#endif
1575
    if (!BCR_DWIO(s)) {
1576
        switch (addr & 0x0f) {
1577
        case 0x00: /* RDP */
1578
            pcnet_csr_writew(s, s->rap, val);
1579
            break;
1580
        case 0x02:
1581
            s->rap = val & 0x7f;
1582
            break;
1583
        case 0x06:
1584
            pcnet_bcr_writew(s, s->rap, val);
1585
            break;
1586
        }
1587
    }
1588
    pcnet_update_irq(s);
1589
}
1590

    
1591
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1592
{
1593
    PCNetState *s = opaque;
1594
    uint32_t val = -1;
1595
    pcnet_poll_timer(s);
1596
    if (!BCR_DWIO(s)) {
1597
        switch (addr & 0x0f) {
1598
        case 0x00: /* RDP */
1599
            val = pcnet_csr_readw(s, s->rap);
1600
            break;
1601
        case 0x02:
1602
            val = s->rap;
1603
            break;
1604
        case 0x04:
1605
            pcnet_s_reset(s);
1606
            val = 0;
1607
            break;
1608
        case 0x06:
1609
            val = pcnet_bcr_readw(s, s->rap);
1610
            break;
1611
        }
1612
    }
1613
    pcnet_update_irq(s);
1614
#ifdef PCNET_DEBUG_IO
1615
    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1616
#endif
1617
    return val;
1618
}
1619

    
1620
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1621
{
1622
    PCNetState *s = opaque;
1623
    pcnet_poll_timer(s);
1624
#ifdef PCNET_DEBUG_IO
1625
    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1626
#endif
1627
    if (BCR_DWIO(s)) {
1628
        switch (addr & 0x0f) {
1629
        case 0x00: /* RDP */
1630
            pcnet_csr_writew(s, s->rap, val & 0xffff);
1631
            break;
1632
        case 0x04:
1633
            s->rap = val & 0x7f;
1634
            break;
1635
        case 0x0c:
1636
            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1637
            break;
1638
        }
1639
    } else
1640
    if ((addr & 0x0f) == 0) {
1641
        /* switch device to dword i/o mode */
1642
        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1643
#ifdef PCNET_DEBUG_IO
1644
        printf("device switched into dword i/o mode\n");
1645
#endif
1646
    }
1647
    pcnet_update_irq(s);
1648
}
1649

    
1650
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1651
{
1652
    PCNetState *s = opaque;
1653
    uint32_t val = -1;
1654
    pcnet_poll_timer(s);
1655
    if (BCR_DWIO(s)) {
1656
        switch (addr & 0x0f) {
1657
        case 0x00: /* RDP */
1658
            val = pcnet_csr_readw(s, s->rap);
1659
            break;
1660
        case 0x04:
1661
            val = s->rap;
1662
            break;
1663
        case 0x08:
1664
            pcnet_s_reset(s);
1665
            val = 0;
1666
            break;
1667
        case 0x0c:
1668
            val = pcnet_bcr_readw(s, s->rap);
1669
            break;
1670
        }
1671
    }
1672
    pcnet_update_irq(s);
1673
#ifdef PCNET_DEBUG_IO
1674
    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1675
#endif
1676
    return val;
1677
}
1678

    
1679
static bool is_version_2(void *opaque, int version_id)
1680
{
1681
    return version_id == 2;
1682
}
1683

    
1684
const VMStateDescription vmstate_pcnet = {
1685
    .name = "pcnet",
1686
    .version_id = 3,
1687
    .minimum_version_id = 2,
1688
    .minimum_version_id_old = 2,
1689
    .fields      = (VMStateField []) {
1690
        VMSTATE_INT32(rap, PCNetState),
1691
        VMSTATE_INT32(isr, PCNetState),
1692
        VMSTATE_INT32(lnkst, PCNetState),
1693
        VMSTATE_UINT32(rdra, PCNetState),
1694
        VMSTATE_UINT32(tdra, PCNetState),
1695
        VMSTATE_BUFFER(prom, PCNetState),
1696
        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1697
        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1698
        VMSTATE_UINT64(timer, PCNetState),
1699
        VMSTATE_INT32(xmit_pos, PCNetState),
1700
        VMSTATE_BUFFER(buffer, PCNetState),
1701
        VMSTATE_UNUSED_TEST(is_version_2, 4),
1702
        VMSTATE_INT32(tx_busy, PCNetState),
1703
        VMSTATE_TIMER(poll_timer, PCNetState),
1704
        VMSTATE_END_OF_LIST()
1705
    }
1706
};
1707

    
1708
void pcnet_common_cleanup(PCNetState *d)
1709
{
1710
    d->nic = NULL;
1711
}
1712

    
1713
int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1714
{
1715
    int i;
1716
    uint16_t checksum;
1717

    
1718
    s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
1719

    
1720
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1721
    s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
1722
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1723

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

    
1726
    /* Initialize the PROM */
1727

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

    
1748
    for (i = 0, checksum = 0; i < 16; i++) {
1749
        checksum += s->prom[i];
1750
    }
1751
    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1752

    
1753
    return 0;
1754
}