⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 s3c4510.c

📁 对于MAC WANG写的4510的驱动的修改,在uClinux环境下.转载
💻 C
📖 第 1 页 / 共 2 页
字号:
					priv->stats.tx_carrier_errors++;
				if(status & Under)
					priv->stats.tx_fifo_errors++;
				if(status & LateColl)
					priv->stats.tx_window_errors++;
				if(status & ExColl)
					priv->stats.collisions++;
			}
		}
	
		// Clear Framedata pointer already used
		FD_ptr->StatusAndFrameLength = 0x0;
		priv->gtx_ptr = (unsigned long) FD_ptr->NextFrameDescriptor;
	}
	
	spin_unlock(&priv->lock);
	return;
}

/*
 * Open and Close
 */
int s3c4510_open(struct net_device *dev)
{
	int i;
#if 0
	unsigned long status;
#endif
	MOD_INC_USE_COUNT;

	TRACE("open\n");

	// Disable irqs
	disable_irq(INT_BDMATX);
	disable_irq(INT_BDMARX);
	disable_irq(INT_MACTX);
	disable_irq(INT_MACRX);

	// register rx isr
	if(request_irq(INT_BDMARX, &s3c4510_rx, SA_INTERRUPT, "eth rx isr", dev)) {
		printk(KERN_ERR "s3c4510: Can't get irq %d\n", INT_BDMARX);
		return -EAGAIN;
	}

	// register tx isr
	if(request_irq(INT_MACTX, &s3c4510_tx, SA_INTERRUPT, "eth tx isr", dev)) {
		printk(KERN_ERR "s3c4510: Can't get irq %d\n", INT_MACTX);
		return -EAGAIN;
	}

	printk("Reseting PHY\n");
	MIIWrite(0x0, 0x0, 1<<15);
//	while((MIIRead(0x0, 0x0) & (1<<15)));
#if 0	
	
	printk("Perform AN again\n");
	MIIWrite(0x0, 0x0, MIIRead(0x0, 0x0) & ~(1<<12));
//	while(!(MIIRead(0x11, 0x0) & (1<<4)));

	MIIWrite(0x0, 0x0, 1<<13|1<<8);
	
	status = MIIRead(0x11, 0x0);
	if(status & 1<<15)
		printk("10M/b  ");
	else
		printk("100M/b  ");
	if(status & 1<<14)
		printk("Full duplex\n");
	else	printk("Half duplex\n");
#endif	
	// reset BDMA and MAC
	CSR_WRITE(BDMARXCON, BRxRS);
	CSR_WRITE(BDMATXCON, BTxRS);
	CSR_WRITE(MACON, Reset);
	CSR_WRITE(BDMARXLSZ, sizeof(struct ethframe));
	CSR_WRITE(MACON, gMACCON);

	FD_Init(dev);

	for(i = 0; i < (int)dev->addr_len-2; i++)
		CAM_Reg(0) = (CAM_Reg(0) << 8) | dev->dev_addr[i];
	for(i = (int)dev->addr_len-2; i < (int)dev->addr_len; i++)
		CAM_Reg(1) = (CAM_Reg(1) << 8) | dev->dev_addr[i];
	CAM_Reg(1) = (CAM_Reg(1) << 16);

	CSR_WRITE(CAMEN, 0x0001);
	CSR_WRITE(CAMCON, gCAMCON);

	enable_irq(INT_BDMARX);
	enable_irq(INT_MACTX);

	// ReadyMACTx();
	CSR_WRITE(BDMATXCON, gBDMATXCON);
	CSR_WRITE(MACTXCON, gMACTXCON);
	// ReadyMACRx();
	CSR_WRITE(BDMARXCON, gBDMARXCON);
	CSR_WRITE(MACRXCON, gMACRXCON);

	// Start the transmit queue
	netif_start_queue(dev);
	
	return 0;
}

int s3c4510_stop(struct net_device *dev)
{
	TRACE("stop\n");
	CSR_WRITE(BDMATXCON, 0);
	CSR_WRITE(BDMARXCON, 0);
	CSR_WRITE(MACTXCON, 0);
	CSR_WRITE(MACRXCON, 0);

	free_irq(INT_BDMARX, dev);
	free_irq(INT_MACTX, dev);

	netif_stop_queue(dev);
	MOD_DEC_USE_COUNT;
	
	return 0;
}

