Statistics
| Branch: | Revision:

root / hw / pcnet.c @ a46007a0

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