mirror of
https://git.rtems.org/rtems-libbsd/
synced 2025-05-14 01:39:57 +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 */
|
||||
|
||||
#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
|
||||
|
||||
@ -324,6 +326,8 @@ typedef struct {
|
||||
volatile lpc_eth_transfer_descriptor *tx_desc_table;
|
||||
volatile uint32_t *tx_status_table;
|
||||
void *tx_buf_table;
|
||||
uint32_t tx_produce_index;
|
||||
uint32_t tx_consume_index;
|
||||
unsigned received_frames;
|
||||
unsigned receive_interrupts;
|
||||
unsigned transmitted_frames;
|
||||
@ -418,9 +422,16 @@ static void lpc_eth_interrupt_handler(void *arg)
|
||||
uint32_t is = lpc_eth->intstatus & im;
|
||||
|
||||
/* Check receive interrupts */
|
||||
if ((is & (ETH_INT_RX_OVERRUN | ETH_INT_TX_UNDERRUN)) != 0) {
|
||||
if ((is & ETH_INT_RX_OVERRUN) != 0) {
|
||||
re = LPC_ETH_EVENT_INITIALIZE;
|
||||
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) {
|
||||
re = LPC_ETH_EVENT_INTERRUPT;
|
||||
ie |= LPC_ETH_INTERRUPT_RECEIVE;
|
||||
@ -433,10 +444,7 @@ static void lpc_eth_interrupt_handler(void *arg)
|
||||
}
|
||||
|
||||
/* Check transmit interrupts */
|
||||
if ((is & ETH_INT_TX_UNDERRUN) != 0) {
|
||||
te = LPC_ETH_EVENT_INITIALIZE;
|
||||
++e->transmit_fatal_errors;
|
||||
} else if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
|
||||
if ((is & LPC_ETH_INTERRUPT_TRANSMIT) != 0) {
|
||||
te = LPC_ETH_EVENT_INTERRUPT;
|
||||
ie |= LPC_ETH_INTERRUPT_TRANSMIT;
|
||||
}
|
||||
@ -492,6 +500,66 @@ static void lpc_eth_disable_transmit_interrupts(void)
|
||||
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
|
||||
|
||||
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) {
|
||||
/* Wait for events */
|
||||
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_INTERRUPT,
|
||||
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
||||
@ -595,8 +664,9 @@ static void lpc_eth_receive_task(rtems_task_argument arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize receiver? */
|
||||
if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
|
||||
/* Initialize receiver or transmitter? */
|
||||
if ((events & (LPC_ETH_EVENT_INIT_RX | LPC_ETH_EVENT_INIT_TX)) != 0) {
|
||||
if ((events & LPC_ETH_EVENT_INIT_RX) != 0) {
|
||||
/* Disable receive interrupts */
|
||||
lpc_eth_disable_receive_interrupts();
|
||||
|
||||
@ -648,6 +718,13 @@ static void lpc_eth_receive_task(rtems_task_argument arg)
|
||||
lpc_eth_enable_receive_interrupts();
|
||||
|
||||
lpc_eth_control_request_complete(e);
|
||||
}
|
||||
|
||||
if ((events & LPC_ETH_EVENT_INIT_TX) != 0) {
|
||||
LPE_LOCK(e);
|
||||
lpc_eth_initialize_transmit(e);
|
||||
LPE_UNLOCK(e);
|
||||
}
|
||||
|
||||
/* Wait for events */
|
||||
continue;
|
||||
@ -797,30 +874,22 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
||||
#endif
|
||||
struct mbuf *m = NULL;
|
||||
uint32_t const index_max = e->tx_unit_count - 1;
|
||||
uint32_t produce_index = 0;
|
||||
uint32_t consume_index = 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__);
|
||||
|
||||
#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 */
|
||||
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 */
|
||||
sc = rtems_event_receive(
|
||||
LPC_ETH_EVENT_INITIALIZE
|
||||
| LPC_ETH_EVENT_STOP
|
||||
LPC_ETH_EVENT_STOP
|
||||
| LPC_ETH_EVENT_TXSTART
|
||||
| LPC_ETH_EVENT_INTERRUPT,
|
||||
RTEMS_EVENT_ANY | RTEMS_WAIT,
|
||||
@ -839,45 +908,11 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Initialize transmitter? */
|
||||
if ((events & LPC_ETH_EVENT_INITIALIZE) != 0) {
|
||||
/* Disable transmit interrupts */
|
||||
lpc_eth_disable_transmit_interrupts();
|
||||
LPE_LOCK(e);
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Initialize indices */
|
||||
produce_index = lpc_eth->txproduceindex;
|
||||
consume_index = lpc_eth->txconsumeindex;
|
||||
/* Get indices */
|
||||
produce_index = e->tx_produce_index;
|
||||
consume_index = e->tx_consume_index;
|
||||
|
||||
#ifndef LPC_ETH_CONFIG_USE_TRANSMIT_DMA
|
||||
/* Fresh frame length and buffer start */
|
||||
@ -885,12 +920,6 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
||||
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 */
|
||||
while (true) {
|
||||
/* Save last known consume index */
|
||||
@ -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? */
|
||||
if (m == NULL) {
|
||||
/* Interface is now inactive */
|
||||
@ -1084,6 +1117,8 @@ static void lpc_eth_transmit_task(rtems_task_argument arg)
|
||||
/* 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;
|
||||
|
||||
/* Initialize tasks */
|
||||
lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INITIALIZE);
|
||||
lpc_eth_control_request(e, e->transmit_task, LPC_ETH_EVENT_INITIALIZE);
|
||||
lpc_eth_control_request(e, e->receive_task, LPC_ETH_EVENT_INIT_RX);
|
||||
lpc_eth_initialize_transmit(e);
|
||||
|
||||
/* Install interrupt handler */
|
||||
sc = rtems_interrupt_handler_install(
|
||||
|
Loading…
x
Reference in New Issue
Block a user