]>
Commit | Line | Data |
---|---|---|
01c966b5 DE |
1 | /* |
2 | * Nuvoton NPCM7xx EMC Module | |
3 | * | |
4 | * Copyright 2020 Google LLC | |
5 | * | |
6 | * This program is free software; you can redistribute it and/or modify it | |
7 | * under the terms of the GNU General Public License as published by the | |
8 | * Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, but WITHOUT | |
12 | * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 | * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 | * for more details. | |
15 | * | |
16 | * Unsupported/unimplemented features: | |
17 | * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported | |
18 | * - Only CAM0 is supported, CAM[1-15] are not | |
19 | * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes | |
20 | * - MII is not implemented, MIIDA.BUSY and MIID always return zero | |
21 | * - MCMDR.LBK is not implemented | |
22 | * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported | |
23 | * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored | |
24 | * - MGSTA.SQE is not supported | |
25 | * - pause and control frames are not implemented | |
26 | * - MGSTA.CCNT is not supported | |
27 | * - MPCNT, DMARFS are not implemented | |
28 | */ | |
29 | ||
30 | #include "qemu/osdep.h" | |
31 | ||
32 | /* For crc32 */ | |
33 | #include <zlib.h> | |
34 | ||
35 | #include "qemu-common.h" | |
36 | #include "hw/irq.h" | |
37 | #include "hw/qdev-clock.h" | |
38 | #include "hw/qdev-properties.h" | |
39 | #include "hw/net/npcm7xx_emc.h" | |
40 | #include "net/eth.h" | |
41 | #include "migration/vmstate.h" | |
42 | #include "qemu/bitops.h" | |
43 | #include "qemu/error-report.h" | |
44 | #include "qemu/log.h" | |
45 | #include "qemu/module.h" | |
46 | #include "qemu/units.h" | |
47 | #include "sysemu/dma.h" | |
48 | #include "trace.h" | |
49 | ||
50 | #define CRC_LENGTH 4 | |
51 | ||
52 | /* | |
53 | * The maximum size of a (layer 2) ethernet frame as defined by 802.3. | |
54 | * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload) | |
55 | * This does not include an additional 4 for the vlan field (802.1q). | |
56 | */ | |
57 | #define MAX_ETH_FRAME_SIZE 1518 | |
58 | ||
59 | static const char *emc_reg_name(int regno) | |
60 | { | |
61 | #define REG(name) case REG_ ## name: return #name; | |
62 | switch (regno) { | |
63 | REG(CAMCMR) | |
64 | REG(CAMEN) | |
65 | REG(TXDLSA) | |
66 | REG(RXDLSA) | |
67 | REG(MCMDR) | |
68 | REG(MIID) | |
69 | REG(MIIDA) | |
70 | REG(FFTCR) | |
71 | REG(TSDR) | |
72 | REG(RSDR) | |
73 | REG(DMARFC) | |
74 | REG(MIEN) | |
75 | REG(MISTA) | |
76 | REG(MGSTA) | |
77 | REG(MPCNT) | |
78 | REG(MRPC) | |
79 | REG(MRPCC) | |
80 | REG(MREPC) | |
81 | REG(DMARFS) | |
82 | REG(CTXDSA) | |
83 | REG(CTXBSA) | |
84 | REG(CRXDSA) | |
85 | REG(CRXBSA) | |
86 | case REG_CAMM_BASE + 0: return "CAM0M"; | |
87 | case REG_CAML_BASE + 0: return "CAM0L"; | |
88 | case REG_CAMM_BASE + 2 ... REG_CAMML_LAST: | |
89 | /* Only CAM0 is supported, fold the others into something simple. */ | |
90 | if (regno & 1) { | |
91 | return "CAM<n>L"; | |
92 | } else { | |
93 | return "CAM<n>M"; | |
94 | } | |
95 | default: return "UNKNOWN"; | |
96 | } | |
97 | #undef REG | |
98 | } | |
99 | ||
100 | static void emc_reset(NPCM7xxEMCState *emc) | |
101 | { | |
102 | trace_npcm7xx_emc_reset(emc->emc_num); | |
103 | ||
104 | memset(&emc->regs[0], 0, sizeof(emc->regs)); | |
105 | ||
106 | /* These regs have non-zero reset values. */ | |
107 | emc->regs[REG_TXDLSA] = 0xfffffffc; | |
108 | emc->regs[REG_RXDLSA] = 0xfffffffc; | |
109 | emc->regs[REG_MIIDA] = 0x00900000; | |
110 | emc->regs[REG_FFTCR] = 0x0101; | |
111 | emc->regs[REG_DMARFC] = 0x0800; | |
112 | emc->regs[REG_MPCNT] = 0x7fff; | |
113 | ||
114 | emc->tx_active = false; | |
115 | emc->rx_active = false; | |
116 | } | |
117 | ||
118 | static void npcm7xx_emc_reset(DeviceState *dev) | |
119 | { | |
120 | NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); | |
121 | emc_reset(emc); | |
122 | } | |
123 | ||
124 | static void emc_soft_reset(NPCM7xxEMCState *emc) | |
125 | { | |
126 | /* | |
127 | * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a | |
128 | * soft reset, but does not go into further detail. For now, KISS. | |
129 | */ | |
130 | uint32_t mcmdr = emc->regs[REG_MCMDR]; | |
131 | emc_reset(emc); | |
132 | emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD); | |
133 | ||
134 | qemu_set_irq(emc->tx_irq, 0); | |
135 | qemu_set_irq(emc->rx_irq, 0); | |
136 | } | |
137 | ||
138 | static void emc_set_link(NetClientState *nc) | |
139 | { | |
140 | /* Nothing to do yet. */ | |
141 | } | |
142 | ||
143 | /* MISTA.TXINTR is the union of the individual bits with their enables. */ | |
144 | static void emc_update_mista_txintr(NPCM7xxEMCState *emc) | |
145 | { | |
146 | /* Only look at the bits we support. */ | |
147 | uint32_t mask = (REG_MISTA_TXBERR | | |
148 | REG_MISTA_TDU | | |
149 | REG_MISTA_TXCP); | |
150 | if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) { | |
151 | emc->regs[REG_MISTA] |= REG_MISTA_TXINTR; | |
152 | } else { | |
153 | emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR; | |
154 | } | |
155 | } | |
156 | ||
157 | /* MISTA.RXINTR is the union of the individual bits with their enables. */ | |
158 | static void emc_update_mista_rxintr(NPCM7xxEMCState *emc) | |
159 | { | |
160 | /* Only look at the bits we support. */ | |
161 | uint32_t mask = (REG_MISTA_RXBERR | | |
162 | REG_MISTA_RDU | | |
163 | REG_MISTA_RXGD); | |
164 | if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) { | |
165 | emc->regs[REG_MISTA] |= REG_MISTA_RXINTR; | |
166 | } else { | |
167 | emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR; | |
168 | } | |
169 | } | |
170 | ||
171 | /* N.B. emc_update_mista_txintr must have already been called. */ | |
172 | static void emc_update_tx_irq(NPCM7xxEMCState *emc) | |
173 | { | |
174 | int level = !!(emc->regs[REG_MISTA] & | |
175 | emc->regs[REG_MIEN] & | |
176 | REG_MISTA_TXINTR); | |
177 | trace_npcm7xx_emc_update_tx_irq(level); | |
178 | qemu_set_irq(emc->tx_irq, level); | |
179 | } | |
180 | ||
181 | /* N.B. emc_update_mista_rxintr must have already been called. */ | |
182 | static void emc_update_rx_irq(NPCM7xxEMCState *emc) | |
183 | { | |
184 | int level = !!(emc->regs[REG_MISTA] & | |
185 | emc->regs[REG_MIEN] & | |
186 | REG_MISTA_RXINTR); | |
187 | trace_npcm7xx_emc_update_rx_irq(level); | |
188 | qemu_set_irq(emc->rx_irq, level); | |
189 | } | |
190 | ||
191 | /* Update IRQ states due to changes in MIEN,MISTA. */ | |
192 | static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc) | |
193 | { | |
194 | emc_update_mista_txintr(emc); | |
195 | emc_update_tx_irq(emc); | |
196 | ||
197 | emc_update_mista_rxintr(emc); | |
198 | emc_update_rx_irq(emc); | |
199 | } | |
200 | ||
201 | static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc) | |
202 | { | |
203 | if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) { | |
204 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" | |
205 | HWADDR_PRIx "\n", __func__, addr); | |
206 | return -1; | |
207 | } | |
208 | desc->flags = le32_to_cpu(desc->flags); | |
209 | desc->txbsa = le32_to_cpu(desc->txbsa); | |
210 | desc->status_and_length = le32_to_cpu(desc->status_and_length); | |
211 | desc->ntxdsa = le32_to_cpu(desc->ntxdsa); | |
212 | return 0; | |
213 | } | |
214 | ||
215 | static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr) | |
216 | { | |
217 | NPCM7xxEMCTxDesc le_desc; | |
218 | ||
219 | le_desc.flags = cpu_to_le32(desc->flags); | |
220 | le_desc.txbsa = cpu_to_le32(desc->txbsa); | |
221 | le_desc.status_and_length = cpu_to_le32(desc->status_and_length); | |
222 | le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa); | |
223 | if (dma_memory_write(&address_space_memory, addr, &le_desc, | |
224 | sizeof(le_desc))) { | |
225 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" | |
226 | HWADDR_PRIx "\n", __func__, addr); | |
227 | return -1; | |
228 | } | |
229 | return 0; | |
230 | } | |
231 | ||
232 | static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc) | |
233 | { | |
234 | if (dma_memory_read(&address_space_memory, addr, desc, sizeof(*desc))) { | |
235 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" | |
236 | HWADDR_PRIx "\n", __func__, addr); | |
237 | return -1; | |
238 | } | |
239 | desc->status_and_length = le32_to_cpu(desc->status_and_length); | |
240 | desc->rxbsa = le32_to_cpu(desc->rxbsa); | |
241 | desc->reserved = le32_to_cpu(desc->reserved); | |
242 | desc->nrxdsa = le32_to_cpu(desc->nrxdsa); | |
243 | return 0; | |
244 | } | |
245 | ||
246 | static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr) | |
247 | { | |
248 | NPCM7xxEMCRxDesc le_desc; | |
249 | ||
250 | le_desc.status_and_length = cpu_to_le32(desc->status_and_length); | |
251 | le_desc.rxbsa = cpu_to_le32(desc->rxbsa); | |
252 | le_desc.reserved = cpu_to_le32(desc->reserved); | |
253 | le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa); | |
254 | if (dma_memory_write(&address_space_memory, addr, &le_desc, | |
255 | sizeof(le_desc))) { | |
256 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" | |
257 | HWADDR_PRIx "\n", __func__, addr); | |
258 | return -1; | |
259 | } | |
260 | return 0; | |
261 | } | |
262 | ||
263 | static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags) | |
264 | { | |
265 | trace_npcm7xx_emc_set_mista(flags); | |
266 | emc->regs[REG_MISTA] |= flags; | |
267 | if (extract32(flags, 16, 16)) { | |
268 | emc_update_mista_txintr(emc); | |
269 | } | |
270 | if (extract32(flags, 0, 16)) { | |
271 | emc_update_mista_rxintr(emc); | |
272 | } | |
273 | } | |
274 | ||
275 | static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag) | |
276 | { | |
277 | emc->tx_active = false; | |
278 | emc_set_mista(emc, mista_flag); | |
279 | } | |
280 | ||
281 | static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag) | |
282 | { | |
283 | emc->rx_active = false; | |
284 | emc_set_mista(emc, mista_flag); | |
285 | } | |
286 | ||
287 | static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc, | |
288 | const NPCM7xxEMCTxDesc *tx_desc, | |
289 | uint32_t desc_addr) | |
290 | { | |
291 | /* Update the current descriptor, if only to reset the owner flag. */ | |
292 | if (emc_write_tx_desc(tx_desc, desc_addr)) { | |
293 | /* | |
294 | * We just read it so this shouldn't generally happen. | |
295 | * Error already reported. | |
296 | */ | |
297 | emc_set_mista(emc, REG_MISTA_TXBERR); | |
298 | } | |
299 | emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa); | |
300 | } | |
301 | ||
302 | static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc, | |
303 | const NPCM7xxEMCRxDesc *rx_desc, | |
304 | uint32_t desc_addr) | |
305 | { | |
306 | /* Update the current descriptor, if only to reset the owner flag. */ | |
307 | if (emc_write_rx_desc(rx_desc, desc_addr)) { | |
308 | /* | |
309 | * We just read it so this shouldn't generally happen. | |
310 | * Error already reported. | |
311 | */ | |
312 | emc_set_mista(emc, REG_MISTA_RXBERR); | |
313 | } | |
314 | emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa); | |
315 | } | |
316 | ||
317 | static void emc_try_send_next_packet(NPCM7xxEMCState *emc) | |
318 | { | |
319 | /* Working buffer for sending out packets. Most packets fit in this. */ | |
320 | #define TX_BUFFER_SIZE 2048 | |
321 | uint8_t tx_send_buffer[TX_BUFFER_SIZE]; | |
322 | uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]); | |
323 | NPCM7xxEMCTxDesc tx_desc; | |
324 | uint32_t next_buf_addr, length; | |
325 | uint8_t *buf; | |
326 | g_autofree uint8_t *malloced_buf = NULL; | |
327 | ||
328 | if (emc_read_tx_desc(desc_addr, &tx_desc)) { | |
329 | /* Error reading descriptor, already reported. */ | |
330 | emc_halt_tx(emc, REG_MISTA_TXBERR); | |
331 | emc_update_tx_irq(emc); | |
332 | return; | |
333 | } | |
334 | ||
335 | /* Nothing we can do if we don't own the descriptor. */ | |
336 | if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) { | |
337 | trace_npcm7xx_emc_cpu_owned_desc(desc_addr); | |
338 | emc_halt_tx(emc, REG_MISTA_TDU); | |
339 | emc_update_tx_irq(emc); | |
340 | return; | |
341 | } | |
342 | ||
343 | /* Give the descriptor back regardless of what happens. */ | |
344 | tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK; | |
345 | tx_desc.status_and_length &= 0xffff; | |
346 | ||
347 | /* | |
348 | * Despite the h/w documentation saying the tx buffer is word aligned, | |
349 | * the linux driver does not word align the buffer. There is value in not | |
350 | * aligning the buffer: See the description of NET_IP_ALIGN in linux | |
351 | * kernel sources. | |
352 | */ | |
353 | next_buf_addr = tx_desc.txbsa; | |
354 | emc->regs[REG_CTXBSA] = next_buf_addr; | |
355 | length = TX_DESC_PKT_LEN(tx_desc.status_and_length); | |
356 | buf = &tx_send_buffer[0]; | |
357 | ||
358 | if (length > sizeof(tx_send_buffer)) { | |
359 | malloced_buf = g_malloc(length); | |
360 | buf = malloced_buf; | |
361 | } | |
362 | ||
363 | if (dma_memory_read(&address_space_memory, next_buf_addr, buf, length)) { | |
364 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n", | |
365 | __func__, next_buf_addr); | |
366 | emc_set_mista(emc, REG_MISTA_TXBERR); | |
367 | emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr); | |
368 | emc_update_tx_irq(emc); | |
369 | trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]); | |
370 | return; | |
371 | } | |
372 | ||
373 | if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) { | |
374 | memset(buf + length, 0, MIN_PACKET_LENGTH - length); | |
375 | length = MIN_PACKET_LENGTH; | |
376 | } | |
377 | ||
378 | /* N.B. emc_receive can get called here. */ | |
379 | qemu_send_packet(qemu_get_queue(emc->nic), buf, length); | |
380 | trace_npcm7xx_emc_sent_packet(length); | |
381 | ||
382 | tx_desc.status_and_length |= TX_DESC_STATUS_TXCP; | |
383 | if (tx_desc.flags & TX_DESC_FLAG_INTEN) { | |
384 | emc_set_mista(emc, REG_MISTA_TXCP); | |
385 | } | |
386 | if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) { | |
387 | tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR; | |
388 | } | |
389 | ||
390 | emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr); | |
391 | emc_update_tx_irq(emc); | |
392 | trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]); | |
393 | } | |
394 | ||
395 | static bool emc_can_receive(NetClientState *nc) | |
396 | { | |
397 | NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc)); | |
398 | ||
399 | bool can_receive = emc->rx_active; | |
400 | trace_npcm7xx_emc_can_receive(can_receive); | |
401 | return can_receive; | |
402 | } | |
403 | ||
404 | /* If result is false then *fail_reason contains the reason. */ | |
405 | static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf, | |
406 | size_t len, const char **fail_reason) | |
407 | { | |
408 | eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf)); | |
409 | ||
410 | switch (pkt_type) { | |
411 | case ETH_PKT_BCAST: | |
412 | if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { | |
413 | return true; | |
414 | } else { | |
415 | *fail_reason = "Broadcast packet disabled"; | |
416 | return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP); | |
417 | } | |
418 | case ETH_PKT_MCAST: | |
419 | if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { | |
420 | return true; | |
421 | } else { | |
422 | *fail_reason = "Multicast packet disabled"; | |
423 | return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP); | |
424 | } | |
425 | case ETH_PKT_UCAST: { | |
426 | bool matches; | |
427 | if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) { | |
428 | return true; | |
429 | } | |
430 | matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) && | |
431 | /* We only support one CAM register, CAM0. */ | |
432 | (emc->regs[REG_CAMEN] & (1 << 0)) && | |
433 | memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0); | |
434 | if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { | |
435 | *fail_reason = "MACADDR matched, comparison complemented"; | |
436 | return !matches; | |
437 | } else { | |
438 | *fail_reason = "MACADDR didn't match"; | |
439 | return matches; | |
440 | } | |
441 | } | |
442 | default: | |
443 | g_assert_not_reached(); | |
444 | } | |
445 | } | |
446 | ||
447 | static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf, | |
448 | size_t len) | |
449 | { | |
450 | const char *fail_reason = NULL; | |
451 | bool ok = emc_receive_filter1(emc, buf, len, &fail_reason); | |
452 | if (!ok) { | |
453 | trace_npcm7xx_emc_packet_filtered_out(fail_reason); | |
454 | } | |
455 | return ok; | |
456 | } | |
457 | ||
458 | static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1) | |
459 | { | |
460 | NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc)); | |
461 | const uint32_t len = len1; | |
462 | size_t max_frame_len; | |
463 | bool long_frame; | |
464 | uint32_t desc_addr; | |
465 | NPCM7xxEMCRxDesc rx_desc; | |
466 | uint32_t crc; | |
467 | uint8_t *crc_ptr; | |
468 | uint32_t buf_addr; | |
469 | ||
470 | trace_npcm7xx_emc_receiving_packet(len); | |
471 | ||
472 | if (!emc_can_receive(nc)) { | |
473 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__); | |
474 | return -1; | |
475 | } | |
476 | ||
477 | if (len < ETH_HLEN || | |
478 | /* Defensive programming: drop unsupportable large packets. */ | |
479 | len > 0xffff - CRC_LENGTH) { | |
480 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n", | |
481 | __func__, len); | |
482 | return len; | |
483 | } | |
484 | ||
485 | /* | |
486 | * DENI is set if EMC received the Length/Type field of the incoming | |
487 | * packet, so it will be set regardless of what happens next. | |
488 | */ | |
489 | emc_set_mista(emc, REG_MISTA_DENI); | |
490 | ||
491 | if (!emc_receive_filter(emc, buf, len)) { | |
492 | emc_update_rx_irq(emc); | |
493 | return len; | |
494 | } | |
495 | ||
496 | /* Huge frames (> DMARFC) are dropped. */ | |
497 | max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]); | |
498 | if (len + CRC_LENGTH > max_frame_len) { | |
499 | trace_npcm7xx_emc_packet_dropped(len); | |
500 | emc_set_mista(emc, REG_MISTA_DFOI); | |
501 | emc_update_rx_irq(emc); | |
502 | return len; | |
503 | } | |
504 | ||
505 | /* | |
506 | * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP | |
507 | * is set. | |
508 | */ | |
509 | long_frame = false; | |
510 | if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) { | |
511 | if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) { | |
512 | long_frame = true; | |
513 | } else { | |
514 | trace_npcm7xx_emc_packet_dropped(len); | |
515 | emc_set_mista(emc, REG_MISTA_PTLE); | |
516 | emc_update_rx_irq(emc); | |
517 | return len; | |
518 | } | |
519 | } | |
520 | ||
521 | desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]); | |
522 | if (emc_read_rx_desc(desc_addr, &rx_desc)) { | |
523 | /* Error reading descriptor, already reported. */ | |
524 | emc_halt_rx(emc, REG_MISTA_RXBERR); | |
525 | emc_update_rx_irq(emc); | |
526 | return len; | |
527 | } | |
528 | ||
529 | /* Nothing we can do if we don't own the descriptor. */ | |
530 | if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) { | |
531 | trace_npcm7xx_emc_cpu_owned_desc(desc_addr); | |
532 | emc_halt_rx(emc, REG_MISTA_RDU); | |
533 | emc_update_rx_irq(emc); | |
534 | return len; | |
535 | } | |
536 | ||
537 | crc = 0; | |
538 | crc_ptr = (uint8_t *) &crc; | |
539 | if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) { | |
540 | crc = cpu_to_be32(crc32(~0, buf, len)); | |
541 | } | |
542 | ||
543 | /* Give the descriptor back regardless of what happens. */ | |
544 | rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK; | |
545 | ||
546 | buf_addr = rx_desc.rxbsa; | |
547 | emc->regs[REG_CRXBSA] = buf_addr; | |
548 | if (dma_memory_write(&address_space_memory, buf_addr, buf, len) || | |
549 | (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) && | |
550 | dma_memory_write(&address_space_memory, buf_addr + len, crc_ptr, | |
551 | 4))) { | |
552 | qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n", | |
553 | __func__); | |
554 | emc_set_mista(emc, REG_MISTA_RXBERR); | |
555 | emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr); | |
556 | emc_update_rx_irq(emc); | |
557 | trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]); | |
558 | return len; | |
559 | } | |
560 | ||
561 | trace_npcm7xx_emc_received_packet(len); | |
562 | ||
563 | /* Note: We've already verified len+4 <= 0xffff. */ | |
564 | rx_desc.status_and_length = len; | |
565 | if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) { | |
566 | rx_desc.status_and_length += 4; | |
567 | } | |
568 | rx_desc.status_and_length |= RX_DESC_STATUS_RXGD; | |
569 | emc_set_mista(emc, REG_MISTA_RXGD); | |
570 | ||
571 | if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) { | |
572 | rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR; | |
573 | } | |
574 | if (long_frame) { | |
575 | rx_desc.status_and_length |= RX_DESC_STATUS_PTLE; | |
576 | } | |
577 | ||
578 | emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr); | |
579 | emc_update_rx_irq(emc); | |
580 | trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]); | |
581 | return len; | |
582 | } | |
583 | ||
584 | static void emc_try_receive_next_packet(NPCM7xxEMCState *emc) | |
585 | { | |
586 | if (emc_can_receive(qemu_get_queue(emc->nic))) { | |
587 | qemu_flush_queued_packets(qemu_get_queue(emc->nic)); | |
588 | } | |
589 | } | |
590 | ||
591 | static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size) | |
592 | { | |
593 | NPCM7xxEMCState *emc = opaque; | |
594 | uint32_t reg = offset / sizeof(uint32_t); | |
595 | uint32_t result; | |
596 | ||
597 | if (reg >= NPCM7XX_NUM_EMC_REGS) { | |
598 | qemu_log_mask(LOG_GUEST_ERROR, | |
599 | "%s: Invalid offset 0x%04" HWADDR_PRIx "\n", | |
600 | __func__, offset); | |
601 | return 0; | |
602 | } | |
603 | ||
604 | switch (reg) { | |
605 | case REG_MIID: | |
606 | /* | |
607 | * We don't implement MII. For determinism, always return zero as | |
608 | * writes record the last value written for debugging purposes. | |
609 | */ | |
610 | qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__); | |
611 | result = 0; | |
612 | break; | |
613 | case REG_TSDR: | |
614 | case REG_RSDR: | |
615 | qemu_log_mask(LOG_GUEST_ERROR, | |
616 | "%s: Read of write-only reg, %s/%d\n", | |
617 | __func__, emc_reg_name(reg), reg); | |
618 | return 0; | |
619 | default: | |
620 | result = emc->regs[reg]; | |
621 | break; | |
622 | } | |
623 | ||
624 | trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg); | |
625 | return result; | |
626 | } | |
627 | ||
628 | static void npcm7xx_emc_write(void *opaque, hwaddr offset, | |
629 | uint64_t v, unsigned size) | |
630 | { | |
631 | NPCM7xxEMCState *emc = opaque; | |
632 | uint32_t reg = offset / sizeof(uint32_t); | |
633 | uint32_t value = v; | |
634 | ||
635 | g_assert(size == sizeof(uint32_t)); | |
636 | ||
637 | if (reg >= NPCM7XX_NUM_EMC_REGS) { | |
638 | qemu_log_mask(LOG_GUEST_ERROR, | |
639 | "%s: Invalid offset 0x%04" HWADDR_PRIx "\n", | |
640 | __func__, offset); | |
641 | return; | |
642 | } | |
643 | ||
644 | trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value); | |
645 | ||
646 | switch (reg) { | |
647 | case REG_CAMCMR: | |
648 | emc->regs[reg] = value; | |
649 | break; | |
650 | case REG_CAMEN: | |
651 | /* Only CAM0 is supported, don't pretend otherwise. */ | |
652 | if (value & ~1) { | |
653 | qemu_log_mask(LOG_GUEST_ERROR, | |
654 | "%s: Only CAM0 is supported, cannot enable others" | |
655 | ": 0x%x\n", | |
656 | __func__, value); | |
657 | } | |
658 | emc->regs[reg] = value & 1; | |
659 | break; | |
660 | case REG_CAMM_BASE + 0: | |
661 | emc->regs[reg] = value; | |
662 | emc->conf.macaddr.a[0] = value >> 24; | |
663 | emc->conf.macaddr.a[1] = value >> 16; | |
664 | emc->conf.macaddr.a[2] = value >> 8; | |
665 | emc->conf.macaddr.a[3] = value >> 0; | |
666 | break; | |
667 | case REG_CAML_BASE + 0: | |
668 | emc->regs[reg] = value; | |
669 | emc->conf.macaddr.a[4] = value >> 24; | |
670 | emc->conf.macaddr.a[5] = value >> 16; | |
671 | break; | |
672 | case REG_MCMDR: { | |
673 | uint32_t prev; | |
674 | if (value & REG_MCMDR_SWR) { | |
675 | emc_soft_reset(emc); | |
676 | /* On h/w the reset happens over multiple cycles. For now KISS. */ | |
677 | break; | |
678 | } | |
679 | prev = emc->regs[reg]; | |
680 | emc->regs[reg] = value; | |
681 | /* Update tx state. */ | |
682 | if (!(prev & REG_MCMDR_TXON) && | |
683 | (value & REG_MCMDR_TXON)) { | |
684 | emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA]; | |
685 | /* | |
686 | * Linux kernel turns TX on with CPU still holding descriptor, | |
687 | * which suggests we should wait for a write to TSDR before trying | |
688 | * to send a packet: so we don't send one here. | |
689 | */ | |
690 | } else if ((prev & REG_MCMDR_TXON) && | |
691 | !(value & REG_MCMDR_TXON)) { | |
692 | emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA; | |
693 | } | |
694 | if (!(value & REG_MCMDR_TXON)) { | |
695 | emc_halt_tx(emc, 0); | |
696 | } | |
697 | /* Update rx state. */ | |
698 | if (!(prev & REG_MCMDR_RXON) && | |
699 | (value & REG_MCMDR_RXON)) { | |
700 | emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA]; | |
701 | } else if ((prev & REG_MCMDR_RXON) && | |
702 | !(value & REG_MCMDR_RXON)) { | |
703 | emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA; | |
704 | } | |
a62ee00a DE |
705 | if (value & REG_MCMDR_RXON) { |
706 | emc->rx_active = true; | |
707 | } else { | |
01c966b5 DE |
708 | emc_halt_rx(emc, 0); |
709 | } | |
710 | break; | |
711 | } | |
712 | case REG_TXDLSA: | |
713 | case REG_RXDLSA: | |
714 | case REG_DMARFC: | |
715 | case REG_MIID: | |
716 | emc->regs[reg] = value; | |
717 | break; | |
718 | case REG_MIEN: | |
719 | emc->regs[reg] = value; | |
720 | emc_update_irq_from_reg_change(emc); | |
721 | break; | |
722 | case REG_MISTA: | |
723 | /* Clear the bits that have 1 in "value". */ | |
724 | emc->regs[reg] &= ~value; | |
725 | emc_update_irq_from_reg_change(emc); | |
726 | break; | |
727 | case REG_MGSTA: | |
728 | /* Clear the bits that have 1 in "value". */ | |
729 | emc->regs[reg] &= ~value; | |
730 | break; | |
731 | case REG_TSDR: | |
732 | if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) { | |
733 | emc->tx_active = true; | |
734 | /* Keep trying to send packets until we run out. */ | |
735 | while (emc->tx_active) { | |
736 | emc_try_send_next_packet(emc); | |
737 | } | |
738 | } | |
739 | break; | |
740 | case REG_RSDR: | |
741 | if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) { | |
742 | emc->rx_active = true; | |
743 | emc_try_receive_next_packet(emc); | |
744 | } | |
745 | break; | |
746 | case REG_MIIDA: | |
747 | emc->regs[reg] = value & ~REG_MIIDA_BUSY; | |
748 | break; | |
749 | case REG_MRPC: | |
750 | case REG_MRPCC: | |
751 | case REG_MREPC: | |
752 | case REG_CTXDSA: | |
753 | case REG_CTXBSA: | |
754 | case REG_CRXDSA: | |
755 | case REG_CRXBSA: | |
756 | qemu_log_mask(LOG_GUEST_ERROR, | |
757 | "%s: Write to read-only reg %s/%d\n", | |
758 | __func__, emc_reg_name(reg), reg); | |
759 | break; | |
760 | default: | |
761 | qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n", | |
762 | __func__, emc_reg_name(reg), reg); | |
763 | break; | |
764 | } | |
765 | } | |
766 | ||
767 | static const struct MemoryRegionOps npcm7xx_emc_ops = { | |
768 | .read = npcm7xx_emc_read, | |
769 | .write = npcm7xx_emc_write, | |
770 | .endianness = DEVICE_LITTLE_ENDIAN, | |
771 | .valid = { | |
772 | .min_access_size = 4, | |
773 | .max_access_size = 4, | |
774 | .unaligned = false, | |
775 | }, | |
776 | }; | |
777 | ||
778 | static void emc_cleanup(NetClientState *nc) | |
779 | { | |
780 | /* Nothing to do yet. */ | |
781 | } | |
782 | ||
783 | static NetClientInfo net_npcm7xx_emc_info = { | |
784 | .type = NET_CLIENT_DRIVER_NIC, | |
785 | .size = sizeof(NICState), | |
786 | .can_receive = emc_can_receive, | |
787 | .receive = emc_receive, | |
788 | .cleanup = emc_cleanup, | |
789 | .link_status_changed = emc_set_link, | |
790 | }; | |
791 | ||
792 | static void npcm7xx_emc_realize(DeviceState *dev, Error **errp) | |
793 | { | |
794 | NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); | |
795 | SysBusDevice *sbd = SYS_BUS_DEVICE(emc); | |
796 | ||
797 | memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc, | |
798 | TYPE_NPCM7XX_EMC, 4 * KiB); | |
799 | sysbus_init_mmio(sbd, &emc->iomem); | |
800 | sysbus_init_irq(sbd, &emc->tx_irq); | |
801 | sysbus_init_irq(sbd, &emc->rx_irq); | |
802 | ||
803 | qemu_macaddr_default_if_unset(&emc->conf.macaddr); | |
804 | emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf, | |
805 | object_get_typename(OBJECT(dev)), dev->id, emc); | |
806 | qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a); | |
807 | } | |
808 | ||
809 | static void npcm7xx_emc_unrealize(DeviceState *dev) | |
810 | { | |
811 | NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); | |
812 | ||
813 | qemu_del_nic(emc->nic); | |
814 | } | |
815 | ||
816 | static const VMStateDescription vmstate_npcm7xx_emc = { | |
817 | .name = TYPE_NPCM7XX_EMC, | |
818 | .version_id = 0, | |
819 | .minimum_version_id = 0, | |
820 | .fields = (VMStateField[]) { | |
821 | VMSTATE_UINT8(emc_num, NPCM7xxEMCState), | |
822 | VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS), | |
823 | VMSTATE_BOOL(tx_active, NPCM7xxEMCState), | |
824 | VMSTATE_BOOL(rx_active, NPCM7xxEMCState), | |
825 | VMSTATE_END_OF_LIST(), | |
826 | }, | |
827 | }; | |
828 | ||
829 | static Property npcm7xx_emc_properties[] = { | |
830 | DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf), | |
831 | DEFINE_PROP_END_OF_LIST(), | |
832 | }; | |
833 | ||
834 | static void npcm7xx_emc_class_init(ObjectClass *klass, void *data) | |
835 | { | |
836 | DeviceClass *dc = DEVICE_CLASS(klass); | |
837 | ||
838 | set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); | |
839 | dc->desc = "NPCM7xx EMC Controller"; | |
840 | dc->realize = npcm7xx_emc_realize; | |
841 | dc->unrealize = npcm7xx_emc_unrealize; | |
842 | dc->reset = npcm7xx_emc_reset; | |
843 | dc->vmsd = &vmstate_npcm7xx_emc; | |
844 | device_class_set_props(dc, npcm7xx_emc_properties); | |
845 | } | |
846 | ||
847 | static const TypeInfo npcm7xx_emc_info = { | |
848 | .name = TYPE_NPCM7XX_EMC, | |
849 | .parent = TYPE_SYS_BUS_DEVICE, | |
850 | .instance_size = sizeof(NPCM7xxEMCState), | |
851 | .class_init = npcm7xx_emc_class_init, | |
852 | }; | |
853 | ||
854 | static void npcm7xx_emc_register_type(void) | |
855 | { | |
856 | type_register_static(&npcm7xx_emc_info); | |
857 | } | |
858 | ||
859 | type_init(npcm7xx_emc_register_type) |