2
* Copyright 2011 Calxeda, Inc.
3
* Based on xilinx_axienet.c Copyright (c) 2011 Edgar E. Iglesias.
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to deal
7
* in the Software without restriction, including without limitation the rights
8
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
* copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
#include "qemu-char.h"
28
#include "net/checksum.h"
30
#define XGMAC_CONTROL 0x00000000 /* MAC Configuration */
31
#define XGMAC_FRAME_FILTER 0x00000001 /* MAC Frame Filter */
32
#define XGMAC_FLOW_CTRL 0x00000006 /* MAC Flow Control */
33
#define XGMAC_VLAN_TAG 0x00000007 /* VLAN Tags */
34
#define XGMAC_VERSION 0x00000008 /* Version */
35
#define XGMAC_VLAN_INCL 0x00000009 /* VLAN tag for insertion or replacement into tx frames */
36
#define XGMAC_LPI_CTRL 0x0000000a /* LPI Control and Status */
37
#define XGMAC_LPI_TIMER 0x0000000b /* LPI Timers Control */
38
#define XGMAC_TX_PACE 0x0000000c /* Transmit Pace and Stretch */
39
#define XGMAC_VLAN_HASH 0x0000000d /* VLAN Hash Table */
40
#define XGMAC_DEBUG 0x0000000e /* Debug */
41
#define XGMAC_INT_STATUS 0x0000000f /* Interrupt and Control */
42
#define XGMAC_HASH(n) (0x00000300/4 + (n)) /* HASH table registers */
43
#define XGMAC_NUM_HASH 16
44
#define XGMAC_OPMODE 0x00000400/4 /* Operation Mode */
45
#define XGMAC_REMOTE_WAKE 0x00000700/4 /* Remote Wake-Up Frame Filter */
46
#define XGMAC_PMT 0x00000704/4 /* PMT Control and Status */
48
#define XGMAC_ADDR_HIGH(reg) (0x00000010+(reg * 2))
49
#define XGMAC_ADDR_LOW(reg) (0x00000011+(reg * 2))
51
#define DMA_BUS_MODE 0x000003c0 /* Bus Mode */
52
#define DMA_XMT_POLL_DEMAND 0x000003c1 /* Transmit Poll Demand */
53
#define DMA_RCV_POLL_DEMAND 0x000003c2 /* Received Poll Demand */
54
#define DMA_RCV_BASE_ADDR 0x000003c3 /* Receive List Base */
55
#define DMA_TX_BASE_ADDR 0x000003c4 /* Transmit List Base */
56
#define DMA_STATUS 0x000003c5 /* Status Register */
57
#define DMA_CONTROL 0x000003c6 /* Ctrl (Operational Mode) */
58
#define DMA_INTR_ENA 0x000003c7 /* Interrupt Enable */
59
#define DMA_MISSED_FRAME_CTR 0x000003c8 /* Missed Frame Counter */
60
#define DMA_RI_WATCHDOG_TIMER 0x000003c9 /* Receive Interrupt Watchdog Timer */
61
#define DMA_AXI_BUS 0x000003ca /* AXI Bus Mode */
62
#define DMA_AXI_STATUS 0x000003cb /* AXI Status */
63
#define DMA_CUR_TX_DESC_ADDR 0x000003d2 /* Current Host Tx Descriptor */
64
#define DMA_CUR_RX_DESC_ADDR 0x000003d3 /* Current Host Rx Descriptor */
65
#define DMA_CUR_TX_BUF_ADDR 0x000003d4 /* Current Host Tx Buffer */
66
#define DMA_CUR_RX_BUF_ADDR 0x000003d5 /* Current Host Rx Buffer */
67
#define DMA_HW_FEATURE 0x000003d6 /* Enabled Hardware Features */
69
/* DMA Status register defines */
70
#define DMA_STATUS_GMI 0x08000000 /* MMC interrupt */
71
#define DMA_STATUS_GLI 0x04000000 /* GMAC Line interface int */
72
#define DMA_STATUS_EB_MASK 0x00380000 /* Error Bits Mask */
73
#define DMA_STATUS_EB_TX_ABORT 0x00080000 /* Error Bits - TX Abort */
74
#define DMA_STATUS_EB_RX_ABORT 0x00100000 /* Error Bits - RX Abort */
75
#define DMA_STATUS_TS_MASK 0x00700000 /* Transmit Process State */
76
#define DMA_STATUS_TS_SHIFT 20
77
#define DMA_STATUS_RS_MASK 0x000e0000 /* Receive Process State */
78
#define DMA_STATUS_RS_SHIFT 17
79
#define DMA_STATUS_NIS 0x00010000 /* Normal Interrupt Summary */
80
#define DMA_STATUS_AIS 0x00008000 /* Abnormal Interrupt Summary */
81
#define DMA_STATUS_ERI 0x00004000 /* Early Receive Interrupt */
82
#define DMA_STATUS_FBI 0x00002000 /* Fatal Bus Error Interrupt */
83
#define DMA_STATUS_ETI 0x00000400 /* Early Transmit Interrupt */
84
#define DMA_STATUS_RWT 0x00000200 /* Receive Watchdog Timeout */
85
#define DMA_STATUS_RPS 0x00000100 /* Receive Process Stopped */
86
#define DMA_STATUS_RU 0x00000080 /* Receive Buffer Unavailable */
87
#define DMA_STATUS_RI 0x00000040 /* Receive Interrupt */
88
#define DMA_STATUS_UNF 0x00000020 /* Transmit Underflow */
89
#define DMA_STATUS_OVF 0x00000010 /* Receive Overflow */
90
#define DMA_STATUS_TJT 0x00000008 /* Transmit Jabber Timeout */
91
#define DMA_STATUS_TU 0x00000004 /* Transmit Buffer Unavailable */
92
#define DMA_STATUS_TPS 0x00000002 /* Transmit Process Stopped */
93
#define DMA_STATUS_TI 0x00000001 /* Transmit Interrupt */
95
/* DMA Control register defines */
96
#define DMA_CONTROL_ST 0x00002000 /* Start/Stop Transmission */
97
#define DMA_CONTROL_SR 0x00000002 /* Start/Stop Receive */
98
#define DMA_CONTROL_DFF 0x01000000 /* Disable flush of rx frames */
102
uint16_t buffer1_size;
103
uint16_t buffer2_size;
104
uint32_t buffer1_addr;
105
uint32_t buffer2_addr;
135
/* Receive configuration words. */
137
/* Transmit config. */
142
/* Unicast Address Word. */
144
/* Unicast address filter used with extended mcast. */
148
uint32_t regs[R_MAX];
150
/* Multicast filter addrs. */
151
uint32_t maddr[4][2];
152
/* 32K x 1 lookup filter. */
153
uint32_t ext_mtable[1024];
159
static void xgmac_read_desc(struct XgmacEnet *s, struct desc *d, int rx)
161
uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] : s->regs[DMA_CUR_TX_DESC_ADDR];
162
cpu_physical_memory_read(addr, d, sizeof(*d));
165
static void xgmac_write_desc(struct XgmacEnet *s, struct desc *d, int rx)
167
int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
168
uint32_t addr = s->regs[reg];
170
if (!rx && (d->ctl_stat & 0x00200000))
171
s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
172
else if (rx && (d->buffer1_size & 0x8000))
173
s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
175
s->regs[reg] += sizeof(*d);
177
cpu_physical_memory_write(addr, d, sizeof(*d));
180
static void xgmac_enet_send(struct XgmacEnet *s)
191
xgmac_read_desc(s, &bd, 0);
192
//printf("tx_bd flags %08x len %d data %08x\n",
193
// bd.ctl_stat, bd.buffer1_size & 0xfff, bd.buffer1_addr);
194
if ((bd.ctl_stat & 0x80000000) == 0) {
195
/* Run out of descriptors to transmit. */
198
len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
200
if ((bd.buffer1_size & 0xfff) >2048) {
201
fprintf(stdout,"qemu:%s:ERROR...ERROR...ERROR... -- "
202
"xgmac buffer 1 len on send > 2048 (0x%x)\n",
203
__FUNCTION__,bd.buffer1_size & 0xfff);
206
if ((bd.buffer2_size & 0xfff) != 0) {
207
fprintf(stdout,"qemu:%s:ERROR...ERROR...ERROR... -- "
208
"xgmac buffer 2 len on send != 0 (0x%x)\n",
209
__FUNCTION__,bd.buffer2_size & 0xfff);
212
if (len >= sizeof(frame)) {
213
fprintf(stdout,"qemu:%s: buffer overflow %d read into %zu "
214
"buffer\n",__FUNCTION__,len,sizeof(frame));
215
fprintf(stdout,"qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
216
__FUNCTION__,bd.buffer1_size,bd.buffer2_size);
220
cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
223
if (bd.ctl_stat & 0x20000000) {
224
/* Last buffer in frame. */
225
//printf("Sending packet\n");
226
qemu_send_packet(&s->nic->nc, frame, len);
229
s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
231
bd.ctl_stat &= ~0x80000000;
232
/* Write back the modified descriptor. */
233
xgmac_write_desc(s, &bd, 0);
237
static void enet_update_irq(struct XgmacEnet *s)
239
int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
240
qemu_set_irq(s->sbd_irq, !!stat);
243
static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
245
struct XgmacEnet *s = opaque;
254
if (addr < ARRAY_SIZE(s->regs)) {
257
//printf("%s addr=" TARGET_FMT_plx " v=%x\n",
258
// __func__, addr * 4, r);
265
enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
267
struct XgmacEnet *s = opaque;
270
//printf("%s addr=" TARGET_FMT_plx " v=%x\n",
271
// __func__, addr * 4, value);
274
s->regs[DMA_BUS_MODE] = value & ~0x1;
276
case DMA_XMT_POLL_DEMAND:
280
s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
282
case DMA_RCV_BASE_ADDR:
283
s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
285
case DMA_TX_BASE_ADDR:
286
s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
289
if (addr < ARRAY_SIZE(s->regs)) {
290
s->regs[addr] = value;
297
static CPUReadMemoryFunc * const enet_read[] = {
303
static CPUWriteMemoryFunc * const enet_write[] = {
309
static int eth_can_rx(VLANClientState *nc)
311
struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
314
return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
317
static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
319
struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
320
static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
322
static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
323
// int promisc = s->fmi & (1 << 31);
324
int unicast, broadcast, multicast;
329
//printf("%s: %zd bytes\n", __func__, size);
331
unicast = ~buf[0] & 0x1;
332
broadcast = memcmp(buf, sa_bcast, 6) == 0;
333
multicast = !unicast && !broadcast;
334
if (multicast && (memcmp(sa_ipmcast, buf, sizeof sa_ipmcast) == 0)) {
338
/* Basic Address filters. If you want to use the extended filters
339
you'll generally have to place the ethernet mac into promiscuous mode
340
to avoid the basic filtering from dropping most frames. */
343
if (!enet_match_addr(buf, s->uaw[0], s->uaw[1])) {
349
if (s->regs[R_RAF] & RAF_BCAST_REJ) {
356
if (s->regs[R_RAF] & RAF_MCAST_REJ) {
360
for (i = 0; i < 4; i++) {
361
if (enet_match_addr(buf, s->maddr[i][0], s->maddr[i][1])) {
374
/* Extended mcast filtering enabled? */
375
if (axienet_newfunc_enabled(s) && axienet_extmcf_enabled(s)) {
377
if (!enet_match_addr(buf, s->ext_uaw[0], s->ext_uaw[1])) {
383
if (s->regs[R_RAF] & RAF_BCAST_REJ) {
390
if (!memcmp(buf, sa_ipmcast, 3)) {
394
idx = (buf[4] & 0x7f) << 8;
397
bit = 1 << (idx & 0x1f);
400
if (!(s->ext_mtable[idx] & bit)) {
408
s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
413
xgmac_read_desc(s, &bd, 1);
414
if ((bd.ctl_stat & 0x80000000) == 0) {
415
s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
420
cpu_physical_memory_write(bd.buffer1_addr, buf, size);
422
// Add in the 4 bytes for crc (the real hw returns length incl crc)
424
bd.ctl_stat = (size << 16) | 0x300;
425
xgmac_write_desc(s, &bd, 1);
427
s->stats.rx_bytes += size;
431
} else if (broadcast) {
435
s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
443
static void eth_cleanup(VLANClientState *nc)
446
struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
450
static NetClientInfo net_xgmac_enet_info = {
451
.type = NET_CLIENT_TYPE_NIC,
452
.size = sizeof(NICState),
453
.can_receive = eth_can_rx,
455
.cleanup = eth_cleanup,
458
static int xgmac_enet_init(SysBusDevice *dev)
460
struct XgmacEnet *s = FROM_SYSBUS(typeof(*s), dev);
463
sysbus_init_irq(dev, &s->sbd_irq);
464
sysbus_init_irq(dev, &s->pmt_irq);
465
sysbus_init_irq(dev, &s->mci_irq);
467
enet_regs = cpu_register_io_memory(enet_read, enet_write, s,
468
DEVICE_LITTLE_ENDIAN);
469
sysbus_init_mmio(dev, 0x1000, enet_regs);
471
qemu_macaddr_default_if_unset(&s->conf.macaddr);
472
s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
473
dev->qdev.info->name, dev->qdev.id, s);
474
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
476
s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | s->conf.macaddr.a[4];
477
s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) |
478
(s->conf.macaddr.a[2] << 16) |
479
(s->conf.macaddr.a[1] << 8) |
480
s->conf.macaddr.a[0];
485
static SysBusDeviceInfo xgmac_enet_info = {
486
.init = xgmac_enet_init,
487
.qdev.name = "xgmac",
488
.qdev.size = sizeof(struct XgmacEnet),
489
.qdev.props = (Property[]) {
490
DEFINE_PROP_UINT32("phyaddr", struct XgmacEnet, c_phyaddr, 7),
491
DEFINE_NIC_PROPERTIES(struct XgmacEnet, conf),
492
DEFINE_PROP_END_OF_LIST(),
495
static void xgmac_enet_register(void)
497
sysbus_register_withprop(&xgmac_enet_info);
500
device_init(xgmac_enet_register)