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

📄 dm9000end.c

📁 S3C2410的DM9000驱动。在优龙的开发板子上调试成功
💻 C
📖 第 1 页 / 共 5 页
字号:
            bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
            END_HADDR_LEN(&pDrvCtrl->end));
            break;
        case EIOCSFLAGS:
        DRV_LOG (DRV_DEBUG_LOAD, "EIOCSFLAGS", 1, 2, 3, 4, 5, 6);
            value = (long)data;
            if (value < 0)
            {
                value = -(--value);
                END_FLAGS_CLR (&pDrvCtrl->end, value);
            }
            else
            {
                END_FLAGS_SET (&pDrvCtrl->end, value);
            }
            dm9000Config (pDrvCtrl);
            break;
        case EIOCGFLAGS:
        DRV_LOG (DRV_DEBUG_LOAD, "EIOCGFLAGS", 1, 2, 3, 4, 5, 6);
            *(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
            break;

        case EIOCPOLLSTART: /* Begin polled operation */
        DRV_LOG (DRV_DEBUG_LOAD, "begin polled operation", 1, 2, 3, 4, 5, 6);
            dm9000PollStart (pDrvCtrl);
            break;

        case EIOCPOLLSTOP:  /* End polled operation */
        DRV_LOG (DRV_DEBUG_LOAD, "end polled operation", 1, 2, 3, 4, 5, 6);
            dm9000PollStop (pDrvCtrl);
            break;

        case EIOCGMIB2:     /* return MIB information */
        DRV_LOG (DRV_DEBUG_LOAD, "return MIB information", 1, 2, 3, 4, 5, 6);
            if (data == NULL)
                return (EINVAL);
            bcopy((char *)&pDrvCtrl->end.mib2Tbl,
                  (char *)data,
                  sizeof(pDrvCtrl->end.mib2Tbl));
            break;
        case EIOCGFBUF:     /* return minimum First Buffer for chaining */
        DRV_LOG (DRV_DEBUG_LOAD, "return minimun first buffer for chaining", 1, 2, 3, 4, 5, 6);
            if (data == NULL)
                return (EINVAL);
            *(int *)data = DM9000_MIN_FBUF;
            break;
        default:
        DRV_LOG (DRV_DEBUG_LOAD, "error", 1, 2, 3, 4, 5, 6);
            error = EINVAL;
    }
    return (error);
}

/******************************************************************************
*
* dm9000Mode - configure the interface mode
*
* mode:
* #define DM9000_10MHD        0
* #define DM9000_100MHD       1
* #define DM9000_10MFD        4
* #define DM9000_100MFD       5
* #define DM9000_AUTO         8
* RETURNS: N/A.
*/
void     dm9000Mode( END_DEVICE *pDrvCtrl, int mode, int reset )
{
    if( pDrvCtrl != 0 )
    {
        printf("pDrvCtrl->op_mode = %d\n",(int)(pDrvCtrl->op_mode) );
        pDrvCtrl->op_mode = (UCHAR)mode;
        printf("pDrvCtrl->op_mode = %d\n",(int)(pDrvCtrl->op_mode) );
        if( reset != 0 )
        {
            dm9000Reset( pDrvCtrl );
            dm9000Config( pDrvCtrl );
        }
    }
    else
    {
        printf("DrvCtrl->op_mode = %d\n",(int)(DrvCtrl->op_mode) );
        DrvCtrl->op_mode = (UCHAR)mode;
        printf("DrvCtrl->op_mode = %d\n",(int)(DrvCtrl->op_mode) );
        if( reset != 0 )
        {
            dm9000Reset( DrvCtrl );
            dm9000Config( DrvCtrl );
        }
    }
}

/******************************************************************************
*
* dm9000Config - reconfigure the interface under us.
*
* Reconfigure the interface setting promiscuous mode, and changing the
* multicast interface list.
*
* RETURNS: N/A.
*/

static void dm9000Config( END_DEVICE *pDrvCtrl ) /* device to be re-configured */
{
    /* Set promiscuous mode if it's asked for. */
    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Config()", 1, 2, 3, 4, 5, 6);

    if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
    {
        DRV_LOG (DRV_DEBUG_IOCTL, "Setting promiscuous mode on!",
                 1, 2, 3, 4, 5, 6);
    }
    else
    {
        DRV_LOG (DRV_DEBUG_IOCTL, "Setting promiscuous mode off!",
                 1, 2, 3, 4, 5, 6);
    }

    /* Set up address filter for multicasting. */

    if (END_MULTI_LST_CNT(&pDrvCtrl->end) > 0)
    {
        dm9000AddrFilterSet (pDrvCtrl);
        dm9000_hash_table( pDrvCtrl ); 
    }

    /* TODO - shutdown device completely */

    /* TODO - reset all device counters/pointers, etc. */

    /* TODO - initialise the hardware according to flags */
    dmfe_config_dm9000( pDrvCtrl, 2 );

    DRV_LOG (DRV_DEBUG_LOAD, "dm9000Config() done", 1, 2, 3, 4, 5, 6);
    return;
}


