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

📄 dm9000end.c

📁 DM9000A的VXWORKS下驱动
💻 C
📖 第 1 页 / 共 5 页
字号:
*
* dm9000MCastGet - get the multicast address list for the device
*
* This routine gets the multicast list of whatever the driver
* is already listening for.
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000MCastGet( END_DEVICE *pDrvCtrl,  /* device pointer */
                             MULTI_TABLE *pTable )  /* address table to be filled in */
{
	int error;
 
	error=etherMultiGet (&pDrvCtrl->end.multiList, pTable);
	printf("in dm9000MCastGet the error is %x!\n",error);
	return(error);
	/*
    return (etherMultiGet (&pDrvCtrl->end.multiList, pTable));
	*/
}

/*******************************************************************************
*
* dm9000Stop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/

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


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

    /*sysEndIsrLink.arg = (int)pDrvCtrl;*/
    SYS_INT_DISCONNECT (pDrvCtrl, dm9000Int, &result);

    if (result == ERROR)
    {
    }

    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 */
{

    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;

    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 */


    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;


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

    /* TODO - re-enable interrupts */

    (pDrvCtrl->flags) &= ~DM9000_POLLING;

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

    intUnlock (oldLevel);


    return (OK);
}

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

static void dm9000Reset( END_DEVICE *pDrvCtrl )
{
    /* TODO - reset the controller */
    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;

/*2007-4-11 shengdegang modify*/
    status=DM9000A_read_reg(0xfe);
    rxbyte=DM9000A_read_reg(0xf0);
	/*2007-4-11 shengdegang modify  */
	/*只需读一次F0H*/
/*    rxbyte=DM9000A_read_reg(0xf0);*/
    
/*    DM9000_IN_CHAR( 0xfe, status );
    DM9000_IN_CHAR( 0xf0, rxbyte ); *//* Dummy read */
 /*   DM9000_IN_CHAR( 0xf0, rxbyte );*/ /* Got most updated data */

/*	pDrvCtrl->flags=2;*/
    if( !((pDrvCtrl->flags) & DM9000_POLLING) )		/*2*/      
        retv |= DM9000_RXON;	/*4*/

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

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

    if( pDrvCtrl->tx_pkt_cnt > 1 )                  
        retv |= DM9000_TFULL;	/*8*/

    if( rxbyte == DM9000_PKT_RDY )
        retv |= DM9000_RXRDY;	/*10*/

    return (retv);
}

static void dmfe_reset_dm9000( END_DEVICE *dev )
{
    char status = 1;
    UCHAR tmp;

/*    DM9000_OUT_CHAR( 0x0, 1 );  */
		/*2007-4-11 shengdegang modify*/
    DM9000A_write_reg(0x0, 1);
    while( (status & 1) )                   
    {
        udelay(100);
        /*2007-4-11 shengdegang modify*/
   	 		status=DM9000A_read_reg(0x0);
/*        DM9000_IN_CHAR( 0x0, status );*/
    }
/*read MAC*/   
/*2007-4-4 shengdegang modify*/
	dev->enetAddr[0] = 0x3e;
    dev->enetAddr[1] = 0x01;
    dev->enetAddr[2] = 0x09;
    dev->enetAddr[3] = 0xfe;
    dev->enetAddr[4] = 0x00;
    dev->enetAddr[5] = 0x00;

    /* I/O mode */
    /*2007-4-11 shengdegang modify*/
   	tmp=DM9000A_read_reg(0xfe);
/*    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 );

    /* Init needed register value */
    dev->reg0 = DM9000_REG00;
    if ( (dev->nic_type != FASTETHER_NIC) && (dev->op_mode & DM9000_1M_HPNA) )
        dev->reg0 |= DM9000_EXT_MII;

		/*2007-4-11 shengdegang modify*/
    DM9000A_write_reg(0x05, DM9000_REG05);
    DM9000A_write_reg(0xff, 0x80);

}


static void dmfe_config_dm9000( END_DEVICE *dev, int oo)
{

    /* Program operating register */
    /*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0xff, 0x80);			/* Enable TX/RX interrupt mask */
    	DM9000A_write_reg(0x00, dev->reg0);
    	DM9000A_write_reg(0x02, 0);				/* TX Polling clear */
    	DM9000A_write_reg(0x08, DM9000_REG08);	/* Less 3Kb, 200us */
    	DM9000A_write_reg(0x09, DM9000_REG09);	/* Flow Control : High/Low Water */
    	DM9000A_write_reg(0x0a, DM9000_REG0A);	/* Flow Control */
    	DM9000A_write_reg(0x2f, 0);				/* Special Mode */
    	DM9000A_write_reg(0x01, 0x2c);			/* clear TX status */
    	DM9000A_write_reg(0xfe, 0x0f);			/* Clear interrupt status */    

    /* Set address filter table */
    /* Set Physical Address Register */
    /* Set Multicast Address Register */
	/*2007-4-20 shengdegang add 4-23 remove*/
/*	dm9000AddrFilterSet (dev);*/
	/*end*/
    dm9000_hash_table( dev );

    if( oo == 2 )
    {
        /* Activate DM9000 */
        /*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0x05, DM9000_REG05 | 1);		/* RX enable */
    	DM9000A_write_reg(0xff, DM9000_REGFF);			/* Enable TX/RX interrupt mask */   
    }
    if( oo == 1 )
    {
        /* Activate DM9000 */
        /*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0x05, DM9000_REG05);		/* RX disable */
    	DM9000A_write_reg(0xff, 0x80);				/* disable TX/RX interrupt mask */         
    }

    /* Init Driver variable */
    dev->tx_pkt_cnt = 0;
    dev->device_wait_reset = 0;
	/*2007-4-20 shengdegang add*/
	dev->queue_pkt_len = 0;

    udelay(500);
}

