drivers/net/wan/hd64572.c

Source file repositories/reference/linux-study-clean/drivers/net/wan/hd64572.c

File Facts

System
Linux kernel
Corpus path
drivers/net/wan/hd64572.c
Extension
.c
Size
17848 bytes
Lines
637
Domain
Driver Families
Bucket
drivers/net
Inferred role
Driver Families: implementation source
Status
source implementation candidate

Why This File Exists

Repeatable hardware-adapter layer. Deep compatibility for every driver is out of scope; this atlas records patterns, probe lifecycles, bus glue, IRQ/DMA usage, and links back to core abstractions.

Dependency Surface

Detected Declarations

Annotated Snippet

else if ((stat & ST_ERROR_MASK) || port->rxpart) {
			dev->stats.rx_errors++;
			if (stat & ST_RX_OVERRUN)
				dev->stats.rx_fifo_errors++;
			else if ((stat & (ST_RX_SHORT | ST_RX_ABORT |
					  ST_RX_RESBIT)) || port->rxpart)
				dev->stats.rx_frame_errors++;
			else if (stat & ST_RX_CRC)
				dev->stats.rx_crc_errors++;
			if (stat & ST_RX_EOM)
				port->rxpart = 0; /* received last fragment */
		} else {
			sca_rx(card, port, desc, port->rxin);
			received++;
		}

		/* Set new error descriptor address */
		sca_outl(desc_off, dmac + EDAL, card);
		port->rxin = (port->rxin + 1) % card->rx_ring_buffers;
	}

	/* make sure RX DMA is enabled */
	sca_out(DSR_DE, DSR_RX(port->chan), card);
	return received;
}

/* Transmit DMA service */
static inline void sca_tx_done(port_t *port)
{
	struct net_device *dev = port->netdev;
	card_t *card = port->card;
	u8 stat;
	unsigned count = 0;

	spin_lock(&port->lock);

	stat = sca_in(DSR_TX(port->chan), card); /* read DMA Status */

	/* Reset DSR status bits */
	sca_out((stat & (DSR_EOT | DSR_EOM | DSR_BOF | DSR_COF)) | DSR_DWE,
		DSR_TX(port->chan), card);

	while (1) {
		pkt_desc __iomem *desc = desc_address(port, port->txlast, 1);
		u8 stat = readb(&desc->stat);

		if (!(stat & ST_TX_OWNRSHP))
			break; /* not yet transmitted */
		if (stat & ST_TX_UNDRRUN) {
			dev->stats.tx_errors++;
			dev->stats.tx_fifo_errors++;
		} else {
			dev->stats.tx_packets++;
			dev->stats.tx_bytes += readw(&desc->len);
		}
		writeb(0, &desc->stat);	/* Free descriptor */
		count++;
		port->txlast = (port->txlast + 1) % card->tx_ring_buffers;
	}

	if (count)
		netif_wake_queue(dev);
	spin_unlock(&port->lock);
}

static int sca_poll(struct napi_struct *napi, int budget)
{
	port_t *port = container_of(napi, port_t, napi);
	u32 isr0 = sca_inl(ISR0, port->card);
	int received = 0;

	if (isr0 & (port->chan ? 0x08000000 : 0x00080000))
		sca_msci_intr(port);

	if (isr0 & (port->chan ? 0x00002000 : 0x00000020))
		sca_tx_done(port);

	if (isr0 & (port->chan ? 0x00000200 : 0x00000002))
		received = sca_rx_done(port, budget);

	if (received < budget) {
		napi_complete_done(napi, received);
		enable_intr(port);
	}

	return received;
}

static irqreturn_t sca_intr(int irq, void *dev_id)
{

Annotation

Implementation Notes