Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 7cb7434b

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