Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 9a6ee9fd

History | View | Annotate | Download (54.5 kB)

1 e3c2613f bellard
/*
2 e3c2613f bellard
 * QEMU AMD PC-Net II (Am79C970A) emulation
3 5fafdf24 ths
 *
4 e3c2613f bellard
 * Copyright (c) 2004 Antony T Curtis
5 5fafdf24 ths
 *
6 e3c2613f bellard
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 e3c2613f bellard
 * of this software and associated documentation files (the "Software"), to deal
8 e3c2613f bellard
 * in the Software without restriction, including without limitation the rights
9 e3c2613f bellard
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 e3c2613f bellard
 * copies of the Software, and to permit persons to whom the Software is
11 e3c2613f bellard
 * furnished to do so, subject to the following conditions:
12 e3c2613f bellard
 *
13 e3c2613f bellard
 * The above copyright notice and this permission notice shall be included in
14 e3c2613f bellard
 * all copies or substantial portions of the Software.
15 e3c2613f bellard
 *
16 e3c2613f bellard
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 e3c2613f bellard
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 e3c2613f bellard
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19 e3c2613f bellard
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 e3c2613f bellard
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 e3c2613f bellard
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22 e3c2613f bellard
 * THE SOFTWARE.
23 e3c2613f bellard
 */
24 5fafdf24 ths
25 e3c2613f bellard
/* This software was written to be compatible with the specification:
26 e3c2613f bellard
 * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
27 e3c2613f bellard
 * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
28 e3c2613f bellard
 */
29 5fafdf24 ths
30 91cc0295 bellard
/*
31 91cc0295 bellard
 * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also
32 91cc0295 bellard
 * produced as NCR89C100. See
33 91cc0295 bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
34 91cc0295 bellard
 * and
35 91cc0295 bellard
 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
36 91cc0295 bellard
 */
37 91cc0295 bellard
38 a4c75a21 Paul Brook
#include "qdev.h"
39 1422e32d Paolo Bonzini
#include "net/net.h"
40 1de7afc9 Paolo Bonzini
#include "qemu/timer.h"
41 1de7afc9 Paolo Bonzini
#include "qemu/sockets.h"
42 9c17d615 Paolo Bonzini
#include "sysemu/sysemu.h"
43 e3c2613f bellard
44 94e1a912 Gerd Hoffmann
#include "pcnet.h"
45 94e1a912 Gerd Hoffmann
46 e3c2613f bellard
//#define PCNET_DEBUG
47 e3c2613f bellard
//#define PCNET_DEBUG_IO
48 e3c2613f bellard
//#define PCNET_DEBUG_BCR
49 e3c2613f bellard
//#define PCNET_DEBUG_CSR
50 e3c2613f bellard
//#define PCNET_DEBUG_RMD
51 e3c2613f bellard
//#define PCNET_DEBUG_TMD
52 e3c2613f bellard
//#define PCNET_DEBUG_MATCH
53 e3c2613f bellard
54 e3c2613f bellard
55 219fb125 bellard
struct qemu_ether_header {
56 219fb125 bellard
    uint8_t ether_dhost[6];
57 219fb125 bellard
    uint8_t ether_shost[6];
58 219fb125 bellard
    uint16_t ether_type;
59 219fb125 bellard
};
60 219fb125 bellard
61 e3c2613f bellard
#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
62 e3c2613f bellard
#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
63 e3c2613f bellard
#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
64 e3c2613f bellard
#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
65 e3c2613f bellard
#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
66 e3c2613f bellard
#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
67 e3c2613f bellard
#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
68 9b94dc32 bellard
#define CSR_BSWP(S)      !!(((S)->csr[3])&0x0004)
69 e3c2613f bellard
#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
70 e3c2613f bellard
#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
71 e3c2613f bellard
#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
72 e3c2613f bellard
#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
73 e3c2613f bellard
#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
74 e3c2613f bellard
#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
75 e3c2613f bellard
#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
76 e3c2613f bellard
#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
77 e3c2613f bellard
#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
78 e3c2613f bellard
#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
79 89b190a2 aurel32
#define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
80 ef45c914 Jan Kiszka
#define CSR_INTL(S)      !!(((S)->csr[15])&0x0040)
81 e3c2613f bellard
#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
82 e3c2613f bellard
#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
83 e3c2613f bellard
#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
84 e3c2613f bellard
85 e3c2613f bellard
#define CSR_CRBC(S)      ((S)->csr[40])
86 e3c2613f bellard
#define CSR_CRST(S)      ((S)->csr[41])
87 e3c2613f bellard
#define CSR_CXBC(S)      ((S)->csr[42])
88 e3c2613f bellard
#define CSR_CXST(S)      ((S)->csr[43])
89 e3c2613f bellard
#define CSR_NRBC(S)      ((S)->csr[44])
90 e3c2613f bellard
#define CSR_NRST(S)      ((S)->csr[45])
91 e3c2613f bellard
#define CSR_POLL(S)      ((S)->csr[46])
92 e3c2613f bellard
#define CSR_PINT(S)      ((S)->csr[47])
93 e3c2613f bellard
#define CSR_RCVRC(S)     ((S)->csr[72])
94 e3c2613f bellard
#define CSR_XMTRC(S)     ((S)->csr[74])
95 e3c2613f bellard
#define CSR_RCVRL(S)     ((S)->csr[76])
96 e3c2613f bellard
#define CSR_XMTRL(S)     ((S)->csr[78])
97 e3c2613f bellard
#define CSR_MISSC(S)     ((S)->csr[112])
98 e3c2613f bellard
99 366c9332 Michael Brown
#define CSR_IADR(S)      ((S)->csr[ 1] | ((uint32_t)(S)->csr[ 2] << 16))
100 366c9332 Michael Brown
#define CSR_CRBA(S)      ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16))
101 366c9332 Michael Brown
#define CSR_CXBA(S)      ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16))
102 366c9332 Michael Brown
#define CSR_NRBA(S)      ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16))
103 366c9332 Michael Brown
#define CSR_BADR(S)      ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16))
104 366c9332 Michael Brown
#define CSR_NRDA(S)      ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16))
105 366c9332 Michael Brown
#define CSR_CRDA(S)      ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16))
106 366c9332 Michael Brown
#define CSR_BADX(S)      ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16))
107 366c9332 Michael Brown
#define CSR_NXDA(S)      ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16))
108 366c9332 Michael Brown
#define CSR_CXDA(S)      ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16))
109 366c9332 Michael Brown
#define CSR_NNRD(S)      ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16))
110 366c9332 Michael Brown
#define CSR_NNXD(S)      ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16))
111 366c9332 Michael Brown
#define CSR_PXDA(S)      ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16))
112 366c9332 Michael Brown
#define CSR_NXBA(S)      ((S)->csr[64] | ((uint32_t)(S)->csr[65] << 16))
113 e3c2613f bellard
114 e3c2613f bellard
#define PHYSADDR(S,A) \
115 366c9332 Michael Brown
  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
116 e3c2613f bellard
117 e3c2613f bellard
struct pcnet_initblk16 {
118 e3c2613f bellard
    uint16_t mode;
119 91cc0295 bellard
    uint16_t padr[3];
120 91cc0295 bellard
    uint16_t ladrf[4];
121 91cc0295 bellard
    uint32_t rdra;
122 91cc0295 bellard
    uint32_t tdra;
123 e3c2613f bellard
};
124 e3c2613f bellard
125 e3c2613f bellard
struct pcnet_initblk32 {
126 e3c2613f bellard
    uint16_t mode;
127 91cc0295 bellard
    uint8_t rlen;
128 91cc0295 bellard
    uint8_t tlen;
129 91cc0295 bellard
    uint16_t padr[3];
130 e3c2613f bellard
    uint16_t _res;
131 91cc0295 bellard
    uint16_t ladrf[4];
132 e3c2613f bellard
    uint32_t rdra;
133 e3c2613f bellard
    uint32_t tdra;
134 e3c2613f bellard
};
135 e3c2613f bellard
136 e3c2613f bellard
struct pcnet_TMD {
137 6d2980f5 ths
    uint32_t tbadr;
138 6d2980f5 ths
    int16_t length;
139 6d2980f5 ths
    int16_t status;
140 6d2980f5 ths
    uint32_t misc;
141 6d2980f5 ths
    uint32_t res;
142 e3c2613f bellard
};
143 e3c2613f bellard
144 6d2980f5 ths
#define TMDL_BCNT_MASK  0x0fff
145 6d2980f5 ths
#define TMDL_BCNT_SH    0
146 6d2980f5 ths
#define TMDL_ONES_MASK  0xf000
147 6d2980f5 ths
#define TMDL_ONES_SH    12
148 6d2980f5 ths
149 6d2980f5 ths
#define TMDS_BPE_MASK   0x0080
150 6d2980f5 ths
#define TMDS_BPE_SH     7
151 6d2980f5 ths
#define TMDS_ENP_MASK   0x0100
152 6d2980f5 ths
#define TMDS_ENP_SH     8
153 6d2980f5 ths
#define TMDS_STP_MASK   0x0200
154 6d2980f5 ths
#define TMDS_STP_SH     9
155 6d2980f5 ths
#define TMDS_DEF_MASK   0x0400
156 6d2980f5 ths
#define TMDS_DEF_SH     10
157 6d2980f5 ths
#define TMDS_ONE_MASK   0x0800
158 6d2980f5 ths
#define TMDS_ONE_SH     11
159 6d2980f5 ths
#define TMDS_LTINT_MASK 0x1000
160 6d2980f5 ths
#define TMDS_LTINT_SH   12
161 6d2980f5 ths
#define TMDS_NOFCS_MASK 0x2000
162 6d2980f5 ths
#define TMDS_NOFCS_SH   13
163 89b190a2 aurel32
#define TMDS_ADDFCS_MASK TMDS_NOFCS_MASK
164 89b190a2 aurel32
#define TMDS_ADDFCS_SH  TMDS_NOFCS_SH
165 6d2980f5 ths
#define TMDS_ERR_MASK   0x4000
166 6d2980f5 ths
#define TMDS_ERR_SH     14
167 6d2980f5 ths
#define TMDS_OWN_MASK   0x8000
168 6d2980f5 ths
#define TMDS_OWN_SH     15
169 6d2980f5 ths
170 6d2980f5 ths
#define TMDM_TRC_MASK   0x0000000f
171 6d2980f5 ths
#define TMDM_TRC_SH     0
172 6d2980f5 ths
#define TMDM_TDR_MASK   0x03ff0000
173 6d2980f5 ths
#define TMDM_TDR_SH     16
174 6d2980f5 ths
#define TMDM_RTRY_MASK  0x04000000
175 6d2980f5 ths
#define TMDM_RTRY_SH    26
176 6d2980f5 ths
#define TMDM_LCAR_MASK  0x08000000
177 6d2980f5 ths
#define TMDM_LCAR_SH    27
178 6d2980f5 ths
#define TMDM_LCOL_MASK  0x10000000
179 6d2980f5 ths
#define TMDM_LCOL_SH    28
180 6d2980f5 ths
#define TMDM_EXDEF_MASK 0x20000000
181 6d2980f5 ths
#define TMDM_EXDEF_SH   29
182 6d2980f5 ths
#define TMDM_UFLO_MASK  0x40000000
183 6d2980f5 ths
#define TMDM_UFLO_SH    30
184 6d2980f5 ths
#define TMDM_BUFF_MASK  0x80000000
185 6d2980f5 ths
#define TMDM_BUFF_SH    31
186 6d2980f5 ths
187 e3c2613f bellard
struct pcnet_RMD {
188 6d2980f5 ths
    uint32_t rbadr;
189 6d2980f5 ths
    int16_t buf_length;
190 6d2980f5 ths
    int16_t status;
191 6d2980f5 ths
    uint32_t msg_length;
192 6d2980f5 ths
    uint32_t res;
193 e3c2613f bellard
};
194 e3c2613f bellard
195 6d2980f5 ths
#define RMDL_BCNT_MASK  0x0fff
196 6d2980f5 ths
#define RMDL_BCNT_SH    0
197 6d2980f5 ths
#define RMDL_ONES_MASK  0xf000
198 6d2980f5 ths
#define RMDL_ONES_SH    12
199 6d2980f5 ths
200 6d2980f5 ths
#define RMDS_BAM_MASK   0x0010
201 6d2980f5 ths
#define RMDS_BAM_SH     4
202 6d2980f5 ths
#define RMDS_LFAM_MASK  0x0020
203 6d2980f5 ths
#define RMDS_LFAM_SH    5
204 6d2980f5 ths
#define RMDS_PAM_MASK   0x0040
205 6d2980f5 ths
#define RMDS_PAM_SH     6
206 6d2980f5 ths
#define RMDS_BPE_MASK   0x0080
207 6d2980f5 ths
#define RMDS_BPE_SH     7
208 6d2980f5 ths
#define RMDS_ENP_MASK   0x0100
209 6d2980f5 ths
#define RMDS_ENP_SH     8
210 6d2980f5 ths
#define RMDS_STP_MASK   0x0200
211 6d2980f5 ths
#define RMDS_STP_SH     9
212 6d2980f5 ths
#define RMDS_BUFF_MASK  0x0400
213 6d2980f5 ths
#define RMDS_BUFF_SH    10
214 6d2980f5 ths
#define RMDS_CRC_MASK   0x0800
215 6d2980f5 ths
#define RMDS_CRC_SH     11
216 6d2980f5 ths
#define RMDS_OFLO_MASK  0x1000
217 6d2980f5 ths
#define RMDS_OFLO_SH    12
218 6d2980f5 ths
#define RMDS_FRAM_MASK  0x2000
219 6d2980f5 ths
#define RMDS_FRAM_SH    13
220 6d2980f5 ths
#define RMDS_ERR_MASK   0x4000
221 6d2980f5 ths
#define RMDS_ERR_SH     14
222 6d2980f5 ths
#define RMDS_OWN_MASK   0x8000
223 6d2980f5 ths
#define RMDS_OWN_SH     15
224 6d2980f5 ths
225 6d2980f5 ths
#define RMDM_MCNT_MASK  0x00000fff
226 6d2980f5 ths
#define RMDM_MCNT_SH    0
227 6d2980f5 ths
#define RMDM_ZEROS_MASK 0x0000f000
228 6d2980f5 ths
#define RMDM_ZEROS_SH   12
229 6d2980f5 ths
#define RMDM_RPC_MASK   0x00ff0000
230 6d2980f5 ths
#define RMDM_RPC_SH     16
231 6d2980f5 ths
#define RMDM_RCC_MASK   0xff000000
232 6d2980f5 ths
#define RMDM_RCC_SH     24
233 6d2980f5 ths
234 6d2980f5 ths
#define SET_FIELD(regp, name, field, value)             \
235 6d2980f5 ths
  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
