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