Statistics
| Branch: | Revision:

root / hw / pcnet.c @ a4c75a21

History | View | Annotate | Download (53.6 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

    
43
#include "pcnet.h"
44

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

    
53

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

    
60
/* BUS CONFIGURATION REGISTERS */
61
#define BCR_MSRDA    0
62
#define BCR_MSWRA    1
63
#define BCR_MC       2
64
#define BCR_LNKST    4
65
#define BCR_LED1     5
66
#define BCR_LED2     6
67
#define BCR_LED3     7
68
#define BCR_FDC      9
69
#define BCR_BSBC     18
70
#define BCR_EECAS    19
71
#define BCR_SWS      20
72
#define BCR_PLAT     22
73

    
74
#define BCR_DWIO(S)      !!((S)->bcr[BCR_BSBC] & 0x0080)
75
#define BCR_SSIZE32(S)   !!((S)->bcr[BCR_SWS ] & 0x0100)
76
#define BCR_SWSTYLE(S)     ((S)->bcr[BCR_SWS ] & 0x00FF)
77

    
78
#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
79
#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
80
#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
81
#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
82
#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
83
#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
84
#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
85
#define CSR_BSWP(S)      !!(((S)->csr[3])&0x0004)
86
#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
87
#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
88
#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
89
#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
90
#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
91
#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
92
#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
93
#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
94
#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
95
#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
96
#define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
97
#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
98
#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
99
#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
100

    
101
#define CSR_CRBC(S)      ((S)->csr[40])
102
#define CSR_CRST(S)      ((S)->csr[41])
103
#define CSR_CXBC(S)      ((S)->csr[42])
104
#define CSR_CXST(S)      ((S)->csr[43])
105
#define CSR_NRBC(S)      ((S)->csr[44])
106
#define CSR_NRST(S)      ((S)->csr[45])
107
#define CSR_POLL(S)      ((S)->csr[46])
108
#define CSR_PINT(S)      ((S)->csr[47])
109
#define CSR_RCVRC(S)     ((S)->csr[72])
110
#define CSR_XMTRC(S)     ((S)->csr[74])
111
#define CSR_RCVRL(S)     ((S)->csr[76])
112
#define CSR_XMTRL(S)     ((S)->csr[78])
113
#define CSR_MISSC(S)     ((S)->csr[112])
114

    
115
#define CSR_IADR(S)      ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
116
#define CSR_CRBA(S)      ((S)->csr[18] | ((S)->csr[19] << 16))
117
#define CSR_CXBA(S)      ((S)->csr[20] | ((S)->csr[21] << 16))
118
#define CSR_NRBA(S)      ((S)->csr[22] | ((S)->csr[23] << 16))
119
#define CSR_BADR(S)      ((S)->csr[24] | ((S)->csr[25] << 16))
120
#define CSR_NRDA(S)      ((S)->csr[26] | ((S)->csr[27] << 16))
121
#define CSR_CRDA(S)      ((S)->csr[28] | ((S)->csr[29] << 16))
122
#define CSR_BADX(S)      ((S)->csr[30] | ((S)->csr[31] << 16))
123
#define CSR_NXDA(S)      ((S)->csr[32] | ((S)->csr[33] << 16))
124
#define CSR_CXDA(S)      ((S)->csr[34] | ((S)->csr[35] << 16))
125
#define CSR_NNRD(S)      ((S)->csr[36] | ((S)->csr[37] << 16))
126
#define CSR_NNXD(S)      ((S)->csr[38] | ((S)->csr[39] << 16))
127
#define CSR_PXDA(S)      ((S)->csr[60] | ((S)->csr[61] << 16))
128
#define CSR_NXBA(S)      ((S)->csr[64] | ((S)->csr[65] << 16))
129

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

    
133
struct pcnet_initblk16 {
134
    uint16_t mode;
135
    uint16_t padr[3];
136
    uint16_t ladrf[4];
137
    uint32_t rdra;
138
    uint32_t tdra;
139
};
140

    
141
struct pcnet_initblk32 {
142
    uint16_t mode;
143
    uint8_t rlen;
144
    uint8_t tlen;
145
    uint16_t padr[3];
146
    uint16_t _res;
147
    uint16_t ladrf[4];
148
    uint32_t rdra;
149
    uint32_t tdra;
150
};
151

    
152
struct pcnet_TMD {
153
    uint32_t tbadr;
154
    int16_t length;
155
    int16_t status;
156
    uint32_t misc;
157
    uint32_t res;
158
};
159

    
160
#define TMDL_BCNT_MASK  0x0fff
161
#define TMDL_BCNT_SH    0
162
#define TMDL_ONES_MASK  0xf000
163
#define TMDL_ONES_SH    12
164

    
165
#define TMDS_BPE_MASK   0x0080
166
#define TMDS_BPE_SH     7
167
#define TMDS_ENP_MASK   0x0100
168
#define TMDS_ENP_SH     8
169
#define TMDS_STP_MASK   0x0200
170
#define TMDS_STP_SH     9
171
#define TMDS_DEF_MASK   0x0400
172
#define TMDS_DEF_SH     10
173
#define TMDS_ONE_MASK   0x0800
174
#define TMDS_ONE_SH     11
175
#define TMDS_LTINT_MASK 0x1000
176
#define TMDS_LTINT_SH   12
177
#define TMDS_NOFCS_MASK 0x2000
178
#define TMDS_NOFCS_SH   13
179
#define TMDS_ADDFCS_MASK TMDS_NOFCS_MASK
180
#define TMDS_ADDFCS_SH  TMDS_NOFCS_SH
181
#define TMDS_ERR_MASK   0x4000
182
#define TMDS_ERR_SH     14
183
#define TMDS_OWN_MASK   0x8000
184
#define TMDS_OWN_SH     15
185

    
186
#define TMDM_TRC_MASK   0x0000000f
187
#define TMDM_TRC_SH     0
188
#define TMDM_TDR_MASK   0x03ff0000
189
#define TMDM_TDR_SH     16
190
#define TMDM_RTRY_MASK  0x04000000
191
#define TMDM_RTRY_SH    26
192
#define TMDM_LCAR_MASK  0x08000000
193
#define TMDM_LCAR_SH    27
194
#define TMDM_LCOL_MASK  0x10000000
195
#define TMDM_LCOL_SH    28
196
#define TMDM_EXDEF_MASK 0x20000000
197
#define TMDM_EXDEF_SH   29
198
#define TMDM_UFLO_MASK  0x40000000
199
#define TMDM_UFLO_SH    30
200
#define TMDM_BUFF_MASK  0x80000000
201
#define TMDM_BUFF_SH    31
202

    
203
struct pcnet_RMD {
204
    uint32_t rbadr;
205
    int16_t buf_length;
206
    int16_t status;
207
    uint32_t msg_length;
208
    uint32_t res;
209
};
210

    
211
#define RMDL_BCNT_MASK  0x0fff
212
#define RMDL_BCNT_SH    0
213
#define RMDL_ONES_MASK  0xf000
214
#define RMDL_ONES_SH    12
215

    
216
#define RMDS_BAM_MASK   0x0010
217
#define RMDS_BAM_SH     4
218
#define RMDS_LFAM_MASK  0x0020
219
#define RMDS_LFAM_SH    5
220
#define RMDS_PAM_MASK   0x0040
221
#define RMDS_PAM_SH     6
222
#define RMDS_BPE_MASK   0x0080
223
#define RMDS_BPE_SH     7
224
#define RMDS_ENP_MASK   0x0100
225
#define RMDS_ENP_SH     8
226
#define RMDS_STP_MASK   0x0200
227
#define RMDS_STP_SH     9
228
#define RMDS_BUFF_MASK  0x0400
229
#define RMDS_BUFF_SH    10
230
#define RMDS_CRC_MASK   0x0800
231
#define RMDS_CRC_SH     11
232
#define RMDS_OFLO_MASK  0x1000
233
#define RMDS_OFLO_SH    12
234
#define RMDS_FRAM_MASK  0x2000
235
#define RMDS_FRAM_SH    13
236
#define RMDS_ERR_MASK   0x4000
237
#define RMDS_ERR_SH     14
238
#define RMDS_OWN_MASK   0x8000
239
#define RMDS_OWN_SH     15
240

    
241
#define RMDM_MCNT_MASK  0x00000fff
242
#define RMDM_MCNT_SH    0
243
#define RMDM_ZEROS_MASK 0x0000f000
244
#define RMDM_ZEROS_SH   12
245
#define RMDM_RPC_MASK   0x00ff0000
246
#define RMDM_RPC_SH     16
247
#define RMDM_RCC_MASK   0xff000000
248
#define RMDM_RCC_SH     24
249

    
250
#define SET_FIELD(regp, name, field, value)             \
251
  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
252
             | ((value) << name ## _ ## field ## _SH))
253

    
254
#define GET_FIELD(reg, name, field)                     \
255
  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
256

    
257
#define PRINT_TMD(T) printf(                            \
258
        "TMD0 : TBADR=0x%08x\n"                         \
259
        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
260
        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
261
        "       BPE=%d, BCNT=%d\n"                      \
262
        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
263
        "LCA=%d, RTR=%d,\n"                             \
264
        "       TDR=%d, TRC=%d\n",                      \
265
        (T)->tbadr,                                     \
266
        GET_FIELD((T)->status, TMDS, OWN),              \
267
        GET_FIELD((T)->status, TMDS, ERR),              \
268
        GET_FIELD((T)->status, TMDS, NOFCS),            \
269
        GET_FIELD((T)->status, TMDS, LTINT),            \
270
        GET_FIELD((T)->status, TMDS, ONE),              \
271
        GET_FIELD((T)->status, TMDS, DEF),              \
272
        GET_FIELD((T)->status, TMDS, STP),              \
273
        GET_FIELD((T)->status, TMDS, ENP),              \
274
        GET_FIELD((T)->status, TMDS, BPE),              \
275
        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
276
        GET_FIELD((T)->misc, TMDM, BUFF),               \
277
        GET_FIELD((T)->misc, TMDM, UFLO),               \
278
        GET_FIELD((T)->misc, TMDM, EXDEF),              \
279
        GET_FIELD((T)->misc, TMDM, LCOL),               \
280
        GET_FIELD((T)->misc, TMDM, LCAR),               \
281
        GET_FIELD((T)->misc, TMDM, RTRY),               \
282
        GET_FIELD((T)->misc, TMDM, TDR),                \
283
        GET_FIELD((T)->misc, TMDM, TRC))
284

    
285
#define PRINT_RMD(R) printf(                            \
286
        "RMD0 : RBADR=0x%08x\n"                         \
287
        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
288
        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
289
        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
290
        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
291
        (R)->rbadr,                                     \
292
        GET_FIELD((R)->status, RMDS, OWN),              \
293
        GET_FIELD((R)->status, RMDS, ERR),              \
294
        GET_FIELD((R)->status, RMDS, FRAM),             \
295
        GET_FIELD((R)->status, RMDS, OFLO),             \
296
        GET_FIELD((R)->status, RMDS, CRC),              \
297
        GET_FIELD((R)->status, RMDS, BUFF),             \
298
        GET_FIELD((R)->status, RMDS, STP),              \
299
        GET_FIELD((R)->status, RMDS, ENP),              \
300
        GET_FIELD((R)->status, RMDS, BPE),              \
301
        GET_FIELD((R)->status, RMDS, PAM),              \
302
        GET_FIELD((R)->status, RMDS, LFAM),             \
303
        GET_FIELD((R)->status, RMDS, BAM),              \
304
        GET_FIELD((R)->buf_length, RMDL, ONES),         \
305
        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
306
        GET_FIELD((R)->msg_length, RMDM, RCC),          \
307
        GET_FIELD((R)->msg_length, RMDM, RPC),          \
308
        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
309
        GET_FIELD((R)->msg_length, RMDM, ZEROS))
