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

📄 dm9sw.c

📁 网卡芯片DM9003在linux下的驱动程序。
💻 C
📖 第 1 页 / 共 3 页
字号:
	/* Program operating register */	iow(db, DM9KS_NCR, 0x20); /* reg.01 cleared by write 1 */	iow(db, DM9KS_FCR, 0x20); /* RX Flow Control Enable */ #if defined(CHECKSUM)	printk("<DM9SW>Enable checksum offload \n");	/* TX checksum enable */	iow(db, DM9KS_TCCR, TCCR_UDP_Chksum|TCCR_TCP_Chksum|TCCR_IP_Chksum);	/* RX checksum enable */	iow(db, DM9KS_RCSR, RCSR_RX_Chksum_enable);#endif	/* switch config */	/* If using EEPROM sets switch functions,  	   don't execute dm9sw_switch_config() function */	dm9sw_switch_config(db);	/* Set address filter table */	dm9000_hash_table(dev);	/* Activate DM9000A/DM9010 */	/* Promisucous mode bug DM9013 V2 */	iow(db, DM9KS_RXCR, RXCR_RxEnable|RXCR_Promiscuous);		iow(db, DM9KS_IMR, DM9KS_REGFF); /* Enable TX/RX interrupt mask */ 	/* Init Driver variable */	db->tx_pkt_cnt = 0;			netif_carrier_on(dev);}inline u8 MAKE_MASK(int p3, int p2, int p1, int p0){	p3 = p3 ? 1:0;	p2 = p2 ? 1:0;	p1 = p1 ? 1:0;	p0 = p0 ? 1:0;		return (p3<<3)|(p2<<2)|(p1<<1)|p0;}static void vlan_group_map(board_info_t *db,u8 reg_group, u8 mapping){	iow(db,reg_group,mapping);	}/*	vlan_type 0:Port-base		 1:Tag-base*/static void VLAN_SETUP(board_info_t *db, int vlan_type){		if (vlan_type)/* Tag-base */	{		printk("DM9013:VLAN TAG-BASE\n");		/* enble tag-base vlan (reg 53h.0=1) */			iow (db, DM9KS_VLANCR, (ior(db,DM9KS_VLANCR)&0xff)|0x1);				/*		input_port	output_port (1:tag-packet, 0:untag-packet)		   0             1		   1		 0		   1		 1		Per-port setting		01: VID(reg 6fH.[3:0])-->output packet tagging(reg 6dH.7=1)-->Group mapping		10: Group mapping		11: output packet tagging(reg 6dH.7=1)-->Group mapping		*/		/*01: set port VID*/		/*vlan_port_vid(db, port_no, VID)*/		vlan_port_vid(db,0,0); /* set P0 VID=0 */		vlan_port_vid(db,1,2); /* set P1 VID=2*/				/*01,11:Per-port output packet tagging enable */		vlan_outpkt_tag(db,0); 		vlan_outpkt_tag(db,1);		vlan_outpkt_tag(db,2); 		vlan_outpkt_tag(db,3);		/*01,10,11:group mapping */		vlan_group_map(db, VLAN_GROUP1, MAKE_MASK(1, 1, 1, 1));		vlan_group_map(db, VLAN_GROUP2, MAKE_MASK(1, 1, 1, 1));		}else{		printk("DM9013:VLAN PORT-BASE\n");		/* enble tag-base vlan (reg 53h.0=0) */			iow (db, DM9KS_VLANCR, (ior(db,DM9KS_VLANCR)&0xfe));		/* port-base VLAN 			step 1:set Port VID			Step 2:set Group mapping */					/* set port VID */		/* vlan_pvid(board_info_t, port_num, VID)*/		vlan_port_vid(db,0,1);/* P0 VID=1  */		vlan_port_vid(db,1,2);/* P1 VID=2  */		vlan_port_vid(db,3,3);/* P3 VID=3  */		/* group mapping */		vlan_group_map(db, VLAN_GROUP1, MAKE_MASK(1, 0, 0, 1));/* Group1 : P3, P0 */		vlan_group_map(db, VLAN_GROUP2, MAKE_MASK(1, 0, 0, 1));/* Group2 : P3, P0 */		vlan_group_map(db, VLAN_GROUP3, MAKE_MASK(1, 0, 1, 1));/* Group3 : P3, P1, P0*/	}}static int vlan_port_vid(board_info_t *db, int port, u8 VID){	if((port<0)||(port > 3)) 	{		printk("<DM9SW>Port number error\n ");		return 1;	}	iow(db, DM9KS_PIndex, port);	iow(db, DM9KS_VLAN_TAGL, VID);		return 0;}static int vlan_outpkt_tag(board_info_t *db, int port){	if(port < 0 || port > 3) 	{		printk("<DM9SW>Port number error \n");		return 1;	}	iow(db, DM9KS_PIndex, port);		iow(db, DM9KS_PPRI, ior(db,DM9KS_PPRI)|0x80); 	return 0;}static int qos_port_pri(board_info_t *db, int port, u8 priority){	u8 tmp;	if(port < 0 || port > 3) 	{		printk("<DM9SW>Port number error\n ");		return 1;	}	iow(db, DM9KS_PIndex, port);	tmp = (ior(db,DM9KS_PPRI)&0xfc)|priority;	iow(db, DM9KS_PPRI,tmp);	return 0;}static int qos_tos_enable(board_info_t *db, int port){	if(port < 0 || port > 3) 	{		printk("<DM9SW>Port number error\n ");		return 1;	}	iow(db, DM9KS_PIndex, port);	iow(db, DM9KS_PPRI,ior(db,DM9KS_PPRI)|0x8);	return 0;}static void QoS_SETUP(board_info_t *db, int QoS_type){	switch (QoS_type)	{	case 0: /* port */		printk("<DM9SW>Port Priority\n");		qos_port_pri(db,0,0); /* set P0 queue0  */		qos_port_pri(db,1,1); /* set P1 queue1  */		qos_port_pri(db,2,2); /* set P2 queue2  */		qos_port_pri(db,3,3); /* set P3 queue3  */		break;	case 1: /* Tag */		/* TAG-VLAN format		   | 0x8100 | vlan-priority(3bit)| CFI(1bit) | VID(12bit)| 		   VLAN-TAG priority (default)		   Queue 0 : vlan-priority = 0 & 1		   Queue 1 : vlan-priority = 2 & 3		   Queue 2 : vlan-priority = 4 & 5		   Queue 3 : vlan-priority = 6 & 7			   if you want to modify the priority map, please refer 		   reg0xC0 and reg0xC1 		 */		printk("<DM9SW>VLAN-TAG Priority\n");		break;	case 2: /* TOS */		printk("<DM9SW>TOS Priority\n");		//check most significant 6-bit of TOS		//iow(db, DM9KS_VLANCR, ior(db,DM9KS_VLANCR)|0x80);		qos_tos_enable(db,0);		qos_tos_enable(db,1);		qos_tos_enable(db,2);		qos_tos_enable(db,3);		/*if you want to modify the priority map,		 	if reg0x53.[7]=1				please refer reg0xC0~reg0xCF			else				please refer reg0xC0 and reg0xC1		*/		break;	}}/*	bw_type refer to reg 61H.3*/static int dm9k_bw_control(board_info_t *db, int port, u8 bw_type, u8 bit74, u8 bit30){	u8 tmp;	printk("<DM9SW>Bandwidth control\n");		if(port < 0 || port > 3) 	{		printk("<DM9SW>Port number error \n");		return 1;	}	iow(db, DM9KS_PIndex, port);/* set port index */	tmp = (ior(db,DM9KS_PCTRL)& 0xf7); /* clear bit3 */	bit74 &= 0x0f;	bit30 &= 0x0f;	if (bw_type==0)	{		iow(db, DM9KS_PCTRL, tmp);		/* per-port Ingress/Egress control */		//Reg.66H [7:4]=RX,[3:0]=TX		iow(db, DM9KS_PRATE, (bit74<<4)|bit30);	}else{ /* bw_type ==1*/		tmp|= 0x8;		iow(db, DM9KS_PCTRL, tmp);		tmp = (ior(db, DM9KS_PBW)&0xf0)|bit30;		iow(db, DM9KS_PBW, tmp);	}	return 0;}/*  Hardware start transmission.  Send a packet to media from the upper layer.*/static int dmfe_start_xmit(struct sk_buff *skb, struct net_device *dev){	board_info_t *db = (board_info_t *)dev->priv;	char * data_ptr;	if (db->tx_pkt_cnt >= 2) return 1;	/* packet counting */	db->tx_pkt_cnt++;	db->stats.tx_packets++;	db->stats.tx_bytes+=skb->len;	// FIFO has fulled already	if (db->tx_pkt_cnt == 2) 	{		netif_stop_queue(dev);		db->stop_transmit =1;	}	/* Disable all interrupt */	iow(db, DM9KS_IMR, DM9KS_DISINTR);	/* Set TX length to reg. 0xfc & 0xfd */	iow(db, DM9KS_TXPLL, (skb->len & 0xff));	iow(db, DM9KS_TXPLH, (skb->len >> 8) & 0xff);	/* Move data to TX SRAM */	data_ptr = (char *)skb->data;		outb(DM9KS_MWCMD, db->io_addr); // Write data into SRAM trigger	db->MoveData(db, data_ptr, skb->len, 1);		/* Issue TX polling command */	iow(db, DM9KS_TCR, TCR_TX_Request); 	/* Saved the time stamp */	dev->trans_start = jiffies;	db->cont_rx_pkt_cnt =0;	/* Free this SKB */	dev_kfree_skb(skb);	/* Re-enable interrupt */	iow(db, DM9KS_IMR, DM9KS_REGFF);	return 0;}/*  Stop the interface.  The interface is stopped when it is brought.*/static int dmfe_stop(struct net_device *dev){	board_info_t *db = (board_info_t *)dev->priv;	int i;	DMFE_DBUG(0, "dmfe_stop", 0);	/* deleted timer */	del_timer(&db->timer);	netif_stop_queue(dev); 	/* free interrupt */	free_irq(dev->irq, dev);	/* RESET devie */	for (i=0; i<=db->port_mode; i++)		phy_write(db, 0x00, 0x8000,i);	/* PHY RESET */	dm9sw_switch_reset(db);	iow(db, 0, 1); /* software reset  */	iow(db, 0x52, 0x60); /* reset switch core and analog PHY core  */	iow(db, DM9KS_RXCR, 0x00);	/* Disable RX */	iow(db, DM9KS_IMR, DM9KS_DISINTR);	/* Disable all interrupt */	/* Dump Statistic counter */#if FALSE	printk("\nRX FIFO OVERFLOW %lx\n", db->stats.rx_fifo_errors);	printk("RX CRC %lx\n", db->stats.rx_crc_errors);	printk("RX LEN Err %lx\n", db->stats.rx_length_errors);	printk("RESET %x\n", db->reset_counter);	printk("RESET: TX Timeout %x\n", db->reset_tx_timeout);	printk("g_TX_nsr %x\n", g_TX_nsr);#endif	return 0;}static void dmfe_tx_done(unsigned long unused){	struct net_device *dev = dmfe_dev;	board_info_t *db = (board_info_t *)dev->priv;	u8  nsr;	DMFE_DBUG(0, "dmfe_tx_done()", 0);		nsr = ior(db, DM9KS_NSR);	iow(db, DM9KS_NSR, nsr); /* clear TX packet complete status */	if(nsr & NSR_TX1END) db->tx_pkt_cnt--;	if(nsr & NSR_TX2END) db->tx_pkt_cnt--;	if (db->tx_pkt_cnt < 0)	{		printk("[dmfe_tx_done] tx_pkt_cnt ERROR!!\n");		db->tx_pkt_cnt =0;	}		if(db->stop_transmit ) 	{		netif_wake_queue(dev);		db->stop_transmit=0;	}				return;}/*  DM9000 insterrupt handler  receive the packet to upper layer, free the transmitted packet*/#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)static void dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)#elsestatic irqreturn_t dmfe_interrupt(int irq, void *dev_id, struct pt_regs *regs)#endif{	struct net_device *dev = dev_id;	board_info_t *db;	int int_status;	u8 reg_save;	DMFE_DBUG(0, "dmfe_interrupt()", 0);	/* A real interrupt coming */	db = (board_info_t *)dev->priv;	spin_lock(&db->lock);	/* Save previous register address */	reg_save = inb(db->io_addr);	/* disable IMR */	iow(db, DM9KS_IMR, 0x80);	/* Got DM9000A/DM9010 interrupt status */	int_status = ior(db, DM9KS_ISR);	/* Got ISR */	iow(db, DM9KS_ISR, int_status);		/* Clear ISR status */ 	/* Trnasmit Interrupt check */	if (int_status & ISR_TX_complete)		dmfe_tx_done(0);	/* Received the coming packet */	if (int_status & ISR_RX_coming) #ifdef NAPI	{		if (netif_rx_schedule_prep(dev)) {			iow(db, DM9KS_IMR,DM9KS_NO_RX_INTR);      			__netif_rx_schedule(dev);                 }	}#else	dmfe_packet_receive(dev);#endif	iow(db, DM9KS_IMR, DM9KS_REGFF);		/* Restore previous register address */	outb(reg_save, db->io_addr); 	spin_unlock(&db->lock); #if LINUX_VERSION_CODE > KERNEL_VERSION(2,5,0)	return IRQ_HANDLED;#endif}#if !defined(CHECKSUM)#define check_rx_ready(a)       ((a) == 0x01)#elseinline u8 check_rx_ready(u8 rxbyte){        if (!(rxbyte & 0x01))                return 0;        return ((rxbyte >> 4) | 0x01);}#endif#ifdef NAPIstatic int dmfe_poll (struct net_device *dev, int *budget){	board_info_t *db = (board_info_t *)dev->priv;	struct sk_buff *skb;        u8 rxbyte, val;        u16 MDRAH, MDRAL;        u32 tmpdata;	unsigned rx_work = dev->quota;	unsigned rx;	rx_t rx_desc;        u8 * ptr = (u8 *)&rx_desc;        u8 * rdptr;rx_status_loop:	rx = 0;	iow(db, DM9KS_ISR, ISR_RX_coming); //clean this bit	while(1){		/*store the value of Memory Data Read address register*/		MDRAH=ior(db, DM9KS_MDRAH);		MDRAL=ior(db, DM9KS_MDRAL);		rxbyte =ior(db, DM9KS_MRCMDX);  		rxbyte =ior(db, DM9KS_ISR);     /* Dummy read */		rxbyte =ior(db, DM9KS_MRCMDX);  /* read the byte of packet ready */				/* packet ready to receive check */

⌨️ 快捷键说明

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