in nicstar.c [1060:1230]
static irqreturn_t ns_irq_handler(int irq, void *dev_id)
{
u32 stat_r;
ns_dev *card;
struct atm_dev *dev;
unsigned long flags;
card = (ns_dev *) dev_id;
dev = card->atmdev;
card->intcnt++;
PRINTK("nicstar%d: NICStAR generated an interrupt\n", card->index);
spin_lock_irqsave(&card->int_lock, flags);
stat_r = readl(card->membase + STAT);
/* Transmit Status Indicator has been written to T. S. Queue */
if (stat_r & NS_STAT_TSIF) {
TXPRINTK("nicstar%d: TSI interrupt\n", card->index);
process_tsq(card);
writel(NS_STAT_TSIF, card->membase + STAT);
}
/* Incomplete CS-PDU has been transmitted */
if (stat_r & NS_STAT_TXICP) {
writel(NS_STAT_TXICP, card->membase + STAT);
TXPRINTK("nicstar%d: Incomplete CS-PDU transmitted.\n",
card->index);
}
/* Transmit Status Queue 7/8 full */
if (stat_r & NS_STAT_TSQF) {
writel(NS_STAT_TSQF, card->membase + STAT);
PRINTK("nicstar%d: TSQ full.\n", card->index);
process_tsq(card);
}
/* Timer overflow */
if (stat_r & NS_STAT_TMROF) {
writel(NS_STAT_TMROF, card->membase + STAT);
PRINTK("nicstar%d: Timer overflow.\n", card->index);
}
/* PHY device interrupt signal active */
if (stat_r & NS_STAT_PHYI) {
writel(NS_STAT_PHYI, card->membase + STAT);
PRINTK("nicstar%d: PHY interrupt.\n", card->index);
if (dev->phy && dev->phy->interrupt) {
dev->phy->interrupt(dev);
}
}
/* Small Buffer Queue is full */
if (stat_r & NS_STAT_SFBQF) {
writel(NS_STAT_SFBQF, card->membase + STAT);
printk("nicstar%d: Small free buffer queue is full.\n",
card->index);
}
/* Large Buffer Queue is full */
if (stat_r & NS_STAT_LFBQF) {
writel(NS_STAT_LFBQF, card->membase + STAT);
printk("nicstar%d: Large free buffer queue is full.\n",
card->index);
}
/* Receive Status Queue is full */
if (stat_r & NS_STAT_RSQF) {
writel(NS_STAT_RSQF, card->membase + STAT);
printk("nicstar%d: RSQ full.\n", card->index);
process_rsq(card);
}
/* Complete CS-PDU received */
if (stat_r & NS_STAT_EOPDU) {
RXPRINTK("nicstar%d: End of CS-PDU received.\n", card->index);
process_rsq(card);
writel(NS_STAT_EOPDU, card->membase + STAT);
}
/* Raw cell received */
if (stat_r & NS_STAT_RAWCF) {
writel(NS_STAT_RAWCF, card->membase + STAT);
#ifndef RCQ_SUPPORT
printk("nicstar%d: Raw cell received and no support yet...\n",
card->index);
#endif /* RCQ_SUPPORT */
/* NOTE: the following procedure may keep a raw cell pending until the
next interrupt. As this preliminary support is only meant to
avoid buffer leakage, this is not an issue. */
while (readl(card->membase + RAWCT) != card->rawch) {
if (ns_rcqe_islast(card->rawcell)) {
struct sk_buff *oldbuf;
oldbuf = card->rcbuf;
card->rcbuf = idr_find(&card->idr,
ns_rcqe_nextbufhandle(card->rawcell));
card->rawch = NS_PRV_DMA(card->rcbuf);
card->rawcell = (struct ns_rcqe *)
card->rcbuf->data;
recycle_rx_buf(card, oldbuf);
} else {
card->rawch += NS_RCQE_SIZE;
card->rawcell++;
}
}
}
/* Small buffer queue is empty */
if (stat_r & NS_STAT_SFBQE) {
int i;
struct sk_buff *sb;
writel(NS_STAT_SFBQE, card->membase + STAT);
printk("nicstar%d: Small free buffer queue empty.\n",
card->index);
for (i = 0; i < card->sbnr.min; i++) {
sb = dev_alloc_skb(NS_SMSKBSIZE);
if (sb == NULL) {
writel(readl(card->membase + CFG) &
~NS_CFG_EFBIE, card->membase + CFG);
card->efbie = 0;
break;
}
NS_PRV_BUFTYPE(sb) = BUF_SM;
skb_queue_tail(&card->sbpool.queue, sb);
skb_reserve(sb, NS_AAL0_HEADER);
push_rxbufs(card, sb);
}
card->sbfqc = i;
process_rsq(card);
}
/* Large buffer queue empty */
if (stat_r & NS_STAT_LFBQE) {
int i;
struct sk_buff *lb;
writel(NS_STAT_LFBQE, card->membase + STAT);
printk("nicstar%d: Large free buffer queue empty.\n",
card->index);
for (i = 0; i < card->lbnr.min; i++) {
lb = dev_alloc_skb(NS_LGSKBSIZE);
if (lb == NULL) {
writel(readl(card->membase + CFG) &
~NS_CFG_EFBIE, card->membase + CFG);
card->efbie = 0;
break;
}
NS_PRV_BUFTYPE(lb) = BUF_LG;
skb_queue_tail(&card->lbpool.queue, lb);
skb_reserve(lb, NS_SMBUFSIZE);
push_rxbufs(card, lb);
}
card->lbfqc = i;
process_rsq(card);
}
/* Receive Status Queue is 7/8 full */
if (stat_r & NS_STAT_RSQAF) {
writel(NS_STAT_RSQAF, card->membase + STAT);
RXPRINTK("nicstar%d: RSQ almost full.\n", card->index);
process_rsq(card);
}
spin_unlock_irqrestore(&card->int_lock, flags);
PRINTK("nicstar%d: end of interrupt service\n", card->index);
return IRQ_HANDLED;
}