static irqreturn_t sport_rx_isr(int irq, void *dev_id)
{
unsigned int i, j;
struct nortel *c = (struct nortel *)dev_id;
/*
* iRxBuffer points to what was just received.
* iTxBuffer points to what was just transmitted.
* Copy the data received into the channel structure,
* update these pointers, and copy the data to transmit.
*/
copy_nortel_to_internal(c, iRxBuffer);
iRxBuffer += TDM_CHANNELS;
j = bfin_read_DMA3_START_ADDR();
if((unsigned int)iRxBuffer >= j + DMA_BUFLEN)
iRxBuffer = (u8 *)j;
iTxBuffer += TDM_CHANNELS;
j = bfin_read_DMA4_START_ADDR();
if((unsigned int)iTxBuffer >= j + DMA_BUFLEN)
iTxBuffer = (u8 *)j;
copy_internal_to_nortel(c, iTxBuffer);
/*
* The next transfer is now set up and waiting.
* Acknowledge the transfer and let the next one go.
*/
i = bfin_read_DMA3_IRQ_STATUS();
j = DMA_DONE;
if(i & DMA_ERR) {
if(debug) printk(KERN_DEBUG "sport_rx_isr: DMA5 reported an error\n");
j |= DMA_ERR;
}
bfin_write_DMA3_IRQ_STATUS(j); /* ACK DMA (and error if present) */
__builtin_bfin_ssync();
/*
* We must begin to process the received frame. Right now,
* we do this within the IRQ handler since it's fast,
* but this is the routine that you may want to kick off to a
* bottom-half handler (tasklet or workqueue).
*
* Once the frame is processed, we must do the ethernet side.
* If we are providing sync to the PC, we kick off a TDMoE packet
* every 8 (ZT_CHUNKSIZE) frames.
* If we are not providing sync to the PC, we don't worry about
* ethernet at all, as it will be taking care of by the
* ethernet receive code.
*/
process_frame(c);
++c->intcount;
if(tdmoe_master && (c->intcount % 8 == 0)) {
copy_internal_to_tdmoe(c); /* also queues packet for tx */
tasklet_hi_schedule(ð_flush_tasklet); /* actually put the frames on the wire */
}
return IRQ_HANDLED;
}