236 6d2980f5 ths
             | ((value) << name ## _ ## field ## _SH))
237 6d2980f5 ths
238 6d2980f5 ths
#define GET_FIELD(reg, name, field)                     \
239 6d2980f5 ths
  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
240 6d2980f5 ths
241 6d2980f5 ths
#define PRINT_TMD(T) printf(                            \
242 6d2980f5 ths
        "TMD0 : TBADR=0x%08x\n"                         \
243 e3c2613f bellard
        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
244 e3c2613f bellard
        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
245 e3c2613f bellard
        "       BPE=%d, BCNT=%d\n"                      \
246 e3c2613f bellard
        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
247 e3c2613f bellard
        "LCA=%d, RTR=%d,\n"                             \
248 e3c2613f bellard
        "       TDR=%d, TRC=%d\n",                      \
249 6d2980f5 ths
        (T)->tbadr,                                     \
250 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, OWN),              \
251 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, ERR),              \
252 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, NOFCS),            \
253 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, LTINT),            \
254 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, ONE),              \
255 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, DEF),              \
256 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, STP),              \
257 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, ENP),              \
258 6d2980f5 ths
        GET_FIELD((T)->status, TMDS, BPE),              \
259 6d2980f5 ths
        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
260 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, BUFF),               \
261 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, UFLO),               \
262 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, EXDEF),              \
263 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, LCOL),               \
264 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, LCAR),               \
265 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, RTRY),               \
266 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, TDR),                \
267 6d2980f5 ths
        GET_FIELD((T)->misc, TMDM, TRC))
268 6d2980f5 ths
269 6d2980f5 ths
#define PRINT_RMD(R) printf(                            \
270 6d2980f5 ths
        "RMD0 : RBADR=0x%08x\n"                         \
271 e3c2613f bellard
        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
272 e3c2613f bellard
        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
273 6d2980f5 ths
        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
274 e3c2613f bellard
        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
275 6d2980f5 ths
        (R)->rbadr,                                     \
276 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, OWN),              \
277 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, ERR),              \
278 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, FRAM),             \
279 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, OFLO),             \
280 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, CRC),              \
281 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, BUFF),             \
282 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, STP),              \
283 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, ENP),              \
284 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, BPE),              \
285 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, PAM),              \
286 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, LFAM),             \
287 6d2980f5 ths
        GET_FIELD((R)->status, RMDS, BAM),              \
288 6d2980f5 ths
        GET_FIELD((R)->buf_length, RMDL, ONES),         \
289 6d2980f5 ths
        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
290 6d2980f5 ths
        GET_FIELD((R)->msg_length, RMDM, RCC),          \
291 6d2980f5 ths
        GET_FIELD((R)->msg_length, RMDM, RPC),          \
292 6d2980f5 ths
        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
293 6d2980f5 ths
        GET_FIELD((R)->msg_length, RMDM, ZEROS))
294 6d2980f5 ths
295 6d2980f5 ths
static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
296 a8170e5e Avi Kivity
                                  hwaddr addr)
297 e3c2613f bellard
{
298 6d2980f5 ths
    if (!BCR_SSIZE32(s)) {
299 6d2980f5 ths
        struct {
300 6d2980f5 ths
            uint32_t tbadr;
301 6d2980f5 ths
            int16_t length;
302 6d2980f5 ths
            int16_t status;
303 6d2980f5 ths
        } xda;
304 6d2980f5 ths
        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
305 6d2980f5 ths
        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
306 6d2980f5 ths
        tmd->length = le16_to_cpu(xda.length);
307 6d2980f5 ths
        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
308 6d2980f5 ths
        tmd->misc = le16_to_cpu(xda.status) << 16;
309 6d2980f5 ths
        tmd->res = 0;
310 03c18475 bellard
    } else {
311 6d2980f5 ths
        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
312 6d2980f5 ths
        le32_to_cpus(&tmd->tbadr);
313 69b34976 ths
        le16_to_cpus((uint16_t *)&tmd->length);
314 69b34976 ths
        le16_to_cpus((uint16_t *)&tmd->status);
315 6d2980f5 ths
        le32_to_cpus(&tmd->misc);
316 6d2980f5 ths
        le32_to_cpus(&tmd->res);
317 6d2980f5 ths
        if (BCR_SWSTYLE(s) == 3) {
318 6d2980f5 ths
            uint32_t tmp = tmd->tbadr;
319 6d2980f5 ths
            tmd->tbadr = tmd->misc;
320 6d2980f5 ths
            tmd->misc = tmp;
321 03c18475 bellard
        }
322 e3c2613f bellard
    }
323 e3c2613f bellard
}
324 e3c2613f bellard
325 6d2980f5 ths
static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
326 a8170e5e Avi Kivity
                                   hwaddr addr)
327 e3c2613f bellard
{
328 6d2980f5 ths
    if (!BCR_SSIZE32(s)) {
329 6d2980f5 ths
        struct {
330 6d2980f5 ths
            uint32_t tbadr;
331 6d2980f5 ths
            int16_t length;
332 6d2980f5 ths
            int16_t status;
333 6d2980f5 ths
        } xda;
334 6d2980f5 ths
        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
335 6d2980f5 ths
                                ((tmd->status & 0xff00) << 16));
336 6d2980f5 ths
        xda.length = cpu_to_le16(tmd->length);
337 6d2980f5 ths
        xda.status = cpu_to_le16(tmd->misc >> 16);
338 6d2980f5 ths
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
339 03c18475 bellard
    } else {
340 6d2980f5 ths
        struct {
341 6d2980f5 ths
            uint32_t tbadr;
342 6d2980f5 ths
            int16_t length;
343 6d2980f5 ths
            int16_t status;
344 6d2980f5 ths
            uint32_t misc;
345 6d2980f5 ths
            uint32_t res;
346 6d2980f5 ths
        } xda;
347 6d2980f5 ths
        xda.tbadr = cpu_to_le32(tmd->tbadr);
348 6d2980f5 ths
        xda.length = cpu_to_le16(tmd->length);
349 6d2980f5 ths
        xda.status = cpu_to_le16(tmd->status);
350 6d2980f5 ths
        xda.misc = cpu_to_le32(tmd->misc);
351 6d2980f5 ths
        xda.res = cpu_to_le32(tmd->res);
352 6d2980f5 ths
        if (BCR_SWSTYLE(s) == 3) {
353 6d2980f5 ths
            uint32_t tmp = xda.tbadr;
354 6d2980f5 ths
            xda.tbadr = xda.misc;
355 6d2980f5 ths
            xda.misc = tmp;
356 03c18475 bellard
        }
357 6d2980f5 ths
        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
358 e3c2613f bellard
    }
359 e3c2613f bellard
}
360 e3c2613f bellard
361 6d2980f5 ths
static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
362 a8170e5e Avi Kivity
                                  hwaddr addr)
363 e3c2613f bellard
{
364 6d2980f5 ths
    if (!BCR_SSIZE32(s)) {
365 6d2980f5 ths
        struct {
366 6d2980f5 ths
            uint32_t rbadr;
367 6d2980f5 ths
            int16_t buf_length;
368 6d2980f5 ths
            int16_t msg_length;
369 6d2980f5 ths
        } rda;
370 6d2980f5 ths
        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
371 6d2980f5 ths
        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
372 6d2980f5 ths
        rmd->buf_length = le16_to_cpu(rda.buf_length);
373 6d2980f5 ths
        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
374 6d2980f5 ths
        rmd->msg_length = le16_to_cpu(rda.msg_length);
375 6d2980f5 ths
        rmd->res = 0;
376 03c18475 bellard
    } else {
377 6d2980f5 ths
        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
378 6d2980f5 ths
        le32_to_cpus(&rmd->rbadr);
379 69b34976 ths
        le16_to_cpus((uint16_t *)&rmd->buf_length);
380 69b34976 ths
        le16_to_cpus((uint16_t *)&rmd->status);
381 6d2980f5 ths
        le32_to_cpus(&rmd->msg_length);
382 6d2980f5 ths
        le32_to_cpus(&rmd->res);
383 6d2980f5 ths
        if (BCR_SWSTYLE(s) == 3) {
384 6d2980f5 ths
            uint32_t tmp = rmd->rbadr;
385 6d2980f5 ths
            rmd->rbadr = rmd->msg_length;
386 6d2980f5 ths
            rmd->msg_length = tmp;
387 03c18475 bellard
        }
388 e3c2613f bellard
    }
389 e3c2613f bellard
}
390 e3c2613f bellard
391 6d2980f5 ths
static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
392 a8170e5e Avi Kivity
                                   hwaddr addr)
393 e3c2613f bellard
{
394 6d2980f5 ths
    if (!BCR_SSIZE32(s)) {
395 6d2980f5 ths
        struct {
396 6d2980f5 ths
            uint32_t rbadr;
397 6d2980f5 ths
            int16_t buf_length;
398 6d2980f5 ths
            int16_t msg_length;
399 6d2980f5 ths
        } rda;
400 6d2980f5 ths
        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
401 6d2980f5 ths
                                ((rmd->status & 0xff00) << 16));
402 6d2980f5 ths
        rda.buf_length = cpu_to_le16(rmd->buf_length);
403 6d2980f5 ths
        rda.msg_length = cpu_to_le16(rmd->msg_length);
404 6d2980f5 ths
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
405 03c18475 bellard
    } else {
406 6d2980f5 ths
        struct {
407 6d2980f5 ths
            uint32_t rbadr;
408 6d2980f5 ths
            int16_t buf_length;
409 6d2980f5 ths
            int16_t status;
410 6d2980f5 ths
            uint32_t msg_length;
411 6d2980f5 ths
            uint32_t res;
412 6d2980f5 ths
        } rda;
413 6d2980f5 ths
        rda.rbadr = cpu_to_le32(rmd->rbadr);
414 6d2980f5 ths
        rda.buf_length = cpu_to_le16(rmd->buf_length);
415 6d2980f5 ths
        rda.status = cpu_to_le16(rmd->status);
416 6d2980f5 ths
        rda.msg_length = cpu_to_le32(rmd->msg_length);
417 6d2980f5 ths
        rda.res = cpu_to_le32(rmd->res);
418 6d2980f5 ths
        if (BCR_SWSTYLE(s) == 3) {
419 6d2980f5 ths
            uint32_t tmp = rda.rbadr;
420 6d2980f5 ths
            rda.rbadr = rda.msg_length;
421 6d2980f5 ths
            rda.msg_length = tmp;
422 e3c2613f bellard
        }
423 6d2980f5 ths
        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
424 e3c2613f bellard
    }
