]> git.proxmox.com Git - qemu.git/blame - hw/pcnet.c
typo
[qemu.git] / hw / pcnet.c
CommitLineData
e3c2613f
FB
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
91cc0295
FB
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/* TODO: remove little endian host assumptions */
39
e3c2613f
FB
40#include "vl.h"
41
e3c2613f
FB
42//#define PCNET_DEBUG
43//#define PCNET_DEBUG_IO
44//#define PCNET_DEBUG_BCR
45//#define PCNET_DEBUG_CSR
46//#define PCNET_DEBUG_RMD
47//#define PCNET_DEBUG_TMD
48//#define PCNET_DEBUG_MATCH
49
50
51#define PCNET_IOPORT_SIZE 0x20
52#define PCNET_PNPMMIO_SIZE 0x20
53
54
55typedef struct PCNetState_st PCNetState;
56
57struct PCNetState_st {
58 PCIDevice dev;
91cc0295 59 PCIDevice *pci_dev;
e3c2613f
FB
60 VLANClientState *vc;
61 NICInfo *nd;
62 QEMUTimer *poll_timer;
91cc0295
FB
63 int mmio_index, rap, isr, lnkst;
64 uint32_t rdra, tdra;
e3c2613f
FB
65 uint8_t prom[16];
66 uint16_t csr[128];
67 uint16_t bcr[32];
68 uint64_t timer;
69 int xmit_pos, recv_pos;
70 uint8_t buffer[4096];
ec607da7 71 int tx_busy;
91cc0295
FB
72 void (*set_irq_cb)(void *s, int isr);
73 void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr,
74 uint8_t *buf, int len);
75 void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr,
76 uint8_t *buf, int len);
77 void *dma_opaque;
e3c2613f
FB
78};
79
29b9a345
FB
80/* XXX: using bitfields for target memory structures is almost surely
81 not portable, so it should be suppressed ASAP */
e3c2613f 82#ifdef __GNUC__
29b9a345 83#define PACKED_FIELD(A) A __attribute__ ((packed))
e3c2613f
FB
84#else
85#error FixMe
86#endif
87
219fb125
FB
88struct qemu_ether_header {
89 uint8_t ether_dhost[6];
90 uint8_t ether_shost[6];
91 uint16_t ether_type;
92};
93
e3c2613f
FB
94/* BUS CONFIGURATION REGISTERS */
95#define BCR_MSRDA 0
96#define BCR_MSWRA 1
97#define BCR_MC 2
98#define BCR_LNKST 4
99#define BCR_LED1 5
100#define BCR_LED2 6
101#define BCR_LED3 7
102#define BCR_FDC 9
103#define BCR_BSBC 18
104#define BCR_EECAS 19
105#define BCR_SWS 20
106#define BCR_PLAT 22
107
108#define BCR_DWIO(S) !!((S)->bcr[BCR_BSBC] & 0x0080)
109#define BCR_SSIZE32(S) !!((S)->bcr[BCR_SWS ] & 0x0100)
110#define BCR_SWSTYLE(S) ((S)->bcr[BCR_SWS ] & 0x00FF)
111
112#define CSR_INIT(S) !!(((S)->csr[0])&0x0001)
113#define CSR_STRT(S) !!(((S)->csr[0])&0x0002)
114#define CSR_STOP(S) !!(((S)->csr[0])&0x0004)
115#define CSR_TDMD(S) !!(((S)->csr[0])&0x0008)
116#define CSR_TXON(S) !!(((S)->csr[0])&0x0010)
117#define CSR_RXON(S) !!(((S)->csr[0])&0x0020)
118#define CSR_INEA(S) !!(((S)->csr[0])&0x0040)
91cc0295 119#define CSR_BIGENDIAN(S) !!(((S)->csr[3])&0x0004)
e3c2613f
FB
120#define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020)
121#define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040)
122#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
123#define CSR_DPOLL(S) !!(((S)->csr[4])&0x1000)
124#define CSR_SPND(S) !!(((S)->csr[5])&0x0001)
125#define CSR_LTINTEN(S) !!(((S)->csr[5])&0x4000)
126#define CSR_TOKINTD(S) !!(((S)->csr[5])&0x8000)
127#define CSR_DRX(S) !!(((S)->csr[15])&0x0001)
128#define CSR_DTX(S) !!(((S)->csr[15])&0x0002)
129#define CSR_LOOP(S) !!(((S)->csr[15])&0x0004)
130#define CSR_DRCVPA(S) !!(((S)->csr[15])&0x2000)
131#define CSR_DRCVBC(S) !!(((S)->csr[15])&0x4000)
132#define CSR_PROM(S) !!(((S)->csr[15])&0x8000)
133
134#define CSR_CRBC(S) ((S)->csr[40])
135#define CSR_CRST(S) ((S)->csr[41])
136#define CSR_CXBC(S) ((S)->csr[42])
137#define CSR_CXST(S) ((S)->csr[43])
138#define CSR_NRBC(S) ((S)->csr[44])
139#define CSR_NRST(S) ((S)->csr[45])
140#define CSR_POLL(S) ((S)->csr[46])
141#define CSR_PINT(S) ((S)->csr[47])
142#define CSR_RCVRC(S) ((S)->csr[72])
143#define CSR_XMTRC(S) ((S)->csr[74])
144#define CSR_RCVRL(S) ((S)->csr[76])
145#define CSR_XMTRL(S) ((S)->csr[78])
146#define CSR_MISSC(S) ((S)->csr[112])
147
148#define CSR_IADR(S) ((S)->csr[ 1] | ((S)->csr[ 2] << 16))
149#define CSR_CRBA(S) ((S)->csr[18] | ((S)->csr[19] << 16))
150#define CSR_CXBA(S) ((S)->csr[20] | ((S)->csr[21] << 16))
151#define CSR_NRBA(S) ((S)->csr[22] | ((S)->csr[23] << 16))
152#define CSR_BADR(S) ((S)->csr[24] | ((S)->csr[25] << 16))
153#define CSR_NRDA(S) ((S)->csr[26] | ((S)->csr[27] << 16))
154#define CSR_CRDA(S) ((S)->csr[28] | ((S)->csr[29] << 16))
155#define CSR_BADX(S) ((S)->csr[30] | ((S)->csr[31] << 16))
156#define CSR_NXDA(S) ((S)->csr[32] | ((S)->csr[33] << 16))
157#define CSR_CXDA(S) ((S)->csr[34] | ((S)->csr[35] << 16))
158#define CSR_NNRD(S) ((S)->csr[36] | ((S)->csr[37] << 16))
159#define CSR_NNXD(S) ((S)->csr[38] | ((S)->csr[39] << 16))
160#define CSR_PXDA(S) ((S)->csr[60] | ((S)->csr[61] << 16))
161#define CSR_NXBA(S) ((S)->csr[64] | ((S)->csr[65] << 16))
162
163#define PHYSADDR(S,A) \
164 (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(s)->csr[2])<<16))
165
166struct pcnet_initblk16 {
167 uint16_t mode;
91cc0295
FB
168 uint16_t padr[3];
169 uint16_t ladrf[4];
170 uint32_t rdra;
171 uint32_t tdra;
e3c2613f
FB
172};
173
174struct pcnet_initblk32 {
175 uint16_t mode;
91cc0295
FB
176 uint8_t rlen;
177 uint8_t tlen;
178 uint16_t padr[3];
e3c2613f 179 uint16_t _res;
91cc0295 180 uint16_t ladrf[4];
e3c2613f
FB
181 uint32_t rdra;
182 uint32_t tdra;
183};
184
185struct pcnet_TMD {
186 struct {
187 unsigned tbadr:32;
188 } tmd0;
189 struct {
29b9a345
FB
190 unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:7), PACKED_FIELD(bpe:1);
191 unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(def:1), PACKED_FIELD(one:1);
192 unsigned PACKED_FIELD(ltint:1), PACKED_FIELD(nofcs:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
e3c2613f
FB
193 } tmd1;
194 struct {
29b9a345
FB
195 unsigned PACKED_FIELD(trc:4), PACKED_FIELD(res:12);
196 unsigned PACKED_FIELD(tdr:10), PACKED_FIELD(rtry:1), PACKED_FIELD(lcar:1);
197 unsigned PACKED_FIELD(lcol:1), PACKED_FIELD(exdef:1), PACKED_FIELD(uflo:1), PACKED_FIELD(buff:1);
e3c2613f
FB
198 } tmd2;
199 struct {
200 unsigned res:32;
201 } tmd3;
202};
203
204struct pcnet_RMD {
205 struct {
206 unsigned rbadr:32;
207 } rmd0;
208 struct {
29b9a345
FB
209 unsigned PACKED_FIELD(bcnt:12), PACKED_FIELD(ones:4), PACKED_FIELD(res:4);
210 unsigned PACKED_FIELD(bam:1), PACKED_FIELD(lafm:1), PACKED_FIELD(pam:1), PACKED_FIELD(bpe:1);
211 unsigned PACKED_FIELD(enp:1), PACKED_FIELD(stp:1), PACKED_FIELD(buff:1), PACKED_FIELD(crc:1);
212 unsigned PACKED_FIELD(oflo:1), PACKED_FIELD(fram:1), PACKED_FIELD(err:1), PACKED_FIELD(own:1);
e3c2613f
FB
213 } rmd1;
214 struct {
29b9a345
FB
215 unsigned PACKED_FIELD(mcnt:12), PACKED_FIELD(zeros:4);
216 unsigned PACKED_FIELD(rpc:8), PACKED_FIELD(rcc:8);
e3c2613f
FB
217 } rmd2;
218 struct {
219 unsigned res:32;
220 } rmd3;
221};
222
223
224#define PRINT_TMD(T) printf( \
225 "TMD0 : TBADR=0x%08x\n" \
226 "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, " \
227 "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n" \
228 " BPE=%d, BCNT=%d\n" \
229 "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, " \
230 "LCA=%d, RTR=%d,\n" \
231 " TDR=%d, TRC=%d\n", \
232 (T)->tmd0.tbadr, \
233 (T)->tmd1.own, (T)->tmd1.err, (T)->tmd1.nofcs, \
234 (T)->tmd1.ltint, (T)->tmd1.one, (T)->tmd1.def, \
235 (T)->tmd1.stp, (T)->tmd1.enp, (T)->tmd1.bpe, \
236 4096-(T)->tmd1.bcnt, \
237 (T)->tmd2.buff, (T)->tmd2.uflo, (T)->tmd2.exdef,\
238 (T)->tmd2.lcol, (T)->tmd2.lcar, (T)->tmd2.rtry, \
239 (T)->tmd2.tdr, (T)->tmd2.trc)
240
241#define PRINT_RMD(R) printf( \
242 "RMD0 : RBADR=0x%08x\n" \
243 "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, " \
244 "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n " \
245 "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
246 "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n", \
247 (R)->rmd0.rbadr, \
248 (R)->rmd1.own, (R)->rmd1.err, (R)->rmd1.fram, \
249 (R)->rmd1.oflo, (R)->rmd1.crc, (R)->rmd1.buff, \
250 (R)->rmd1.stp, (R)->rmd1.enp, (R)->rmd1.bpe, \
251 (R)->rmd1.pam, (R)->rmd1.lafm, (R)->rmd1.bam, \
252 (R)->rmd1.ones, 4096-(R)->rmd1.bcnt, \
253 (R)->rmd2.rcc, (R)->rmd2.rpc, (R)->rmd2.mcnt, \
254 (R)->rmd2.zeros)
255
03c18475
FB
256static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd1,
257 target_phys_addr_t addr)
e3c2613f 258{
03c18475
FB
259 uint32_t *tmd = (uint32_t *)tmd1;
260
e3c2613f
FB
261 if (!BCR_SWSTYLE(s)) {
262 uint16_t xda[4];
91cc0295 263 s->phys_mem_read(s->dma_opaque, addr,
e3c2613f 264 (void *)&xda[0], sizeof(xda));
91cc0295 265 if (CSR_BIGENDIAN(s)) {
03c18475
FB
266 be16_to_cpus(&xda[0]);
267 be16_to_cpus(&xda[1]);
268 be16_to_cpus(&xda[2]);
269 be16_to_cpus(&xda[3]);
91cc0295 270 } else {
03c18475
FB
271 le16_to_cpus(&xda[0]);
272 le16_to_cpus(&xda[1]);
273 le16_to_cpus(&xda[2]);
274 le16_to_cpus(&xda[3]);
91cc0295 275 }
03c18475
FB
276
277 tmd[0] = (xda[0]&0xffff) |
278 ((xda[1]&0x00ff) << 16);
279 tmd[1] = (xda[2]&0xffff)|
280 ((xda[1] & 0xff00) << 16);
281 tmd[2] =
282 (xda[3] & 0xffff) << 16;
283 tmd[3] = 0;
284 } else {
e3c2613f 285 uint32_t xda[4];
91cc0295 286 s->phys_mem_read(s->dma_opaque, addr,
e3c2613f 287 (void *)&xda[0], sizeof(xda));
03c18475
FB
288 if (CSR_BIGENDIAN(s)) {
289 be32_to_cpus(&xda[0]);
290 be32_to_cpus(&xda[1]);
291 be32_to_cpus(&xda[2]);
292 be32_to_cpus(&xda[3]);
293 } else {
294 le32_to_cpus(&xda[0]);
295 le32_to_cpus(&xda[1]);
296 le32_to_cpus(&xda[2]);
297 le32_to_cpus(&xda[3]);
298 }
299 if (BCR_SWSTYLE(s) != 3) {
300 memcpy(tmd, xda, sizeof(xda));
301 } else {
302 tmd[0] = xda[2];
303 tmd[1] = xda[1];
304 tmd[2] = xda[0];
305 tmd[3] = xda[3];
306 }
e3c2613f
FB
307 }
308}
309
03c18475
FB
310static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd1,
311 target_phys_addr_t addr)
e3c2613f 312{
03c18475 313 const uint32_t *tmd = (const uint32_t *)tmd1;
e3c2613f
FB
314 if (!BCR_SWSTYLE(s)) {
315 uint16_t xda[4];
03c18475
FB
316 xda[0] = tmd[0] & 0xffff;
317 xda[1] = ((tmd[0]>>16)&0x00ff) |
318 ((tmd[1]>>16)&0xff00);
319 xda[2] = tmd[1] & 0xffff;
320 xda[3] = tmd[2] >> 16;
91cc0295 321 if (CSR_BIGENDIAN(s)) {
03c18475
FB
322 cpu_to_be16s(&xda[0]);
323 cpu_to_be16s(&xda[1]);
324 cpu_to_be16s(&xda[2]);
325 cpu_to_be16s(&xda[3]);
91cc0295 326 } else {
03c18475
FB
327 cpu_to_le16s(&xda[0]);
328 cpu_to_le16s(&xda[1]);
329 cpu_to_le16s(&xda[2]);
330 cpu_to_le16s(&xda[3]);
91cc0295
FB
331 }
332 s->phys_mem_write(s->dma_opaque, addr,
e3c2613f 333 (void *)&xda[0], sizeof(xda));
03c18475
FB
334 } else {
335 uint32_t xda[4];
336 if (BCR_SWSTYLE(s) != 3) {
337 memcpy(xda, tmd, sizeof(xda));
338 } else {
339 xda[0] = tmd[2];
340 xda[1] = tmd[1];
341 xda[2] = tmd[0];
342 xda[3] = tmd[3];
343 }
344 if (CSR_BIGENDIAN(s)) {
345 cpu_to_be32s(&xda[0]);
346 cpu_to_be32s(&xda[1]);
347 cpu_to_be32s(&xda[2]);
348 cpu_to_be32s(&xda[3]);
349 } else {
350 cpu_to_le32s(&xda[0]);
351 cpu_to_le32s(&xda[1]);
352 cpu_to_le32s(&xda[2]);
353 cpu_to_le32s(&xda[3]);
e3c2613f 354 }
03c18475
FB
355 s->phys_mem_write(s->dma_opaque, addr,
356 (void *)&xda[0], sizeof(xda));
e3c2613f
FB
357 }
358}
359
03c18475
FB
360static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd1,
361 target_phys_addr_t addr)
e3c2613f 362{
03c18475
FB
363 uint32_t *rmd = (uint32_t *)rmd1;
364
e3c2613f
FB
365 if (!BCR_SWSTYLE(s)) {
366 uint16_t rda[4];
03c18475 367 s->phys_mem_read(s->dma_opaque, addr, (void *)&rda[0], sizeof(rda));
91cc0295 368 if (CSR_BIGENDIAN(s)) {
03c18475
FB
369 be16_to_cpus(&rda[0]);
370 be16_to_cpus(&rda[1]);
371 be16_to_cpus(&rda[2]);
372 be16_to_cpus(&rda[3]);
91cc0295 373 } else {
03c18475
FB
374 le16_to_cpus(&rda[0]);
375 le16_to_cpus(&rda[1]);
376 le16_to_cpus(&rda[2]);
377 le16_to_cpus(&rda[3]);
91cc0295 378 }
03c18475
FB
379 rmd[0] = (rda[0]&0xffff)|
380 ((rda[1] & 0x00ff) << 16);
381 rmd[1] = (rda[2]&0xffff)|
382 ((rda[1] & 0xff00) << 16);
383 rmd[2] = rda[3] & 0xffff;
384 rmd[3] = 0;
385 } else {
e3c2613f 386 uint32_t rda[4];
03c18475
FB
387 s->phys_mem_read(s->dma_opaque, addr, (void *)&rda[0], sizeof(rda));
388 if (CSR_BIGENDIAN(s)) {
389 be32_to_cpus(&rda[0]);
390 be32_to_cpus(&rda[1]);
391 be32_to_cpus(&rda[2]);
392 be32_to_cpus(&rda[3]);
393 } else {
394 le32_to_cpus(&rda[0]);
395 le32_to_cpus(&rda[1]);
396 le32_to_cpus(&rda[2]);
397 le32_to_cpus(&rda[3]);
398 }
399 if (BCR_SWSTYLE(s) != 3) {
400 memcpy(rmd, rda, sizeof(rda));
401 } else {
402 rmd[0] = rda[2];
403 rmd[1] = rda[1];
404 rmd[2] = rda[0];
405 rmd[3] = rda[3];
406 }
e3c2613f
FB
407 }
408}
409
03c18475
FB
410static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd1,
411 target_phys_addr_t addr)
e3c2613f 412{
03c18475
FB
413 const uint32_t *rmd = (const uint32_t *)rmd1;
414
e3c2613f 415 if (!BCR_SWSTYLE(s)) {
91cc0295 416 uint16_t rda[4];
03c18475
FB
417 rda[0] = rmd[0] & 0xffff;
418 rda[1] = ((rmd[0]>>16)&0xff)|
419 ((rmd[1]>>16)&0xff00);
420 rda[2] = rmd[1] & 0xffff;
421 rda[3] = rmd[2] & 0xffff;
91cc0295 422 if (CSR_BIGENDIAN(s)) {
03c18475
FB
423 cpu_to_be16s(&rda[0]);
424 cpu_to_be16s(&rda[1]);
425 cpu_to_be16s(&rda[2]);
426 cpu_to_be16s(&rda[3]);
91cc0295 427 } else {
03c18475
FB
428 cpu_to_le16s(&rda[0]);
429 cpu_to_le16s(&rda[1]);
430 cpu_to_le16s(&rda[2]);
431 cpu_to_le16s(&rda[3]);
91cc0295
FB
432 }
433 s->phys_mem_write(s->dma_opaque, addr,
434 (void *)&rda[0], sizeof(rda));
03c18475
FB
435 } else {
436 uint32_t rda[4];
437 if (BCR_SWSTYLE(s) != 3) {
438 memcpy(rda, rmd, sizeof(rda));
439 } else {
440 rda[0] = rmd[2];
441 rda[1] = rmd[1];
442 rda[2] = rmd[0];
443 rda[3] = rmd[3];
e3c2613f 444 }
03c18475
FB
445 if (CSR_BIGENDIAN(s)) {
446 cpu_to_be32s(&rda[0]);
447 cpu_to_be32s(&rda[1]);
448 cpu_to_be32s(&rda[2]);
449 cpu_to_be32s(&rda[3]);
450 } else {
451 cpu_to_le32s(&rda[0]);
452 cpu_to_le32s(&rda[1]);
453 cpu_to_le32s(&rda[2]);
454 cpu_to_le32s(&rda[3]);
455 }
456 s->phys_mem_write(s->dma_opaque, addr,
457 (void *)&rda[0], sizeof(rda));
e3c2613f
FB
458 }
459}
460
461
462#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
463
464#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
465
466#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
467
468#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
469
470#if 1
471
472#define CHECK_RMD(ADDR,RES) do { \
473 struct pcnet_RMD rmd; \
474 RMDLOAD(&rmd,(ADDR)); \
475 (RES) |= (rmd.rmd1.ones != 15) \
476 || (rmd.rmd2.zeros != 0); \
477} while (0)
478
479#define CHECK_TMD(ADDR,RES) do { \
480 struct pcnet_TMD tmd; \
481 TMDLOAD(&tmd,(ADDR)); \
482 (RES) |= (tmd.tmd1.ones != 15); \
483} while (0)
484
485#else
486
487#define CHECK_RMD(ADDR,RES) do { \
488 switch (BCR_SWSTYLE(s)) { \
489 case 0x00: \
490 do { \
491 uint16_t rda[4]; \
91cc0295 492 s->phys_mem_read(s->dma_opaque, (ADDR), \
e3c2613f
FB
493 (void *)&rda[0], sizeof(rda)); \
494 (RES) |= (rda[2] & 0xf000)!=0xf000; \
495 (RES) |= (rda[3] & 0xf000)!=0x0000; \
496 } while (0); \
497 break; \
498 case 0x01: \
499 case 0x02: \
500 do { \
501 uint32_t rda[4]; \
91cc0295 502 s->phys_mem_read(s->dma_opaque, (ADDR), \
e3c2613f
FB
503 (void *)&rda[0], sizeof(rda)); \
504 (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
505 (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
506 } while (0); \
507 break; \
508 case 0x03: \
509 do { \
510 uint32_t rda[4]; \
91cc0295 511 s->phys_mem_read(s->dma_opaque, (ADDR), \
e3c2613f
FB
512 (void *)&rda[0], sizeof(rda)); \
513 (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
514 (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
515 } while (0); \
516 break; \
517 } \
518} while (0)
519
520#define CHECK_TMD(ADDR,RES) do { \
521 switch (BCR_SWSTYLE(s)) { \
522 case 0x00: \
523 do { \
524 uint16_t xda[4]; \
91cc0295 525 s->phys_mem_read(s->dma_opaque, (ADDR), \
e3c2613f
FB
526 (void *)&xda[0], sizeof(xda)); \
527 (RES) |= (xda[2] & 0xf000)!=0xf000;\
528 } while (0); \
529 break; \
530 case 0x01: \
531 case 0x02: \
532 case 0x03: \
533 do { \
534 uint32_t xda[4]; \
91cc0295 535 s->phys_mem_read(s->dma_opaque, (ADDR), \
e3c2613f
FB
536 (void *)&xda[0], sizeof(xda)); \
537 (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
538 } while (0); \
539 break; \
540 } \
541} while (0)
542
543#endif
544
545#define PRINT_PKTHDR(BUF) do { \
219fb125 546 struct qemu_ether_header *hdr = (void *)(BUF); \
e3c2613f
FB
547 printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
548 "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
549 "type=0x%04x (bcast=%d)\n", \
550 hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
551 hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
552 hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
553 hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
219fb125 554 be16_to_cpu(hdr->ether_type), \
e3c2613f
FB
555 !!ETHER_IS_MULTICAST(hdr->ether_dhost)); \
556} while (0)
557
558#define MULTICAST_FILTER_LEN 8
559
560static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
561{
562#define LNC_POLYNOMIAL 0xEDB88320UL
563 uint32_t crc = 0xFFFFFFFF;
564 int idx, bit;
565 uint8_t data;
566
219fb125 567 for (idx = 0; idx < 6; idx++) {
e3c2613f
FB
568 for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
569 crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
570 data >>= 1;
571 }
572 }
573 return crc;
574#undef LNC_POLYNOMIAL
575}
576
577#define CRC(crc, ch) (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
578
579/* generated using the AUTODIN II polynomial
580 * x^32 + x^26 + x^23 + x^22 + x^16 +
581 * x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
582 */
583static const uint32_t crctab[256] = {
584 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
585 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
586 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
587 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
588 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
589 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
590 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
591 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
592 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
593 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
594 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
595 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
596 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
597 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
598 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
599 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
600 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
601 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
602 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
603 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
604 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
605 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
606 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
607 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
608 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
609 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
610 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
611 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
612 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
613 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
614 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
615 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
616 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
617 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
618 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
619 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
620 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
621 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
622 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
623 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
624 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
625 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
626 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
627 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
628 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
629 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
630 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
631 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
632 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
633 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
634 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
635 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
636 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
637 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
638 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
639 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
640 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
641 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
642 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
643 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
644 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
645 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
646 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
647 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
648};
649
650static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
651{
219fb125 652 struct qemu_ether_header *hdr = (void *)buf;
e3c2613f
FB
653 uint8_t padr[6] = {
654 s->csr[12] & 0xff, s->csr[12] >> 8,
655 s->csr[13] & 0xff, s->csr[13] >> 8,
656 s->csr[14] & 0xff, s->csr[14] >> 8
657 };
29b9a345 658 int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
e3c2613f
FB
659#ifdef PCNET_DEBUG_MATCH
660 printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
661 "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
662 hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
663 hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
664 padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
665 printf("padr_match result=%d\n", result);
666#endif
667 return result;
668}
669
670static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
671{
672 static uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
219fb125 673 struct qemu_ether_header *hdr = (void *)buf;
29b9a345 674 int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
e3c2613f
FB
675#ifdef PCNET_DEBUG_MATCH
676 printf("padr_bcast result=%d\n", result);
677#endif
678 return result;
679}
680
681static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
682{
219fb125 683 struct qemu_ether_header *hdr = (void *)buf;
e3c2613f
FB
684 if ((*(hdr->ether_dhost)&0x01) &&
685 ((uint64_t *)&s->csr[8])[0] != 0LL) {
686 uint8_t ladr[8] = {
687 s->csr[8] & 0xff, s->csr[8] >> 8,
688 s->csr[9] & 0xff, s->csr[9] >> 8,
689 s->csr[10] & 0xff, s->csr[10] >> 8,
690 s->csr[11] & 0xff, s->csr[11] >> 8
691 };
692 int index = lnc_mchash(hdr->ether_dhost) >> 26;
693 return !!(ladr[index >> 3] & (1 << (index & 7)));
694 }
695 return 0;
696}
697
698static inline target_phys_addr_t pcnet_rdra_addr(PCNetState *s, int idx)
699{
700 while (idx < 1) idx += CSR_RCVRL(s);
701 return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
702}
703
704static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
705{
706 int64_t next_time = current_time +
707 muldiv64(65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s)),
708 ticks_per_sec, 33000000L);
709 if (next_time <= current_time)
710 next_time = current_time + 1;
711 return next_time;
712}
713
714static void pcnet_poll(PCNetState *s);
715static void pcnet_poll_timer(void *opaque);
716
717static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
718static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
719static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
720static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap);
721
722static void pcnet_s_reset(PCNetState *s)
723{
724#ifdef PCNET_DEBUG
725 printf("pcnet_s_reset\n");
726#endif
727
728 s->lnkst = 0x40;
729 s->rdra = 0;
730 s->tdra = 0;
731 s->rap = 0;
732
733 s->bcr[BCR_BSBC] &= ~0x0080;
734
735 s->csr[0] = 0x0004;
736 s->csr[3] = 0x0000;
737 s->csr[4] = 0x0115;
738 s->csr[5] = 0x0000;
739 s->csr[6] = 0x0000;
740 s->csr[8] = 0;
741 s->csr[9] = 0;
742 s->csr[10] = 0;
743 s->csr[11] = 0;
744 s->csr[12] = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
745 s->csr[13] = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
746 s->csr[14] = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
747 s->csr[15] &= 0x21c4;
748 s->csr[72] = 1;
749 s->csr[74] = 1;
750 s->csr[76] = 1;
751 s->csr[78] = 1;
752 s->csr[80] = 0x1410;
753 s->csr[88] = 0x1003;
754 s->csr[89] = 0x0262;
755 s->csr[94] = 0x0000;
756 s->csr[100] = 0x0200;
757 s->csr[103] = 0x0105;
758 s->csr[103] = 0x0105;
759 s->csr[112] = 0x0000;
760 s->csr[114] = 0x0000;
761 s->csr[122] = 0x0000;
762 s->csr[124] = 0x0000;
ec607da7
FB
763
764 s->tx_busy = 0;
e3c2613f
FB
765}
766
767static void pcnet_update_irq(PCNetState *s)
768{
769 int isr = 0;
770 s->csr[0] &= ~0x0080;
771
772#if 1
773 if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
774 (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
775 (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
776#else
777 if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
778 (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
779 (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
780 (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
781 (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
782 (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
783 (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
784 (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
785 (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
786 (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
787 (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
788 (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
789#endif
790 {
791
792 isr = CSR_INEA(s);
793 s->csr[0] |= 0x0080;
794 }
795
796 if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
797 s->csr[4] &= ~0x0080;
798 s->csr[4] |= 0x0040;
799 s->csr[0] |= 0x0080;
800 isr = 1;
801#ifdef PCNET_DEBUG
802 printf("pcnet user int\n");
803#endif
804 }
805
806#if 1
807 if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
808#else
809 if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
810 (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
811#endif
812 {
813 isr = 1;
814 s->csr[0] |= 0x0080;
815 }
816
817 if (isr != s->isr) {
818#ifdef PCNET_DEBUG
819 printf("pcnet: INTA=%d\n", isr);
820#endif
821 }
91cc0295
FB
822 s->set_irq_cb(s, isr);
823 s->isr = isr;
e3c2613f
FB
824}
825
826static void pcnet_init(PCNetState *s)
827{
91cc0295
FB
828 int rlen, tlen;
829 uint16_t *padr, *ladrf, mode;
830 uint32_t rdra, tdra;
831
e3c2613f
FB
832#ifdef PCNET_DEBUG
833 printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s)));
834#endif
835
e3c2613f
FB
836 if (BCR_SSIZE32(s)) {
837 struct pcnet_initblk32 initblk;
91cc0295
FB
838 s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
839 (uint8_t *)&initblk, sizeof(initblk));
840 mode = initblk.mode;
841 rlen = initblk.rlen >> 4;
842 tlen = initblk.tlen >> 4;
843 ladrf = initblk.ladrf;
844 padr = initblk.padr;
845 if (CSR_BIGENDIAN(s)) {
846 rdra = be32_to_cpu(initblk.rdra);
847 tdra = be32_to_cpu(initblk.tdra);
848 } else {
849 rdra = le32_to_cpu(initblk.rdra);
850 tdra = le32_to_cpu(initblk.tdra);
851 }
852 s->rdra = PHYSADDR(s,initblk.rdra);
853 s->tdra = PHYSADDR(s,initblk.tdra);
e3c2613f
FB
854 } else {
855 struct pcnet_initblk16 initblk;
91cc0295
FB
856 s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
857 (uint8_t *)&initblk, sizeof(initblk));
858 mode = initblk.mode;
859 ladrf = initblk.ladrf;
860 padr = initblk.padr;
861 if (CSR_BIGENDIAN(s)) {
862 rdra = be32_to_cpu(initblk.rdra);
863 tdra = be32_to_cpu(initblk.tdra);
864 } else {
865 rdra = le32_to_cpu(initblk.rdra);
866 tdra = le32_to_cpu(initblk.tdra);
867 }
868 rlen = rdra >> 29;
869 tlen = tdra >> 29;
870 rdra &= 0x00ffffff;
871 tdra &= 0x00ffffff;
872 }
873
874#if defined(PCNET_DEBUG)
875 printf("rlen=%d tlen=%d\n",
876 rlen, tlen);
e3c2613f 877#endif
91cc0295
FB
878 CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
879 CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
880 s->csr[ 6] = (tlen << 12) | (rlen << 8);
881 if (CSR_BIGENDIAN(s)) {
882 s->csr[15] = be16_to_cpu(mode);
883 s->csr[ 8] = be16_to_cpu(ladrf[0]);
884 s->csr[ 9] = be16_to_cpu(ladrf[1]);
885 s->csr[10] = be16_to_cpu(ladrf[2]);
886 s->csr[11] = be16_to_cpu(ladrf[3]);
887 s->csr[12] = be16_to_cpu(padr[0]);
888 s->csr[13] = be16_to_cpu(padr[1]);
889 s->csr[14] = be16_to_cpu(padr[2]);
890 } else {
891 s->csr[15] = le16_to_cpu(mode);
892 s->csr[ 8] = le16_to_cpu(ladrf[0]);
893 s->csr[ 9] = le16_to_cpu(ladrf[1]);
894 s->csr[10] = le16_to_cpu(ladrf[2]);
895 s->csr[11] = le16_to_cpu(ladrf[3]);
896 s->csr[12] = le16_to_cpu(padr[0]);
897 s->csr[13] = le16_to_cpu(padr[1]);
898 s->csr[14] = le16_to_cpu(padr[2]);
e3c2613f 899 }
91cc0295
FB
900 s->rdra = PHYSADDR(s, rdra);
901 s->tdra = PHYSADDR(s, tdra);
e3c2613f
FB
902
903 CSR_RCVRC(s) = CSR_RCVRL(s);
904 CSR_XMTRC(s) = CSR_XMTRL(s);
905
906#ifdef PCNET_DEBUG
907 printf("pcnet ss32=%d rdra=0x%08x[%d] tdra=0x%08x[%d]\n",
908 BCR_SSIZE32(s),
909 s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
910#endif
911
912 s->csr[0] |= 0x0101;
913 s->csr[0] &= ~0x0004; /* clear STOP bit */
914}
915
916static void pcnet_start(PCNetState *s)
917{
918#ifdef PCNET_DEBUG
919 printf("pcnet_start\n");
920#endif
921
922 if (!CSR_DTX(s))
923 s->csr[0] |= 0x0010; /* set TXON */
924
925 if (!CSR_DRX(s))
926 s->csr[0] |= 0x0020; /* set RXON */
927
928 s->csr[0] &= ~0x0004; /* clear STOP bit */
929 s->csr[0] |= 0x0002;
930}
931
932static void pcnet_stop(PCNetState *s)
933{
934#ifdef PCNET_DEBUG
935 printf("pcnet_stop\n");
936#endif
937 s->csr[0] &= ~0x7feb;
938 s->csr[0] |= 0x0014;
939 s->csr[4] &= ~0x02c2;
940 s->csr[5] &= ~0x0011;
941 pcnet_poll_timer(s);
942}
943
944static void pcnet_rdte_poll(PCNetState *s)
945{
946 s->csr[28] = s->csr[29] = 0;
947 if (s->rdra) {
948 int bad = 0;
949#if 1
950 target_phys_addr_t crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
951 target_phys_addr_t nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
952 target_phys_addr_t nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
953#else
954 target_phys_addr_t crda = s->rdra +
955 (CSR_RCVRL(s) - CSR_RCVRC(s)) *
956 (BCR_SWSTYLE(s) ? 16 : 8 );
957 int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
958 target_phys_addr_t nrda = s->rdra +
959 (CSR_RCVRL(s) - nrdc) *
960 (BCR_SWSTYLE(s) ? 16 : 8 );
961 int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
962 target_phys_addr_t nnrd = s->rdra +
963 (CSR_RCVRL(s) - nnrc) *
964 (BCR_SWSTYLE(s) ? 16 : 8 );
965#endif
966
967 CHECK_RMD(PHYSADDR(s,crda), bad);
968 if (!bad) {
969 CHECK_RMD(PHYSADDR(s,nrda), bad);
970 if (bad || (nrda == crda)) nrda = 0;
971 CHECK_RMD(PHYSADDR(s,nnrd), bad);
972 if (bad || (nnrd == crda)) nnrd = 0;
973
974 s->csr[28] = crda & 0xffff;
975 s->csr[29] = crda >> 16;
976 s->csr[26] = nrda & 0xffff;
977 s->csr[27] = nrda >> 16;
978 s->csr[36] = nnrd & 0xffff;
979 s->csr[37] = nnrd >> 16;
980#ifdef PCNET_DEBUG
981 if (bad) {
982 printf("pcnet: BAD RMD RECORDS AFTER 0x%08x\n",
983 PHYSADDR(s,crda));
984 }
985 } else {
986 printf("pcnet: BAD RMD RDA=0x%08x\n", PHYSADDR(s,crda));
987#endif
988 }
989 }
990
991 if (CSR_CRDA(s)) {
992 struct pcnet_RMD rmd;
993 RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
994 CSR_CRBC(s) = rmd.rmd1.bcnt;
995 CSR_CRST(s) = ((uint32_t *)&rmd)[1] >> 16;
996#ifdef PCNET_DEBUG_RMD_X
997 printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMD1=0x%08x RMD2=0x%08x\n",
998 PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
999 ((uint32_t *)&rmd)[1], ((uint32_t *)&rmd)[2]);
1000 PRINT_RMD(&rmd);
1001#endif
1002 } else {
1003 CSR_CRBC(s) = CSR_CRST(s) = 0;
1004 }
1005
1006 if (CSR_NRDA(s)) {
1007 struct pcnet_RMD rmd;
1008 RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
1009 CSR_NRBC(s) = rmd.rmd1.bcnt;
1010 CSR_NRST(s) = ((uint32_t *)&rmd)[1] >> 16;
1011 } else {
1012 CSR_NRBC(s) = CSR_NRST(s) = 0;
1013 }
1014
1015}
1016
1017static int pcnet_tdte_poll(PCNetState *s)
1018{
1019 s->csr[34] = s->csr[35] = 0;
1020 if (s->tdra) {
1021 target_phys_addr_t cxda = s->tdra +
1022 (CSR_XMTRL(s) - CSR_XMTRC(s)) *
1023 (BCR_SWSTYLE(s) ? 16 : 8 );
1024 int bad = 0;
1025 CHECK_TMD(PHYSADDR(s, cxda),bad);
1026 if (!bad) {
1027 if (CSR_CXDA(s) != cxda) {
1028 s->csr[60] = s->csr[34];
1029 s->csr[61] = s->csr[35];
1030 s->csr[62] = CSR_CXBC(s);
1031 s->csr[63] = CSR_CXST(s);
1032 }
1033 s->csr[34] = cxda & 0xffff;
1034 s->csr[35] = cxda >> 16;
1035#ifdef PCNET_DEBUG
1036 } else {
1037 printf("pcnet: BAD TMD XDA=0x%08x\n", PHYSADDR(s,cxda));
1038#endif
1039 }
1040 }
1041
1042 if (CSR_CXDA(s)) {
1043 struct pcnet_TMD tmd;
1044
1045 TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1046
1047 CSR_CXBC(s) = tmd.tmd1.bcnt;
1048 CSR_CXST(s) = ((uint32_t *)&tmd)[1] >> 16;
1049 } else {
1050 CSR_CXBC(s) = CSR_CXST(s) = 0;
1051 }
1052
1053 return !!(CSR_CXST(s) & 0x8000);
1054}
1055
1056static int pcnet_can_receive(void *opaque)
1057{
1058 PCNetState *s = opaque;
1059 if (CSR_STOP(s) || CSR_SPND(s))
1060 return 0;
1061
1062 if (s->recv_pos > 0)
1063 return 0;
1064
1065 return sizeof(s->buffer)-16;
1066}
1067
1068#define MIN_BUF_SIZE 60
1069
1070static void pcnet_receive(void *opaque, const uint8_t *buf, int size)
1071{
1072 PCNetState *s = opaque;
1073 int is_padr = 0, is_bcast = 0, is_ladr = 0;
1074 uint8_t buf1[60];
1075
1076 if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size)
1077 return;
1078
1079#ifdef PCNET_DEBUG
1080 printf("pcnet_receive size=%d\n", size);
1081#endif
1082
1083 /* if too small buffer, then expand it */
1084 if (size < MIN_BUF_SIZE) {
1085 memcpy(buf1, buf, size);
1086 memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1087 buf = buf1;
1088 size = MIN_BUF_SIZE;
1089 }
1090
1091 if (CSR_PROM(s)
1092 || (is_padr=padr_match(s, buf, size))
1093 || (is_bcast=padr_bcast(s, buf, size))
1094 || (is_ladr=ladr_match(s, buf, size))) {
1095
1096 pcnet_rdte_poll(s);
1097
1098 if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1099 struct pcnet_RMD rmd;
1100 int rcvrc = CSR_RCVRC(s)-1,i;
1101 target_phys_addr_t nrda;
1102 for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1103 if (rcvrc <= 1)
1104 rcvrc = CSR_RCVRL(s);
1105 nrda = s->rdra +
1106 (CSR_RCVRL(s) - rcvrc) *
1107 (BCR_SWSTYLE(s) ? 16 : 8 );
1108 RMDLOAD(&rmd, PHYSADDR(s,nrda));
1109 if (rmd.rmd1.own) {
1110#ifdef PCNET_DEBUG_RMD
1111 printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1112 rcvrc, CSR_RCVRC(s));
1113#endif
1114 CSR_RCVRC(s) = rcvrc;
1115 pcnet_rdte_poll(s);
1116 break;
1117 }
1118 }
1119 }
1120
1121 if (!(CSR_CRST(s) & 0x8000)) {
1122#ifdef PCNET_DEBUG_RMD
1123 printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1124#endif
1125 s->csr[0] |= 0x1000; /* Set MISS flag */
1126 CSR_MISSC(s)++;
1127 } else {
1128 uint8_t *src = &s->buffer[8];
1129 target_phys_addr_t crda = CSR_CRDA(s);
1130 struct pcnet_RMD rmd;
1131 int pktcount = 0;
1132
1133 memcpy(src, buf, size);
1134
219fb125
FB
1135#if 1
1136 /* no need to compute the CRC */
1137 src[size] = 0;
1138 src[size + 1] = 0;
1139 src[size + 2] = 0;
1140 src[size + 3] = 0;
1141 size += 4;
1142#else
e3c2613f
FB
1143 /* XXX: avoid CRC generation */
1144 if (!CSR_ASTRP_RCV(s)) {
1145 uint32_t fcs = ~0;
e3c2613f 1146 uint8_t *p = src;
e3c2613f
FB
1147
1148 while (size < 46) {
1149 src[size++] = 0;
1150 }
1151
1152 while (p != &src[size]) {
1153 CRC(fcs, *p++);
1154 }
1155 ((uint32_t *)&src[size])[0] = htonl(fcs);
1156 size += 4; /* FCS at end of packet */
1157 } else size += 4;
219fb125 1158#endif
e3c2613f
FB
1159
1160#ifdef PCNET_DEBUG_MATCH
1161 PRINT_PKTHDR(buf);
1162#endif
1163
1164 RMDLOAD(&rmd, PHYSADDR(s,crda));
1165 /*if (!CSR_LAPPEN(s))*/
1166 rmd.rmd1.stp = 1;
1167
1168#define PCNET_RECV_STORE() do { \
1169 int count = MIN(4096 - rmd.rmd1.bcnt,size); \
1170 target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \
91cc0295 1171 s->phys_mem_write(s->dma_opaque, rbadr, src, count); \
e3c2613f
FB
1172 src += count; size -= count; \
1173 rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \
1174 RMDSTORE(&rmd, PHYSADDR(s,crda)); \
1175 pktcount++; \
1176} while (0)
1177
1178 PCNET_RECV_STORE();
1179 if ((size > 0) && CSR_NRDA(s)) {
1180 target_phys_addr_t nrda = CSR_NRDA(s);
1181 RMDLOAD(&rmd, PHYSADDR(s,nrda));
1182 if (rmd.rmd1.own) {
1183 crda = nrda;
1184 PCNET_RECV_STORE();
1185 if ((size > 0) && (nrda=CSR_NNRD(s))) {
1186 RMDLOAD(&rmd, PHYSADDR(s,nrda));
1187 if (rmd.rmd1.own) {
1188 crda = nrda;
1189 PCNET_RECV_STORE();
1190 }
1191 }
1192 }
1193 }
1194
1195#undef PCNET_RECV_STORE
1196
1197 RMDLOAD(&rmd, PHYSADDR(s,crda));
1198 if (size == 0) {
1199 rmd.rmd1.enp = 1;
1200 rmd.rmd1.pam = !CSR_PROM(s) && is_padr;
1201 rmd.rmd1.lafm = !CSR_PROM(s) && is_ladr;
1202 rmd.rmd1.bam = !CSR_PROM(s) && is_bcast;
1203 } else {
1204 rmd.rmd1.oflo = 1;
1205 rmd.rmd1.buff = 1;
1206 rmd.rmd1.err = 1;
1207 }
1208 RMDSTORE(&rmd, PHYSADDR(s,crda));
1209 s->csr[0] |= 0x0400;
1210
1211#ifdef PCNET_DEBUG
1212 printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1213 CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1214#endif
1215#ifdef PCNET_DEBUG_RMD
1216 PRINT_RMD(&rmd);
1217#endif
1218
1219 while (pktcount--) {
1220 if (CSR_RCVRC(s) <= 1)
1221 CSR_RCVRC(s) = CSR_RCVRL(s);
1222 else
1223 CSR_RCVRC(s)--;
1224 }
1225
1226 pcnet_rdte_poll(s);
1227
1228 }
1229 }
1230
1231 pcnet_poll(s);
1232 pcnet_update_irq(s);
1233}
1234
1235static void pcnet_transmit(PCNetState *s)
1236{
1237 target_phys_addr_t xmit_cxda = 0;
1238 int count = CSR_XMTRL(s)-1;
1239 s->xmit_pos = -1;
1240
1241 if (!CSR_TXON(s)) {
1242 s->csr[0] &= ~0x0008;
1243 return;
1244 }
ec607da7
FB
1245
1246 s->tx_busy = 1;
1247
e3c2613f
FB
1248 txagain:
1249 if (pcnet_tdte_poll(s)) {
1250 struct pcnet_TMD tmd;
1251
1252 TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1253
1254#ifdef PCNET_DEBUG_TMD
1255 printf(" TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1256 PRINT_TMD(&tmd);
1257#endif
1258 if (tmd.tmd1.stp) {
1259 s->xmit_pos = 0;
1260 if (!tmd.tmd1.enp) {
91cc0295 1261 s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
e3c2613f
FB
1262 s->buffer, 4096 - tmd.tmd1.bcnt);
1263 s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1264 }
1265 xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1266 }
1267 if (tmd.tmd1.enp && (s->xmit_pos >= 0)) {
91cc0295 1268 s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr),
e3c2613f
FB
1269 s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt);
1270 s->xmit_pos += 4096 - tmd.tmd1.bcnt;
1271#ifdef PCNET_DEBUG
1272 printf("pcnet_transmit size=%d\n", s->xmit_pos);
1273#endif
1274 if (CSR_LOOP(s))
1275 pcnet_receive(s, s->buffer, s->xmit_pos);
1276 else
1277 qemu_send_packet(s->vc, s->buffer, s->xmit_pos);
1278
1279 s->csr[0] &= ~0x0008; /* clear TDMD */
1280 s->csr[4] |= 0x0004; /* set TXSTRT */
1281 s->xmit_pos = -1;
1282 }
1283
1284 tmd.tmd1.own = 0;
1285 TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1286 if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && tmd.tmd1.ltint))
1287 s->csr[0] |= 0x0200; /* set TINT */
1288
1289 if (CSR_XMTRC(s)<=1)
1290 CSR_XMTRC(s) = CSR_XMTRL(s);
1291 else
1292 CSR_XMTRC(s)--;
1293 if (count--)
1294 goto txagain;
1295
1296 } else
1297 if (s->xmit_pos >= 0) {
1298 struct pcnet_TMD tmd;
1299 TMDLOAD(&tmd, PHYSADDR(s,xmit_cxda));
1300 tmd.tmd2.buff = tmd.tmd2.uflo = tmd.tmd1.err = 1;
1301 tmd.tmd1.own = 0;
1302 TMDSTORE(&tmd, PHYSADDR(s,xmit_cxda));
1303 s->csr[0] |= 0x0200; /* set TINT */
1304 if (!CSR_DXSUFLO(s)) {
1305 s->csr[0] &= ~0x0010;
1306 } else
1307 if (count--)
1308 goto txagain;
1309 }
ec607da7
FB
1310
1311 s->tx_busy = 0;
e3c2613f
FB
1312}
1313
1314static void pcnet_poll(PCNetState *s)
1315{
1316 if (CSR_RXON(s)) {
1317 pcnet_rdte_poll(s);
1318 }
1319
1320 if (CSR_TDMD(s) ||
1321 (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
ec607da7
FB
1322 {
1323 /* prevent recursion */
1324 if (s->tx_busy)
1325 return;
1326
e3c2613f 1327 pcnet_transmit(s);
ec607da7 1328 }
e3c2613f
FB
1329}
1330
1331static void pcnet_poll_timer(void *opaque)
1332{
1333 PCNetState *s = opaque;
1334
1335 qemu_del_timer(s->poll_timer);
1336
1337 if (CSR_TDMD(s)) {
1338 pcnet_transmit(s);
1339 }
1340
1341 pcnet_update_irq(s);
1342
1343 if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1344 uint64_t now = qemu_get_clock(vm_clock) * 33;
1345 if (!s->timer || !now)
1346 s->timer = now;
1347 else {
1348 uint64_t t = now - s->timer + CSR_POLL(s);
1349 if (t > 0xffffLL) {
1350 pcnet_poll(s);
1351 CSR_POLL(s) = CSR_PINT(s);
1352 } else
1353 CSR_POLL(s) = t;
1354 }
1355 qemu_mod_timer(s->poll_timer,
1356 pcnet_get_next_poll_time(s,qemu_get_clock(vm_clock)));
1357 }
1358}
1359
1360
1361static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1362{
1363 uint16_t val = new_value;
1364#ifdef PCNET_DEBUG_CSR
1365 printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1366#endif
1367 switch (rap) {
1368 case 0:
1369 s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1370
1371 s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1372
1373 val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1374
1375 /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1376 if ((val&7) == 7)
1377 val &= ~3;
1378
1379 if (!CSR_STOP(s) && (val & 4))
1380 pcnet_stop(s);
1381
1382 if (!CSR_INIT(s) && (val & 1))
1383 pcnet_init(s);
1384
1385 if (!CSR_STRT(s) && (val & 2))
1386 pcnet_start(s);
1387
1388 if (CSR_TDMD(s))
1389 pcnet_transmit(s);
1390
1391 return;
1392 case 1:
1393 case 2:
1394 case 8:
1395 case 9:
1396 case 10:
1397 case 11:
1398 case 12:
1399 case 13:
1400 case 14:
1401 case 15:
1402 case 18: /* CRBAL */
1403 case 19: /* CRBAU */
1404 case 20: /* CXBAL */
1405 case 21: /* CXBAU */
1406 case 22: /* NRBAU */
1407 case 23: /* NRBAU */
1408 case 24:
1409 case 25:
1410 case 26:
1411 case 27:
1412 case 28:
1413 case 29:
1414 case 30:
1415 case 31:
1416 case 32:
1417 case 33:
1418 case 34:
1419 case 35:
1420 case 36:
1421 case 37:
1422 case 38:
1423 case 39:
1424 case 40: /* CRBC */
1425 case 41:
1426 case 42: /* CXBC */
1427 case 43:
1428 case 44:
1429 case 45:
1430 case 46: /* POLL */
1431 case 47: /* POLLINT */
1432 case 72:
1433 case 74:
1434 case 76: /* RCVRL */
1435 case 78: /* XMTRL */
1436 case 112:
1437 if (CSR_STOP(s) || CSR_SPND(s))
1438 break;
1439 return;
1440 case 3:
1441 break;
1442 case 4:
1443 s->csr[4] &= ~(val & 0x026a);
1444 val &= ~0x026a; val |= s->csr[4] & 0x026a;
1445 break;
1446 case 5:
1447 s->csr[5] &= ~(val & 0x0a90);
1448 val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1449 break;
1450 case 16:
1451 pcnet_csr_writew(s,1,val);
1452 return;
1453 case 17:
1454 pcnet_csr_writew(s,2,val);
1455 return;
1456 case 58:
1457 pcnet_bcr_writew(s,BCR_SWS,val);
1458 break;
1459 default:
1460 return;
1461 }
1462 s->csr[rap] = val;
1463}
1464
1465static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1466{
1467 uint32_t val;
1468 switch (rap) {
1469 case 0:
1470 pcnet_update_irq(s);
1471 val = s->csr[0];
1472 val |= (val & 0x7800) ? 0x8000 : 0;
1473 break;
1474 case 16:
1475 return pcnet_csr_readw(s,1);
1476 case 17:
1477 return pcnet_csr_readw(s,2);
1478 case 58:
1479 return pcnet_bcr_readw(s,BCR_SWS);
1480 case 88:
1481 val = s->csr[89];
1482 val <<= 16;
1483 val |= s->csr[88];
1484 break;
1485 default:
1486 val = s->csr[rap];
1487 }
1488#ifdef PCNET_DEBUG_CSR
1489 printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1490#endif
1491 return val;
1492}
1493
1494static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1495{
1496 rap &= 127;
1497#ifdef PCNET_DEBUG_BCR
1498 printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1499#endif
1500 switch (rap) {
1501 case BCR_SWS:
1502 if (!(CSR_STOP(s) || CSR_SPND(s)))
1503 return;
1504 val &= ~0x0300;
1505 switch (val & 0x00ff) {
1506 case 0:
1507 val |= 0x0200;
1508 break;
1509 case 1:
1510 val |= 0x0100;
1511 break;
1512 case 2:
1513 case 3:
1514 val |= 0x0300;
1515 break;
1516 default:
1517 printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1518 val = 0x0200;
1519 break;
1520 }
1521#ifdef PCNET_DEBUG
1522 printf("BCR_SWS=0x%04x\n", val);
1523#endif
1524 case BCR_LNKST:
1525 case BCR_LED1:
1526 case BCR_LED2:
1527 case BCR_LED3:
1528 case BCR_MC:
1529 case BCR_FDC:
1530 case BCR_BSBC:
1531 case BCR_EECAS:
1532 case BCR_PLAT:
1533 s->bcr[rap] = val;
1534 break;
1535 default:
1536 break;
1537 }
1538}
1539
1540static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1541{
1542 uint32_t val;
1543 rap &= 127;
1544 switch (rap) {
1545 case BCR_LNKST:
1546 case BCR_LED1:
1547 case BCR_LED2:
1548 case BCR_LED3:
1549 val = s->bcr[rap] & ~0x8000;
1550 val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1551 break;
1552 default:
1553 val = rap < 32 ? s->bcr[rap] : 0;
1554 break;
1555 }
1556#ifdef PCNET_DEBUG_BCR
1557 printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1558#endif
1559 return val;
1560}
1561
91cc0295 1562void pcnet_h_reset(void *opaque)
e3c2613f 1563{
91cc0295 1564 PCNetState *s = opaque;
e3c2613f
FB
1565 int i;
1566 uint16_t checksum;
1567
1568 /* Initialize the PROM */
1569
1570 memcpy(s->prom, s->nd->macaddr, 6);
1571 s->prom[12] = s->prom[13] = 0x00;
1572 s->prom[14] = s->prom[15] = 0x57;
1573
1574 for (i = 0,checksum = 0; i < 16; i++)
1575 checksum += s->prom[i];
1576 *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1577
1578
1579 s->bcr[BCR_MSRDA] = 0x0005;
1580 s->bcr[BCR_MSWRA] = 0x0005;
1581 s->bcr[BCR_MC ] = 0x0002;
1582 s->bcr[BCR_LNKST] = 0x00c0;
1583 s->bcr[BCR_LED1 ] = 0x0084;
1584 s->bcr[BCR_LED2 ] = 0x0088;
1585 s->bcr[BCR_LED3 ] = 0x0090;
1586 s->bcr[BCR_FDC ] = 0x0000;
1587 s->bcr[BCR_BSBC ] = 0x9001;
1588 s->bcr[BCR_EECAS] = 0x0002;
1589 s->bcr[BCR_SWS ] = 0x0200;
1590 s->bcr[BCR_PLAT ] = 0xff06;
1591
1592 pcnet_s_reset(s);
1593}
1594
1595static void pcnet_aprom_writeb(void *opaque, uint32_t addr, uint32_t val)
1596{
1597 PCNetState *s = opaque;
1598#ifdef PCNET_DEBUG
1599 printf("pcnet_aprom_writeb addr=0x%08x val=0x%02x\n", addr, val);
1600#endif
1601 /* Check APROMWE bit to enable write access */
1602 if (pcnet_bcr_readw(s,2) & 0x80)
1603 s->prom[addr & 15] = val;
1604}
1605
1606static uint32_t pcnet_aprom_readb(void *opaque, uint32_t addr)
1607{
1608 PCNetState *s = opaque;
1609 uint32_t val = s->prom[addr &= 15];
1610#ifdef PCNET_DEBUG
1611 printf("pcnet_aprom_readb addr=0x%08x val=0x%02x\n", addr, val);
1612#endif
1613 return val;
1614}
1615
1616static void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1617{
1618 PCNetState *s = opaque;
1619 pcnet_poll_timer(s);
1620#ifdef PCNET_DEBUG_IO
1621 printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1622#endif
1623 if (!BCR_DWIO(s)) {
1624 switch (addr & 0x0f) {
1625 case 0x00: /* RDP */
1626 pcnet_csr_writew(s, s->rap, val);
1627 break;
1628 case 0x02:
1629 s->rap = val & 0x7f;
1630 break;
1631 case 0x06:
1632 pcnet_bcr_writew(s, s->rap, val);
1633 break;
1634 }
1635 }
1636 pcnet_update_irq(s);
1637}
1638
1639static uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1640{
1641 PCNetState *s = opaque;
1642 uint32_t val = -1;
1643 pcnet_poll_timer(s);
1644 if (!BCR_DWIO(s)) {
1645 switch (addr & 0x0f) {
1646 case 0x00: /* RDP */
1647 val = pcnet_csr_readw(s, s->rap);
1648 break;
1649 case 0x02:
1650 val = s->rap;
1651 break;
1652 case 0x04:
1653 pcnet_s_reset(s);
1654 val = 0;
1655 break;
1656 case 0x06:
1657 val = pcnet_bcr_readw(s, s->rap);
1658 break;
1659 }
1660 }
1661 pcnet_update_irq(s);
1662#ifdef PCNET_DEBUG_IO
1663 printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1664#endif
1665 return val;
1666}
1667
1668static void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1669{
1670 PCNetState *s = opaque;
1671 pcnet_poll_timer(s);
1672#ifdef PCNET_DEBUG_IO
1673 printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1674#endif
1675 if (BCR_DWIO(s)) {
1676 switch (addr & 0x0f) {
1677 case 0x00: /* RDP */
1678 pcnet_csr_writew(s, s->rap, val & 0xffff);
1679 break;
1680 case 0x04:
1681 s->rap = val & 0x7f;
1682 break;
1683 case 0x0c:
1684 pcnet_bcr_writew(s, s->rap, val & 0xffff);
1685 break;
1686 }
1687 } else
1688 if ((addr & 0x0f) == 0) {
1689 /* switch device to dword i/o mode */
1690 pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1691#ifdef PCNET_DEBUG_IO
1692 printf("device switched into dword i/o mode\n");
1693#endif
1694 }
1695 pcnet_update_irq(s);
1696}
1697
1698static uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1699{
1700 PCNetState *s = opaque;
1701 uint32_t val = -1;
1702 pcnet_poll_timer(s);
1703 if (BCR_DWIO(s)) {
1704 switch (addr & 0x0f) {
1705 case 0x00: /* RDP */
1706 val = pcnet_csr_readw(s, s->rap);
1707 break;
1708 case 0x04:
1709 val = s->rap;
1710 break;
1711 case 0x08:
1712 pcnet_s_reset(s);
1713 val = 0;
1714 break;
1715 case 0x0c:
1716 val = pcnet_bcr_readw(s, s->rap);
1717 break;
1718 }
1719 }
1720 pcnet_update_irq(s);
1721#ifdef PCNET_DEBUG_IO
1722 printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1723#endif
1724 return val;
1725}
1726
1727static void pcnet_ioport_map(PCIDevice *pci_dev, int region_num,
1728 uint32_t addr, uint32_t size, int type)
1729{
1730 PCNetState *d = (PCNetState *)pci_dev;
1731
1732#ifdef PCNET_DEBUG_IO
1733 printf("pcnet_ioport_map addr=0x%04x size=0x%04x\n", addr, size);
1734#endif
1735
1736 register_ioport_write(addr, 16, 1, pcnet_aprom_writeb, d);
1737 register_ioport_read(addr, 16, 1, pcnet_aprom_readb, d);
1738
1739 register_ioport_write(addr + 0x10, 0x10, 2, pcnet_ioport_writew, d);
1740 register_ioport_read(addr + 0x10, 0x10, 2, pcnet_ioport_readw, d);
1741 register_ioport_write(addr + 0x10, 0x10, 4, pcnet_ioport_writel, d);
1742 register_ioport_read(addr + 0x10, 0x10, 4, pcnet_ioport_readl, d);
1743}
1744
1745static void pcnet_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1746{
1747 PCNetState *d = opaque;
1748#ifdef PCNET_DEBUG_IO
1749 printf("pcnet_mmio_writeb addr=0x%08x val=0x%02x\n", addr, val);
1750#endif
1751 if (!(addr & 0x10))
1752 pcnet_aprom_writeb(d, addr & 0x0f, val);
1753}
1754
1755static uint32_t pcnet_mmio_readb(void *opaque, target_phys_addr_t addr)
1756{
1757 PCNetState *d = opaque;
1758 uint32_t val = -1;
1759 if (!(addr & 0x10))
1760 val = pcnet_aprom_readb(d, addr & 0x0f);
1761#ifdef PCNET_DEBUG_IO
1762 printf("pcnet_mmio_readb addr=0x%08x val=0x%02x\n", addr, val & 0xff);
1763#endif
1764 return val;
1765}
1766
1767static void pcnet_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1768{
1769 PCNetState *d = opaque;
1770#ifdef PCNET_DEBUG_IO
1771 printf("pcnet_mmio_writew addr=0x%08x val=0x%04x\n", addr, val);
1772#endif
1773 if (addr & 0x10)
1774 pcnet_ioport_writew(d, addr & 0x0f, val);
1775 else {
1776 addr &= 0x0f;
1777 pcnet_aprom_writeb(d, addr, val & 0xff);
1778 pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1779 }
1780}
1781
1782static uint32_t pcnet_mmio_readw(void *opaque, target_phys_addr_t addr)
1783{
1784 PCNetState *d = opaque;
1785 uint32_t val = -1;
1786 if (addr & 0x10)
1787 val = pcnet_ioport_readw(d, addr & 0x0f);
1788 else {
1789 addr &= 0x0f;
1790 val = pcnet_aprom_readb(d, addr+1);
1791 val <<= 8;
1792 val |= pcnet_aprom_readb(d, addr);
1793 }
1794#ifdef PCNET_DEBUG_IO
1795 printf("pcnet_mmio_readw addr=0x%08x val = 0x%04x\n", addr, val & 0xffff);
1796#endif
1797 return val;
1798}
1799
1800static void pcnet_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1801{
1802 PCNetState *d = opaque;
1803#ifdef PCNET_DEBUG_IO
1804 printf("pcnet_mmio_writel addr=0x%08x val=0x%08x\n", addr, val);
1805#endif
1806 if (addr & 0x10)
1807 pcnet_ioport_writel(d, addr & 0x0f, val);
1808 else {
1809 addr &= 0x0f;
1810 pcnet_aprom_writeb(d, addr, val & 0xff);
1811 pcnet_aprom_writeb(d, addr+1, (val & 0xff00) >> 8);
1812 pcnet_aprom_writeb(d, addr+2, (val & 0xff0000) >> 16);
1813 pcnet_aprom_writeb(d, addr+3, (val & 0xff000000) >> 24);
1814 }
1815}
1816
1817static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr)
1818{
1819 PCNetState *d = opaque;
1820 uint32_t val;
1821 if (addr & 0x10)
1822 val = pcnet_ioport_readl(d, addr & 0x0f);
1823 else {
1824 addr &= 0x0f;
1825 val = pcnet_aprom_readb(d, addr+3);
1826 val <<= 8;
1827 val |= pcnet_aprom_readb(d, addr+2);
1828 val <<= 8;
1829 val |= pcnet_aprom_readb(d, addr+1);
1830 val <<= 8;
1831 val |= pcnet_aprom_readb(d, addr);
1832 }
1833#ifdef PCNET_DEBUG_IO
1834 printf("pcnet_mmio_readl addr=0x%08x val=0x%08x\n", addr, val);
1835#endif
1836 return val;
1837}
1838
1839
91cc0295
FB
1840static void pcnet_save(QEMUFile *f, void *opaque)
1841{
1842 PCNetState *s = opaque;
1843 unsigned int i;
1844
1845 if (s->pci_dev)
1846 pci_device_save(s->pci_dev, f);
1847
1848 qemu_put_be32s(f, &s->rap);
1849 qemu_put_be32s(f, &s->isr);
1850 qemu_put_be32s(f, &s->lnkst);
1851 qemu_put_be32s(f, &s->rdra);
1852 qemu_put_be32s(f, &s->tdra);
1853 qemu_put_buffer(f, s->prom, 16);
1854 for (i = 0; i < 128; i++)
1855 qemu_put_be16s(f, &s->csr[i]);
1856 for (i = 0; i < 32; i++)
1857 qemu_put_be16s(f, &s->bcr[i]);
1858 qemu_put_be64s(f, &s->timer);
1859 qemu_put_be32s(f, &s->xmit_pos);
1860 qemu_put_be32s(f, &s->recv_pos);
1861 qemu_put_buffer(f, s->buffer, 4096);
1862 qemu_put_be32s(f, &s->tx_busy);
1863 qemu_put_timer(f, s->poll_timer);
1864}
1865
1866static int pcnet_load(QEMUFile *f, void *opaque, int version_id)
1867{
1868 PCNetState *s = opaque;
1869 int i, ret;
1870
1871 if (version_id != 2)
1872 return -EINVAL;
1873
1874 if (s->pci_dev) {
1875 ret = pci_device_load(s->pci_dev, f);
1876 if (ret < 0)
1877 return ret;
1878 }
1879
1880 qemu_get_be32s(f, &s->rap);
1881 qemu_get_be32s(f, &s->isr);
1882 qemu_get_be32s(f, &s->lnkst);
1883 qemu_get_be32s(f, &s->rdra);
1884 qemu_get_be32s(f, &s->tdra);
1885 qemu_get_buffer(f, s->prom, 16);
1886 for (i = 0; i < 128; i++)
1887 qemu_get_be16s(f, &s->csr[i]);
1888 for (i = 0; i < 32; i++)
1889 qemu_get_be16s(f, &s->bcr[i]);
1890 qemu_get_be64s(f, &s->timer);
1891 qemu_get_be32s(f, &s->xmit_pos);
1892 qemu_get_be32s(f, &s->recv_pos);
1893 qemu_get_buffer(f, s->buffer, 4096);
1894 qemu_get_be32s(f, &s->tx_busy);
1895 qemu_get_timer(f, s->poll_timer);
1896
1897 return 0;
1898}
1899
1900static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str)
1901{
1902 d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d);
1903
1904 d->nd = nd;
1905
1906 d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive,
1907 pcnet_can_receive, d);
1908
1909 snprintf(d->vc->info_str, sizeof(d->vc->info_str),
1910 "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
1911 d->nd->macaddr[0],
1912 d->nd->macaddr[1],
1913 d->nd->macaddr[2],
1914 d->nd->macaddr[3],
1915 d->nd->macaddr[4],
1916 d->nd->macaddr[5]);
1917
1918 pcnet_h_reset(d);
1919 register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d);
1920}
1921
1922/* PCI interface */
1923
e3c2613f
FB
1924static CPUWriteMemoryFunc *pcnet_mmio_write[] = {
1925 (CPUWriteMemoryFunc *)&pcnet_mmio_writeb,
1926 (CPUWriteMemoryFunc *)&pcnet_mmio_writew,
1927 (CPUWriteMemoryFunc *)&pcnet_mmio_writel
1928};
1929
1930static CPUReadMemoryFunc *pcnet_mmio_read[] = {
1931 (CPUReadMemoryFunc *)&pcnet_mmio_readb,
1932 (CPUReadMemoryFunc *)&pcnet_mmio_readw,
1933 (CPUReadMemoryFunc *)&pcnet_mmio_readl
1934};
1935
1936static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num,
1937 uint32_t addr, uint32_t size, int type)
1938{
1939 PCNetState *d = (PCNetState *)pci_dev;
1940
1941#ifdef PCNET_DEBUG_IO
1942 printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size);
1943#endif
1944
91cc0295
FB
1945 cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index);
1946}
1947
1948static void pcnet_pci_set_irq_cb(void *opaque, int isr)
1949{
1950 PCNetState *s = opaque;
1951
1952 pci_set_irq(&s->dev, 0, isr);
1953}
1954
1955static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr,
1956 uint8_t *buf, int len)
1957{
1958 cpu_physical_memory_write(addr, buf, len);
1959}
1960
1961static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr,
1962 uint8_t *buf, int len)
1963{
1964 cpu_physical_memory_read(addr, buf, len);
e3c2613f
FB
1965}
1966
1967void pci_pcnet_init(PCIBus *bus, NICInfo *nd)
1968{
1969 PCNetState *d;
1970 uint8_t *pci_conf;
1971
1972#if 0
1973 printf("sizeof(RMD)=%d, sizeof(TMD)=%d\n",
1974 sizeof(struct pcnet_RMD), sizeof(struct pcnet_TMD));
1975#endif
1976
1977 d = (PCNetState *)pci_register_device(bus, "PCNet", sizeof(PCNetState),
1978 -1, NULL, NULL);
1979
1980 pci_conf = d->dev.config;
1981
1982 *(uint16_t *)&pci_conf[0x00] = cpu_to_le16(0x1022);
1983 *(uint16_t *)&pci_conf[0x02] = cpu_to_le16(0x2000);
1984 *(uint16_t *)&pci_conf[0x04] = cpu_to_le16(0x0007);
1985 *(uint16_t *)&pci_conf[0x06] = cpu_to_le16(0x0280);
1986 pci_conf[0x08] = 0x10;
1987 pci_conf[0x09] = 0x00;
1988 pci_conf[0x0a] = 0x00; // ethernet network controller
1989 pci_conf[0x0b] = 0x02;
1990 pci_conf[0x0e] = 0x00; // header_type
1991
1992 *(uint32_t *)&pci_conf[0x10] = cpu_to_le32(0x00000001);
1993 *(uint32_t *)&pci_conf[0x14] = cpu_to_le32(0x00000000);
1994
1995 pci_conf[0x3d] = 1; // interrupt pin 0
1996 pci_conf[0x3e] = 0x06;
1997 pci_conf[0x3f] = 0xff;
1998
1999 /* Handler for memory-mapped I/O */
91cc0295 2000 d->mmio_index =
e3c2613f
FB
2001 cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d);
2002
2003 pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE,
2004 PCI_ADDRESS_SPACE_IO, pcnet_ioport_map);
2005
2006 pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE,
2007 PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map);
2008
91cc0295
FB
2009 d->set_irq_cb = pcnet_pci_set_irq_cb;
2010 d->phys_mem_read = pci_physical_memory_read;
2011 d->phys_mem_write = pci_physical_memory_write;
2012 d->pci_dev = &d->dev;
e3c2613f 2013
91cc0295
FB
2014 pcnet_common_init(d, nd, "pcnet");
2015}
e3c2613f 2016
91cc0295 2017/* SPARC32 interface */
e3c2613f 2018
91cc0295
FB
2019#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure
2020
2021static CPUReadMemoryFunc *lance_mem_read[3] = {
2022 (CPUReadMemoryFunc *)&pcnet_ioport_readw,
2023 (CPUReadMemoryFunc *)&pcnet_ioport_readw,
2024 (CPUReadMemoryFunc *)&pcnet_ioport_readw,
2025};
2026
2027static CPUWriteMemoryFunc *lance_mem_write[3] = {
2028 (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
2029 (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
2030 (CPUWriteMemoryFunc *)&pcnet_ioport_writew,
2031};
2032
2033static void pcnet_sparc_set_irq_cb(void *opaque, int isr)
2034{
2035 PCNetState *s = opaque;
2036
2037 ledma_set_irq(s->dma_opaque, isr);
2038}
2039
2040void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque)
2041{
2042 PCNetState *d;
2043 int lance_io_memory;
2044
2045 d = qemu_mallocz(sizeof(PCNetState));
2046 if (!d)
2047 return NULL;
2048
2049 lance_io_memory =
2050 cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d);
2051
2052 d->dma_opaque = dma_opaque;
2053 cpu_register_physical_memory(leaddr, 4, lance_io_memory);
2054
2055 d->set_irq_cb = pcnet_sparc_set_irq_cb;
2056 d->phys_mem_read = ledma_memory_read;
2057 d->phys_mem_write = ledma_memory_write;
2058
2059 pcnet_common_init(d, nd, "lance");
2060
2061 return d;
e3c2613f 2062}
91cc0295 2063#endif /* TARGET_SPARC */