mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 01:10:15 +08:00
if_lpe.c: Move transmit initialization
Move the transmit initialization out of the transmit task to be able to remove the transmit task in the next patch.
This commit is contained in:
parent
ff4c60af7a
commit
1056349b4e
@ -260,7 +260,9 @@ static volatile lpc_eth_controller *const lpc_eth =
|
|||||||
|
|
||||||
/* Events */
|
/* Events */
|
||||||
|
|
||||||
#define LPC_ETH_EVENT_INITIALIZE RTEMS_EVENT_1
|
#define LPC_ETH_EVENT_INIT_RX RTEMS_EVENT_0
|
||||||
|
|
||||||
|
#define LPC_ETH_EVENT_INIT_TX RTEMS_EVENT_1
|
||||||
|
|
||||||
#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2
|
#define LPC_ETH_EVENT_TXSTART RTEMS_EVENT_2
|
||||||
|
|
||||||
@ -324,6 +326,8 @@ typedef struct {
|
|||||||
volatile lpc_eth_transfer_descriptor *tx_desc_table;
|
volatile lpc_eth_transfer_descriptor *tx_desc_table;
|
||||||
volatile uint32_t *tx_status_table;
|
volatile uint32_t *tx_status_table;
|
||||||
void *tx_buf_table;
|
void *tx_buf_table;
|
||||||
|
uint32_t tx_produce_index;
|
||||||
|
uint32_t tx_consume_index;
|
||||||
unsigned received_frames;
|
unsigned received_frames;
|
||||||
unsigned receive_interrupts;
|
unsigned receive_interrupts;
|
||||||
unsigned transmitted_frames;
|
unsigned transmitted_frames;
|
||||||
@ -418,9 +422,16 @@ static void lpc_eth_interrupt_handler(void *arg)
|
|||||||
uint32_t is = lpc_eth->intstatus & im;
|
uint32_t is = lpc_eth->intstatus & im;
|
||||||
|
|
||||||
/* Check receive interrupts */
|
/* Check receive interrupts */
|
||||||
if ((is & ETH_INT_RX_OVERRUN) != 0) {
|
if ((is & (ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN)) != 0) {
|
||||||
re = LPC_ETH_EVENT_INITIALIZE;
|
if ((is & ETH_INT_RX_OVERRUN) != 0) {
|
||||||
++e->receive_fatal_errors;
|
re = LPC_ETH_EVENT_INIT_RX;
|
||||||
|
++e->receive_fatal_errors;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((is & ETH_INT_TX_UNDERRUN) != 0) {
|
||||||
|
re = LPC_ETH_EVENT_INIT_TX;
|
||||||
|
++e->transmit_fatal_errors;
|
||||||
|
}
|
||||||
} else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) {
|
} else if ((is & LPC_ETH_INTERRUPT_RECEIVE) != 0) {
|
||||||
re = LPC_ETH_EVENT_INTERRUPT;
|
re = LPC_ETH_EVENT_INTERRUPT;
|
||||||
ie |= LPC_ETH_INTERRUPT_RECEIVE;
|
ie |= LPC_ETH_INTERRUPT_RECEIVE;
|
||||||
@ -433,10 +444,7 @@ static void lpc_eth_interrupt_handler(void *arg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check transmit interrupts */
|
/* Check transmit interrupts */
|
||||||
if ((is & ETH_INT_TX_UNDERRUN) != 0) {
|
if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
|
||||||
te = LPC_ETH_EVENT_INITIALIZE;
|
|
||||||
++e->transmit_fatal_errors;
|
|
||||||
} else if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
|
|
||||||
te = LPC_ETH_EVENT_INTERRUPT;
|
te = LPC_ETH_EVENT_INTERRUPT;
|
||||||
ie |= LPC_ETH_INTERRUPT_TRANSMIT;
|
ie |= LPC_ETH_INTERRUPT_TRANSMIT;
|
||||||
}
|
}
|
||||||
@ -492,6 +500,66 @@ static void lpc_eth_disable_transmit_interrupts(void)
|
|||||||
rtems_interrupt_enable(level);
|
rtems_interrupt_enable(level);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void lpc_eth_initialize_transmit(lpc_eth_driver_entry *e)
|
||||||
|
{
|
||||||
|
volatile uint32_t *const status = e->tx_status_table;
|
||||||
|
uint32_t const index_max = e->tx_unit_count - 1;
|
||||||
|
volatile lpc_eth_transfer_descriptor *const desc = e->tx_desc_table;
|
||||||
|
#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
||||||
|
struct mbuf **const mbufs = e->tx_buf_table;
|
||||||
|
#else
|
||||||
|
char *const buf = e->tx_buf_table;
|
||||||
|
#endif
|
||||||
|
uint32_t produce_index;
|
||||||
|
|
||||||
|
/* Disable transmit interrupts */
|
||||||
|
lpc_eth_disable_transmit_interrupts();
|
||||||
|
|
||||||
|
/* Disable transmitter */
|
||||||
|
lpc_eth->command &= ~ETH_CMD_TX_ENABLE;
|
||||||
|
|
||||||
|
/* Wait for inactive status */
|
||||||
|
while ((lpc_eth->status & ETH_STAT_TX_ACTIVE) != 0) {
|
||||||
|
/* Wait */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
lpc_eth->command |= ETH_CMD_TX_RESET;
|
||||||
|
|
||||||
|
/* Clear transmit interrupts */
|
||||||
|
lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
|
||||||
|
|
||||||
|
/* Transmit descriptors */
|
||||||
|
lpc_eth->txdescriptornum = index_max;
|
||||||
|
lpc_eth->txdescriptor = (uint32_t) desc;
|
||||||
|
lpc_eth->txstatus = (uint32_t) status;
|
||||||
|
|
||||||
|
#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
||||||
|
/* Discard outstanding fragments (= data loss) */
|
||||||
|
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
||||||
|
struct mbuf *victim = mbufs [produce_index];
|
||||||
|
|
||||||
|
if (victim != NULL) {
|
||||||
|
m_free(victim);
|
||||||
|
mbufs [produce_index] = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
/* Initialize descriptor table */
|
||||||
|
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
||||||
|
desc [produce_index].start =
|
||||||
|
(uint32_t) (buf + produce_index * LPC_ETH_CONFIG_TX_BUF_SIZE);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Initialize indices */
|
||||||
|
e->tx_produce_index = lpc_eth->txproduceindex;
|
||||||
|
e->tx_consume_index = lpc_eth->txconsumeindex;
|
||||||
|
|
||||||
|
/* Enable transmitter */
|
||||||
|
lpc_eth->command |= ETH_CMD_TX_ENABLE;
|
||||||
|
}
|
||||||
|
|
||||||
#define LPC_ETH_RX_DATA_OFFSET 2
|
#define LPC_ETH_RX_DATA_OFFSET 2
|
||||||
|
|
||||||
static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait)
|
static struct mbuf *lpc_eth_new_mbuf(struct ifnet *ifp, bool wait)
|
||||||
@ -576,7 +644,8 @@ static void lpc_eth_receive_task(rtems_task_argument arg)
|
|||||||
while (true) {
|
while (true) {
|
||||||
/* Wait for events */
|
/* Wait for events */
|
||||||
sc = rtems_event_receive(
|
sc = rtems_event_receive(
|
||||||
LPC_ETH_EVENT_INITIALIZE
|
LPC_ETH_EVENT_INIT_RX
|
||||||
|
| LPC_ETH_EVENT_INIT_TX
|
||||||
| LPC_ETH_EVENT_STOP
|
| LPC_ETH_EVENT_STOP
|
||||||
| LPC_ETH_EVENT_INTERRUPT,
|
| LPC_ETH_EVENT_INTERRUPT,
|
||||||
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
||||||
@ -595,60 +664,68 @@ static void lpc_eth_receive_task(rtems_task_argument arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize receiver? */
|
/* Initialize receiver or transmitter? */
|
||||||
if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
|
if ((events & (LPC_ETH_EVENT_INIT_RX | LPC_ETH_EVENT_INIT_TX)) != 0) {
|
||||||
/* Disable receive interrupts */
|
if ((events & LPC_ETH_EVENT_INIT_RX) != 0) {
|
||||||
lpc_eth_disable_receive_interrupts();
|
/* Disable receive interrupts */
|
||||||
|
lpc_eth_disable_receive_interrupts();
|
||||||
|
|
||||||
/* Disable receiver */
|
/* Disable receiver */
|
||||||
lpc_eth->command &= ~ETH_CMD_RX_ENABLE;
|
lpc_eth->command &= ~ETH_CMD_RX_ENABLE;
|
||||||
|
|
||||||
/* Wait for inactive status */
|
/* Wait for inactive status */
|
||||||
while ((lpc_eth->status & ETH_STAT_RX_ACTIVE) != 0) {
|
while ((lpc_eth->status & ETH_STAT_RX_ACTIVE) != 0) {
|
||||||
/* Wait */
|
/* Wait */
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset */
|
|
||||||
lpc_eth->command |= ETH_CMD_RX_RESET;
|
|
||||||
|
|
||||||
/* Clear receive interrupts */
|
|
||||||
lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
|
|
||||||
|
|
||||||
/* Move existing mbufs to the front */
|
|
||||||
consume_index = 0;
|
|
||||||
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
|
||||||
if (mbufs [produce_index] != NULL) {
|
|
||||||
mbufs [consume_index] = mbufs [produce_index];
|
|
||||||
++consume_index;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Reset */
|
||||||
|
lpc_eth->command |= ETH_CMD_RX_RESET;
|
||||||
|
|
||||||
|
/* Clear receive interrupts */
|
||||||
|
lpc_eth->intclear = LPC_ETH_INTERRUPT_RECEIVE;
|
||||||
|
|
||||||
|
/* Move existing mbufs to the front */
|
||||||
|
consume_index = 0;
|
||||||
|
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
||||||
|
if (mbufs [produce_index] != NULL) {
|
||||||
|
mbufs [consume_index] = mbufs [produce_index];
|
||||||
|
++consume_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Fill receive queue */
|
||||||
|
for (
|
||||||
|
produce_index = consume_index;
|
||||||
|
produce_index <= index_max;
|
||||||
|
++produce_index
|
||||||
|
) {
|
||||||
|
lpc_eth_add_new_mbuf(ifp, desc, mbufs, produce_index, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Receive descriptor table */
|
||||||
|
lpc_eth->rxdescriptornum = index_max;
|
||||||
|
lpc_eth->rxdescriptor = (uint32_t) desc;
|
||||||
|
lpc_eth->rxstatus = (uint32_t) status;
|
||||||
|
|
||||||
|
/* Initialize indices */
|
||||||
|
produce_index = lpc_eth->rxproduceindex;
|
||||||
|
consume_index = lpc_eth->rxconsumeindex;
|
||||||
|
|
||||||
|
/* Enable receiver */
|
||||||
|
lpc_eth->command |= ETH_CMD_RX_ENABLE;
|
||||||
|
|
||||||
|
/* Enable receive interrupts */
|
||||||
|
lpc_eth_enable_receive_interrupts();
|
||||||
|
|
||||||
|
lpc_eth_control_request_complete(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill receive queue */
|
if ((events & LPC_ETH_EVENT_INIT_TX) != 0) {
|
||||||
for (
|
LPE_LOCK(e);
|
||||||
produce_index = consume_index;
|
lpc_eth_initialize_transmit(e);
|
||||||
produce_index <= index_max;
|
LPE_UNLOCK(e);
|
||||||
++produce_index
|
|
||||||
) {
|
|
||||||
lpc_eth_add_new_mbuf(ifp, desc, mbufs, produce_index, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Receive descriptor table */
|
|
||||||
lpc_eth->rxdescriptornum = index_max;
|
|
||||||
lpc_eth->rxdescriptor = (uint32_t) desc;
|
|
||||||
lpc_eth->rxstatus = (uint32_t) status;
|
|
||||||
|
|
||||||
/* Initialize indices */
|
|
||||||
produce_index = lpc_eth->rxproduceindex;
|
|
||||||
consume_index = lpc_eth->rxconsumeindex;
|
|
||||||
|
|
||||||
/* Enable receiver */
|
|
||||||
lpc_eth->command |= ETH_CMD_RX_ENABLE;
|
|
||||||
|
|
||||||
/* Enable receive interrupts */
|
|
||||||
lpc_eth_enable_receive_interrupts();
|
|
||||||
|
|
||||||
lpc_eth_control_request_complete(e);
|
|
||||||
|
|
||||||
/* Wait for events */
|
/* Wait for events */
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -797,30 +874,22 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
|||||||
#endif
|
#endif
|
||||||
struct mbuf *m = NULL;
|
struct mbuf *m = NULL;
|
||||||
uint32_t const index_max = e->tx_unit_count - 1;
|
uint32_t const index_max = e->tx_unit_count - 1;
|
||||||
uint32_t produce_index = 0;
|
|
||||||
uint32_t consume_index = 0;
|
|
||||||
uint32_t ctrl = 0;
|
uint32_t ctrl = 0;
|
||||||
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
|
||||||
uint32_t frame_length = 0;
|
|
||||||
char *frame_buffer = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LPC_ETH_PRINTF("%s\n", __func__);
|
LPC_ETH_PRINTF("%s\n", __func__);
|
||||||
|
|
||||||
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
|
||||||
/* Initialize descriptor table */
|
|
||||||
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
|
||||||
desc [produce_index].start =
|
|
||||||
(uint32_t) (buf + produce_index * LPC_ETH_CONFIG_TX_BUF_SIZE);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Main event loop */
|
/* Main event loop */
|
||||||
while (true) {
|
while (true) {
|
||||||
|
uint32_t produce_index;
|
||||||
|
uint32_t consume_index;
|
||||||
|
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
||||||
|
uint32_t frame_length;
|
||||||
|
char *frame_buffer;
|
||||||
|
#endif
|
||||||
|
|
||||||
/* Wait for events */
|
/* Wait for events */
|
||||||
sc = rtems_event_receive(
|
sc = rtems_event_receive(
|
||||||
LPC_ETH_EVENT_INITIALIZE
|
LPC_ETH_EVENT_STOP
|
||||||
| LPC_ETH_EVENT_STOP
|
|
||||||
| LPC_ETH_EVENT_TXSTART
|
| LPC_ETH_EVENT_TXSTART
|
||||||
| LPC_ETH_EVENT_INTERRUPT,
|
| LPC_ETH_EVENT_INTERRUPT,
|
||||||
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
||||||
@ -839,57 +908,17 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Initialize transmitter? */
|
LPE_LOCK(e);
|
||||||
if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
|
|
||||||
/* Disable transmit interrupts */
|
|
||||||
lpc_eth_disable_transmit_interrupts();
|
|
||||||
|
|
||||||
/* Disable transmitter */
|
/* Get indices */
|
||||||
lpc_eth->command &= ~ETH_CMD_TX_ENABLE;
|
produce_index = e->tx_produce_index;
|
||||||
|
consume_index = e->tx_consume_index;
|
||||||
|
|
||||||
/* Wait for inactive status */
|
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
||||||
while ((lpc_eth->status & ETH_STAT_TX_ACTIVE) != 0) {
|
/* Fresh frame length and buffer start */
|
||||||
/* Wait */
|
frame_length = 0;
|
||||||
}
|
frame_buffer = (char *) desc [produce_index].start;
|
||||||
|
#endif
|
||||||
/* Reset */
|
|
||||||
lpc_eth->command |= ETH_CMD_TX_RESET;
|
|
||||||
|
|
||||||
/* Clear transmit interrupts */
|
|
||||||
lpc_eth->intclear = LPC_ETH_INTERRUPT_TRANSMIT;
|
|
||||||
|
|
||||||
/* Transmit descriptors */
|
|
||||||
lpc_eth->txdescriptornum = index_max;
|
|
||||||
lpc_eth->txdescriptor = (uint32_t) desc;
|
|
||||||
lpc_eth->txstatus = (uint32_t) status;
|
|
||||||
|
|
||||||
#ifdef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
|
||||||
/* Discard outstanding fragments (= data loss) */
|
|
||||||
for (produce_index = 0; produce_index <= index_max; ++produce_index) {
|
|
||||||
struct mbuf *victim = mbufs [produce_index];
|
|
||||||
|
|
||||||
if (victim != NULL) {
|
|
||||||
m_free(victim);
|
|
||||||
mbufs [produce_index] = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Initialize indices */
|
|
||||||
produce_index = lpc_eth->txproduceindex;
|
|
||||||
consume_index = lpc_eth->txconsumeindex;
|
|
||||||
|
|
||||||
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
|
||||||
/* Fresh frame length and buffer start */
|
|
||||||
frame_length = 0;
|
|
||||||
frame_buffer = (char *) desc [produce_index].start;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* Enable transmitter */
|
|
||||||
lpc_eth->command |= ETH_CMD_TX_ENABLE;
|
|
||||||
|
|
||||||
lpc_eth_control_request_complete(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Free consumed fragments */
|
/* Free consumed fragments */
|
||||||
while (true) {
|
while (true) {
|
||||||
@ -1074,6 +1103,10 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Save indices */
|
||||||
|
e->tx_produce_index = produce_index;
|
||||||
|
e->tx_consume_index = consume_index;
|
||||||
|
|
||||||
/* No more fragments? */
|
/* No more fragments? */
|
||||||
if (m == NULL) {
|
if (m == NULL) {
|
||||||
/* Interface is now inactive */
|
/* Interface is now inactive */
|
||||||
@ -1084,6 +1117,8 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
|||||||
/* Enable transmit interrupts */
|
/* Enable transmit interrupts */
|
||||||
lpc_eth_enable_transmit_interrupts();
|
lpc_eth_enable_transmit_interrupts();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
LPE_UNLOCK(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1418,8 +1453,8 @@ static int lpc_eth_up_or_down(lpc_eth_driver_entry *e, bool up)
|
|||||||
lpc_eth->mac1 = 0x03;
|
lpc_eth->mac1 = 0x03;
|
||||||
|
|
||||||
/* Initialize tasks */
|
/* Initialize tasks */
|
||||||
lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INITIALIZE);
|
lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INIT_RX);
|
||||||
lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_INITIALIZE);
|
lpc_eth_initialize_transmit(e);
|
||||||
|
|
||||||
/* Install interrupt handler */
|
/* Install interrupt handler */
|
||||||
sc = rtems_interrupt_handler_install(
|
sc = rtems_interrupt_handler_install(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user