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