Commit 27cf9155 authored by Grzegorz Daniluk's avatar Grzegorz Daniluk

minic_fifo: receiving frames with new minic HDL

parent 16a21407
...@@ -20,22 +20,13 @@ ...@@ -20,22 +20,13 @@
#include <hw/minic_regs.h> #include <hw/minic_regs.h>
#define MINIC_DMA_TX_BUF_SIZE 1024
#define MINIC_DMA_RX_BUF_SIZE 2048
#define MINIC_MTU 256
#define F_COUNTER_BITS 4 #define F_COUNTER_BITS 4
#define F_COUNTER_MASK ((1<<F_COUNTER_BITS)-1) #define F_COUNTER_MASK ((1<<F_COUNTER_BITS)-1)
#define RX_DESC_VALID(d) ((d) & (1<<31) ? 1 : 0) #define RX_STATUS_ERROR(d) ((d) & (1<<1) ? 1 : 0)
#define RX_DESC_ERROR(d) ((d) & (1<<30) ? 1 : 0)
#define RX_DESC_HAS_OOB(d) ((d) & (1<<29) ? 1 : 0)
#define RX_DESC_SIZE(d) (((d) & (1<<0) ? -1 : 0) + (d & 0xffe))
#define RXOOB_TS_INCORRECT (1<<11) #define RXOOB_TS_INCORRECT (1<<11)
#define RX_OOB_SIZE 6 #define RX_OOB_SIZE 3 /* as the number of FIFO data words */
#define ETH_HEADER_SIZE 14 #define ETH_HEADER_SIZE 14
...@@ -45,8 +36,6 @@ ...@@ -45,8 +36,6 @@
rc = (raw) & 0xfffffff; \ rc = (raw) & 0xfffffff; \
fc = (raw >> 28) & 0xf; fc = (raw >> 28) & 0xf;
static volatile uint32_t dma_rx_buf[MINIC_DMA_RX_BUF_SIZE / 4];
struct wr_minic minic; struct wr_minic minic;
static inline void minic_writel(uint32_t reg, uint32_t data) static inline void minic_writel(uint32_t reg, uint32_t data)
...@@ -65,6 +54,20 @@ static inline void minic_txword(uint8_t type, uint16_t word) ...@@ -65,6 +54,20 @@ static inline void minic_txword(uint8_t type, uint16_t word)
MINIC_TX_FIFO_TYPE_W(type) | MINIC_TX_FIFO_DAT_W(word)); MINIC_TX_FIFO_TYPE_W(type) | MINIC_TX_FIFO_DAT_W(word));
} }
static inline void minic_rxword(uint8_t *type, uint16_t *data, uint8_t *empty,
uint8_t *full)
{
uint32_t rx;
rx = minic_readl(MINIC_REG_RX_FIFO);
*type = (uint8_t) MINIC_RX_FIFO_TYPE_R(rx);
*data = (uint16_t) MINIC_RX_FIFO_DAT_R(rx);
if (empty)
*empty = (rx & MINIC_RX_FIFO_EMPTY) ? 1 : 0;
if (full)
*full = (rx & MINIC_RX_FIFO_FULL) ? 1 : 0;
}
void minic_init() void minic_init()
{ {
uint32_t mcr; uint32_t mcr;
...@@ -85,90 +88,122 @@ void minic_disable() ...@@ -85,90 +88,122 @@ void minic_disable()
int minic_poll_rx() int minic_poll_rx()
{ {
uint32_t isr; uint32_t mcr;
isr = minic_readl(MINIC_REG_EIC_ISR); mcr = minic_readl(MINIC_REG_MCR);
return (isr & MINIC_EIC_ISR_RX) ? 1 : 0; return (mcr & MINIC_MCR_RX_EMPTY) ? 0 : 1;
} }
int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size, int minic_rx_frame(struct wr_ethhdr *hdr, uint8_t * payload, uint32_t buf_size,
struct hw_timestamp *hwts) struct hw_timestamp *hwts)
{ {
uint32_t frame_size, payload_size, num_words; uint32_t hdr_size, payload_size;
uint32_t desc_hdr;
uint32_t raw_ts; uint32_t raw_ts;
uint32_t cur_avail; uint8_t rx_empty, rx_full, rx_type;
int n_recvd; uint16_t rx_data;
uint16_t *ptr16_hdr, *ptr16_payload;
if (!(minic_readl(MINIC_REG_EIC_ISR) & MINIC_EIC_ISR_RX)) uint32_t oob_cnt;
uint16_t oob_hdr;
uint64_t sec;
uint32_t counter_r, counter_f, counter_ppsg;
int cntr_diff;
/* check if there is something in the Rx FIFO to be retrieved */
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_EMPTY)
return 0; return 0;
if (!RX_DESC_VALID(desc_hdr)) { /* invalid descriptor? Weird, the RX_ADDR seems to be saying something different. Ignore the packet and purge the RX buffer. */ hdr_size = 0;
//invalid descriptor ? then probably the interrupt was generated by full rx buffer payload_size = 0;
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL) { /* uint16_t pointers to copy directly 16-bit data from FIFO to memory */
//minic_new_rx_buffer(); ptr16_hdr = (uint16_t *)hdr;
ptr16_payload = (uint16_t *)payload;
/* Read the whole frame till OOB or till the FIFO is empty */
do {
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full);
if (rx_type == WRF_DATA && hdr_size < ETH_HEADER_SIZE) {
/* reading header */
ptr16_hdr[hdr_size>>1] = rx_data;
hdr_size += 2;
} else if (rx_type != WRF_STATUS && payload_size > buf_size) {
/* we've filled the whole buffer, in this case retreive
* remaining part of this frame (WRF_DATA or
* WRF_BYTESEL) but don't store it in the buffer */
payload_size += 2;
} else if (rx_type == WRF_DATA) {
/* normal situation, retreiving payload */
ptr16_payload[payload_size>>1] = rx_data;
payload_size += 2;
} else if (rx_type == WRF_BYTESEL) {
ptr16_payload[payload_size>>1] = rx_data;
payload_size += 1;
} else if (rx_type == WRF_STATUS && hdr_size > 0) {
/* receiving status means error in our frame or
* beginning of next frame. We check hdr_size > 0 to
* make sure it's not the first received word, i.e. our
* own initial status.*/
if (RX_STATUS_ERROR(rx_data))
pp_printf("Warning: Minic received erroneous "
"frame\n");
break;
} }
return 0; } while (!rx_empty && rx_type != WRF_OOB);
/* Receive OOB, if it's there */
oob_cnt = 0;
raw_ts = 0;
oob_hdr = RXOOB_TS_INCORRECT;
while (!rx_empty && rx_type == WRF_OOB) {
if (oob_cnt == 0)
oob_hdr = rx_data;
else if (oob_cnt == 1)
raw_ts = (rx_data << 16) & 0xffff0000;
else if (oob_cnt == 2)
raw_ts |= (rx_data & 0x0000ffff);
minic_rxword(&rx_type, &rx_data, &rx_empty, &rx_full);
oob_cnt++;
} }
num_words = ((frame_size + 3) >> 2) + 1; if (oob_cnt == 0 || oob_cnt > RX_OOB_SIZE) {
/* in WRPC we expect every Rx frame to contain a valid OOB.
/* valid packet */ * If it's not the case, something went wrong... */
if (!RX_DESC_ERROR(desc_hdr)) { net_verbose("Warning: got incorrect or missing Rx OOB\n");
if (hwts)
//if (RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL) { hwts->valid = 0;
// uint32_t counter_r, counter_f, counter_ppsg; } else if (hwts) {
// uint64_t sec; /* build correct timestamp to return in hwts structure */
// int cntr_diff; shw_pps_gen_get_time(&sec, &counter_ppsg);
// uint16_t dhdr;
// frame_size -= RX_OOB_SIZE;
// /* fixme: ugly way of doing unaligned read */
// minic_rx_memcpy((uint8_t *) & raw_ts,
// (uint8_t *) minic.rx_head
// + frame_size + 6, 4);
// minic_rx_memcpy((uint8_t *) & dhdr,
// (uint8_t *) minic.rx_head +
// frame_size + 4, 2);
// EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
// shw_pps_gen_get_time(&sec, &counter_ppsg); EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
// if (counter_r > 3 * REF_CLOCK_FREQ_HZ / 4
// && counter_ppsg < 250000000)
// sec--;
// hwts->sec = sec & 0x7fffffff; if (counter_r > 3 * REF_CLOCK_FREQ_HZ / 4
&& counter_ppsg < 250000000)
sec--;
// cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f; hwts->sec = sec & 0x7fffffff;
// if (cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK)) cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
// hwts->ahead = 1;
// else
// hwts->ahead = 0;
// hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000); if (cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK))
// hwts->valid = (dhdr & RXOOB_TS_INCORRECT) ? 0 : 1; hwts->ahead = 1;
//} else
payload_size = frame_size - ETH_HEADER_SIZE; hwts->ahead = 0;
n_recvd = (buf_size < payload_size ? buf_size : payload_size);
minic.rx_count++;
} else { hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000);
n_recvd = -1; hwts->valid = (oob_hdr & RXOOB_TS_INCORRECT) ? 0 : 1;
} }
/*empty buffer->no more received packets, or packet reception in progress but not done */ /* Increment Rx counter for statistics */
//if (!RX_DESC_VALID(*minic.rx_head)) { minic.rx_count++;
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL)
//minic_new_rx_buffer();
minic_writel(MINIC_REG_EIC_ISR, MINIC_EIC_ISR_RX); if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL)
//} pp_printf("Warning: Minic Rx fifo full, expect wrong frames");
return n_recvd; /* return number of bytes written to the *payload buffer */
return (buf_size < payload_size ? buf_size : payload_size);
} }
int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size, int minic_tx_frame(struct wr_ethhdr_vlan *hdr, uint8_t *payload, uint32_t size,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment