xref: /openbmc/qemu/hw/net/pcnet.c (revision 35ac6831d98e18e2c78c85c93e3a6ca1f1ae3e58)
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