Statistics
| Branch: | Revision:

root / hw / pcnet.c @ a2d4e44b

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