saa9730.c

来自「linux 内核源代码」· C语言 代码 · 共 1,140 行 · 第 1/3 页

C
1,140
字号
			return -1;		}		mdelay(1);	/* wait 1 ms. */	}	/* Wait for 1 ms. */	mdelay(1);	/* Check the link status. */	if (readl(&lp->lan_saa9730_regs->StationMgmtData) &	    PHY_STATUS_LINK_UP) {		/* Link is up. */		return 0;	} else {		/* Link is down, reset the PHY first. */		/* set PHY address = 'CONTROL' */		writel(PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR | PHY_CONTROL,		       &lp->lan_saa9730_regs->StationMgmtCtl);		/* Wait for 1 ms. */		mdelay(1);		/* set 'CONTROL' = force reset and renegotiate */		writel(PHY_CONTROL_RESET | PHY_CONTROL_AUTO_NEG |		       PHY_CONTROL_RESTART_AUTO_NEG,		       &lp->lan_saa9730_regs->StationMgmtData);		/* Wait for 50 ms. */		mdelay(50);		/* set 'BUSY' to start operation */		writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF | MD_CA_WR |		       PHY_CONTROL, &lp->lan_saa9730_regs->StationMgmtCtl);		/* await completion */		i = 0;		while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &		       MD_CA_BUSY) {			i++;			if (i > 100) {				printk				    ("Error: lan_saa9730_mii_init: timeout\n");				return -1;			}			mdelay(1);	/* wait 1 ms. */		}		/* Wait for 1 ms. */		mdelay(1);		for (l = 0; l < 2; l++) {			/* set PHY address = 'STATUS' */			writel(MD_CA_BUSY | PHY_ADDRESS << MD_CA_PHY_SHF |			       PHY_STATUS,			       &lp->lan_saa9730_regs->StationMgmtCtl);			/* await completion */			i = 0;			while (readl(&lp->lan_saa9730_regs->StationMgmtCtl) &			       MD_CA_BUSY) {				i++;				if (i > 100) {					printk					    ("Error: lan_saa9730_mii_init: timeout\n");					return -1;				}				mdelay(1);	/* wait 1 ms. */			}			/* wait for 3 sec. */			mdelay(3000);			/* check the link status */			if (readl(&lp->lan_saa9730_regs->StationMgmtData) &			    PHY_STATUS_LINK_UP) {				/* link is up */				break;			}		}	}	return 0;}static int lan_saa9730_control_init(struct lan_saa9730_private *lp){	/* Initialize DMA control register. */	writel((LANMB_ANY << DMA_CTL_MAX_XFER_SHF) |	       (LANEND_LITTLE << DMA_CTL_ENDIAN_SHF) |	       (LAN_SAA9730_RCV_Q_INT_THRESHOLD << DMA_CTL_RX_INT_COUNT_SHF)	       | DMA_CTL_RX_INT_TO_EN | DMA_CTL_RX_INT_EN |	       DMA_CTL_MAC_RX_INT_EN | DMA_CTL_MAC_TX_INT_EN,	       &lp->lan_saa9730_regs->LanDmaCtl);	/* Initial MAC control register. */	writel((MACCM_MII << MAC_CONTROL_CONN_SHF) | MAC_CONTROL_FULL_DUP,	       &lp->lan_saa9730_regs->MacCtl);	/* Initialize CAM control register. */	writel(CAM_CONTROL_COMP_EN | CAM_CONTROL_BROAD_ACC,	       &lp->lan_saa9730_regs->CamCtl);	/*	 * Initialize CAM enable register, only turn on first entry, should	 * contain own addr.	 */	writel(0x0001, &lp->lan_saa9730_regs->CamEnable);	/* Initialize Tx control register */	writel(TX_CTL_EN_COMP, &lp->lan_saa9730_regs->TxCtl);	/* Initialize Rcv control register */	writel(RX_CTL_STRIP_CRC, &lp->lan_saa9730_regs->RxCtl);	/* Reset DMA engine */	writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);	return 0;}static int lan_saa9730_stop(struct lan_saa9730_private *lp){	int i;	/* Stop DMA first */	writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) &	       ~(DMA_CTL_EN_TX_DMA | DMA_CTL_EN_RX_DMA),	       &lp->lan_saa9730_regs->LanDmaCtl);	/* Set the SW Reset bits in DMA and MAC control registers */	writel(DMA_TEST_SW_RESET, &lp->lan_saa9730_regs->DmaTest);	writel(readl(&lp->lan_saa9730_regs->MacCtl) | MAC_CONTROL_RESET,	       &lp->lan_saa9730_regs->MacCtl);	/*	 * Wait for MAC reset to have finished. The reset bit is auto cleared	 * when the reset is done.	 */	i = 0;	while (readl(&lp->lan_saa9730_regs->MacCtl) & MAC_CONTROL_RESET) {		i++;		if (i > 100) {			printk			    ("Error: lan_sa9730_stop: MAC reset timeout\n");			return -1;		}		mdelay(1);	/* wait 1 ms. */	}	return 0;}static int lan_saa9730_dma_init(struct lan_saa9730_private *lp){	/* Stop lan controller. */	lan_saa9730_stop(lp);	writel(LAN_SAA9730_DEFAULT_TIME_OUT_CNT,	       &lp->lan_saa9730_regs->Timeout);	return 0;}static int lan_saa9730_start(struct lan_saa9730_private *lp){	lan_saa9730_buffer_init(lp);	/* Initialize Rx Buffer Index */	lp->NextRcvPacketIndex = 0;	lp->NextRcvBufferIndex = 0;	/* Set current buffer index & next available packet index */	lp->NextTxmPacketIndex = 0;	lp->NextTxmBufferIndex = 0;	lp->PendingTxmPacketIndex = 0;	lp->PendingTxmBufferIndex = 0;	writel(readl(&lp->lan_saa9730_regs->LanDmaCtl) | DMA_CTL_EN_TX_DMA |	       DMA_CTL_EN_RX_DMA, &lp->lan_saa9730_regs->LanDmaCtl);	/* For Tx, turn on MAC then DMA */	writel(readl(&lp->lan_saa9730_regs->TxCtl) | TX_CTL_TX_EN,	       &lp->lan_saa9730_regs->TxCtl);	/* For Rx, turn on DMA then MAC */	writel(readl(&lp->lan_saa9730_regs->RxCtl) | RX_CTL_RX_EN,	       &lp->lan_saa9730_regs->RxCtl);	/* Set Ok2Use to let hardware own the buffers.	*/	writel(OK2USE_RX_A | OK2USE_RX_B, &lp->lan_saa9730_regs->Ok2Use);	return 0;}static int lan_saa9730_restart(struct lan_saa9730_private *lp){	lan_saa9730_stop(lp);	lan_saa9730_start(lp);	return 0;}static int lan_saa9730_tx(struct net_device *dev){	struct lan_saa9730_private *lp = netdev_priv(dev);	unsigned int *pPacket;	unsigned int tx_status;	if (lan_saa9730_debug > 5)		printk("lan_saa9730_tx interrupt\n");	/* Clear interrupt. */	writel(DMA_STATUS_MAC_TX_INT, &lp->lan_saa9730_regs->DmaStatus);	while (1) {		pPacket = lp->TxmBuffer[lp->PendingTxmBufferIndex]				       [lp->PendingTxmPacketIndex];		/* Get status of first packet transmitted. */		tx_status = le32_to_cpu(*pPacket);		/* Check ownership. */		if ((tx_status & TX_STAT_CTL_OWNER_MSK) !=		    (TXSF_HWDONE << TX_STAT_CTL_OWNER_SHF)) break;		/* Check for error. */		if (tx_status & TX_STAT_CTL_ERROR_MSK) {			if (lan_saa9730_debug > 1)				printk("lan_saa9730_tx: tx error = %x\n",				       tx_status);			dev->stats.tx_errors++;			if (tx_status &			    (TX_STATUS_EX_COLL << TX_STAT_CTL_STATUS_SHF))				dev->stats.tx_aborted_errors++;			if (tx_status &			    (TX_STATUS_LATE_COLL << TX_STAT_CTL_STATUS_SHF))				dev->stats.tx_window_errors++;			if (tx_status &			    (TX_STATUS_L_CARR << TX_STAT_CTL_STATUS_SHF))				dev->stats.tx_carrier_errors++;			if (tx_status &			    (TX_STATUS_UNDER << TX_STAT_CTL_STATUS_SHF))				dev->stats.tx_fifo_errors++;			if (tx_status &			    (TX_STATUS_SQ_ERR << TX_STAT_CTL_STATUS_SHF))				dev->stats.tx_heartbeat_errors++;			dev->stats.collisions +=				tx_status & TX_STATUS_TX_COLL_MSK;		}		/* Free buffer. */		*pPacket =		    cpu_to_le32(TXSF_EMPTY << TX_STAT_CTL_OWNER_SHF);		/* Update pending index pointer. */		lp->PendingTxmPacketIndex++;		if (lp->PendingTxmPacketIndex >= LAN_SAA9730_TXM_Q_SIZE) {			lp->PendingTxmPacketIndex = 0;			lp->PendingTxmBufferIndex ^= 1;		}	}	/* The tx buffer is no longer full. */	netif_wake_queue(dev);	return 0;}static int lan_saa9730_rx(struct net_device *dev){	struct lan_saa9730_private *lp = netdev_priv(dev);	int len = 0;	struct sk_buff *skb = 0;	unsigned int rx_status;	int BufferIndex;	int PacketIndex;	unsigned int *pPacket;	unsigned char *pData;	if (lan_saa9730_debug > 5)		printk("lan_saa9730_rx interrupt\n");	/* Clear receive interrupts. */	writel(DMA_STATUS_MAC_RX_INT | DMA_STATUS_RX_INT |	       DMA_STATUS_RX_TO_INT, &lp->lan_saa9730_regs->DmaStatus);	/* Address next packet */	BufferIndex = lp->NextRcvBufferIndex;	PacketIndex = lp->NextRcvPacketIndex;	pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];	rx_status = le32_to_cpu(*pPacket);	/* Process each packet. */	while ((rx_status & RX_STAT_CTL_OWNER_MSK) ==	       (RXSF_HWDONE << RX_STAT_CTL_OWNER_SHF)) {		/* Check the rx status. */		if (rx_status & (RX_STATUS_GOOD << RX_STAT_CTL_STATUS_SHF)) {			/* Received packet is good. */			len = (rx_status & RX_STAT_CTL_LENGTH_MSK) >>			    RX_STAT_CTL_LENGTH_SHF;			pData = (unsigned char *) pPacket;			pData += 4;			skb = dev_alloc_skb(len + 2);			if (skb == 0) {				printk				    ("%s: Memory squeeze, deferring packet.\n",				     dev->name);				dev->stats.rx_dropped++;			} else {				dev->stats.rx_bytes += len;				dev->stats.rx_packets++;				skb_reserve(skb, 2);	/* 16 byte align */				skb_put(skb, len);	/* make room */				skb_copy_to_linear_data(skb,						 (unsigned char *) pData,						 len);				skb->protocol = eth_type_trans(skb, dev);				netif_rx(skb);				dev->last_rx = jiffies;			}		} else {			/* We got an error packet. */			if (lan_saa9730_debug > 2)				printk				    ("lan_saa9730_rx: We got an error packet = %x\n",				     rx_status);			dev->stats.rx_errors++;			if (rx_status &			    (RX_STATUS_CRC_ERR << RX_STAT_CTL_STATUS_SHF))				dev->stats.rx_crc_errors++;			if (rx_status &			    (RX_STATUS_ALIGN_ERR << RX_STAT_CTL_STATUS_SHF))				dev->stats.rx_frame_errors++;			if (rx_status &			    (RX_STATUS_OVERFLOW << RX_STAT_CTL_STATUS_SHF))				dev->stats.rx_fifo_errors++;			if (rx_status &			    (RX_STATUS_LONG_ERR << RX_STAT_CTL_STATUS_SHF))				dev->stats.rx_length_errors++;		}		/* Indicate we have processed the buffer. */		*pPacket = cpu_to_le32(RXSF_READY << RX_STAT_CTL_OWNER_SHF);		/* Make sure A or B is available to hardware as appropriate. */		writel(BufferIndex ? OK2USE_RX_B : OK2USE_RX_A,		       &lp->lan_saa9730_regs->Ok2Use);		/* Go to next packet in sequence. */		lp->NextRcvPacketIndex++;		if (lp->NextRcvPacketIndex >= LAN_SAA9730_RCV_Q_SIZE) {			lp->NextRcvPacketIndex = 0;			lp->NextRcvBufferIndex ^= 1;		}		/* Address next packet */		BufferIndex = lp->NextRcvBufferIndex;		PacketIndex = lp->NextRcvPacketIndex;		pPacket = lp->RcvBuffer[BufferIndex][PacketIndex];		rx_status = le32_to_cpu(*pPacket);	}	return 0;}static irqreturn_t lan_saa9730_interrupt(const int irq, void *dev_id){	struct net_device *dev = dev_id;	struct lan_saa9730_private *lp = netdev_priv(dev);	if (lan_saa9730_debug > 5)		printk("lan_saa9730_interrupt\n");	/* Disable the EVM LAN interrupt. */	evm_saa9730_block_lan_int(lp);

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?