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

minic_fifo: receiving frames with new minic HDL

parent 16a21407
......@@ -20,22 +20,13 @@
#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_MASK ((1<<F_COUNTER_BITS)-1)
#define RX_DESC_VALID(d) ((d) & (1<<31) ? 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 RX_STATUS_ERROR(d) ((d) & (1<<1) ? 1 : 0)
#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
......@@ -45,8 +36,6 @@
rc = (raw) & 0xfffffff; \
fc = (raw >> 28) & 0xf;
static volatile uint32_t dma_rx_buf[MINIC_DMA_RX_BUF_SIZE / 4];
struct wr_minic minic;
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)
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()
{
uint32_t mcr;
......@@ -85,90 +88,122 @@ void minic_disable()
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,
struct hw_timestamp *hwts)
{
uint32_t frame_size, payload_size, num_words;
uint32_t desc_hdr;
uint32_t hdr_size, payload_size;
uint32_t raw_ts;
uint32_t cur_avail;
int n_recvd;
if (!(minic_readl(MINIC_REG_EIC_ISR) & MINIC_EIC_ISR_RX))
uint8_t rx_empty, rx_full, rx_type;
uint16_t rx_data;
uint16_t *ptr16_hdr, *ptr16_payload;
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;
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. */
//invalid descriptor ? then probably the interrupt was generated by full rx buffer
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL) {
//minic_new_rx_buffer();
hdr_size = 0;
payload_size = 0;
/* uint16_t pointers to copy directly 16-bit data from FIFO to memory */
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;
/* valid packet */
if (!RX_DESC_ERROR(desc_hdr)) {
//if (RX_DESC_HAS_OOB(desc_hdr) && hwts != NULL) {
// uint32_t counter_r, counter_f, counter_ppsg;
// uint64_t sec;
// int cntr_diff;
// 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);
if (oob_cnt == 0 || oob_cnt > RX_OOB_SIZE) {
/* in WRPC we expect every Rx frame to contain a valid OOB.
* If it's not the case, something went wrong... */
net_verbose("Warning: got incorrect or missing Rx OOB\n");
if (hwts)
hwts->valid = 0;
} else if (hwts) {
/* build correct timestamp to return in hwts structure */
shw_pps_gen_get_time(&sec, &counter_ppsg);
// shw_pps_gen_get_time(&sec, &counter_ppsg);
// if (counter_r > 3 * REF_CLOCK_FREQ_HZ / 4
// && counter_ppsg < 250000000)
// sec--;
EXPLODE_WR_TIMESTAMP(raw_ts, counter_r, counter_f);
// 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))
// hwts->ahead = 1;
// else
// hwts->ahead = 0;
cntr_diff = (counter_r & F_COUNTER_MASK) - counter_f;
// hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000);
// hwts->valid = (dhdr & RXOOB_TS_INCORRECT) ? 0 : 1;
//}
payload_size = frame_size - ETH_HEADER_SIZE;
n_recvd = (buf_size < payload_size ? buf_size : payload_size);
minic.rx_count++;
if (cntr_diff == 1 || cntr_diff == (-F_COUNTER_MASK))
hwts->ahead = 1;
else
hwts->ahead = 0;
} else {
n_recvd = -1;
hwts->nsec = counter_r * (REF_CLOCK_PERIOD_PS / 1000);
hwts->valid = (oob_hdr & RXOOB_TS_INCORRECT) ? 0 : 1;
}
/*empty buffer->no more received packets, or packet reception in progress but not done */
//if (!RX_DESC_VALID(*minic.rx_head)) {
if (minic_readl(MINIC_REG_MCR) & MINIC_MCR_RX_FULL)
//minic_new_rx_buffer();
/* Increment Rx counter for statistics */
minic.rx_count++;
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,
......
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