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

📄 dm9kend.c

📁 AT91RM9200 BSP with dual ethernet port
💻 C
📖 第 1 页 / 共 4 页
字号:
LOCAL STATUS dm9kSend    (    DM9K_DRV_CTRL * 	pDrvCtrl,  /* device to be initialized */    M_BLK_ID 		pMblk      /* data to send */    )    {    char *       	pBuf;    UINT16			    index,i;    UINT16        	len = 0,tmpLen;       /* check device mode */       if (pDrvCtrl->flags & DM9K_POLLING)        {        netMblkClChainFree (pMblk);        errno = EINVAL;        return (ERROR);        }	  /*     * Obtain exclusive access to transmitter.  This is necessary because     * we might have more than one stack transmitting at once.     */    END_TX_SEM_TAKE (&pDrvCtrl->endObj, WAIT_FOREVER);    /* Advance our management index (first) */    index = pDrvCtrl->tmdIndex;	    pBuf = (char *)(pDrvCtrl->pTxMemBase);   if (pBuf == NULL)        { 		DRV_LOG (DRV_DEBUG_TX, "Error\n", (int)pBuf, index, 3, 4, 5, 6);		pDrvCtrl->txBlocked = TRUE;        END_TX_SEM_GIVE (&pDrvCtrl->endObj);        return (END_ERR_BLOCK);        }    /* copy and release the packet */    len = netMblkToBufCopy (pMblk, pBuf, NULL);    netMblkClChainFree (pMblk);	   /* flush the cache, if necessary */    CACHE_DMA_FLUSH(pBuf, len);    if (len < ETHERSMALL)	{	/* Pad to ETHERSMALL with zeros, required by H/W */	bzero (&pBuf[len], ETHERSMALL - len);	len = ETHERSMALL;	}	/* Disable all interrupt */	regWriteByte(DM9KS_IMR, DM9KS_DISINTR); 	/*----------------------------------------------*/								/* Write data into SRAM trigger */	OUT_WORD(DM9KS_ADDR_PORT, DM9KS_MWCMD);//	udelay(10);	tmpLen = (len + 1) / 2;	for (i = 0; i < tmpLen; i++)		{			OUT_WORD(DM9KS_DATA_PORT, ((UINT16 *)pBuf)[i]);			}		/* Set TX length to reg. 0xfc & 0xfd */	regWriteByte(DM9KS_TXPLL, (len & 0xff));	regWriteByte(DM9KS_TXPLH, (len >> 8) & 0xff);	/* Request for transmitting */	regWriteByte(DM9KS_TCR, 0x1); /* Cleared after TX complete*/			/* Re-enable interrupt */	regWriteByte(DM9KS_IMR, DM9KS_REGFF);	/*----------------------------------------------*/         /* Advance our management index */    index = (pDrvCtrl->tmdIndex + 1) & (pDrvCtrl->tringSize - 1);    pDrvCtrl->tmdIndex = index;      		pDrvCtrl->tmdLastIndex = (pDrvCtrl->tmdLastIndex + 1) &					 (pDrvCtrl->tringSize - 1);    /* Bump the statistic counter. */    END_ERR_ADD (&pDrvCtrl->endObj, MIB2_OUT_UCAST, +1);    END_TX_SEM_GIVE (&pDrvCtrl->endObj);    DRV_LOG (DRV_DEBUG_TX, "dm9kSend Done\n", 1, 2, 3, 4, 5, 6);    return (OK);    }/********************************************************************************* dm9kIoctl - the driver I/O control routine** Process an ioctl request.** RETURNS OK or ERROR value*/LOCAL int dm9kIoctl    (    DM9K_DRV_CTRL * 	pDrvCtrl, /* device to be initialized */    int 		        cmd,	  /* ioctl command to execute */    caddr_t 		    data	  /* data to get or set       */    )    {    long 		value;    int 		error = 0;    switch (cmd)        {        case EIOCSADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->endObj),		   END_HADDR_LEN (&pDrvCtrl->endObj));            break;        case EIOCGADDR:	    if (data == NULL)		return (EINVAL);            bcopy ((char *)END_HADDR (&pDrvCtrl->endObj), (char *)data,		    END_HADDR_LEN (&pDrvCtrl->endObj));            break;        case EIOCSFLAGS:	    value = (long)data;            	    if (value < 0)		{		value = -value;		value--;		/* HELP: WHY ??? */		END_FLAGS_CLR (&pDrvCtrl->endObj, value);		}	    else		{		END_FLAGS_SET (&pDrvCtrl->endObj, value);		}	    dm9kConfig (pDrvCtrl);            break;        case EIOCGFLAGS:	    *(int *)data = END_FLAGS_GET (&pDrvCtrl->endObj);            break;        case EIOCMULTIADD:            error = dm9kMCastAddrAdd (pDrvCtrl, (char *) data);            break;        case EIOCMULTIDEL:            error = dm9kMCastAddrDel (pDrvCtrl, (char *) data);            break;        case EIOCMULTIGET:            error = dm9kMCastAddrGet (pDrvCtrl, (MULTI_TABLE *) data);            break;	case EIOCPOLLSTART:	    error = dm9kPollStart (pDrvCtrl);	    break;	case EIOCPOLLSTOP:	    error = dm9kPollStop (pDrvCtrl);	    break;        case EIOCGMIB2:            if (data == NULL)                return (EINVAL);            bcopy((char *)&pDrvCtrl->endObj.mib2Tbl, (char *)data,                  sizeof(pDrvCtrl->endObj.mib2Tbl));            break;        case EIOCGFBUF:            if (data == NULL)                return (EINVAL);            *(int *)data = DM9K_MIN_FBUF;            break;        case EIOCGMWIDTH:            if (data == NULL)                return (EINVAL);            *(int *)data = 4;            break;        case EIOCGHDRLEN:            if (data == NULL)                return (EINVAL);            *(int *)data = 14;            break;        default:            error = EINVAL;        }    return (error);    }/********************************************************************************* dm9kReset - hardware reset of chip (stop it)** This routine is responsible for resetting the device and switching into* 32 bit mode.** RETURNS: OK/ERROR*/LOCAL int dm9kReset    (    DM9K_DRV_CTRL * 	pDrvCtrl /* device to be initialized */    )    {             DRV_LOG (DRV_DEBUG_LOAD, "dm9kReset\n", 1, 2, 3, 4, 5, 6);    /* setup Rx memory pointers */    pDrvCtrl->rmdIndex = 0;   	    /* setup Tx memory pointers */    pDrvCtrl->tmdIndex = 0;    pDrvCtrl->tmdLastIndex = 0;	   /* SYS_WB_FLUSH();*/    return (OK);    }/********************************************************************************* dm9kRestartSetup - setup memory descriptors and turn on chip** This routine initializes all the shared memory structures and turns on* the chip.** RETURNS OK/ERROR*/LOCAL STATUS dm9kRestartSetup    (    DM9K_DRV_CTRL * 	pDrvCtrl /* device to be initialized */    )    {      DRV_LOG (DRV_DEBUG_LOAD, "dm9kRestartSetup\n", 1, 2, 3, 4, 5, 6);    /* reset the device */    dm9kReset (pDrvCtrl);    DRV_LOG (DRV_DEBUG_LOAD, "Memory setup complete\n", 1, 2, 3, 4, 5, 6);    /* reconfigure the device */    dm9kConfig (pDrvCtrl);    return (OK);    }/********************************************************************************* dm9kRestart - restart the device after a fatal error** This routine takes care of all the messy details of a restart.  The device* is reset and re-initialized.  The driver state is re-synchronized.** RETURNS: N/A*/LOCAL void dm9kRestart    (    DM9K_DRV_CTRL * 	pDrvCtrl /* device to be initialized */    )    {    dm9kRestartSetup (pDrvCtrl);    /* set the flags to indicate readiness */    END_OBJ_READY (&pDrvCtrl->endObj,                    IFF_UP | IFF_RUNNING | IFF_NOTRAILERS | IFF_BROADCAST                    | IFF_MULTICAST);    return;    }/*----------------------------------------** Set PHY operationg mode*/	static void dm9k_set_PHY_mode(DM9K_DRV_CTRL * 	pDrvCtrl)	{		/* Auto-negotiation & Restart Auto-negotiation */		UINT16 phy_reg0 = 0x1200;		/* Default flow control disable*/		UINT16 phy_reg4 = 0x01e1;			if ( !(pDrvCtrl->op_mode & DM9KS_AUTO) ) // op_mode didn't auto sense */		{ 			switch(pDrvCtrl->op_mode) {				case DM9KS_10MHD:  phy_reg4 = 0x21; 										   phy_reg0 = 0x1000;						   break;				case DM9KS_10MFD:  phy_reg4 = 0x41; 						   phy_reg0 = 0x1100;										   break;				case DM9KS_100MHD: phy_reg4 = 0x81; 						   phy_reg0 = 0x3000;							   break;				case DM9KS_100MFD: phy_reg4 = 0x101; 						   phy_reg0 = 0x3100;						   break;				default: 						   break;			} // end of switch		} // end of if			phy_write(0, phy_reg0);		phy_write(4, phy_reg4);	}/******************************************************************************** dm9kConfig - reconfigure the interface under us.** Reconfigure the interface setting promiscuous mode, and changing the* multicast interface list.** RETURNS: N/A*/LOCAL void dm9kConfig    (    DM9K_DRV_CTRL * 	pDrvCtrl /* device to be initialized */    )    {    	UINT8	i;    DRV_LOG (DRV_DEBUG_LOAD, "dm9kConfig\n", 1, 2, 3, 4, 5, 6);    /* Set promiscuous mode if it's asked for. */    if (END_FLAGS_GET (&pDrvCtrl->endObj) & IFF_PROMISC)        {        DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode on!\n",                 1, 2, 3, 4, 5, 6);        /* chip will be in promiscuous mode */        pDrvCtrl->flags |= DM9K_PROMISCUOUS_FLAG;         }    else        {        DRV_LOG (DRV_DEBUG_LOAD, "Setting promiscuous mode off!\n",                 1, 2, 3, 4, 5, 6);        pDrvCtrl->flags &= ~DM9K_PROMISCUOUS_FLAG;         }    /* Set up address filter for multicasting. */    if (END_MULTI_LST_CNT (&pDrvCtrl->endObj) > 0)        {        dm9kAddrFilterSet (pDrvCtrl);        }	      /* Enable transmit and receive */	regWriteByte(DM9KS_GPCR, 1);	/* set the internal PHY power-on, GPIOs normal, and wait 2ms */	regWriteByte(DM9KS_GPR, 1); 	/* Power-Down PHY */	udelay(50);	regWriteByte(DM9KS_GPR, 0);	/* GPR (reg_1Fh)bit GPIO0=0 pre-activate PHY */	udelay(50);		/* wait 2ms for PHY power-on ready */	/* do a software reset and wait 20us */	regWriteByte(DM9KS_NCR, 3);	udelay(50);		/* wait 20us at least for software reset ok */	regWriteByte(DM9KS_NCR, 3);	/* NCR (reg_00h) bit[0] RST=1 & Loopback=1, reset on */	udelay(50);		/* wait 20us at least for software reset ok */	/* I/O mode */		pDrvCtrl->io_mode = regReadByte(DM9KS_ISR) >> 6; /* ISR bit7:6 keeps I/O mode */		/* Set PHY */	pDrvCtrl->op_mode = media_mode;		dm9k_set_PHY_mode(pDrvCtrl);	/* set MAC address in PAR register */        /* added by HL */	for (i=0;i<6;i++)		{		regWriteByte(DM9KS_PAR0+i,pDrvCtrl->enetAddr[i]);		}		/* Program operating register */	regWriteByte(DM9KS_OTCR, 0x80);    regWriteByte(DM9KS_NCR, 0); 	regWriteByte(DM9KS_TCR, 0x0);		/* !!!disable PAD CRC appends  */	regWriteByte(DM9KS_TCR2, 0x80);	/* LED mode 2 */	regWriteByte(DM9KS_BPTR, 0x3f);	/* Less 3kb, 600us */	regWriteByte(DM9KS_SMCR, 0);		/* Special Mode disabled */	regReadByte(DM9KS_NSR);	/* clear TX status */	regWriteByte(DM9KS_ISR, 0x0f); 	/* Clear interrupt status */   return;    }/******************************************************************************** dm9kAddrFilterSet - set the address filter for multicast addresses** This routine goes through all of the multicast addresses on the list* of addresses (added with the dm9kAddrAdd() routine) and sets the* device's filter correctly.** RETURNS: N/A*/LOCAL void dm9kAddrFilterSet    (    DM9K_DRV_CTRL * 	pDrvCtrl /* device to be initialized */    )    {    ETHER_MULTI * 	pCurr;    UINT8 *		pCp;    UINT8 		byte;    UINT32 		crc;    int 		len;    int 		count;	UINT32 hash_val;	UINT16 i, oft, hash_table[4];		/* Set Node address */	for (i = 0, oft = DM9KS_PAR0; i < 6; i++, oft++)		regWriteByte(oft, pDrvCtrl->enetAddr[i]);	/* Clear Hash Table */	for (i = 0; i < 4; i++)		hash_table[i] = 0x0;	/* broadcast address */	hash_table[3] = 0x8000;    pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->endObj);    while (pCurr != NULL)	{	pCp = (UINT8 *)&pCurr->addr;	crc = 0xffffffff;	for (len = DM9K_LA_LEN; --len >= 0;)	    {	    byte = *pCp++;            for (count = 0; count < DM9K_LAF_LEN; count++)		{		if ((byte & 0x01) ^ (crc & 0x01))		    {		    crc >>= 1;		    crc = crc ^ DM9K_CRC_POLYNOMIAL;		    }		else		    {		    crc >>= 1;		    }		byte >>= 1;		}	    }	hash_val = crc & 0x3f;	hash_table[hash_val/16] = (UINT16) 1 << (hash_val %16);          /* can be dangerous */

⌨️ 快捷键说明

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