static void dm9000needreset( END_DEVICE *pDrvCtrl )
{
    int oldv;

    DRV_LOG (DRV_DEBUG_STATUS, "dm9000needreset()", 1, 2, 3, 4, 5, 6);

    oldv = intLock();
    pDrvCtrl->device_wait_reset = 0;

    dm9000Reset( pDrvCtrl );
    dm9000Config( pDrvCtrl );
    intUnlock( oldv );
}
/******************************************************************************
*
* dm9000AddrFilterSet - set the address filter for multicast addresses
*
* This routine goes through all of the multicast addresses on the list
* of addresses (added with the endAddrAdd() routine) and sets the
* device's filter correctly.
*
* RETURNS: N/A.
*/

void dm9000AddrFilterSet( END_DEVICE *pDrvCtrl )
{
    int i;
    unsigned long crc; 
    unsigned long hash_table[4];
    ETHER_MULTI* pCurr;
    
    pDrvCtrl->mcastFilter[0] = 0;
    pDrvCtrl->mcastFilter[1] = 0;
    pDrvCtrl->mcastFilter[2] = 0;
    pDrvCtrl->mcastFilter[3] = 0;
    pDrvCtrl->mcastFilter[4] = 0;
    pDrvCtrl->mcastFilter[5] = 0;
    pDrvCtrl->mcastFilter[6] = 0;
    pDrvCtrl->mcastFilter[7] = 0;
    
    for(i=0;i<4;i++)hash_table[i]=0;
    hash_table[3]=0x8000;
    
    /* broadcast address */
    /*pDrvCtrl->mcastFilter[7] = 0x80; */      /*mabe  [6] */

    /* the multicast address in Hash Table : 64 bits */

    pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);

    while (pCurr != NULL)
    {
        /* TODO - set up the multicast list */
        crc = cal_CRC(((unsigned char *)&pCurr->addr), 6, 0 )&0x3f;
        hash_table[crc/16] |= (unsigned short) 1 << (crc % 16);
        
    pCurr = END_MULTI_LST_NEXT(pCurr);     
    }
 
       pDrvCtrl->mcastFilter[0] |= hash_table[0]&0xff;
       pDrvCtrl->mcastFilter[1] |= (hash_table[0]>>8)&0xff;
       pDrvCtrl->mcastFilter[2] |= hash_table[1]&0xff;
       pDrvCtrl->mcastFilter[3] |= (hash_table[1]>>8)&0xff;
       pDrvCtrl->mcastFilter[4] |= hash_table[2]&0xff;
       pDrvCtrl->mcastFilter[5] |= (hash_table[2]>>8)&0xff;
       pDrvCtrl->mcastFilter[6] |= hash_table[3]&0xff;
       pDrvCtrl->mcastFilter[7] |= (hash_table[3]>>8)&0xff;
}

#if 0
void dm9000AddrFilterSet( END_DEVICE *pDrvCtrl )    /* device to be updated */
{
    ETHER_MULTI* pCurr;
    u_long crc;

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

    /* TODO - clean the device filter list */
    pDrvCtrl->mcastFilter[0] = 0;
    pDrvCtrl->mcastFilter[1] = 0;
    pDrvCtrl->mcastFilter[2] = 0;
    pDrvCtrl->mcastFilter[3] = 0;
    pDrvCtrl->mcastFilter[4] = 0;
    pDrvCtrl->mcastFilter[5] = 0;
    pDrvCtrl->mcastFilter[6] = 0;
    pDrvCtrl->mcastFilter[7] = 0;

    pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);

    while (pCurr != NULL)
    {
        /* TODO - set up the multicast list */

        /* build the CRC for the 6 byte adrs */
        crc = cal_CRC( ((unsigned char *)&pCurr->addr), 6, 0 );

        
        /* get six msb */
        crc >>= 26;
        crc &= 0x3f;

        /* high 3 bit index MAR reg, low three bits index reg bit */
        pDrvCtrl->mcastFilter[crc >> 3] |= (1 << (crc & 7));

        
        pCurr = END_MULTI_LST_NEXT(pCurr);
    }

    /* TODO - update the device filter list */

    
}
#endif
/*******************************************************************************
*
* dm9000PollRcv - routine to receive a packet in polled mode.
*
* This routine is called by a user to try and get a packet from the
* device.
*
* RETURNS: OK upon success.  EAGAIN is returned when no packet is available.
*/

