/* Transmit DMA interrupt service */ static inline void sca_tx_intr(port_t *port) { struct net_device *dev = port_to_dev(port); struct net_device_stats *stats = hdlc_stats(dev); u16 dmac = get_dmac_tx(port); card_t* card = port_to_card(port); u8 stat; spin_lock(&port->lock); stat = sca_in(DSR_TX(phy_node(port)), card); /* read DMA Status */ /* Reset DSR status bits */ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, DSR_TX(phy_node(port)), card); while (1) { pkt_desc __iomem *desc; u32 desc_off = desc_offset(port, port->txlast, 1); u32 cda = sca_ina(dmac + CDAL, card); if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) break; /* Transmitter is/will_be sending this frame */ desc = desc_address(port, port->txlast, 1); stats->tx_packets++; stats->tx_bytes += readw(&desc->len); writeb(0, &desc->stat); /* Free descriptor */ port->txlast = next_desc(port, port->txlast, 1); } netif_wake_queue(dev); spin_unlock(&port->lock); }
static inline void sca_rx(card_t *card, port_t *port, pkt_desc *desc, u16 rxin) { struct net_device *dev = port_to_dev(port); struct net_device_stats *stats = hdlc_stats(dev); struct sk_buff *skb; u16 len; u32 buff; #ifndef ALL_PAGES_ALWAYS_MAPPED u32 maxlen; u8 page; #endif len = readw(&desc->len); skb = dev_alloc_skb(len); if (!skb) { stats->rx_dropped++; return; } buff = buffer_offset(port, rxin, 0); #ifndef ALL_PAGES_ALWAYS_MAPPED page = buff / winsize(card); buff = buff % winsize(card); maxlen = winsize(card) - buff; openwin(card, page); if (len > maxlen) { memcpy_fromio(skb->data, winbase(card) + buff, maxlen); openwin(card, page + 1); memcpy_fromio(skb->data + maxlen, winbase(card), len - maxlen); } else #endif memcpy_fromio(skb->data, winbase(card) + buff, len); #if !defined(PAGE0_ALWAYS_MAPPED) && !defined(ALL_PAGES_ALWAYS_MAPPED) /* select pkt_desc table page back */ openwin(card, 0); #endif skb_put(skb, len); #ifdef DEBUG_PKT printk(KERN_DEBUG "%s RX(%i):", dev->name, skb->len); debug_frame(skb); #endif stats->rx_packets++; stats->rx_bytes += skb->len; skb->mac.raw = skb->data; skb->dev = dev; skb->dev->last_rx = jiffies; skb->protocol = hdlc_type_trans(skb, dev); netif_rx(skb); }
/* Receive DMA interrupt service */ static inline void sca_rx_intr(port_t *port) { u16 dmac = get_dmac_rx(port); card_t *card = port_to_card(port); u8 stat = sca_in(DSR_RX(phy_node(port)), card); /* read DMA Status */ struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); /* Reset DSR status bits */ sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE, DSR_RX(phy_node(port)), card); if (stat & DSR_BOF) stats->rx_over_errors++; /* Dropped one or more frames */ while (1) { u32 desc_off = desc_offset(port, port->rxin, 0); pkt_desc __iomem *desc; u32 cda = sca_ina(dmac + CDAL, card); if ((cda >= desc_off) && (cda < desc_off + sizeof(pkt_desc))) break; /* No frame received */ desc = desc_address(port, port->rxin, 0); stat = readb(&desc->stat); if (!(stat & ST_RX_EOM)) port->rxpart = 1; /* partial frame received */ else if ((stat & ST_ERROR_MASK) || port->rxpart) { stats->rx_errors++; if (stat & ST_RX_OVERRUN) stats->rx_fifo_errors++; else if ((stat & (ST_RX_SHORT | ST_RX_ABORT | ST_RX_RESBIT)) || port->rxpart) stats->rx_frame_errors++; else if (stat & ST_RX_CRC) stats->rx_crc_errors++; if (stat & ST_RX_EOM) port->rxpart = 0; /* received last fragment */ } else sca_rx(card, port, desc, port->rxin); /* Set new error descriptor address */ sca_outa(desc_off, dmac + EDAL, card); port->rxin = next_desc(port, port->rxin, 0); } /* make sure RX DMA is enabled */ sca_out(DSR_DE, DSR_RX(phy_node(port)), card); }
/* MSCI interrupt service */ static inline void sca_msci_intr(port_t *port) { u16 msci = get_msci(port); card_t* card = port_to_card(port); u8 stat = sca_in(msci + ST1, card); /* read MSCI ST1 status */ /* Reset MSCI TX underrun and CDCD status bit */ sca_out(stat & (ST1_UDRN | ST1_CDCD), msci + ST1, card); if (stat & ST1_UDRN) { struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); stats->tx_errors++; /* TX Underrun error detected */ stats->tx_fifo_errors++; } if (stat & ST1_CDCD) hdlc_set_carrier(!(sca_in(msci + ST3, card) & ST3_DCD), port_to_dev(port)); }
static void sca_msci_intr(port_t *port) { u8 stat = sca_in(MSCI0_OFFSET + ST1, port); /* read MSCI ST1 status */ /* Reset MSCI TX underrun and CDCD (ignored) status bit */ sca_out(stat & (ST1_UDRN | ST1_CDCD), MSCI0_OFFSET + ST1, port); if (stat & ST1_UDRN) { struct net_device_stats *stats = hdlc_stats(port_to_dev(port)); stats->tx_errors++; /* TX Underrun error detected */ stats->tx_fifo_errors++; } stat = sca_in(MSCI1_OFFSET + ST1, port); /* read MSCI1 ST1 status */ /* Reset MSCI CDCD status bit - uses ch#2 DCD input */ sca_out(stat & ST1_CDCD, MSCI1_OFFSET + ST1, port); if (stat & ST1_CDCD) set_carrier(port); }
static struct net_device_stats *hdlc_get_stats(struct net_device *dev) { return hdlc_stats(dev); }