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