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

📄 dm9000end.c

📁 基于s3c2440和vxworks的dm9000驱动代码
💻 C
📖 第 1 页 / 共 5 页
字号:
* RETURNS: OK or ERROR.
*/

static STATUS dm9000Stop( END_DEVICE *pDrvCtrl )     /* device to be stopped */
{
    STATUS result = OK;

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Stop()", 1, 2, 3, 4, 5, 6);

    /* TODO - stop/disable the device. */
    dmfe_stop_dm9000( pDrvCtrl );

    /*cljG  mask INTR7 for dm9000*/    
    cpuForDm9000disable();    
    
    /*sysEndIsrLink.arg = (int)pDrvCtrl;*/
    SYS_INT_DISCONNECT (pDrvCtrl, dm9000Int, &result);
    if (result == ERROR)
    {
        DRV_LOG (DRV_DEBUG_STATUS, "Could not disconnect interrupt!",
            1, 2, 3, 4, 5, 6);            
    }
     
    return (result);
}

/******************************************************************************
*
* dm9000Unload - unload a driver from the system
*
* This function first brings down the device, and then frees any
* stuff that was allocated by the driver in the load function.
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000Unload( END_DEVICE *pDrvCtrl )   /* device to be unloaded */
{
    DRV_LOG (DRV_DEBUG_NO, "dm9000Unload()", 1, 2, 3, 4, 5, 6);

    END_OBJECT_UNLOAD (&pDrvCtrl->end);

    /* TODO - Free any shared DMA memory */

    return (OK);
}

/*******************************************************************************
*
* dm9000PollStart - start polled mode operations
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000PollStart( END_DEVICE *pDrvCtrl )    /* device to be polled */
{
    int         oldLevel;

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000PollStart()", 1, 2, 3, 4, 5, 6);
    oldLevel = intLock ();          /* disable ints during update */

    /* TODO - turn off interrupts */

    (pDrvCtrl->flags) |= DM9000_POLLING;

    dm9000Reset( pDrvCtrl );
    dm9000Config( pDrvCtrl );       /* reconfigure device */

    intUnlock (oldLevel);   /* now dm9000Int won't get confused */

    DRV_LOG (DRV_DEBUG_POLL, "STARTED", 1, 2, 3, 4, 5, 6);


    return (OK);
}

/*******************************************************************************
*
* dm9000PollStop - stop polled mode operations
*
* This function terminates polled mode operation.  The device returns to
* interrupt mode.
*
* The device interrupts are enabled, the current mode flag is switched
* to indicate interrupt mode and the device is then reconfigured for
* interrupt operation.
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000PollStop( END_DEVICE *pDrvCtrl ) /* device to be polled */
{
    int         oldLevel;

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000PollStop()", 1, 2, 3, 4, 5, 6);

    oldLevel = intLock ();  /* disable ints during register updates */

    /* TODO - re-enable interrupts */

    (pDrvCtrl->flags) &= ~DM9000_POLLING;

    dm9000Reset( pDrvCtrl );
    dm9000Config( pDrvCtrl );       /* reconfigure device */

    intUnlock (oldLevel);

    DRV_LOG (DRV_DEBUG_POLL, "STOPPED", 1, 2, 3, 4, 5, 6);

    return (OK);
}

/*******************************************************************************
*
* dm9000Reset - reset device
*
* RETURNS: N/A.
*/

static void dm9000Reset( END_DEVICE *pDrvCtrl )
{
    /* TODO - reset the controller */
    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Reset()", 1, 2, 3, 4, 5, 6);
    dmfe_reset_dm9000( pDrvCtrl );
}

/*******************************************************************************
*
* dm9000StatusRead - get current device state/status
*
* RETURNS: status bits.
*/

static UINT dm9000StatusRead( END_DEVICE *pDrvCtrl )
{
    /* TODO - read and return status bits/register */
    UINT retv = 0;
    UCHAR status = 0;
    UCHAR rxbyte = 0;

    DM9000_IN_CHAR( 0xfe, status );
    DM9000_IN_CHAR( 0xf0, rxbyte ); /* Dummy read */
    DM9000_IN_CHAR( 0xf0, rxbyte ); /* Got most updated data */

    if( !((pDrvCtrl->flags) & DM9000_POLLING) )       
        retv |= DM9000_RXON;

    if( status & 0x01 )
        retv |= DM9000_RINT;

    if( status & 0x02 )
        retv |= DM9000_TINT;

    if( pDrvCtrl->tx_pkt_cnt > 2 )                  
        retv |= DM9000_TFULL;

    if( rxbyte == DM9000_PKT_RDY )
        retv |= DM9000_RXRDY;
    return (retv);
}

