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

📄 dm9000.c

📁 硬件设计LPC2138+DM9000AE
💻 C
📖 第 1 页 / 共 3 页
字号:

/*Spenser---------------------------------------------------------*/
	/*Initial DM9000*/
	init_dm9000();		 
	
	/*Set the Mac address*/
	
	err=ETHER_MacLoad(netp);	
	
	/* set Multicast table */	
	ETHER_setMulticast(netp); 

	/*added by anlow for multicast, 06-01-09*/
	//netp->set_multicalist = &dm9000_hash_table;
	netp->set_multicalist =dm9000_hash_table;
	
#ifdef AUTO_RELEASE  	
  	  	
  	/* automatically  release successfully transmitted packets */
  	
#endif	


#ifdef LOOP_BACK
	iow(iobase, 0, 0x02);	/*MAC internal loop back.	*/	  	
#endif
		
	/* Activate DM9000 */
	iow(iobase, 0x5, (RXCTL_DEFAULT | 1));	/* RX enable */

	/*install the interupt handler */

	/* enables IRQs */	
	/* By Anky */
	iow(iobase, 0xFF, IMR_DEFAULT); 	/* Enable TX/RX interrupt mask */	
	
	return(err);	
}



/*-----------------------------------------------------------------------------
	Name		: init_dm9000
	Description	: Initialize MAC & PHY
	Author		: Spenser
------------------------------------------------------------------------------*/
ErrorCode_t init_dm9000(void)
{	
	iow(iobase, 0x1F, 0);	/* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */
	task_delay(200);
	iow(iobase, 0, 3);
	task_delay(200);		/* wait 20us at least for software reset ok */
	iow(iobase, 0, 3);		/* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on. Added by SPenser */
	task_delay(200);		/* wait 20us at least for software reset ok */

	/* change I/O mode to byte mode 
	iow(iobase, 0xfe, U8 RegData)*/
	

	/* I/O mode */
	dm9000_iomode = ior(iobase, 0xfe) >> 6; /* ISR bit7:6 keeps I/O mode */

	/* Configure the PHY */
	set_PHY_mode();
	
	/* Program operating register */
	iow(iobase, 0x00, 0);	
	iow(iobase, 0x02, 0);		/* TX Polling clear */
	iow(iobase, 0x2f, 0);		/* Special Mode */
	iow(iobase, 0x01, 0x2c);	/* clear TX status */
	/* iow(iobase, 0xfe, 0x0f); 	Clear interrupt status */
	
	iow(iobase, 0x08, BACK_PRESSURE_THRESHOLD);
	iow(iobase, 0x09, FLOWCONTROL_THRESHOLD);	/* Flow control: High/Low water */
	iow(iobase, 0x0a, TX_RX_FLOWCONTROL);	/* flow control */
		
	/* Initial Global variable */
	tx_pkt_cnt = 0;


}		

/*---------------------------------------------------------------------------
	Name		: set_PHY_mode
	Description	: PHY setting
	Author		: Spenser
-----------------------------------------------------------------------------*/
ErrorCode_t set_PHY_mode(void)
{
	/*U16 phy_reg0 = 0x1200;		 Auto-negotiation & non-duplux mode*/
	U16 phy_reg0 = 0x1000;	
	U16 phy_reg4 = 0x01e1;		/* Default non flow control */

	phy_write(0, phy_reg0);
	phy_write(4, phy_reg4);
	
}		

/*--------------------------------------------------------------
	Name		: phy_write
	Description	: Write PHY's register.
	Author		: Spenser
---------------------------------------------------------------*/
void phy_write(U8 reg, U16 value)
{
	/* Fill the phyxcer register into REG_0C */
	iow(iobase, 0xc, DM9000_PHY | reg);

	/* Fill the written data into REG_0D & REG_0E */
	iow(iobase, 0xd, (value & 0xff));
	iow(iobase, 0xe, ( (value >> 8) & 0xff));

	iow(iobase, 0xb, 0xa);		/* Issue phyxcer write command */
	task_delay(500);			/* Wait write complete */
	iow(iobase, 0xb, 0x0);		/* Clear phyxcer write command */
		
}

/*-------------------------------------------------------------------
	Name	: phy_read
	Description	: Read a word from phyxcer
	Author	: Spenser
---------------------------------------------------------------------*/
static U16 phy_read(int reg)
{
	/* Fill the phyxcer register into REG_0C */
	iow(iobase, 0xc, DM9000_PHY | reg);

	iow(iobase, 0xb, 0xc); 	/* Issue phyxcer read command */
	task_delay(100);		/* Wait read complete */
	iow(iobase, 0xb, 0x0); 	/* Clear phyxcer read command */

	/* The read data keeps on REG_0D & REG_0E */
	return ( ior(iobase, 0xe) << 8 ) | ior(iobase, 0xd);
}


