提交 ebdd8cdd 编写于 作者: A Andrey Smirnov 提交者: Peter Maydell

imx_fec: Emulate SHIFT16 in ENETx_RACC

Needed to support latest Linux kernel driver which relies on that
functionality.

Cc: Peter Maydell <peter.maydell@linaro.org>
Cc: Jason Wang <jasowang@redhat.com>
Cc: Philippe Mathieu-Daudé <f4bug@amsat.org>
Cc: qemu-devel@nongnu.org
Cc: qemu-arm@nongnu.org
Cc: yurovsky@gmail.com
Reviewed-by: NPeter Maydell <peter.maydell@linaro.org>
Signed-off-by: NAndrey Smirnov <andrew.smirnov@gmail.com>
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
上级 4c5e7a6c
......@@ -1037,6 +1037,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
uint8_t *crc_ptr;
unsigned int buf_len;
size_t size = len;
bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
FEC_PRINTF("len %d\n", (int)size);
......@@ -1051,6 +1052,10 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
crc = cpu_to_be32(crc32(~0, buf, size));
crc_ptr = (uint8_t *) &crc;
if (shift16) {
size += 2;
}
/* Huge frames are truncted. */
if (size > s->regs[ENET_FTRL]) {
size = s->regs[ENET_FTRL];
......@@ -1087,6 +1092,24 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
buf_len += size - 4;
}
buf_addr = bd.data;
if (shift16) {
/*
* If SHIFT16 bit of ENETx_RACC register is set we need to
* align the payload to 4-byte boundary.
*/
const uint8_t zeros[2] = { 0 };
dma_memory_write(&address_space_memory, buf_addr,
zeros, sizeof(zeros));
buf_addr += sizeof(zeros);
buf_len -= sizeof(zeros);
/* We only do this once per Ethernet frame */
shift16 = false;
}
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
buf += buf_len;
if (size < 4) {
......
......@@ -170,6 +170,8 @@
#define ENET_TWFR_TFWR_LENGTH (6)
#define ENET_TWFR_STRFWD (1 << 8)
#define ENET_RACC_SHIFT16 BIT(7)
/* Buffer Descriptor. */
typedef struct {
uint16_t length;
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册