Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 0aab0d3a

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