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