425 e3c2613f bellard
}
426 e3c2613f bellard
427 e3c2613f bellard
428 e3c2613f bellard
#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
429 e3c2613f bellard
430 e3c2613f bellard
#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
431 e3c2613f bellard
432 e3c2613f bellard
#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
433 e3c2613f bellard
434 e3c2613f bellard
#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
435 e3c2613f bellard
436 e3c2613f bellard
#if 1
437 e3c2613f bellard
438 e3c2613f bellard
#define CHECK_RMD(ADDR,RES) do {                \
439 e3c2613f bellard
    struct pcnet_RMD rmd;                       \
440 e3c2613f bellard
    RMDLOAD(&rmd,(ADDR));                       \
441 6d2980f5 ths
    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
442 6d2980f5 ths
          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
443 e3c2613f bellard
} while (0)
444 e3c2613f bellard
445 e3c2613f bellard
#define CHECK_TMD(ADDR,RES) do {                \
446 e3c2613f bellard
    struct pcnet_TMD tmd;                       \
447 e3c2613f bellard
    TMDLOAD(&tmd,(ADDR));                       \
448 6d2980f5 ths
    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
449 e3c2613f bellard
} while (0)
450 e3c2613f bellard
451 e3c2613f bellard
#else
452 e3c2613f bellard
453 e3c2613f bellard
#define CHECK_RMD(ADDR,RES) do {                \
454 e3c2613f bellard
    switch (BCR_SWSTYLE(s)) {                   \
455 e3c2613f bellard
    case 0x00:                                  \
456 e3c2613f bellard
        do {                                    \
457 e3c2613f bellard
            uint16_t rda[4];                    \
458 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, (ADDR), \
459 6d2980f5 ths
                (void *)&rda[0], sizeof(rda), 0); \
460 e3c2613f bellard
            (RES) |= (rda[2] & 0xf000)!=0xf000; \
461 e3c2613f bellard
            (RES) |= (rda[3] & 0xf000)!=0x0000; \
462 e3c2613f bellard
        } while (0);                            \
463 e3c2613f bellard
        break;                                  \
464 e3c2613f bellard
    case 0x01:                                  \
465 e3c2613f bellard
    case 0x02:                                  \
466 e3c2613f bellard
        do {                                    \
467 e3c2613f bellard
            uint32_t rda[4];                    \
468 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, (ADDR), \
469 9b94dc32 bellard
                (void *)&rda[0], sizeof(rda), 0); \
470 e3c2613f bellard
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
471 e3c2613f bellard
            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
472 e3c2613f bellard
        } while (0);                            \
473 e3c2613f bellard
        break;                                  \
474 e3c2613f bellard
    case 0x03:                                  \
475 e3c2613f bellard
        do {                                    \
476 e3c2613f bellard
            uint32_t rda[4];                    \
477 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, (ADDR), \
478 9b94dc32 bellard
                (void *)&rda[0], sizeof(rda), 0); \
479 e3c2613f bellard
            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
480 e3c2613f bellard
            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
481 e3c2613f bellard
        } while (0);                            \
482 e3c2613f bellard
        break;                                  \
483 e3c2613f bellard
    }                                           \
484 e3c2613f bellard
} while (0)
485 e3c2613f bellard
486 e3c2613f bellard
#define CHECK_TMD(ADDR,RES) do {                \
487 e3c2613f bellard
    switch (BCR_SWSTYLE(s)) {                   \
488 e3c2613f bellard
    case 0x00:                                  \
489 e3c2613f bellard
        do {                                    \
490 e3c2613f bellard
            uint16_t xda[4];                    \
491 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, (ADDR), \
492 6d2980f5 ths
                (void *)&xda[0], sizeof(xda), 0); \
493 6d2980f5 ths
            (RES) |= (xda[2] & 0xf000)!=0xf000; \
494 e3c2613f bellard
        } while (0);                            \
495 e3c2613f bellard
        break;                                  \
496 e3c2613f bellard
    case 0x01:                                  \
497 e3c2613f bellard
    case 0x02:                                  \
498 e3c2613f bellard
    case 0x03:                                  \
499 e3c2613f bellard
        do {                                    \
500 e3c2613f bellard
            uint32_t xda[4];                    \
501 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, (ADDR), \
502 6d2980f5 ths
                (void *)&xda[0], sizeof(xda), 0); \
503 e3c2613f bellard
            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
504 e3c2613f bellard
        } while (0);                            \
505 e3c2613f bellard
        break;                                  \
506 e3c2613f bellard
    }                                           \
507 e3c2613f bellard
} while (0)
508 e3c2613f bellard
509 e3c2613f bellard
#endif
510 e3c2613f bellard
511 e3c2613f bellard
#define PRINT_PKTHDR(BUF) do {                  \
512 6d2980f5 ths
    struct qemu_ether_header *hdr = (void *)(BUF); \
513 6d2980f5 ths
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
514 6d2980f5 ths
           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
515 6d2980f5 ths
           "type=0x%04x\n",                     \
516 e3c2613f bellard
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
517 e3c2613f bellard
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
518 e3c2613f bellard
           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
519 e3c2613f bellard
           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
520 6d2980f5 ths
           be16_to_cpu(hdr->ether_type));       \
521 e3c2613f bellard
} while (0)
522 e3c2613f bellard
523 e3c2613f bellard
#define MULTICAST_FILTER_LEN 8
524 e3c2613f bellard
525 e3c2613f bellard
static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
526 e3c2613f bellard
{
527 e3c2613f bellard
#define LNC_POLYNOMIAL          0xEDB88320UL
528 e3c2613f bellard
    uint32_t crc = 0xFFFFFFFF;
529 e3c2613f bellard
    int idx, bit;
530 e3c2613f bellard
    uint8_t data;
531 e3c2613f bellard
532 219fb125 bellard
    for (idx = 0; idx < 6; idx++) {
533 e3c2613f bellard
        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
534 e3c2613f bellard
            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
535 e3c2613f bellard
            data >>= 1;
536 e3c2613f bellard
        }
537 e3c2613f bellard
    }
538 e3c2613f bellard
    return crc;
539 e3c2613f bellard
#undef LNC_POLYNOMIAL
540 e3c2613f bellard
}
541 e3c2613f bellard
542 e3c2613f bellard
#define CRC(crc, ch)         (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
543 e3c2613f bellard
544 e3c2613f bellard
/* generated using the AUTODIN II polynomial
545 e3c2613f bellard
 *        x^32 + x^26 + x^23 + x^22 + x^16 +
546 e3c2613f bellard
 *        x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
547 e3c2613f bellard
 */
548 e3c2613f bellard
static const uint32_t crctab[256] = {
549 e3c2613f bellard
        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
550 e3c2613f bellard
        0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
551 e3c2613f bellard
        0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
552 e3c2613f bellard
        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
553 e3c2613f bellard
        0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
554 e3c2613f bellard
        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
555 e3c2613f bellard
        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
556 e3c2613f bellard
        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
557 e3c2613f bellard
        0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
558 e3c2613f bellard
        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
559 e3c2613f bellard
        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
560 e3c2613f bellard
        0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
561 e3c2613f bellard
        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
562 e3c2613f bellard
        0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
563 e3c2613f bellard
        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
564 e3c2613f bellard
        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
565 e3c2613f bellard
        0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
566 e3c2613f bellard
        0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
567 e3c2613f bellard
        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
568 e3c2613f bellard
        0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
569 e3c2613f bellard
        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
570 e3c2613f bellard
        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
571 e3c2613f bellard
        0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
572 e3c2613f bellard
        0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
573 e3c2613f bellard
        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
574 e3c2613f bellard
        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
575 e3c2613f bellard
        0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
576 e3c2613f bellard
        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
577 e3c2613f bellard
        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
578 e3c2613f bellard
        0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
579 e3c2613f bellard
        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
580 e3c2613f bellard
        0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
581 e3c2613f bellard
        0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
582 e3c2613f bellard
        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
583 e3c2613f bellard
        0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
584 e3c2613f bellard
        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
585 e3c2613f bellard
        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
586 e3c2613f bellard
        0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
587 e3c2613f bellard
        0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
588 e3c2613f bellard
        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
589 e3c2613f bellard
        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
590 e3c2613f bellard
        0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
591 e3c2613f bellard
        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
592 e3c2613f bellard
        0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
593 e3c2613f bellard
        0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
594 e3c2613f bellard
        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
595 e3c2613f bellard
        0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
596 e3c2613f bellard
        0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
597 e3c2613f bellard
        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
598 e3c2613f bellard
        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
599 e3c2613f bellard
        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
600 e3c2613f bellard
        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
601 e3c2613f bellard
        0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
602 e3c2613f bellard
        0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
603 e3c2613f bellard
        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
604 e3c2613f bellard
        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
605 e3c2613f bellard
        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
606 e3c2613f bellard
        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
607 e3c2613f bellard
        0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
608 e3c2613f bellard
        0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
609 e3c2613f bellard
        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
610 e3c2613f bellard
        0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
611 e3c2613f bellard
        0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
612 e3c2613f bellard
        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
613 e3c2613f bellard
};
614 e3c2613f bellard
615 e3c2613f bellard
static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
616 e3c2613f bellard
{
617 219fb125 bellard
    struct qemu_ether_header *hdr = (void *)buf;
618 5fafdf24 ths
    uint8_t padr[6] = {
619 e3c2613f bellard
        s->csr[12] & 0xff, s->csr[12] >> 8,
620 e3c2613f bellard
        s->csr[13] & 0xff, s->csr[13] >> 8,
621 5fafdf24 ths
        s->csr[14] & 0xff, s->csr[14] >> 8
622 e3c2613f bellard
    };
623 29b9a345 bellard
    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
624 e3c2613f bellard
#ifdef PCNET_DEBUG_MATCH
625 e3c2613f bellard
    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
626 e3c2613f bellard
           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
627 e3c2613f bellard
           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
628 e3c2613f bellard
           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
629 e3c2613f bellard
           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
630 e3c2613f bellard
    printf("padr_match result=%d\n", result);
631 e3c2613f bellard
#endif
632 e3c2613f bellard
    return result;
633 e3c2613f bellard
}
634 e3c2613f bellard
635 e3c2613f bellard
static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
636 e3c2613f bellard
{
637 9b94dc32 bellard
    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
638 219fb125 bellard
    struct qemu_ether_header *hdr = (void *)buf;
639 29b9a345 bellard
    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
640 e3c2613f bellard
#ifdef PCNET_DEBUG_MATCH
641 e3c2613f bellard
    printf("padr_bcast result=%d\n", result);
642 e3c2613f bellard
#endif
643 e3c2613f bellard
    return result;
644 e3c2613f bellard
}
645 e3c2613f bellard
646 e3c2613f bellard
static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
647 e3c2613f bellard
{
648 219fb125 bellard
    struct qemu_ether_header *hdr = (void *)buf;
649 5fafdf24 ths
    if ((*(hdr->ether_dhost)&0x01) &&
650 e3c2613f bellard
        ((uint64_t *)&s->csr[8])[0] != 0LL) {
651 5fafdf24 ths
        uint8_t ladr[8] = {
652 e3c2613f bellard
            s->csr[8] & 0xff, s->csr[8] >> 8,
653 e3c2613f bellard
            s->csr[9] & 0xff, s->csr[9] >> 8,
654 5fafdf24 ths
            s->csr[10] & 0xff, s->csr[10] >> 8,
655 5fafdf24 ths
            s->csr[11] & 0xff, s->csr[11] >> 8
656 e3c2613f bellard
        };
657 e3c2613f bellard
        int index = lnc_mchash(hdr->ether_dhost) >> 26;
658 e3c2613f bellard
        return !!(ladr[index >> 3] & (1 << (index & 7)));
659 e3c2613f bellard
    }
660 e3c2613f bellard
    return 0;
661 e3c2613f bellard
}
662 e3c2613f bellard
663 a8170e5e Avi Kivity
static inline hwaddr pcnet_rdra_addr(PCNetState *s, int idx)
664 e3c2613f bellard
{
665 e3c2613f bellard
    while (idx < 1) idx += CSR_RCVRL(s);
666 e3c2613f bellard
    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
667 e3c2613f bellard
}
668 e3c2613f bellard
669 e3c2613f bellard
static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
670 e3c2613f bellard
{
671 5fafdf24 ths
    int64_t next_time = current_time +
672 5fafdf24 ths
        muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
673 6ee093c9 Juan Quintela
                 get_ticks_per_sec(), 33000000L);