int s3c4510_start_xmit(struct sk_buff *skb, struct net_device *dev)
{
//	int i;
	int len;
	char *data;
	struct s3c4510_priv *priv = (struct s3c4510_priv *) dev->priv;

	struct FrameDesc	*FD_ptr;	// frame descriptor pointer
	volatile unsigned long	*FB_ptr;	// frame data pointer
	unsigned char		*FB_data;	// frame data
	unsigned long ulFlags;
	
	spin_lock_irqsave(&priv->lock, ulFlags);
	TRACE("start_xmit\n");
/*
	printk("sk_buff->len: %d\n", skb->len);
	printk("sk_buff->data_len: %d\n", skb->data_len);
	for(i = 0; i < skb->len; i++) {
		printk("%4x", skb->data[i]);
		if((i+1)%16 ==0)
			printk("\n");
	}
	printk("\n");
*/
	len = skb->len < ETH_ZLEN ? ETH_ZLEN : skb->len;
	data = skb->data;
	dev->trans_start = jiffies;
	
	// 1. Get Tx frame descriptor & data pointer
	FD_ptr = (struct FrameDesc *) priv->tx_ptr;
	FB_ptr = (unsigned long *) &FD_ptr->FrameDataPtr;
	FB_data = (unsigned char *) FD_ptr->FrameDataPtr;

	// 2. Check BDMA ownership
	if(*FB_ptr & BDMA_owner) {
		printk("no tx buffer\n");
//		check it later
//		netif_stop_queue(dev);
		spin_unlock_irqrestore(&priv->lock, ulFlags);
		return 1;
	}
	
	// 3. Prepare Tx Frame data to Frame buffer
	memcpy(FB_data, data, len);
	
	// 4. Set Tx Frame flag & Length Field
	FD_ptr->Reserved = (Padding | CRCMode | FrameDataPtrInc | LittleEndian | WA00 | MACTxIntEn);
	FD_ptr->StatusAndFrameLength = (len & 0xFFFF);
	
	// 5. Change ownership to BDMA
	FD_ptr->FrameDataPtr |= BDMA_owner;

	// 6. Enable MAC and BDMA Tx control register
	CSR_WRITE(BDMATXCON, gBDMATXCON);
	CSR_WRITE(MACTXCON, gMACTXCON);

	// 7. Change the Tx frame descriptor for next use
	priv->tx_ptr = (unsigned long)(FD_ptr->NextFrameDescriptor);

	spin_unlock_irqrestore(&priv->lock, ulFlags);

	dev_kfree_skb(skb);
	
	return 0;
}

struct net_device_stats *s3c4510_get_stats(struct net_device *dev)
{
	struct s3c4510_priv *priv = (struct s3c4510_priv *) dev->priv;
	TRACE("get_stats\n");
	return &priv->stats;
}

/*
*	change mac address when up
*/
static int	s3c4510_set_mac_address(struct net_device *dev, void *addr)
{
	struct sockaddr *p=(struct sockaddr *)addr;
	int i=0;
	s3c4510_stop(dev);
	memcpy(dev->dev_addr, p->sa_data,dev->addr_len);

	//Set CAM register
	for(i = 0; i < (int)dev->addr_len-2; i++)
		CAM_Reg(0) = (CAM_Reg(0) << 8) | dev->dev_addr[i];
	for(i = (int)dev->addr_len-2; i < (int)dev->addr_len; i++)
		CAM_Reg(1) = (CAM_Reg(1) << 8) | dev->dev_addr[i];
	CAM_Reg(1) = (CAM_Reg(1) << 16);

	CSR_WRITE(CAMEN, 0x0001);
	CSR_WRITE(CAMCON, gCAMCON);
	
	s3c4510_open(dev);
	return 0;
}

/*
 * The init function, invoked by register_netdev()
 */
int s3c4510_init(struct net_device *dev)
{
	int i;
	TRACE("init\n");
	ether_setup(dev);	// Assign some of the fields

	// set net_device methods
	dev->open = s3c4510_open;
	dev->stop = s3c4510_stop;
//	dev->ioctl = s3c4510_ioctl;
	dev->get_stats = s3c4510_get_stats;
//	dev->tx_timeout = s3c4510_tx_timeout;
	dev->hard_start_xmit = s3c4510_start_xmit;
	dev->set_mac_address=s3c4510_set_mac_address;
	
	// set net_device data members
	dev->watchdog_timeo = timeout;
	dev->irq = 17;
	dev->dma = 0;

	// set MAC address manually
	dev->dev_addr[0] = 0x00;
	dev->dev_addr[1] = 0x40;
	dev->dev_addr[2] = 0x95;
	dev->dev_addr[3] = 0x36;
	dev->dev_addr[4] = 0x35;
	dev->dev_addr[5] = 0x34;

	printk(KERN_INFO "%s: ", dev->name);
	for(i = 0; i < 6; i++)
		printk("%2.2x%c", dev->dev_addr[i], (i==5) ? ' ' : ':');
	printk("\n");

	SET_MODULE_OWNER(dev);

	dev->priv = kmalloc(sizeof(struct s3c4510_priv), GFP_KERNEL);
	if(dev->priv == NULL)
		return -ENOMEM;
	memset(dev->priv, 0, sizeof(struct s3c4510_priv));
	spin_lock_init(&((struct s3c4510_priv *) dev->priv)->lock);
	return 0;
}

struct net_device s3c4510_netdevs = {
	init: s3c4510_init,
};

/*
 * Finally, the module stuff
 */
int __init s3c4510_init_module(void)
{
	int result;
	TRACE("init_module\n");

	//Print version information
	printk(KERN_INFO "%s", version);

	//register_netdev will call s3c4510_init()
	if((result = register_netdev(&s3c4510_netdevs)))
		printk("S3C4510 eth: Error %i registering device \"%s\"\n", result, s3c4510_netdevs.name);
	return result ? 0 : -ENODEV;
}

void __exit s3c4510_cleanup(void)
{
	TRACE("cleanup\n");
	kfree(s3c4510_netdevs.priv);
	unregister_netdev(&s3c4510_netdevs);
	return;
}

module_init(s3c4510_init_module);
module_exit(s3c4510_cleanup);

MODULE_DESCRIPTION("Samsung 4510B ethernet driver");
MODULE_AUTHOR("Mac Wang <mac@os.nctu.edu.tw>");
MODULE_LICENSE("GPL");

⌨️ 快捷键说明

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