xref: /qemu/hw/net/pcnet.c (revision 6a5287ce)
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 
pcnet_tmd_load(PCNetState * s,struct pcnet_TMD * tmd,hwaddr addr)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 
pcnet_tmd_store(PCNetState * s,const struct pcnet_TMD * tmd,hwaddr addr)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 
pcnet_rmd_load(PCNetState * s,struct pcnet_RMD * rmd,hwaddr addr)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 
pcnet_rmd_store(PCNetState * s,struct pcnet_RMD * rmd,hwaddr addr)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 
padr_match(PCNetState * s,const uint8_t * buf,int size)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 
padr_bcast(PCNetState * s,const uint8_t * buf,int size)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 
ladr_match(PCNetState * s,const uint8_t * buf,int size)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         (s->csr[8] | s->csr[9] | s->csr[10] | s->csr[11]) != 0) {
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 
pcnet_rdra_addr(PCNetState * s,int idx)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 
pcnet_get_next_poll_time(PCNetState * s,int64_t current_time)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 
pcnet_s_reset(PCNetState * s)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 
pcnet_update_irq(PCNetState * s)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 
pcnet_init(PCNetState * s)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 
pcnet_start(PCNetState * s)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 
pcnet_stop(PCNetState * s)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 
pcnet_rdte_poll(PCNetState * s)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" HWADDR_FMT_plx "\n",
912                        crda);
913             }
914         } else {
915             printf("pcnet: BAD RMD RDA=0x" HWADDR_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 
pcnet_tdte_poll(PCNetState * s)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 
pcnet_receive(NetClientState * nc,const uint8_t * buf,size_t size_)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     int remaining;
991     int crc_err = 0;
992     size_t size = size_;
993 
994     if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
995         (CSR_LOOP(s) && !s->looptest)) {
996         return -1;
997     }
998 #ifdef PCNET_DEBUG
999     printf("pcnet_receive size=%zu\n", size);
1000 #endif
1001 
1002     if (CSR_PROM(s)
1003         || (is_padr=padr_match(s, buf, size))
1004         || (is_bcast=padr_bcast(s, buf, size))
1005         || (is_ladr=ladr_match(s, buf, size))) {
1006 
1007         pcnet_rdte_poll(s);
1008 
1009         if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1010             struct pcnet_RMD rmd;
1011             int rcvrc = CSR_RCVRC(s)-1,i;
1012             hwaddr nrda;
1013             for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1014                 if (rcvrc <= 1)
1015                     rcvrc = CSR_RCVRL(s);
1016                 nrda = s->rdra +
1017                     (CSR_RCVRL(s) - rcvrc) *
1018                     (BCR_SWSTYLE(s) ? 16 : 8 );
1019                 RMDLOAD(&rmd, nrda);
1020                 if (GET_FIELD(rmd.status, RMDS, OWN)) {
1021 #ifdef PCNET_DEBUG_RMD
1022                     printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1023                                 rcvrc, CSR_RCVRC(s));
1024 #endif
1025                     CSR_RCVRC(s) = rcvrc;
1026                     pcnet_rdte_poll(s);
1027                     break;
1028                 }
1029             }
1030         }
1031 
1032         if (!(CSR_CRST(s) & 0x8000)) {
1033 #ifdef PCNET_DEBUG_RMD
1034             printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1035 #endif
1036             s->csr[0] |= 0x1000; /* Set MISS flag */
1037             CSR_MISSC(s)++;
1038         } else {
1039             uint8_t *src = s->buffer;
1040             hwaddr crda = CSR_CRDA(s);
1041             struct pcnet_RMD rmd;
1042             int pktcount = 0;
1043 
1044             if (!s->looptest) {
1045                 if (size > 4092) {
1046 #ifdef PCNET_DEBUG_RMD
1047                     fprintf(stderr, "pcnet: truncates rx packet.\n");
1048 #endif
1049                     size = 4092;
1050                 }
1051                 memcpy(src, buf, size);
1052                 /* no need to compute the CRC */
1053                 src[size] = 0;
1054                 src[size + 1] = 0;
1055                 src[size + 2] = 0;
1056                 src[size + 3] = 0;
1057                 size += 4;
1058             } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1059                        !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1060                 uint32_t fcs = ~0;
1061                 uint8_t *p = src;
1062 
1063                 while (p != &src[size])
1064                     CRC(fcs, *p++);
1065                 *(uint32_t *)p = htonl(fcs);
1066                 size += 4;
1067             } else {
1068                 uint32_t fcs = ~0;
1069                 uint8_t *p = src;
1070 
1071                 while (p != &src[size])
1072                     CRC(fcs, *p++);
1073                 crc_err = (*(uint32_t *)p != htonl(fcs));
1074             }
1075 
1076 #ifdef PCNET_DEBUG_MATCH
1077             PRINT_PKTHDR(buf);
1078 #endif
1079 
1080             RMDLOAD(&rmd, PHYSADDR(s,crda));
1081             /*if (!CSR_LAPPEN(s))*/
1082                 SET_FIELD(&rmd.status, RMDS, STP, 1);
1083 
1084 #define PCNET_RECV_STORE() do {                                 \
1085     int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1086     hwaddr rbadr = PHYSADDR(s, rmd.rbadr);          \
1087     s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1088     src += count; remaining -= count;                           \
1089     SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1090     RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1091     pktcount++;                                                 \
1092 } while (0)
1093 
1094             remaining = size;
1095             PCNET_RECV_STORE();
1096             if ((remaining > 0) && CSR_NRDA(s)) {
1097                 hwaddr nrda = CSR_NRDA(s);
1098 #ifdef PCNET_DEBUG_RMD
1099                 PRINT_RMD(&rmd);
1100 #endif
1101                 RMDLOAD(&rmd, PHYSADDR(s,nrda));
1102                 if (GET_FIELD(rmd.status, RMDS, OWN)) {
1103                     crda = nrda;
1104                     PCNET_RECV_STORE();
1105 #ifdef PCNET_DEBUG_RMD
1106                     PRINT_RMD(&rmd);
1107 #endif
1108                     if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1109                         RMDLOAD(&rmd, PHYSADDR(s,nrda));
1110                         if (GET_FIELD(rmd.status, RMDS, OWN)) {
1111                             crda = nrda;
1112                             PCNET_RECV_STORE();
1113                         }
1114                     }
1115                 }
1116             }
1117 
1118 #undef PCNET_RECV_STORE
1119 
1120             RMDLOAD(&rmd, PHYSADDR(s,crda));
1121             if (remaining == 0) {
1122                 SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1123                 SET_FIELD(&rmd.status, RMDS, ENP, 1);
1124                 SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1125                 SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1126                 SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1127                 if (crc_err) {
1128                     SET_FIELD(&rmd.status, RMDS, CRC, 1);
1129                     SET_FIELD(&rmd.status, RMDS, ERR, 1);
1130                 }
1131             } else {
1132                 SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1133                 SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1134                 SET_FIELD(&rmd.status, RMDS, ERR, 1);
1135             }
1136             RMDSTORE(&rmd, PHYSADDR(s,crda));
1137             s->csr[0] |= 0x0400;
1138 
1139 #ifdef PCNET_DEBUG
1140             printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1141                 CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1142 #endif
1143 #ifdef PCNET_DEBUG_RMD
1144             PRINT_RMD(&rmd);
1145 #endif
1146 
1147             while (pktcount--) {
1148                 if (CSR_RCVRC(s) <= 1) {
1149                     CSR_RCVRC(s) = CSR_RCVRL(s);
1150                 } else {
1151                     CSR_RCVRC(s)--;
1152                 }
1153             }
1154 
1155             pcnet_rdte_poll(s);
1156 
1157         }
1158     }
1159 
1160     pcnet_poll(s);
1161     pcnet_update_irq(s);
1162 
1163     return size_;
1164 }
1165 
pcnet_set_link_status(NetClientState * nc)1166 void pcnet_set_link_status(NetClientState *nc)
1167 {
1168     PCNetState *d = qemu_get_nic_opaque(nc);
1169 
1170     d->lnkst = nc->link_down ? 0 : 0x40;
1171 }
1172 
pcnet_transmit(PCNetState * s)1173 static void pcnet_transmit(PCNetState *s)
1174 {
1175     hwaddr xmit_cxda = 0;
1176     int count = CSR_XMTRL(s)-1;
1177     int add_crc = 0;
1178     int bcnt;
1179     s->xmit_pos = -1;
1180 
1181     if (!CSR_TXON(s)) {
1182         s->csr[0] &= ~0x0008;
1183         return;
1184     }
1185 
1186     s->tx_busy = 1;
1187 
1188 txagain:
1189     if (pcnet_tdte_poll(s)) {
1190         struct pcnet_TMD tmd;
1191 
1192         TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1193 
1194 #ifdef PCNET_DEBUG_TMD
1195         printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1196         PRINT_TMD(&tmd);
1197 #endif
1198         if (GET_FIELD(tmd.status, TMDS, STP)) {
1199             s->xmit_pos = 0;
1200             xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1201             if (BCR_SWSTYLE(s) != 1)
1202                 add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1203         }
1204         if (s->lnkst == 0 &&
1205             (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
1206             SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
1207             SET_FIELD(&tmd.status, TMDS, ERR, 1);
1208             SET_FIELD(&tmd.status, TMDS, OWN, 0);
1209             s->csr[0] |= 0xa000; /* ERR | CERR */
1210             s->xmit_pos = -1;
1211             goto txdone;
1212         }
1213 
1214         if (s->xmit_pos < 0) {
1215             goto txdone;
1216         }
1217 
1218         bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1219 
1220         /* if multi-tmd packet outsizes s->buffer then skip it silently.
1221          * Note: this is not what real hw does.
1222          * Last four bytes of s->buffer are used to store CRC FCS code.
1223          */
1224         if (s->xmit_pos + bcnt > sizeof(s->buffer) - 4) {
1225             s->xmit_pos = -1;
1226             goto txdone;
1227         }
1228 
1229         s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1230                          s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1231         s->xmit_pos += bcnt;
1232 
1233         if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1234             goto txdone;
1235         }
1236 
1237 #ifdef PCNET_DEBUG
1238         printf("pcnet_transmit size=%d\n", s->xmit_pos);
1239 #endif
1240         if (CSR_LOOP(s)) {
1241             if (BCR_SWSTYLE(s) == 1)
1242                 add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1243             s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1244             qemu_receive_packet(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
1245             s->looptest = 0;
1246         } else {
1247             if (s->nic) {
1248                 qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
1249                                  s->xmit_pos);
1250             }
1251         }
1252 
1253         s->csr[0] &= ~0x0008;   /* clear TDMD */
1254         s->csr[4] |= 0x0004;    /* set TXSTRT */
1255         s->xmit_pos = -1;
1256 
1257 txdone:
1258         SET_FIELD(&tmd.status, TMDS, OWN, 0);
1259         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1260         if (!CSR_TOKINTD(s)
1261             || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT))) {
1262             s->csr[0] |= 0x0200;    /* set TINT */
1263         }
1264         if (CSR_XMTRC(s) <= 1) {
1265             CSR_XMTRC(s) = CSR_XMTRL(s);
1266         } else {
1267             CSR_XMTRC(s)--;
1268         }
1269         if (count--) {
1270             goto txagain;
1271         }
1272     } else if (s->xmit_pos >= 0) {
1273         struct pcnet_TMD tmd;
1274         TMDLOAD(&tmd, xmit_cxda);
1275         SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1276         SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1277         SET_FIELD(&tmd.status, TMDS, ERR, 1);
1278         SET_FIELD(&tmd.status, TMDS, OWN, 0);
1279         TMDSTORE(&tmd, xmit_cxda);
1280         s->csr[0] |= 0x0200;    /* set TINT */
1281         if (!CSR_DXSUFLO(s)) {
1282             s->csr[0] &= ~0x0010;
1283         } else if (count--) {
1284             goto txagain;
1285         }
1286     }
1287 
1288     s->tx_busy = 0;
1289 }
1290 
pcnet_poll(PCNetState * s)1291 static void pcnet_poll(PCNetState *s)
1292 {
1293     if (CSR_RXON(s)) {
1294         pcnet_rdte_poll(s);
1295     }
1296 
1297     if (CSR_TDMD(s) || (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) {
1298         /* prevent recursion */
1299         if (s->tx_busy) {
1300             return;
1301         }
1302         pcnet_transmit(s);
1303     }
1304 }
1305 
pcnet_poll_timer(void * opaque)1306 static void pcnet_poll_timer(void *opaque)
1307 {
1308     PCNetState *s = opaque;
1309 
1310     timer_del(s->poll_timer);
1311 
1312     if (CSR_TDMD(s)) {
1313         pcnet_transmit(s);
1314     }
1315 
1316     pcnet_update_irq(s);
1317 
1318     if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1319         uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) * 33;
1320         if (!s->timer || !now) {
1321             s->timer = now;
1322         } else {
1323             uint64_t t = now - s->timer + CSR_POLL(s);
1324             if (t > 0xffffLL) {
1325                 pcnet_poll(s);
1326                 CSR_POLL(s) = CSR_PINT(s);
1327             } else {
1328                 CSR_POLL(s) = t;
1329             }
1330         }
1331         timer_mod(s->poll_timer,
1332             pcnet_get_next_poll_time(s,qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)));
1333     }
1334 }
1335 
1336 
pcnet_csr_writew(PCNetState * s,uint32_t rap,uint32_t new_value)1337 static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1338 {
1339     uint16_t val = new_value;
1340 #ifdef PCNET_DEBUG_CSR
1341     printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1342 #endif
1343     switch (rap) {
1344     case 0:
1345         s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1346 
1347         s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1348 
1349         val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1350 
1351         /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1352         if ((val & 7) == 7) {
1353             val &= ~3;
1354         }
1355         if (!CSR_STOP(s) && (val & 4)) {
1356             pcnet_stop(s);
1357         }
1358         if (!CSR_INIT(s) && (val & 1)) {
1359             pcnet_init(s);
1360         }
1361         if (!CSR_STRT(s) && (val & 2)) {
1362             pcnet_start(s);
1363         }
1364         if (CSR_TDMD(s)) {
1365             pcnet_transmit(s);
1366         }
1367         return;
1368     case 1:
1369     case 2:
1370     case 8:
1371     case 9:
1372     case 10:
1373     case 11:
1374     case 12:
1375     case 13:
1376     case 14:
1377     case 15:
1378     case 18: /* CRBAL */
1379     case 19: /* CRBAU */
1380     case 20: /* CXBAL */
1381     case 21: /* CXBAU */
1382     case 22: /* NRBAU */
1383     case 23: /* NRBAU */
1384     case 24:
1385     case 25:
1386     case 26:
1387     case 27:
1388     case 28:
1389     case 29:
1390     case 30:
1391     case 31:
1392     case 32:
1393     case 33:
1394     case 34:
1395     case 35:
1396     case 36:
1397     case 37:
1398     case 38:
1399     case 39:
1400     case 40: /* CRBC */
1401     case 41:
1402     case 42: /* CXBC */
1403     case 43:
1404     case 44:
1405     case 45:
1406     case 46: /* POLL */
1407     case 47: /* POLLINT */
1408     case 72:
1409     case 74:
1410         break;
1411     case 76: /* RCVRL */
1412     case 78: /* XMTRL */
1413         val = (val > 0) ? val : 512;
1414         break;
1415     case 112:
1416         if (CSR_STOP(s) || CSR_SPND(s)) {
1417             break;
1418         }
1419         return;
1420     case 3:
1421         break;
1422     case 4:
1423         s->csr[4] &= ~(val & 0x026a);
1424         val &= ~0x026a; val |= s->csr[4] & 0x026a;
1425         break;
1426     case 5:
1427         s->csr[5] &= ~(val & 0x0a90);
1428         val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1429         break;
1430     case 16:
1431         pcnet_csr_writew(s,1,val);
1432         return;
1433     case 17:
1434         pcnet_csr_writew(s,2,val);
1435         return;
1436     case 58:
1437         pcnet_bcr_writew(s,BCR_SWS,val);
1438         break;
1439     default:
1440         return;
1441     }
1442     s->csr[rap] = val;
1443 }
1444 
pcnet_csr_readw(PCNetState * s,uint32_t rap)1445 static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1446 {
1447     uint32_t val;
1448     switch (rap) {
1449     case 0:
1450         pcnet_update_irq(s);
1451         val = s->csr[0];
1452         val |= (val & 0x7800) ? 0x8000 : 0;
1453         break;
1454     case 16:
1455         return pcnet_csr_readw(s,1);
1456     case 17:
1457         return pcnet_csr_readw(s,2);
1458     case 58:
1459         return pcnet_bcr_readw(s,BCR_SWS);
1460     case 88:
1461         val = s->csr[89];
1462         val <<= 16;
1463         val |= s->csr[88];
1464         break;
1465     default:
1466         val = s->csr[rap];
1467     }
1468 #ifdef PCNET_DEBUG_CSR
1469     printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1470 #endif
1471     return val;
1472 }
1473 
pcnet_bcr_writew(PCNetState * s,uint32_t rap,uint32_t val)1474 static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1475 {
1476     rap &= 127;
1477 #ifdef PCNET_DEBUG_BCR
1478     printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1479 #endif
1480     switch (rap) {
1481     case BCR_SWS:
1482         if (!(CSR_STOP(s) || CSR_SPND(s)))
1483             return;
1484         val &= ~0x0300;
1485         switch (val & 0x00ff) {
1486         case 0:
1487             val |= 0x0200;
1488             break;
1489         case 1:
1490             val |= 0x0100;
1491             break;
1492         case 2:
1493         case 3:
1494             val |= 0x0300;
1495             break;
1496         default:
1497             qemu_log_mask(LOG_GUEST_ERROR, "pcnet: Bad SWSTYLE=0x%02x\n",
1498                           val & 0xff);
1499             val = 0x0200;
1500             break;
1501         }
1502 #ifdef PCNET_DEBUG
1503        printf("BCR_SWS=0x%04x\n", val);
1504 #endif
1505         /* fall through */
1506     case BCR_LNKST:
1507     case BCR_LED1:
1508     case BCR_LED2:
1509     case BCR_LED3:
1510     case BCR_MC:
1511     case BCR_FDC:
1512     case BCR_BSBC:
1513     case BCR_EECAS:
1514     case BCR_PLAT:
1515         s->bcr[rap] = val;
1516         break;
1517     default:
1518         break;
1519     }
1520 }
1521 
pcnet_bcr_readw(PCNetState * s,uint32_t rap)1522 uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1523 {
1524     uint32_t val;
1525     rap &= 127;
1526     switch (rap) {
1527     case BCR_LNKST:
1528     case BCR_LED1:
1529     case BCR_LED2:
1530     case BCR_LED3:
1531         val = s->bcr[rap] & ~0x8000;
1532         val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1533         break;
1534     default:
1535         val = rap < 32 ? s->bcr[rap] : 0;
1536         break;
1537     }
1538 #ifdef PCNET_DEBUG_BCR
1539     printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1540 #endif
1541     return val;
1542 }
1543 
pcnet_h_reset(void * opaque)1544 void pcnet_h_reset(void *opaque)
1545 {
1546     PCNetState *s = opaque;
1547 
1548     s->bcr[BCR_MSRDA] = 0x0005;
1549     s->bcr[BCR_MSWRA] = 0x0005;
1550     s->bcr[BCR_MC   ] = 0x0002;
1551     s->bcr[BCR_LNKST] = 0x00c0;
1552     s->bcr[BCR_LED1 ] = 0x0084;
1553     s->bcr[BCR_LED2 ] = 0x0088;
1554     s->bcr[BCR_LED3 ] = 0x0090;
1555     s->bcr[BCR_FDC  ] = 0x0000;
1556     s->bcr[BCR_BSBC ] = 0x9001;
1557     s->bcr[BCR_EECAS] = 0x0002;
1558     s->bcr[BCR_SWS  ] = 0x0200;
1559     s->bcr[BCR_PLAT ] = 0xff06;
1560 
1561     pcnet_s_reset(s);
1562     pcnet_update_irq(s);
1563     pcnet_poll_timer(s);
1564 }
1565 
pcnet_ioport_writew(void * opaque,uint32_t addr,uint32_t val)1566 void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1567 {
1568     PCNetState *s = opaque;
1569     pcnet_poll_timer(s);
1570 #ifdef PCNET_DEBUG_IO
1571     printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1572 #endif
1573     if (!BCR_DWIO(s)) {
1574         switch (addr & 0x0f) {
1575         case 0x00: /* RDP */
1576             pcnet_csr_writew(s, s->rap, val);
1577             break;
1578         case 0x02:
1579             s->rap = val & 0x7f;
1580             break;
1581         case 0x06:
1582             pcnet_bcr_writew(s, s->rap, val);
1583             break;
1584         }
1585     }
1586     pcnet_update_irq(s);
1587 }
1588 
pcnet_ioport_readw(void * opaque,uint32_t addr)1589 uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1590 {
1591     PCNetState *s = opaque;
1592     uint32_t val = -1;
1593     pcnet_poll_timer(s);
1594     if (!BCR_DWIO(s)) {
1595         switch (addr & 0x0f) {
1596         case 0x00: /* RDP */
1597             val = pcnet_csr_readw(s, s->rap);
1598             break;
1599         case 0x02:
1600             val = s->rap;
1601             break;
1602         case 0x04:
1603             pcnet_s_reset(s);
1604             val = 0;
1605             break;
1606         case 0x06:
1607             val = pcnet_bcr_readw(s, s->rap);
1608             break;
1609         }
1610     }
1611     pcnet_update_irq(s);
1612 #ifdef PCNET_DEBUG_IO
1613     printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1614 #endif
1615     return val;
1616 }
1617 
pcnet_ioport_writel(void * opaque,uint32_t addr,uint32_t val)1618 void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1619 {
1620     PCNetState *s = opaque;
1621     pcnet_poll_timer(s);
1622 #ifdef PCNET_DEBUG_IO
1623     printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1624 #endif
1625     if (BCR_DWIO(s)) {
1626         switch (addr & 0x0f) {
1627         case 0x00: /* RDP */
1628             pcnet_csr_writew(s, s->rap, val & 0xffff);
1629             break;
1630         case 0x04:
1631             s->rap = val & 0x7f;
1632             break;
1633         case 0x0c:
1634             pcnet_bcr_writew(s, s->rap, val & 0xffff);
1635             break;
1636         }
1637     } else if ((addr & 0x0f) == 0) {
1638         /* switch device to dword i/o mode */
1639         pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1640 #ifdef PCNET_DEBUG_IO
1641         printf("device switched into dword i/o mode\n");
1642 #endif
1643     }
1644     pcnet_update_irq(s);
1645 }
1646 
pcnet_ioport_readl(void * opaque,uint32_t addr)1647 uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1648 {
1649     PCNetState *s = opaque;
1650     uint32_t val = -1;
1651     pcnet_poll_timer(s);
1652     if (BCR_DWIO(s)) {
1653         switch (addr & 0x0f) {
1654         case 0x00: /* RDP */
1655             val = pcnet_csr_readw(s, s->rap);
1656             break;
1657         case 0x04:
1658             val = s->rap;
1659             break;
1660         case 0x08:
1661             pcnet_s_reset(s);
1662             val = 0;
1663             break;
1664         case 0x0c:
1665             val = pcnet_bcr_readw(s, s->rap);
1666             break;
1667         }
1668     }
1669     pcnet_update_irq(s);
1670 #ifdef PCNET_DEBUG_IO
1671     printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1672 #endif
1673     return val;
1674 }
1675 
is_version_2(void * opaque,int version_id)1676 static bool is_version_2(void *opaque, int version_id)
1677 {
1678     return version_id == 2;
1679 }
1680 
1681 const VMStateDescription vmstate_pcnet = {
1682     .name = "pcnet",
1683     .version_id = 3,
1684     .minimum_version_id = 2,
1685     .fields = (const VMStateField[]) {
1686         VMSTATE_INT32(rap, PCNetState),
1687         VMSTATE_INT32(isr, PCNetState),
1688         VMSTATE_INT32(lnkst, PCNetState),
1689         VMSTATE_UINT32(rdra, PCNetState),
1690         VMSTATE_UINT32(tdra, PCNetState),
1691         VMSTATE_BUFFER(prom, PCNetState),
1692         VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1693         VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1694         VMSTATE_UINT64(timer, PCNetState),
1695         VMSTATE_INT32(xmit_pos, PCNetState),
1696         VMSTATE_BUFFER(buffer, PCNetState),
1697         VMSTATE_UNUSED_TEST(is_version_2, 4),
1698         VMSTATE_INT32(tx_busy, PCNetState),
1699         VMSTATE_TIMER_PTR(poll_timer, PCNetState),
1700         VMSTATE_END_OF_LIST()
1701     }
1702 };
1703 
pcnet_common_init(DeviceState * dev,PCNetState * s,NetClientInfo * info)1704 void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1705 {
1706     int i;
1707     uint16_t checksum;
1708 
1709     s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
1710 
1711     qemu_macaddr_default_if_unset(&s->conf.macaddr);
1712     s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)),
1713                           dev->id, &dev->mem_reentrancy_guard, s);
1714     qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1715 
1716     /* Initialize the PROM */
1717 
1718     /*
1719       Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1720       page 95
1721     */
1722     memcpy(s->prom, s->conf.macaddr.a, 6);
1723     /* Reserved Location: must be 00h */
1724     s->prom[6] = s->prom[7] = 0x00;
1725     /* Reserved Location: must be 00h */
1726     s->prom[8] = 0x00;
1727     /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1728     s->prom[9] = 0x11;
1729     /* User programmable space, init with 0 */
1730     s->prom[10] = s->prom[11] = 0x00;
1731     /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1732        and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1733     s->prom[12] = s->prom[13] = 0x00;
1734     /* Must be ASCII W (57h) if compatibility to AMD
1735        driver software is desired */
1736     s->prom[14] = s->prom[15] = 0x57;
1737 
1738     for (i = 0, checksum = 0; i < 16; i++) {
1739         checksum += s->prom[i];
1740     }
1741     *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1742 
1743     s->lnkst = 0x40; /* initial link state: up */
1744 }
1745