310

    
311
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
312
                                  target_phys_addr_t addr)
313
{
314
    if (!BCR_SSIZE32(s)) {
315
        struct {
316
            uint32_t tbadr;
317
            int16_t length;
318
            int16_t status;
319
        } xda;
320
        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
321
        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
322
        tmd->length = le16_to_cpu(xda.length);
323
        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
324
        tmd->misc = le16_to_cpu(xda.status) << 16;
325
        tmd->res = 0;
326
    } else {
327
        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
328
        le32_to_cpus(&tmd->tbadr);
329
        le16_to_cpus((uint16_t *)&tmd->length);
330
        le16_to_cpus((uint16_t *)&tmd->status);
331
        le32_to_cpus(&tmd->misc);
332
        le32_to_cpus(&tmd->res);
333
        if (BCR_SWSTYLE(s) == 3) {
334
            uint32_t tmp = tmd->tbadr;
335
            tmd->tbadr = tmd->misc;
336
            tmd->misc = tmp;
337
        }
338
    }
339
}
340

    
341
static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
342
                                   target_phys_addr_t addr)
343
{
344
    if (!BCR_SSIZE32(s)) {
345
        struct {
346
            uint32_t tbadr;
347
            int16_t length;
348
            int16_t status;
349
        } xda;
350
        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
351
                                ((tmd->status & 0xff00) << 16));
352
        xda.length = cpu_to_le16(tmd->length);
353
        xda.status = cpu_to_le16(tmd->misc >> 16);
354
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
355
    } else {
356
        struct {
357
            uint32_t tbadr;
358
            int16_t length;
359
            int16_t status;
360
            uint32_t misc;
361
            uint32_t res;
362
        } xda;
363
        xda.tbadr = cpu_to_le32(tmd->tbadr);
364
        xda.length = cpu_to_le16(tmd->length);
365
        xda.status = cpu_to_le16(tmd->status);
366
        xda.misc = cpu_to_le32(tmd->misc);
367
        xda.res = cpu_to_le32(tmd->res);
368
        if (BCR_SWSTYLE(s) == 3) {
369
            uint32_t tmp = xda.tbadr;
370
            xda.tbadr = xda.misc;
371
            xda.misc = tmp;
372
        }
373
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
374
    }