static STATUS dm9000PollRcv( END_DEVICE *pDrvCtrl,  /* device to be polled */
                            M_BLK_ID   pMblk )     /* ptr to buffer */
{
    u_short stat;
    char* pPacket;
    int len;
    PKT         skb;

    DRV_LOG (DRV_DEBUG_POLL_RX, "dm9000PollRcv", 1, 2, 3, 4, 5, 6);

    stat = dm9000StatusRead (pDrvCtrl);
    /* TODO - If no packet is available return immediately */

    if( !(stat&DM9000_RXRDY) )
    {
        DRV_LOG (DRV_DEBUG_POLL_RX, "dm9000PollRcv no data", 1,
                 2, 3, 4, 5, 6);
        return (EAGAIN);
    }

    
    pPacket = NULL; /* DUMMY CODE */
    len = 64;       /* DUMMY CODE */

    /* Upper layer must provide a valid buffer. */

    if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
    {
        DRV_LOG (DRV_DEBUG_POLL_RX, "PRX bad mblk", 1, 2, 3, 4, 5, 6);
        return (EAGAIN);
    }

    /* TODO - clear any status bits that may be set. */

    /* TODO - Check packet and device for errors */

    END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);

    /* TODO - Process device packet into net buffer */
    skb.len = 0;
    skb.pData = pMblk->m_data;
    if( dmfe_packet_receive( &skb, pDrvCtrl ) )
    {
        DRV_LOG (DRV_DEBUG_POLL_RX, "packet receive FAIL", 1, 2, 3, 4, 5, 6);
        return (EAGAIN);
    }

/*    bcopy (pPacket, pMblk->m_data, len);   */
    pMblk->mBlkHdr.mFlags |= M_PKTHDR;  /* set the packet header */
    pMblk->mBlkHdr.mLen = len;          /* set the data len */
    pMblk->mBlkPktHdr.len = len;        /* set the total len */

    /* TODO - Done with packet, clean up and give it to the device. */

    DRV_LOG (DRV_DEBUG_POLL_RX, "dm9000PollRcv OK", 1, 2, 3, 4, 5, 6);
    DRV_LOG (DRV_DEBUG_POLL_RX, "dm9000PollRcv OK", 1, 2, 3, 4, 5, 6);

    return (OK);
}

/*******************************************************************************
*
* dm9000PollSend - routine to send a packet in polled mode.
*
* This routine is called by a user to try and send a packet on the
* device.
*
* RETURNS: OK upon success.  EAGAIN if device is busy.
*/

static STATUS dm9000PollSend( END_DEVICE *pDrvCtrl,   /* device to be polled */
                             M_BLK_ID   pMblk )      /* packet to send */
{
    int         len;
    u_short     stat;
    PKT         skb;
    int         oldv;

    DRV_LOG (DRV_DEBUG_POLL_TX, "dm9000PollSend", 1, 2, 3, 4, 5, 6);

    /* TODO - test to see if tx is busy */
    stat = dm9000StatusRead (pDrvCtrl);             /* dummy code */
    if ((stat & (DM9000_TINT|DM9000_TFULL)) == 0)
        return ((STATUS) EAGAIN);

    /* TODO - Process the net buffer into a device transmit packet */

    /* TODO - transmit packet */
    len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL);
    len = max (len, ETHERSMALL);
    skb.len = len;
    skb.pData = (char*)pDrvCtrl->txBuf;

    oldv = intLock();
    dmfe_start_xmit( &skb, pDrvCtrl );
    intUnlock( oldv );

    /* Bump the statistic counter. */

    END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);

    /* Free the data if it was accepted by device */

    netMblkClFree (pMblk);

    DRV_LOG (DRV_DEBUG_POLL_TX, "leaving dm9000PollSend", 1, 2, 3, 4, 5, 6);

    return (OK);
}

/*****************************************************************************
*
* dm9000MCastAdd - add a multicast address for the device
*
* This routine adds a multicast address to whatever the driver
* is already listening for.  It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000MCastAdd( END_DEVICE *pDrvCtrl,      /* device pointer */
                             char* pAddress )           /* new address to add */
{
    int error;
    int oldv=intLock();
    DRV_LOG (DRV_DEBUG_LOAD, "dm9000MCastAdd()", 1, 2, 3, 4, 5, 6);

    if (etherMultiAdd (&pDrvCtrl->end.multiList,
        pAddress) == ENETRESET)
    {
        dm9000AddrFilterSet (pDrvCtrl);
        dm9000_hash_table( pDrvCtrl ); 
    }
    intUnlock(oldv);
    return (OK);
}

/*****************************************************************************
*
* dm9000MCastDel - delete a multicast address for the device
*
* This routine removes a multicast address from whatever the driver
* is listening for.  It then resets the address filter.
*
* RETURNS: OK or ERROR.
*/

static STATUS dm9000MCastDel( END_DEVICE *pDrvCtrl,  /* device pointer */
                             char *pAddress )       /* address to be deleted */
{
    int error;
    int oldv=intLock();
    DRV_LOG (DRV_DEBUG_LOAD, "dm9000MCastDel()", 1, 2, 3, 4, 5, 6);

    if (etherMultiDel (&pDrvCtrl->end.multiList,
         (char *)pAddress) == ENETRESET)
    {
        dm9000AddrFilterSet (pDrvCtrl);
        dm9000_hash_table( pDrvCtrl );
    }
   intUnlock(oldv);
    return (OK);
}

/*****************************************************************************
*
* dm9000MCastGet - get the multicast address list for the device
*

⌨️ 快捷键说明

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