/* 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;
    int tmplen;
    UWORD  tmpdata;
    UCHAR  regsave;

	/*2007-4-11 shengdegang modify*/
   	tmpdata=DM9000A_read_reg(0x01);
/*    DM9000_IN_CHAR( 0x01, tmpdata );*/
    if( !(tmpdata & 0x40) )
    {
 		printf("tx need reset!\n");
        dm9000Reset( dev );
        dm9000Config( dev );
        return 3;
    }
	/*DM9000_IN_CHAR(0xff,imr);
	printf("imr= %x",imr);
	DM9000_IN_CHAR(0xfe,imr);
	printf("imr= %x",imr);*/
    if( (skb->len == 0) || (skb->pData == NULL) )
    {
		printf("len == 0 || pData == NULL!\n");
        return 2;
    }

    /* Resource flag check */
    if( dev->tx_pkt_cnt > 1)
    {
		printf("tx full!\n");
        /*2007-4-11 shengdegang modify*/
   			regsave=DM9000A_read_reg(2);
/*        DM9000_IN_CHAR( 2, regsave );*/
        return 1;
    }

    /* Disable all interrupt
    DM9000_IN_CHAR( 0xff, regsave );
    DM9000_OUT_CHAR( 0xff, 0x80 ); */
	
    /* Move data to DM9000 TX RAM */
    data_ptr = (char *)skb->pData;
   /* for (i=0; i < skb->len ;i ++)
	{
		printf("%2x",data_ptr[i]);
		if (!(i%16))
			printf("\n");
	}*/
	/*printf("packet end..\n");*/
	
	/*2007-4-11 shengdegang modify*/
    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++ )
        {
            tmpdata = ((UWORD *)data_ptr)[i];
			tmpdata=htons(tmpdata);
            DM9000_OUT_WORD( (tmpdata) );
        }
    }
    dev->queue_pkt_len = skb->len;
    dev->tx_pkt_cnt ++;

    /* TX control: First packet immediately send, second packet queue */
    if (dev->tx_pkt_cnt == 1)
    {
        /* First Packet */

        /* Set TX length to DM9000 */
        /*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0xfc, skb->len & 0xff);
    	DM9000A_write_reg(0xfd, (skb->len >> 8) & 0xff);
/*        DM9000_OUT_CHAR( 0xfc, skb->len & 0xff );
        DM9000_OUT_CHAR( 0xfd, (skb->len >> 8) & 0xff);*/

        /* Issue TX polling command */
        /*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0x2, 0x1);
/*        DM9000_OUT_CHAR( 0x2, 0x1 ); */       /* Cleared after TX complete */
    }
    /* Re-enable resource check */


    /* Re-enable interrupt mask
    DM9000_OUT_CHAR( 0xff, regsave ); */
    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=intLock();

     /*oldv=INT_LOCK();*/
    /* Check packet ready or not */
    /*2007-4-11 shengdegang modify*/
   	rxbyte=DM9000A_read_reg(0xf0);
/*	printf("in packet the rxbyte is %x\n",rxbyte);*/
	/*只需读一次F0H*/
   rxbyte=DM9000A_read_reg(0xf0);
/*   printf("in packet the rxbyte1 is %x\n",rxbyte);*/

/*    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 )*/
	if( rxbyte > DM9000_PKT_RDY )
    {
		printf("rxbyte > DM9000_PKT_RDY!\n");
    	/*2007-4-11 shengdegang modify*/
    	DM9000A_write_reg(0x05, 0x00);
    	DM9000A_write_reg(0xfe, 0x80);
/*        DM9000_OUT_CHAR( 0x05, 0x00);*/   /* Stop Device */
/*        DM9000_OUT_CHAR( 0xfe, 0x80);*/   /* Stop INT request */

        /* dev->device_wait_reset = 1; */
        
        dm9000Reset( dev );
        dm9000Config( dev );
      /*  INT_UNLOCK(oldv);*/
		/*2007-4-18 shengdegang add*/
		intUnlock(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 */
            /*2007-4-11 shengdegang modify*/
   					tmp1=DM9000A_read_reg(0xf2);
   					tmp2=DM9000A_read_reg(0xf2);
/*            DM9000_IN_CHAR( 0xf2, tmp1 );
            DM9000_IN_CHAR( 0xf2, tmp2 );*/
            RxStatus = tmp1 + (tmp2 << 8);

⌨️ 快捷键说明

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