674 e3c2613f bellard
    if (next_time <= current_time)
675 e3c2613f bellard
        next_time = current_time + 1;
676 e3c2613f bellard
    return next_time;
677 e3c2613f bellard
}
678 e3c2613f bellard
679 e3c2613f bellard
static void pcnet_poll(PCNetState *s);
680 e3c2613f bellard
static void pcnet_poll_timer(void *opaque);
681 e3c2613f bellard
682 e3c2613f bellard
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
683 e3c2613f bellard
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
684 e3c2613f bellard
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
685 e3c2613f bellard
686 e3c2613f bellard
static void pcnet_s_reset(PCNetState *s)
687 e3c2613f bellard
{
688 e3c2613f bellard
#ifdef PCNET_DEBUG
689 e3c2613f bellard
    printf("pcnet_s_reset\n");
690 e3c2613f bellard
#endif
691 e3c2613f bellard
692 e3c2613f bellard
    s->rdra = 0;
693 e3c2613f bellard
    s->tdra = 0;
694 e3c2613f bellard
    s->rap = 0;
695 3b46e624 ths
696 e3c2613f bellard
    s->bcr[BCR_BSBC] &= ~0x0080;
697 e3c2613f bellard
698 e3c2613f bellard
    s->csr[0]   = 0x0004;
699 e3c2613f bellard
    s->csr[3]   = 0x0000;
700 e3c2613f bellard
    s->csr[4]   = 0x0115;
701 e3c2613f bellard
    s->csr[5]   = 0x0000;
702 e3c2613f bellard
    s->csr[6]   = 0x0000;
703 e3c2613f bellard
    s->csr[8]   = 0;
704 e3c2613f bellard
    s->csr[9]   = 0;
705 e3c2613f bellard
    s->csr[10]  = 0;
706 e3c2613f bellard
    s->csr[11]  = 0;
707 e3c2613f bellard
    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
708 e3c2613f bellard
    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
709 e3c2613f bellard
    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
710 e3c2613f bellard
    s->csr[15] &= 0x21c4;
711 e3c2613f bellard
    s->csr[72]  = 1;
712 e3c2613f bellard
    s->csr[74]  = 1;
713 e3c2613f bellard
    s->csr[76]  = 1;
714 e3c2613f bellard
    s->csr[78]  = 1;
715 e3c2613f bellard
    s->csr[80]  = 0x1410;
716 e3c2613f bellard
    s->csr[88]  = 0x1003;
717 e3c2613f bellard
    s->csr[89]  = 0x0262;
718 e3c2613f bellard
    s->csr[94]  = 0x0000;
719 e3c2613f bellard
    s->csr[100] = 0x0200;
720 e3c2613f bellard
    s->csr[103] = 0x0105;
721 e3c2613f bellard
    s->csr[103] = 0x0105;
722 e3c2613f bellard
    s->csr[112] = 0x0000;
723 e3c2613f bellard
    s->csr[114] = 0x0000;
724 e3c2613f bellard
    s->csr[122] = 0x0000;
725 e3c2613f bellard
    s->csr[124] = 0x0000;
726 ec607da7 bellard
727 ec607da7 bellard
    s->tx_busy = 0;
728 e3c2613f bellard
}
729 e3c2613f bellard
730 e3c2613f bellard
static void pcnet_update_irq(PCNetState *s)
731 e3c2613f bellard
{
732 e3c2613f bellard
    int isr = 0;
733 e3c2613f bellard
    s->csr[0] &= ~0x0080;
734 3b46e624 ths
735 e3c2613f bellard
#if 1
736 e3c2613f bellard
    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
737 e3c2613f bellard
        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
738 e3c2613f bellard
        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
739 e3c2613f bellard
#else
740 e3c2613f bellard
    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
741 e3c2613f bellard
        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
742 e3c2613f bellard
        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
743 e3c2613f bellard
        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
744 e3c2613f bellard
        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
745 e3c2613f bellard
        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
746 e3c2613f bellard
        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
747 e3c2613f bellard
        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
748 e3c2613f bellard
        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
749 e3c2613f bellard
        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
750 e3c2613f bellard
        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
751 e3c2613f bellard
        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
752 e3c2613f bellard
#endif
753 e3c2613f bellard
    {
754 3b46e624 ths
755 e3c2613f bellard
        isr = CSR_INEA(s);
756 e3c2613f bellard
        s->csr[0] |= 0x0080;
757 e3c2613f bellard
    }
758 3b46e624 ths
759 e3c2613f bellard
    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
760 e3c2613f bellard
        s->csr[4] &= ~0x0080;
761 e3c2613f bellard
        s->csr[4] |= 0x0040;
762 e3c2613f bellard
        s->csr[0] |= 0x0080;
763 e3c2613f bellard
        isr = 1;
764 e3c2613f bellard
#ifdef PCNET_DEBUG
765 e3c2613f bellard
        printf("pcnet user int\n");
766 e3c2613f bellard
#endif
767 e3c2613f bellard
    }
768 e3c2613f bellard
769 e3c2613f bellard
#if 1
770 5fafdf24 ths
    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
771 e3c2613f bellard
#else
772 e3c2613f bellard
    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
773 e3c2613f bellard
        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
774 e3c2613f bellard
#endif
775 e3c2613f bellard
    {
776 e3c2613f bellard
        isr = 1;
777 e3c2613f bellard
        s->csr[0] |= 0x0080;
778 e3c2613f bellard
    }
779 e3c2613f bellard
780 e3c2613f bellard
    if (isr != s->isr) {
781 e3c2613f bellard
#ifdef PCNET_DEBUG
782 e3c2613f bellard
        printf("pcnet: INTA=%d\n", isr);
783 e3c2613f bellard
#endif
784 e3c2613f bellard
    }
785 d537cf6c pbrook
    qemu_set_irq(s->irq, isr);
786 91cc0295 bellard
    s->isr = isr;
787 e3c2613f bellard
}
788 e3c2613f bellard
789 e3c2613f bellard
static void pcnet_init(PCNetState *s)
790 e3c2613f bellard
{
791 91cc0295 bellard
    int rlen, tlen;
792 6d2980f5 ths
    uint16_t padr[3], ladrf[4], mode;
793 91cc0295 bellard
    uint32_t rdra, tdra;
794 91cc0295 bellard
795 e3c2613f bellard
#ifdef PCNET_DEBUG
796 e3c2613f bellard
    printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
797 e3c2613f bellard
#endif
798 3b46e624 ths
799 e3c2613f bellard
    if (BCR_SSIZE32(s)) {
800 e3c2613f bellard
        struct pcnet_initblk32 initblk;
801 91cc0295 bellard
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
802 9b94dc32 bellard
                (uint8_t *)&initblk, sizeof(initblk), 0);
803 6d2980f5 ths
        mode = le16_to_cpu(initblk.mode);
804 91cc0295 bellard
        rlen = initblk.rlen >> 4;
805 91cc0295 bellard
        tlen = initblk.tlen >> 4;
806 6d2980f5 ths
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
807 6d2980f5 ths
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
808 6d2980f5 ths
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
809 6d2980f5 ths
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
810 6d2980f5 ths
        padr[0] = le16_to_cpu(initblk.padr[0]);
811 6d2980f5 ths
        padr[1] = le16_to_cpu(initblk.padr[1]);
812 6d2980f5 ths
        padr[2] = le16_to_cpu(initblk.padr[2]);
813 9b94dc32 bellard
        rdra = le32_to_cpu(initblk.rdra);
814 9b94dc32 bellard
        tdra = le32_to_cpu(initblk.tdra);
815 e3c2613f bellard
    } else {
816 e3c2613f bellard
        struct pcnet_initblk16 initblk;
817 91cc0295 bellard
        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
818 9b94dc32 bellard
                (uint8_t *)&initblk, sizeof(initblk), 0);
819 6d2980f5 ths
        mode = le16_to_cpu(initblk.mode);
820 6d2980f5 ths
        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
821 6d2980f5 ths
        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
822 6d2980f5 ths
        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
823 6d2980f5 ths
        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
824 6d2980f5 ths
        padr[0] = le16_to_cpu(initblk.padr[0]);
825 6d2980f5 ths
        padr[1] = le16_to_cpu(initblk.padr[1]);
826 6d2980f5 ths
        padr[2] = le16_to_cpu(initblk.padr[2]);
827 9b94dc32 bellard
        rdra = le32_to_cpu(initblk.rdra);
828 9b94dc32 bellard
        tdra = le32_to_cpu(initblk.tdra);
829 91cc0295 bellard
        rlen = rdra >> 29;
830 91cc0295 bellard
        tlen = tdra >> 29;
831 91cc0295 bellard
        rdra &= 0x00ffffff;
832 91cc0295 bellard
        tdra &= 0x00ffffff;
833 91cc0295 bellard
    }
834 6d2980f5 ths
835 91cc0295 bellard
#if defined(PCNET_DEBUG)
836 6d2980f5 ths
    printf("rlen=%d tlen=%d\n", rlen, tlen);
837 e3c2613f bellard
#endif
838 6d2980f5 ths
839 91cc0295 bellard
    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
840 91cc0295 bellard
    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
841 91cc0295 bellard
    s->csr[ 6] = (tlen << 12) | (rlen << 8);
842 6d2980f5 ths
    s->csr[15] = mode;
843 6d2980f5 ths
    s->csr[ 8] = ladrf[0];
844 6d2980f5 ths
    s->csr[ 9] = ladrf[1];
845 6d2980f5 ths
    s->csr[10] = ladrf[2];
846 6d2980f5 ths
    s->csr[11] = ladrf[3];
847 6d2980f5 ths
    s->csr[12] = padr[0];
848 6d2980f5 ths
    s->csr[13] = padr[1];
849 6d2980f5 ths
    s->csr[14] = padr[2];
850 91cc0295 bellard
    s->rdra = PHYSADDR(s, rdra);
851 91cc0295 bellard
    s->tdra = PHYSADDR(s, tdra);
852 e3c2613f bellard
853 e3c2613f bellard
    CSR_RCVRC(s) = CSR_RCVRL(s);
854 e3c2613f bellard
    CSR_XMTRC(s) = CSR_XMTRL(s);
855 e3c2613f bellard
856 e3c2613f bellard
#ifdef PCNET_DEBUG
857 5fafdf24 ths
    printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
858 e3c2613f bellard
        BCR_SSIZE32(s),
859 e3c2613f bellard
        s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
860 e3c2613f bellard
#endif
861 e3c2613f bellard
862 3b46e624 ths
    s->csr[0] |= 0x0101;
