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