2015-04-08 19:54:00 +02:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2015 Ell-i open source co-operative
|
|
|
|
* Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
*
|
|
|
|
* This file is subject to the terms and conditions of the GNU Lesser
|
|
|
|
* General Public License v2.1. See the file LICENSE in the top level
|
|
|
|
* directory for more details.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/**
|
|
|
|
* @ingroup driver_encx24j600
|
|
|
|
* @{
|
|
|
|
*
|
|
|
|
* @file
|
|
|
|
* @brief Internal functions for the ENCX24J600 driver
|
|
|
|
*
|
|
|
|
* @author Kaspar Schleiser <kaspar@schleiser.de>
|
|
|
|
*
|
|
|
|
* @}
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include <errno.h>
|
|
|
|
|
|
|
|
#include "mutex.h"
|
|
|
|
#include "encx24j600.h"
|
|
|
|
#include "encx24j600_internal.h"
|
|
|
|
#include "encx24j600_defines.h"
|
2015-08-14 00:46:42 +02:00
|
|
|
#include "xtimer.h"
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
#include "net/netdev.h"
|
|
|
|
#include "net/netdev/eth.h"
|
2015-04-08 19:54:00 +02:00
|
|
|
#include "net/eui64.h"
|
|
|
|
#include "net/ethernet.h"
|
2017-05-18 17:11:39 +02:00
|
|
|
|
|
|
|
#ifdef MODULE_NETSTATS_L2
|
|
|
|
#include <string.h>
|
2016-04-03 18:05:07 +02:00
|
|
|
#include "net/netstats.h"
|
2017-05-18 17:11:39 +02:00
|
|
|
#endif
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
#define ENABLE_DEBUG (0)
|
|
|
|
#include "debug.h"
|
|
|
|
|
2016-11-08 18:41:38 +01:00
|
|
|
#define SPI_CLK SPI_CLK_1MHZ
|
|
|
|
#define SPI_MODE SPI_MODE_0
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-11-08 18:41:38 +01:00
|
|
|
#define ENCX24J600_INIT_DELAY (100000U)
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-11-08 18:41:38 +01:00
|
|
|
#define ENC_BUFFER_START (0x0000)
|
|
|
|
#define ENC_BUFFER_SIZE (0x6000)
|
|
|
|
#define ENC_BUFFER_END (0x5FFF)
|
|
|
|
#define RX_BUFFER_START (0x5340) /* Default value */
|
|
|
|
#define RX_BUFFER_END (ENC_BUFFER_END)
|
|
|
|
#define TX_BUFFER_LEN (0x2000)
|
|
|
|
#define TX_BUFFER_END (RX_BUFFER_START)
|
|
|
|
#define TX_BUFFER_START (TX_BUFFER_END - TX_BUFFER_LEN)
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
static void cmd(encx24j600_t *dev, char cmd);
|
|
|
|
static void reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value);
|
|
|
|
static uint16_t reg_get(encx24j600_t *dev, uint8_t reg);
|
|
|
|
static void reg_clear_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask);
|
|
|
|
static inline int _packets_available(encx24j600_t *dev);
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static void _get_mac_addr(netdev_t *dev, uint8_t* buf);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
/* netdev interface */
|
|
|
|
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count);
|
|
|
|
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info);
|
|
|
|
static int _init(netdev_t *dev);
|
|
|
|
static void _isr(netdev_t *dev);
|
|
|
|
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
const static netdev_driver_t netdev_driver_encx24j600 = {
|
2015-04-08 19:54:00 +02:00
|
|
|
.send = _send,
|
|
|
|
.recv = _recv,
|
|
|
|
.init = _init,
|
|
|
|
.isr = _isr,
|
|
|
|
.get = _get,
|
2017-02-15 13:07:34 +01:00
|
|
|
.set = netdev_eth_set,
|
2015-04-08 19:54:00 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
static inline void lock(encx24j600_t *dev) {
|
2016-11-08 18:41:38 +01:00
|
|
|
spi_acquire(dev->spi, dev->cs, SPI_MODE, SPI_CLK);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline void unlock(encx24j600_t *dev) {
|
2016-11-08 18:41:38 +01:00
|
|
|
spi_release(dev->spi);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
2016-03-27 21:36:00 +02:00
|
|
|
void encx24j600_setup(encx24j600_t *dev, const encx24j600_params_t *params)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
2017-02-15 13:07:34 +01:00
|
|
|
dev->netdev.driver = &netdev_driver_encx24j600;
|
2016-03-27 21:36:00 +02:00
|
|
|
dev->spi = params->spi;
|
2016-04-06 22:53:27 +02:00
|
|
|
dev->cs = params->cs_pin;
|
2016-03-27 21:36:00 +02:00
|
|
|
dev->int_pin = params->int_pin;
|
2015-04-08 19:54:00 +02:00
|
|
|
dev->rx_next_ptr = RX_BUFFER_START;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void encx24j600_isr(void *arg)
|
|
|
|
{
|
|
|
|
encx24j600_t *dev = (encx24j600_t *) arg;
|
|
|
|
|
|
|
|
/* disable interrupt line */
|
|
|
|
gpio_irq_disable(dev->int_pin);
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
/* call netdev hook */
|
|
|
|
dev->netdev.event_callback((netdev_t*) dev, NETDEV_EVENT_ISR);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static void _isr(netdev_t *netdev)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
|
|
|
encx24j600_t *dev = (encx24j600_t *) netdev;
|
|
|
|
|
|
|
|
uint16_t eir;
|
|
|
|
|
|
|
|
lock(dev);
|
2016-04-06 22:53:47 +02:00
|
|
|
cmd(dev, ENC_CLREIE);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-04-06 22:53:47 +02:00
|
|
|
eir = reg_get(dev, ENC_EIR);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* check & handle link state change */
|
2016-04-06 22:53:47 +02:00
|
|
|
if (eir & ENC_LINKIF) {
|
|
|
|
uint16_t estat = reg_get(dev, ENC_ESTAT);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
netdev_event_t event = (estat & ENC_PHYLNK) ?
|
|
|
|
NETDEV_EVENT_LINK_DOWN :
|
|
|
|
NETDEV_EVENT_LINK_UP;
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-02-21 23:56:19 +01:00
|
|
|
netdev->event_callback(netdev, event);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
/* check & handle available packets */
|
2016-04-06 22:53:47 +02:00
|
|
|
if (eir & ENC_PKTIF) {
|
2015-04-08 19:54:00 +02:00
|
|
|
while (_packets_available(dev)) {
|
|
|
|
unlock(dev);
|
2017-02-15 13:07:34 +01:00
|
|
|
netdev->event_callback(netdev, NETDEV_EVENT_RX_COMPLETE);
|
2015-04-08 19:54:00 +02:00
|
|
|
lock(dev);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* drop all flags */
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_clear_bits(dev, ENC_EIR, ENC_LINKIF);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* re-enable interrupt */
|
|
|
|
gpio_irq_enable(dev->int_pin);
|
2016-04-06 22:53:47 +02:00
|
|
|
cmd(dev, ENC_SETEIE);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
unlock(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline void enc_spi_transfer(encx24j600_t *dev, char *out, char *in, int len)
|
|
|
|
{
|
2016-11-08 18:41:38 +01:00
|
|
|
spi_transfer_bytes(dev->spi, dev->cs, false, out, in, len);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static inline uint16_t reg_get(encx24j600_t *dev, uint8_t reg)
|
|
|
|
{
|
2016-04-06 22:53:47 +02:00
|
|
|
char cmd[4] = { ENC_RCRU, reg, 0, 0 };
|
2015-04-08 19:54:00 +02:00
|
|
|
char result[4];
|
|
|
|
|
|
|
|
enc_spi_transfer(dev, cmd, result, 4);
|
|
|
|
|
|
|
|
return result[2] | (result[3] << 8);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void phy_reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value) {
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set(dev, ENC_MIREGADR, reg | (1<<8));
|
|
|
|
reg_set(dev, ENC_MIWR, value);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void cmd(encx24j600_t *dev, char cmd) {
|
2016-11-08 18:41:38 +01:00
|
|
|
spi_transfer_byte(dev->spi, dev->cs, false, (uint8_t)cmd);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void cmdn(encx24j600_t *dev, uint8_t cmd, char *out, char *in, int len) {
|
2016-11-08 18:41:38 +01:00
|
|
|
spi_transfer_byte(dev->spi, dev->cs, true, cmd);
|
|
|
|
spi_transfer_bytes(dev->spi, dev->cs, false, out, in, len);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
static void reg_set(encx24j600_t *dev, uint8_t reg, uint16_t value)
|
|
|
|
{
|
2016-04-06 22:53:47 +02:00
|
|
|
char cmd[4] = { ENC_WCRU, reg, value, value >> 8 };
|
2015-04-08 19:54:00 +02:00
|
|
|
enc_spi_transfer(dev, cmd, NULL, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void reg_set_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask)
|
|
|
|
{
|
2016-04-06 22:53:47 +02:00
|
|
|
char cmd[4] = { ENC_BFSU, reg, mask, mask >> 8 };
|
2015-04-08 19:54:00 +02:00
|
|
|
enc_spi_transfer(dev, cmd, NULL, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void reg_clear_bits(encx24j600_t *dev, uint8_t reg, uint16_t mask)
|
|
|
|
{
|
2016-04-06 22:53:47 +02:00
|
|
|
char cmd[4] = { ENC_BFCU, reg, mask, mask >> 8 };
|
2015-04-08 19:54:00 +02:00
|
|
|
enc_spi_transfer(dev, cmd, NULL, 4);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* @brief Read/Write to encx24j600's SRAM
|
|
|
|
*
|
|
|
|
* @param[in] dev ptr to encx24j600 device handle
|
2016-04-06 22:53:47 +02:00
|
|
|
* @param[in] cmd either ENC_WGPDATA, ENC_RGPDATA, ENC_WRXDATA, ENC_RRXDATA, ENC_WUDADATA, ENC_RUDADATA
|
2015-04-08 19:54:00 +02:00
|
|
|
* @param[in] addr SRAM address to start reading. 0xFFFF means continue from old address
|
|
|
|
* @param ptr pointer to buffer to read from / write to
|
|
|
|
* @param[in] len nr of bytes to read/write
|
|
|
|
*/
|
|
|
|
static void sram_op(encx24j600_t *dev, uint16_t cmd, uint16_t addr, char *ptr, int len)
|
|
|
|
{
|
|
|
|
uint16_t reg;
|
|
|
|
char* in = NULL;
|
|
|
|
char* out = NULL;
|
|
|
|
|
|
|
|
/* determine pointer addr
|
|
|
|
*
|
|
|
|
* all SRAM access commands have an
|
|
|
|
* offset 0x5e to their pointer registers
|
|
|
|
* */
|
|
|
|
reg = cmd + 0x5e;
|
|
|
|
|
|
|
|
/* read or write? bit 1 tells us */
|
|
|
|
if (reg & 0x2) {
|
|
|
|
out = ptr;
|
|
|
|
} else {
|
|
|
|
in = ptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set pointer */
|
|
|
|
if (addr != 0xFFFF) {
|
|
|
|
reg_set(dev, reg, addr);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* copy data */
|
|
|
|
cmdn(dev, cmd, in, out, len);
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static int _init(netdev_t *encdev)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
|
|
|
encx24j600_t *dev = (encx24j600_t *) encdev;
|
|
|
|
|
|
|
|
DEBUG("encx24j600: starting initialization...\n");
|
|
|
|
|
|
|
|
/* setup IO */
|
2016-11-08 18:41:38 +01:00
|
|
|
if (spi_init_cs(dev->spi, dev->cs) != SPI_OK) {
|
2015-04-08 19:54:00 +02:00
|
|
|
return -1;
|
|
|
|
}
|
2016-11-08 18:41:38 +01:00
|
|
|
gpio_init_int(dev->int_pin, GPIO_IN_PU, GPIO_FALLING, encx24j600_isr, (void*)dev);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
lock(dev);
|
|
|
|
|
|
|
|
/* initialization procedure as described in data sheet (39935c.pdf) */
|
|
|
|
do {
|
|
|
|
do {
|
2015-08-14 00:46:42 +02:00
|
|
|
xtimer_usleep(ENCX24J600_INIT_DELAY);
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set(dev, ENC_EUDAST, 0x1234);
|
2015-08-14 00:46:42 +02:00
|
|
|
xtimer_usleep(ENCX24J600_INIT_DELAY);
|
2016-04-06 22:53:47 +02:00
|
|
|
} while (reg_get(dev, ENC_EUDAST) != 0x1234);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-04-06 22:53:47 +02:00
|
|
|
while (!(reg_get(dev, ENC_ESTAT) & ENC_CLKRDY));
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* issue System Reset */
|
2016-04-06 22:53:47 +02:00
|
|
|
cmd(dev, ENC_SETETHRST);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* make sure initialization finalizes */
|
2015-08-14 00:46:42 +02:00
|
|
|
xtimer_usleep(1000);
|
2016-04-06 22:53:47 +02:00
|
|
|
} while (!(reg_get(dev, ENC_EUDAST) == 0x0000));
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* configure flow control */
|
2016-04-06 22:53:47 +02:00
|
|
|
phy_reg_set(dev, ENC_PHANA, 0x05E1);
|
|
|
|
reg_set_bits(dev, ENC_ECON2, ENC_AUTOFC);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* setup receive buffer */
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set(dev, ENC_ERXST, RX_BUFFER_START);
|
|
|
|
reg_set(dev, ENC_ERXTAIL, RX_BUFFER_END);
|
2015-04-08 19:54:00 +02:00
|
|
|
dev->rx_next_ptr = RX_BUFFER_START;
|
|
|
|
|
|
|
|
/* configure receive filter to receive multicast frames */
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set_bits(dev, ENC_ERXFCON, ENC_MCEN);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* setup interrupts */
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set_bits(dev, ENC_EIE, ENC_PKTIE | ENC_LINKIE);
|
|
|
|
cmd(dev, ENC_ENABLERX);
|
|
|
|
cmd(dev, ENC_SETEIE);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
DEBUG("encx24j600: initialization complete.\n");
|
|
|
|
|
|
|
|
unlock(dev);
|
|
|
|
|
2016-04-03 18:05:07 +02:00
|
|
|
#ifdef MODULE_NETSTATS_L2
|
2017-01-26 10:56:59 +01:00
|
|
|
memset(&encdev->stats, 0, sizeof(netstats_t));
|
2016-04-03 18:05:07 +02:00
|
|
|
#endif
|
2015-04-08 19:54:00 +02:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static int _send(netdev_t *netdev, const struct iovec *vector, unsigned count) {
|
2015-04-08 19:54:00 +02:00
|
|
|
encx24j600_t * dev = (encx24j600_t *) netdev;
|
|
|
|
lock(dev);
|
|
|
|
|
|
|
|
/* wait until previous packet has been sent */
|
2016-04-06 22:53:47 +02:00
|
|
|
while ((reg_get(dev, ENC_ECON1) & ENC_TXRTS));
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* copy packet to SRAM */
|
|
|
|
size_t len = 0;
|
|
|
|
|
|
|
|
for (int i = 0; i < count; i++) {
|
2016-04-06 22:53:47 +02:00
|
|
|
sram_op(dev, ENC_WGPDATA, (i ? 0xFFFF : TX_BUFFER_START), vector[i].iov_base, vector[i].iov_len);
|
2015-04-08 19:54:00 +02:00
|
|
|
len += vector[i].iov_len;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* set start of TX packet and length */
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set(dev, ENC_ETXST, TX_BUFFER_START);
|
|
|
|
reg_set(dev, ENC_ETXLEN, len);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* initiate sending */
|
2016-04-06 22:53:47 +02:00
|
|
|
cmd(dev, ENC_SETTXRTS);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* wait for sending to complete */
|
|
|
|
/* (not sure if it is needed, keeping the line uncommented) */
|
2016-04-06 22:53:47 +02:00
|
|
|
/*while ((reg_get(dev, ENC_ECON1) & ENC_TXRTS));*/
|
2015-04-08 19:54:00 +02:00
|
|
|
|
2016-06-17 11:44:07 +02:00
|
|
|
#ifdef MODULE_NETSTATS_L2
|
|
|
|
netdev->stats.tx_bytes += len;
|
|
|
|
#endif
|
|
|
|
|
2015-04-08 19:54:00 +02:00
|
|
|
unlock(dev);
|
|
|
|
|
|
|
|
return len;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline int _packets_available(encx24j600_t *dev)
|
|
|
|
{
|
2016-04-06 22:53:47 +02:00
|
|
|
/* return ENC_PKTCNT (low byte of ENC_ESTAT) */
|
|
|
|
return reg_get(dev, ENC_ESTAT) & ~0xFF00;
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static void _get_mac_addr(netdev_t *encdev, uint8_t* buf)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
|
|
|
encx24j600_t * dev = (encx24j600_t *) encdev;
|
|
|
|
uint16_t *addr = (uint16_t *) buf;
|
|
|
|
|
|
|
|
lock(dev);
|
|
|
|
|
2016-04-06 22:53:47 +02:00
|
|
|
addr[0] = reg_get(dev, ENC_MAADR1);
|
|
|
|
addr[1] = reg_get(dev, ENC_MAADR2);
|
|
|
|
addr[2] = reg_get(dev, ENC_MAADR3);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
unlock(dev);
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static int _recv(netdev_t *netdev, void *buf, size_t len, void *info)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
|
|
|
encx24j600_t * dev = (encx24j600_t *) netdev;
|
|
|
|
encx24j600_frame_hdr_t hdr;
|
|
|
|
|
2016-01-29 15:48:10 +01:00
|
|
|
(void)info;
|
2015-04-08 19:54:00 +02:00
|
|
|
lock(dev);
|
|
|
|
|
|
|
|
/* read frame header */
|
2016-04-06 22:53:47 +02:00
|
|
|
sram_op(dev, ENC_RRXDATA, dev->rx_next_ptr, (char*)&hdr, sizeof(hdr));
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* hdr.frame_len given by device contains 4 bytes checksum */
|
|
|
|
size_t payload_len = hdr.frame_len - 4;
|
|
|
|
|
2017-06-03 23:24:44 +02:00
|
|
|
|
2015-04-08 19:54:00 +02:00
|
|
|
if (buf) {
|
2017-06-03 23:24:44 +02:00
|
|
|
if (payload_len > len) {
|
|
|
|
/* payload exceeds buffer size */
|
|
|
|
unlock(dev);
|
|
|
|
return -ENOBUFS;
|
|
|
|
}
|
2016-04-03 18:05:07 +02:00
|
|
|
#ifdef MODULE_NETSTATS_L2
|
|
|
|
netdev->stats.rx_count++;
|
2017-06-04 20:08:57 +02:00
|
|
|
netdev->stats.rx_bytes += payload_len;
|
2016-04-03 18:05:07 +02:00
|
|
|
#endif
|
2015-04-08 19:54:00 +02:00
|
|
|
/* read packet (without 4 bytes checksum) */
|
2016-04-06 22:53:47 +02:00
|
|
|
sram_op(dev, ENC_RRXDATA, 0xFFFF, buf, payload_len);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
/* decrement available packet count */
|
2016-04-06 22:53:47 +02:00
|
|
|
cmd(dev, ENC_SETPKTDEC);
|
2015-04-08 19:54:00 +02:00
|
|
|
|
|
|
|
dev->rx_next_ptr = hdr.rx_next_ptr;
|
|
|
|
|
2016-04-06 22:53:47 +02:00
|
|
|
reg_set(dev, ENC_ERXTAIL, dev->rx_next_ptr - 2);
|
2015-04-08 19:54:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
unlock(dev);
|
|
|
|
|
|
|
|
return payload_len;
|
|
|
|
}
|
|
|
|
|
2017-02-15 13:07:34 +01:00
|
|
|
static int _get(netdev_t *dev, netopt_t opt, void *value, size_t max_len)
|
2015-04-08 19:54:00 +02:00
|
|
|
{
|
|
|
|
int res = 0;
|
|
|
|
|
|
|
|
switch (opt) {
|
|
|
|
case NETOPT_ADDRESS:
|
|
|
|
if (max_len < ETHERNET_ADDR_LEN) {
|
|
|
|
res = -EINVAL;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
_get_mac_addr(dev, (uint8_t*)value);
|
|
|
|
res = ETHERNET_ADDR_LEN;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
default:
|
2017-02-15 13:07:34 +01:00
|
|
|
res = netdev_eth_get(dev, opt, value, max_len);
|
2015-04-08 19:54:00 +02:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
return res;
|
|
|
|
}
|