/*-------------------------------------------------------------------
	Name		: read_srom_word
	Description	: Read a word data from SROM
	Parameters	: offset = Word offset of eeprom.
	Author		: Spenser
--------------------------------------------------------------------*/
U16 read_srom_word(int offset)
{
	EEPROM_PHY_ADR_REG = offset;	/*Word address	*/
	EEPROM_PHY_CTL_REG = EEPROM_READ_COMMAND;	/*read command	*/
	task_delay(200);
	EEPROM_PHY_CTL_REG = 0;	/*Clear read command		*/
	
	return (EE_PHY_L_REG + (EE_PHY_H_REG << 8));
	
}

/*----------------------------------------------------------------------------
	Name		: dm9000_hash_table
	Description	: Set DM9000 MAC address & multicase address filter
	Author		: Spenser
-----------------------------------------------------------------------------*/
void dm9000_hash_table(struct netif *dev)
{
//board_info_t *db = (board_info_t *)dev->priv;
	struct dev_mc_list *mcptr = dev->mc_list;
	int mc_cnt = dev->mc_count;
	U32 hash_val;
	U16 i, oft, hash_table[4];

	/* Set Node address */
	PAB0_REG = mac_addr[0];
	PAB1_REG = mac_addr[1];
	PAB2_REG = mac_addr[2];
	PAB3_REG = mac_addr[3];
	PAB4_REG = mac_addr[4];
	PAB5_REG = mac_addr[5];
	
	/* Clear Hash Table */
	for (i = 0; i < 4; i++)
		hash_table[i] = 0x0;

	/* broadcast address */
	hash_table[3] = 0x8000;

	/* the multicast address in Hash Table : 64 bits */
	for (i = 0; i < mc_cnt; i++, mcptr = mcptr->next) {
		hash_val = cal_CRC((char *)mcptr->dmi_addr, 6, 0) & 0x3f; 
		hash_table[hash_val / 16] |= (U16) 1 << (hash_val % 16);
	}

	/* Write the hash table to MAC MD table */
	for (i = 0, oft = 0x16; i < 4; i++) {
		iow(IO_base, oft++, hash_table[i] & 0xff);
		iow(IO_base, oft++, (hash_table[i] >> 8) & 0xff);
	}	
}		

/*----------------------------------------------------------------------------
	Name		: cal_CRC
	Description	: Calculate the CRC valude of the Rx packet
	Parameter	: flag = 1 : return the reverse CRC (for the received packet CRC)
         				 0 : return the normal CRC (for Hash Table index)
    Author		: Spenser
--------------------------------------------------------------------------------*/
static unsigned long cal_CRC(unsigned char * Data, unsigned int Len, U8 flag)
{  
    unsigned long Crc = 0xffffffff;

	while (Len--) {
		Crc = CrcTable[(Crc ^ *Data++) & 0xFF] ^ (Crc >> 8);
	}

	if (flag)
		return ~Crc;
	else
		return Crc;
}



