mirror of https://github.com/zrafa/xinu-avr.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
123 lines
2.8 KiB
123 lines
2.8 KiB
/* ethhandler.c - ethhandler */ |
|
|
|
#include <xinu.h> |
|
|
|
/*------------------------------------------------------------------------ |
|
* ethhandler - TI AM335X Ethernet Interrupt Handler |
|
*------------------------------------------------------------------------ |
|
*/ |
|
interrupt ethhandler ( |
|
uint32 xnum /* IRQ number */ |
|
) |
|
{ |
|
struct eth_a_csreg *csrptr; /* Ethernet CSR pointer */ |
|
struct eth_a_tx_desc *tdescptr; /* Tx desc pointer */ |
|
struct eth_a_rx_desc *rdescptr; /* Rx desc pointer */ |
|
struct ethcblk *ethptr = ðertab[0]; /* Ethernet ctl blk ptr */ |
|
|
|
csrptr = (struct eth_a_csreg *)ethptr->csr; |
|
|
|
if(xnum == ETH_AM335X_TXINT) { /* Transmit interrupt */ |
|
|
|
/* Get pointer to first desc in queue */ |
|
|
|
tdescptr = (struct eth_a_tx_desc *)ethptr->txRing + |
|
ethptr->txHead; |
|
|
|
/* Defer scheduling until all descs are processed */ |
|
|
|
resched_cntl(DEFER_START); |
|
|
|
while(semcount(ethptr->osem) < (int32)ethptr->txRingSize) { |
|
|
|
/* If desc owned by DMA, check if we need to */ |
|
/* Restart the transmission */ |
|
|
|
if(tdescptr->stat & ETH_AM335X_TDS_OWN) { |
|
if(csrptr->stateram->tx_hdp[0] == 0) { |
|
csrptr->stateram->tx_hdp[0] = |
|
(uint32)tdescptr; |
|
} |
|
break; |
|
} |
|
|
|
/* Acknowledge the interrupt */ |
|
|
|
csrptr->stateram->tx_cp[0] = (uint32)tdescptr; |
|
|
|
/* Increment the head index of the queue */ |
|
/* And go to the next descriptor in queue */ |
|
|
|
ethptr->txHead++; |
|
tdescptr++; |
|
if(ethptr->txHead >= ethptr->txRingSize) { |
|
ethptr->txHead = 0; |
|
tdescptr = (struct eth_a_tx_desc *) |
|
ethptr->txRing; |
|
} |
|
|
|
/* Signal the output semaphore */ |
|
|
|
signal(ethptr->osem); |
|
} |
|
|
|
/* Acknowledge the transmit interrupt */ |
|
|
|
csrptr->cpdma->eoi_vector = 0x2; |
|
|
|
/* Resume rescheduling */ |
|
|
|
resched_cntl(DEFER_STOP); |
|
} |
|
else if(xnum == ETH_AM335X_RXINT) { /* Receive interrupt */ |
|
|
|
/* Get the pointer to last desc in the queue */ |
|
|
|
rdescptr = (struct eth_a_rx_desc *)ethptr->rxRing + |
|
ethptr->rxTail; |
|
|
|
/* Defer scheduling until all descriptors are processed */ |
|
|
|
resched_cntl(DEFER_START); |
|
|
|
while(semcount(ethptr->isem) < (int32)ethptr->rxRingSize) { |
|
|
|
/* Check if we need to restart the DMA */ |
|
|
|
if(rdescptr->stat & ETH_AM335X_RDS_OWN) { |
|
if(csrptr->stateram->rx_hdp[0] == 0) { |
|
csrptr->stateram->rx_hdp[0] = |
|
(uint32)rdescptr; |
|
} |
|
break; |
|
} |
|
|
|
/* Acknowledge the interrupt */ |
|
|
|
csrptr->stateram->rx_cp[0] = (uint32)rdescptr; |
|
|
|
/* Increment the tail index of the queue */ |
|
/* And go to the next descriptor in the queue */ |
|
|
|
ethptr->rxTail++; |
|
rdescptr++; |
|
if(ethptr->rxTail >= ethptr->rxRingSize) { |
|
ethptr->rxTail = 0; |
|
rdescptr = (struct eth_a_rx_desc *) |
|
ethptr->rxRing; |
|
} |
|
|
|
/* Signal the input semaphore */ |
|
|
|
signal(ethptr->isem); |
|
} |
|
|
|
/* Acknowledge the receive interrupt */ |
|
|
|
csrptr->cpdma->eoi_vector = 0x1; |
|
|
|
/* Resume rescheduling */ |
|
|
|
resched_cntl(DEFER_STOP); |
|
} |
|
}
|
|
|