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

📄 dm9000xend.c

📁 博创PXA270-S开发箱的VxWorks BSP驱动(含注释)
💻 C
📖 第 1 页 / 共 3 页
字号:
 *  Open the interface. *  The interface is opened whenever "ifconfig" actives it. */static intdmfe_open(DM9000_END_DEVICE *pDrvCtrl){		/* Initialize DM9000 board */	dmfe_reset(pDrvCtrl);	dmfe_init_dm9000(pDrvCtrl);		return OK;}/*  * Set PHY operating mode */static voidset_PHY_mode(DM9000_END_DEVICE *pDrvCtrl){	u16 phy_reg4 = 0x01e1, phy_reg0 = 0x1000;	UINT32 id;	       id = dmfe_phy_read(pDrvCtrl, 0, MII_PHYSID1);/*	printf("id = 0x%x\n\r", id); */	if (!(pDrvCtrl->op_mode & DM9000_AUTO)) {		switch (pDrvCtrl->op_mode) {		case DM9000_10MHD:			phy_reg4 = ADVERTISE_10HALF | ADVERTISE_CSMA;			phy_reg0 = 0;			break;		case DM9000_10MFD:			phy_reg4 = ADVERTISE_10FULL | ADVERTISE_CSMA;			phy_reg0 = BMCR_ANENABLE | BMCR_FULLDPLX;			break;		case DM9000_100MHD:			phy_reg4 = ADVERTISE_100HALF | ADVERTISE_CSMA;			phy_reg0 = BMCR_SPEED100;			break;		case DM9000_100MFD:			phy_reg4 = ADVERTISE_100FULL | ADVERTISE_CSMA;			phy_reg0 =			    BMCR_SPEED100 | BMCR_ANENABLE | BMCR_FULLDPLX;			break;		}		dmfe_phy_write(pDrvCtrl, 0, MII_ADVERTISE, phy_reg4);	/* Set PHY media mode */		dmfe_phy_write(pDrvCtrl, 0, MII_BMCR, phy_reg0);	/*  Tmp */	}	iow(pDrvCtrl, DMFE_GPCR, 0x01);	/* Let GPIO0 output ?*/	iow(pDrvCtrl, DMFE_GPR, 0x00);	/* Enable PHY */}/*  * Initilize dm9000 board */static voiddmfe_init_dm9000(DM9000_END_DEVICE *pDrvCtrl){	/* I/O mode */	pDrvCtrl->io_mode = ior(pDrvCtrl, DMFE_ISR) >> 6;	/* ISR bit7:6 keeps I/O mode */	/* GPIO0 on pre-activate PHY */	iow(pDrvCtrl, DMFE_GPR, 0x00);	/*REG_1F bit0 activate phyxcer */	/* Set PHY */	pDrvCtrl->op_mode = media_mode;	set_PHY_mode(pDrvCtrl); 	/* Init needed register value */	pDrvCtrl->reg0 = DM9000_REG00;	/* User passed argument */	pDrvCtrl->reg5 = reg5;	pDrvCtrl->reg8 = reg8;	pDrvCtrl->reg9 = reg9;	pDrvCtrl->rega = rega;	/* Program operating register */	iow(pDrvCtrl, DMFE_NCR, pDrvCtrl->reg0);/*关闭唤醒,全双工*/	iow(pDrvCtrl, DMFE_TCR, 0);	        /* TX Polling clear */	iow(pDrvCtrl, DMFE_BPTR, 0x3f);	    /* Less 3Kb, 200us */	iow(pDrvCtrl, DMFE_FCTR, pDrvCtrl->reg9);	/* Flow Control : High/Low Water */	iow(pDrvCtrl, DMFE_FCR, pDrvCtrl->rega);	/* Flow Control */	iow(pDrvCtrl, DMFE_SMCR, 0);	        /* Special Mode */	iow(pDrvCtrl, DMFE_NSR, 0x2c);	    /* clear TX status */	iow(pDrvCtrl, DMFE_ISR, ISR_CLR_STATUS); /* Clear interrupt status */	/* Set address filter table */	dm9000_hash_table(pDrvCtrl);	/* Activate DM9000 */	iow(pDrvCtrl, DMFE_RCR, pDrvCtrl->reg5 | 0x1);	/* RX enable *//*丢弃长包和CRC错误包,接收使能*/	iow(pDrvCtrl, DMFE_IMR, DM9000_REGFF);	/* Enable TX/RX interrupt mask */	}/* *  Hardware start transmission. *  Send a packet to media from the upper layer. */static intdmfe_start_xmit(M_BLK* pMblk, DM9000_END_DEVICE *pDrvCtrl){	char *data_ptr;	int i,packetLenAlign = 0, packetLen = 0;	u32 tempdata;	u8   reg_value;	M_BLK* sendPacket = pMblk;	int freeFlag = 0;	END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);	reg_value = ior(pDrvCtrl, DMFE_IMR);	/* Disable all interrupts */	iow(pDrvCtrl, DMFE_IMR, IMR_PAR);    		/* Move data to DM9000 TX RAM */	DM9000_outb(DMFE_MWCMD, pDrvCtrl->ioaddr);	if((sendPacket->m_next != NULL) && 		(sendPacket->mBlkPktHdr.len > sendPacket->m_len))	{		char *tmp_buffer;				packetLen = sendPacket->mBlkPktHdr.len;		packetLenAlign = (packetLen + 3) / 4;				tmp_buffer = data_ptr = (char *)memalign (4, packetLenAlign*4+4);		do 		{			memcpy(tmp_buffer, (char *)sendPacket->m_data, sendPacket->m_len);			tmp_buffer += sendPacket->m_len;			sendPacket = sendPacket->m_next;		}while(sendPacket != NULL);		freeFlag = 1;	}	else	{		data_ptr = (char *) sendPacket->m_data;		packetLen = sendPacket->m_len;		packetLenAlign = (sendPacket->m_len + 3) / 4;	}		for (i = 0; i < packetLenAlign; i++)	{		memcpy(&tempdata, data_ptr+i*sizeof(tempdata),sizeof(tempdata));	 		DM9000_outl(tempdata, pDrvCtrl->io_data);				}	/* TX control: First packet immediately send, second packet queue */		/* Set TX length to DM9000 */		iow(pDrvCtrl, DMFE_TXPLL, (packetLen) & 0xff);		iow(pDrvCtrl, DMFE_TXPLH, ((packetLen)>> 8) & 0xff);		/* Issue TX polling command */		tempdata = ior(pDrvCtrl, DMFE_TCR);		iow(pDrvCtrl, DMFE_TCR, tempdata|TCR_TXREQ);	/* Cleared after TX complete */	while(ior(pDrvCtrl, DMFE_TCR) & 0x1);		/* free this MBLK */	netMblkClChainFree (pMblk); 	if(freeFlag)		free(data_ptr);		/* Re-enable interrupt */	iow(pDrvCtrl, DMFE_IMR, reg_value); 	END_TX_SEM_GIVE (&pDrvCtrl->endObj);	/*	iow(pDrvCtrl, DMFE_IMR, IMR_PAR | IMR_PTM | IMR_PRM); */	return OK;}static voiddmfe_shutdown(DM9000_END_DEVICE *pDrvCtrl){	/* RESET devie */	dmfe_phy_write(pDrvCtrl, 0, MII_BMCR, BMCR_RESET);	/* PHY RESET */	iow(pDrvCtrl, DMFE_GPR, 0x01);	/* Power-Down PHY */	iow(pDrvCtrl, DMFE_IMR, IMR_PAR);	/* Disable all interrupt */	iow(pDrvCtrl, DMFE_RCR, 0x00);	/* Disable RX */}/*  Stop the interface.  The interface is stopped when it is brought.*/static intdmfe_stop(DM9000_END_DEVICE *pDrvCtrl){	dmfe_shutdown(pDrvCtrl);	return 0;}/*  DM9000 interrupt handler  receive the packet to upper layer, free the transmitted packet*/voiddmfe_tx_done(DM9000_END_DEVICE *pDrvCtrl){	int tx_status = ior(pDrvCtrl, DMFE_NSR);	/* Got TX status *//*读网络状态寄存器*/	if (tx_status & 0xc) 		{					}		}static voiddmfe_interrupt(DM9000_END_DEVICE *pDrvCtrl){	int int_status;	u8 reg_save, reg_save1;	/* Save previous register address */	reg_save = DM9000_inb(pDrvCtrl->ioaddr);	/* Disable all interrupts */	reg_save1 = ior(pDrvCtrl, DMFE_IMR);/*读出中断屏蔽寄存器内容*/	iow(pDrvCtrl, DMFE_IMR, IMR_PAR);/*使能SRAM读写指针*/	/* Got DM9000 interrupt status */	int_status = ior(pDrvCtrl, DMFE_ISR);	/* Got ISR *//*读中断状态寄存器*/	iow(pDrvCtrl, DMFE_ISR, int_status);	/* Clear ISR status *//*写中断状态寄存器*/	/* Received the coming packet */	if (int_status & ISR_PRS)/*包接收*/	{/*		logMsg("rx\n\r",1,2,3,4,5,6); */		netJobAdd ((FUNCPTR) dmfe_rx, (int) pDrvCtrl, 0, 0, 0, 0);		iow(pDrvCtrl, DMFE_IMR, reg_save1&(~IMR_PRM)); /*关闭包接收中断*/				goto intr_end;	}       	/* Trnasmit Interrupt check */	if (int_status & ISR_PTS)/*包发送*/	{/*		logMsg("tx\n\r",1,2,3,4,5,6); */		dmfe_tx_done(pDrvCtrl);	}	iow(pDrvCtrl, DMFE_IMR, reg_save1);/*恢复中断屏蔽寄存器内容*/intr_end:	/* Restore previous register address */	DM9000_outb(reg_save, pDrvCtrl->ioaddr);}/* *  Received a packet and pass to upper layer */static voiddmfe_rx(DM9000_END_DEVICE *pDrvCtrl){	char *		pCluster ;	u8 rxbyte;	u16 i, RxStatus, RxLen, GoodPacket, tmplen;#ifdef DM9000_DWORD_MODE	u32 tmpdata;#endif	u8 reg_save1;	reg_save1 = ior(pDrvCtrl, DMFE_IMR);/*读中断屏蔽寄存器*/	/* Check packet ready or not */	do {		ior(pDrvCtrl, DMFE_MRCMDX);	/* Dummy read */			/* Get most updated data */		rxbyte = DM9000_inb(pDrvCtrl->io_data);				/* Status check: this byte must be 0 or 1 */		if (rxbyte > DM9000_PKT_RDY) {			iow(pDrvCtrl, DMFE_RCR, 0x00);	/* Stop Device *//*接收计数寄存器写0*/			iow(pDrvCtrl, DMFE_ISR, IMR_PAR);	/* Stop INT request *//*设置io模式为8位模式*/			printf("status check failed: %d\n", rxbyte);			iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM);			return;		}				if (rxbyte != DM9000_PKT_RDY)		{			iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM);/*使能包接收中断*/			return;		}				/* A packet ready now  & Get status/length */		GoodPacket = TRUE;		DM9000_outb(DMFE_MRCMD, pDrvCtrl->ioaddr);/*读内存数据指令,地址自增*/#ifdef DM9000_BYTE_MODE		RxStatus = DM9000_inb(pDrvCtrl->io_data) +		          (DM9000_inb(pDrvCtrl->io_data) << 8);		RxLen = DM9000_inb(pDrvCtrl->io_data) +		        (DM9000_inb(pDrvCtrl->io_data) << 8);#elif defined DM9000_WORD_MODE		RxStatus = DM9000_inw(pDrvCtrl->io_data);		RxLen = DM9000_inw(pDrvCtrl->io_data);#elif defined DM9000_DWORD_MODE		tmpdata = DM9000_inl(pDrvCtrl->io_data);		RxStatus = tmpdata;		RxLen = tmpdata >> 16;#endif		/* Packet Status check */		if (RxLen < 0x40) {/*如果包长小于64,坏包*/			GoodPacket = FALSE;			printf("Baaaad Packet received\n");		}		if (RxLen > DM9000_PKT_MAX) {			printf("RST: RX Len:%x\n", RxLen);					}		if (RxStatus & 0xbf00) {			GoodPacket = FALSE;			if (RxStatus & 0x100) {				printf("fifo error\n");							}			if (RxStatus & 0x200) {				printf("crc error\n");							}			if (RxStatus & 0x8000) {				printf("length error\n");							}		}		/* Move data from DM9000 */				if (GoodPacket		    && (pCluster = netClusterGet (pDrvCtrl->endObj.pNetPool,pDrvCtrl->pClPoolId)) )		    {			/* Read received packet from RX SRAM */			dmfe_mx1_ins( pDrvCtrl->io_data, pCluster, RxLen);						dm9000Recv(pDrvCtrl, pCluster,RxLen); 						} else {#ifdef DM9000_BYTE_MODE			for (i = 0; i < RxLen; i++)				DM9000_inb(pDrvCtrl->io_data);#elif defined DM9000_WORD_MODE			tmplen = (RxLen + 1) / 2;			for (i = 0; i < tmplen; i++)				DM9000_inw(pDrvCtrl->io_data);#elif defined DM9000_DWORD_MODE			tmplen = (RxLen + 3) / 4;			for (i = 0; i < tmplen; i++)				DM9000_inl(pDrvCtrl->io_data);#endif		}}while (rxbyte == DM9000_PKT_RDY);		/* Re-enable interrupt mask */	iow(pDrvCtrl, DMFE_IMR, reg_save1| IMR_PRM);}/* *  Read a word data from SROM */static u16read_srom_word(DM9000_END_DEVICE *pDrvCtrl, int offset){	iow(pDrvCtrl, DMFE_EPAR, offset);	iow(pDrvCtrl, DMFE_EPCR, EPCR_ERPRR);	taskDelay(8);		/* according to the datasheet 200us should be enough,				   but it doesn't work */	iow(pDrvCtrl, DMFE_EPCR, 0x0);	return (ior(pDrvCtrl, DMFE_EPDRL) + (ior(pDrvCtrl, DMFE_EPDRH) << 8));}/* *  Set DM9000 multicast address */static voiddm9000_hash_table(DM9000_END_DEVICE *pDrvCtrl){	u16 i, oft, hash_table[4];   /*    MULTI_TABLE *	mcptr = */	   		for (i = 0, oft = 0x10; i < 6; i++, oft++)/*写物理地址寄存器*/		iow(pDrvCtrl, oft, pDrvCtrl->enetAddr[i]);	/* 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++) {/*wriet muticast address register*/		iow(pDrvCtrl, oft++, hash_table[i] & 0xff);		iow(pDrvCtrl, oft++, (hash_table[i] >> 8) & 0xff);	}}/* *   Read a byte from I/O port */static u8ior(DM9000_END_DEVICE *pDrvCtrl, int reg){	DM9000_outb(reg, pDrvCtrl->ioaddr);	return DM9000_inb(pDrvCtrl->io_data);}static u8ior1( int reg){	DM9000_outb(reg, CONFIG_DM9K_BASE);	return DM9000_inb(CONFIG_DM9K_BASE+4);}/* *   Write a byte to I/O port */static voidiow(DM9000_END_DEVICE *pDrvCtrl, int reg, int value){	DM9000_outb(reg, pDrvCtrl->ioaddr);	DM9000_outb(value, pDrvCtrl->io_data);}void dm9000Read(int reg){	UINT8 value;		value = ior(temp, reg);	printf("reg 0x%x = 0x%x\n\r", reg, value);	}void dm9000Read1(int reg){	UINT8 value;		value = ior1(reg);	printf("reg 0x%x = 0x%x\n\r", reg, value);	}void dm9kReadAll(void){	int i;	for(i=0;i<0x100;i++)	{		dm9000Read(i);	}}void dm9kReadAll1(void){	int i;	for(i=0;i<0x100;i++)	{		dm9000Read1(i);	}}void dm9000Write(int reg, int value){	iow(temp, reg, value);}/* *   Read a word from phyxcer */static intdmfe_phy_read(DM9000_END_DEVICE *pDrvCtrl, int phy_reg_unused, int reg){	UINT8 value;		/* Fill the phyxcer register into REG_0C */	iow(pDrvCtrl, DMFE_EPAR, DM9000_PHY | reg);	iow(pDrvCtrl, DMFE_EPCR, 0xc);	/* Issue phyxcer read command */	value = ior(pDrvCtrl, DMFE_EPCR);	while(value & 0x1)                         /* Wait read complete */	{		taskDelay(1);		value = ior(pDrvCtrl, DMFE_EPCR);		}			iow(pDrvCtrl, DMFE_EPCR, 0x8);	/* Clear phyxcer read command */	/* The read data keeps on REG_0D & REG_0E */	return (ior(pDrvCtrl, DMFE_EPDRH) << 8) | ior(pDrvCtrl, DMFE_EPDRL);}void dm9k_phy_read(int reg){	int value;		value = dmfe_phy_read(temp, 0 , reg);	printf("phy addr 0x%x = 0x%x\n\r", reg, value);}/* *   Write a word to phyxcer */static voiddmfe_phy_write(DM9000_END_DEVICE *pDrvCtrl, int phyaddr_unused, int reg, int value){	/* Fill the phyxcer register into REG_0C */	iow(pDrvCtrl, DMFE_EPAR, DM9000_PHY | reg);	/* Fill the written data into REG_0D & REG_0E */	iow(pDrvCtrl, DMFE_EPDRL, (value & 0xff));	iow(pDrvCtrl, DMFE_EPDRH, ((value >> 8) & 0xff));	iow(pDrvCtrl, DMFE_EPCR, 0xa);	/* Issue phyxcer write command */	value = ior(pDrvCtrl, DMFE_EPCR);		/* Wait write complete */	while(value & 0x1)	{		taskDelay(1);		value = ior(pDrvCtrl, DMFE_EPCR);		}	iow(pDrvCtrl, DMFE_EPCR, 0x8);	/* Clear phyxcer write command */}static voiddmfe_mx1_ins(u_long ioaddr, u_char * buf, int len){	u16 tmplen, i;	u32 tempdata;		tmplen = (len + 3) / 4;	for (i = 0; i < tmplen; i++)	{		tempdata = *((volatile u32*)((u32)ioaddr));		memcpy(buf+2+i*sizeof(tempdata), &tempdata, sizeof(tempdata));	}}#endif

⌨️ 快捷键说明

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