Statistics
| Branch: | Revision:

root / hw / pcnet.c @ 681f8c29

History | View | Annotate | Download (62.8 kB)

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