375
}
376

    
377
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
378
                                  target_phys_addr_t addr)
379
{
380
    if (!BCR_SSIZE32(s)) {
381
        struct {
382
            uint32_t rbadr;
383
            int16_t buf_length;
384
            int16_t msg_length;
385
        } rda;
386
        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
387
        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
388
        rmd->buf_length = le16_to_cpu(rda.buf_length);
389
        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
390
        rmd->msg_length = le16_to_cpu(rda.msg_length);
391
        rmd->res = 0;
392
    } else {
393
        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
394
        le32_to_cpus(&rmd->rbadr);
395
        le16_to_cpus((uint16_t *)&rmd->buf_length);
396
        le16_to_cpus((uint16_t *)&rmd->status);
397
        le32_to_cpus(&rmd->msg_length);
398
        le32_to_cpus(&rmd->res);
399
        if (BCR_SWSTYLE(s) == 3) {
400
            uint32_t tmp = rmd->rbadr;
401
            rmd->rbadr = rmd->msg_length;
402
            rmd->msg_length = tmp;
403
        }
404
    }
405
}
406

    
407
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
408
                                   target_phys_addr_t addr)
409
{
410
    if (!BCR_SSIZE32(s)) {
411
        struct {
412
            uint32_t rbadr;
413
            int16_t buf_length;
414
            int16_t msg_length;
415
        } rda;
416
        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
417
                                ((rmd->status & 0xff00) << 16));
418
        rda.buf_length = cpu_to_le16(rmd->buf_length);
419
        rda.msg_length = cpu_to_le16(rmd->msg_length);
420
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
421
    } else {
422
        struct {
423
            uint32_t rbadr;
424
            int16_t buf_length;
425
            int16_t status;
426
            uint32_t msg_length;
427
            uint32_t res;
428
        } rda;
429
        rda.rbadr = cpu_to_le32(rmd->rbadr);
430
        rda.buf_length = cpu_to_le16(rmd->buf_length);
431
        rda.status = cpu_to_le16(rmd->status);
432
        rda.msg_length = cpu_to_le32(rmd->msg_length);
433
        rda.res = cpu_to_le32(rmd->res);
434
        if (BCR_SWSTYLE(s) == 3) {
435
            uint32_t tmp = rda.rbadr;
436
            rda.rbadr = rda.msg_length;
437
            rda.msg_length = tmp;
438
        }
439
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
440
    }
441
}
442

    
443

    
444
#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
445

    
446
#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
447

    
448
#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
449

    
450
#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
451

    
452
#if 1
453

    
454
#define CHECK_RMD(ADDR,RES) do {                \
455
    struct pcnet_RMD rmd;                       \
456
    RMDLOAD(&rmd,(ADDR));                       \
457
    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
458
          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
459
} while (0)
460

    
461
#define CHECK_TMD(ADDR,RES) do {                \
462
    struct pcnet_TMD tmd;                       \
463
    TMDLOAD(&tmd,(ADDR));                       \
464
    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
465
} while (0)
466

    
467
#else
468

    
469
#define CHECK_RMD(ADDR,RES) do {                \
470
    switch (BCR_SWSTYLE(s)) {                   \
471
    case 0x00:                                  \
472
        do {                                    \
473
            uint16_t rda[4];                    \
474
            s->phys_mem_read(s->dma_opaque, (ADDR), \
475
                (void *)&rda[0], sizeof(rda), 0); \
476
            (RES) |= (rda[2] & 0xf000)!=0xf000; \
477
            (RES) |= (rda[3] & 0xf000)!=0x0000; \
478
        } while (0);                            \
479
        break;                                  \
480
    case 0x01:                                  \
481
    case 0x02:                                  \
482
        do {                                    \
483
            uint32_t rda[4];                    \
484
            s->phys_mem_read(s->dma_opaque, (ADDR), \
485
                (void *)&rda[0], sizeof(rda), 0); \
486
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
487
            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
488
        } while (0);                            \
489
        break;                                  \
490
    case 0x03:                                  \
491
        do {                                    \
492
            uint32_t rda[4];                    \
493
            s->phys_mem_read(s->dma_opaque, (ADDR), \
494
                (void *)&rda[0], sizeof(rda), 0); \
495
            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
496
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
497
        } while (0);                            \
498
        break;                                  \
499
    }                                           \
