]> Git Repo - qemu.git/blob - hw/pcnet.c
PPC: Bump MPIC up to 32 supported CPUs
[qemu.git] / hw / pcnet.c
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] | ((uint32_t)(S)->csr[ 2] << 16))
117 #define CSR_CRBA(S)      ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16))
118 #define CSR_CXBA(S)      ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16))
119 #define CSR_NRBA(S)      ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16))
120 #define CSR_BADR(S)      ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16))
121 #define CSR_NRDA(S)      ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16))
122 #define CSR_CRDA(S)      ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16))
123 #define CSR_BADX(S)      ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16))
124 #define CSR_NXDA(S)      ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16))
125 #define CSR_CXDA(S)      ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16))
126 #define CSR_NNRD(S)      ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16))
127 #define CSR_NNXD(S)      ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16))
128 #define CSR_PXDA(S)      ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16))
129 #define CSR_NXBA(S)      ((S)->csr[64] | ((uint32_t)(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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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         if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1250             int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1251             s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1252                              s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1253             s->xmit_pos += bcnt;
1254         } else if (s->xmit_pos >= 0) {
1255             int bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1256             s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1257                              s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1258             s->xmit_pos += bcnt;
1259 #ifdef PCNET_DEBUG
1260             printf("pcnet_transmit size=%d\n", s->xmit_pos);
1261 #endif
1262             if (CSR_LOOP(s)) {
1263                 if (BCR_SWSTYLE(s) == 1)
1264                     add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1265                 s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1266                 pcnet_receive(&s->nic->nc, s->buffer, s->xmit_pos);
1267                 s->looptest = 0;
1268             } else
1269                 if (s->nic)
1270                     qemu_send_packet(&s->nic->nc, s->buffer, s->xmit_pos);
1271
1272             s->csr[0] &= ~0x0008;   /* clear TDMD */
1273             s->csr[4] |= 0x0004;    /* set TXSTRT */
1274             s->xmit_pos = -1;
1275         }
1276
1277         SET_FIELD(&tmd.status, TMDS, OWN, 0);
1278         TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1279         if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1280             s->csr[0] |= 0x0200;    /* set TINT */
1281
1282         if (CSR_XMTRC(s)<=1)
1283             CSR_XMTRC(s) = CSR_XMTRL(s);
1284         else
1285             CSR_XMTRC(s)--;
1286         if (count--)
1287             goto txagain;
1288
1289     } else
1290     if (s->xmit_pos >= 0) {
1291         struct pcnet_TMD tmd;
1292         TMDLOAD(&tmd, xmit_cxda);
1293         SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1294         SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1295         SET_FIELD(&tmd.status, TMDS, ERR, 1);
1296         SET_FIELD(&tmd.status, TMDS, OWN, 0);
1297         TMDSTORE(&tmd, xmit_cxda);
1298         s->csr[0] |= 0x0200;    /* set TINT */
1299         if (!CSR_DXSUFLO(s)) {
1300             s->csr[0] &= ~0x0010;
1301         } else
1302         if (count--)
1303           goto txagain;
1304     }
1305
1306     s->tx_busy = 0;
1307 }
1308
1309 static void pcnet_poll(PCNetState *s)
1310 {
1311     if (CSR_RXON(s)) {
1312         pcnet_rdte_poll(s);
1313     }
1314
1315     if (CSR_TDMD(s) ||
1316         (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1317     {
1318         /* prevent recursion */
1319         if (s->tx_busy)
1320             return;
1321
1322         pcnet_transmit(s);
1323     }
1324 }
1325
1326 static void pcnet_poll_timer(void *opaque)
1327 {
1328     PCNetState *s = opaque;
1329
1330     qemu_del_timer(s->poll_timer);
1331
1332     if (CSR_TDMD(s)) {
1333         pcnet_transmit(s);
1334     }
1335
1336     pcnet_update_irq(s);
1337
1338     if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1339         uint64_t now = qemu_get_clock_ns(vm_clock) * 33;
1340         if (!s->timer || !now)
1341             s->timer = now;
1342         else {
1343             uint64_t t = now - s->timer + CSR_POLL(s);
1344             if (t > 0xffffLL) {
1345                 pcnet_poll(s);
1346                 CSR_POLL(s) = CSR_PINT(s);
1347             } else
1348                 CSR_POLL(s) = t;
1349         }
1350         qemu_mod_timer(s->poll_timer,
1351             pcnet_get_next_poll_time(s,qemu_get_clock_ns(vm_clock)));
1352     }
1353 }
1354
1355
1356 static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1357 {
1358     uint16_t val = new_value;
1359 #ifdef PCNET_DEBUG_CSR
1360     printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1361 #endif
1362     switch (rap) {
1363     case 0:
1364         s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1365
1366         s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1367
1368         val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1369
1370         /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1371         if ((val&7) == 7)
1372           val &= ~3;
1373
1374         if (!CSR_STOP(s) && (val & 4))
1375             pcnet_stop(s);
1376
1377         if (!CSR_INIT(s) && (val & 1))
1378             pcnet_init(s);
1379
1380         if (!CSR_STRT(s) && (val & 2))
1381             pcnet_start(s);
1382
1383         if (CSR_TDMD(s))
1384             pcnet_transmit(s);
1385
1386         return;
1387     case 1:
1388     case 2:
1389     case 8:
1390     case 9:
1391     case 10:
1392     case 11:
1393     case 12:
1394     case 13:
1395     case 14:
1396     case 15:
1397     case 18: /* CRBAL */
1398     case 19: /* CRBAU */
1399     case 20: /* CXBAL */
1400     case 21: /* CXBAU */
1401     case 22: /* NRBAU */
1402     case 23: /* NRBAU */
1403     case 24:
1404     case 25:
1405     case 26:
1406     case 27:
1407     case 28:
1408     case 29:
1409     case 30:
1410     case 31:
1411     case 32:
1412     case 33:
1413     case 34:
1414     case 35:
1415     case 36:
1416     case 37:
1417     case 38:
1418     case 39:
1419     case 40: /* CRBC */
1420     case 41:
1421     case 42: /* CXBC */
1422     case 43:
1423     case 44:
1424     case 45:
1425     case 46: /* POLL */
1426     case 47: /* POLLINT */
1427     case 72:
1428     case 74:
1429     case 76: /* RCVRL */
1430     case 78: /* XMTRL */
1431     case 112:
1432        if (CSR_STOP(s) || CSR_SPND(s))
1433            break;
1434        return;
1435     case 3:
1436         break;
1437     case 4:
1438         s->csr[4] &= ~(val & 0x026a);
1439         val &= ~0x026a; val |= s->csr[4] & 0x026a;
1440         break;
1441     case 5:
1442         s->csr[5] &= ~(val & 0x0a90);
1443         val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1444         break;
1445     case 16:
1446         pcnet_csr_writew(s,1,val);
1447         return;
1448     case 17:
1449         pcnet_csr_writew(s,2,val);
1450         return;
1451     case 58:
1452         pcnet_bcr_writew(s,BCR_SWS,val);
1453         break;
1454     default:
1455         return;
1456     }
1457     s->csr[rap] = val;
1458 }
1459
1460 static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1461 {
1462     uint32_t val;
1463     switch (rap) {
1464     case 0:
1465         pcnet_update_irq(s);
1466         val = s->csr[0];
1467         val |= (val & 0x7800) ? 0x8000 : 0;
1468         break;
1469     case 16:
1470         return pcnet_csr_readw(s,1);
1471     case 17:
1472         return pcnet_csr_readw(s,2);
1473     case 58:
1474         return pcnet_bcr_readw(s,BCR_SWS);
1475     case 88:
1476         val = s->csr[89];
1477         val <<= 16;
1478         val |= s->csr[88];
1479         break;
1480     default:
1481         val = s->csr[rap];
1482     }
1483 #ifdef PCNET_DEBUG_CSR
1484     printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1485 #endif
1486     return val;
1487 }
1488
1489 static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1490 {
1491     rap &= 127;
1492 #ifdef PCNET_DEBUG_BCR
1493     printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1494 #endif
1495     switch (rap) {
1496     case BCR_SWS:
1497         if (!(CSR_STOP(s) || CSR_SPND(s)))
1498             return;
1499         val &= ~0x0300;
1500         switch (val & 0x00ff) {
1501         case 0:
1502             val |= 0x0200;
1503             break;
1504         case 1:
1505             val |= 0x0100;
1506             break;
1507         case 2:
1508         case 3:
1509             val |= 0x0300;
1510             break;
1511         default:
1512             printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1513             val = 0x0200;
1514             break;
1515         }
1516 #ifdef PCNET_DEBUG
1517        printf("BCR_SWS=0x%04x\n", val);
1518 #endif
1519     case BCR_LNKST:
1520     case BCR_LED1:
1521     case BCR_LED2:
1522     case BCR_LED3:
1523     case BCR_MC:
1524     case BCR_FDC:
1525     case BCR_BSBC:
1526     case BCR_EECAS:
1527     case BCR_PLAT:
1528         s->bcr[rap] = val;
1529         break;
1530     default:
1531         break;
1532     }
1533 }
1534
1535 uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1536 {
1537     uint32_t val;
1538     rap &= 127;
1539     switch (rap) {
1540     case BCR_LNKST:
1541     case BCR_LED1:
1542     case BCR_LED2:
1543     case BCR_LED3:
1544         val = s->bcr[rap] & ~0x8000;
1545         val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1546         break;
1547     default:
1548         val = rap < 32 ? s->bcr[rap] : 0;
1549         break;
1550     }
1551 #ifdef PCNET_DEBUG_BCR
1552     printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1553 #endif
1554     return val;
1555 }
1556
1557 void pcnet_h_reset(void *opaque)
1558 {
1559     PCNetState *s = opaque;
1560
1561     s->bcr[BCR_MSRDA] = 0x0005;
1562     s->bcr[BCR_MSWRA] = 0x0005;
1563     s->bcr[BCR_MC   ] = 0x0002;
1564     s->bcr[BCR_LNKST] = 0x00c0;
1565     s->bcr[BCR_LED1 ] = 0x0084;
1566     s->bcr[BCR_LED2 ] = 0x0088;
1567     s->bcr[BCR_LED3 ] = 0x0090;
1568     s->bcr[BCR_FDC  ] = 0x0000;
1569     s->bcr[BCR_BSBC ] = 0x9001;
1570     s->bcr[BCR_EECAS] = 0x0002;
1571     s->bcr[BCR_SWS  ] = 0x0200;
1572     s->bcr[BCR_PLAT ] = 0xff06;
1573
1574     pcnet_s_reset(s);
1575     pcnet_update_irq(s);
1576     pcnet_poll_timer(s);
1577 }
1578
1579 void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1580 {
1581     PCNetState *s = opaque;
1582     pcnet_poll_timer(s);
1583 #ifdef PCNET_DEBUG_IO
1584     printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1585 #endif
1586     if (!BCR_DWIO(s)) {
1587         switch (addr & 0x0f) {
1588         case 0x00: /* RDP */
1589             pcnet_csr_writew(s, s->rap, val);
1590             break;
1591         case 0x02:
1592             s->rap = val & 0x7f;
1593             break;
1594         case 0x06:
1595             pcnet_bcr_writew(s, s->rap, val);
1596             break;
1597         }
1598     }
1599     pcnet_update_irq(s);
1600 }
1601
1602 uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1603 {
1604     PCNetState *s = opaque;
1605     uint32_t val = -1;
1606     pcnet_poll_timer(s);
1607     if (!BCR_DWIO(s)) {
1608         switch (addr & 0x0f) {
1609         case 0x00: /* RDP */
1610             val = pcnet_csr_readw(s, s->rap);
1611             break;
1612         case 0x02:
1613             val = s->rap;
1614             break;
1615         case 0x04:
1616             pcnet_s_reset(s);
1617             val = 0;
1618             break;
1619         case 0x06:
1620             val = pcnet_bcr_readw(s, s->rap);
1621             break;
1622         }
1623     }
1624     pcnet_update_irq(s);
1625 #ifdef PCNET_DEBUG_IO
1626     printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1627 #endif
1628     return val;
1629 }
1630
1631 void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1632 {
1633     PCNetState *s = opaque;
1634     pcnet_poll_timer(s);
1635 #ifdef PCNET_DEBUG_IO
1636     printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1637 #endif
1638     if (BCR_DWIO(s)) {
1639         switch (addr & 0x0f) {
1640         case 0x00: /* RDP */
1641             pcnet_csr_writew(s, s->rap, val & 0xffff);
1642             break;
1643         case 0x04:
1644             s->rap = val & 0x7f;
1645             break;
1646         case 0x0c:
1647             pcnet_bcr_writew(s, s->rap, val & 0xffff);
1648             break;
1649         }
1650     } else
1651     if ((addr & 0x0f) == 0) {
1652         /* switch device to dword i/o mode */
1653         pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1654 #ifdef PCNET_DEBUG_IO
1655         printf("device switched into dword i/o mode\n");
1656 #endif
1657     }
1658     pcnet_update_irq(s);
1659 }
1660
1661 uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1662 {
1663     PCNetState *s = opaque;
1664     uint32_t val = -1;
1665     pcnet_poll_timer(s);
1666     if (BCR_DWIO(s)) {
1667         switch (addr & 0x0f) {
1668         case 0x00: /* RDP */
1669             val = pcnet_csr_readw(s, s->rap);
1670             break;
1671         case 0x04:
1672             val = s->rap;
1673             break;
1674         case 0x08:
1675             pcnet_s_reset(s);
1676             val = 0;
1677             break;
1678         case 0x0c:
1679             val = pcnet_bcr_readw(s, s->rap);
1680             break;
1681         }
1682     }
1683     pcnet_update_irq(s);
1684 #ifdef PCNET_DEBUG_IO
1685     printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1686 #endif
1687     return val;
1688 }
1689
1690 static bool is_version_2(void *opaque, int version_id)
1691 {
1692     return version_id == 2;
1693 }
1694
1695 const VMStateDescription vmstate_pcnet = {
1696     .name = "pcnet",
1697     .version_id = 3,
1698     .minimum_version_id = 2,
1699     .minimum_version_id_old = 2,
1700     .fields      = (VMStateField []) {
1701         VMSTATE_INT32(rap, PCNetState),
1702         VMSTATE_INT32(isr, PCNetState),
1703         VMSTATE_INT32(lnkst, PCNetState),
1704         VMSTATE_UINT32(rdra, PCNetState),
1705         VMSTATE_UINT32(tdra, PCNetState),
1706         VMSTATE_BUFFER(prom, PCNetState),
1707         VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1708         VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1709         VMSTATE_UINT64(timer, PCNetState),
1710         VMSTATE_INT32(xmit_pos, PCNetState),
1711         VMSTATE_BUFFER(buffer, PCNetState),
1712         VMSTATE_UNUSED_TEST(is_version_2, 4),
1713         VMSTATE_INT32(tx_busy, PCNetState),
1714         VMSTATE_TIMER(poll_timer, PCNetState),
1715         VMSTATE_END_OF_LIST()
1716     }
1717 };
1718
1719 void pcnet_common_cleanup(PCNetState *d)
1720 {
1721     d->nic = NULL;
1722 }
1723
1724 int pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1725 {
1726     int i;
1727     uint16_t checksum;
1728
1729     s->poll_timer = qemu_new_timer_ns(vm_clock, pcnet_poll_timer, s);
1730
1731     qemu_macaddr_default_if_unset(&s->conf.macaddr);
1732     s->nic = qemu_new_nic(info, &s->conf, dev->info->name, dev->id, s);
1733     qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1734
1735     add_boot_device_path(s->conf.bootindex, dev, "/ethernet-phy@0");
1736
1737     /* Initialize the PROM */
1738
1739     /*
1740       Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1741       page 95
1742     */
1743     memcpy(s->prom, s->conf.macaddr.a, 6);
1744     /* Reserved Location: must be 00h */
1745     s->prom[6] = s->prom[7] = 0x00;
1746     /* Reserved Location: must be 00h */
1747     s->prom[8] = 0x00;
1748     /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1749     s->prom[9] = 0x11;
1750     /* User programmable space, init with 0 */
1751     s->prom[10] = s->prom[11] = 0x00;
1752     /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1753        and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1754     s->prom[12] = s->prom[13] = 0x00;
1755     /* Must be ASCII W (57h) if compatibility to AMD
1756        driver software is desired */
1757     s->prom[14] = s->prom[15] = 0x57;
1758
1759     for (i = 0, checksum = 0; i < 16; i++) {
1760         checksum += s->prom[i];
1761     }
1762     *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1763
1764     return 0;
1765 }
This page took 0.123282 seconds and 4 git commands to generate.