static void dmfe_reset_dm9000( END_DEVICE *dev )
{
    UWORD enaddr;
    UCHAR tmp;
    int i;

    DRV_LOG (DRV_DEBUG_LOAD, "dmfe_reset_dm9000()", 1, 2, 3, 4, 5, 6);
    DM9000_OUT_CHAR( 0x00, 0x03 );    
    taskDelay(1);
    DM9000_OUT_CHAR( 0x00, 0x03 );              
    taskDelay(1);
	
		for(i=0;i<6;i++)
		{
			dev->enetAddr[i] = DM9KDefaultMacAddr[i];
		} 
   

    DRV_LOG (DRV_DEBUG_LOAD, "netAddress",
            dev->enetAddr[0],
            dev->enetAddr[1],
            dev->enetAddr[2],
            dev->enetAddr[3],
            dev->enetAddr[4],
            dev->enetAddr[5] );

    /* I/O mode */
    DM9000_IN_CHAR( 0xfe, tmp );
    dev->io_mode = (tmp & 0xff) >> 6;        /* ISR bit7:6 keeps I/O mode */

    /* NIC Type: FASTETHER, HOMERUN, LONGRUN */
   /* identify_nic( dev );*/

    /* Set PHY */
    set_PHY_mode( dev );

    DM9000_OUT_CHAR( 0xff, DM9000_REGFF_OFF );  /* disable TX/RX interrupt mask */
    DM9000_OUT_CHAR( 0x05, DM9000_REG05_OFF);  /* RX disable */

}


static void dmfe_config_dm9000( END_DEVICE *dev, int oo)
{
    DRV_LOG (DRV_DEBUG_LOAD, "dmfe_config_dm9000()", 1, 2, 3, 4, 5, 6);

    /* Program operating register */
    DM9000_OUT_CHAR( 0xff, DM9000_REGFF_OFF ); /* Enable FIFO chain */
    DM9000_OUT_CHAR( 0x00, dev->reg0 );
    DM9000_OUT_CHAR( 0x02, 0x00 );         /* TX Polling clear */
    DM9000_OUT_CHAR( 0x08, DM9000_REG08 ); /* Less 3Kb, 200us */
    DM9000_OUT_CHAR( 0x09, DM9000_REG09 ); /* Flow Control : High/Low Water */
    DM9000_OUT_CHAR( 0x0a, DM9000_REG0A ); /* Flow Control */
    DM9000_OUT_CHAR( 0x2f, 0x00);       /* Special Mode */
    DM9000_OUT_CHAR( 0x01, 0x2c);       /* clear TX status */
    DM9000_OUT_CHAR( 0xfe, 0x0f);       /* Clear interrupt status */
  /*  DM9000_OUT_CHAR( 0x2d, 0x80); */      /* LED mode setting */

    /* Set address filter table */
    /* Set Physical Address Register */
    /* Set Multicast Address Register */
    dm9000_hash_table( dev );

    if( oo == 2 )
    {
        /* Activate DM9000 */
        DM9000_OUT_CHAR( 0x05, DM9000_REG05 );      /* RX enable */
        DM9000_OUT_CHAR( 0xff, DM9000_REGFF );      /* Enable TX/RX interrupt mask */
    }
    if( oo == 1 )
    {
        /* Activate DM9000 */
        DM9000_OUT_CHAR( 0x05, DM9000_REG05_OFF );  /* RX disable */
        DM9000_OUT_CHAR( 0xff, DM9000_REGFF_OFF );  /* disable TX/RX interrupt mask */
    }

    /* Init Driver variable */
    dev->tx_pkt_cnt = 0;
    dev->device_wait_reset = 0;

    taskDelay(1);
}

/* Hardware start transmission.
   Send a packet to media from the upper layer.
*/
static int dmfe_start_xmit( PKT *skb, END_DEVICE *dev)
{ 
    char *data_ptr;    
    int i, oldv;
    unsigned char imr=0;
    int tmplen;
    UWORD  tmpdata;
    UCHAR  regsave;   

    DRV_LOG (DRV_DEBUG_TX, "dmfe_start_xmit()", 1, 2, 3, 4, 5, 6);
    DRV_SP( DRV_PK,"." );
        	
    if( (skb->len == 0) || (skb->pData == NULL) )
    {
        DRV_LOG (DRV_DEBUG_STATUS,"len == 0 || pData == NULL", 1, 2, 3, 4, 5, 6);
        return 2;
    }

    /* Resource flag check */
    if( dev->tx_pkt_cnt >= 2)
    {
        DRV_LOG (DRV_DEBUG_STATUS,"tx full", dev->tx_pkt_cnt, 2, 3, 4, 5, 6); 
        DM9000_IN_CHAR( 2, regsave );     
        return 1;
    }    		
	
    /* Move data to DM9000 TX RAM */
    data_ptr = (char *)skb->pData; 
    
    DM9000_OUT_ADDR( 0xf8 );
    if( dev->io_mode == 2 )
    {
        /* Byte mode */
        for( i = 0; i < skb->len; i++ )
            DM9000_OUT_BYTE( (data_ptr[i] & 0xff) );
    }
    else
    {
        /* Word mode */
        tmplen = (skb->len + 1) / 2;
        for( i = 0; i < tmplen; i++ )
        {
           DM9000_OUT_WORD( ((UWORD *)data_ptr)[i] );
        }
    }
    /* TX control: First packet immediately send, second packet queue */
		if (dev->tx_pkt_cnt == 0) 
    {    	
	    /* First Packet */
	    dev->tx_pkt_cnt ++;
	    /* Set TX length to DM9000 */
	    DM9000_OUT_CHAR( 0xfc, skb->len & 0xff );
	    DM9000_OUT_CHAR( 0xfd, (skb->len >> 8) & 0xff );
	
	    /* Issue TX polling command */
	    DM9000_OUT_CHAR( 0x2, 0x01 );        /* Cleared after TX complete */
    }
    else /* Second packet */
    {
    	    dev->queue_pkt_len = skb->len;
    	    dev->tx_pkt_cnt ++;
    }  
    return 0;
}
/* Received a packet and pass to upper layer
 * return 0  good
 * return 1  bad data
 * return 2  need reset
 */