500
} while (0)
501

    
502
#define CHECK_TMD(ADDR,RES) do {                \
503
    switch (BCR_SWSTYLE(s)) {                   \
504
    case 0x00:                                  \
505
        do {                                    \
506
            uint16_t xda[4];                    \
507
            s->phys_mem_read(s->dma_opaque, (ADDR), \
508
                (void *)&xda[0], sizeof(xda), 0); \
509
            (RES) |= (xda[2] & 0xf000)!=0xf000; \
510
        } while (0);                            \
511
        break;                                  \
512
    case 0x01:                                  \
513
    case 0x02:                                  \
514
    case 0x03:                                  \
515
        do {                                    \
516
            uint32_t xda[4];                    \
517
            s->phys_mem_read(s->dma_opaque, (ADDR), \
518
                (void *)&xda[0], sizeof(xda), 0); \
519
            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
520
        } while (0);                            \
521
        break;                                  \
522
    }                                           \
523
} while (0)
524

    
525
#endif
526

    
527
#define PRINT_PKTHDR(BUF) do {                  \
528
    struct qemu_ether_header *hdr = (void *)(BUF); \
529
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
530
           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
531
           "type=0x%04x\n",                     \
532
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
533
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
534
           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
535
           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
536
           be16_to_cpu(hdr->ether_type));       \
537
} while (0)
538

    
539
#define MULTICAST_FILTER_LEN 8
540

    
541
static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
542
{
543
#define LNC_POLYNOMIAL          0xEDB88320UL
544
    uint32_t crc = 0xFFFFFFFF;
545
    int idx, bit;
546
    uint8_t data;
547

    
548
    for (idx = 0; idx < 6; idx++) {
549
        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
550
            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
551
            data >>= 1;
552
        }
553
    }
554
    return crc;
555
#undef LNC_POLYNOMIAL
556
}
557

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

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

    
631
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
632
{
633
    struct qemu_ether_header *hdr = (void *)buf;
634
    uint8_t padr[6] = {
635
        s->csr[12] & 0xff, s->csr[12] >> 8,
636
        s->csr[13] & 0xff, s->csr[13] >> 8,
637
        s->csr[14] & 0xff, s->csr[14] >> 8
638
    };
639
    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
640
#ifdef PCNET_DEBUG_MATCH
641
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
642
           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
643
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
644
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
645
           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
646
    printf("padr_match result=%d\n", result);
647
#endif
648
    return result;
649
}
650

    
651
static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
652
{
653
    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
654
    struct qemu_ether_header *hdr = (void *)buf;
655
    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
656
#ifdef PCNET_DEBUG_MATCH
657
    printf("padr_bcast result=%d\n", result);
658
#endif
659
    return result;
660
}
661

    
662
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
663
{
664
    struct qemu_ether_header *hdr = (void *)buf;
665
    if ((*(hdr->ether_dhost)&0x01) &&
666
        ((uint64_t *)&s->csr[8])[0] != 0LL) {
667
        uint8_t ladr[8] = {
668
            s->csr[8] & 0xff, s->csr[8] >> 8,
669
            s->csr[9] & 0xff, s->csr[9] >> 8,
670
            s->csr[10] & 0xff, s->csr[10] >> 8,
671
            s->csr[11] & 0xff, s->csr[11] >> 8
672
        };
673
        int index = lnc_mchash(hdr->ether_dhost) >> 26;
674
        return !!(ladr[index >> 3] & (1 << (index & 7)));
675
    }
676
    return 0;
677
}
678

    
679
static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
680
{
681
    while (idx < 1) idx += CSR_RCVRL(s);
682
    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
683
}
684

    
685
static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
686
{
687
    int64_t next_time = current_time +
688
        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
689
                 get_ticks_per_sec(), 33000000L);
690
    if (next_time <= current_time)
691
        next_time = current_time + 1;
692
    return next_time;
693
}
694

    
695
static void pcnet_poll(PCNetState *s);
696
static void pcnet_poll_timer(void *opaque);
697

    
698
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
699
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
700
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
701

    
702
static void pcnet_s_reset(PCNetState *s)
703
{
704
#ifdef PCNET_DEBUG
705
    printf("pcnet_s_reset\n");
706
#endif
707

    
708
    s->lnkst = 0x40;
709
    s->rdra = 0;
710
    s->tdra = 0;
711
    s->rap = 0;
712

    
713
    s->bcr[BCR_BSBC] &= ~0x0080;
714

    
715
    s->csr[0]   = 0x0004;
716
    s->csr[3]   = 0x0000;
717
    s->csr[4]   = 0x0115;
718
    s->csr[5]   = 0x0000;
719
    s->csr[6]   = 0x0000;
720
    s->csr[8]   = 0;
721
    s->csr[9]   = 0;
722
    s->csr[10]  = 0;
723
    s->csr[11]  = 0;
724
    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
725
    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
726
    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
727
    s->csr[15] &= 0x21c4;
728
    s->csr[72]  = 1;
729
    s->csr[74]  = 1;
730
    s->csr[76]  = 1;
731
    s->csr[78]  = 1;
732
    s->csr[80]  = 0x1410;
733
    s->csr[88]  = 0x1003;
734
    s->csr[89]  = 0x0262;
735
    s->csr[94]  = 0x0000;
736
    s->csr[100] = 0x0200;
737
    s->csr[103] = 0x0105;
738
    s->csr[103] = 0x0105;
739
    s->csr[112] = 0x0000;
740
    s->csr[114] = 0x0000;
741
    s->csr[122] = 0x0000;
742
    s->csr[124] = 0x0000;
743

    
744
    s->tx_busy = 0;
745
}
746

    
747
static void pcnet_update_irq(PCNetState *s)
748
{
749
    int isr = 0;
750
    s->csr[0] &= ~0x0080;
751

    
752
#if 1
753
    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
754
        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
755
        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
756
#else
757
    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
758
        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
759
        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
760
        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
761
        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
762
        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
763
        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
764
        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
765
        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
766
        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
767
        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
768
        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
769
#endif
770
    {
771

    
772
        isr = CSR_INEA(s);
773
        s->csr[0] |= 0x0080;
774
    }
775

    
776
    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
777
        s->csr[4] &= ~0x0080;
778
        s->csr[4] |= 0x0040;
779
        s->csr[0] |= 0x0080;
780
        isr = 1;
781
#ifdef PCNET_DEBUG
782
        printf("pcnet user int\n");
783
#endif
784
    }
