1 | /* |
2 | * Faraday FTGMAC100 Gigabit Ethernet |
3 | * |
4 | * Copyright (C) 2016-2017, IBM Corporation. |
5 | * |
6 | * Based on Coldfire Fast Ethernet Controller emulation. |
7 | * |
8 | * Copyright (c) 2007 CodeSourcery. |
9 | * |
10 | * This code is licensed under the GPL version 2 or later. See the |
11 | * COPYING file in the top-level directory. |
12 | */ |
13 | |
14 | #include "qemu/osdep.h" |
15 | #include "hw/irq.h" |
16 | #include "hw/net/ftgmac100.h" |
17 | #include "sysemu/dma.h" |
18 | #include "qemu/log.h" |
19 | #include "qemu/module.h" |
20 | #include "net/checksum.h" |
21 | #include "net/eth.h" |
22 | #include "hw/net/mii.h" |
23 | #include "hw/qdev-properties.h" |
24 | #include "migration/vmstate.h" |
25 | |
26 | /* For crc32 */ |
27 | #include <zlib.h> |
28 | |
29 | /* |
30 | * FTGMAC100 registers |
31 | */ |
32 | #define FTGMAC100_ISR 0x00 |
33 | #define FTGMAC100_IER 0x04 |
34 | #define FTGMAC100_MAC_MADR 0x08 |
35 | #define FTGMAC100_MAC_LADR 0x0c |
36 | #define FTGMAC100_MATH0 0x10 |
37 | #define FTGMAC100_MATH1 0x14 |
38 | #define FTGMAC100_NPTXPD 0x18 |
39 | #define FTGMAC100_RXPD 0x1C |
40 | #define FTGMAC100_NPTXR_BADR 0x20 |
41 | #define FTGMAC100_RXR_BADR 0x24 |
42 | #define FTGMAC100_HPTXPD 0x28 |
43 | #define FTGMAC100_HPTXR_BADR 0x2c |
44 | #define FTGMAC100_ITC 0x30 |
45 | #define FTGMAC100_APTC 0x34 |
46 | #define FTGMAC100_DBLAC 0x38 |
47 | #define FTGMAC100_REVR 0x40 |
48 | #define FTGMAC100_FEAR1 0x44 |
49 | #define FTGMAC100_RBSR 0x4c |
50 | #define FTGMAC100_TPAFCR 0x48 |
51 | |
52 | #define FTGMAC100_MACCR 0x50 |
53 | #define FTGMAC100_MACSR 0x54 |
54 | #define FTGMAC100_PHYCR 0x60 |
55 | #define FTGMAC100_PHYDATA 0x64 |
56 | #define FTGMAC100_FCR 0x68 |
57 | |
58 | /* |
59 | * Interrupt status register & interrupt enable register |
60 | */ |
61 | #define FTGMAC100_INT_RPKT_BUF (1 << 0) |
62 | #define FTGMAC100_INT_RPKT_FIFO (1 << 1) |
63 | #define FTGMAC100_INT_NO_RXBUF (1 << 2) |
64 | #define FTGMAC100_INT_RPKT_LOST (1 << 3) |
65 | #define FTGMAC100_INT_XPKT_ETH (1 << 4) |
66 | #define FTGMAC100_INT_XPKT_FIFO (1 << 5) |
67 | #define FTGMAC100_INT_NO_NPTXBUF (1 << 6) |
68 | #define FTGMAC100_INT_XPKT_LOST (1 << 7) |
69 | #define FTGMAC100_INT_AHB_ERR (1 << 8) |
70 | #define FTGMAC100_INT_PHYSTS_CHG (1 << 9) |
71 | #define FTGMAC100_INT_NO_HPTXBUF (1 << 10) |
72 | |
73 | /* |
74 | * Automatic polling timer control register |
75 | */ |
76 | #define FTGMAC100_APTC_RXPOLL_CNT(x) ((x) & 0xf) |
77 | #define FTGMAC100_APTC_RXPOLL_TIME_SEL (1 << 4) |
78 | #define FTGMAC100_APTC_TXPOLL_CNT(x) (((x) >> 8) & 0xf) |
79 | #define FTGMAC100_APTC_TXPOLL_TIME_SEL (1 << 12) |
80 | |
81 | /* |
82 | * PHY control register |
83 | */ |
84 | #define FTGMAC100_PHYCR_MIIRD (1 << 26) |
85 | #define FTGMAC100_PHYCR_MIIWR (1 << 27) |
86 | |
87 | #define FTGMAC100_PHYCR_DEV(x) (((x) >> 16) & 0x1f) |
88 | #define FTGMAC100_PHYCR_REG(x) (((x) >> 21) & 0x1f) |
89 | |
90 | /* |
91 | * PHY data register |
92 | */ |
93 | #define FTGMAC100_PHYDATA_MIIWDATA(x) ((x) & 0xffff) |
94 | #define FTGMAC100_PHYDATA_MIIRDATA(x) (((x) >> 16) & 0xffff) |
95 | |
96 | /* |
97 | * PHY control register - New MDC/MDIO interface |
98 | */ |
99 | #define FTGMAC100_PHYCR_NEW_DATA(x) (((x) >> 16) & 0xffff) |
100 | #define FTGMAC100_PHYCR_NEW_FIRE (1 << 15) |
101 | #define FTGMAC100_PHYCR_NEW_ST_22 (1 << 12) |
102 | #define FTGMAC100_PHYCR_NEW_OP(x) (((x) >> 10) & 3) |
103 | #define FTGMAC100_PHYCR_NEW_OP_WRITE 0x1 |
104 | #define FTGMAC100_PHYCR_NEW_OP_READ 0x2 |
105 | #define FTGMAC100_PHYCR_NEW_DEV(x) (((x) >> 5) & 0x1f) |
106 | #define FTGMAC100_PHYCR_NEW_REG(x) ((x) & 0x1f) |
107 | |
108 | /* |
109 | * Feature Register |
110 | */ |
111 | #define FTGMAC100_REVR_NEW_MDIO_INTERFACE (1 << 31) |
112 | |
113 | /* |
114 | * MAC control register |
115 | */ |
116 | #define FTGMAC100_MACCR_TXDMA_EN (1 << 0) |
117 | #define FTGMAC100_MACCR_RXDMA_EN (1 << 1) |
118 | #define FTGMAC100_MACCR_TXMAC_EN (1 << 2) |
119 | #define FTGMAC100_MACCR_RXMAC_EN (1 << 3) |
120 | #define FTGMAC100_MACCR_RM_VLAN (1 << 4) |
121 | #define FTGMAC100_MACCR_HPTXR_EN (1 << 5) |
122 | #define FTGMAC100_MACCR_LOOP_EN (1 << 6) |
123 | #define FTGMAC100_MACCR_ENRX_IN_HALFTX (1 << 7) |
124 | #define FTGMAC100_MACCR_FULLDUP (1 << 8) |
125 | #define FTGMAC100_MACCR_GIGA_MODE (1 << 9) |
126 | #define FTGMAC100_MACCR_CRC_APD (1 << 10) /* not needed */ |
127 | #define FTGMAC100_MACCR_RX_RUNT (1 << 12) |
128 | #define FTGMAC100_MACCR_JUMBO_LF (1 << 13) |
129 | #define FTGMAC100_MACCR_RX_ALL (1 << 14) |
130 | #define FTGMAC100_MACCR_HT_MULTI_EN (1 << 15) |
131 | #define FTGMAC100_MACCR_RX_MULTIPKT (1 << 16) |
132 | #define FTGMAC100_MACCR_RX_BROADPKT (1 << 17) |
133 | #define FTGMAC100_MACCR_DISCARD_CRCERR (1 << 18) |
134 | #define FTGMAC100_MACCR_FAST_MODE (1 << 19) |
135 | #define FTGMAC100_MACCR_SW_RST (1 << 31) |
136 | |
137 | /* |
138 | * Transmit descriptor |
139 | */ |
140 | #define FTGMAC100_TXDES0_TXBUF_SIZE(x) ((x) & 0x3fff) |
141 | #define FTGMAC100_TXDES0_EDOTR (1 << 15) |
142 | #define FTGMAC100_TXDES0_CRC_ERR (1 << 19) |
143 | #define FTGMAC100_TXDES0_LTS (1 << 28) |
144 | #define FTGMAC100_TXDES0_FTS (1 << 29) |
145 | #define FTGMAC100_TXDES0_EDOTR_ASPEED (1 << 30) |
146 | #define FTGMAC100_TXDES0_TXDMA_OWN (1 << 31) |
147 | |
148 | #define FTGMAC100_TXDES1_VLANTAG_CI(x) ((x) & 0xffff) |
149 | #define FTGMAC100_TXDES1_INS_VLANTAG (1 << 16) |
150 | #define FTGMAC100_TXDES1_TCP_CHKSUM (1 << 17) |
151 | #define FTGMAC100_TXDES1_UDP_CHKSUM (1 << 18) |
152 | #define FTGMAC100_TXDES1_IP_CHKSUM (1 << 19) |
153 | #define FTGMAC100_TXDES1_LLC (1 << 22) |
154 | #define FTGMAC100_TXDES1_TX2FIC (1 << 30) |
155 | #define FTGMAC100_TXDES1_TXIC (1 << 31) |
156 | |
157 | /* |
158 | * Receive descriptor |
159 | */ |
160 | #define FTGMAC100_RXDES0_VDBC 0x3fff |
161 | #define FTGMAC100_RXDES0_EDORR (1 << 15) |
162 | #define FTGMAC100_RXDES0_MULTICAST (1 << 16) |
163 | #define FTGMAC100_RXDES0_BROADCAST (1 << 17) |
164 | #define FTGMAC100_RXDES0_RX_ERR (1 << 18) |
165 | #define FTGMAC100_RXDES0_CRC_ERR (1 << 19) |
166 | #define FTGMAC100_RXDES0_FTL (1 << 20) |
167 | #define FTGMAC100_RXDES0_RUNT (1 << 21) |
168 | #define FTGMAC100_RXDES0_RX_ODD_NB (1 << 22) |
169 | #define FTGMAC100_RXDES0_FIFO_FULL (1 << 23) |
170 | #define FTGMAC100_RXDES0_PAUSE_OPCODE (1 << 24) |
171 | #define FTGMAC100_RXDES0_PAUSE_FRAME (1 << 25) |
172 | #define FTGMAC100_RXDES0_LRS (1 << 28) |
173 | #define FTGMAC100_RXDES0_FRS (1 << 29) |
174 | #define FTGMAC100_RXDES0_EDORR_ASPEED (1 << 30) |
175 | #define FTGMAC100_RXDES0_RXPKT_RDY (1 << 31) |
176 | |
177 | #define FTGMAC100_RXDES1_VLANTAG_CI 0xffff |
178 | #define FTGMAC100_RXDES1_PROT_MASK (0x3 << 20) |
179 | #define FTGMAC100_RXDES1_PROT_NONIP (0x0 << 20) |
180 | #define FTGMAC100_RXDES1_PROT_IP (0x1 << 20) |
181 | #define FTGMAC100_RXDES1_PROT_TCPIP (0x2 << 20) |
182 | #define FTGMAC100_RXDES1_PROT_UDPIP (0x3 << 20) |
183 | #define FTGMAC100_RXDES1_LLC (1 << 22) |
184 | #define FTGMAC100_RXDES1_DF (1 << 23) |
185 | #define FTGMAC100_RXDES1_VLANTAG_AVAIL (1 << 24) |
186 | #define FTGMAC100_RXDES1_TCP_CHKSUM_ERR (1 << 25) |
187 | #define FTGMAC100_RXDES1_UDP_CHKSUM_ERR (1 << 26) |
188 | #define FTGMAC100_RXDES1_IP_CHKSUM_ERR (1 << 27) |
189 | |
190 | /* |
191 | * Receive and transmit Buffer Descriptor |
192 | */ |
193 | typedef struct { |
194 | uint32_t des0; |
195 | uint32_t des1; |
196 | uint32_t des2; /* not used by HW */ |
197 | uint32_t des3; |
198 | } FTGMAC100Desc; |
199 | |
200 | /* |
201 | * Specific RTL8211E MII Registers |
202 | */ |
203 | #define RTL8211E_MII_PHYCR 16 /* PHY Specific Control */ |
204 | #define RTL8211E_MII_PHYSR 17 /* PHY Specific Status */ |
205 | #define RTL8211E_MII_INER 18 /* Interrupt Enable */ |
206 | #define RTL8211E_MII_INSR 19 /* Interrupt Status */ |
207 | #define RTL8211E_MII_RXERC 24 /* Receive Error Counter */ |
208 | #define RTL8211E_MII_LDPSR 27 /* Link Down Power Saving */ |
209 | #define RTL8211E_MII_EPAGSR 30 /* Extension Page Select */ |
210 | #define RTL8211E_MII_PAGSEL 31 /* Page Select */ |
211 | |
212 | /* |
213 | * RTL8211E Interrupt Status |
214 | */ |
215 | #define PHY_INT_AUTONEG_ERROR (1 << 15) |
216 | #define PHY_INT_PAGE_RECV (1 << 12) |
217 | #define PHY_INT_AUTONEG_COMPLETE (1 << 11) |
218 | #define PHY_INT_LINK_STATUS (1 << 10) |
219 | #define PHY_INT_ERROR (1 << 9) |
220 | #define PHY_INT_DOWN (1 << 8) |
221 | #define PHY_INT_JABBER (1 << 0) |
222 | |
223 | /* |
224 | * Max frame size for the receiving buffer |
225 | */ |
226 | #define FTGMAC100_MAX_FRAME_SIZE 9220 |
227 | |
228 | /* Limits depending on the type of the frame |
229 | * |
230 | * 9216 for Jumbo frames (+ 4 for VLAN) |
231 | * 1518 for other frames (+ 4 for VLAN) |
232 | */ |
233 | static int ftgmac100_max_frame_size(FTGMAC100State *s, uint16_t proto) |
234 | { |
235 | int max = (s->maccr & FTGMAC100_MACCR_JUMBO_LF ? 9216 : 1518); |
236 | |
237 | return max + (proto == ETH_P_VLAN ? 4 : 0); |
238 | } |
239 | |
240 | static void ftgmac100_update_irq(FTGMAC100State *s) |
241 | { |
242 | qemu_set_irq(s->irq, s->isr & s->ier); |
243 | } |
244 | |
245 | /* |
246 | * The MII phy could raise a GPIO to the processor which in turn |
247 | * could be handled as an interrpt by the OS. |
248 | * For now we don't handle any GPIO/interrupt line, so the OS will |
249 | * have to poll for the PHY status. |
250 | */ |
251 | static void phy_update_irq(FTGMAC100State *s) |
252 | { |
253 | ftgmac100_update_irq(s); |
254 | } |
255 | |
256 | static void phy_update_link(FTGMAC100State *s) |
257 | { |
258 | /* Autonegotiation status mirrors link status. */ |
259 | if (qemu_get_queue(s->nic)->link_down) { |
260 | s->phy_status &= ~(MII_BMSR_LINK_ST | MII_BMSR_AN_COMP); |
261 | s->phy_int |= PHY_INT_DOWN; |
262 | } else { |
263 | s->phy_status |= (MII_BMSR_LINK_ST | MII_BMSR_AN_COMP); |
264 | s->phy_int |= PHY_INT_AUTONEG_COMPLETE; |
265 | } |
266 | phy_update_irq(s); |
267 | } |
268 | |
269 | static void ftgmac100_set_link(NetClientState *nc) |
270 | { |
271 | phy_update_link(FTGMAC100(qemu_get_nic_opaque(nc))); |
272 | } |
273 | |
274 | static void phy_reset(FTGMAC100State *s) |
275 | { |
276 | s->phy_status = (MII_BMSR_100TX_FD | MII_BMSR_100TX_HD | MII_BMSR_10T_FD | |
277 | MII_BMSR_10T_HD | MII_BMSR_EXTSTAT | MII_BMSR_MFPS | |
278 | MII_BMSR_AN_COMP | MII_BMSR_AUTONEG | MII_BMSR_LINK_ST | |
279 | MII_BMSR_EXTCAP); |
280 | s->phy_control = (MII_BMCR_AUTOEN | MII_BMCR_FD | MII_BMCR_SPEED1000); |
281 | s->phy_advertise = (MII_ANAR_PAUSE_ASYM | MII_ANAR_PAUSE | MII_ANAR_TXFD | |
282 | MII_ANAR_TX | MII_ANAR_10FD | MII_ANAR_10 | |
283 | MII_ANAR_CSMACD); |
284 | s->phy_int_mask = 0; |
285 | s->phy_int = 0; |
286 | } |
287 | |
288 | static uint16_t do_phy_read(FTGMAC100State *s, uint8_t reg) |
289 | { |
290 | uint16_t val; |
291 | |
292 | switch (reg) { |
293 | case MII_BMCR: /* Basic Control */ |
294 | val = s->phy_control; |
295 | break; |
296 | case MII_BMSR: /* Basic Status */ |
297 | val = s->phy_status; |
298 | break; |
299 | case MII_PHYID1: /* ID1 */ |
300 | val = RTL8211E_PHYID1; |
301 | break; |
302 | case MII_PHYID2: /* ID2 */ |
303 | val = RTL8211E_PHYID2; |
304 | break; |
305 | case MII_ANAR: /* Auto-neg advertisement */ |
306 | val = s->phy_advertise; |
307 | break; |
308 | case MII_ANLPAR: /* Auto-neg Link Partner Ability */ |
309 | val = (MII_ANLPAR_ACK | MII_ANLPAR_PAUSE | MII_ANLPAR_TXFD | |
310 | MII_ANLPAR_TX | MII_ANLPAR_10FD | MII_ANLPAR_10 | |
311 | MII_ANLPAR_CSMACD); |
312 | break; |
313 | case MII_ANER: /* Auto-neg Expansion */ |
314 | val = MII_ANER_NWAY; |
315 | break; |
316 | case MII_CTRL1000: /* 1000BASE-T control */ |
317 | val = (MII_CTRL1000_HALF | MII_CTRL1000_FULL); |
318 | break; |
319 | case MII_STAT1000: /* 1000BASE-T status */ |
320 | val = MII_STAT1000_FULL; |
321 | break; |
322 | case RTL8211E_MII_INSR: /* Interrupt status. */ |
323 | val = s->phy_int; |
324 | s->phy_int = 0; |
325 | phy_update_irq(s); |
326 | break; |
327 | case RTL8211E_MII_INER: /* Interrupt enable */ |
328 | val = s->phy_int_mask; |
329 | break; |
330 | case RTL8211E_MII_PHYCR: |
331 | case RTL8211E_MII_PHYSR: |
332 | case RTL8211E_MII_RXERC: |
333 | case RTL8211E_MII_LDPSR: |
334 | case RTL8211E_MII_EPAGSR: |
335 | case RTL8211E_MII_PAGSEL: |
336 | qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n" , |
337 | __func__, reg); |
338 | val = 0; |
339 | break; |
340 | default: |
341 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n" , |
342 | __func__, reg); |
343 | val = 0; |
344 | break; |
345 | } |
346 | |
347 | return val; |
348 | } |
349 | |
350 | #define MII_BMCR_MASK (MII_BMCR_LOOPBACK | MII_BMCR_SPEED100 | \ |
351 | MII_BMCR_SPEED | MII_BMCR_AUTOEN | MII_BMCR_PDOWN | \ |
352 | MII_BMCR_FD | MII_BMCR_CTST) |
353 | #define MII_ANAR_MASK 0x2d7f |
354 | |
355 | static void do_phy_write(FTGMAC100State *s, uint8_t reg, uint16_t val) |
356 | { |
357 | switch (reg) { |
358 | case MII_BMCR: /* Basic Control */ |
359 | if (val & MII_BMCR_RESET) { |
360 | phy_reset(s); |
361 | } else { |
362 | s->phy_control = val & MII_BMCR_MASK; |
363 | /* Complete autonegotiation immediately. */ |
364 | if (val & MII_BMCR_AUTOEN) { |
365 | s->phy_status |= MII_BMSR_AN_COMP; |
366 | } |
367 | } |
368 | break; |
369 | case MII_ANAR: /* Auto-neg advertisement */ |
370 | s->phy_advertise = (val & MII_ANAR_MASK) | MII_ANAR_TX; |
371 | break; |
372 | case RTL8211E_MII_INER: /* Interrupt enable */ |
373 | s->phy_int_mask = val & 0xff; |
374 | phy_update_irq(s); |
375 | break; |
376 | case RTL8211E_MII_PHYCR: |
377 | case RTL8211E_MII_PHYSR: |
378 | case RTL8211E_MII_RXERC: |
379 | case RTL8211E_MII_LDPSR: |
380 | case RTL8211E_MII_EPAGSR: |
381 | case RTL8211E_MII_PAGSEL: |
382 | qemu_log_mask(LOG_UNIMP, "%s: reg %d not implemented\n" , |
383 | __func__, reg); |
384 | break; |
385 | default: |
386 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset %d\n" , |
387 | __func__, reg); |
388 | break; |
389 | } |
390 | } |
391 | |
392 | static void do_phy_new_ctl(FTGMAC100State *s) |
393 | { |
394 | uint8_t reg; |
395 | uint16_t data; |
396 | |
397 | if (!(s->phycr & FTGMAC100_PHYCR_NEW_ST_22)) { |
398 | qemu_log_mask(LOG_UNIMP, "%s: unsupported ST code\n" , __func__); |
399 | return; |
400 | } |
401 | |
402 | /* Nothing to do */ |
403 | if (!(s->phycr & FTGMAC100_PHYCR_NEW_FIRE)) { |
404 | return; |
405 | } |
406 | |
407 | reg = FTGMAC100_PHYCR_NEW_REG(s->phycr); |
408 | data = FTGMAC100_PHYCR_NEW_DATA(s->phycr); |
409 | |
410 | switch (FTGMAC100_PHYCR_NEW_OP(s->phycr)) { |
411 | case FTGMAC100_PHYCR_NEW_OP_WRITE: |
412 | do_phy_write(s, reg, data); |
413 | break; |
414 | case FTGMAC100_PHYCR_NEW_OP_READ: |
415 | s->phydata = do_phy_read(s, reg) & 0xffff; |
416 | break; |
417 | default: |
418 | qemu_log_mask(LOG_GUEST_ERROR, "%s: invalid OP code %08x\n" , |
419 | __func__, s->phycr); |
420 | } |
421 | |
422 | s->phycr &= ~FTGMAC100_PHYCR_NEW_FIRE; |
423 | } |
424 | |
425 | static void do_phy_ctl(FTGMAC100State *s) |
426 | { |
427 | uint8_t reg = FTGMAC100_PHYCR_REG(s->phycr); |
428 | |
429 | if (s->phycr & FTGMAC100_PHYCR_MIIWR) { |
430 | do_phy_write(s, reg, s->phydata & 0xffff); |
431 | s->phycr &= ~FTGMAC100_PHYCR_MIIWR; |
432 | } else if (s->phycr & FTGMAC100_PHYCR_MIIRD) { |
433 | s->phydata = do_phy_read(s, reg) << 16; |
434 | s->phycr &= ~FTGMAC100_PHYCR_MIIRD; |
435 | } else { |
436 | qemu_log_mask(LOG_GUEST_ERROR, "%s: no OP code %08x\n" , |
437 | __func__, s->phycr); |
438 | } |
439 | } |
440 | |
441 | static int ftgmac100_read_bd(FTGMAC100Desc *bd, dma_addr_t addr) |
442 | { |
443 | if (dma_memory_read(&address_space_memory, addr, bd, sizeof(*bd))) { |
444 | qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read descriptor @ 0x%" |
445 | HWADDR_PRIx "\n" , __func__, addr); |
446 | return -1; |
447 | } |
448 | bd->des0 = le32_to_cpu(bd->des0); |
449 | bd->des1 = le32_to_cpu(bd->des1); |
450 | bd->des2 = le32_to_cpu(bd->des2); |
451 | bd->des3 = le32_to_cpu(bd->des3); |
452 | return 0; |
453 | } |
454 | |
455 | static int ftgmac100_write_bd(FTGMAC100Desc *bd, dma_addr_t addr) |
456 | { |
457 | FTGMAC100Desc lebd; |
458 | |
459 | lebd.des0 = cpu_to_le32(bd->des0); |
460 | lebd.des1 = cpu_to_le32(bd->des1); |
461 | lebd.des2 = cpu_to_le32(bd->des2); |
462 | lebd.des3 = cpu_to_le32(bd->des3); |
463 | if (dma_memory_write(&address_space_memory, addr, &lebd, sizeof(lebd))) { |
464 | qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to write descriptor @ 0x%" |
465 | HWADDR_PRIx "\n" , __func__, addr); |
466 | return -1; |
467 | } |
468 | return 0; |
469 | } |
470 | |
471 | static void ftgmac100_do_tx(FTGMAC100State *s, uint32_t tx_ring, |
472 | uint32_t tx_descriptor) |
473 | { |
474 | int frame_size = 0; |
475 | uint8_t *ptr = s->frame; |
476 | uint32_t addr = tx_descriptor; |
477 | uint32_t flags = 0; |
478 | |
479 | while (1) { |
480 | FTGMAC100Desc bd; |
481 | int len; |
482 | |
483 | if (ftgmac100_read_bd(&bd, addr) || |
484 | ((bd.des0 & FTGMAC100_TXDES0_TXDMA_OWN) == 0)) { |
485 | /* Run out of descriptors to transmit. */ |
486 | s->isr |= FTGMAC100_INT_NO_NPTXBUF; |
487 | break; |
488 | } |
489 | |
490 | /* record transmit flags as they are valid only on the first |
491 | * segment */ |
492 | if (bd.des0 & FTGMAC100_TXDES0_FTS) { |
493 | flags = bd.des1; |
494 | } |
495 | |
496 | len = FTGMAC100_TXDES0_TXBUF_SIZE(bd.des0); |
497 | if (frame_size + len > sizeof(s->frame)) { |
498 | qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n" , |
499 | __func__, len); |
500 | s->isr |= FTGMAC100_INT_XPKT_LOST; |
501 | len = sizeof(s->frame) - frame_size; |
502 | } |
503 | |
504 | if (dma_memory_read(&address_space_memory, bd.des3, ptr, len)) { |
505 | qemu_log_mask(LOG_GUEST_ERROR, "%s: failed to read packet @ 0x%x\n" , |
506 | __func__, bd.des3); |
507 | s->isr |= FTGMAC100_INT_NO_NPTXBUF; |
508 | break; |
509 | } |
510 | |
511 | /* Check for VLAN */ |
512 | if (bd.des0 & FTGMAC100_TXDES0_FTS && |
513 | bd.des1 & FTGMAC100_TXDES1_INS_VLANTAG && |
514 | be16_to_cpu(PKT_GET_ETH_HDR(ptr)->h_proto) != ETH_P_VLAN) { |
515 | if (frame_size + len + 4 > sizeof(s->frame)) { |
516 | qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %d bytes\n" , |
517 | __func__, len); |
518 | s->isr |= FTGMAC100_INT_XPKT_LOST; |
519 | len = sizeof(s->frame) - frame_size - 4; |
520 | } |
521 | memmove(ptr + 16, ptr + 12, len - 12); |
522 | stw_be_p(ptr + 12, ETH_P_VLAN); |
523 | stw_be_p(ptr + 14, bd.des1); |
524 | len += 4; |
525 | } |
526 | |
527 | ptr += len; |
528 | frame_size += len; |
529 | if (bd.des0 & FTGMAC100_TXDES0_LTS) { |
530 | if (flags & FTGMAC100_TXDES1_IP_CHKSUM) { |
531 | net_checksum_calculate(s->frame, frame_size); |
532 | } |
533 | /* Last buffer in frame. */ |
534 | qemu_send_packet(qemu_get_queue(s->nic), s->frame, frame_size); |
535 | ptr = s->frame; |
536 | frame_size = 0; |
537 | if (flags & FTGMAC100_TXDES1_TXIC) { |
538 | s->isr |= FTGMAC100_INT_XPKT_ETH; |
539 | } |
540 | } |
541 | |
542 | if (flags & FTGMAC100_TXDES1_TX2FIC) { |
543 | s->isr |= FTGMAC100_INT_XPKT_FIFO; |
544 | } |
545 | bd.des0 &= ~FTGMAC100_TXDES0_TXDMA_OWN; |
546 | |
547 | /* Write back the modified descriptor. */ |
548 | ftgmac100_write_bd(&bd, addr); |
549 | /* Advance to the next descriptor. */ |
550 | if (bd.des0 & s->txdes0_edotr) { |
551 | addr = tx_ring; |
552 | } else { |
553 | addr += sizeof(FTGMAC100Desc); |
554 | } |
555 | } |
556 | |
557 | s->tx_descriptor = addr; |
558 | |
559 | ftgmac100_update_irq(s); |
560 | } |
561 | |
562 | static int ftgmac100_can_receive(NetClientState *nc) |
563 | { |
564 | FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc)); |
565 | FTGMAC100Desc bd; |
566 | |
567 | if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) |
568 | != (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) { |
569 | return 0; |
570 | } |
571 | |
572 | if (ftgmac100_read_bd(&bd, s->rx_descriptor)) { |
573 | return 0; |
574 | } |
575 | return !(bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY); |
576 | } |
577 | |
578 | /* |
579 | * This is purely informative. The HW can poll the RW (and RX) ring |
580 | * buffers for available descriptors but we don't need to trigger a |
581 | * timer for that in qemu. |
582 | */ |
583 | static uint32_t ftgmac100_rxpoll(FTGMAC100State *s) |
584 | { |
585 | /* Polling times : |
586 | * |
587 | * Speed TIME_SEL=0 TIME_SEL=1 |
588 | * |
589 | * 10 51.2 ms 819.2 ms |
590 | * 100 5.12 ms 81.92 ms |
591 | * 1000 1.024 ms 16.384 ms |
592 | */ |
593 | static const int div[] = { 20, 200, 1000 }; |
594 | |
595 | uint32_t cnt = 1024 * FTGMAC100_APTC_RXPOLL_CNT(s->aptcr); |
596 | uint32_t speed = (s->maccr & FTGMAC100_MACCR_FAST_MODE) ? 1 : 0; |
597 | |
598 | if (s->aptcr & FTGMAC100_APTC_RXPOLL_TIME_SEL) { |
599 | cnt <<= 4; |
600 | } |
601 | |
602 | if (s->maccr & FTGMAC100_MACCR_GIGA_MODE) { |
603 | speed = 2; |
604 | } |
605 | |
606 | return cnt / div[speed]; |
607 | } |
608 | |
609 | static void ftgmac100_reset(DeviceState *d) |
610 | { |
611 | FTGMAC100State *s = FTGMAC100(d); |
612 | |
613 | /* Reset the FTGMAC100 */ |
614 | s->isr = 0; |
615 | s->ier = 0; |
616 | s->rx_enabled = 0; |
617 | s->rx_ring = 0; |
618 | s->rbsr = 0x640; |
619 | s->rx_descriptor = 0; |
620 | s->tx_ring = 0; |
621 | s->tx_descriptor = 0; |
622 | s->math[0] = 0; |
623 | s->math[1] = 0; |
624 | s->itc = 0; |
625 | s->aptcr = 1; |
626 | s->dblac = 0x00022f00; |
627 | s->revr = 0; |
628 | s->fear1 = 0; |
629 | s->tpafcr = 0xf1; |
630 | |
631 | s->maccr = 0; |
632 | s->phycr = 0; |
633 | s->phydata = 0; |
634 | s->fcr = 0x400; |
635 | |
636 | /* and the PHY */ |
637 | phy_reset(s); |
638 | } |
639 | |
640 | static uint64_t ftgmac100_read(void *opaque, hwaddr addr, unsigned size) |
641 | { |
642 | FTGMAC100State *s = FTGMAC100(opaque); |
643 | |
644 | switch (addr & 0xff) { |
645 | case FTGMAC100_ISR: |
646 | return s->isr; |
647 | case FTGMAC100_IER: |
648 | return s->ier; |
649 | case FTGMAC100_MAC_MADR: |
650 | return (s->conf.macaddr.a[0] << 8) | s->conf.macaddr.a[1]; |
651 | case FTGMAC100_MAC_LADR: |
652 | return ((uint32_t) s->conf.macaddr.a[2] << 24) | |
653 | (s->conf.macaddr.a[3] << 16) | (s->conf.macaddr.a[4] << 8) | |
654 | s->conf.macaddr.a[5]; |
655 | case FTGMAC100_MATH0: |
656 | return s->math[0]; |
657 | case FTGMAC100_MATH1: |
658 | return s->math[1]; |
659 | case FTGMAC100_ITC: |
660 | return s->itc; |
661 | case FTGMAC100_DBLAC: |
662 | return s->dblac; |
663 | case FTGMAC100_REVR: |
664 | return s->revr; |
665 | case FTGMAC100_FEAR1: |
666 | return s->fear1; |
667 | case FTGMAC100_TPAFCR: |
668 | return s->tpafcr; |
669 | case FTGMAC100_FCR: |
670 | return s->fcr; |
671 | case FTGMAC100_MACCR: |
672 | return s->maccr; |
673 | case FTGMAC100_PHYCR: |
674 | return s->phycr; |
675 | case FTGMAC100_PHYDATA: |
676 | return s->phydata; |
677 | |
678 | /* We might want to support these one day */ |
679 | case FTGMAC100_HPTXPD: /* High Priority Transmit Poll Demand */ |
680 | case FTGMAC100_HPTXR_BADR: /* High Priority Transmit Ring Base Address */ |
681 | case FTGMAC100_MACSR: /* MAC Status Register (MACSR) */ |
682 | qemu_log_mask(LOG_UNIMP, "%s: read to unimplemented register 0x%" |
683 | HWADDR_PRIx "\n" , __func__, addr); |
684 | return 0; |
685 | default: |
686 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%" |
687 | HWADDR_PRIx "\n" , __func__, addr); |
688 | return 0; |
689 | } |
690 | } |
691 | |
692 | static void ftgmac100_write(void *opaque, hwaddr addr, |
693 | uint64_t value, unsigned size) |
694 | { |
695 | FTGMAC100State *s = FTGMAC100(opaque); |
696 | |
697 | switch (addr & 0xff) { |
698 | case FTGMAC100_ISR: /* Interrupt status */ |
699 | s->isr &= ~value; |
700 | break; |
701 | case FTGMAC100_IER: /* Interrupt control */ |
702 | s->ier = value; |
703 | break; |
704 | case FTGMAC100_MAC_MADR: /* MAC */ |
705 | s->conf.macaddr.a[0] = value >> 8; |
706 | s->conf.macaddr.a[1] = value; |
707 | break; |
708 | case FTGMAC100_MAC_LADR: |
709 | s->conf.macaddr.a[2] = value >> 24; |
710 | s->conf.macaddr.a[3] = value >> 16; |
711 | s->conf.macaddr.a[4] = value >> 8; |
712 | s->conf.macaddr.a[5] = value; |
713 | break; |
714 | case FTGMAC100_MATH0: /* Multicast Address Hash Table 0 */ |
715 | s->math[0] = value; |
716 | break; |
717 | case FTGMAC100_MATH1: /* Multicast Address Hash Table 1 */ |
718 | s->math[1] = value; |
719 | break; |
720 | case FTGMAC100_ITC: /* TODO: Interrupt Timer Control */ |
721 | s->itc = value; |
722 | break; |
723 | case FTGMAC100_RXR_BADR: /* Ring buffer address */ |
724 | s->rx_ring = value; |
725 | s->rx_descriptor = s->rx_ring; |
726 | break; |
727 | |
728 | case FTGMAC100_RBSR: /* DMA buffer size */ |
729 | s->rbsr = value; |
730 | break; |
731 | |
732 | case FTGMAC100_NPTXR_BADR: /* Transmit buffer address */ |
733 | s->tx_ring = value; |
734 | s->tx_descriptor = s->tx_ring; |
735 | break; |
736 | |
737 | case FTGMAC100_NPTXPD: /* Trigger transmit */ |
738 | if ((s->maccr & (FTGMAC100_MACCR_TXDMA_EN | FTGMAC100_MACCR_TXMAC_EN)) |
739 | == (FTGMAC100_MACCR_TXDMA_EN | FTGMAC100_MACCR_TXMAC_EN)) { |
740 | /* TODO: high priority tx ring */ |
741 | ftgmac100_do_tx(s, s->tx_ring, s->tx_descriptor); |
742 | } |
743 | if (ftgmac100_can_receive(qemu_get_queue(s->nic))) { |
744 | qemu_flush_queued_packets(qemu_get_queue(s->nic)); |
745 | } |
746 | break; |
747 | |
748 | case FTGMAC100_RXPD: /* Receive Poll Demand Register */ |
749 | if (ftgmac100_can_receive(qemu_get_queue(s->nic))) { |
750 | qemu_flush_queued_packets(qemu_get_queue(s->nic)); |
751 | } |
752 | break; |
753 | |
754 | case FTGMAC100_APTC: /* Automatic polling */ |
755 | s->aptcr = value; |
756 | |
757 | if (FTGMAC100_APTC_RXPOLL_CNT(s->aptcr)) { |
758 | ftgmac100_rxpoll(s); |
759 | } |
760 | |
761 | if (FTGMAC100_APTC_TXPOLL_CNT(s->aptcr)) { |
762 | qemu_log_mask(LOG_UNIMP, "%s: no transmit polling\n" , __func__); |
763 | } |
764 | break; |
765 | |
766 | case FTGMAC100_MACCR: /* MAC Device control */ |
767 | s->maccr = value; |
768 | if (value & FTGMAC100_MACCR_SW_RST) { |
769 | ftgmac100_reset(DEVICE(s)); |
770 | } |
771 | |
772 | if (ftgmac100_can_receive(qemu_get_queue(s->nic))) { |
773 | qemu_flush_queued_packets(qemu_get_queue(s->nic)); |
774 | } |
775 | break; |
776 | |
777 | case FTGMAC100_PHYCR: /* PHY Device control */ |
778 | s->phycr = value; |
779 | if (s->revr & FTGMAC100_REVR_NEW_MDIO_INTERFACE) { |
780 | do_phy_new_ctl(s); |
781 | } else { |
782 | do_phy_ctl(s); |
783 | } |
784 | break; |
785 | case FTGMAC100_PHYDATA: |
786 | s->phydata = value & 0xffff; |
787 | break; |
788 | case FTGMAC100_DBLAC: /* DMA Burst Length and Arbitration Control */ |
789 | s->dblac = value; |
790 | break; |
791 | case FTGMAC100_REVR: /* Feature Register */ |
792 | s->revr = value; |
793 | break; |
794 | case FTGMAC100_FEAR1: /* Feature Register 1 */ |
795 | s->fear1 = value; |
796 | break; |
797 | case FTGMAC100_TPAFCR: /* Transmit Priority Arbitration and FIFO Control */ |
798 | s->tpafcr = value; |
799 | break; |
800 | case FTGMAC100_FCR: /* Flow Control */ |
801 | s->fcr = value; |
802 | break; |
803 | |
804 | case FTGMAC100_HPTXPD: /* High Priority Transmit Poll Demand */ |
805 | case FTGMAC100_HPTXR_BADR: /* High Priority Transmit Ring Base Address */ |
806 | case FTGMAC100_MACSR: /* MAC Status Register (MACSR) */ |
807 | qemu_log_mask(LOG_UNIMP, "%s: write to unimplemented register 0x%" |
808 | HWADDR_PRIx "\n" , __func__, addr); |
809 | break; |
810 | default: |
811 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bad address at offset 0x%" |
812 | HWADDR_PRIx "\n" , __func__, addr); |
813 | break; |
814 | } |
815 | |
816 | ftgmac100_update_irq(s); |
817 | } |
818 | |
819 | static int ftgmac100_filter(FTGMAC100State *s, const uint8_t *buf, size_t len) |
820 | { |
821 | unsigned mcast_idx; |
822 | |
823 | if (s->maccr & FTGMAC100_MACCR_RX_ALL) { |
824 | return 1; |
825 | } |
826 | |
827 | switch (get_eth_packet_type(PKT_GET_ETH_HDR(buf))) { |
828 | case ETH_PKT_BCAST: |
829 | if (!(s->maccr & FTGMAC100_MACCR_RX_BROADPKT)) { |
830 | return 0; |
831 | } |
832 | break; |
833 | case ETH_PKT_MCAST: |
834 | if (!(s->maccr & FTGMAC100_MACCR_RX_MULTIPKT)) { |
835 | if (!(s->maccr & FTGMAC100_MACCR_HT_MULTI_EN)) { |
836 | return 0; |
837 | } |
838 | |
839 | mcast_idx = net_crc32_le(buf, ETH_ALEN); |
840 | mcast_idx = (~(mcast_idx >> 2)) & 0x3f; |
841 | if (!(s->math[mcast_idx / 32] & (1 << (mcast_idx % 32)))) { |
842 | return 0; |
843 | } |
844 | } |
845 | break; |
846 | case ETH_PKT_UCAST: |
847 | if (memcmp(s->conf.macaddr.a, buf, 6)) { |
848 | return 0; |
849 | } |
850 | break; |
851 | } |
852 | |
853 | return 1; |
854 | } |
855 | |
856 | static ssize_t ftgmac100_receive(NetClientState *nc, const uint8_t *buf, |
857 | size_t len) |
858 | { |
859 | FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc)); |
860 | FTGMAC100Desc bd; |
861 | uint32_t flags = 0; |
862 | uint32_t addr; |
863 | uint32_t crc; |
864 | uint32_t buf_addr; |
865 | uint8_t *crc_ptr; |
866 | uint32_t buf_len; |
867 | size_t size = len; |
868 | uint32_t first = FTGMAC100_RXDES0_FRS; |
869 | uint16_t proto = be16_to_cpu(PKT_GET_ETH_HDR(buf)->h_proto); |
870 | int max_frame_size = ftgmac100_max_frame_size(s, proto); |
871 | |
872 | if ((s->maccr & (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) |
873 | != (FTGMAC100_MACCR_RXDMA_EN | FTGMAC100_MACCR_RXMAC_EN)) { |
874 | return -1; |
875 | } |
876 | |
877 | /* TODO : Pad to minimum Ethernet frame length */ |
878 | /* handle small packets. */ |
879 | if (size < 10) { |
880 | qemu_log_mask(LOG_GUEST_ERROR, "%s: dropped frame of %zd bytes\n" , |
881 | __func__, size); |
882 | return size; |
883 | } |
884 | |
885 | if (!ftgmac100_filter(s, buf, size)) { |
886 | return size; |
887 | } |
888 | |
889 | /* 4 bytes for the CRC. */ |
890 | size += 4; |
891 | crc = cpu_to_be32(crc32(~0, buf, size)); |
892 | crc_ptr = (uint8_t *) &crc; |
893 | |
894 | /* Huge frames are truncated. */ |
895 | if (size > max_frame_size) { |
896 | qemu_log_mask(LOG_GUEST_ERROR, "%s: frame too big : %zd bytes\n" , |
897 | __func__, size); |
898 | size = max_frame_size; |
899 | flags |= FTGMAC100_RXDES0_FTL; |
900 | } |
901 | |
902 | switch (get_eth_packet_type(PKT_GET_ETH_HDR(buf))) { |
903 | case ETH_PKT_BCAST: |
904 | flags |= FTGMAC100_RXDES0_BROADCAST; |
905 | break; |
906 | case ETH_PKT_MCAST: |
907 | flags |= FTGMAC100_RXDES0_MULTICAST; |
908 | break; |
909 | case ETH_PKT_UCAST: |
910 | break; |
911 | } |
912 | |
913 | addr = s->rx_descriptor; |
914 | while (size > 0) { |
915 | if (!ftgmac100_can_receive(nc)) { |
916 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n" , __func__); |
917 | return -1; |
918 | } |
919 | |
920 | if (ftgmac100_read_bd(&bd, addr) || |
921 | (bd.des0 & FTGMAC100_RXDES0_RXPKT_RDY)) { |
922 | /* No descriptors available. Bail out. */ |
923 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Lost end of frame\n" , |
924 | __func__); |
925 | s->isr |= FTGMAC100_INT_NO_RXBUF; |
926 | break; |
927 | } |
928 | buf_len = (size <= s->rbsr) ? size : s->rbsr; |
929 | bd.des0 |= buf_len & 0x3fff; |
930 | size -= buf_len; |
931 | |
932 | /* The last 4 bytes are the CRC. */ |
933 | if (size < 4) { |
934 | buf_len += size - 4; |
935 | } |
936 | buf_addr = bd.des3; |
937 | if (first && proto == ETH_P_VLAN && buf_len >= 18) { |
938 | bd.des1 = lduw_be_p(buf + 14) | FTGMAC100_RXDES1_VLANTAG_AVAIL; |
939 | |
940 | if (s->maccr & FTGMAC100_MACCR_RM_VLAN) { |
941 | dma_memory_write(&address_space_memory, buf_addr, buf, 12); |
942 | dma_memory_write(&address_space_memory, buf_addr + 12, buf + 16, |
943 | buf_len - 16); |
944 | } else { |
945 | dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); |
946 | } |
947 | } else { |
948 | bd.des1 = 0; |
949 | dma_memory_write(&address_space_memory, buf_addr, buf, buf_len); |
950 | } |
951 | buf += buf_len; |
952 | if (size < 4) { |
953 | dma_memory_write(&address_space_memory, buf_addr + buf_len, |
954 | crc_ptr, 4 - size); |
955 | crc_ptr += 4 - size; |
956 | } |
957 | |
958 | bd.des0 |= first | FTGMAC100_RXDES0_RXPKT_RDY; |
959 | first = 0; |
960 | if (size == 0) { |
961 | /* Last buffer in frame. */ |
962 | bd.des0 |= flags | FTGMAC100_RXDES0_LRS; |
963 | s->isr |= FTGMAC100_INT_RPKT_BUF; |
964 | } else { |
965 | s->isr |= FTGMAC100_INT_RPKT_FIFO; |
966 | } |
967 | ftgmac100_write_bd(&bd, addr); |
968 | if (bd.des0 & s->rxdes0_edorr) { |
969 | addr = s->rx_ring; |
970 | } else { |
971 | addr += sizeof(FTGMAC100Desc); |
972 | } |
973 | } |
974 | s->rx_descriptor = addr; |
975 | |
976 | ftgmac100_update_irq(s); |
977 | return len; |
978 | } |
979 | |
980 | static const MemoryRegionOps ftgmac100_ops = { |
981 | .read = ftgmac100_read, |
982 | .write = ftgmac100_write, |
983 | .valid.min_access_size = 4, |
984 | .valid.max_access_size = 4, |
985 | .endianness = DEVICE_LITTLE_ENDIAN, |
986 | }; |
987 | |
988 | static void ftgmac100_cleanup(NetClientState *nc) |
989 | { |
990 | FTGMAC100State *s = FTGMAC100(qemu_get_nic_opaque(nc)); |
991 | |
992 | s->nic = NULL; |
993 | } |
994 | |
995 | static NetClientInfo net_ftgmac100_info = { |
996 | .type = NET_CLIENT_DRIVER_NIC, |
997 | .size = sizeof(NICState), |
998 | .can_receive = ftgmac100_can_receive, |
999 | .receive = ftgmac100_receive, |
1000 | .cleanup = ftgmac100_cleanup, |
1001 | .link_status_changed = ftgmac100_set_link, |
1002 | }; |
1003 | |
1004 | static void ftgmac100_realize(DeviceState *dev, Error **errp) |
1005 | { |
1006 | FTGMAC100State *s = FTGMAC100(dev); |
1007 | SysBusDevice *sbd = SYS_BUS_DEVICE(dev); |
1008 | |
1009 | if (s->aspeed) { |
1010 | s->txdes0_edotr = FTGMAC100_TXDES0_EDOTR_ASPEED; |
1011 | s->rxdes0_edorr = FTGMAC100_RXDES0_EDORR_ASPEED; |
1012 | } else { |
1013 | s->txdes0_edotr = FTGMAC100_TXDES0_EDOTR; |
1014 | s->rxdes0_edorr = FTGMAC100_RXDES0_EDORR; |
1015 | } |
1016 | |
1017 | memory_region_init_io(&s->iomem, OBJECT(dev), &ftgmac100_ops, s, |
1018 | TYPE_FTGMAC100, 0x2000); |
1019 | sysbus_init_mmio(sbd, &s->iomem); |
1020 | sysbus_init_irq(sbd, &s->irq); |
1021 | qemu_macaddr_default_if_unset(&s->conf.macaddr); |
1022 | |
1023 | s->nic = qemu_new_nic(&net_ftgmac100_info, &s->conf, |
1024 | object_get_typename(OBJECT(dev)), DEVICE(dev)->id, |
1025 | s); |
1026 | qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); |
1027 | } |
1028 | |
1029 | static const VMStateDescription vmstate_ftgmac100 = { |
1030 | .name = TYPE_FTGMAC100, |
1031 | .version_id = 1, |
1032 | .minimum_version_id = 1, |
1033 | .fields = (VMStateField[]) { |
1034 | VMSTATE_UINT32(irq_state, FTGMAC100State), |
1035 | VMSTATE_UINT32(isr, FTGMAC100State), |
1036 | VMSTATE_UINT32(ier, FTGMAC100State), |
1037 | VMSTATE_UINT32(rx_enabled, FTGMAC100State), |
1038 | VMSTATE_UINT32(rx_ring, FTGMAC100State), |
1039 | VMSTATE_UINT32(rbsr, FTGMAC100State), |
1040 | VMSTATE_UINT32(tx_ring, FTGMAC100State), |
1041 | VMSTATE_UINT32(rx_descriptor, FTGMAC100State), |
1042 | VMSTATE_UINT32(tx_descriptor, FTGMAC100State), |
1043 | VMSTATE_UINT32_ARRAY(math, FTGMAC100State, 2), |
1044 | VMSTATE_UINT32(itc, FTGMAC100State), |
1045 | VMSTATE_UINT32(aptcr, FTGMAC100State), |
1046 | VMSTATE_UINT32(dblac, FTGMAC100State), |
1047 | VMSTATE_UINT32(revr, FTGMAC100State), |
1048 | VMSTATE_UINT32(fear1, FTGMAC100State), |
1049 | VMSTATE_UINT32(tpafcr, FTGMAC100State), |
1050 | VMSTATE_UINT32(maccr, FTGMAC100State), |
1051 | VMSTATE_UINT32(phycr, FTGMAC100State), |
1052 | VMSTATE_UINT32(phydata, FTGMAC100State), |
1053 | VMSTATE_UINT32(fcr, FTGMAC100State), |
1054 | VMSTATE_UINT32(phy_status, FTGMAC100State), |
1055 | VMSTATE_UINT32(phy_control, FTGMAC100State), |
1056 | VMSTATE_UINT32(phy_advertise, FTGMAC100State), |
1057 | VMSTATE_UINT32(phy_int, FTGMAC100State), |
1058 | VMSTATE_UINT32(phy_int_mask, FTGMAC100State), |
1059 | VMSTATE_UINT32(txdes0_edotr, FTGMAC100State), |
1060 | VMSTATE_UINT32(rxdes0_edorr, FTGMAC100State), |
1061 | VMSTATE_END_OF_LIST() |
1062 | } |
1063 | }; |
1064 | |
1065 | static Property ftgmac100_properties[] = { |
1066 | DEFINE_PROP_BOOL("aspeed" , FTGMAC100State, aspeed, false), |
1067 | DEFINE_NIC_PROPERTIES(FTGMAC100State, conf), |
1068 | DEFINE_PROP_END_OF_LIST(), |
1069 | }; |
1070 | |
1071 | static void ftgmac100_class_init(ObjectClass *klass, void *data) |
1072 | { |
1073 | DeviceClass *dc = DEVICE_CLASS(klass); |
1074 | |
1075 | dc->vmsd = &vmstate_ftgmac100; |
1076 | dc->reset = ftgmac100_reset; |
1077 | dc->props = ftgmac100_properties; |
1078 | set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); |
1079 | dc->realize = ftgmac100_realize; |
1080 | dc->desc = "Faraday FTGMAC100 Gigabit Ethernet emulation" ; |
1081 | } |
1082 | |
1083 | static const TypeInfo ftgmac100_info = { |
1084 | .name = TYPE_FTGMAC100, |
1085 | .parent = TYPE_SYS_BUS_DEVICE, |
1086 | .instance_size = sizeof(FTGMAC100State), |
1087 | .class_init = ftgmac100_class_init, |
1088 | }; |
1089 | |
1090 | static void ftgmac100_register_types(void) |
1091 | { |
1092 | type_register_static(&ftgmac100_info); |
1093 | } |
1094 | |
1095 | type_init(ftgmac100_register_types) |
1096 | |