/*-----------------------------------------------------------------------------
	Name	: dmfe_start_xmit
	Description	: Hardware start transmission. Send a packet to media from the upper layer.
	
--------------------------------------------------------------------------------*/
int dmfe_start_xmit(struct netif *netp, struct pbuf *p)
{
	char * data_ptr;
	int i, tmplen;
	int sent_pkt_len;
  	struct pbuf *q;
  	

	if (tx_pkt_cnt > 1)
		return 1; 
	
/*	netif_stop_queue(dev); 	*/

#ifdef MUTEX_RD
semaphore_wait(mutex_wr_dm9k);
#endif


	/* Disable all interrupt */
	iow(iobase, 0xff, IMR_DIS_ALL);

	/* Move data to DM9000 TX RAM */
	outb(0xf8,iobase);
	
	sent_pkt_len = p->tot_len;
	
	if (dm9000_iomode == DM9000_BYTE_MODE) {
		
  		for(q = p; q != NULL; q = q->next) 
			{
    			/* Send the data from the pbuf to the interface, one pbuf at a
      			 time. The size of the data in each pbuf is kept in the ->len
       		variable. */
			data_ptr = (char *)q->payload;
			for (i = 0; i < q->len; i++)
				outb((data_ptr[i] & 0xff), iodata);
  			}
		
	}else{
		/* Word mode */		
  		for(q = p; q != NULL; q = q->next) 
			{		
			tmplen = (q->len + 1) / 2;
			data_ptr = (char *)q->payload;
			for (i = 0; i < tmplen; i++)
				{
				outw(((U16 *)data_ptr)[i], iodata);	
				}
  			}

		tx_counter++;		/*for test*/
	}

	/* TX control: First packet immediately send, second packet queue */
	if (tx_pkt_cnt == 0) 
	{
		/* First Packet */
		tx_pkt_cnt++;

		/* Set TX length to DM9000 */
		#if 0
		iow(iobase, 0xfc, sent_pkt_len & 0xff);
		iow(iobase, 0xfd, (sent_pkt_len >> 8) & 0xff);
		#else
		iow(iobase, 0xfc, sent_pkt_len & 0xff);
		iow(iobase, 0xfd, (sent_pkt_len >> 8) & 0xff);
		#endif

		/* Issue TX polling command */
		iow(iobase, 0x2, 0x1);		/* Cleared after TX complete */

		/*save data length to use it in stat*/
		pktsize=sent_pkt_len;
			//netp->if_opackets++;
			//netp->if_obytes += pktsize;  
	} 
	else {
		/* Second packet */
		tx_pkt_cnt++;
		queue_pkt_len = sent_pkt_len;
	}


		
	/* Re-enable interrupt*/ 
	iow(iobase,0xff, IMR_DEFAULT);


#ifdef MUTEX_RD
semaphore_signal(mutex_wr_dm9k);
#endif

	
	return 0;
}


#ifdef TASK_MODE
/*============================================================================
	Name  		:	
	Description :	Copy Data from chip to  NexGen buffer.
 ============================================================================*/
static void ETHER_CopyData(struct netif *netp)
{

	while(task_run)
	{	
		semaphore_wait(CopyGo);	
		
		dmfe_packet_receive(netp);		

	}	
}	

#endif


static int ETHER_Close(struct netif *netp) 
{
	
	/*U16 cfg_reg;
	static NGbuf * bufp;	*/
	
	/*interface must be already running*/
	if(!(netp->flags)&NG_IFF_RUNNING)
	{
		return(1);
	}	
	
	/* clear flags*/
	/*(netp->flags)&=~(NG_IFF_RUNNING|NG_IFF_UP);			*/
	(netp->flags)&=~NG_IFF_RUNNING;
	

	/* RESET devie */
/*	phy_write(db, 0x00, 0x8000);	 PHY RESET */	
	iow(iobase, 0xff, 0x80);		/* Disable all interrupt */	
	iow(iobase, 0x05, 0x00);		/* Disable RX */
	iow(iobase, 0x1f, 0x01); 		/* Power-Down PHY */

	/*uninstall the irq*/
	
#ifdef TASK_MODE	
	task_run=FALSE;
	task_delete(Task);
	semaphore_delete(CopyGo);
#endif	

	#if 0
	/* Remove pending buffers */
  	while (1) 
  	{
    	ngBufDequeue(netp, bufp);
    	if (bufp == NULL)
    	{
    		 break;
    	}	 
    	ngBufOutputFree(bufp);
  	}
	#endif	
	
	return(0);
}	

/*-------------------------------------------------------------------------
	Name	: ETHER_InterruptHandler
	Description	: handler of the interruptions.
	Author	: 
--------------------------------------------------------------------------*/
static void InterruptHandler(struct netif *netp)
{
	
	/* A real interrupt coming */	

	/* Save previous register address */
	reg_save = inb(iobase);

	/* Disable all interrupt */
	iow(iobase, 0xff, IMR_DIS_ALL); 

	/* Got DM9000 interrupt status */
	int_status = ior(iobase, 0xfe);		/* Got ISR */
	iow(iobase, 0xfe, 0x3f);		 /*Clear ISR status */ 


	/* Trnasmit Interrupt check */
	if (int_status & DM9000_TX_INTR)
	{
		tx_status = ior(iobase, 0x01);	/* Got TX status */
		if (tx_status & 0xc) 
		{
			/* One packet sent complete */
			tx_pkt_cnt--;

			/* Queue packet check & send */
			if (tx_pkt_cnt > 0)
			{
				/* Set TX length to DM9000 */
				iow(iobase, 0xfc, queue_pkt_len & 0xff);
				iow(iobase, 0xfd, (queue_pkt_len >> 8) & 0xff);
		
				/* Issue TX polling command */
				iow(iobase, 0x2, 0x1);    /* Cleared after TX complete */
				

⌨️ 快捷键说明

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