785

    
786
#if 1
787
    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
788
#else
789
    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
790
        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
791
#endif
792
    {
793
        isr = 1;
794
        s->csr[0] |= 0x0080;
795
    }
796

    
797
    if (isr != s->isr) {
798
#ifdef PCNET_DEBUG
799
        printf("pcnet: INTA=%d\n", isr);
800
#endif
801
    }
802
    qemu_set_irq(s->irq, isr);
803
    s->isr = isr;
804
}
805

    
806
static void pcnet_init(PCNetState *s)
807
{
808
    int rlen, tlen;
809
    uint16_t padr[3], ladrf[4], mode;
810
    uint32_t rdra, tdra;
811

    
812
#ifdef PCNET_DEBUG
813
    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
814
#endif
815

    
816
    if (BCR_SSIZE32(s)) {
817
        struct pcnet_initblk32 initblk;
818
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
819
                (uint8_t *)&initblk, sizeof(initblk), 0);
820
        mode = le16_to_cpu(initblk.mode);
821
        rlen = initblk.rlen >> 4;
822
        tlen = initblk.tlen >> 4;
823
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
824
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
825
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
826
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
827
        padr[0] = le16_to_cpu(initblk.padr[0]);
828
        padr[1] = le16_to_cpu(initblk.padr[1]);
829
        padr[2] = le16_to_cpu(initblk.padr[2]);
830
        rdra = le32_to_cpu(initblk.rdra);
831
        tdra = le32_to_cpu(initblk.tdra);
832
    } else {
833
        struct pcnet_initblk16 initblk;
834
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
835
                (uint8_t *)&initblk, sizeof(initblk), 0);
836
        mode = le16_to_cpu(initblk.mode);
837
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
838
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
839
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
840
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
841
        padr[0] = le16_to_cpu(initblk.padr[0]);
842
        padr[1] = le16_to_cpu(initblk.padr[1]);
843
        padr[2] = le16_to_cpu(initblk.padr[2]);
844
        rdra = le32_to_cpu(initblk.rdra);
845
        tdra = le32_to_cpu(initblk.tdra);
846
        rlen = rdra >> 29;
847
        tlen = tdra >> 29;
848
        rdra &= 0x00ffffff;
849
        tdra &= 0x00ffffff;
850
    }
851

    
852
#if defined(PCNET_DEBUG)
853
    printf("rlen=%d tlen=%d\n", rlen, tlen);
854
#endif
855

    
856
    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
857
    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
858
    s->csr[ 6] = (tlen << 12) | (rlen << 8);
859
    s->csr[15] = mode;
860
    s->csr[ 8] = ladrf[0];
861
    s->csr[ 9] = ladrf[1];
862
    s->csr[10] = ladrf[2];
863
    s->csr[11] = ladrf[3];
864
    s->csr[12] = padr[0];
865
    s->csr[13] = padr[1];
866
    s->csr[14] = padr[2];
867
    s->rdra = PHYSADDR(s, rdra);
868
    s->tdra = PHYSADDR(s, tdra);
869

    
870
    CSR_RCVRC(s) = CSR_RCVRL(s);
871
    CSR_XMTRC(s) = CSR_XMTRL(s);
872

    
873
#ifdef PCNET_DEBUG
874
    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
875
        BCR_SSIZE32(s),
876
        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
877
#endif
878

    
879
    s->csr[0] |= 0x0101;
