| Example |
static void interrupt_ethernet (void) __irq {
/* EMAC Ethernet Controller Interrupt function. */
OS_FRAME *frame;
U32 idx,int_stat,RxLen,info;
U32 *sp,*dp;
while ((int_stat = (MAC_INTSTATUS & MAC_INTENABLE)) != 0) {
MAC_INTCLEAR = int_stat;
if (int_stat & INT_RX_DONE) {
/* Packet received, check if packet is valid. */
idx = MAC_RXCONSUMEINDEX;
while (idx != MAC_RXPRODUCEINDEX) {
info = Rx_Stat[idx].Info;
if (!(info & RINFO_LAST_FLAG)) {
goto rel;
}
RxLen = (info & RINFO_SIZE) - 3;
if (RxLen > ETH_MTU || (info & RINFO_ERR_MASK)) {
/* Invalid frame, ignore it and free buffer. */
goto rel;
}
/* Flag 0x80000000 to skip sys_error() call when out of memory. */
frame = alloc_mem (RxLen | 0x80000000);
/* if 'alloc_mem()' has failed, ignore this packet. */
if (frame != NULL) {
dp = (U32 *)&frame->data[0];
sp = (U32 *)Rx_Desc[idx].Packet;
for (RxLen = (RxLen + 3) >> 2; RxLen; RxLen--) {
*dp++ = *sp++;
}
put_in_queue (frame);
}
rel: if (++idx == NUM_RX_FRAG) idx = 0;
/* Release frame from EMAC buffer. */
MAC_RXCONSUMEINDEX = idx;
}
}
if (int_stat & INT_TX_DONE) {
/* Frame transmit completed. */
}
}
/* Acknowledge the interrupt. */
VICVectAddr = 0;
}
|