101c966b5SDoug Evans /* 201c966b5SDoug Evans * Nuvoton NPCM7xx EMC Module 301c966b5SDoug Evans * 401c966b5SDoug Evans * Copyright 2020 Google LLC 501c966b5SDoug Evans * 601c966b5SDoug Evans * This program is free software; you can redistribute it and/or modify it 701c966b5SDoug Evans * under the terms of the GNU General Public License as published by the 801c966b5SDoug Evans * Free Software Foundation; either version 2 of the License, or 901c966b5SDoug Evans * (at your option) any later version. 1001c966b5SDoug Evans * 1101c966b5SDoug Evans * This program is distributed in the hope that it will be useful, but WITHOUT 1201c966b5SDoug Evans * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1301c966b5SDoug Evans * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1401c966b5SDoug Evans * for more details. 1501c966b5SDoug Evans * 1601c966b5SDoug Evans * Unsupported/unimplemented features: 1701c966b5SDoug Evans * - MCMDR.FDUP (full duplex) is ignored, half duplex is not supported 1801c966b5SDoug Evans * - Only CAM0 is supported, CAM[1-15] are not 1901c966b5SDoug Evans * - writes to CAMEN.[1-15] are ignored, these bits always read as zeroes 2001c966b5SDoug Evans * - MII is not implemented, MIIDA.BUSY and MIID always return zero 2101c966b5SDoug Evans * - MCMDR.LBK is not implemented 2201c966b5SDoug Evans * - MCMDR.{OPMOD,ENSQE,AEP,ARP} are not supported 2301c966b5SDoug Evans * - H/W FIFOs are not supported, MCMDR.FFTCR is ignored 2401c966b5SDoug Evans * - MGSTA.SQE is not supported 2501c966b5SDoug Evans * - pause and control frames are not implemented 2601c966b5SDoug Evans * - MGSTA.CCNT is not supported 2701c966b5SDoug Evans * - MPCNT, DMARFS are not implemented 2801c966b5SDoug Evans */ 2901c966b5SDoug Evans 3001c966b5SDoug Evans #include "qemu/osdep.h" 3101c966b5SDoug Evans 3201c966b5SDoug Evans /* For crc32 */ 3301c966b5SDoug Evans #include <zlib.h> 3401c966b5SDoug Evans 3501c966b5SDoug Evans #include "qemu-common.h" 3601c966b5SDoug Evans #include "hw/irq.h" 3701c966b5SDoug Evans #include "hw/qdev-clock.h" 3801c966b5SDoug Evans #include "hw/qdev-properties.h" 3901c966b5SDoug Evans #include "hw/net/npcm7xx_emc.h" 4001c966b5SDoug Evans #include "net/eth.h" 4101c966b5SDoug Evans #include "migration/vmstate.h" 4201c966b5SDoug Evans #include "qemu/bitops.h" 4301c966b5SDoug Evans #include "qemu/error-report.h" 4401c966b5SDoug Evans #include "qemu/log.h" 4501c966b5SDoug Evans #include "qemu/module.h" 4601c966b5SDoug Evans #include "qemu/units.h" 4701c966b5SDoug Evans #include "sysemu/dma.h" 4801c966b5SDoug Evans #include "trace.h" 4901c966b5SDoug Evans 5001c966b5SDoug Evans #define CRC_LENGTH 4 5101c966b5SDoug Evans 5201c966b5SDoug Evans /* 5301c966b5SDoug Evans * The maximum size of a (layer 2) ethernet frame as defined by 802.3. 5401c966b5SDoug Evans * 1518 = 6(dest macaddr) + 6(src macaddr) + 2(proto) + 4(crc) + 1500(payload) 5501c966b5SDoug Evans * This does not include an additional 4 for the vlan field (802.1q). 5601c966b5SDoug Evans */ 5701c966b5SDoug Evans #define MAX_ETH_FRAME_SIZE 1518 5801c966b5SDoug Evans 5901c966b5SDoug Evans static const char *emc_reg_name(int regno) 6001c966b5SDoug Evans { 6101c966b5SDoug Evans #define REG(name) case REG_ ## name: return #name; 6201c966b5SDoug Evans switch (regno) { 6301c966b5SDoug Evans REG(CAMCMR) 6401c966b5SDoug Evans REG(CAMEN) 6501c966b5SDoug Evans REG(TXDLSA) 6601c966b5SDoug Evans REG(RXDLSA) 6701c966b5SDoug Evans REG(MCMDR) 6801c966b5SDoug Evans REG(MIID) 6901c966b5SDoug Evans REG(MIIDA) 7001c966b5SDoug Evans REG(FFTCR) 7101c966b5SDoug Evans REG(TSDR) 7201c966b5SDoug Evans REG(RSDR) 7301c966b5SDoug Evans REG(DMARFC) 7401c966b5SDoug Evans REG(MIEN) 7501c966b5SDoug Evans REG(MISTA) 7601c966b5SDoug Evans REG(MGSTA) 7701c966b5SDoug Evans REG(MPCNT) 7801c966b5SDoug Evans REG(MRPC) 7901c966b5SDoug Evans REG(MRPCC) 8001c966b5SDoug Evans REG(MREPC) 8101c966b5SDoug Evans REG(DMARFS) 8201c966b5SDoug Evans REG(CTXDSA) 8301c966b5SDoug Evans REG(CTXBSA) 8401c966b5SDoug Evans REG(CRXDSA) 8501c966b5SDoug Evans REG(CRXBSA) 8601c966b5SDoug Evans case REG_CAMM_BASE + 0: return "CAM0M"; 8701c966b5SDoug Evans case REG_CAML_BASE + 0: return "CAM0L"; 8801c966b5SDoug Evans case REG_CAMM_BASE + 2 ... REG_CAMML_LAST: 8901c966b5SDoug Evans /* Only CAM0 is supported, fold the others into something simple. */ 9001c966b5SDoug Evans if (regno & 1) { 9101c966b5SDoug Evans return "CAM<n>L"; 9201c966b5SDoug Evans } else { 9301c966b5SDoug Evans return "CAM<n>M"; 9401c966b5SDoug Evans } 9501c966b5SDoug Evans default: return "UNKNOWN"; 9601c966b5SDoug Evans } 9701c966b5SDoug Evans #undef REG 9801c966b5SDoug Evans } 9901c966b5SDoug Evans 10001c966b5SDoug Evans static void emc_reset(NPCM7xxEMCState *emc) 10101c966b5SDoug Evans { 10201c966b5SDoug Evans trace_npcm7xx_emc_reset(emc->emc_num); 10301c966b5SDoug Evans 10401c966b5SDoug Evans memset(&emc->regs[0], 0, sizeof(emc->regs)); 10501c966b5SDoug Evans 10601c966b5SDoug Evans /* These regs have non-zero reset values. */ 10701c966b5SDoug Evans emc->regs[REG_TXDLSA] = 0xfffffffc; 10801c966b5SDoug Evans emc->regs[REG_RXDLSA] = 0xfffffffc; 10901c966b5SDoug Evans emc->regs[REG_MIIDA] = 0x00900000; 11001c966b5SDoug Evans emc->regs[REG_FFTCR] = 0x0101; 11101c966b5SDoug Evans emc->regs[REG_DMARFC] = 0x0800; 11201c966b5SDoug Evans emc->regs[REG_MPCNT] = 0x7fff; 11301c966b5SDoug Evans 11401c966b5SDoug Evans emc->tx_active = false; 11501c966b5SDoug Evans emc->rx_active = false; 11601c966b5SDoug Evans } 11701c966b5SDoug Evans 11801c966b5SDoug Evans static void npcm7xx_emc_reset(DeviceState *dev) 11901c966b5SDoug Evans { 12001c966b5SDoug Evans NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); 12101c966b5SDoug Evans emc_reset(emc); 12201c966b5SDoug Evans } 12301c966b5SDoug Evans 12401c966b5SDoug Evans static void emc_soft_reset(NPCM7xxEMCState *emc) 12501c966b5SDoug Evans { 12601c966b5SDoug Evans /* 12701c966b5SDoug Evans * The docs say at least MCMDR.{LBK,OPMOD} bits are not changed during a 12801c966b5SDoug Evans * soft reset, but does not go into further detail. For now, KISS. 12901c966b5SDoug Evans */ 13001c966b5SDoug Evans uint32_t mcmdr = emc->regs[REG_MCMDR]; 13101c966b5SDoug Evans emc_reset(emc); 13201c966b5SDoug Evans emc->regs[REG_MCMDR] = mcmdr & (REG_MCMDR_LBK | REG_MCMDR_OPMOD); 13301c966b5SDoug Evans 13401c966b5SDoug Evans qemu_set_irq(emc->tx_irq, 0); 13501c966b5SDoug Evans qemu_set_irq(emc->rx_irq, 0); 13601c966b5SDoug Evans } 13701c966b5SDoug Evans 13801c966b5SDoug Evans static void emc_set_link(NetClientState *nc) 13901c966b5SDoug Evans { 14001c966b5SDoug Evans /* Nothing to do yet. */ 14101c966b5SDoug Evans } 14201c966b5SDoug Evans 14301c966b5SDoug Evans /* MISTA.TXINTR is the union of the individual bits with their enables. */ 14401c966b5SDoug Evans static void emc_update_mista_txintr(NPCM7xxEMCState *emc) 14501c966b5SDoug Evans { 14601c966b5SDoug Evans /* Only look at the bits we support. */ 14701c966b5SDoug Evans uint32_t mask = (REG_MISTA_TXBERR | 14801c966b5SDoug Evans REG_MISTA_TDU | 14901c966b5SDoug Evans REG_MISTA_TXCP); 15001c966b5SDoug Evans if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) { 15101c966b5SDoug Evans emc->regs[REG_MISTA] |= REG_MISTA_TXINTR; 15201c966b5SDoug Evans } else { 15301c966b5SDoug Evans emc->regs[REG_MISTA] &= ~REG_MISTA_TXINTR; 15401c966b5SDoug Evans } 15501c966b5SDoug Evans } 15601c966b5SDoug Evans 15701c966b5SDoug Evans /* MISTA.RXINTR is the union of the individual bits with their enables. */ 15801c966b5SDoug Evans static void emc_update_mista_rxintr(NPCM7xxEMCState *emc) 15901c966b5SDoug Evans { 16001c966b5SDoug Evans /* Only look at the bits we support. */ 16101c966b5SDoug Evans uint32_t mask = (REG_MISTA_RXBERR | 16201c966b5SDoug Evans REG_MISTA_RDU | 16301c966b5SDoug Evans REG_MISTA_RXGD); 16401c966b5SDoug Evans if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & mask) { 16501c966b5SDoug Evans emc->regs[REG_MISTA] |= REG_MISTA_RXINTR; 16601c966b5SDoug Evans } else { 16701c966b5SDoug Evans emc->regs[REG_MISTA] &= ~REG_MISTA_RXINTR; 16801c966b5SDoug Evans } 16901c966b5SDoug Evans } 17001c966b5SDoug Evans 17101c966b5SDoug Evans /* N.B. emc_update_mista_txintr must have already been called. */ 17201c966b5SDoug Evans static void emc_update_tx_irq(NPCM7xxEMCState *emc) 17301c966b5SDoug Evans { 17401c966b5SDoug Evans int level = !!(emc->regs[REG_MISTA] & 17501c966b5SDoug Evans emc->regs[REG_MIEN] & 17601c966b5SDoug Evans REG_MISTA_TXINTR); 17701c966b5SDoug Evans trace_npcm7xx_emc_update_tx_irq(level); 17801c966b5SDoug Evans qemu_set_irq(emc->tx_irq, level); 17901c966b5SDoug Evans } 18001c966b5SDoug Evans 18101c966b5SDoug Evans /* N.B. emc_update_mista_rxintr must have already been called. */ 18201c966b5SDoug Evans static void emc_update_rx_irq(NPCM7xxEMCState *emc) 18301c966b5SDoug Evans { 18401c966b5SDoug Evans int level = !!(emc->regs[REG_MISTA] & 18501c966b5SDoug Evans emc->regs[REG_MIEN] & 18601c966b5SDoug Evans REG_MISTA_RXINTR); 18701c966b5SDoug Evans trace_npcm7xx_emc_update_rx_irq(level); 18801c966b5SDoug Evans qemu_set_irq(emc->rx_irq, level); 18901c966b5SDoug Evans } 19001c966b5SDoug Evans 19101c966b5SDoug Evans /* Update IRQ states due to changes in MIEN,MISTA. */ 19201c966b5SDoug Evans static void emc_update_irq_from_reg_change(NPCM7xxEMCState *emc) 19301c966b5SDoug Evans { 19401c966b5SDoug Evans emc_update_mista_txintr(emc); 19501c966b5SDoug Evans emc_update_tx_irq(emc); 19601c966b5SDoug Evans 19701c966b5SDoug Evans emc_update_mista_rxintr(emc); 19801c966b5SDoug Evans emc_update_rx_irq(emc); 19901c966b5SDoug Evans } 20001c966b5SDoug Evans 20101c966b5SDoug Evans static int emc_read_tx_desc(dma_addr_t addr, NPCM7xxEMCTxDesc *desc) 20201c966b5SDoug Evans { 203*ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(&address_space_memory, addr, desc, 204*ba06fe8aSPhilippe Mathieu-Daudé sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) { 20501c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" 20601c966b5SDoug Evans HWADDR_PRIx "\n", __func__, addr); 20701c966b5SDoug Evans return -1; 20801c966b5SDoug Evans } 20901c966b5SDoug Evans desc->flags = le32_to_cpu(desc->flags); 21001c966b5SDoug Evans desc->txbsa = le32_to_cpu(desc->txbsa); 21101c966b5SDoug Evans desc->status_and_length = le32_to_cpu(desc->status_and_length); 21201c966b5SDoug Evans desc->ntxdsa = le32_to_cpu(desc->ntxdsa); 21301c966b5SDoug Evans return 0; 21401c966b5SDoug Evans } 21501c966b5SDoug Evans 21601c966b5SDoug Evans static int emc_write_tx_desc(const NPCM7xxEMCTxDesc *desc, dma_addr_t addr) 21701c966b5SDoug Evans { 21801c966b5SDoug Evans NPCM7xxEMCTxDesc le_desc; 21901c966b5SDoug Evans 22001c966b5SDoug Evans le_desc.flags = cpu_to_le32(desc->flags); 22101c966b5SDoug Evans le_desc.txbsa = cpu_to_le32(desc->txbsa); 22201c966b5SDoug Evans le_desc.status_and_length = cpu_to_le32(desc->status_and_length); 22301c966b5SDoug Evans le_desc.ntxdsa = cpu_to_le32(desc->ntxdsa); 22401c966b5SDoug Evans if (dma_memory_write(&address_space_memory, addr, &le_desc, 225*ba06fe8aSPhilippe Mathieu-Daudé sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) { 22601c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" 22701c966b5SDoug Evans HWADDR_PRIx "\n", __func__, addr); 22801c966b5SDoug Evans return -1; 22901c966b5SDoug Evans } 23001c966b5SDoug Evans return 0; 23101c966b5SDoug Evans } 23201c966b5SDoug Evans 23301c966b5SDoug Evans static int emc_read_rx_desc(dma_addr_t addr, NPCM7xxEMCRxDesc *desc) 23401c966b5SDoug Evans { 235*ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(&address_space_memory, addr, desc, 236*ba06fe8aSPhilippe Mathieu-Daudé sizeof(*desc), MEMTXATTRS_UNSPECIFIED)) { 23701c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read descriptor @ 0x%" 23801c966b5SDoug Evans HWADDR_PRIx "\n", __func__, addr); 23901c966b5SDoug Evans return -1; 24001c966b5SDoug Evans } 24101c966b5SDoug Evans desc->status_and_length = le32_to_cpu(desc->status_and_length); 24201c966b5SDoug Evans desc->rxbsa = le32_to_cpu(desc->rxbsa); 24301c966b5SDoug Evans desc->reserved = le32_to_cpu(desc->reserved); 24401c966b5SDoug Evans desc->nrxdsa = le32_to_cpu(desc->nrxdsa); 24501c966b5SDoug Evans return 0; 24601c966b5SDoug Evans } 24701c966b5SDoug Evans 24801c966b5SDoug Evans static int emc_write_rx_desc(const NPCM7xxEMCRxDesc *desc, dma_addr_t addr) 24901c966b5SDoug Evans { 25001c966b5SDoug Evans NPCM7xxEMCRxDesc le_desc; 25101c966b5SDoug Evans 25201c966b5SDoug Evans le_desc.status_and_length = cpu_to_le32(desc->status_and_length); 25301c966b5SDoug Evans le_desc.rxbsa = cpu_to_le32(desc->rxbsa); 25401c966b5SDoug Evans le_desc.reserved = cpu_to_le32(desc->reserved); 25501c966b5SDoug Evans le_desc.nrxdsa = cpu_to_le32(desc->nrxdsa); 25601c966b5SDoug Evans if (dma_memory_write(&address_space_memory, addr, &le_desc, 257*ba06fe8aSPhilippe Mathieu-Daudé sizeof(le_desc), MEMTXATTRS_UNSPECIFIED)) { 25801c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to write descriptor @ 0x%" 25901c966b5SDoug Evans HWADDR_PRIx "\n", __func__, addr); 26001c966b5SDoug Evans return -1; 26101c966b5SDoug Evans } 26201c966b5SDoug Evans return 0; 26301c966b5SDoug Evans } 26401c966b5SDoug Evans 26501c966b5SDoug Evans static void emc_set_mista(NPCM7xxEMCState *emc, uint32_t flags) 26601c966b5SDoug Evans { 26701c966b5SDoug Evans trace_npcm7xx_emc_set_mista(flags); 26801c966b5SDoug Evans emc->regs[REG_MISTA] |= flags; 26901c966b5SDoug Evans if (extract32(flags, 16, 16)) { 27001c966b5SDoug Evans emc_update_mista_txintr(emc); 27101c966b5SDoug Evans } 27201c966b5SDoug Evans if (extract32(flags, 0, 16)) { 27301c966b5SDoug Evans emc_update_mista_rxintr(emc); 27401c966b5SDoug Evans } 27501c966b5SDoug Evans } 27601c966b5SDoug Evans 27701c966b5SDoug Evans static void emc_halt_tx(NPCM7xxEMCState *emc, uint32_t mista_flag) 27801c966b5SDoug Evans { 27901c966b5SDoug Evans emc->tx_active = false; 28001c966b5SDoug Evans emc_set_mista(emc, mista_flag); 28101c966b5SDoug Evans } 28201c966b5SDoug Evans 28301c966b5SDoug Evans static void emc_halt_rx(NPCM7xxEMCState *emc, uint32_t mista_flag) 28401c966b5SDoug Evans { 28501c966b5SDoug Evans emc->rx_active = false; 28601c966b5SDoug Evans emc_set_mista(emc, mista_flag); 28701c966b5SDoug Evans } 28801c966b5SDoug Evans 289530cd6c2SPatrick Venture static void emc_enable_rx_and_flush(NPCM7xxEMCState *emc) 290530cd6c2SPatrick Venture { 291530cd6c2SPatrick Venture emc->rx_active = true; 292530cd6c2SPatrick Venture qemu_flush_queued_packets(qemu_get_queue(emc->nic)); 293530cd6c2SPatrick Venture } 294530cd6c2SPatrick Venture 29501c966b5SDoug Evans static void emc_set_next_tx_descriptor(NPCM7xxEMCState *emc, 29601c966b5SDoug Evans const NPCM7xxEMCTxDesc *tx_desc, 29701c966b5SDoug Evans uint32_t desc_addr) 29801c966b5SDoug Evans { 29901c966b5SDoug Evans /* Update the current descriptor, if only to reset the owner flag. */ 30001c966b5SDoug Evans if (emc_write_tx_desc(tx_desc, desc_addr)) { 30101c966b5SDoug Evans /* 30201c966b5SDoug Evans * We just read it so this shouldn't generally happen. 30301c966b5SDoug Evans * Error already reported. 30401c966b5SDoug Evans */ 30501c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_TXBERR); 30601c966b5SDoug Evans } 30701c966b5SDoug Evans emc->regs[REG_CTXDSA] = TX_DESC_NTXDSA(tx_desc->ntxdsa); 30801c966b5SDoug Evans } 30901c966b5SDoug Evans 31001c966b5SDoug Evans static void emc_set_next_rx_descriptor(NPCM7xxEMCState *emc, 31101c966b5SDoug Evans const NPCM7xxEMCRxDesc *rx_desc, 31201c966b5SDoug Evans uint32_t desc_addr) 31301c966b5SDoug Evans { 31401c966b5SDoug Evans /* Update the current descriptor, if only to reset the owner flag. */ 31501c966b5SDoug Evans if (emc_write_rx_desc(rx_desc, desc_addr)) { 31601c966b5SDoug Evans /* 31701c966b5SDoug Evans * We just read it so this shouldn't generally happen. 31801c966b5SDoug Evans * Error already reported. 31901c966b5SDoug Evans */ 32001c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_RXBERR); 32101c966b5SDoug Evans } 32201c966b5SDoug Evans emc->regs[REG_CRXDSA] = RX_DESC_NRXDSA(rx_desc->nrxdsa); 32301c966b5SDoug Evans } 32401c966b5SDoug Evans 32501c966b5SDoug Evans static void emc_try_send_next_packet(NPCM7xxEMCState *emc) 32601c966b5SDoug Evans { 32701c966b5SDoug Evans /* Working buffer for sending out packets. Most packets fit in this. */ 32801c966b5SDoug Evans #define TX_BUFFER_SIZE 2048 32901c966b5SDoug Evans uint8_t tx_send_buffer[TX_BUFFER_SIZE]; 33001c966b5SDoug Evans uint32_t desc_addr = TX_DESC_NTXDSA(emc->regs[REG_CTXDSA]); 33101c966b5SDoug Evans NPCM7xxEMCTxDesc tx_desc; 33201c966b5SDoug Evans uint32_t next_buf_addr, length; 33301c966b5SDoug Evans uint8_t *buf; 33401c966b5SDoug Evans g_autofree uint8_t *malloced_buf = NULL; 33501c966b5SDoug Evans 33601c966b5SDoug Evans if (emc_read_tx_desc(desc_addr, &tx_desc)) { 33701c966b5SDoug Evans /* Error reading descriptor, already reported. */ 33801c966b5SDoug Evans emc_halt_tx(emc, REG_MISTA_TXBERR); 33901c966b5SDoug Evans emc_update_tx_irq(emc); 34001c966b5SDoug Evans return; 34101c966b5SDoug Evans } 34201c966b5SDoug Evans 34301c966b5SDoug Evans /* Nothing we can do if we don't own the descriptor. */ 34401c966b5SDoug Evans if (!(tx_desc.flags & TX_DESC_FLAG_OWNER_MASK)) { 34501c966b5SDoug Evans trace_npcm7xx_emc_cpu_owned_desc(desc_addr); 34601c966b5SDoug Evans emc_halt_tx(emc, REG_MISTA_TDU); 34701c966b5SDoug Evans emc_update_tx_irq(emc); 34801c966b5SDoug Evans return; 34901c966b5SDoug Evans } 35001c966b5SDoug Evans 35101c966b5SDoug Evans /* Give the descriptor back regardless of what happens. */ 35201c966b5SDoug Evans tx_desc.flags &= ~TX_DESC_FLAG_OWNER_MASK; 35301c966b5SDoug Evans tx_desc.status_and_length &= 0xffff; 35401c966b5SDoug Evans 35501c966b5SDoug Evans /* 35601c966b5SDoug Evans * Despite the h/w documentation saying the tx buffer is word aligned, 35701c966b5SDoug Evans * the linux driver does not word align the buffer. There is value in not 35801c966b5SDoug Evans * aligning the buffer: See the description of NET_IP_ALIGN in linux 35901c966b5SDoug Evans * kernel sources. 36001c966b5SDoug Evans */ 36101c966b5SDoug Evans next_buf_addr = tx_desc.txbsa; 36201c966b5SDoug Evans emc->regs[REG_CTXBSA] = next_buf_addr; 36301c966b5SDoug Evans length = TX_DESC_PKT_LEN(tx_desc.status_and_length); 36401c966b5SDoug Evans buf = &tx_send_buffer[0]; 36501c966b5SDoug Evans 36601c966b5SDoug Evans if (length > sizeof(tx_send_buffer)) { 36701c966b5SDoug Evans malloced_buf = g_malloc(length); 36801c966b5SDoug Evans buf = malloced_buf; 36901c966b5SDoug Evans } 37001c966b5SDoug Evans 371*ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_read(&address_space_memory, next_buf_addr, buf, 372*ba06fe8aSPhilippe Mathieu-Daudé length, MEMTXATTRS_UNSPECIFIED)) { 37301c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Failed to read packet @ 0x%x\n", 37401c966b5SDoug Evans __func__, next_buf_addr); 37501c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_TXBERR); 37601c966b5SDoug Evans emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr); 37701c966b5SDoug Evans emc_update_tx_irq(emc); 37801c966b5SDoug Evans trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]); 37901c966b5SDoug Evans return; 38001c966b5SDoug Evans } 38101c966b5SDoug Evans 38201c966b5SDoug Evans if ((tx_desc.flags & TX_DESC_FLAG_PADEN) && (length < MIN_PACKET_LENGTH)) { 38301c966b5SDoug Evans memset(buf + length, 0, MIN_PACKET_LENGTH - length); 38401c966b5SDoug Evans length = MIN_PACKET_LENGTH; 38501c966b5SDoug Evans } 38601c966b5SDoug Evans 38701c966b5SDoug Evans /* N.B. emc_receive can get called here. */ 38801c966b5SDoug Evans qemu_send_packet(qemu_get_queue(emc->nic), buf, length); 38901c966b5SDoug Evans trace_npcm7xx_emc_sent_packet(length); 39001c966b5SDoug Evans 39101c966b5SDoug Evans tx_desc.status_and_length |= TX_DESC_STATUS_TXCP; 39201c966b5SDoug Evans if (tx_desc.flags & TX_DESC_FLAG_INTEN) { 39301c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_TXCP); 39401c966b5SDoug Evans } 39501c966b5SDoug Evans if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_TXINTR) { 39601c966b5SDoug Evans tx_desc.status_and_length |= TX_DESC_STATUS_TXINTR; 39701c966b5SDoug Evans } 39801c966b5SDoug Evans 39901c966b5SDoug Evans emc_set_next_tx_descriptor(emc, &tx_desc, desc_addr); 40001c966b5SDoug Evans emc_update_tx_irq(emc); 40101c966b5SDoug Evans trace_npcm7xx_emc_tx_done(emc->regs[REG_CTXDSA]); 40201c966b5SDoug Evans } 40301c966b5SDoug Evans 40401c966b5SDoug Evans static bool emc_can_receive(NetClientState *nc) 40501c966b5SDoug Evans { 40601c966b5SDoug Evans NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc)); 40701c966b5SDoug Evans 40801c966b5SDoug Evans bool can_receive = emc->rx_active; 40901c966b5SDoug Evans trace_npcm7xx_emc_can_receive(can_receive); 41001c966b5SDoug Evans return can_receive; 41101c966b5SDoug Evans } 41201c966b5SDoug Evans 41301c966b5SDoug Evans /* If result is false then *fail_reason contains the reason. */ 41401c966b5SDoug Evans static bool emc_receive_filter1(NPCM7xxEMCState *emc, const uint8_t *buf, 41501c966b5SDoug Evans size_t len, const char **fail_reason) 41601c966b5SDoug Evans { 41701c966b5SDoug Evans eth_pkt_types_e pkt_type = get_eth_packet_type(PKT_GET_ETH_HDR(buf)); 41801c966b5SDoug Evans 41901c966b5SDoug Evans switch (pkt_type) { 42001c966b5SDoug Evans case ETH_PKT_BCAST: 42101c966b5SDoug Evans if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { 42201c966b5SDoug Evans return true; 42301c966b5SDoug Evans } else { 42401c966b5SDoug Evans *fail_reason = "Broadcast packet disabled"; 42501c966b5SDoug Evans return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_ABP); 42601c966b5SDoug Evans } 42701c966b5SDoug Evans case ETH_PKT_MCAST: 42801c966b5SDoug Evans if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { 42901c966b5SDoug Evans return true; 43001c966b5SDoug Evans } else { 43101c966b5SDoug Evans *fail_reason = "Multicast packet disabled"; 43201c966b5SDoug Evans return !!(emc->regs[REG_CAMCMR] & REG_CAMCMR_AMP); 43301c966b5SDoug Evans } 43401c966b5SDoug Evans case ETH_PKT_UCAST: { 43501c966b5SDoug Evans bool matches; 43601c966b5SDoug Evans if (emc->regs[REG_CAMCMR] & REG_CAMCMR_AUP) { 43701c966b5SDoug Evans return true; 43801c966b5SDoug Evans } 43901c966b5SDoug Evans matches = ((emc->regs[REG_CAMCMR] & REG_CAMCMR_ECMP) && 44001c966b5SDoug Evans /* We only support one CAM register, CAM0. */ 44101c966b5SDoug Evans (emc->regs[REG_CAMEN] & (1 << 0)) && 44201c966b5SDoug Evans memcmp(buf, emc->conf.macaddr.a, ETH_ALEN) == 0); 44301c966b5SDoug Evans if (emc->regs[REG_CAMCMR] & REG_CAMCMR_CCAM) { 44401c966b5SDoug Evans *fail_reason = "MACADDR matched, comparison complemented"; 44501c966b5SDoug Evans return !matches; 44601c966b5SDoug Evans } else { 44701c966b5SDoug Evans *fail_reason = "MACADDR didn't match"; 44801c966b5SDoug Evans return matches; 44901c966b5SDoug Evans } 45001c966b5SDoug Evans } 45101c966b5SDoug Evans default: 45201c966b5SDoug Evans g_assert_not_reached(); 45301c966b5SDoug Evans } 45401c966b5SDoug Evans } 45501c966b5SDoug Evans 45601c966b5SDoug Evans static bool emc_receive_filter(NPCM7xxEMCState *emc, const uint8_t *buf, 45701c966b5SDoug Evans size_t len) 45801c966b5SDoug Evans { 45901c966b5SDoug Evans const char *fail_reason = NULL; 46001c966b5SDoug Evans bool ok = emc_receive_filter1(emc, buf, len, &fail_reason); 46101c966b5SDoug Evans if (!ok) { 46201c966b5SDoug Evans trace_npcm7xx_emc_packet_filtered_out(fail_reason); 46301c966b5SDoug Evans } 46401c966b5SDoug Evans return ok; 46501c966b5SDoug Evans } 46601c966b5SDoug Evans 46701c966b5SDoug Evans static ssize_t emc_receive(NetClientState *nc, const uint8_t *buf, size_t len1) 46801c966b5SDoug Evans { 46901c966b5SDoug Evans NPCM7xxEMCState *emc = NPCM7XX_EMC(qemu_get_nic_opaque(nc)); 47001c966b5SDoug Evans const uint32_t len = len1; 47101c966b5SDoug Evans size_t max_frame_len; 47201c966b5SDoug Evans bool long_frame; 47301c966b5SDoug Evans uint32_t desc_addr; 47401c966b5SDoug Evans NPCM7xxEMCRxDesc rx_desc; 47501c966b5SDoug Evans uint32_t crc; 47601c966b5SDoug Evans uint8_t *crc_ptr; 47701c966b5SDoug Evans uint32_t buf_addr; 47801c966b5SDoug Evans 47901c966b5SDoug Evans trace_npcm7xx_emc_receiving_packet(len); 48001c966b5SDoug Evans 48101c966b5SDoug Evans if (!emc_can_receive(nc)) { 48201c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Unexpected packet\n", __func__); 48301c966b5SDoug Evans return -1; 48401c966b5SDoug Evans } 48501c966b5SDoug Evans 48601c966b5SDoug Evans if (len < ETH_HLEN || 48701c966b5SDoug Evans /* Defensive programming: drop unsupportable large packets. */ 48801c966b5SDoug Evans len > 0xffff - CRC_LENGTH) { 48901c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Dropped frame of %u bytes\n", 49001c966b5SDoug Evans __func__, len); 49101c966b5SDoug Evans return len; 49201c966b5SDoug Evans } 49301c966b5SDoug Evans 49401c966b5SDoug Evans /* 49501c966b5SDoug Evans * DENI is set if EMC received the Length/Type field of the incoming 49601c966b5SDoug Evans * packet, so it will be set regardless of what happens next. 49701c966b5SDoug Evans */ 49801c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_DENI); 49901c966b5SDoug Evans 50001c966b5SDoug Evans if (!emc_receive_filter(emc, buf, len)) { 50101c966b5SDoug Evans emc_update_rx_irq(emc); 50201c966b5SDoug Evans return len; 50301c966b5SDoug Evans } 50401c966b5SDoug Evans 50501c966b5SDoug Evans /* Huge frames (> DMARFC) are dropped. */ 50601c966b5SDoug Evans max_frame_len = REG_DMARFC_RXMS(emc->regs[REG_DMARFC]); 50701c966b5SDoug Evans if (len + CRC_LENGTH > max_frame_len) { 50801c966b5SDoug Evans trace_npcm7xx_emc_packet_dropped(len); 50901c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_DFOI); 51001c966b5SDoug Evans emc_update_rx_irq(emc); 51101c966b5SDoug Evans return len; 51201c966b5SDoug Evans } 51301c966b5SDoug Evans 51401c966b5SDoug Evans /* 51501c966b5SDoug Evans * Long Frames (> MAX_ETH_FRAME_SIZE) are also dropped, unless MCMDR.ALP 51601c966b5SDoug Evans * is set. 51701c966b5SDoug Evans */ 51801c966b5SDoug Evans long_frame = false; 51901c966b5SDoug Evans if (len + CRC_LENGTH > MAX_ETH_FRAME_SIZE) { 52001c966b5SDoug Evans if (emc->regs[REG_MCMDR] & REG_MCMDR_ALP) { 52101c966b5SDoug Evans long_frame = true; 52201c966b5SDoug Evans } else { 52301c966b5SDoug Evans trace_npcm7xx_emc_packet_dropped(len); 52401c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_PTLE); 52501c966b5SDoug Evans emc_update_rx_irq(emc); 52601c966b5SDoug Evans return len; 52701c966b5SDoug Evans } 52801c966b5SDoug Evans } 52901c966b5SDoug Evans 53001c966b5SDoug Evans desc_addr = RX_DESC_NRXDSA(emc->regs[REG_CRXDSA]); 53101c966b5SDoug Evans if (emc_read_rx_desc(desc_addr, &rx_desc)) { 53201c966b5SDoug Evans /* Error reading descriptor, already reported. */ 53301c966b5SDoug Evans emc_halt_rx(emc, REG_MISTA_RXBERR); 53401c966b5SDoug Evans emc_update_rx_irq(emc); 53501c966b5SDoug Evans return len; 53601c966b5SDoug Evans } 53701c966b5SDoug Evans 53801c966b5SDoug Evans /* Nothing we can do if we don't own the descriptor. */ 53901c966b5SDoug Evans if (!(rx_desc.status_and_length & RX_DESC_STATUS_OWNER_MASK)) { 54001c966b5SDoug Evans trace_npcm7xx_emc_cpu_owned_desc(desc_addr); 54101c966b5SDoug Evans emc_halt_rx(emc, REG_MISTA_RDU); 54201c966b5SDoug Evans emc_update_rx_irq(emc); 54301c966b5SDoug Evans return len; 54401c966b5SDoug Evans } 54501c966b5SDoug Evans 54601c966b5SDoug Evans crc = 0; 54701c966b5SDoug Evans crc_ptr = (uint8_t *) &crc; 54801c966b5SDoug Evans if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) { 54901c966b5SDoug Evans crc = cpu_to_be32(crc32(~0, buf, len)); 55001c966b5SDoug Evans } 55101c966b5SDoug Evans 55201c966b5SDoug Evans /* Give the descriptor back regardless of what happens. */ 55301c966b5SDoug Evans rx_desc.status_and_length &= ~RX_DESC_STATUS_OWNER_MASK; 55401c966b5SDoug Evans 55501c966b5SDoug Evans buf_addr = rx_desc.rxbsa; 55601c966b5SDoug Evans emc->regs[REG_CRXBSA] = buf_addr; 557*ba06fe8aSPhilippe Mathieu-Daudé if (dma_memory_write(&address_space_memory, buf_addr, buf, 558*ba06fe8aSPhilippe Mathieu-Daudé len, MEMTXATTRS_UNSPECIFIED) || 55901c966b5SDoug Evans (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC) && 560*ba06fe8aSPhilippe Mathieu-Daudé dma_memory_write(&address_space_memory, buf_addr + len, 561*ba06fe8aSPhilippe Mathieu-Daudé crc_ptr, 4, MEMTXATTRS_UNSPECIFIED))) { 56201c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, "%s: Bus error writing packet\n", 56301c966b5SDoug Evans __func__); 56401c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_RXBERR); 56501c966b5SDoug Evans emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr); 56601c966b5SDoug Evans emc_update_rx_irq(emc); 56701c966b5SDoug Evans trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]); 56801c966b5SDoug Evans return len; 56901c966b5SDoug Evans } 57001c966b5SDoug Evans 57101c966b5SDoug Evans trace_npcm7xx_emc_received_packet(len); 57201c966b5SDoug Evans 57301c966b5SDoug Evans /* Note: We've already verified len+4 <= 0xffff. */ 57401c966b5SDoug Evans rx_desc.status_and_length = len; 57501c966b5SDoug Evans if (!(emc->regs[REG_MCMDR] & REG_MCMDR_SPCRC)) { 57601c966b5SDoug Evans rx_desc.status_and_length += 4; 57701c966b5SDoug Evans } 57801c966b5SDoug Evans rx_desc.status_and_length |= RX_DESC_STATUS_RXGD; 57901c966b5SDoug Evans emc_set_mista(emc, REG_MISTA_RXGD); 58001c966b5SDoug Evans 58101c966b5SDoug Evans if (emc->regs[REG_MISTA] & emc->regs[REG_MIEN] & REG_MISTA_RXINTR) { 58201c966b5SDoug Evans rx_desc.status_and_length |= RX_DESC_STATUS_RXINTR; 58301c966b5SDoug Evans } 58401c966b5SDoug Evans if (long_frame) { 58501c966b5SDoug Evans rx_desc.status_and_length |= RX_DESC_STATUS_PTLE; 58601c966b5SDoug Evans } 58701c966b5SDoug Evans 58801c966b5SDoug Evans emc_set_next_rx_descriptor(emc, &rx_desc, desc_addr); 58901c966b5SDoug Evans emc_update_rx_irq(emc); 59001c966b5SDoug Evans trace_npcm7xx_emc_rx_done(emc->regs[REG_CRXDSA]); 59101c966b5SDoug Evans return len; 59201c966b5SDoug Evans } 59301c966b5SDoug Evans 59401c966b5SDoug Evans static uint64_t npcm7xx_emc_read(void *opaque, hwaddr offset, unsigned size) 59501c966b5SDoug Evans { 59601c966b5SDoug Evans NPCM7xxEMCState *emc = opaque; 59701c966b5SDoug Evans uint32_t reg = offset / sizeof(uint32_t); 59801c966b5SDoug Evans uint32_t result; 59901c966b5SDoug Evans 60001c966b5SDoug Evans if (reg >= NPCM7XX_NUM_EMC_REGS) { 60101c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, 60201c966b5SDoug Evans "%s: Invalid offset 0x%04" HWADDR_PRIx "\n", 60301c966b5SDoug Evans __func__, offset); 60401c966b5SDoug Evans return 0; 60501c966b5SDoug Evans } 60601c966b5SDoug Evans 60701c966b5SDoug Evans switch (reg) { 60801c966b5SDoug Evans case REG_MIID: 60901c966b5SDoug Evans /* 61001c966b5SDoug Evans * We don't implement MII. For determinism, always return zero as 61101c966b5SDoug Evans * writes record the last value written for debugging purposes. 61201c966b5SDoug Evans */ 61301c966b5SDoug Evans qemu_log_mask(LOG_UNIMP, "%s: Read of MIID, returning 0\n", __func__); 61401c966b5SDoug Evans result = 0; 61501c966b5SDoug Evans break; 61601c966b5SDoug Evans case REG_TSDR: 61701c966b5SDoug Evans case REG_RSDR: 61801c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, 61901c966b5SDoug Evans "%s: Read of write-only reg, %s/%d\n", 62001c966b5SDoug Evans __func__, emc_reg_name(reg), reg); 62101c966b5SDoug Evans return 0; 62201c966b5SDoug Evans default: 62301c966b5SDoug Evans result = emc->regs[reg]; 62401c966b5SDoug Evans break; 62501c966b5SDoug Evans } 62601c966b5SDoug Evans 62701c966b5SDoug Evans trace_npcm7xx_emc_reg_read(emc->emc_num, result, emc_reg_name(reg), reg); 62801c966b5SDoug Evans return result; 62901c966b5SDoug Evans } 63001c966b5SDoug Evans 63101c966b5SDoug Evans static void npcm7xx_emc_write(void *opaque, hwaddr offset, 63201c966b5SDoug Evans uint64_t v, unsigned size) 63301c966b5SDoug Evans { 63401c966b5SDoug Evans NPCM7xxEMCState *emc = opaque; 63501c966b5SDoug Evans uint32_t reg = offset / sizeof(uint32_t); 63601c966b5SDoug Evans uint32_t value = v; 63701c966b5SDoug Evans 63801c966b5SDoug Evans g_assert(size == sizeof(uint32_t)); 63901c966b5SDoug Evans 64001c966b5SDoug Evans if (reg >= NPCM7XX_NUM_EMC_REGS) { 64101c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, 64201c966b5SDoug Evans "%s: Invalid offset 0x%04" HWADDR_PRIx "\n", 64301c966b5SDoug Evans __func__, offset); 64401c966b5SDoug Evans return; 64501c966b5SDoug Evans } 64601c966b5SDoug Evans 64701c966b5SDoug Evans trace_npcm7xx_emc_reg_write(emc->emc_num, emc_reg_name(reg), reg, value); 64801c966b5SDoug Evans 64901c966b5SDoug Evans switch (reg) { 65001c966b5SDoug Evans case REG_CAMCMR: 65101c966b5SDoug Evans emc->regs[reg] = value; 65201c966b5SDoug Evans break; 65301c966b5SDoug Evans case REG_CAMEN: 65401c966b5SDoug Evans /* Only CAM0 is supported, don't pretend otherwise. */ 65501c966b5SDoug Evans if (value & ~1) { 65601c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, 65701c966b5SDoug Evans "%s: Only CAM0 is supported, cannot enable others" 65801c966b5SDoug Evans ": 0x%x\n", 65901c966b5SDoug Evans __func__, value); 66001c966b5SDoug Evans } 66101c966b5SDoug Evans emc->regs[reg] = value & 1; 66201c966b5SDoug Evans break; 66301c966b5SDoug Evans case REG_CAMM_BASE + 0: 66401c966b5SDoug Evans emc->regs[reg] = value; 66501c966b5SDoug Evans emc->conf.macaddr.a[0] = value >> 24; 66601c966b5SDoug Evans emc->conf.macaddr.a[1] = value >> 16; 66701c966b5SDoug Evans emc->conf.macaddr.a[2] = value >> 8; 66801c966b5SDoug Evans emc->conf.macaddr.a[3] = value >> 0; 66901c966b5SDoug Evans break; 67001c966b5SDoug Evans case REG_CAML_BASE + 0: 67101c966b5SDoug Evans emc->regs[reg] = value; 67201c966b5SDoug Evans emc->conf.macaddr.a[4] = value >> 24; 67301c966b5SDoug Evans emc->conf.macaddr.a[5] = value >> 16; 67401c966b5SDoug Evans break; 67501c966b5SDoug Evans case REG_MCMDR: { 67601c966b5SDoug Evans uint32_t prev; 67701c966b5SDoug Evans if (value & REG_MCMDR_SWR) { 67801c966b5SDoug Evans emc_soft_reset(emc); 67901c966b5SDoug Evans /* On h/w the reset happens over multiple cycles. For now KISS. */ 68001c966b5SDoug Evans break; 68101c966b5SDoug Evans } 68201c966b5SDoug Evans prev = emc->regs[reg]; 68301c966b5SDoug Evans emc->regs[reg] = value; 68401c966b5SDoug Evans /* Update tx state. */ 68501c966b5SDoug Evans if (!(prev & REG_MCMDR_TXON) && 68601c966b5SDoug Evans (value & REG_MCMDR_TXON)) { 68701c966b5SDoug Evans emc->regs[REG_CTXDSA] = emc->regs[REG_TXDLSA]; 68801c966b5SDoug Evans /* 68901c966b5SDoug Evans * Linux kernel turns TX on with CPU still holding descriptor, 69001c966b5SDoug Evans * which suggests we should wait for a write to TSDR before trying 69101c966b5SDoug Evans * to send a packet: so we don't send one here. 69201c966b5SDoug Evans */ 69301c966b5SDoug Evans } else if ((prev & REG_MCMDR_TXON) && 69401c966b5SDoug Evans !(value & REG_MCMDR_TXON)) { 69501c966b5SDoug Evans emc->regs[REG_MGSTA] |= REG_MGSTA_TXHA; 69601c966b5SDoug Evans } 69701c966b5SDoug Evans if (!(value & REG_MCMDR_TXON)) { 69801c966b5SDoug Evans emc_halt_tx(emc, 0); 69901c966b5SDoug Evans } 70001c966b5SDoug Evans /* Update rx state. */ 70101c966b5SDoug Evans if (!(prev & REG_MCMDR_RXON) && 70201c966b5SDoug Evans (value & REG_MCMDR_RXON)) { 70301c966b5SDoug Evans emc->regs[REG_CRXDSA] = emc->regs[REG_RXDLSA]; 70401c966b5SDoug Evans } else if ((prev & REG_MCMDR_RXON) && 70501c966b5SDoug Evans !(value & REG_MCMDR_RXON)) { 70601c966b5SDoug Evans emc->regs[REG_MGSTA] |= REG_MGSTA_RXHA; 70701c966b5SDoug Evans } 708a62ee00aSDoug Evans if (value & REG_MCMDR_RXON) { 709530cd6c2SPatrick Venture emc_enable_rx_and_flush(emc); 710a62ee00aSDoug Evans } else { 71101c966b5SDoug Evans emc_halt_rx(emc, 0); 71201c966b5SDoug Evans } 71301c966b5SDoug Evans break; 71401c966b5SDoug Evans } 71501c966b5SDoug Evans case REG_TXDLSA: 71601c966b5SDoug Evans case REG_RXDLSA: 71701c966b5SDoug Evans case REG_DMARFC: 71801c966b5SDoug Evans case REG_MIID: 71901c966b5SDoug Evans emc->regs[reg] = value; 72001c966b5SDoug Evans break; 72101c966b5SDoug Evans case REG_MIEN: 72201c966b5SDoug Evans emc->regs[reg] = value; 72301c966b5SDoug Evans emc_update_irq_from_reg_change(emc); 72401c966b5SDoug Evans break; 72501c966b5SDoug Evans case REG_MISTA: 72601c966b5SDoug Evans /* Clear the bits that have 1 in "value". */ 72701c966b5SDoug Evans emc->regs[reg] &= ~value; 72801c966b5SDoug Evans emc_update_irq_from_reg_change(emc); 72901c966b5SDoug Evans break; 73001c966b5SDoug Evans case REG_MGSTA: 73101c966b5SDoug Evans /* Clear the bits that have 1 in "value". */ 73201c966b5SDoug Evans emc->regs[reg] &= ~value; 73301c966b5SDoug Evans break; 73401c966b5SDoug Evans case REG_TSDR: 73501c966b5SDoug Evans if (emc->regs[REG_MCMDR] & REG_MCMDR_TXON) { 73601c966b5SDoug Evans emc->tx_active = true; 73701c966b5SDoug Evans /* Keep trying to send packets until we run out. */ 73801c966b5SDoug Evans while (emc->tx_active) { 73901c966b5SDoug Evans emc_try_send_next_packet(emc); 74001c966b5SDoug Evans } 74101c966b5SDoug Evans } 74201c966b5SDoug Evans break; 74301c966b5SDoug Evans case REG_RSDR: 74401c966b5SDoug Evans if (emc->regs[REG_MCMDR] & REG_MCMDR_RXON) { 745530cd6c2SPatrick Venture emc_enable_rx_and_flush(emc); 74601c966b5SDoug Evans } 74701c966b5SDoug Evans break; 74801c966b5SDoug Evans case REG_MIIDA: 74901c966b5SDoug Evans emc->regs[reg] = value & ~REG_MIIDA_BUSY; 75001c966b5SDoug Evans break; 75101c966b5SDoug Evans case REG_MRPC: 75201c966b5SDoug Evans case REG_MRPCC: 75301c966b5SDoug Evans case REG_MREPC: 75401c966b5SDoug Evans case REG_CTXDSA: 75501c966b5SDoug Evans case REG_CTXBSA: 75601c966b5SDoug Evans case REG_CRXDSA: 75701c966b5SDoug Evans case REG_CRXBSA: 75801c966b5SDoug Evans qemu_log_mask(LOG_GUEST_ERROR, 75901c966b5SDoug Evans "%s: Write to read-only reg %s/%d\n", 76001c966b5SDoug Evans __func__, emc_reg_name(reg), reg); 76101c966b5SDoug Evans break; 76201c966b5SDoug Evans default: 76301c966b5SDoug Evans qemu_log_mask(LOG_UNIMP, "%s: Write to unimplemented reg %s/%d\n", 76401c966b5SDoug Evans __func__, emc_reg_name(reg), reg); 76501c966b5SDoug Evans break; 76601c966b5SDoug Evans } 76701c966b5SDoug Evans } 76801c966b5SDoug Evans 76901c966b5SDoug Evans static const struct MemoryRegionOps npcm7xx_emc_ops = { 77001c966b5SDoug Evans .read = npcm7xx_emc_read, 77101c966b5SDoug Evans .write = npcm7xx_emc_write, 77201c966b5SDoug Evans .endianness = DEVICE_LITTLE_ENDIAN, 77301c966b5SDoug Evans .valid = { 77401c966b5SDoug Evans .min_access_size = 4, 77501c966b5SDoug Evans .max_access_size = 4, 77601c966b5SDoug Evans .unaligned = false, 77701c966b5SDoug Evans }, 77801c966b5SDoug Evans }; 77901c966b5SDoug Evans 78001c966b5SDoug Evans static void emc_cleanup(NetClientState *nc) 78101c966b5SDoug Evans { 78201c966b5SDoug Evans /* Nothing to do yet. */ 78301c966b5SDoug Evans } 78401c966b5SDoug Evans 78501c966b5SDoug Evans static NetClientInfo net_npcm7xx_emc_info = { 78601c966b5SDoug Evans .type = NET_CLIENT_DRIVER_NIC, 78701c966b5SDoug Evans .size = sizeof(NICState), 78801c966b5SDoug Evans .can_receive = emc_can_receive, 78901c966b5SDoug Evans .receive = emc_receive, 79001c966b5SDoug Evans .cleanup = emc_cleanup, 79101c966b5SDoug Evans .link_status_changed = emc_set_link, 79201c966b5SDoug Evans }; 79301c966b5SDoug Evans 79401c966b5SDoug Evans static void npcm7xx_emc_realize(DeviceState *dev, Error **errp) 79501c966b5SDoug Evans { 79601c966b5SDoug Evans NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); 79701c966b5SDoug Evans SysBusDevice *sbd = SYS_BUS_DEVICE(emc); 79801c966b5SDoug Evans 79901c966b5SDoug Evans memory_region_init_io(&emc->iomem, OBJECT(emc), &npcm7xx_emc_ops, emc, 80001c966b5SDoug Evans TYPE_NPCM7XX_EMC, 4 * KiB); 80101c966b5SDoug Evans sysbus_init_mmio(sbd, &emc->iomem); 80201c966b5SDoug Evans sysbus_init_irq(sbd, &emc->tx_irq); 80301c966b5SDoug Evans sysbus_init_irq(sbd, &emc->rx_irq); 80401c966b5SDoug Evans 80501c966b5SDoug Evans qemu_macaddr_default_if_unset(&emc->conf.macaddr); 80601c966b5SDoug Evans emc->nic = qemu_new_nic(&net_npcm7xx_emc_info, &emc->conf, 80701c966b5SDoug Evans object_get_typename(OBJECT(dev)), dev->id, emc); 80801c966b5SDoug Evans qemu_format_nic_info_str(qemu_get_queue(emc->nic), emc->conf.macaddr.a); 80901c966b5SDoug Evans } 81001c966b5SDoug Evans 81101c966b5SDoug Evans static void npcm7xx_emc_unrealize(DeviceState *dev) 81201c966b5SDoug Evans { 81301c966b5SDoug Evans NPCM7xxEMCState *emc = NPCM7XX_EMC(dev); 81401c966b5SDoug Evans 81501c966b5SDoug Evans qemu_del_nic(emc->nic); 81601c966b5SDoug Evans } 81701c966b5SDoug Evans 81801c966b5SDoug Evans static const VMStateDescription vmstate_npcm7xx_emc = { 81901c966b5SDoug Evans .name = TYPE_NPCM7XX_EMC, 82001c966b5SDoug Evans .version_id = 0, 82101c966b5SDoug Evans .minimum_version_id = 0, 82201c966b5SDoug Evans .fields = (VMStateField[]) { 82301c966b5SDoug Evans VMSTATE_UINT8(emc_num, NPCM7xxEMCState), 82401c966b5SDoug Evans VMSTATE_UINT32_ARRAY(regs, NPCM7xxEMCState, NPCM7XX_NUM_EMC_REGS), 82501c966b5SDoug Evans VMSTATE_BOOL(tx_active, NPCM7xxEMCState), 82601c966b5SDoug Evans VMSTATE_BOOL(rx_active, NPCM7xxEMCState), 82701c966b5SDoug Evans VMSTATE_END_OF_LIST(), 82801c966b5SDoug Evans }, 82901c966b5SDoug Evans }; 83001c966b5SDoug Evans 83101c966b5SDoug Evans static Property npcm7xx_emc_properties[] = { 83201c966b5SDoug Evans DEFINE_NIC_PROPERTIES(NPCM7xxEMCState, conf), 83301c966b5SDoug Evans DEFINE_PROP_END_OF_LIST(), 83401c966b5SDoug Evans }; 83501c966b5SDoug Evans 83601c966b5SDoug Evans static void npcm7xx_emc_class_init(ObjectClass *klass, void *data) 83701c966b5SDoug Evans { 83801c966b5SDoug Evans DeviceClass *dc = DEVICE_CLASS(klass); 83901c966b5SDoug Evans 84001c966b5SDoug Evans set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 84101c966b5SDoug Evans dc->desc = "NPCM7xx EMC Controller"; 84201c966b5SDoug Evans dc->realize = npcm7xx_emc_realize; 84301c966b5SDoug Evans dc->unrealize = npcm7xx_emc_unrealize; 84401c966b5SDoug Evans dc->reset = npcm7xx_emc_reset; 84501c966b5SDoug Evans dc->vmsd = &vmstate_npcm7xx_emc; 84601c966b5SDoug Evans device_class_set_props(dc, npcm7xx_emc_properties); 84701c966b5SDoug Evans } 84801c966b5SDoug Evans 84901c966b5SDoug Evans static const TypeInfo npcm7xx_emc_info = { 85001c966b5SDoug Evans .name = TYPE_NPCM7XX_EMC, 85101c966b5SDoug Evans .parent = TYPE_SYS_BUS_DEVICE, 85201c966b5SDoug Evans .instance_size = sizeof(NPCM7xxEMCState), 85301c966b5SDoug Evans .class_init = npcm7xx_emc_class_init, 85401c966b5SDoug Evans }; 85501c966b5SDoug Evans 85601c966b5SDoug Evans static void npcm7xx_emc_register_type(void) 85701c966b5SDoug Evans { 85801c966b5SDoug Evans type_register_static(&npcm7xx_emc_info); 85901c966b5SDoug Evans } 86001c966b5SDoug Evans 86101c966b5SDoug Evans type_init(npcm7xx_emc_register_type) 862