863 e3c2613f bellard
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
864 e3c2613f bellard
}
865 e3c2613f bellard
866 e3c2613f bellard
static void pcnet_start(PCNetState *s)
867 e3c2613f bellard
{
868 e3c2613f bellard
#ifdef PCNET_DEBUG
869 e3c2613f bellard
    printf("pcnet_start\n");
870 e3c2613f bellard
#endif
871 e3c2613f bellard
872 e3c2613f bellard
    if (!CSR_DTX(s))
873 e3c2613f bellard
        s->csr[0] |= 0x0010;    /* set TXON */
874 3b46e624 ths
875 e3c2613f bellard
    if (!CSR_DRX(s))
876 e3c2613f bellard
        s->csr[0] |= 0x0020;    /* set RXON */
877 e3c2613f bellard
878 e3c2613f bellard
    s->csr[0] &= ~0x0004;       /* clear STOP bit */
879 e3c2613f bellard
    s->csr[0] |= 0x0002;
880 ad323081 Jan Kiszka
    pcnet_poll_timer(s);
881 e3c2613f bellard
}
882 e3c2613f bellard
883 e3c2613f bellard
static void pcnet_stop(PCNetState *s)
884 e3c2613f bellard
{
885 e3c2613f bellard
#ifdef PCNET_DEBUG
886 e3c2613f bellard
    printf("pcnet_stop\n");
887 e3c2613f bellard
#endif
888 6655124d Jan Kiszka
    s->csr[0] &= ~0xffeb;
889 e3c2613f bellard
    s->csr[0] |= 0x0014;
890 e3c2613f bellard
    s->csr[4] &= ~0x02c2;
891 e3c2613f bellard
    s->csr[5] &= ~0x0011;
892 e3c2613f bellard
    pcnet_poll_timer(s);
893 e3c2613f bellard
}
894 e3c2613f bellard
895 e3c2613f bellard
static void pcnet_rdte_poll(PCNetState *s)
896 e3c2613f bellard
{
897 e3c2613f bellard
    s->csr[28] = s->csr[29] = 0;
898 e3c2613f bellard
    if (s->rdra) {
899 e3c2613f bellard
        int bad = 0;
900 e3c2613f bellard
#if 1
901 a8170e5e Avi Kivity
        hwaddr crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
902 a8170e5e Avi Kivity
        hwaddr nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
903 a8170e5e Avi Kivity
        hwaddr nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
904 e3c2613f bellard
#else
905 a8170e5e Avi Kivity
        hwaddr crda = s->rdra +
906 e3c2613f bellard
            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
907 e3c2613f bellard
            (BCR_SWSTYLE(s) ? 16 : 8 );
908 e3c2613f bellard
        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
909 a8170e5e Avi Kivity
        hwaddr nrda = s->rdra +
910 e3c2613f bellard
            (CSR_RCVRL(s) - nrdc) *
911 e3c2613f bellard
            (BCR_SWSTYLE(s) ? 16 : 8 );
912 e3c2613f bellard
        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
913 a8170e5e Avi Kivity
        hwaddr nnrd = s->rdra +
914 e3c2613f bellard
            (CSR_RCVRL(s) - nnrc) *
915 e3c2613f bellard
            (BCR_SWSTYLE(s) ? 16 : 8 );
916 e3c2613f bellard
#endif
917 e3c2613f bellard
918 f1afe02a aurel32
        CHECK_RMD(crda, bad);
919 e3c2613f bellard
        if (!bad) {
920 f1afe02a aurel32
            CHECK_RMD(nrda, bad);
921 e3c2613f bellard
            if (bad || (nrda == crda)) nrda = 0;
922 f1afe02a aurel32
            CHECK_RMD(nnrd, bad);
923 e3c2613f bellard
            if (bad || (nnrd == crda)) nnrd = 0;
924 e3c2613f bellard
925 e3c2613f bellard
            s->csr[28] = crda & 0xffff;
926 e3c2613f bellard
            s->csr[29] = crda >> 16;
927 e3c2613f bellard
            s->csr[26] = nrda & 0xffff;
928 e3c2613f bellard
            s->csr[27] = nrda >> 16;
929 e3c2613f bellard
            s->csr[36] = nnrd & 0xffff;
930 e3c2613f bellard
            s->csr[37] = nnrd >> 16;
931 e3c2613f bellard
#ifdef PCNET_DEBUG
932 e3c2613f bellard
            if (bad) {
933 cb3df91a blueswir1
                printf("pcnet: BAD RMD RECORDS AFTER 0x" TARGET_FMT_plx "\n",
934 f1afe02a aurel32
                       crda);
935 e3c2613f bellard
            }
936 e3c2613f bellard
        } else {
937 cb3df91a blueswir1
            printf("pcnet: BAD RMD RDA=0x" TARGET_FMT_plx "\n",
938 f1afe02a aurel32
                   crda);
939 e3c2613f bellard
#endif
940 e3c2613f bellard
        }
941 e3c2613f bellard
    }
942 3b46e624 ths
943 e3c2613f bellard
    if (CSR_CRDA(s)) {
944 e3c2613f bellard
        struct pcnet_RMD rmd;
945 e3c2613f bellard
        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
946 6d2980f5 ths
        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
947 6d2980f5 ths
        CSR_CRST(s) = rmd.status;
948 e3c2613f bellard
#ifdef PCNET_DEBUG_RMD_X
949 6d2980f5 ths
        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
950 e3c2613f bellard
                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
951 6d2980f5 ths
                rmd.buf_length, rmd.status, rmd.msg_length);
952 e3c2613f bellard
        PRINT_RMD(&rmd);
953 e3c2613f bellard
#endif
954 e3c2613f bellard
    } else {
955 e3c2613f bellard
        CSR_CRBC(s) = CSR_CRST(s) = 0;
956 e3c2613f bellard
    }
957 3b46e624 ths
958 e3c2613f bellard
    if (CSR_NRDA(s)) {
959 e3c2613f bellard
        struct pcnet_RMD rmd;
960 e3c2613f bellard
        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
961 6d2980f5 ths
        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
962 6d2980f5 ths
        CSR_NRST(s) = rmd.status;
963 e3c2613f bellard
    } else {
964 e3c2613f bellard
        CSR_NRBC(s) = CSR_NRST(s) = 0;
965 e3c2613f bellard
    }
966 e3c2613f bellard
967 e3c2613f bellard
}
968 e3c2613f bellard
969 e3c2613f bellard
static int pcnet_tdte_poll(PCNetState *s)
970 e3c2613f bellard
{
971 e3c2613f bellard
    s->csr[34] = s->csr[35] = 0;
972 e3c2613f bellard
    if (s->tdra) {
973 a8170e5e Avi Kivity
        hwaddr cxda = s->tdra +
974 e3c2613f bellard
            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
975 6d2980f5 ths
            (BCR_SWSTYLE(s) ? 16 : 8);
976 e3c2613f bellard
        int bad = 0;
977 f1afe02a aurel32
        CHECK_TMD(cxda, bad);
978 e3c2613f bellard
        if (!bad) {
979 e3c2613f bellard
            if (CSR_CXDA(s) != cxda) {
980 e3c2613f bellard
                s->csr[60] = s->csr[34];
981 e3c2613f bellard
                s->csr[61] = s->csr[35];
982 e3c2613f bellard
                s->csr[62] = CSR_CXBC(s);
983 e3c2613f bellard
                s->csr[63] = CSR_CXST(s);
984 e3c2613f bellard
            }
985 e3c2613f bellard
            s->csr[34] = cxda & 0xffff;
986 e3c2613f bellard
            s->csr[35] = cxda >> 16;
987 6d2980f5 ths
#ifdef PCNET_DEBUG_X
988 f1afe02a aurel32
            printf("pcnet: BAD TMD XDA=0x%08x\n", cxda);
989 e3c2613f bellard
#endif
990 e3c2613f bellard
        }
991 e3c2613f bellard
    }
992 e3c2613f bellard
993 e3c2613f bellard
    if (CSR_CXDA(s)) {
994 e3c2613f bellard
        struct pcnet_TMD tmd;
995 e3c2613f bellard
996 3b46e624 ths
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
997 e3c2613f bellard
998 6d2980f5 ths
        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
999 6d2980f5 ths
        CSR_CXST(s) = tmd.status;
1000 e3c2613f bellard
    } else {
1001 e3c2613f bellard
        CSR_CXBC(s) = CSR_CXST(s) = 0;
1002 e3c2613f bellard
    }
1003 3b46e624 ths
1004 e3c2613f bellard
    return !!(CSR_CXST(s) & 0x8000);
1005 e3c2613f bellard
}
1006 e3c2613f bellard
1007 4e68f7a0 Stefan Hajnoczi
int pcnet_can_receive(NetClientState *nc)
1008 e3c2613f bellard
{
1009 cc1f0f45 Jason Wang
    PCNetState *s = qemu_get_nic_opaque(nc);
1010 e3c2613f bellard
    if (CSR_STOP(s) || CSR_SPND(s))
1011 e3c2613f bellard
        return 0;
1012 3b46e624 ths
1013 e3c2613f bellard
    return sizeof(s->buffer)-16;
1014 e3c2613f bellard
}
1015 e3c2613f bellard
1016 e3c2613f bellard
#define MIN_BUF_SIZE 60
1017 e3c2613f bellard
1018 4e68f7a0 Stefan Hajnoczi
ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
1019 e3c2613f bellard
{
1020 cc1f0f45 Jason Wang
    PCNetState *s = qemu_get_nic_opaque(nc);
1021 e3c2613f bellard
    int is_padr = 0, is_bcast = 0, is_ladr = 0;
1022 e3c2613f bellard
    uint8_t buf1[60];
1023 89b190a2 aurel32
    int remaining;
1024 89b190a2 aurel32
    int crc_err = 0;
1025 4f1c942b Mark McLoughlin
    int size = size_;
1026 e3c2613f bellard
1027 c1ded3dc Jan Kiszka
    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
1028 c1ded3dc Jan Kiszka
        (CSR_LOOP(s) && !s->looptest)) {
1029 4f1c942b Mark McLoughlin
        return -1;
1030 c1ded3dc Jan Kiszka
    }
1031 e3c2613f bellard
#ifdef PCNET_DEBUG
1032 e3c2613f bellard
    printf("pcnet_receive size=%d\n", size);
1033 e3c2613f bellard
#endif
1034 e3c2613f bellard
1035 e3c2613f bellard
    /* if too small buffer, then expand it */
1036 e3c2613f bellard
    if (size < MIN_BUF_SIZE) {
1037 e3c2613f bellard
        memcpy(buf1, buf, size);
1038 e3c2613f bellard
        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1039 e3c2613f bellard
        buf = buf1;
1040 e3c2613f bellard
        size = MIN_BUF_SIZE;
1041 e3c2613f bellard
    }
1042 e3c2613f bellard
1043 5fafdf24 ths
    if (CSR_PROM(s)
1044 5fafdf24 ths
        || (is_padr=padr_match(s, buf, size))
1045 e3c2613f bellard
        || (is_bcast=padr_bcast(s, buf, size))
1046 e3c2613f bellard
        || (is_ladr=ladr_match(s, buf, size))) {
1047 e3c2613f bellard
1048 e3c2613f bellard
        pcnet_rdte_poll(s);
1049 e3c2613f bellard
1050 e3c2613f bellard
        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1051 e3c2613f bellard
            struct pcnet_RMD rmd;
1052 e3c2613f bellard
            int rcvrc = CSR_RCVRC(s)-1,i;
1053 a8170e5e Avi Kivity
            hwaddr nrda;
1054 e3c2613f bellard
            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1055 e3c2613f bellard
                if (rcvrc <= 1)
1056 e3c2613f bellard
                    rcvrc = CSR_RCVRL(s);
1057 e3c2613f bellard
                nrda = s->rdra +
1058 e3c2613f bellard
                    (CSR_RCVRL(s) - rcvrc) *
1059 e3c2613f bellard
                    (BCR_SWSTYLE(s) ? 16 : 8 );
1060 f1afe02a aurel32
                RMDLOAD(&rmd, nrda);
1061 6d2980f5 ths
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1062 e3c2613f bellard
#ifdef PCNET_DEBUG_RMD
1063 5fafdf24 ths
                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1064 e3c2613f bellard
                                rcvrc, CSR_RCVRC(s));
1065 e3c2613f bellard
#endif
1066 e3c2613f bellard
                    CSR_RCVRC(s) = rcvrc;
1067 e3c2613f bellard
                    pcnet_rdte_poll(s);
1068 e3c2613f bellard
                    break;
1069 e3c2613f bellard
                }
1070 e3c2613f bellard
            }
1071 e3c2613f bellard
        }
1072 e3c2613f bellard
1073 e3c2613f bellard
        if (!(CSR_CRST(s) & 0x8000)) {
1074 e3c2613f bellard
#ifdef PCNET_DEBUG_RMD
1075 e3c2613f bellard
            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1076 e3c2613f bellard
#endif
1077 e3c2613f bellard
            s->csr[0] |= 0x1000; /* Set MISS flag */
1078 e3c2613f bellard
            CSR_MISSC(s)++;
1079 e3c2613f bellard
        } else {
1080 89b190a2 aurel32
            uint8_t *src = s->buffer;
1081 a8170e5e Avi Kivity
            hwaddr crda = CSR_CRDA(s);
1082 e3c2613f bellard
            struct pcnet_RMD rmd;
1083 e3c2613f bellard
            int pktcount = 0;
1084 e3c2613f bellard
1085 89b190a2 aurel32
            if (!s->looptest) {
1086 89b190a2 aurel32
                memcpy(src, buf, size);
1087 89b190a2 aurel32
                /* no need to compute the CRC */
1088 89b190a2 aurel32
                src[size] = 0;
1089 89b190a2 aurel32
                src[size + 1] = 0;
1090 89b190a2 aurel32
                src[size + 2] = 0;
1091 89b190a2 aurel32
                src[size + 3] = 0;
1092 89b190a2 aurel32
                size += 4;
1093 89b190a2 aurel32
            } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1094 89b190a2 aurel32
                       !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1095 e3c2613f bellard
                uint32_t fcs = ~0;
1096 e3c2613f bellard
                uint8_t *p = src;
1097 e3c2613f bellard
1098 89b190a2 aurel32
                while (p != &src[size])
1099 89b190a2 aurel32
                    CRC(fcs, *p++);
1100 89b190a2 aurel32
                *(uint32_t *)p = htonl(fcs);
1101 89b190a2 aurel32
                size += 4;
1102 89b190a2 aurel32
            } else {
1103 89b190a2 aurel32
                uint32_t fcs = ~0;
1104 89b190a2 aurel32
                uint8_t *p = src;
1105 3b46e624 ths
1106 89b190a2 aurel32
                while (p != &src[size-4])
1107 e3c2613f bellard
                    CRC(fcs, *p++);
1108 89b190a2 aurel32
                crc_err = (*(uint32_t *)p != htonl(fcs));
1109 89b190a2 aurel32
            }
