Statistics
| Branch: | Revision:

root / hw / pcnet.c @ c1ded3dc

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