Statistics
| Branch: | Revision:

root / hw / pcnet.c @ f79f2bfc

History | View | Annotate | Download (54.3 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->rdra = 0;
692
    s->tdra = 0;
693
    s->rap = 0;
694

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

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

    
726
    s->tx_busy = 0;
727
}
728

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
966
}
967

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

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

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

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

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

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

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

    
1015
#define MIN_BUF_SIZE 60
1016

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

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

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

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

    
1047
        pcnet_rdte_poll(s);
1048

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

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

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

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

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

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

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

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

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

    
1152
#undef PCNET_RECV_STORE
1153

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

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

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

    
1188
            pcnet_rdte_poll(s);
1189

    
1190
        }
1191
    }
1192

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

    
1196
    return size_;
1197
}
1198

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

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

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

    
1212
    s->xmit_pos = -1;
1213

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

    
1219
    s->tx_busy = 1;
1220

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

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

    
1227
#ifdef PCNET_DEBUG_TMD
1228
        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1229
        PRINT_TMD(&tmd);
1230
#endif
1231
        if (GET_FIELD(tmd.status, TMDS, STP)) {
1232
            s->xmit_pos = 0;
1233
            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1234
            if (BCR_SWSTYLE(s) != 1)
1235
                add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1236
        }
1237
        if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1238
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1239
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1240
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1241
            s->xmit_pos += bcnt;
1242
        } else if (s->xmit_pos >= 0) {
1243
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1244
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1245
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1246
            s->xmit_pos += bcnt;
1247
#ifdef PCNET_DEBUG
1248
            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1249
#endif
1250
            if (CSR_LOOP(s)) {
1251
                if (BCR_SWSTYLE(s) == 1)
1252
                    add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1253
                s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1254
                pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos);
1255
                s->looptest = 0;
1256
            } else
1257
                if (s->nic)
1258
                    qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos);
1259

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

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

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

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

    
1294
    s->tx_busy = 0;
1295
}
1296

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

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

    
1310
        pcnet_transmit(s);
1311
    }
1312
}
1313

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

    
1318
    qemu_del_timer(s->poll_timer);
1319

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

    
1324
    pcnet_update_irq(s);
1325

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

    
1343

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

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

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

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

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

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

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

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

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

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

    
1477
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1478
{
1479
    rap &= 127;
1480
#ifdef PCNET_DEBUG_BCR
1481
    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1482
#endif
1483
    switch (rap) {
1484
    case BCR_SWS:
1485
        if (!(CSR_STOP(s) || CSR_SPND(s)))
1486
            return;
1487
        val &= ~0x0300;
1488
        switch (val & 0x00ff) {
1489
        case 0:
1490
            val |= 0x0200;
1491
            break;
1492
        case 1:
1493
            val |= 0x0100;
1494
            break;
1495
        case 2:
1496
        case 3:
1497
            val |= 0x0300;
1498
            break;
1499
        default:
1500
            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1501
            val = 0x0200;
1502
            break;
1503
        }
1504
#ifdef PCNET_DEBUG
1505
       printf("BCR_SWS=0x%04x\n", val);
1506
#endif
1507
        /* fall through */
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, object_get_typename(OBJECT(dev)), 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
    s->lnkst = 0x40; /* initial link state: up */
1754

    
1755
    return 0;
1756
}