trivial: etraxfs_eth: Eliminate checkpatch errors

This is a trivial patch to harmonize the coding style on
hw/etraxfs_eth.c. This is in preparation to split off the bitbang mdio
code into a separate file.

Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Paul Brook <paul@codesourcery.com>
Cc: Edgar E. Iglesias <edgar.iglesias@gmail.com>
Cc: Anthony Liguori <aliguori@us.ibm.com>
Cc: Andreas Färber <afaerber@suse.de>
Signed-off-by: Grant Likely <grant.likely@secretlab.ca>
Signed-off-by: Edgar E. Iglesias <edgar.iglesias@gmail.com>
This commit is contained in:
Grant Likely 2013-01-23 16:15:25 +00:00 committed by Edgar E. Iglesias
parent 177f7fc688
commit 9fc7577af5

View File

@ -42,575 +42,585 @@
*/ */
struct qemu_phy struct qemu_phy
{ {
uint32_t regs[32]; uint32_t regs[32];
int link; int link;
unsigned int (*read)(struct qemu_phy *phy, unsigned int req); unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
void (*write)(struct qemu_phy *phy, unsigned int req, void (*write)(struct qemu_phy *phy, unsigned int req, unsigned int data);
unsigned int data);
}; };
static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req) static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
{ {
int regnum; int regnum;
unsigned r = 0; unsigned r = 0;
regnum = req & 0x1f; regnum = req & 0x1f;
switch (regnum) { switch (regnum) {
case 1: case 1:
if (!phy->link) if (!phy->link) {
break; break;
/* MR1. */ }
/* Speeds and modes. */ /* MR1. */
r |= (1 << 13) | (1 << 14); /* Speeds and modes. */
r |= (1 << 11) | (1 << 12); r |= (1 << 13) | (1 << 14);
r |= (1 << 5); /* Autoneg complete. */ r |= (1 << 11) | (1 << 12);
r |= (1 << 3); /* Autoneg able. */ r |= (1 << 5); /* Autoneg complete. */
r |= (1 << 2); /* link. */ r |= (1 << 3); /* Autoneg able. */
break; r |= (1 << 2); /* link. */
case 5: break;
/* Link partner ability. case 5:
We are kind; always agree with whatever best mode /* Link partner ability.
the guest advertises. */ We are kind; always agree with whatever best mode
r = 1 << 14; /* Success. */ the guest advertises. */
/* Copy advertised modes. */ r = 1 << 14; /* Success. */
r |= phy->regs[4] & (15 << 5); /* Copy advertised modes. */
/* Autoneg support. */ r |= phy->regs[4] & (15 << 5);
r |= 1; /* Autoneg support. */
break; r |= 1;
case 18: break;
{ case 18:
/* Diagnostics reg. */ {
int duplex = 0; /* Diagnostics reg. */
int speed_100 = 0; int duplex = 0;
int speed_100 = 0;
if (!phy->link) if (!phy->link) {
break; break;
}
/* Are we advertising 100 half or 100 duplex ? */ /* Are we advertising 100 half or 100 duplex ? */
speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF); speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL); speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
/* Are we advertising 10 duplex or 100 duplex ? */ /* Are we advertising 10 duplex or 100 duplex ? */
duplex = !!(phy->regs[4] & ADVERTISE_100FULL); duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
duplex |= !!(phy->regs[4] & ADVERTISE_10FULL); duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
r = (speed_100 << 10) | (duplex << 11); r = (speed_100 << 10) | (duplex << 11);
} }
break; break;
default: default:
r = phy->regs[regnum]; r = phy->regs[regnum];
break; break;
} }
D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum)); D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
return r; return r;
} }
static void static void
tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data) tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
{ {
int regnum; int regnum;
regnum = req & 0x1f; regnum = req & 0x1f;
D(printf("%s reg[%d] = %x\n", __func__, regnum, data)); D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
switch (regnum) { switch (regnum) {
default: default:
phy->regs[regnum] = data; phy->regs[regnum] = data;
break; break;
} }
} }
static void static void
tdk_init(struct qemu_phy *phy) tdk_init(struct qemu_phy *phy)
{ {
phy->regs[0] = 0x3100; phy->regs[0] = 0x3100;
/* PHY Id. */ /* PHY Id. */
phy->regs[2] = 0x0300; phy->regs[2] = 0x0300;
phy->regs[3] = 0xe400; phy->regs[3] = 0xe400;
/* Autonegotiation advertisement reg. */ /* Autonegotiation advertisement reg. */
phy->regs[4] = 0x01E1; phy->regs[4] = 0x01E1;
phy->link = 1; phy->link = 1;
phy->read = tdk_read; phy->read = tdk_read;
phy->write = tdk_write; phy->write = tdk_write;
} }
struct qemu_mdio struct qemu_mdio
{ {
/* bus. */ /* bus. */
int mdc; int mdc;
int mdio; int mdio;
/* decoder. */ /* decoder. */
enum { enum {
PREAMBLE, PREAMBLE,
SOF, SOF,
OPC, OPC,
ADDR, ADDR,
REQ, REQ,
TURNAROUND, TURNAROUND,
DATA DATA
} state; } state;
unsigned int drive; unsigned int drive;
unsigned int cnt; unsigned int cnt;
unsigned int addr; unsigned int addr;
unsigned int opc; unsigned int opc;
unsigned int req; unsigned int req;
unsigned int data; unsigned int data;
struct qemu_phy *devs[32]; struct qemu_phy *devs[32];
}; };
static void static void
mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
{ {
bus->devs[addr & 0x1f] = phy; bus->devs[addr & 0x1f] = phy;
} }
#ifdef USE_THIS_DEAD_CODE #ifdef USE_THIS_DEAD_CODE
static void static void
mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr) mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
{ {
bus->devs[addr & 0x1f] = NULL; bus->devs[addr & 0x1f] = NULL;
} }
#endif #endif
static void mdio_read_req(struct qemu_mdio *bus) static void mdio_read_req(struct qemu_mdio *bus)
{ {
struct qemu_phy *phy; struct qemu_phy *phy;
phy = bus->devs[bus->addr]; phy = bus->devs[bus->addr];
if (phy && phy->read) if (phy && phy->read) {
bus->data = phy->read(phy, bus->req); bus->data = phy->read(phy, bus->req);
else } else {
bus->data = 0xffff; bus->data = 0xffff;
}
} }
static void mdio_write_req(struct qemu_mdio *bus) static void mdio_write_req(struct qemu_mdio *bus)
{ {
struct qemu_phy *phy; struct qemu_phy *phy;
phy = bus->devs[bus->addr]; phy = bus->devs[bus->addr];
if (phy && phy->write) if (phy && phy->write) {
phy->write(phy, bus->req, bus->data); phy->write(phy, bus->req, bus->data);
}
} }
static void mdio_cycle(struct qemu_mdio *bus) static void mdio_cycle(struct qemu_mdio *bus)
{ {
bus->cnt++; bus->cnt++;
D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n", D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive)); bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
#if 0 #if 0
if (bus->mdc) if (bus->mdc) {
printf("%d", bus->mdio); printf("%d", bus->mdio);
}
#endif #endif
switch (bus->state) switch (bus->state) {
{ case PREAMBLE:
case PREAMBLE: if (bus->mdc) {
if (bus->mdc) { if (bus->cnt >= (32 * 2) && !bus->mdio) {
if (bus->cnt >= (32 * 2) && !bus->mdio) { bus->cnt = 0;
bus->cnt = 0; bus->state = SOF;
bus->state = SOF; bus->data = 0;
bus->data = 0; }
} }
} break;
break; case SOF:
case SOF: if (bus->mdc) {
if (bus->mdc) { if (bus->mdio != 1) {
if (bus->mdio != 1) printf("WARNING: no SOF\n");
printf("WARNING: no SOF\n"); }
if (bus->cnt == 1*2) { if (bus->cnt == 1*2) {
bus->cnt = 0; bus->cnt = 0;
bus->opc = 0; bus->opc = 0;
bus->state = OPC; bus->state = OPC;
} }
} }
break; break;
case OPC: case OPC:
if (bus->mdc) { if (bus->mdc) {
bus->opc <<= 1; bus->opc <<= 1;
bus->opc |= bus->mdio & 1; bus->opc |= bus->mdio & 1;
if (bus->cnt == 2*2) { if (bus->cnt == 2*2) {
bus->cnt = 0; bus->cnt = 0;
bus->addr = 0; bus->addr = 0;
bus->state = ADDR; bus->state = ADDR;
} }
} }
break; break;
case ADDR: case ADDR:
if (bus->mdc) { if (bus->mdc) {
bus->addr <<= 1; bus->addr <<= 1;
bus->addr |= bus->mdio & 1; bus->addr |= bus->mdio & 1;
if (bus->cnt == 5*2) { if (bus->cnt == 5*2) {
bus->cnt = 0; bus->cnt = 0;
bus->req = 0; bus->req = 0;
bus->state = REQ; bus->state = REQ;
} }
} }
break; break;
case REQ: case REQ:
if (bus->mdc) { if (bus->mdc) {
bus->req <<= 1; bus->req <<= 1;
bus->req |= bus->mdio & 1; bus->req |= bus->mdio & 1;
if (bus->cnt == 5*2) { if (bus->cnt == 5*2) {
bus->cnt = 0; bus->cnt = 0;
bus->state = TURNAROUND; bus->state = TURNAROUND;
} }
} }
break; break;
case TURNAROUND: case TURNAROUND:
if (bus->mdc && bus->cnt == 2*2) { if (bus->mdc && bus->cnt == 2*2) {
bus->mdio = 0; bus->mdio = 0;
bus->cnt = 0; bus->cnt = 0;
if (bus->opc == 2) { if (bus->opc == 2) {
bus->drive = 1; bus->drive = 1;
mdio_read_req(bus); mdio_read_req(bus);
bus->mdio = bus->data & 1; bus->mdio = bus->data & 1;
} }
bus->state = DATA; bus->state = DATA;
} }
break; break;
case DATA: case DATA:
if (!bus->mdc) { if (!bus->mdc) {
if (bus->drive) { if (bus->drive) {
bus->mdio = !!(bus->data & (1 << 15)); bus->mdio = !!(bus->data & (1 << 15));
bus->data <<= 1; bus->data <<= 1;
} }
} else { } else {
if (!bus->drive) { if (!bus->drive) {
bus->data <<= 1; bus->data <<= 1;
bus->data |= bus->mdio; bus->data |= bus->mdio;
} }
if (bus->cnt == 16 * 2) { if (bus->cnt == 16 * 2) {
bus->cnt = 0; bus->cnt = 0;
bus->state = PREAMBLE; bus->state = PREAMBLE;
if (!bus->drive) if (!bus->drive) {
mdio_write_req(bus); mdio_write_req(bus);
bus->drive = 0; }
} bus->drive = 0;
} }
break; }
default: break;
break; default:
} break;
}
} }
/* ETRAX-FS Ethernet MAC block starts here. */ /* ETRAX-FS Ethernet MAC block starts here. */
#define RW_MA0_LO 0x00 #define RW_MA0_LO 0x00
#define RW_MA0_HI 0x01 #define RW_MA0_HI 0x01
#define RW_MA1_LO 0x02 #define RW_MA1_LO 0x02
#define RW_MA1_HI 0x03 #define RW_MA1_HI 0x03
#define RW_GA_LO 0x04 #define RW_GA_LO 0x04
#define RW_GA_HI 0x05 #define RW_GA_HI 0x05
#define RW_GEN_CTRL 0x06 #define RW_GEN_CTRL 0x06
#define RW_REC_CTRL 0x07 #define RW_REC_CTRL 0x07
#define RW_TR_CTRL 0x08 #define RW_TR_CTRL 0x08
#define RW_CLR_ERR 0x09 #define RW_CLR_ERR 0x09
#define RW_MGM_CTRL 0x0a #define RW_MGM_CTRL 0x0a
#define R_STAT 0x0b #define R_STAT 0x0b
#define FS_ETH_MAX_REGS 0x17 #define FS_ETH_MAX_REGS 0x17
struct fs_eth struct fs_eth
{ {
SysBusDevice busdev; SysBusDevice busdev;
MemoryRegion mmio; MemoryRegion mmio;
NICState *nic; NICState *nic;
NICConf conf; NICConf conf;
/* Two addrs in the filter. */ /* Two addrs in the filter. */
uint8_t macaddr[2][6]; uint8_t macaddr[2][6];
uint32_t regs[FS_ETH_MAX_REGS]; uint32_t regs[FS_ETH_MAX_REGS];
union { union {
void *vdma_out; void *vdma_out;
struct etraxfs_dma_client *dma_out; struct etraxfs_dma_client *dma_out;
}; };
union { union {
void *vdma_in; void *vdma_in;
struct etraxfs_dma_client *dma_in; struct etraxfs_dma_client *dma_in;
}; };
/* MDIO bus. */ /* MDIO bus. */
struct qemu_mdio mdio_bus; struct qemu_mdio mdio_bus;
unsigned int phyaddr; unsigned int phyaddr;
int duplex_mismatch; int duplex_mismatch;
/* PHY. */ /* PHY. */
struct qemu_phy phy; struct qemu_phy phy;
}; };
static void eth_validate_duplex(struct fs_eth *eth) static void eth_validate_duplex(struct fs_eth *eth)
{ {
struct qemu_phy *phy; struct qemu_phy *phy;
unsigned int phy_duplex; unsigned int phy_duplex;
unsigned int mac_duplex; unsigned int mac_duplex;
int new_mm = 0; int new_mm = 0;
phy = eth->mdio_bus.devs[eth->phyaddr]; phy = eth->mdio_bus.devs[eth->phyaddr];
phy_duplex = !!(phy->read(phy, 18) & (1 << 11)); phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128); mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
if (mac_duplex != phy_duplex) if (mac_duplex != phy_duplex) {
new_mm = 1; new_mm = 1;
}
if (eth->regs[RW_GEN_CTRL] & 1) { if (eth->regs[RW_GEN_CTRL] & 1) {
if (new_mm != eth->duplex_mismatch) { if (new_mm != eth->duplex_mismatch) {
if (new_mm) if (new_mm) {
printf("HW: WARNING " printf("HW: WARNING ETH duplex mismatch MAC=%d PHY=%d\n",
"ETH duplex mismatch MAC=%d PHY=%d\n", mac_duplex, phy_duplex);
mac_duplex, phy_duplex); } else {
else printf("HW: ETH duplex ok.\n");
printf("HW: ETH duplex ok.\n"); }
} }
eth->duplex_mismatch = new_mm; eth->duplex_mismatch = new_mm;
} }
} }
static uint64_t static uint64_t
eth_read(void *opaque, hwaddr addr, unsigned int size) eth_read(void *opaque, hwaddr addr, unsigned int size)
{ {
struct fs_eth *eth = opaque; struct fs_eth *eth = opaque;
uint32_t r = 0; uint32_t r = 0;
addr >>= 2; addr >>= 2;
switch (addr) { switch (addr) {
case R_STAT: case R_STAT:
r = eth->mdio_bus.mdio & 1; r = eth->mdio_bus.mdio & 1;
break; break;
default: default:
r = eth->regs[addr]; r = eth->regs[addr];
D(printf ("%s %x\n", __func__, addr * 4)); D(printf("%s %x\n", __func__, addr * 4));
break; break;
} }
return r; return r;
} }
static void eth_update_ma(struct fs_eth *eth, int ma) static void eth_update_ma(struct fs_eth *eth, int ma)
{ {
int reg; int reg;
int i = 0; int i = 0;
ma &= 1; ma &= 1;
reg = RW_MA0_LO; reg = RW_MA0_LO;
if (ma) if (ma) {
reg = RW_MA1_LO; reg = RW_MA1_LO;
}
eth->macaddr[ma][i++] = eth->regs[reg]; eth->macaddr[ma][i++] = eth->regs[reg];
eth->macaddr[ma][i++] = eth->regs[reg] >> 8; eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
eth->macaddr[ma][i++] = eth->regs[reg] >> 16; eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
eth->macaddr[ma][i++] = eth->regs[reg] >> 24; eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
eth->macaddr[ma][i++] = eth->regs[reg + 1]; eth->macaddr[ma][i++] = eth->regs[reg + 1];
eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8; eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8;
D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma, D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
eth->macaddr[ma][0], eth->macaddr[ma][1], eth->macaddr[ma][0], eth->macaddr[ma][1],
eth->macaddr[ma][2], eth->macaddr[ma][3], eth->macaddr[ma][2], eth->macaddr[ma][3],
eth->macaddr[ma][4], eth->macaddr[ma][5])); eth->macaddr[ma][4], eth->macaddr[ma][5]));
} }
static void static void
eth_write(void *opaque, hwaddr addr, eth_write(void *opaque, hwaddr addr,
uint64_t val64, unsigned int size) uint64_t val64, unsigned int size)
{ {
struct fs_eth *eth = opaque; struct fs_eth *eth = opaque;
uint32_t value = val64; uint32_t value = val64;
addr >>= 2; addr >>= 2;
switch (addr) switch (addr) {
{ case RW_MA0_LO:
case RW_MA0_LO: case RW_MA0_HI:
case RW_MA0_HI: eth->regs[addr] = value;
eth->regs[addr] = value; eth_update_ma(eth, 0);
eth_update_ma(eth, 0); break;
break; case RW_MA1_LO:
case RW_MA1_LO: case RW_MA1_HI:
case RW_MA1_HI: eth->regs[addr] = value;
eth->regs[addr] = value; eth_update_ma(eth, 1);
eth_update_ma(eth, 1); break;
break;
case RW_MGM_CTRL: case RW_MGM_CTRL:
/* Attach an MDIO/PHY abstraction. */ /* Attach an MDIO/PHY abstraction. */
if (value & 2) if (value & 2) {
eth->mdio_bus.mdio = value & 1; eth->mdio_bus.mdio = value & 1;
if (eth->mdio_bus.mdc != (value & 4)) { }
mdio_cycle(&eth->mdio_bus); if (eth->mdio_bus.mdc != (value & 4)) {
eth_validate_duplex(eth); mdio_cycle(&eth->mdio_bus);
} eth_validate_duplex(eth);
eth->mdio_bus.mdc = !!(value & 4); }
eth->regs[addr] = value; eth->mdio_bus.mdc = !!(value & 4);
break; eth->regs[addr] = value;
break;
case RW_REC_CTRL: case RW_REC_CTRL:
eth->regs[addr] = value; eth->regs[addr] = value;
eth_validate_duplex(eth); eth_validate_duplex(eth);
break; break;
default: default:
eth->regs[addr] = value; eth->regs[addr] = value;
D(printf ("%s %x %x\n", D(printf("%s %x %x\n", __func__, addr, value));
__func__, addr, value)); break;
break; }
}
} }
/* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom
filter dropping group addresses we have not joined. The filter has 64 filter dropping group addresses we have not joined. The filter has 64
bits (m). The has function is a simple nible xor of the group addr. */ bits (m). The has function is a simple nible xor of the group addr. */
static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa) static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa)
{ {
unsigned int hsh; unsigned int hsh;
int m_individual = eth->regs[RW_REC_CTRL] & 4; int m_individual = eth->regs[RW_REC_CTRL] & 4;
int match; int match;
/* First bit on the wire of a MAC address signals multicast or /* First bit on the wire of a MAC address signals multicast or
physical address. */ physical address. */
if (!m_individual && !(sa[0] & 1)) if (!m_individual && !(sa[0] & 1)) {
return 0; return 0;
}
/* Calculate the hash index for the GA registers. */ /* Calculate the hash index for the GA registers. */
hsh = 0; hsh = 0;
hsh ^= (*sa) & 0x3f; hsh ^= (*sa) & 0x3f;
hsh ^= ((*sa) >> 6) & 0x03; hsh ^= ((*sa) >> 6) & 0x03;
++sa; ++sa;
hsh ^= ((*sa) << 2) & 0x03c; hsh ^= ((*sa) << 2) & 0x03c;
hsh ^= ((*sa) >> 4) & 0xf; hsh ^= ((*sa) >> 4) & 0xf;
++sa; ++sa;
hsh ^= ((*sa) << 4) & 0x30; hsh ^= ((*sa) << 4) & 0x30;
hsh ^= ((*sa) >> 2) & 0x3f; hsh ^= ((*sa) >> 2) & 0x3f;
++sa; ++sa;
hsh ^= (*sa) & 0x3f; hsh ^= (*sa) & 0x3f;
hsh ^= ((*sa) >> 6) & 0x03; hsh ^= ((*sa) >> 6) & 0x03;
++sa; ++sa;
hsh ^= ((*sa) << 2) & 0x03c; hsh ^= ((*sa) << 2) & 0x03c;
hsh ^= ((*sa) >> 4) & 0xf; hsh ^= ((*sa) >> 4) & 0xf;
++sa; ++sa;
hsh ^= ((*sa) << 4) & 0x30; hsh ^= ((*sa) << 4) & 0x30;
hsh ^= ((*sa) >> 2) & 0x3f; hsh ^= ((*sa) >> 2) & 0x3f;
hsh &= 63; hsh &= 63;
if (hsh > 31) if (hsh > 31) {
match = eth->regs[RW_GA_HI] & (1 << (hsh - 32)); match = eth->regs[RW_GA_HI] & (1 << (hsh - 32));
else } else {
match = eth->regs[RW_GA_LO] & (1 << hsh); match = eth->regs[RW_GA_LO] & (1 << hsh);
D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh, }
eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match)); D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh,
return match; eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match));
return match;
} }
static int eth_can_receive(NetClientState *nc) static int eth_can_receive(NetClientState *nc)
{ {
return 1; return 1;
} }
static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size) static ssize_t eth_receive(NetClientState *nc, const uint8_t *buf, size_t size)
{ {
unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
int use_ma0 = eth->regs[RW_REC_CTRL] & 1; int use_ma0 = eth->regs[RW_REC_CTRL] & 1;
int use_ma1 = eth->regs[RW_REC_CTRL] & 2; int use_ma1 = eth->regs[RW_REC_CTRL] & 2;
int r_bcast = eth->regs[RW_REC_CTRL] & 8; int r_bcast = eth->regs[RW_REC_CTRL] & 8;
if (size < 12) if (size < 12) {
return -1; return -1;
}
D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n", D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n",
buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
use_ma0, use_ma1, r_bcast)); use_ma0, use_ma1, r_bcast));
/* Does the frame get through the address filters? */ /* Does the frame get through the address filters? */
if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6)) if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6))
&& (!use_ma1 || memcmp(buf, eth->macaddr[1], 6)) && (!use_ma1 || memcmp(buf, eth->macaddr[1], 6))
&& (!r_bcast || memcmp(buf, sa_bcast, 6)) && (!r_bcast || memcmp(buf, sa_bcast, 6))
&& !eth_match_groupaddr(eth, buf)) && !eth_match_groupaddr(eth, buf)) {
return size; return size;
}
/* FIXME: Find another way to pass on the fake csum. */ /* FIXME: Find another way to pass on the fake csum. */
etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1); etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1);
return size; return size;
} }
static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop) static int eth_tx_push(void *opaque, unsigned char *buf, int len, bool eop)
{ {
struct fs_eth *eth = opaque; struct fs_eth *eth = opaque;
D(printf("%s buf=%p len=%d\n", __func__, buf, len)); D(printf("%s buf=%p len=%d\n", __func__, buf, len));
qemu_send_packet(&eth->nic->nc, buf, len); qemu_send_packet(&eth->nic->nc, buf, len);
return len; return len;
} }
static void eth_set_link(NetClientState *nc) static void eth_set_link(NetClientState *nc)
{ {
struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
D(printf("%s %d\n", __func__, nc->link_down)); D(printf("%s %d\n", __func__, nc->link_down));
eth->phy.link = !nc->link_down; eth->phy.link = !nc->link_down;
} }
static const MemoryRegionOps eth_ops = { static const MemoryRegionOps eth_ops = {
.read = eth_read, .read = eth_read,
.write = eth_write, .write = eth_write,
.endianness = DEVICE_LITTLE_ENDIAN, .endianness = DEVICE_LITTLE_ENDIAN,
.valid = { .valid = {
.min_access_size = 4, .min_access_size = 4,
.max_access_size = 4 .max_access_size = 4
} }
}; };
static void eth_cleanup(NetClientState *nc) static void eth_cleanup(NetClientState *nc)
{ {
struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque; struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
/* Disconnect the client. */ /* Disconnect the client. */
eth->dma_out->client.push = NULL; eth->dma_out->client.push = NULL;
eth->dma_out->client.opaque = NULL; eth->dma_out->client.opaque = NULL;
eth->dma_in->client.opaque = NULL; eth->dma_in->client.opaque = NULL;
eth->dma_in->client.pull = NULL; eth->dma_in->client.pull = NULL;
g_free(eth); g_free(eth);
} }
static NetClientInfo net_etraxfs_info = { static NetClientInfo net_etraxfs_info = {
.type = NET_CLIENT_OPTIONS_KIND_NIC, .type = NET_CLIENT_OPTIONS_KIND_NIC,
.size = sizeof(NICState), .size = sizeof(NICState),
.can_receive = eth_can_receive, .can_receive = eth_can_receive,
.receive = eth_receive, .receive = eth_receive,
.cleanup = eth_cleanup, .cleanup = eth_cleanup,
.link_status_changed = eth_set_link, .link_status_changed = eth_set_link,
}; };
static int fs_eth_init(SysBusDevice *dev) static int fs_eth_init(SysBusDevice *dev)
{ {
struct fs_eth *s = FROM_SYSBUS(typeof(*s), dev); struct fs_eth *s = FROM_SYSBUS(typeof(*s), dev);
if (!s->dma_out || !s->dma_in) { if (!s->dma_out || !s->dma_in) {
hw_error("Unconnected ETRAX-FS Ethernet MAC.\n"); hw_error("Unconnected ETRAX-FS Ethernet MAC.\n");
} }
s->dma_out->client.push = eth_tx_push; s->dma_out->client.push = eth_tx_push;
s->dma_out->client.opaque = s; s->dma_out->client.opaque = s;
s->dma_in->client.opaque = s; s->dma_in->client.opaque = s;
s->dma_in->client.pull = NULL; s->dma_in->client.pull = NULL;
memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c); memory_region_init_io(&s->mmio, &eth_ops, s, "etraxfs-eth", 0x5c);
sysbus_init_mmio(dev, &s->mmio); sysbus_init_mmio(dev, &s->mmio);
qemu_macaddr_default_if_unset(&s->conf.macaddr); qemu_macaddr_default_if_unset(&s->conf.macaddr);
s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf, s->nic = qemu_new_nic(&net_etraxfs_info, &s->conf,
object_get_typename(OBJECT(s)), dev->qdev.id, s); object_get_typename(OBJECT(s)), dev->qdev.id, s);
qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a); qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
tdk_init(&s->phy); tdk_init(&s->phy);
mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr); mdio_attach(&s->mdio_bus, &s->phy, s->phyaddr);
return 0; return 0;
} }
static Property etraxfs_eth_properties[] = { static Property etraxfs_eth_properties[] = {