Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 5fafdf24

History | View | Annotate | Download (62.8 kB)

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