1110 e3c2613f bellard
1111 e3c2613f bellard
#ifdef PCNET_DEBUG_MATCH
1112 e3c2613f bellard
            PRINT_PKTHDR(buf);
1113 e3c2613f bellard
#endif
1114 e3c2613f bellard
1115 e3c2613f bellard
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1116 e3c2613f bellard
            /*if (!CSR_LAPPEN(s))*/
1117 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, STP, 1);
1118 e3c2613f bellard
1119 e3c2613f bellard
#define PCNET_RECV_STORE() do {                                 \
1120 89b190a2 aurel32
    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1121 a8170e5e Avi Kivity
    hwaddr rbadr = PHYSADDR(s, rmd.rbadr);          \
1122 6d2980f5 ths
    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1123 89b190a2 aurel32
    src += count; remaining -= count;                           \
1124 6d2980f5 ths
    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1125 e3c2613f bellard
    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1126 e3c2613f bellard
    pktcount++;                                                 \
1127 e3c2613f bellard
} while (0)
1128 e3c2613f bellard
1129 89b190a2 aurel32
            remaining = size;
1130 e3c2613f bellard
            PCNET_RECV_STORE();
1131 89b190a2 aurel32
            if ((remaining > 0) && CSR_NRDA(s)) {
1132 a8170e5e Avi Kivity
                hwaddr nrda = CSR_NRDA(s);
1133 89b190a2 aurel32
#ifdef PCNET_DEBUG_RMD
1134 89b190a2 aurel32
                PRINT_RMD(&rmd);
1135 89b190a2 aurel32
#endif
1136 e3c2613f bellard
                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1137 6d2980f5 ths
                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1138 e3c2613f bellard
                    crda = nrda;
1139 e3c2613f bellard
                    PCNET_RECV_STORE();
1140 89b190a2 aurel32
#ifdef PCNET_DEBUG_RMD
1141 89b190a2 aurel32
                    PRINT_RMD(&rmd);
1142 89b190a2 aurel32
#endif
1143 89b190a2 aurel32
                    if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1144 e3c2613f bellard
                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1145 6d2980f5 ths
                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
1146 e3c2613f bellard
                            crda = nrda;
1147 e3c2613f bellard
                            PCNET_RECV_STORE();
1148 e3c2613f bellard
                        }
1149 e3c2613f bellard
                    }
1150 3b46e624 ths
                }
1151 e3c2613f bellard
            }
1152 e3c2613f bellard
1153 e3c2613f bellard
#undef PCNET_RECV_STORE
1154 e3c2613f bellard
1155 e3c2613f bellard
            RMDLOAD(&rmd, PHYSADDR(s,crda));
1156 89b190a2 aurel32
            if (remaining == 0) {
1157 89b190a2 aurel32
                SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1158 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, ENP, 1);
1159 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1160 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1161 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1162 89b190a2 aurel32
                if (crc_err) {
1163 89b190a2 aurel32
                    SET_FIELD(&rmd.status, RMDS, CRC, 1);
1164 89b190a2 aurel32
                    SET_FIELD(&rmd.status, RMDS, ERR, 1);
1165 89b190a2 aurel32
                }
1166 e3c2613f bellard
            } else {
1167 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1168 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1169 6d2980f5 ths
                SET_FIELD(&rmd.status, RMDS, ERR, 1);
1170 e3c2613f bellard
            }
1171 e3c2613f bellard
            RMDSTORE(&rmd, PHYSADDR(s,crda));
1172 e3c2613f bellard
            s->csr[0] |= 0x0400;
1173 e3c2613f bellard
1174 e3c2613f bellard
#ifdef PCNET_DEBUG
1175 5fafdf24 ths
            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1176 e3c2613f bellard
                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1177 e3c2613f bellard
#endif
1178 e3c2613f bellard
#ifdef PCNET_DEBUG_RMD
1179 e3c2613f bellard
            PRINT_RMD(&rmd);
1180 3b46e624 ths
#endif
1181 e3c2613f bellard
1182 e3c2613f bellard
            while (pktcount--) {
1183 e3c2613f bellard
                if (CSR_RCVRC(s) <= 1)
1184 e3c2613f bellard
                    CSR_RCVRC(s) = CSR_RCVRL(s);
1185 e3c2613f bellard
                else
1186 3b46e624 ths
                    CSR_RCVRC(s)--;
1187 e3c2613f bellard
            }
1188 3b46e624 ths
1189 e3c2613f bellard
            pcnet_rdte_poll(s);
1190 e3c2613f bellard
1191 3b46e624 ths
        }
1192 e3c2613f bellard
    }
1193 e3c2613f bellard
1194 e3c2613f bellard
    pcnet_poll(s);
1195 3b46e624 ths
    pcnet_update_irq(s);
1196 4f1c942b Mark McLoughlin
1197 4f1c942b Mark McLoughlin
    return size_;
1198 e3c2613f bellard
}
1199 e3c2613f bellard
1200 4e68f7a0 Stefan Hajnoczi
void pcnet_set_link_status(NetClientState *nc)
1201 e1c2008a Jan Kiszka
{
1202 cc1f0f45 Jason Wang
    PCNetState *d = qemu_get_nic_opaque(nc);
1203 e1c2008a Jan Kiszka
1204 e1c2008a Jan Kiszka
    d->lnkst = nc->link_down ? 0 : 0x40;
1205 e1c2008a Jan Kiszka
}
1206 e1c2008a Jan Kiszka
1207 e3c2613f bellard
static void pcnet_transmit(PCNetState *s)
1208 e3c2613f bellard
{
1209 a8170e5e Avi Kivity
    hwaddr xmit_cxda = 0;
1210 e3c2613f bellard
    int count = CSR_XMTRL(s)-1;
1211 89b190a2 aurel32
    int add_crc = 0;
1212 89b190a2 aurel32
1213 e3c2613f bellard
    s->xmit_pos = -1;
1214 3b46e624 ths
1215 e3c2613f bellard
    if (!CSR_TXON(s)) {
1216 e3c2613f bellard
        s->csr[0] &= ~0x0008;
1217 e3c2613f bellard
        return;
1218 e3c2613f bellard
    }
1219 ec607da7 bellard
1220 ec607da7 bellard
    s->tx_busy = 1;
1221 ec607da7 bellard
1222 e3c2613f bellard
    txagain:
1223 e3c2613f bellard
    if (pcnet_tdte_poll(s)) {
1224 e3c2613f bellard
        struct pcnet_TMD tmd;
1225 e3c2613f bellard
1226 6d2980f5 ths
        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1227 e3c2613f bellard
1228 e3c2613f bellard
#ifdef PCNET_DEBUG_TMD
1229 e3c2613f bellard
        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1230 e3c2613f bellard
        PRINT_TMD(&tmd);
1231 e3c2613f bellard
#endif
1232 6d2980f5 ths
        if (GET_FIELD(tmd.status, TMDS, STP)) {
1233 6d2980f5 ths
            s->xmit_pos = 0;
1234 e3c2613f bellard
            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1235 89b190a2 aurel32
            if (BCR_SWSTYLE(s) != 1)
1236 89b190a2 aurel32
                add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1237 e3c2613f bellard
        }
1238 ef45c914 Jan Kiszka
        if (s->lnkst == 0 &&
1239 ef45c914 Jan Kiszka
            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
1240 ef45c914 Jan Kiszka
            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
1241 ef45c914 Jan Kiszka
            SET_FIELD(&tmd.status, TMDS, ERR, 1);
1242 ef45c914 Jan Kiszka
            SET_FIELD(&tmd.status, TMDS, OWN, 0);
1243 ef45c914 Jan Kiszka
            s->csr[0] |= 0xa000; /* ERR | CERR */
1244 ef45c914 Jan Kiszka
            s->xmit_pos = -1;
1245 ef45c914 Jan Kiszka
            goto txdone;
1246 ef45c914 Jan Kiszka
        }
1247 9bd0d294 blueswir1
        if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1248 9bd0d294 blueswir1
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1249 9bd0d294 blueswir1
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1250 9bd0d294 blueswir1
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1251 9bd0d294 blueswir1
            s->xmit_pos += bcnt;
1252 9bd0d294 blueswir1
        } else if (s->xmit_pos >= 0) {
1253 6d2980f5 ths
            int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1254 6d2980f5 ths
            s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1255 6d2980f5 ths
                             s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1256 6d2980f5 ths
            s->xmit_pos += bcnt;
1257 e3c2613f bellard
#ifdef PCNET_DEBUG
1258 e3c2613f bellard
            printf("pcnet_transmit size=%d\n", s->xmit_pos);
1259 6d2980f5 ths
#endif
1260 89b190a2 aurel32
            if (CSR_LOOP(s)) {
1261 89b190a2 aurel32
                if (BCR_SWSTYLE(s) == 1)
1262 89b190a2 aurel32
                    add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1263 89b190a2 aurel32
                s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1264 b356f76d Jason Wang
                pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
1265 89b190a2 aurel32
                s->looptest = 0;
1266 89b190a2 aurel32
            } else
1267 1fa51482 Mark McLoughlin
                if (s->nic)
1268 b356f76d Jason Wang
                    qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
1269 b356f76d Jason Wang
                                     s->xmit_pos);
1270 e3c2613f bellard
1271 e3c2613f bellard
            s->csr[0] &= ~0x0008;   /* clear TDMD */
1272 e3c2613f bellard
            s->csr[4] |= 0x0004;    /* set TXSTRT */
1273 e3c2613f bellard
            s->xmit_pos = -1;
1274 e3c2613f bellard
        }
1275 e3c2613f bellard
1276 ef45c914 Jan Kiszka
    txdone:
1277 6d2980f5 ths
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1278 e3c2613f bellard
        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1279 6d2980f5 ths
        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1280 e3c2613f bellard
            s->csr[0] |= 0x0200;    /* set TINT */
1281 e3c2613f bellard
1282 e3c2613f bellard
        if (CSR_XMTRC(s)<=1)
1283 e3c2613f bellard
            CSR_XMTRC(s) = CSR_XMTRL(s);
1284 e3c2613f bellard
        else
1285 e3c2613f bellard
            CSR_XMTRC(s)--;
1286 e3c2613f bellard
        if (count--)
1287 e3c2613f bellard
            goto txagain;
1288 e3c2613f bellard
1289 5fafdf24 ths
    } else
1290 e3c2613f bellard
    if (s->xmit_pos >= 0) {
1291 e3c2613f bellard
        struct pcnet_TMD tmd;
1292 f1afe02a aurel32
        TMDLOAD(&tmd, xmit_cxda);
1293 6d2980f5 ths
        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1294 6d2980f5 ths
        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1295 6d2980f5 ths
        SET_FIELD(&tmd.status, TMDS, ERR, 1);
1296 6d2980f5 ths
        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1297 f1afe02a aurel32
        TMDSTORE(&tmd, xmit_cxda);
1298 e3c2613f bellard
        s->csr[0] |= 0x0200;    /* set TINT */
1299 e3c2613f bellard
        if (!CSR_DXSUFLO(s)) {
1300 e3c2613f bellard
            s->csr[0] &= ~0x0010;
1301 e3c2613f bellard
        } else
1302 e3c2613f bellard
        if (count--)
1303 e3c2613f bellard
          goto txagain;
1304 e3c2613f bellard
    }
1305 ec607da7 bellard
1306 ec607da7 bellard
    s->tx_busy = 0;