880
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
881
}
882

    
883
static void pcnet_start(PCNetState *s)
884
{
885
#ifdef PCNET_DEBUG
886
    printf("pcnet_start\n");
887
#endif
888

    
889
    if (!CSR_DTX(s))
890
        s->csr[0] |= 0x0010;    /* set TXON */
891

    
892
    if (!CSR_DRX(s))
893
        s->csr[0] |= 0x0020;    /* set RXON */
894

    
895
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
896
    s->csr[0] |= 0x0002;
897
    pcnet_poll_timer(s);
898
}
899

    
900
static void pcnet_stop(PCNetState *s)
901
{
902
#ifdef PCNET_DEBUG
903
    printf("pcnet_stop\n");
904
#endif
905
    s->csr[0] &= ~0x7feb;
906
    s->csr[0] |= 0x0014;
907
    s->csr[4] &= ~0x02c2;
908
    s->csr[5] &= ~0x0011;
909
    pcnet_poll_timer(s);
910
}
911

    
912
static void pcnet_rdte_poll(PCNetState *s)
913
{
914
    s->csr[28] = s->csr[29] = 0;
915
    if (s->rdra) {
916
        int bad = 0;
917
#if 1
918
        target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
919
        target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
920
        target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
921
#else
922
        target_phys_addr_t crda = s->rdra +
923
            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
924
            (BCR_SWSTYLE(s) ? 16 : 8 );
925
        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
926
        target_phys_addr_t nrda = s->rdra +
927
            (CSR_RCVRL(s) - nrdc) *
928
            (BCR_SWSTYLE(s) ? 16 : 8 );
929
        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
930
        target_phys_addr_t nnrd = s->rdra +
931
            (CSR_RCVRL(s) - nnrc) *
932
            (BCR_SWSTYLE(s) ? 16 : 8 );
933
#endif
934

    
935
        CHECK_RMD(crda, bad);
936
        if (!bad) {
937
            CHECK_RMD(nrda, bad);
938
            if (bad || (nrda == crda)) nrda = 0;
939
            CHECK_RMD(nnrd, bad);
940
            if (bad || (nnrd == crda)) nnrd = 0;
941

    
942
            s->csr[28] = crda & 0xffff;
943
            s->csr[29] = crda >> 16;
944
            s->csr[26] = nrda & 0xffff;
945
            s->csr[27] = nrda >> 16;
946
            s->csr[36] = nnrd & 0xffff;
947
            s->csr[37] = nnrd >> 16;
948
#ifdef PCNET_DEBUG
949
            if (bad) {
950
                printf("pcnet: BAD RMD RECORDS AFTER 0x" TARGET_FMT_plx "\n",
951
                       crda);
952
            }
953
        } else {
954
            printf("pcnet: BAD RMD RDA=0x" TARGET_FMT_plx "\n",
955
                   crda);
956
#endif
957
        }
958
    }
959

    
960
    if (CSR_CRDA(s)) {
961
        struct pcnet_RMD rmd;
962
        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
963
        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
964
        CSR_CRST(s) = rmd.status;
965
#ifdef PCNET_DEBUG_RMD_X
966
        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
967
                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
968
                rmd.buf_length, rmd.status, rmd.msg_length);
969
        PRINT_RMD(&rmd);
970
#endif
971
    } else {
972
        CSR_CRBC(s) = CSR_CRST(s) = 0;
973
    }
974

    
975
    if (CSR_NRDA(s)) {
976
        struct pcnet_RMD rmd;
977
        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
978
        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
979
        CSR_NRST(s) = rmd.status;
980
    } else {
981
        CSR_NRBC(s) = CSR_NRST(s) = 0;
982
    }
983

    
984
}
985

    
986
static int pcnet_tdte_poll(PCNetState *s)
987
{
988
    s->csr[34] = s->csr[35] = 0;
989
    if (s->tdra) {
990
        target_phys_addr_t cxda = s->tdra +
991
            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
992
            (BCR_SWSTYLE(s) ? 16 : 8);
993
        int bad = 0;
994
        CHECK_TMD(cxda, bad);
995
        if (!bad) {
996
            if (CSR_CXDA(s) != cxda) {
997
                s->csr[60] = s->csr[34];
998
                s->csr[61] = s->csr[35];
999
                s->csr[62] = CSR_CXBC(s);
1000
                s->csr[63] = CSR_CXST(s);
1001
            }
1002
            s->csr[34] = cxda & 0xffff;
1003
            s->csr[35] = cxda >> 16;
1004
#ifdef PCNET_DEBUG_X
1005
            printf("pcnet: BAD TMD XDA=0x%08x\n", cxda);
1006
#endif
1007
        }
1008
    }
1009

    
1010
    if (CSR_CXDA(s)) {
1011
        struct pcnet_TMD tmd;
1012

    
1013
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1014

    
1015
        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
1016
        CSR_CXST(s) = tmd.status;
1017
    } else {
1018
        CSR_CXBC(s) = CSR_CXST(s) = 0;
1019
    }
1020

    
1021
    return !!(CSR_CXST(s) & 0x8000);
1022
}
1023

    
1024
int pcnet_can_receive(VLANClientState *nc)
1025
{
1026
    PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1027
    if (CSR_STOP(s) || CSR_SPND(s))
1028
        return 0;
1029

    
1030
    return sizeof(s->buffer)-16;
1031
}
1032

    
1033
#define MIN_BUF_SIZE 60
1034

    
1035
ssize_t pcnet_receive(VLANClientState *nc, const uint8_t *buf, size_t size_)
1036
{
1037
    PCNetState *s = DO_UPCAST(NICState, nc, nc)->opaque;
1038
    int is_padr = 0, is_bcast = 0, is_ladr = 0;
1039
    uint8_t buf1[60];
1040
    int remaining;
1041
    int crc_err = 0;
1042
    int size = size_;
1043

    
1044
    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
1045
        (CSR_LOOP(s) && !s->looptest)) {
1046
        return -1;
1047
    }
1048
#ifdef PCNET_DEBUG
1049
    printf("pcnet_receive size=%d\n", size);
1050
#endif
1051

    
1052
    /* if too small buffer, then expand it */
1053
    if (size < MIN_BUF_SIZE) {
1054
        memcpy(buf1, buf, size);
1055
        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1056
        buf = buf1;
1057
        size = MIN_BUF_SIZE;
1058
    }
1059

    
1060
    if (CSR_PROM(s)
1061
        || (is_padr=padr_match(s, buf, size))
1062
        || (is_bcast=padr_bcast(s, buf, size))
1063
        || (is_ladr=ladr_match(s, buf, size))) {
1064

    
1065
        pcnet_rdte_poll(s);
1066

    
1067
        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1068
            struct pcnet_RMD rmd;
1069
            int rcvrc = CSR_RCVRC(s)-1,i;
1070
            target_phys_addr_t nrda;
1071
            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1072
                if (rcvrc <= 1)
1073
                    rcvrc = CSR_RCVRL(s);
1074
                nrda = s->rdra +
1075
                    (CSR_RCVRL(s) - rcvrc) *
1076
                    (BCR_SWSTYLE(s) ? 16 : 8 );
1077
                RMDLOAD(&rmd, nrda);
1078
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1079
#ifdef PCNET_DEBUG_RMD
1080
                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1081
                                rcvrc, CSR_RCVRC(s));
1082
#endif
1083
                    CSR_RCVRC(s) = rcvrc;
1084
                    pcnet_rdte_poll(s);
1085
                    break;
