Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 03c18475

History | View | Annotate | Download (61.6 kB)

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