1307 e3c2613f bellard
}
1308 e3c2613f bellard
1309 e3c2613f bellard
static void pcnet_poll(PCNetState *s)
1310 e3c2613f bellard
{
1311 e3c2613f bellard
    if (CSR_RXON(s)) {
1312 e3c2613f bellard
        pcnet_rdte_poll(s);
1313 e3c2613f bellard
    }
1314 e3c2613f bellard
1315 5fafdf24 ths
    if (CSR_TDMD(s) ||
1316 e3c2613f bellard
        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1317 ec607da7 bellard
    {
1318 ec607da7 bellard
        /* prevent recursion */
1319 ec607da7 bellard
        if (s->tx_busy)
1320 ec607da7 bellard
            return;
1321 ec607da7 bellard
1322 e3c2613f bellard
        pcnet_transmit(s);
1323 ec607da7 bellard
    }
1324 e3c2613f bellard
}
1325 e3c2613f bellard
1326 e3c2613f bellard
static void pcnet_poll_timer(void *opaque)
1327 e3c2613f bellard
{
1328 e3c2613f bellard
    PCNetState *s = opaque;
1329 e3c2613f bellard
1330 e3c2613f bellard
    qemu_del_timer(s->poll_timer);
1331 e3c2613f bellard
1332 e3c2613f bellard
    if (CSR_TDMD(s)) {
1333 e3c2613f bellard
        pcnet_transmit(s);
1334 e3c2613f bellard
    }
1335 e3c2613f bellard
1336 3b46e624 ths
    pcnet_update_irq(s);
1337 e3c2613f bellard
1338 e3c2613f bellard
    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1339 74475455 Paolo Bonzini
        uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
1340 e3c2613f bellard
        if (!s->timer || !now)
1341 e3c2613f bellard
            s->timer = now;
1342 e3c2613f bellard
        else {
1343 e3c2613f bellard
            uint64_t t = now - s->timer + CSR_POLL(s);
1344 e3c2613f bellard
            if (t > 0xffffLL) {
1345 e3c2613f bellard
                pcnet_poll(s);
1346 e3c2613f bellard
                CSR_POLL(s) = CSR_PINT(s);
1347 e3c2613f bellard
            } else
1348 e3c2613f bellard
                CSR_POLL(s) = t;
1349 e3c2613f bellard
        }
1350 5fafdf24 ths
        qemu_mod_timer(s->poll_timer,
1351 74475455 Paolo Bonzini
            pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
1352 e3c2613f bellard
    }
1353 e3c2613f bellard
}
1354 e3c2613f bellard
1355 e3c2613f bellard
1356 e3c2613f bellard
static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1357 e3c2613f bellard
{
1358 e3c2613f bellard
    uint16_t val = new_value;
1359 e3c2613f bellard
#ifdef PCNET_DEBUG_CSR
1360 e3c2613f bellard
    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1361 e3c2613f bellard
#endif
1362 e3c2613f bellard
    switch (rap) {
1363 e3c2613f bellard
    case 0:
1364 e3c2613f bellard
        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1365 e3c2613f bellard
1366 e3c2613f bellard
        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1367 e3c2613f bellard
1368 e3c2613f bellard
        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1369 e3c2613f bellard
1370 e3c2613f bellard
        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1371 e3c2613f bellard
        if ((val&7) == 7)
1372 e3c2613f bellard
          val &= ~3;
1373 e3c2613f bellard
1374 e3c2613f bellard
        if (!CSR_STOP(s) && (val & 4))
1375 e3c2613f bellard
            pcnet_stop(s);
1376 e3c2613f bellard
1377 e3c2613f bellard
        if (!CSR_INIT(s) && (val & 1))
1378 e3c2613f bellard
            pcnet_init(s);
1379 e3c2613f bellard
1380 e3c2613f bellard
        if (!CSR_STRT(s) && (val & 2))
1381 e3c2613f bellard
            pcnet_start(s);
1382 e3c2613f bellard
1383 5fafdf24 ths
        if (CSR_TDMD(s))
1384 e3c2613f bellard
            pcnet_transmit(s);
1385 e3c2613f bellard
1386 e3c2613f bellard
        return;
1387 e3c2613f bellard
    case 1:
1388 e3c2613f bellard
    case 2:
1389 e3c2613f bellard
    case 8:
1390 e3c2613f bellard
    case 9:
1391 e3c2613f bellard
    case 10:
1392 e3c2613f bellard
    case 11:
1393 e3c2613f bellard
    case 12:
1394 e3c2613f bellard
    case 13:
1395 e3c2613f bellard
    case 14:
1396 e3c2613f bellard
    case 15:
1397 e3c2613f bellard
    case 18: /* CRBAL */
1398 e3c2613f bellard
    case 19: /* CRBAU */
1399 e3c2613f bellard
    case 20: /* CXBAL */
1400 e3c2613f bellard
    case 21: /* CXBAU */
1401 e3c2613f bellard
    case 22: /* NRBAU */
1402 e3c2613f bellard
    case 23: /* NRBAU */
1403 e3c2613f bellard
    case 24:
1404 e3c2613f bellard
    case 25:
1405 e3c2613f bellard
    case 26:
1406 e3c2613f bellard
    case 27:
1407 e3c2613f bellard
    case 28:
1408 e3c2613f bellard
    case 29:
1409 e3c2613f bellard
    case 30:
1410 e3c2613f bellard
    case 31:
1411 e3c2613f bellard
    case 32:
1412 e3c2613f bellard
    case 33:
1413 e3c2613f bellard
    case 34:
1414 e3c2613f bellard
    case 35:
1415 e3c2613f bellard
    case 36:
1416 e3c2613f bellard
    case 37:
1417 e3c2613f bellard
    case 38:
1418 e3c2613f bellard
    case 39:
1419 e3c2613f bellard
    case 40: /* CRBC */
1420 e3c2613f bellard
    case 41:
1421 e3c2613f bellard
    case 42: /* CXBC */
1422 e3c2613f bellard
    case 43:
1423 e3c2613f bellard
    case 44:
1424 e3c2613f bellard
    case 45:
1425 e3c2613f bellard
    case 46: /* POLL */
1426 e3c2613f bellard
    case 47: /* POLLINT */
1427 e3c2613f bellard
    case 72:
1428 e3c2613f bellard
    case 74:
1429 e3c2613f bellard
    case 76: /* RCVRL */
1430 e3c2613f bellard
    case 78: /* XMTRL */
1431 e3c2613f bellard
    case 112:
1432 e3c2613f bellard
       if (CSR_STOP(s) || CSR_SPND(s))
1433 e3c2613f bellard
           break;
1434 e3c2613f bellard
       return;
1435 e3c2613f bellard
    case 3:
1436 e3c2613f bellard
        break;
1437 e3c2613f bellard
    case 4:
1438 5fafdf24 ths
        s->csr[4] &= ~(val & 0x026a);
1439 e3c2613f bellard
        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1440 e3c2613f bellard
        break;
1441 e3c2613f bellard
    case 5:
1442 5fafdf24 ths
        s->csr[5] &= ~(val & 0x0a90);
1443 e3c2613f bellard
        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1444 e3c2613f bellard
        break;
1445 e3c2613f bellard
    case 16:
1446 e3c2613f bellard
        pcnet_csr_writew(s,1,val);
1447 e3c2613f bellard
        return;
1448 e3c2613f bellard
    case 17:
1449 e3c2613f bellard
        pcnet_csr_writew(s,2,val);
1450 e3c2613f bellard
        return;
1451 e3c2613f bellard
    case 58:
1452 e3c2613f bellard
        pcnet_bcr_writew(s,BCR_SWS,val);
1453 e3c2613f bellard
        break;
1454 e3c2613f bellard
    default:
1455 e3c2613f bellard
        return;
1456 e3c2613f bellard
    }
1457 e3c2613f bellard
    s->csr[rap] = val;
1458 e3c2613f bellard
}
1459 e3c2613f bellard
1460 e3c2613f bellard
static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1461 e3c2613f bellard
{
1462 e3c2613f bellard
    uint32_t val;
1463 e3c2613f bellard
    switch (rap) {
1464 e3c2613f bellard
    case 0:
1465 e3c2613f bellard
        pcnet_update_irq(s);
1466 e3c2613f bellard
        val = s->csr[0];
1467 e3c2613f bellard
        val |= (val & 0x7800) ? 0x8000 : 0;
1468 e3c2613f bellard
        break;
1469 e3c2613f bellard
    case 16:
1470 e3c2613f bellard
        return pcnet_csr_readw(s,1);
1471 e3c2613f bellard
    case 17:
1472 e3c2613f bellard
        return pcnet_csr_readw(s,2);
1473 e3c2613f bellard
    case 58:
1474 e3c2613f bellard
        return pcnet_bcr_readw(s,BCR_SWS);
1475 e3c2613f bellard
    case 88:
1476 e3c2613f bellard
        val = s->csr[89];
1477 e3c2613f bellard
        val <<= 16;
1478 e3c2613f bellard
        val |= s->csr[88];
1479 e3c2613f bellard
        break;
1480 e3c2613f bellard
    default:
1481 e3c2613f bellard
        val = s->csr[rap];
1482 e3c2613f bellard
    }
1483 e3c2613f bellard
#ifdef PCNET_DEBUG_CSR
1484 e3c2613f bellard
    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1485 e3c2613f bellard
#endif
1486 e3c2613f bellard
    return val;
1487 e3c2613f bellard
}
1488 e3c2613f bellard
1489 e3c2613f bellard
static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1490 e3c2613f bellard
{
1491 e3c2613f bellard
    rap &= 127;
1492 e3c2613f bellard
#ifdef PCNET_DEBUG_BCR
1493 e3c2613f bellard
    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1494 e3c2613f bellard
#endif
1495 e3c2613f bellard
    switch (rap) {
1496 e3c2613f bellard
    case BCR_SWS:
1497 e3c2613f bellard
        if (!(CSR_STOP(s) || CSR_SPND(s)))
1498 e3c2613f bellard
            return;
1499 e3c2613f bellard
        val &= ~0x0300;
1500 e3c2613f bellard
        switch (val & 0x00ff) {
1501 e3c2613f bellard
        case 0:
1502 e3c2613f bellard
            val |= 0x0200;
1503 e3c2613f bellard
            break;
1504 e3c2613f bellard
        case 1:
1505 e3c2613f bellard
            val |= 0x0100;
1506 e3c2613f bellard
            break;
1507 e3c2613f bellard
        case 2:
1508 e3c2613f bellard
        case 3:
1509 e3c2613f bellard
            val |= 0x0300;
1510 e3c2613f bellard
            break;
1511 e3c2613f bellard
        default:
1512 e3c2613f bellard
            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1513 e3c2613f bellard
            val = 0x0200;
1514 e3c2613f bellard
            break;
1515 e3c2613f bellard
        }
1516 e3c2613f bellard
#ifdef PCNET_DEBUG
1517 e3c2613f bellard
       printf("BCR_SWS=0x%04x\n", val);
1518 e3c2613f bellard
#endif
1519 0b0404bf Stefan Weil
        /* fall through */
1520 e3c2613f bellard
    case BCR_LNKST:
1521 e3c2613f bellard
    case BCR_LED1:
1522 e3c2613f bellard
    case BCR_LED2:
1523 e3c2613f bellard
    case BCR_LED3:
1524 e3c2613f bellard
    case BCR_MC:
1525 e3c2613f bellard
    case BCR_FDC:
1526 e3c2613f bellard
    case BCR_BSBC:
1527 e3c2613f bellard
    case BCR_EECAS:
1528 e3c2613f bellard
    case BCR_PLAT:
1529 e3c2613f bellard
        s->bcr[rap] = val;
1530 e3c2613f bellard
        break;
1531 e3c2613f bellard
    default:
1532 e3c2613f bellard
        break;
1533 e3c2613f bellard
    }
1534 e3c2613f bellard
}
1535 e3c2613f bellard
1536 a4c75a21 Paul Brook
uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1537 e3c2613f bellard
{
1538 e3c2613f bellard
    uint32_t val;
1539 e3c2613f bellard
    rap &= 127;
1540 e3c2613f bellard
    switch (rap) {
1541 e3c2613f bellard
    case BCR_LNKST:
1542 e3c2613f bellard
    case BCR_LED1:
1543 e3c2613f bellard
    case BCR_LED2:
1544 e3c2613f bellard
    case BCR_LED3:
1545 e3c2613f bellard
        val = s->bcr[rap] & ~0x8000;
1546 e3c2613f bellard
        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1547 e3c2613f bellard
        break;
1548 e3c2613f bellard
    default:
1549 e3c2613f bellard
        val = rap < 32 ? s->bcr[rap] : 0;
1550 e3c2613f bellard
        break;
1551 e3c2613f bellard
    }
1552 e3c2613f bellard
#ifdef PCNET_DEBUG_BCR
1553 e3c2613f bellard
    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1554 e3c2613f bellard
#endif
1555 e3c2613f bellard
    return val;
1556 e3c2613f bellard
}
1557 e3c2613f bellard
1558 94e1a912 Gerd Hoffmann
void pcnet_h_reset(void *opaque)
1559 e3c2613f bellard
{
1560 91cc0295 bellard
    PCNetState *s = opaque;
1561 e3c2613f bellard
1562 e3c2613f bellard
    s->bcr[BCR_MSRDA] = 0x0005;
1563 e3c2613f bellard
    s->bcr[BCR_MSWRA] = 0x0005;
1564 e3c2613f bellard
    s->bcr[BCR_MC   ] = 0x0002;
1565 e3c2613f bellard
    s->bcr[BCR_LNKST] = 0x00c0;
1566 e3c2613f bellard
    s->bcr[BCR_LED1 ] = 0x0084;
1567 e3c2613f bellard
    s->bcr[BCR_LED2 ] = 0x0088;
1568 e3c2613f bellard
    s->bcr[BCR_LED3 ] = 0x0090;
1569 e3c2613f bellard
    s->bcr[BCR_FDC  ] = 0x0000;
1570 e3c2613f bellard
    s->bcr[BCR_BSBC ] = 0x9001;
1571 e3c2613f bellard
    s->bcr[BCR_EECAS] = 0x0002;
1572 e3c2613f bellard
    s->bcr[BCR_SWS  ] = 0x0200;
1573 e3c2613f bellard
    s->bcr[BCR_PLAT ] = 0xff06;
1574 e3c2613f bellard
1575 e3c2613f bellard
    pcnet_s_reset(s);
1576 de41ac92 Jan Kiszka
    pcnet_update_irq(s);
1577 de41ac92 Jan Kiszka
    pcnet_poll_timer(s);
1578 e3c2613f bellard
}
1579 e3c2613f bellard
1580 94e1a912 Gerd Hoffmann
void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1581 e3c2613f bellard
{
1582 e3c2613f bellard
    PCNetState *s = opaque;
1583 e3c2613f bellard
    pcnet_poll_timer(s);
1584 e3c2613f bellard
#ifdef PCNET_DEBUG_IO
1585 e3c2613f bellard
    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1586 e3c2613f bellard
#endif
1587 e3c2613f bellard
    if (!BCR_DWIO(s)) {
1588 e3c2613f bellard
        switch (addr & 0x0f) {
1589 e3c2613f bellard
        case 0x00: /* RDP */
1590 e3c2613f bellard
            pcnet_csr_writew(s, s->rap, val);
1591 e3c2613f bellard
            break;
1592 e3c2613f bellard
        case 0x02:
1593 e3c2613f bellard
            s->rap = val & 0x7f;
1594 e3c2613f bellard
            break;
1595 e3c2613f bellard
        case 0x06:
1596 e3c2613f bellard
            pcnet_bcr_writew(s, s->rap, val);
1597 e3c2613f bellard
            break;
1598 e3c2613f bellard
        }
1599 e3c2613f bellard
    }
1600 e3c2613f bellard
    pcnet_update_irq(s);
1601 e3c2613f bellard
}
1602 e3c2613f bellard
1603 94e1a912 Gerd Hoffmann
uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1604 e3c2613f bellard
{
1605 e3c2613f bellard
    PCNetState *s = opaque;
1606 e3c2613f bellard
    uint32_t val = -1;
1607 e3c2613f bellard
    pcnet_poll_timer(s);
1608 e3c2613f bellard
    if (!BCR_DWIO(s)) {
1609 e3c2613f bellard
        switch (addr & 0x0f) {
1610 e3c2613f bellard
        case 0x00: /* RDP */
1611 e3c2613f bellard
            val = pcnet_csr_readw(s, s->rap);
1612 e3c2613f bellard
            break;
1613 e3c2613f bellard
        case 0x02:
1614 e3c2613f bellard
            val = s->rap;
1615 e3c2613f bellard
            break;
1616 e3c2613f bellard
        case 0x04:
1617 e3c2613f bellard
            pcnet_s_reset(s);
1618 e3c2613f bellard
            val = 0;
1619 e3c2613f bellard
            break;
1620 e3c2613f bellard
        case 0x06:
1621 e3c2613f bellard
            val = pcnet_bcr_readw(s, s->rap);
1622 e3c2613f bellard
            break;
1623 e3c2613f bellard
        }
1624 e3c2613f bellard
    }
1625 e3c2613f bellard
    pcnet_update_irq(s);
1626 e3c2613f bellard
#ifdef PCNET_DEBUG_IO
1627 e3c2613f bellard
    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1628 e3c2613f bellard
#endif
1629 e3c2613f bellard
    return val;
1630 e3c2613f bellard
}
1631 e3c2613f bellard
1632 a4c75a21 Paul Brook
void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1633 e3c2613f bellard
{
1634 e3c2613f bellard
    PCNetState *s = opaque;
1635 e3c2613f bellard
    pcnet_poll_timer(s);
1636 e3c2613f bellard
#ifdef PCNET_DEBUG_IO
1637 e3c2613f bellard
    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1638 e3c2613f bellard
#endif
1639 e3c2613f bellard
    if (BCR_DWIO(s)) {
1640 e3c2613f bellard
        switch (addr & 0x0f) {
1641 e3c2613f bellard
        case 0x00: /* RDP */
1642 e3c2613f bellard
            pcnet_csr_writew(s, s->rap, val & 0xffff);
1643 e3c2613f bellard
            break;
1644 e3c2613f bellard
        case 0x04:
1645 e3c2613f bellard
            s->rap = val & 0x7f;
1646 e3c2613f bellard
            break;
1647 e3c2613f bellard
        case 0x0c:
1648 e3c2613f bellard
            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1649 e3c2613f bellard
            break;
1650 e3c2613f bellard
        }
1651 e3c2613f bellard
    } else
1652 e3c2613f bellard
    if ((addr & 0x0f) == 0) {
1653 e3c2613f bellard
        /* switch device to dword i/o mode */
1654 e3c2613f bellard
        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1655 e3c2613f bellard
#ifdef PCNET_DEBUG_IO
1656 e3c2613f bellard
        printf("device switched into dword i/o mode\n");
1657 3b46e624 ths
#endif
1658 e3c2613f bellard
    }
1659 e3c2613f bellard
    pcnet_update_irq(s);
1660 e3c2613f bellard
}
1661 e3c2613f bellard
1662 a4c75a21 Paul Brook
uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1663 e3c2613f bellard
{
1664 e3c2613f bellard
    PCNetState *s = opaque;
1665 e3c2613f bellard
    uint32_t val = -1;
1666 e3c2613f bellard
    pcnet_poll_timer(s);
1667 3b46e624 ths
    if (BCR_DWIO(s)) {
1668 e3c2613f bellard
        switch (addr & 0x0f) {
1669 e3c2613f bellard
        case 0x00: /* RDP */
1670 e3c2613f bellard
            val = pcnet_csr_readw(s, s->rap);
1671 e3c2613f bellard
            break;
1672 e3c2613f bellard
        case 0x04:
1673 e3c2613f bellard
            val = s->rap;
1674 e3c2613f bellard
            break;
1675 e3c2613f bellard
        case 0x08:
1676 e3c2613f bellard
            pcnet_s_reset(s);
1677 e3c2613f bellard
            val = 0;
1678 e3c2613f bellard
            break;
1679 e3c2613f bellard
        case 0x0c:
1680 e3c2613f bellard
            val = pcnet_bcr_readw(s, s->rap);
1681 e3c2613f bellard
            break;
1682 e3c2613f bellard
        }
1683 e3c2613f bellard
    }
1684 e3c2613f bellard
    pcnet_update_irq(s);
1685 e3c2613f bellard
#ifdef PCNET_DEBUG_IO
1686 e3c2613f bellard
    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1687 e3c2613f bellard
#endif
1688 e3c2613f bellard
    return val;
1689 e3c2613f bellard
}
1690 e3c2613f bellard
1691 3d865059 Juan Quintela
static bool is_version_2(void *opaque, int version_id)
1692 91cc0295 bellard
{
1693 3d865059 Juan Quintela
    return version_id == 2;
1694 91cc0295 bellard
}
1695 91cc0295 bellard
1696 3d865059 Juan Quintela
const VMStateDescription vmstate_pcnet = {
1697 3d865059 Juan Quintela
    .name = "pcnet",
1698 3d865059 Juan Quintela
    .version_id = 3,
1699 3d865059 Juan Quintela
    .minimum_version_id = 2,
1700 3d865059 Juan Quintela
    .minimum_version_id_old = 2,
1701 3d865059 Juan Quintela
    .fields      = (VMStateField []) {
1702 3d865059 Juan Quintela
        VMSTATE_INT32(rap, PCNetState),
1703 3d865059 Juan Quintela
        VMSTATE_INT32(isr, PCNetState),
1704 3d865059 Juan Quintela
        VMSTATE_INT32(lnkst, PCNetState),
1705 3d865059 Juan Quintela
        VMSTATE_UINT32(rdra, PCNetState),
1706 3d865059 Juan Quintela
        VMSTATE_UINT32(tdra, PCNetState),
1707 3d865059 Juan Quintela
        VMSTATE_BUFFER(prom, PCNetState),
1708 3d865059 Juan Quintela
        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1709 3d865059 Juan Quintela
        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1710 3d865059 Juan Quintela
        VMSTATE_UINT64(timer, PCNetState),
1711 3d865059 Juan Quintela
        VMSTATE_INT32(xmit_pos, PCNetState),
1712 3d865059 Juan Quintela
        VMSTATE_BUFFER(buffer, PCNetState),
1713 3d865059 Juan Quintela
        VMSTATE_UNUSED_TEST(is_version_2, 4),
1714 3d865059 Juan Quintela
        VMSTATE_INT32(tx_busy, PCNetState),
1715 3d865059 Juan Quintela
        VMSTATE_TIMER(poll_timer, PCNetState),
1716 3d865059 Juan Quintela
        VMSTATE_END_OF_LIST()
1717 efb56cf7 Jan Kiszka
    }
1718 3d865059 Juan Quintela
};
1719 0abaa7c1 Juan Quintela
1720 94e1a912 Gerd Hoffmann
void pcnet_common_cleanup(PCNetState *d)
1721 b946a153 aliguori
{
1722 1fa51482 Mark McLoughlin
    d->nic = NULL;
1723 b946a153 aliguori
}
1724 b946a153 aliguori
1725 1fa51482 Mark McLoughlin
int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1726 91cc0295 bellard
{
1727 7165448a William Dauchy
    int i;
1728 7165448a William Dauchy
    uint16_t checksum;
1729 7165448a William Dauchy
1730 74475455 Paolo Bonzini
    s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
1731 9d07d757 Paul Brook
1732 76224833 Gerd Hoffmann
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1733 f79f2bfc Anthony Liguori
    s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
1734 b356f76d Jason Wang
    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1735 1ca4d09a Gleb Natapov
1736 1ca4d09a Gleb Natapov
    add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
1737 1ca4d09a Gleb Natapov
1738 7165448a William Dauchy
    /* Initialize the PROM */
1739 7165448a William Dauchy
1740 7165448a William Dauchy
    /*
1741 7165448a William Dauchy
      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1742 7165448a William Dauchy
      page 95
1743 7165448a William Dauchy
    */
1744 7165448a William Dauchy
    memcpy(s->prom, s->conf.macaddr.a, 6);
1745 7165448a William Dauchy
    /* Reserved Location: must be 00h */
1746 7165448a William Dauchy
    s->prom[6] = s->prom[7] = 0x00;
1747 7165448a William Dauchy
    /* Reserved Location: must be 00h */
1748 7165448a William Dauchy
    s->prom[8] = 0x00;
1749 7165448a William Dauchy
    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1750 7165448a William Dauchy
    s->prom[9] = 0x11;
1751 7165448a William Dauchy
    /* User programmable space, init with 0 */
1752 7165448a William Dauchy
    s->prom[10] = s->prom[11] = 0x00;
1753 7165448a William Dauchy
    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1754 7165448a William Dauchy
       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1755 7165448a William Dauchy
    s->prom[12] = s->prom[13] = 0x00;
1756 7165448a William Dauchy
    /* Must be ASCII W (57h) if compatibility to AMD
1757 7165448a William Dauchy
       driver software is desired */
1758 7165448a William Dauchy
    s->prom[14] = s->prom[15] = 0x57;
1759 7165448a William Dauchy
1760 7165448a William Dauchy
    for (i = 0, checksum = 0; i < 16; i++) {
1761 7165448a William Dauchy
        checksum += s->prom[i];
1762 7165448a William Dauchy
    }
1763 7165448a William Dauchy
    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1764 7165448a William Dauchy
1765 9f2a8d7a Jan Kiszka
    s->lnkst = 0x40; /* initial link state: up */
1766 9f2a8d7a Jan Kiszka
1767 81a322d4 Gerd Hoffmann
    return 0;
1768 91cc0295 bellard
}