1086
                }
1087
            }
1088
        }
1089

    
1090
        if (!(CSR_CRST(s) & 0x8000)) {
1091
#ifdef PCNET_DEBUG_RMD
1092
            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1093
#endif
1094
            s->csr[0] |= 0x1000; /* Set MISS flag */
1095
            CSR_MISSC(s)++;
1096
        } else {
1097
            uint8_t *src = s->buffer;
1098
            target_phys_addr_t crda = CSR_CRDA(s);
1099
            struct pcnet_RMD rmd;
1100
            int pktcount = 0;
1101

    
1102
            if (!s->looptest) {
1103
                memcpy(src, buf, size);
1104
                /* no need to compute the CRC */
1105
                src[size] = 0;
1106
                src[size + 1] = 0;
1107
                src[size + 2] = 0;
1108
                src[size + 3] = 0;
1109
                size += 4;
1110
            } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1111
                       !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1112
                uint32_t fcs = ~0;
1113
                uint8_t *p = src;
1114

    
1115
                while (p != &src[size])
1116
                    CRC(fcs, *p++);
1117
                *(uint32_t *)p = htonl(fcs);
1118
                size += 4;
1119
            } else {
1120
                uint32_t fcs = ~0;
1121
                uint8_t *p = src;
1122

    
1123
                while (p != &src[size-4])
1124
                    CRC(fcs, *p++);
1125
                crc_err = (*(uint32_t *)p != htonl(fcs));
1126
            }
1127

    
1128
#ifdef PCNET_DEBUG_MATCH
1129
            PRINT_PKTHDR(buf);
1130
#endif
1131

    
1132
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1133
            /*if (!CSR_LAPPEN(s))*/
1134
                SET_FIELD(&rmd.status, RMDS, STP, 1);
1135

    
1136
#define PCNET_RECV_STORE() do {                                 \
1137
    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1138
    target_phys_addr_t rbadr = PHYSADDR(s, rmd.rbadr);          \
1139
    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1140
    src += count; remaining -= count;                           \
1141
    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1142
    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1143
    pktcount++;                                                 \
1144
} while (0)
1145

    
1146
            remaining = size;
1147
            PCNET_RECV_STORE();
1148
            if ((remaining > 0) && CSR_NRDA(s)) {
1149
                target_phys_addr_t nrda = CSR_NRDA(s);
1150
#ifdef PCNET_DEBUG_RMD
1151
                PRINT_RMD(&rmd);
1152
#endif
1153
                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1154
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1155
                    crda = nrda;
1156
                    PCNET_RECV_STORE();
1157
#ifdef PCNET_DEBUG_RMD
1158
                    PRINT_RMD(&rmd);
1159
#endif
1160
                    if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1161
                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1162
                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
1163
                            crda = nrda;
1164
                            PCNET_RECV_STORE();
1165
                        }
1166
                    }
1167
                }
1168
            }
1169

    
1170
#undef PCNET_RECV_STORE
1171

    
1172
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1173
            if (remaining == 0) {
1174
                SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1175
                SET_FIELD(&rmd.status, RMDS, ENP, 1);
1176
                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1177
                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1178
                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1179
                if (crc_err) {
1180
                    SET_FIELD(&rmd.status, RMDS, CRC, 1);
1181
                    SET_FIELD(&rmd.status, RMDS, ERR, 1);
1182
                }
1183
            } else {
1184
                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1185
                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1186
                SET_FIELD(&rmd.status, RMDS, ERR, 1);
1187
            }
1188
            RMDSTORE(&rmd, PHYSADDR(s,crda));
1189
            s->csr[0] |= 0x0400;
1190

    
1191
#ifdef PCNET_DEBUG
1192
            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1193
                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1194
#endif
1195
#ifdef PCNET_DEBUG_RMD
1196
            PRINT_RMD(&rmd);
1197
#endif
1198

    
1199
            while (pktcount--) {
1200
                if (CSR_RCVRC(s) <= 1)
1201
                    CSR_RCVRC(s) = CSR_RCVRL(s);
1202
                else
1203
                    CSR_RCVRC(s)--;
1204
            }
1205

    
1206
            pcnet_rdte_poll(s);
1207

    
1208
        }
1209
    }
1210

    
1211
    pcnet_poll(s);
1212
    pcnet_update_irq(s);
1213

    
1214
    return size_;
1215
}
1216

    
1217
static void pcnet_transmit(PCNetState *s)
1218
{
1219
    target_phys_addr_t xmit_cxda = 0;
1220
    int count = CSR_XMTRL(s)-1;
1221
    int add_crc = 0;
1222

    
1223
    s->xmit_pos = -1;
1224

    
1225
    if (!CSR_TXON(s)) {
1226
        s->csr[0] &= ~0x0008;
1227
        return;
1228
    }
1229

    
1230
    s->tx_busy = 1;
1231

    
1232
    txagain:
1233
    if (pcnet_tdte_poll(s)) {
1234
        struct pcnet_TMD tmd;
1235

    
1236
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1237

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

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

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

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

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

    
1305
    s->tx_busy = 0;
1306
}
1307

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

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

    
1321
        pcnet_transmit(s);
1322
    }
1323
}
1324

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

    
1329
    qemu_del_timer(s->poll_timer);
1330

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

    
1335
    pcnet_update_irq(s);
