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: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Andrey Smirnov <andrew.smirnov@gmail.com> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
4c5e7a6cda
commit
ebdd8cddb9
@ -1037,6 +1037,7 @@ static ssize_t imx_enet_receive(NetClientState *nc, const uint8_t *buf,
|
|||||||
uint8_t *crc_ptr;
|
uint8_t *crc_ptr;
|
||||||
unsigned int buf_len;
|
unsigned int buf_len;
|
||||||
size_t size = len;
|
size_t size = len;
|
||||||
|
bool shift16 = s->regs[ENET_RACC] & ENET_RACC_SHIFT16;
|
||||||
|
|
||||||
FEC_PRINTF("len %d\n", (int)size);
|
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 = cpu_to_be32(crc32(~0, buf, size));
|
||||||
crc_ptr = (uint8_t *) &crc;
|
crc_ptr = (uint8_t *) &crc;
|
||||||
|
|
||||||
|
if (shift16) {
|
||||||
|
size += 2;
|
||||||
|
}
|
||||||
|
|
||||||
/* Huge frames are truncted. */
|
/* Huge frames are truncted. */
|
||||||
if (size > s->regs[ENET_FTRL]) {
|
if (size > s->regs[ENET_FTRL]) {
|
||||||
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_len += size - 4;
|
||||||
}
|
}
|
||||||
buf_addr = bd.data;
|
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);
|
dma_memory_write(&address_space_memory, buf_addr, buf, buf_len);
|
||||||
buf += buf_len;
|
buf += buf_len;
|
||||||
if (size < 4) {
|
if (size < 4) {
|
||||||
|
@ -170,6 +170,8 @@
|
|||||||
#define ENET_TWFR_TFWR_LENGTH (6)
|
#define ENET_TWFR_TFWR_LENGTH (6)
|
||||||
#define ENET_TWFR_STRFWD (1 << 8)
|
#define ENET_TWFR_STRFWD (1 << 8)
|
||||||
|
|
||||||
|
#define ENET_RACC_SHIFT16 BIT(7)
|
||||||
|
|
||||||
/* Buffer Descriptor. */
|
/* Buffer Descriptor. */
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint16_t length;
|
uint16_t length;
|
||||||
|
Loading…
Reference in New Issue
Block a user