1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25#include "qemu/osdep.h"
26#include <zlib.h>
27
28#include "hw/irq.h"
29#include "hw/net/cadence_gem.h"
30#include "hw/qdev-properties.h"
31#include "migration/vmstate.h"
32#include "qapi/error.h"
33#include "qemu/log.h"
34#include "qemu/module.h"
35#include "sysemu/dma.h"
36#include "net/checksum.h"
37#include "net/eth.h"
38#include "exec/address-spaces.h"
39
40#define CADENCE_GEM_ERR_DEBUG 0
41#define DB_PRINT(...) do {\
42 if (CADENCE_GEM_ERR_DEBUG) { \
43 qemu_log(": %s: ", __func__); \
44 qemu_log(__VA_ARGS__); \
45 } \
46} while (0)
47
48#define GEM_NWCTRL (0x00000000 / 4)
49#define GEM_NWCFG (0x00000004 / 4)
50#define GEM_NWSTATUS (0x00000008 / 4)
51#define GEM_USERIO (0x0000000C / 4)
52#define GEM_DMACFG (0x00000010 / 4)
53#define GEM_TXSTATUS (0x00000014 / 4)
54#define GEM_RXQBASE (0x00000018 / 4)
55#define GEM_TXQBASE (0x0000001C / 4)
56#define GEM_RXSTATUS (0x00000020 / 4)
57#define GEM_ISR (0x00000024 / 4)
58#define GEM_IER (0x00000028 / 4)
59#define GEM_IDR (0x0000002C / 4)
60#define GEM_IMR (0x00000030 / 4)
61#define GEM_PHYMNTNC (0x00000034 / 4)
62#define GEM_RXPAUSE (0x00000038 / 4)
63#define GEM_TXPAUSE (0x0000003C / 4)
64#define GEM_TXPARTIALSF (0x00000040 / 4)
65#define GEM_RXPARTIALSF (0x00000044 / 4)
66#define GEM_JUMBO_MAX_LEN (0x00000048 / 4)
67#define GEM_HASHLO (0x00000080 / 4)
68#define GEM_HASHHI (0x00000084 / 4)
69#define GEM_SPADDR1LO (0x00000088 / 4)
70#define GEM_SPADDR1HI (0x0000008C / 4)
71#define GEM_SPADDR2LO (0x00000090 / 4)
72#define GEM_SPADDR2HI (0x00000094 / 4)
73#define GEM_SPADDR3LO (0x00000098 / 4)
74#define GEM_SPADDR3HI (0x0000009C / 4)
75#define GEM_SPADDR4LO (0x000000A0 / 4)
76#define GEM_SPADDR4HI (0x000000A4 / 4)
77#define GEM_TIDMATCH1 (0x000000A8 / 4)
78#define GEM_TIDMATCH2 (0x000000AC / 4)
79#define GEM_TIDMATCH3 (0x000000B0 / 4)
80#define GEM_TIDMATCH4 (0x000000B4 / 4)
81#define GEM_WOLAN (0x000000B8 / 4)
82#define GEM_IPGSTRETCH (0x000000BC / 4)
83#define GEM_SVLAN (0x000000C0 / 4)
84#define GEM_MODID (0x000000FC / 4)
85#define GEM_OCTTXLO (0x00000100 / 4)
86#define GEM_OCTTXHI (0x00000104 / 4)
87#define GEM_TXCNT (0x00000108 / 4)
88#define GEM_TXBCNT (0x0000010C / 4)
89#define GEM_TXMCNT (0x00000110 / 4)
90#define GEM_TXPAUSECNT (0x00000114 / 4)
91#define GEM_TX64CNT (0x00000118 / 4)
92#define GEM_TX65CNT (0x0000011C / 4)
93#define GEM_TX128CNT (0x00000120 / 4)
94#define GEM_TX256CNT (0x00000124 / 4)
95#define GEM_TX512CNT (0x00000128 / 4)
96#define GEM_TX1024CNT (0x0000012C / 4)
97#define GEM_TX1519CNT (0x00000130 / 4)
98#define GEM_TXURUNCNT (0x00000134 / 4)
99#define GEM_SINGLECOLLCNT (0x00000138 / 4)
100#define GEM_MULTCOLLCNT (0x0000013C / 4)
101#define GEM_EXCESSCOLLCNT (0x00000140 / 4)
102#define GEM_LATECOLLCNT (0x00000144 / 4)
103#define GEM_DEFERTXCNT (0x00000148 / 4)
104#define GEM_CSENSECNT (0x0000014C / 4)
105#define GEM_OCTRXLO (0x00000150 / 4)
106#define GEM_OCTRXHI (0x00000154 / 4)
107#define GEM_RXCNT (0x00000158 / 4)
108#define GEM_RXBROADCNT (0x0000015C / 4)
109#define GEM_RXMULTICNT (0x00000160 / 4)
110#define GEM_RXPAUSECNT (0x00000164 / 4)
111#define GEM_RX64CNT (0x00000168 / 4)
112#define GEM_RX65CNT (0x0000016C / 4)
113#define GEM_RX128CNT (0x00000170 / 4)
114#define GEM_RX256CNT (0x00000174 / 4)
115#define GEM_RX512CNT (0x00000178 / 4)
116#define GEM_RX1024CNT (0x0000017C / 4)
117#define GEM_RX1519CNT (0x00000180 / 4)
118#define GEM_RXUNDERCNT (0x00000184 / 4)
119#define GEM_RXOVERCNT (0x00000188 / 4)
120#define GEM_RXJABCNT (0x0000018C / 4)
121#define GEM_RXFCSCNT (0x00000190 / 4)
122#define GEM_RXLENERRCNT (0x00000194 / 4)
123#define GEM_RXSYMERRCNT (0x00000198 / 4)
124#define GEM_RXALIGNERRCNT (0x0000019C / 4)
125#define GEM_RXRSCERRCNT (0x000001A0 / 4)
126#define GEM_RXORUNCNT (0x000001A4 / 4)
127#define GEM_RXIPCSERRCNT (0x000001A8 / 4)
128#define GEM_RXTCPCCNT (0x000001AC / 4)
129#define GEM_RXUDPCCNT (0x000001B0 / 4)
130
131#define GEM_1588S (0x000001D0 / 4)
132#define GEM_1588NS (0x000001D4 / 4)
133#define GEM_1588ADJ (0x000001D8 / 4)
134#define GEM_1588INC (0x000001DC / 4)
135#define GEM_PTPETXS (0x000001E0 / 4)
136#define GEM_PTPETXNS (0x000001E4 / 4)
137
138
139#define GEM_PTPERXS (0x000001E8 / 4)
140#define GEM_PTPERXNS (0x000001EC / 4)
141#define GEM_PTPPTXS (0x000001E0 / 4)
142#define GEM_PTPPTXNS (0x000001E4 / 4)
143#define GEM_PTPPRXS (0x000001E8 / 4)
144#define GEM_PTPPRXNS (0x000001EC / 4)
145
146
147#define GEM_DESCONF (0x00000280 / 4)
148#define GEM_DESCONF2 (0x00000284 / 4)
149#define GEM_DESCONF3 (0x00000288 / 4)
150#define GEM_DESCONF4 (0x0000028C / 4)
151#define GEM_DESCONF5 (0x00000290 / 4)
152#define GEM_DESCONF6 (0x00000294 / 4)
153#define GEM_DESCONF6_64B_MASK (1U << 23)
154#define GEM_DESCONF7 (0x00000298 / 4)
155
156#define GEM_INT_Q1_STATUS (0x00000400 / 4)
157#define GEM_INT_Q1_MASK (0x00000640 / 4)
158
159#define GEM_TRANSMIT_Q1_PTR (0x00000440 / 4)
160#define GEM_TRANSMIT_Q7_PTR (GEM_TRANSMIT_Q1_PTR + 6)
161
162#define GEM_RECEIVE_Q1_PTR (0x00000480 / 4)
163#define GEM_RECEIVE_Q7_PTR (GEM_RECEIVE_Q1_PTR + 6)
164
165#define GEM_TBQPH (0x000004C8 / 4)
166#define GEM_RBQPH (0x000004D4 / 4)
167
168#define GEM_INT_Q1_ENABLE (0x00000600 / 4)
169#define GEM_INT_Q7_ENABLE (GEM_INT_Q1_ENABLE + 6)
170
171#define GEM_INT_Q1_DISABLE (0x00000620 / 4)
172#define GEM_INT_Q7_DISABLE (GEM_INT_Q1_DISABLE + 6)
173
174#define GEM_INT_Q1_MASK (0x00000640 / 4)
175#define GEM_INT_Q7_MASK (GEM_INT_Q1_MASK + 6)
176
177#define GEM_SCREENING_TYPE1_REGISTER_0 (0x00000500 / 4)
178
179#define GEM_ST1R_UDP_PORT_MATCH_ENABLE (1 << 29)
180#define GEM_ST1R_DSTC_ENABLE (1 << 28)
181#define GEM_ST1R_UDP_PORT_MATCH_SHIFT (12)
182#define GEM_ST1R_UDP_PORT_MATCH_WIDTH (27 - GEM_ST1R_UDP_PORT_MATCH_SHIFT + 1)
183#define GEM_ST1R_DSTC_MATCH_SHIFT (4)
184#define GEM_ST1R_DSTC_MATCH_WIDTH (11 - GEM_ST1R_DSTC_MATCH_SHIFT + 1)
185#define GEM_ST1R_QUEUE_SHIFT (0)
186#define GEM_ST1R_QUEUE_WIDTH (3 - GEM_ST1R_QUEUE_SHIFT + 1)
187
188#define GEM_SCREENING_TYPE2_REGISTER_0 (0x00000540 / 4)
189
190#define GEM_ST2R_COMPARE_A_ENABLE (1 << 18)
191#define GEM_ST2R_COMPARE_A_SHIFT (13)
192#define GEM_ST2R_COMPARE_WIDTH (17 - GEM_ST2R_COMPARE_A_SHIFT + 1)
193#define GEM_ST2R_ETHERTYPE_ENABLE (1 << 12)
194#define GEM_ST2R_ETHERTYPE_INDEX_SHIFT (9)
195#define GEM_ST2R_ETHERTYPE_INDEX_WIDTH (11 - GEM_ST2R_ETHERTYPE_INDEX_SHIFT \
196 + 1)
197#define GEM_ST2R_QUEUE_SHIFT (0)
198#define GEM_ST2R_QUEUE_WIDTH (3 - GEM_ST2R_QUEUE_SHIFT + 1)
199
200#define GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 (0x000006e0 / 4)
201#define GEM_TYPE2_COMPARE_0_WORD_0 (0x00000700 / 4)
202
203#define GEM_T2CW1_COMPARE_OFFSET_SHIFT (7)
204#define GEM_T2CW1_COMPARE_OFFSET_WIDTH (8 - GEM_T2CW1_COMPARE_OFFSET_SHIFT + 1)
205#define GEM_T2CW1_OFFSET_VALUE_SHIFT (0)
206#define GEM_T2CW1_OFFSET_VALUE_WIDTH (6 - GEM_T2CW1_OFFSET_VALUE_SHIFT + 1)
207
208
209#define GEM_NWCTRL_TXSTART 0x00000200
210#define GEM_NWCTRL_TXENA 0x00000008
211#define GEM_NWCTRL_RXENA 0x00000004
212#define GEM_NWCTRL_LOCALLOOP 0x00000002
213
214#define GEM_NWCFG_STRIP_FCS 0x00020000
215#define GEM_NWCFG_LERR_DISC 0x00010000
216#define GEM_NWCFG_BUFF_OFST_M 0x0000C000
217#define GEM_NWCFG_BUFF_OFST_S 14
218#define GEM_NWCFG_RCV_1538 0x00000100
219#define GEM_NWCFG_UCAST_HASH 0x00000080
220#define GEM_NWCFG_MCAST_HASH 0x00000040
221#define GEM_NWCFG_BCAST_REJ 0x00000020
222#define GEM_NWCFG_PROMISC 0x00000010
223#define GEM_NWCFG_JUMBO_FRAME 0x00000008
224
225#define GEM_DMACFG_ADDR_64B (1U << 30)
226#define GEM_DMACFG_TX_BD_EXT (1U << 29)
227#define GEM_DMACFG_RX_BD_EXT (1U << 28)
228#define GEM_DMACFG_RBUFSZ_M 0x00FF0000
229#define GEM_DMACFG_RBUFSZ_S 16
230#define GEM_DMACFG_RBUFSZ_MUL 64
231#define GEM_DMACFG_TXCSUM_OFFL 0x00000800
232
233#define GEM_TXSTATUS_TXCMPL 0x00000020
234#define GEM_TXSTATUS_USED 0x00000001
235
236#define GEM_RXSTATUS_FRMRCVD 0x00000002
237#define GEM_RXSTATUS_NOBUF 0x00000001
238
239
240#define GEM_INT_TXCMPL 0x00000080
241#define GEM_INT_AMBA_ERR 0x00000040
242#define GEM_INT_TXUSED 0x00000008
243#define GEM_INT_RXUSED 0x00000004
244#define GEM_INT_RXCMPL 0x00000002
245
246#define GEM_PHYMNTNC_OP_R 0x20000000
247#define GEM_PHYMNTNC_OP_W 0x10000000
248#define GEM_PHYMNTNC_ADDR 0x0F800000
249#define GEM_PHYMNTNC_ADDR_SHFT 23
250#define GEM_PHYMNTNC_REG 0x007C0000
251#define GEM_PHYMNTNC_REG_SHIFT 18
252
253
254#define BOARD_PHY_ADDRESS 0
255
256#define PHY_REG_CONTROL 0
257#define PHY_REG_STATUS 1
258#define PHY_REG_PHYID1 2
259#define PHY_REG_PHYID2 3
260#define PHY_REG_ANEGADV 4
261#define PHY_REG_LINKPABIL 5
262#define PHY_REG_ANEGEXP 6
263#define PHY_REG_NEXTP 7
264#define PHY_REG_LINKPNEXTP 8
265#define PHY_REG_100BTCTRL 9
266#define PHY_REG_1000BTSTAT 10
267#define PHY_REG_EXTSTAT 15
268#define PHY_REG_PHYSPCFC_CTL 16
269#define PHY_REG_PHYSPCFC_ST 17
270#define PHY_REG_INT_EN 18
271#define PHY_REG_INT_ST 19
272#define PHY_REG_EXT_PHYSPCFC_CTL 20
273#define PHY_REG_RXERR 21
274#define PHY_REG_EACD 22
275#define PHY_REG_LED 24
276#define PHY_REG_LED_OVRD 25
277#define PHY_REG_EXT_PHYSPCFC_CTL2 26
278#define PHY_REG_EXT_PHYSPCFC_ST 27
279#define PHY_REG_CABLE_DIAG 28
280
281#define PHY_REG_CONTROL_RST 0x8000
282#define PHY_REG_CONTROL_LOOP 0x4000
283#define PHY_REG_CONTROL_ANEG 0x1000
284#define PHY_REG_CONTROL_ANRESTART 0x0200
285
286#define PHY_REG_STATUS_LINK 0x0004
287#define PHY_REG_STATUS_ANEGCMPL 0x0020
288
289#define PHY_REG_INT_ST_ANEGCMPL 0x0800
290#define PHY_REG_INT_ST_LINKC 0x0400
291#define PHY_REG_INT_ST_ENERGY 0x0010
292
293
294#define GEM_RX_REJECT (-1)
295#define GEM_RX_PROMISCUOUS_ACCEPT (-2)
296#define GEM_RX_BROADCAST_ACCEPT (-3)
297#define GEM_RX_MULTICAST_HASH_ACCEPT (-4)
298#define GEM_RX_UNICAST_HASH_ACCEPT (-5)
299
300#define GEM_RX_SAR_ACCEPT 0
301
302
303
304#define DESC_1_USED 0x80000000
305#define DESC_1_LENGTH 0x00003FFF
306
307#define DESC_1_TX_WRAP 0x40000000
308#define DESC_1_TX_LAST 0x00008000
309
310#define DESC_0_RX_WRAP 0x00000002
311#define DESC_0_RX_OWNERSHIP 0x00000001
312
313#define R_DESC_1_RX_SAR_SHIFT 25
314#define R_DESC_1_RX_SAR_LENGTH 2
315#define R_DESC_1_RX_SAR_MATCH (1 << 27)
316#define R_DESC_1_RX_UNICAST_HASH (1 << 29)
317#define R_DESC_1_RX_MULTICAST_HASH (1 << 30)
318#define R_DESC_1_RX_BROADCAST (1 << 31)
319
320#define DESC_1_RX_SOF 0x00004000
321#define DESC_1_RX_EOF 0x00008000
322
323#define GEM_MODID_VALUE 0x00020118
324
325static inline uint64_t tx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
326{
327 uint64_t ret = desc[0];
328
329 if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
330 ret |= (uint64_t)desc[2] << 32;
331 }
332 return ret;
333}
334
335static inline unsigned tx_desc_get_used(uint32_t *desc)
336{
337 return (desc[1] & DESC_1_USED) ? 1 : 0;
338}
339
340static inline void tx_desc_set_used(uint32_t *desc)
341{
342 desc[1] |= DESC_1_USED;
343}
344
345static inline unsigned tx_desc_get_wrap(uint32_t *desc)
346{
347 return (desc[1] & DESC_1_TX_WRAP) ? 1 : 0;
348}
349
350static inline unsigned tx_desc_get_last(uint32_t *desc)
351{
352 return (desc[1] & DESC_1_TX_LAST) ? 1 : 0;
353}
354
355static inline unsigned tx_desc_get_length(uint32_t *desc)
356{
357 return desc[1] & DESC_1_LENGTH;
358}
359
360static inline void print_gem_tx_desc(uint32_t *desc, uint8_t queue)
361{
362 DB_PRINT("TXDESC (queue %" PRId8 "):\n", queue);
363 DB_PRINT("bufaddr: 0x%08x\n", *desc);
364 DB_PRINT("used_hw: %d\n", tx_desc_get_used(desc));
365 DB_PRINT("wrap: %d\n", tx_desc_get_wrap(desc));
366 DB_PRINT("last: %d\n", tx_desc_get_last(desc));
367 DB_PRINT("length: %d\n", tx_desc_get_length(desc));
368}
369
370static inline uint64_t rx_desc_get_buffer(CadenceGEMState *s, uint32_t *desc)
371{
372 uint64_t ret = desc[0] & ~0x3UL;
373
374 if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
375 ret |= (uint64_t)desc[2] << 32;
376 }
377 return ret;
378}
379
380static inline int gem_get_desc_len(CadenceGEMState *s, bool rx_n_tx)
381{
382 int ret = 2;
383
384 if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
385 ret += 2;
386 }
387 if (s->regs[GEM_DMACFG] & (rx_n_tx ? GEM_DMACFG_RX_BD_EXT
388 : GEM_DMACFG_TX_BD_EXT)) {
389 ret += 2;
390 }
391
392 assert(ret <= DESC_MAX_NUM_WORDS);
393 return ret;
394}
395
396static inline unsigned rx_desc_get_wrap(uint32_t *desc)
397{
398 return desc[0] & DESC_0_RX_WRAP ? 1 : 0;
399}
400
401static inline unsigned rx_desc_get_ownership(uint32_t *desc)
402{
403 return desc[0] & DESC_0_RX_OWNERSHIP ? 1 : 0;
404}
405
406static inline void rx_desc_set_ownership(uint32_t *desc)
407{
408 desc[0] |= DESC_0_RX_OWNERSHIP;
409}
410
411static inline void rx_desc_set_sof(uint32_t *desc)
412{
413 desc[1] |= DESC_1_RX_SOF;
414}
415
416static inline void rx_desc_clear_control(uint32_t *desc)
417{
418 desc[1] = 0;
419}
420
421static inline void rx_desc_set_eof(uint32_t *desc)
422{
423 desc[1] |= DESC_1_RX_EOF;
424}
425
426static inline void rx_desc_set_length(uint32_t *desc, unsigned len)
427{
428 desc[1] &= ~DESC_1_LENGTH;
429 desc[1] |= len;
430}
431
432static inline void rx_desc_set_broadcast(uint32_t *desc)
433{
434 desc[1] |= R_DESC_1_RX_BROADCAST;
435}
436
437static inline void rx_desc_set_unicast_hash(uint32_t *desc)
438{
439 desc[1] |= R_DESC_1_RX_UNICAST_HASH;
440}
441
442static inline void rx_desc_set_multicast_hash(uint32_t *desc)
443{
444 desc[1] |= R_DESC_1_RX_MULTICAST_HASH;
445}
446
447static inline void rx_desc_set_sar(uint32_t *desc, int sar_idx)
448{
449 desc[1] = deposit32(desc[1], R_DESC_1_RX_SAR_SHIFT, R_DESC_1_RX_SAR_LENGTH,
450 sar_idx);
451 desc[1] |= R_DESC_1_RX_SAR_MATCH;
452}
453
454
455static const uint8_t broadcast_addr[] = { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF };
456
457static uint32_t gem_get_max_buf_len(CadenceGEMState *s, bool tx)
458{
459 uint32_t size;
460 if (s->regs[GEM_NWCFG] & GEM_NWCFG_JUMBO_FRAME) {
461 size = s->regs[GEM_JUMBO_MAX_LEN];
462 if (size > s->jumbo_max_len) {
463 size = s->jumbo_max_len;
464 qemu_log_mask(LOG_GUEST_ERROR, "GEM_JUMBO_MAX_LEN reg cannot be"
465 " greater than 0x%" PRIx32 "\n", s->jumbo_max_len);
466 }
467 } else if (tx) {
468 size = 1518;
469 } else {
470 size = s->regs[GEM_NWCFG] & GEM_NWCFG_RCV_1538 ? 1538 : 1518;
471 }
472 return size;
473}
474
475static void gem_set_isr(CadenceGEMState *s, int q, uint32_t flag)
476{
477 if (q == 0) {
478 s->regs[GEM_ISR] |= flag & ~(s->regs[GEM_IMR]);
479 } else {
480 s->regs[GEM_INT_Q1_STATUS + q - 1] |= flag &
481 ~(s->regs[GEM_INT_Q1_MASK + q - 1]);
482 }
483}
484
485
486
487
488
489
490static void gem_init_register_masks(CadenceGEMState *s)
491{
492 unsigned int i;
493
494 memset(&s->regs_ro[0], 0, sizeof(s->regs_ro));
495 s->regs_ro[GEM_NWCTRL] = 0xFFF80000;
496 s->regs_ro[GEM_NWSTATUS] = 0xFFFFFFFF;
497 s->regs_ro[GEM_DMACFG] = 0x8E00F000;
498 s->regs_ro[GEM_TXSTATUS] = 0xFFFFFE08;
499 s->regs_ro[GEM_RXQBASE] = 0x00000003;
500 s->regs_ro[GEM_TXQBASE] = 0x00000003;
501 s->regs_ro[GEM_RXSTATUS] = 0xFFFFFFF0;
502 s->regs_ro[GEM_ISR] = 0xFFFFFFFF;
503 s->regs_ro[GEM_IMR] = 0xFFFFFFFF;
504 s->regs_ro[GEM_MODID] = 0xFFFFFFFF;
505 for (i = 0; i < s->num_priority_queues; i++) {
506 s->regs_ro[GEM_INT_Q1_STATUS + i] = 0xFFFFFFFF;
507 s->regs_ro[GEM_INT_Q1_ENABLE + i] = 0xFFFFF319;
508 s->regs_ro[GEM_INT_Q1_DISABLE + i] = 0xFFFFF319;
509 s->regs_ro[GEM_INT_Q1_MASK + i] = 0xFFFFFFFF;
510 }
511
512
513 memset(&s->regs_rtc[0], 0, sizeof(s->regs_rtc));
514 s->regs_rtc[GEM_ISR] = 0xFFFFFFFF;
515 for (i = 0; i < s->num_priority_queues; i++) {
516 s->regs_rtc[GEM_INT_Q1_STATUS + i] = 0x00000CE6;
517 }
518
519
520 memset(&s->regs_w1c[0], 0, sizeof(s->regs_w1c));
521 s->regs_w1c[GEM_TXSTATUS] = 0x000001F7;
522 s->regs_w1c[GEM_RXSTATUS] = 0x0000000F;
523
524
525 memset(&s->regs_wo[0], 0, sizeof(s->regs_wo));
526 s->regs_wo[GEM_NWCTRL] = 0x00073E60;
527 s->regs_wo[GEM_IER] = 0x07FFFFFF;
528 s->regs_wo[GEM_IDR] = 0x07FFFFFF;
529 for (i = 0; i < s->num_priority_queues; i++) {
530 s->regs_wo[GEM_INT_Q1_ENABLE + i] = 0x00000CE6;
531 s->regs_wo[GEM_INT_Q1_DISABLE + i] = 0x00000CE6;
532 }
533}
534
535
536
537
538
539static void phy_update_link(CadenceGEMState *s)
540{
541 DB_PRINT("down %d\n", qemu_get_queue(s->nic)->link_down);
542
543
544 if (qemu_get_queue(s->nic)->link_down) {
545 s->phy_regs[PHY_REG_STATUS] &= ~(PHY_REG_STATUS_ANEGCMPL |
546 PHY_REG_STATUS_LINK);
547 s->phy_regs[PHY_REG_INT_ST] |= PHY_REG_INT_ST_LINKC;
548 } else {
549 s->phy_regs[PHY_REG_STATUS] |= (PHY_REG_STATUS_ANEGCMPL |
550 PHY_REG_STATUS_LINK);
551 s->phy_regs[PHY_REG_INT_ST] |= (PHY_REG_INT_ST_LINKC |
552 PHY_REG_INT_ST_ANEGCMPL |
553 PHY_REG_INT_ST_ENERGY);
554 }
555}
556
557static bool gem_can_receive(NetClientState *nc)
558{
559 CadenceGEMState *s;
560 int i;
561
562 s = qemu_get_nic_opaque(nc);
563
564
565 if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_RXENA)) {
566 if (s->can_rx_state != 1) {
567 s->can_rx_state = 1;
568 DB_PRINT("can't receive - no enable\n");
569 }
570 return false;
571 }
572
573 for (i = 0; i < s->num_priority_queues; i++) {
574 if (rx_desc_get_ownership(s->rx_desc[i]) != 1) {
575 break;
576 }
577 };
578
579 if (i == s->num_priority_queues) {
580 if (s->can_rx_state != 2) {
581 s->can_rx_state = 2;
582 DB_PRINT("can't receive - all the buffer descriptors are busy\n");
583 }
584 return false;
585 }
586
587 if (s->can_rx_state != 0) {
588 s->can_rx_state = 0;
589 DB_PRINT("can receive\n");
590 }
591 return true;
592}
593
594
595
596
597
598static void gem_update_int_status(CadenceGEMState *s)
599{
600 int i;
601
602 qemu_set_irq(s->irq[0], !!s->regs[GEM_ISR]);
603
604 for (i = 1; i < s->num_priority_queues; ++i) {
605 qemu_set_irq(s->irq[i], !!s->regs[GEM_INT_Q1_STATUS + i - 1]);
606 }
607}
608
609
610
611
612
613static void gem_receive_updatestats(CadenceGEMState *s, const uint8_t *packet,
614 unsigned bytes)
615{
616 uint64_t octets;
617
618
619 octets = ((uint64_t)(s->regs[GEM_OCTRXLO]) << 32) |
620 s->regs[GEM_OCTRXHI];
621 octets += bytes;
622 s->regs[GEM_OCTRXLO] = octets >> 32;
623 s->regs[GEM_OCTRXHI] = octets;
624
625
626 s->regs[GEM_RXCNT]++;
627
628
629 if (!memcmp(packet, broadcast_addr, 6)) {
630 s->regs[GEM_RXBROADCNT]++;
631 }
632
633
634 if (packet[0] == 0x01) {
635 s->regs[GEM_RXMULTICNT]++;
636 }
637
638 if (bytes <= 64) {
639 s->regs[GEM_RX64CNT]++;
640 } else if (bytes <= 127) {
641 s->regs[GEM_RX65CNT]++;
642 } else if (bytes <= 255) {
643 s->regs[GEM_RX128CNT]++;
644 } else if (bytes <= 511) {
645 s->regs[GEM_RX256CNT]++;
646 } else if (bytes <= 1023) {
647 s->regs[GEM_RX512CNT]++;
648 } else if (bytes <= 1518) {
649 s->regs[GEM_RX1024CNT]++;
650 } else {
651 s->regs[GEM_RX1519CNT]++;
652 }
653}
654
655
656
657
658static unsigned get_bit(const uint8_t *mac, unsigned bit)
659{
660 unsigned byte;
661
662 byte = mac[bit / 8];
663 byte >>= (bit & 0x7);
664 byte &= 1;
665
666 return byte;
667}
668
669
670
671
672static unsigned calc_mac_hash(const uint8_t *mac)
673{
674 int index_bit, mac_bit;
675 unsigned hash_index;
676
677 hash_index = 0;
678 mac_bit = 5;
679 for (index_bit = 5; index_bit >= 0; index_bit--) {
680 hash_index |= (get_bit(mac, mac_bit) ^
681 get_bit(mac, mac_bit + 6) ^
682 get_bit(mac, mac_bit + 12) ^
683 get_bit(mac, mac_bit + 18) ^
684 get_bit(mac, mac_bit + 24) ^
685 get_bit(mac, mac_bit + 30) ^
686 get_bit(mac, mac_bit + 36) ^
687 get_bit(mac, mac_bit + 42)) << index_bit;
688 mac_bit--;
689 }
690
691 return hash_index;
692}
693
694
695
696
697
698
699
700
701
702
703
704static int gem_mac_address_filter(CadenceGEMState *s, const uint8_t *packet)
705{
706 uint8_t *gem_spaddr;
707 int i, is_mc;
708
709
710 if (s->regs[GEM_NWCFG] & GEM_NWCFG_PROMISC) {
711 return GEM_RX_PROMISCUOUS_ACCEPT;
712 }
713
714 if (!memcmp(packet, broadcast_addr, 6)) {
715
716 if (s->regs[GEM_NWCFG] & GEM_NWCFG_BCAST_REJ) {
717 return GEM_RX_REJECT;
718 }
719 return GEM_RX_BROADCAST_ACCEPT;
720 }
721
722
723 is_mc = is_multicast_ether_addr(packet);
724 if ((is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_MCAST_HASH)) ||
725 (!is_mc && (s->regs[GEM_NWCFG] & GEM_NWCFG_UCAST_HASH))) {
726 uint64_t buckets;
727 unsigned hash_index;
728
729 hash_index = calc_mac_hash(packet);
730 buckets = ((uint64_t)s->regs[GEM_HASHHI] << 32) | s->regs[GEM_HASHLO];
731 if ((buckets >> hash_index) & 1) {
732 return is_mc ? GEM_RX_MULTICAST_HASH_ACCEPT
733 : GEM_RX_UNICAST_HASH_ACCEPT;
734 }
735 }
736
737
738 gem_spaddr = (uint8_t *)&(s->regs[GEM_SPADDR1LO]);
739 for (i = 3; i >= 0; i--) {
740 if (s->sar_active[i] && !memcmp(packet, gem_spaddr + 8 * i, 6)) {
741 return GEM_RX_SAR_ACCEPT + i;
742 }
743 }
744
745
746 return GEM_RX_REJECT;
747}
748
749
750static int get_queue_from_screen(CadenceGEMState *s, uint8_t *rxbuf_ptr,
751 unsigned rxbufsize)
752{
753 uint32_t reg;
754 bool matched, mismatched;
755 int i, j;
756
757 for (i = 0; i < s->num_type1_screeners; i++) {
758 reg = s->regs[GEM_SCREENING_TYPE1_REGISTER_0 + i];
759 matched = false;
760 mismatched = false;
761
762
763 if (reg & GEM_ST1R_UDP_PORT_MATCH_ENABLE) {
764 uint16_t udp_port = rxbuf_ptr[14 + 22] << 8 | rxbuf_ptr[14 + 23];
765 if (udp_port == extract32(reg, GEM_ST1R_UDP_PORT_MATCH_SHIFT,
766 GEM_ST1R_UDP_PORT_MATCH_WIDTH)) {
767 matched = true;
768 } else {
769 mismatched = true;
770 }
771 }
772
773
774 if (reg & GEM_ST1R_DSTC_ENABLE) {
775 uint8_t dscp = rxbuf_ptr[14 + 1];
776 if (dscp == extract32(reg, GEM_ST1R_DSTC_MATCH_SHIFT,
777 GEM_ST1R_DSTC_MATCH_WIDTH)) {
778 matched = true;
779 } else {
780 mismatched = true;
781 }
782 }
783
784 if (matched && !mismatched) {
785 return extract32(reg, GEM_ST1R_QUEUE_SHIFT, GEM_ST1R_QUEUE_WIDTH);
786 }
787 }
788
789 for (i = 0; i < s->num_type2_screeners; i++) {
790 reg = s->regs[GEM_SCREENING_TYPE2_REGISTER_0 + i];
791 matched = false;
792 mismatched = false;
793
794 if (reg & GEM_ST2R_ETHERTYPE_ENABLE) {
795 uint16_t type = rxbuf_ptr[12] << 8 | rxbuf_ptr[13];
796 int et_idx = extract32(reg, GEM_ST2R_ETHERTYPE_INDEX_SHIFT,
797 GEM_ST2R_ETHERTYPE_INDEX_WIDTH);
798
799 if (et_idx > s->num_type2_screeners) {
800 qemu_log_mask(LOG_GUEST_ERROR, "Out of range ethertype "
801 "register index: %d\n", et_idx);
802 }
803 if (type == s->regs[GEM_SCREENING_TYPE2_ETHERTYPE_REG_0 +
804 et_idx]) {
805 matched = true;
806 } else {
807 mismatched = true;
808 }
809 }
810
811
812 for (j = 0; j < 3; j++) {
813 uint32_t cr0, cr1, mask;
814 uint16_t rx_cmp;
815 int offset;
816 int cr_idx = extract32(reg, GEM_ST2R_COMPARE_A_SHIFT + j * 6,
817 GEM_ST2R_COMPARE_WIDTH);
818
819 if (!(reg & (GEM_ST2R_COMPARE_A_ENABLE << (j * 6)))) {
820 continue;
821 }
822 if (cr_idx > s->num_type2_screeners) {
823 qemu_log_mask(LOG_GUEST_ERROR, "Out of range compare "
824 "register index: %d\n", cr_idx);
825 }
826
827 cr0 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2];
828 cr1 = s->regs[GEM_TYPE2_COMPARE_0_WORD_0 + cr_idx * 2 + 1];
829 offset = extract32(cr1, GEM_T2CW1_OFFSET_VALUE_SHIFT,
830 GEM_T2CW1_OFFSET_VALUE_WIDTH);
831
832 switch (extract32(cr1, GEM_T2CW1_COMPARE_OFFSET_SHIFT,
833 GEM_T2CW1_COMPARE_OFFSET_WIDTH)) {
834 case 3:
835 qemu_log_mask(LOG_UNIMP, "TCP compare offsets"
836 "unimplemented - assuming UDP\n");
837 offset += 8;
838
839 case 2:
840 offset += 20;
841
842 case 1:
843 offset += 14;
844 break;
845 case 0:
846
847 break;
848 }
849
850 rx_cmp = rxbuf_ptr[offset] << 8 | rxbuf_ptr[offset];
851 mask = extract32(cr0, 0, 16);
852
853 if ((rx_cmp & mask) == (extract32(cr0, 16, 16) & mask)) {
854 matched = true;
855 } else {
856 mismatched = true;
857 }
858 }
859
860 if (matched && !mismatched) {
861 return extract32(reg, GEM_ST2R_QUEUE_SHIFT, GEM_ST2R_QUEUE_WIDTH);
862 }
863 }
864
865
866 return 0;
867}
868
869static uint32_t gem_get_queue_base_addr(CadenceGEMState *s, bool tx, int q)
870{
871 uint32_t base_addr = 0;
872
873 switch (q) {
874 case 0:
875 base_addr = s->regs[tx ? GEM_TXQBASE : GEM_RXQBASE];
876 break;
877 case 1 ... (MAX_PRIORITY_QUEUES - 1):
878 base_addr = s->regs[(tx ? GEM_TRANSMIT_Q1_PTR :
879 GEM_RECEIVE_Q1_PTR) + q - 1];
880 break;
881 default:
882 g_assert_not_reached();
883 };
884
885 return base_addr;
886}
887
888static inline uint32_t gem_get_tx_queue_base_addr(CadenceGEMState *s, int q)
889{
890 return gem_get_queue_base_addr(s, true, q);
891}
892
893static inline uint32_t gem_get_rx_queue_base_addr(CadenceGEMState *s, int q)
894{
895 return gem_get_queue_base_addr(s, false, q);
896}
897
898static hwaddr gem_get_desc_addr(CadenceGEMState *s, bool tx, int q)
899{
900 hwaddr desc_addr = 0;
901
902 if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
903 desc_addr = s->regs[tx ? GEM_TBQPH : GEM_RBQPH];
904 }
905 desc_addr <<= 32;
906 desc_addr |= tx ? s->tx_desc_addr[q] : s->rx_desc_addr[q];
907 return desc_addr;
908}
909
910static hwaddr gem_get_tx_desc_addr(CadenceGEMState *s, int q)
911{
912 return gem_get_desc_addr(s, true, q);
913}
914
915static hwaddr gem_get_rx_desc_addr(CadenceGEMState *s, int q)
916{
917 return gem_get_desc_addr(s, false, q);
918}
919
920static void gem_get_rx_desc(CadenceGEMState *s, int q)
921{
922 hwaddr desc_addr = gem_get_rx_desc_addr(s, q);
923
924 DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", desc_addr);
925
926
927 address_space_read(&s->dma_as, desc_addr, *s->attr_r,
928 (uint8_t *)s->rx_desc[q],
929 sizeof(uint32_t) * gem_get_desc_len(s, true));
930
931
932 if (rx_desc_get_ownership(s->rx_desc[q]) == 1) {
933 DB_PRINT("descriptor 0x%" HWADDR_PRIx " owned by sw.\n", desc_addr);
934 s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_NOBUF;
935 gem_set_isr(s, q, GEM_INT_RXUSED);
936
937 gem_update_int_status(s);
938 }
939}
940
941
942
943
944
945static ssize_t gem_receive(NetClientState *nc, const uint8_t *buf, size_t size)
946{
947 CadenceGEMState *s = qemu_get_nic_opaque(nc);
948 unsigned rxbufsize, bytes_to_copy;
949 unsigned rxbuf_offset;
950 uint8_t *rxbuf_ptr;
951 bool first_desc = true;
952 int maf;
953 int q = 0;
954
955
956 maf = gem_mac_address_filter(s, buf);
957 if (maf == GEM_RX_REJECT) {
958 return size;
959 }
960
961
962 if (s->regs[GEM_NWCFG] & GEM_NWCFG_LERR_DISC) {
963 unsigned type_len;
964
965
966 type_len = buf[12] << 8 | buf[13];
967
968 if (type_len < 0x600) {
969 if (size < type_len) {
970
971 return -1;
972 }
973 }
974 }
975
976
977
978
979 rxbuf_offset = (s->regs[GEM_NWCFG] & GEM_NWCFG_BUFF_OFST_M) >>
980 GEM_NWCFG_BUFF_OFST_S;
981
982
983
984
985 rxbufsize = ((s->regs[GEM_DMACFG] & GEM_DMACFG_RBUFSZ_M) >>
986 GEM_DMACFG_RBUFSZ_S) * GEM_DMACFG_RBUFSZ_MUL;
987 bytes_to_copy = size;
988
989
990
991
992 if (rxbufsize < GEM_DMACFG_RBUFSZ_MUL) {
993 rxbufsize = GEM_DMACFG_RBUFSZ_MUL;
994 }
995
996
997
998
999
1000 if (size < 60) {
1001 size = 60;
1002 }
1003
1004
1005 if (s->regs[GEM_NWCFG] & GEM_NWCFG_STRIP_FCS) {
1006 rxbuf_ptr = (void *)buf;
1007 } else {
1008 unsigned crc_val;
1009
1010 if (size > MAX_FRAME_SIZE - sizeof(crc_val)) {
1011 size = MAX_FRAME_SIZE - sizeof(crc_val);
1012 }
1013 bytes_to_copy = size;
1014
1015
1016
1017
1018 memcpy(s->rx_packet, buf, size);
1019 memset(s->rx_packet + size, 0, MAX_FRAME_SIZE - size);
1020 rxbuf_ptr = s->rx_packet;
1021 crc_val = cpu_to_le32(crc32(0, s->rx_packet, MAX(size, 60)));
1022 memcpy(s->rx_packet + size, &crc_val, sizeof(crc_val));
1023
1024 bytes_to_copy += 4;
1025 size += 4;
1026 }
1027
1028 DB_PRINT("config bufsize: %u packet size: %zd\n", rxbufsize, size);
1029
1030
1031 q = get_queue_from_screen(s, rxbuf_ptr, rxbufsize);
1032
1033 if (size > gem_get_max_buf_len(s, false)) {
1034 qemu_log_mask(LOG_GUEST_ERROR, "rx frame too long\n");
1035 gem_set_isr(s, q, GEM_INT_AMBA_ERR);
1036 return -1;
1037 }
1038
1039 while (bytes_to_copy) {
1040 hwaddr desc_addr;
1041
1042
1043 if (!gem_can_receive(nc)) {
1044 return -1;
1045 }
1046
1047 DB_PRINT("copy %" PRIu32 " bytes to 0x%" PRIx64 "\n",
1048 MIN(bytes_to_copy, rxbufsize),
1049 rx_desc_get_buffer(s, s->rx_desc[q]));
1050
1051
1052 address_space_write(&s->dma_as, rx_desc_get_buffer(s, s->rx_desc[q]) +
1053 rxbuf_offset,
1054 *s->attr_w, rxbuf_ptr,
1055 MIN(bytes_to_copy, rxbufsize));
1056 rxbuf_ptr += MIN(bytes_to_copy, rxbufsize);
1057 bytes_to_copy -= MIN(bytes_to_copy, rxbufsize);
1058
1059 rx_desc_clear_control(s->rx_desc[q]);
1060
1061
1062 if (first_desc) {
1063 rx_desc_set_sof(s->rx_desc[q]);
1064 first_desc = false;
1065 }
1066 if (bytes_to_copy == 0) {
1067 rx_desc_set_eof(s->rx_desc[q]);
1068 rx_desc_set_length(s->rx_desc[q], size);
1069 }
1070 rx_desc_set_ownership(s->rx_desc[q]);
1071
1072 switch (maf) {
1073 case GEM_RX_PROMISCUOUS_ACCEPT:
1074 break;
1075 case GEM_RX_BROADCAST_ACCEPT:
1076 rx_desc_set_broadcast(s->rx_desc[q]);
1077 break;
1078 case GEM_RX_UNICAST_HASH_ACCEPT:
1079 rx_desc_set_unicast_hash(s->rx_desc[q]);
1080 break;
1081 case GEM_RX_MULTICAST_HASH_ACCEPT:
1082 rx_desc_set_multicast_hash(s->rx_desc[q]);
1083 break;
1084 case GEM_RX_REJECT:
1085 abort();
1086 default:
1087 rx_desc_set_sar(s->rx_desc[q], maf);
1088 }
1089
1090
1091 desc_addr = gem_get_rx_desc_addr(s, q);
1092 address_space_write(&s->dma_as, desc_addr,
1093 *s->attr_w,
1094 (uint8_t *)s->rx_desc[q],
1095 sizeof(uint32_t) * gem_get_desc_len(s, true));
1096
1097
1098 if (rx_desc_get_wrap(s->rx_desc[q])) {
1099 DB_PRINT("wrapping RX descriptor list\n");
1100 s->rx_desc_addr[q] = gem_get_rx_queue_base_addr(s, q);
1101 } else {
1102 DB_PRINT("incrementing RX descriptor list\n");
1103 s->rx_desc_addr[q] += 4 * gem_get_desc_len(s, true);
1104 }
1105
1106 gem_get_rx_desc(s, q);
1107 }
1108
1109
1110 gem_receive_updatestats(s, buf, size);
1111
1112 s->regs[GEM_RXSTATUS] |= GEM_RXSTATUS_FRMRCVD;
1113 gem_set_isr(s, q, GEM_INT_RXCMPL);
1114
1115
1116 gem_update_int_status(s);
1117
1118 return size;
1119}
1120
1121
1122
1123
1124
1125static void gem_transmit_updatestats(CadenceGEMState *s, const uint8_t *packet,
1126 unsigned bytes)
1127{
1128 uint64_t octets;
1129
1130
1131 octets = ((uint64_t)(s->regs[GEM_OCTTXLO]) << 32) |
1132 s->regs[GEM_OCTTXHI];
1133 octets += bytes;
1134 s->regs[GEM_OCTTXLO] = octets >> 32;
1135 s->regs[GEM_OCTTXHI] = octets;
1136
1137
1138 s->regs[GEM_TXCNT]++;
1139
1140
1141 if (!memcmp(packet, broadcast_addr, 6)) {
1142 s->regs[GEM_TXBCNT]++;
1143 }
1144
1145
1146 if (packet[0] == 0x01) {
1147 s->regs[GEM_TXMCNT]++;
1148 }
1149
1150 if (bytes <= 64) {
1151 s->regs[GEM_TX64CNT]++;
1152 } else if (bytes <= 127) {
1153 s->regs[GEM_TX65CNT]++;
1154 } else if (bytes <= 255) {
1155 s->regs[GEM_TX128CNT]++;
1156 } else if (bytes <= 511) {
1157 s->regs[GEM_TX256CNT]++;
1158 } else if (bytes <= 1023) {
1159 s->regs[GEM_TX512CNT]++;
1160 } else if (bytes <= 1518) {
1161 s->regs[GEM_TX1024CNT]++;
1162 } else {
1163 s->regs[GEM_TX1519CNT]++;
1164 }
1165}
1166
1167
1168
1169
1170
1171static void gem_transmit(CadenceGEMState *s)
1172{
1173 uint32_t desc[DESC_MAX_NUM_WORDS];
1174 hwaddr packet_desc_addr;
1175 uint8_t *p;
1176 unsigned total_bytes;
1177 int q = 0;
1178
1179
1180 if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
1181 return;
1182 }
1183
1184 DB_PRINT("\n");
1185
1186
1187
1188
1189
1190 p = s->tx_packet;
1191 total_bytes = 0;
1192
1193 for (q = s->num_priority_queues - 1; q >= 0; q--) {
1194
1195 packet_desc_addr = gem_get_tx_desc_addr(s, q);
1196
1197 DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
1198 address_space_read(&s->dma_as, packet_desc_addr,
1199 *s->attr_r, (uint8_t *)desc,
1200 sizeof(uint32_t) * gem_get_desc_len(s, false));
1201
1202 while (tx_desc_get_used(desc) == 0) {
1203
1204
1205 if (!(s->regs[GEM_NWCTRL] & GEM_NWCTRL_TXENA)) {
1206 return;
1207 }
1208 print_gem_tx_desc(desc, q);
1209
1210
1211
1212
1213 if ((tx_desc_get_buffer(s, desc) == 0) ||
1214 (tx_desc_get_length(desc) == 0)) {
1215 DB_PRINT("Invalid TX descriptor @ 0x%" HWADDR_PRIx "\n",
1216 packet_desc_addr);
1217 break;
1218 }
1219
1220 if (tx_desc_get_length(desc) > gem_get_max_buf_len(s, true) -
1221 (p - s->tx_packet)) {
1222 qemu_log_mask(LOG_GUEST_ERROR, "TX descriptor @ 0x%" \
1223 HWADDR_PRIx " too large: size 0x%x space 0x%zx\n",
1224 packet_desc_addr, tx_desc_get_length(desc),
1225 gem_get_max_buf_len(s, true) - (p - s->tx_packet));
1226 gem_set_isr(s, q, GEM_INT_AMBA_ERR);
1227 break;
1228 }
1229
1230
1231
1232
1233 address_space_read(&s->dma_as, tx_desc_get_buffer(s, desc),
1234 *s->attr_r,
1235 p, tx_desc_get_length(desc));
1236 p += tx_desc_get_length(desc);
1237 total_bytes += tx_desc_get_length(desc);
1238
1239
1240 if (tx_desc_get_last(desc)) {
1241 uint32_t desc_first[DESC_MAX_NUM_WORDS];
1242 hwaddr desc_addr = gem_get_tx_desc_addr(s, q);
1243
1244
1245
1246
1247 address_space_read(&s->dma_as, desc_addr,
1248 *s->attr_r,
1249 (uint8_t *)desc_first,
1250 sizeof(desc_first));
1251 tx_desc_set_used(desc_first);
1252 address_space_write(&s->dma_as, desc_addr,
1253 *s->attr_w,
1254 (uint8_t *)desc_first,
1255 sizeof(desc_first));
1256
1257 if (tx_desc_get_wrap(desc)) {
1258 s->tx_desc_addr[q] = gem_get_tx_queue_base_addr(s, q);
1259 } else {
1260 s->tx_desc_addr[q] = (uint32_t)packet_desc_addr +
1261 4 * gem_get_desc_len(s, false);
1262 }
1263 DB_PRINT("TX descriptor next: 0x%08x\n", s->tx_desc_addr[q]);
1264
1265 s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_TXCMPL;
1266 gem_set_isr(s, q, GEM_INT_TXCMPL);
1267
1268
1269 gem_update_int_status(s);
1270
1271
1272 if (s->regs[GEM_DMACFG] & GEM_DMACFG_TXCSUM_OFFL) {
1273 net_checksum_calculate(s->tx_packet, total_bytes, CSUM_ALL);
1274 }
1275
1276
1277 gem_transmit_updatestats(s, s->tx_packet, total_bytes);
1278
1279
1280 if (s->phy_loop || (s->regs[GEM_NWCTRL] &
1281 GEM_NWCTRL_LOCALLOOP)) {
1282 qemu_receive_packet(qemu_get_queue(s->nic), s->tx_packet,
1283 total_bytes);
1284 } else {
1285 qemu_send_packet(qemu_get_queue(s->nic), s->tx_packet,
1286 total_bytes);
1287 }
1288
1289
1290 p = s->tx_packet;
1291 total_bytes = 0;
1292 }
1293
1294
1295 if (tx_desc_get_wrap(desc)) {
1296 if (s->regs[GEM_DMACFG] & GEM_DMACFG_ADDR_64B) {
1297 packet_desc_addr = s->regs[GEM_TBQPH];
1298 packet_desc_addr <<= 32;
1299 } else {
1300 packet_desc_addr = 0;
1301 }
1302 packet_desc_addr |= gem_get_tx_queue_base_addr(s, q);
1303 } else {
1304 packet_desc_addr += 4 * gem_get_desc_len(s, false);
1305 }
1306 DB_PRINT("read descriptor 0x%" HWADDR_PRIx "\n", packet_desc_addr);
1307 address_space_read(&s->dma_as, packet_desc_addr,
1308 *s->attr_r, (uint8_t *)desc,
1309 sizeof(uint32_t) * gem_get_desc_len(s, false));
1310 }
1311
1312 if (tx_desc_get_used(desc)) {
1313 s->regs[GEM_TXSTATUS] |= GEM_TXSTATUS_USED;
1314
1315 if (q == 0) {
1316 gem_set_isr(s, 0, GEM_INT_TXUSED);
1317 }
1318 gem_update_int_status(s);
1319 }
1320 }
1321}
1322
1323static void gem_phy_reset(CadenceGEMState *s)
1324{
1325 memset(&s->phy_regs[0], 0, sizeof(s->phy_regs));
1326 s->phy_regs[PHY_REG_CONTROL] = 0x1140;
1327 s->phy_regs[PHY_REG_STATUS] = 0x7969;
1328 s->phy_regs[PHY_REG_PHYID1] = 0x0141;
1329 s->phy_regs[PHY_REG_PHYID2] = 0x0CC2;
1330 s->phy_regs[PHY_REG_ANEGADV] = 0x01E1;
1331 s->phy_regs[PHY_REG_LINKPABIL] = 0xCDE1;
1332 s->phy_regs[PHY_REG_ANEGEXP] = 0x000F;
1333 s->phy_regs[PHY_REG_NEXTP] = 0x2001;
1334 s->phy_regs[PHY_REG_LINKPNEXTP] = 0x40E6;
1335 s->phy_regs[PHY_REG_100BTCTRL] = 0x0300;
1336 s->phy_regs[PHY_REG_1000BTSTAT] = 0x7C00;
1337 s->phy_regs[PHY_REG_EXTSTAT] = 0x3000;
1338 s->phy_regs[PHY_REG_PHYSPCFC_CTL] = 0x0078;
1339 s->phy_regs[PHY_REG_PHYSPCFC_ST] = 0x7C00;
1340 s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL] = 0x0C60;
1341 s->phy_regs[PHY_REG_LED] = 0x4100;
1342 s->phy_regs[PHY_REG_EXT_PHYSPCFC_CTL2] = 0x000A;
1343 s->phy_regs[PHY_REG_EXT_PHYSPCFC_ST] = 0x848B;
1344
1345 phy_update_link(s);
1346}
1347
1348static void gem_reset(DeviceState *d)
1349{
1350 int i;
1351 CadenceGEMState *s = CADENCE_GEM(d);
1352 const uint8_t *a;
1353 uint32_t queues_mask = 0;
1354
1355 DB_PRINT("\n");
1356
1357
1358 memset(&s->regs[0], 0, sizeof(s->regs));
1359 s->regs[GEM_NWCFG] = 0x00080000;
1360 s->regs[GEM_NWSTATUS] = 0x00000006;
1361 s->regs[GEM_DMACFG] = 0x00020784;
1362 s->regs[GEM_IMR] = 0x07ffffff;
1363 s->regs[GEM_TXPAUSE] = 0x0000ffff;
1364 s->regs[GEM_TXPARTIALSF] = 0x000003ff;
1365 s->regs[GEM_RXPARTIALSF] = 0x000003ff;
1366 s->regs[GEM_MODID] = s->revision;
1367 s->regs[GEM_DESCONF] = 0x02D00111;
1368 s->regs[GEM_DESCONF2] = 0x2ab10000 | s->jumbo_max_len;
1369 s->regs[GEM_DESCONF5] = 0x002f2045;
1370 s->regs[GEM_DESCONF6] = GEM_DESCONF6_64B_MASK;
1371 s->regs[GEM_INT_Q1_MASK] = 0x00000CE6;
1372 s->regs[GEM_JUMBO_MAX_LEN] = s->jumbo_max_len;
1373
1374 if (s->num_priority_queues > 1) {
1375 queues_mask = MAKE_64BIT_MASK(1, s->num_priority_queues - 1);
1376 s->regs[GEM_DESCONF6] |= queues_mask;
1377 }
1378
1379
1380 a = &s->conf.macaddr.a[0];
1381 s->regs[GEM_SPADDR1LO] = a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24);
1382 s->regs[GEM_SPADDR1HI] = a[4] | (a[5] << 8);
1383
1384 for (i = 0; i < 4; i++) {
1385 s->sar_active[i] = false;
1386 }
1387
1388 if (s->mdio) {
1389 phy_update_link(s);
1390 } else {
1391 gem_phy_reset(s);
1392 }
1393
1394 gem_update_int_status(s);
1395}
1396
1397static uint16_t gem_phy_read(CadenceGEMState *s, unsigned reg_num)
1398{
1399 DB_PRINT("reg: %d value: 0x%04x\n", reg_num, s->phy_regs[reg_num]);
1400
1401 assert(!s->mdio);
1402
1403 return s->phy_regs[reg_num];
1404}
1405
1406static void gem_phy_write(CadenceGEMState *s, unsigned reg_num, uint16_t val)
1407{
1408 DB_PRINT("reg: %d value: 0x%04x\n", reg_num, val);
1409
1410 assert(!s->mdio);
1411
1412 switch (reg_num) {
1413 case PHY_REG_CONTROL:
1414 if (val & PHY_REG_CONTROL_RST) {
1415
1416 gem_phy_reset(s);
1417 val &= ~(PHY_REG_CONTROL_RST | PHY_REG_CONTROL_LOOP);
1418 s->phy_loop = 0;
1419 }
1420 if (val & PHY_REG_CONTROL_ANEG) {
1421
1422 val &= ~(PHY_REG_CONTROL_ANEG | PHY_REG_CONTROL_ANRESTART);
1423 s->phy_regs[PHY_REG_STATUS] |= PHY_REG_STATUS_ANEGCMPL;
1424 }
1425 if (val & PHY_REG_CONTROL_LOOP) {
1426 DB_PRINT("PHY placed in loopback\n");
1427 s->phy_loop = 1;
1428 } else {
1429 s->phy_loop = 0;
1430 }
1431 break;
1432 }
1433 s->phy_regs[reg_num] = val;
1434}
1435
1436static void gem_phy_loopback_setup(CadenceGEMState *s, unsigned reg_num,
1437 uint16_t val)
1438{
1439 assert(s->mdio);
1440
1441 switch (reg_num) {
1442 case PHY_REG_CONTROL:
1443 if (val & PHY_REG_CONTROL_RST) {
1444
1445 s->phy_loop = 0;
1446 }
1447 if (val & PHY_REG_CONTROL_LOOP) {
1448 DB_PRINT("PHY placed in loopback\n");
1449 s->phy_loop = 1;
1450 } else {
1451 s->phy_loop = 0;
1452 }
1453 break;
1454 }
1455}
1456
1457
1458
1459
1460
1461static uint64_t gem_read(void *opaque, hwaddr offset, unsigned size)
1462{
1463 CadenceGEMState *s;
1464 uint32_t retval;
1465 s = (CadenceGEMState *)opaque;
1466
1467 offset >>= 2;
1468 retval = s->regs[offset];
1469
1470 DB_PRINT("offset: 0x%04x read: 0x%08x\n", (unsigned)offset*4, retval);
1471
1472 switch (offset) {
1473 case GEM_ISR:
1474 DB_PRINT("lowering irqs on ISR read\n");
1475
1476 break;
1477 case GEM_PHYMNTNC:
1478 if (retval & GEM_PHYMNTNC_OP_R) {
1479 uint32_t phy_addr, reg_num;
1480
1481 phy_addr = (retval & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
1482 if (s->mdio) {
1483 reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
1484 retval &= 0xFFFF0000;
1485 retval |= s->mdio->read(s->mdio, phy_addr, reg_num);
1486 } else if (phy_addr == s->phy_addr || phy_addr == 0) {
1487 reg_num = (retval & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
1488 retval &= 0xFFFF0000;
1489 retval |= gem_phy_read(s, reg_num);
1490 } else {
1491 retval |= 0xFFFF;
1492 }
1493 }
1494 break;
1495 }
1496
1497
1498 s->regs[offset] &= ~(s->regs_rtc[offset]);
1499
1500
1501 retval &= ~(s->regs_wo[offset]);
1502
1503 DB_PRINT("0x%08x\n", retval);
1504 gem_update_int_status(s);
1505 return retval;
1506}
1507
1508
1509
1510
1511
1512static void gem_write(void *opaque, hwaddr offset, uint64_t val,
1513 unsigned size)
1514{
1515 CadenceGEMState *s = (CadenceGEMState *)opaque;
1516 uint32_t readonly;
1517 int i;
1518
1519 DB_PRINT("offset: 0x%04x write: 0x%08x ", (unsigned)offset, (unsigned)val);
1520 offset >>= 2;
1521
1522
1523 val &= ~(s->regs_ro[offset]);
1524
1525 readonly = s->regs[offset] & (s->regs_ro[offset] | s->regs_w1c[offset]);
1526
1527
1528 s->regs[offset] = (val & ~s->regs_w1c[offset]) | readonly;
1529
1530
1531 s->regs[offset] &= ~(s->regs_w1c[offset] & val);
1532
1533
1534 switch (offset) {
1535 case GEM_NWCTRL:
1536 if (val & GEM_NWCTRL_RXENA) {
1537 for (i = 0; i < s->num_priority_queues; ++i) {
1538 gem_get_rx_desc(s, i);
1539 }
1540 }
1541 if (val & GEM_NWCTRL_TXSTART) {
1542 gem_transmit(s);
1543 }
1544 if (!(val & GEM_NWCTRL_TXENA)) {
1545
1546 for (i = 0; i < s->num_priority_queues; i++) {
1547 s->tx_desc_addr[i] = gem_get_tx_queue_base_addr(s, i);
1548 }
1549 }
1550 if (gem_can_receive(qemu_get_queue(s->nic))) {
1551 qemu_flush_queued_packets(qemu_get_queue(s->nic));
1552 }
1553 break;
1554
1555 case GEM_TXSTATUS:
1556 gem_update_int_status(s);
1557 break;
1558 case GEM_RXQBASE:
1559 s->rx_desc_addr[0] = val;
1560 break;
1561 case GEM_RECEIVE_Q1_PTR ... GEM_RECEIVE_Q7_PTR:
1562 s->rx_desc_addr[offset - GEM_RECEIVE_Q1_PTR + 1] = val;
1563 break;
1564 case GEM_TXQBASE:
1565 s->tx_desc_addr[0] = val;
1566 break;
1567 case GEM_TRANSMIT_Q1_PTR ... GEM_TRANSMIT_Q7_PTR:
1568 s->tx_desc_addr[offset - GEM_TRANSMIT_Q1_PTR + 1] = val;
1569 break;
1570 case GEM_RXSTATUS:
1571 gem_update_int_status(s);
1572 break;
1573 case GEM_IER:
1574 s->regs[GEM_IMR] &= ~val;
1575 gem_update_int_status(s);
1576 break;
1577 case GEM_JUMBO_MAX_LEN:
1578 s->regs[GEM_JUMBO_MAX_LEN] = val & MAX_JUMBO_FRAME_SIZE_MASK;
1579 break;
1580 case GEM_INT_Q1_ENABLE ... GEM_INT_Q7_ENABLE:
1581 s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_ENABLE] &= ~val;
1582 gem_update_int_status(s);
1583 break;
1584 case GEM_IDR:
1585 s->regs[GEM_IMR] |= val;
1586 gem_update_int_status(s);
1587 break;
1588 case GEM_INT_Q1_DISABLE ... GEM_INT_Q7_DISABLE:
1589 s->regs[GEM_INT_Q1_MASK + offset - GEM_INT_Q1_DISABLE] |= val;
1590 gem_update_int_status(s);
1591 break;
1592 case GEM_SPADDR1LO:
1593 case GEM_SPADDR2LO:
1594 case GEM_SPADDR3LO:
1595 case GEM_SPADDR4LO:
1596 s->sar_active[(offset - GEM_SPADDR1LO) / 2] = false;
1597 break;
1598 case GEM_SPADDR1HI:
1599 case GEM_SPADDR2HI:
1600 case GEM_SPADDR3HI:
1601 case GEM_SPADDR4HI:
1602 s->sar_active[(offset - GEM_SPADDR1HI) / 2] = true;
1603 break;
1604 case GEM_PHYMNTNC:
1605 if (val & GEM_PHYMNTNC_OP_W) {
1606 uint32_t phy_addr, reg_num;
1607
1608 phy_addr = (val & GEM_PHYMNTNC_ADDR) >> GEM_PHYMNTNC_ADDR_SHFT;
1609 if (s->mdio) {
1610 reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
1611 gem_phy_loopback_setup(s, reg_num, val);
1612 s->mdio->write(s->mdio, phy_addr, reg_num, val);
1613 } else if (phy_addr == s->phy_addr || phy_addr == 0) {
1614 reg_num = (val & GEM_PHYMNTNC_REG) >> GEM_PHYMNTNC_REG_SHIFT;
1615 gem_phy_write(s, reg_num, val);
1616 }
1617 }
1618 break;
1619 }
1620
1621 DB_PRINT("newval: 0x%08x\n", s->regs[offset]);
1622}
1623
1624static const MemoryRegionOps gem_ops = {
1625 .read = gem_read,
1626 .write = gem_write,
1627 .endianness = DEVICE_LITTLE_ENDIAN,
1628};
1629
1630static void gem_set_link(NetClientState *nc)
1631{
1632 CadenceGEMState *s = qemu_get_nic_opaque(nc);
1633
1634 DB_PRINT("\n");
1635 phy_update_link(s);
1636 gem_update_int_status(s);
1637}
1638
1639static NetClientInfo net_gem_info = {
1640 .type = NET_CLIENT_DRIVER_NIC,
1641 .size = sizeof(NICState),
1642 .can_receive = gem_can_receive,
1643 .receive = gem_receive,
1644 .link_status_changed = gem_set_link,
1645};
1646
1647static void gem_realize(DeviceState *dev, Error **errp)
1648{
1649 CadenceGEMState *s = CADENCE_GEM(dev);
1650 int i;
1651
1652 address_space_init(&s->dma_as,
1653 s->dma_mr ? s->dma_mr : get_system_memory(), "dma");
1654
1655 if (s->num_priority_queues == 0 ||
1656 s->num_priority_queues > MAX_PRIORITY_QUEUES) {
1657 error_setg(errp, "Invalid num-priority-queues value: %" PRIx8,
1658 s->num_priority_queues);
1659 return;
1660 } else if (s->num_type1_screeners > MAX_TYPE1_SCREENERS) {
1661 error_setg(errp, "Invalid num-type1-screeners value: %" PRIx8,
1662 s->num_type1_screeners);
1663 return;
1664 } else if (s->num_type2_screeners > MAX_TYPE2_SCREENERS) {
1665 error_setg(errp, "Invalid num-type2-screeners value: %" PRIx8,
1666 s->num_type2_screeners);
1667 return;
1668 }
1669
1670 for (i = 0; i < s->num_priority_queues; ++i) {
1671 sysbus_init_irq(SYS_BUS_DEVICE(dev), &s->irq[i]);
1672 }
1673
1674 if (!s->attr_r) {
1675 s->attr_r = MEMORY_TRANSACTION_ATTR(
1676 object_new(TYPE_MEMORY_TRANSACTION_ATTR));
1677 }
1678 if (!s->attr_w) {
1679 s->attr_w = s->attr_r;
1680 }
1681
1682 qemu_macaddr_default_if_unset(&s->conf.macaddr);
1683
1684 s->nic = qemu_new_nic(&net_gem_info, &s->conf,
1685 object_get_typename(OBJECT(dev)), dev->id, s);
1686
1687 if (s->jumbo_max_len > MAX_FRAME_SIZE) {
1688 error_setg(errp, "jumbo-max-len is greater than %d",
1689 MAX_FRAME_SIZE);
1690 return;
1691 }
1692}
1693
1694static void gem_init(Object *obj)
1695{
1696 CadenceGEMState *s = CADENCE_GEM(obj);
1697 DeviceState *dev = DEVICE(obj);
1698
1699 DB_PRINT("\n");
1700
1701 gem_init_register_masks(s);
1702 memory_region_init_io(&s->iomem, OBJECT(s), &gem_ops, s,
1703 "enet", sizeof(s->regs));
1704
1705 sysbus_init_mmio(SYS_BUS_DEVICE(dev), &s->iomem);
1706
1707 object_property_add_link(obj, "dma", TYPE_MEMORY_REGION,
1708 (Object **)&s->dma_mr,
1709 qdev_prop_allow_set_link_before_realize,
1710 OBJ_PROP_LINK_STRONG);
1711 object_property_add_link(obj, "memattr", TYPE_MEMORY_TRANSACTION_ATTR,
1712 (Object **)&s->attr_r,
1713 qdev_prop_allow_set_link_before_realize,
1714 OBJ_PROP_LINK_STRONG);
1715 object_property_add_link(obj, "memattr-write", TYPE_MEMORY_TRANSACTION_ATTR,
1716 (Object **)&s->attr_w,
1717 qdev_prop_allow_set_link_before_realize,
1718 OBJ_PROP_LINK_STRONG);
1719 object_property_add_link(obj, "mdio", TYPE_MDIO, (Object **)&s->mdio,
1720 qdev_prop_allow_set_link,
1721 OBJ_PROP_LINK_STRONG);
1722}
1723
1724static const VMStateDescription vmstate_cadence_gem = {
1725 .name = "cadence_gem",
1726 .version_id = 4,
1727 .minimum_version_id = 4,
1728 .fields = (VMStateField[]) {
1729 VMSTATE_UINT32_ARRAY(regs, CadenceGEMState, CADENCE_GEM_MAXREG),
1730 VMSTATE_UINT8(phy_loop, CadenceGEMState),
1731 VMSTATE_UINT32_ARRAY(rx_desc_addr, CadenceGEMState,
1732 MAX_PRIORITY_QUEUES),
1733 VMSTATE_UINT32_ARRAY(tx_desc_addr, CadenceGEMState,
1734 MAX_PRIORITY_QUEUES),
1735 VMSTATE_BOOL_ARRAY(sar_active, CadenceGEMState, 4),
1736 VMSTATE_END_OF_LIST(),
1737 }
1738};
1739
1740static Property gem_properties[] = {
1741 DEFINE_NIC_PROPERTIES(CadenceGEMState, conf),
1742 DEFINE_PROP_UINT32("revision", CadenceGEMState, revision,
1743 GEM_MODID_VALUE),
1744 DEFINE_PROP_UINT8("phy-addr", CadenceGEMState, phy_addr, BOARD_PHY_ADDRESS),
1745 DEFINE_PROP_UINT8("num-priority-queues", CadenceGEMState,
1746 num_priority_queues, 1),
1747 DEFINE_PROP_UINT8("num-type1-screeners", CadenceGEMState,
1748 num_type1_screeners, 4),
1749 DEFINE_PROP_UINT8("num-type2-screeners", CadenceGEMState,
1750 num_type2_screeners, 4),
1751 DEFINE_PROP_UINT16("jumbo-max-len", CadenceGEMState,
1752 jumbo_max_len, 10240),
1753 DEFINE_PROP_END_OF_LIST(),
1754};
1755
1756static void gem_class_init(ObjectClass *klass, void *data)
1757{
1758 DeviceClass *dc = DEVICE_CLASS(klass);
1759
1760 dc->realize = gem_realize;
1761 device_class_set_props(dc, gem_properties);
1762 dc->vmsd = &vmstate_cadence_gem;
1763 dc->reset = gem_reset;
1764}
1765
1766static const TypeInfo gem_info = {
1767 .name = TYPE_CADENCE_GEM,
1768 .parent = TYPE_SYS_BUS_DEVICE,
1769 .instance_size = sizeof(CadenceGEMState),
1770 .instance_init = gem_init,
1771 .class_init = gem_class_init,
1772};
1773
1774static void gem_register_types(void)
1775{
1776 type_register_static(&gem_info);
1777}
1778
1779type_init(gem_register_types)
1780