1336

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

    
1354

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

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

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

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

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

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

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

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

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

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

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

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

    
1556
void pcnet_h_reset(void *opaque)
1557
{
1558
    PCNetState *s = opaque;
1559
    int i;
1560
    uint16_t checksum;
1561

    
1562
    /* Initialize the PROM */
1563

    
1564
    memcpy(s->prom, s->conf.macaddr.a, 6);
1565
    s->prom[12] = s->prom[13] = 0x00;
1566
    s->prom[14] = s->prom[15] = 0x57;
1567

    
1568
    for (i = 0,checksum = 0; i < 16; i++)
1569
        checksum += s->prom[i];
1570
    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1571

    
1572

    
1573
    s->bcr[BCR_MSRDA] = 0x0005;
1574
    s->bcr[BCR_MSWRA] = 0x0005;
1575
    s->bcr[BCR_MC   ] = 0x0002;
1576
    s->bcr[BCR_LNKST] = 0x00c0;
1577
    s->bcr[BCR_LED1 ] = 0x0084;
1578
    s->bcr[BCR_LED2 ] = 0x0088;
1579
    s->bcr[BCR_LED3 ] = 0x0090;
1580
    s->bcr[BCR_FDC  ] = 0x0000;
1581
    s->bcr[BCR_BSBC ] = 0x9001;
1582
    s->bcr[BCR_EECAS] = 0x0002;
1583
    s->bcr[BCR_SWS  ] = 0x0200;
1584
    s->bcr[BCR_PLAT ] = 0xff06;
1585

    
1586
    pcnet_s_reset(s);
1587
    pcnet_update_irq(s);
1588
    pcnet_poll_timer(s);
1589
}
1590

    
1591
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1592
{
1593
    PCNetState *s = opaque;
1594
    pcnet_poll_timer(s);
1595
#ifdef PCNET_DEBUG_IO
1596
    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1597
#endif
1598
    if (!BCR_DWIO(s)) {
1599
        switch (addr & 0x0f) {
1600
        case 0x00: /* RDP */
1601
            pcnet_csr_writew(s, s->rap, val);
1602
            break;
1603
        case 0x02:
1604
            s->rap = val & 0x7f;
1605
            break;
1606
        case 0x06:
1607
            pcnet_bcr_writew(s, s->rap, val);
1608
            break;
1609
        }
1610
    }
1611
    pcnet_update_irq(s);
1612
}
1613

    
1614
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1615
{
1616
    PCNetState *s = opaque;
1617
    uint32_t val = -1;
1618
    pcnet_poll_timer(s);
1619
    if (!BCR_DWIO(s)) {
1620
        switch (addr & 0x0f) {
1621
        case 0x00: /* RDP */
1622
            val = pcnet_csr_readw(s, s->rap);
1623
            break;
1624
        case 0x02:
1625
            val = s->rap;
1626
            break;
1627
        case 0x04:
1628
            pcnet_s_reset(s);
1629
            val = 0;
1630
            break;
1631
        case 0x06:
1632
            val = pcnet_bcr_readw(s, s->rap);
1633
            break;
1634
        }
1635
    }
1636
    pcnet_update_irq(s);
1637
#ifdef PCNET_DEBUG_IO
1638
    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1639
#endif
1640
    return val;
1641
}
1642

    
1643
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1644
{
1645
    PCNetState *s = opaque;
1646
    pcnet_poll_timer(s);
1647
#ifdef PCNET_DEBUG_IO
1648
    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1649
#endif
1650
    if (BCR_DWIO(s)) {
1651
        switch (addr & 0x0f) {
1652
        case 0x00: /* RDP */
1653
            pcnet_csr_writew(s, s->rap, val & 0xffff);
1654
            break;
1655
        case 0x04:
1656
            s->rap = val & 0x7f;
1657
            break;
1658
        case 0x0c:
1659
            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1660
            break;
1661
        }
1662
    } else
1663
    if ((addr & 0x0f) == 0) {
1664
        /* switch device to dword i/o mode */
1665
        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1666
#ifdef PCNET_DEBUG_IO
1667
        printf("device switched into dword i/o mode\n");
1668
#endif
1669
    }
1670
    pcnet_update_irq(s);
1671
}
1672

    
1673
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1674
{
1675
    PCNetState *s = opaque;
1676
    uint32_t val = -1;
1677
    pcnet_poll_timer(s);
1678
    if (BCR_DWIO(s)) {
1679
        switch (addr & 0x0f) {
1680
        case 0x00: /* RDP */
1681
            val = pcnet_csr_readw(s, s->rap);
1682
            break;
1683
        case 0x04:
1684
            val = s->rap;
1685
            break;
1686
        case 0x08:
1687
            pcnet_s_reset(s);
1688
            val = 0;
1689
            break;
1690
        case 0x0c:
1691
            val = pcnet_bcr_readw(s, s->rap);
1692
            break;
1693
        }
1694
    }
1695
    pcnet_update_irq(s);
1696
#ifdef PCNET_DEBUG_IO
1697
    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1698
#endif
1699
    return val;
1700
}
1701

    
1702
static bool is_version_2(void *opaque, int version_id)
1703
{
1704
    return version_id == 2;
1705
}
1706

    
1707
const VMStateDescription vmstate_pcnet = {
1708
    .name = "pcnet",
1709
    .version_id = 3,
1710
    .minimum_version_id = 2,
1711
    .minimum_version_id_old = 2,
1712
    .fields      = (VMStateField []) {
1713
        VMSTATE_INT32(rap, PCNetState),
1714
        VMSTATE_INT32(isr, PCNetState),
1715
        VMSTATE_INT32(lnkst, PCNetState),
1716
        VMSTATE_UINT32(rdra, PCNetState),
1717
        VMSTATE_UINT32(tdra, PCNetState),
1718
        VMSTATE_BUFFER(prom, PCNetState),
1719
        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1720
        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1721
        VMSTATE_UINT64(timer, PCNetState),
1722
        VMSTATE_INT32(xmit_pos, PCNetState),
1723
        VMSTATE_BUFFER(buffer, PCNetState),
1724
        VMSTATE_UNUSED_TEST(is_version_2, 4),
1725
        VMSTATE_INT32(tx_busy, PCNetState),
1726
        VMSTATE_TIMER(poll_timer, PCNetState),
1727
        VMSTATE_END_OF_LIST()
1728
    }
1729
};
1730

    
1731
void pcnet_common_cleanup(PCNetState *d)
1732
{
1733
    d->nic = NULL;
1734
}
1735

    
1736
int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1737
{
1738
    s->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, s);
1739

    
1740
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1741
    s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
1742
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1743
    return 0;
1744
}