static int dmfe_packet_receive( PKT *skb, END_DEVICE *dev )
{
    UCHAR tmp1,tmp2;
    UWORD tmp3;
    UCHAR rxbyte;
    UCHAR *rdptr;
    UWORD i, RxStatus, RxLen, GoodPacket, tmplen;
    int   oldv;


    DRV_LOG (DRV_DEBUG_NO, "dmfe_packet_receive()", 1, 2, 3, 4, 5, 6);
    /*oldv=INT_LOCK();*/

    /* Check packet ready or not */
    DM9000_IN_CHAR( 0xf0, rxbyte ); /* Dummy read */
    DM9000_IN_CHAR( 0xf0, rxbyte ); /* Got most updated data */

    /* Status check: this byte must be 0 or 1 */
    if( rxbyte > DM9000_PKT_RDY )
    {
        DM9000_OUT_CHAR( 0x05, DM9000_REG05_OFF);   /* Stop Device */
        DM9000_OUT_CHAR( 0xff, DM9000_REGFF_OFF);   /* Stop Device */

        /* dev->device_wait_reset = 1; */
        
        DRV_LOG (DRV_DEBUG_RX,"rx need reset", 1, 2, 3, 4, 5, 6);
        dm9000Reset( dev );
        dm9000Config( dev );
      /*  INT_UNLOCK(oldv);*/
        return 2;
    }

    /* packet ready to receive check */
    if( rxbyte == DM9000_PKT_RDY )
    {
        /* A packet ready now  & Get status/length */
        GoodPacket = 1;
        if( dev->io_mode == 2 )
        {
            /* Byte mode */
            DM9000_IN_CHAR( 0xf2, tmp1 );
            DM9000_IN_CHAR( 0xf2, tmp2 );
            RxStatus = tmp1 + (tmp2 << 8);

            DM9000_IN_CHAR( 0xf2, tmp1 );
            DM9000_IN_CHAR( 0xf2, tmp2 );
            RxLen = tmp1 + (tmp2<<8);
        }
        else
        {
            /* Word mode */
            DM9000_OUT_ADDR( 0xf2 );
            DM9000_IN_WORD( RxStatus );
            DM9000_IN_WORD( RxLen );
          
        }
        
        if( RxLen < 0x40)
        {
            DRV_LOG (DRV_DEBUG_RX, "packet too small ", 1, 2, 3, 4, 5, 6);
            GoodPacket = 0;
        }
        if( RxLen > DM9000_PKT_MAX )
        {
            DRV_LOG (DRV_DEBUG_RX, "packet too big need reset ", 1, 2, 3, 4, 5, 6);
            dm9000Reset( dev );
            dm9000Config( dev );
            return 2;
        }
       
        if( RxStatus & 0xbf00)
        {
            GoodPacket = 0;
            /*if( RxStatus & 0x100 )   fifo error */
            /*if( RxStatus & 0x200 )   crc error */
            /*if( RxStatus & 0x8000 )  length error */
            DRV_LOG (DRV_DEBUG_RX, "packet error ", RxStatus, 2, 3, 4, 5, 6);
        }

        /* Move data from DM9000 */
        skb->len = 0;
        if( GoodPacket && (skb != NULL) )
        {   /* good packet*/
            skb->len = RxLen;
            rdptr = skb->pData;
            /* Read received packet from RX SARM */
            if (dev->io_mode == 2)
            {
                /* Byte mode */
                for( i=0; i<RxLen; i++ )
                    DM9000_IN_BYTE( rdptr[i] );
            }
            else
            {
                /* Word mode */
                tmplen = (RxLen + 1) / 2;

⌨️ 快捷键说明

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