📄 dm9000end.c
字号:
/* TODO - initiate device transmit */
len = netMblkToBufCopy (pMblk, (char*)(pDrvCtrl->txBuf), NULL);
len = max (len, ETHERSMALL);
skb.len = len;
skb.pData = (char*)pDrvCtrl->txBuf;
if( dmfe_start_xmit( &skb, pDrvCtrl ) )
{
freeNow = FALSE;
/* Advance our management index(es) */
/*if (!((pDrvCtrl->flags) & DM9000_POLLING))*/
intUnlock (oldLevel);
if (!((pDrvCtrl->flags) & DM9000_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->end);
return(END_ERR_BLOCK);
}
/* Advance our management index(es) */
/*if (!((pDrvCtrl->flags) & DM9000_POLLING))*/
intUnlock (oldLevel);
if (!((pDrvCtrl->flags) & DM9000_POLLING))
END_TX_SEM_GIVE (&pDrvCtrl->end);
/* Bump the statistics counters. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
/*
* Cleanup. The driver must either free the packet now or
* set up a structure so it can be freed later after a transmit
* interrupt occurs.
*/
if (freeNow)
netMblkClChainFree (pMblk);
return (OK);
}
/*******************************************************************************
*
* dm9000Ioctl - the driver I/O control routine
*
* Process an ioctl request.
*
* RETURNS: A command specific response, usually OK or ERROR.
*/
static int dm9000Ioctl( END_DEVICE * pDrvCtrl, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data ) /* command argument */
{
int error = 0;
long value;
/* END_OBJ *temp_end;*/
switch (cmd)
{
case EIOCSADDR:
if (data == NULL)
{
return (EINVAL);
}
bcopy ((char *)data, (char *)END_HADDR(&pDrvCtrl->end),
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCGADDR:
if (data == NULL)
{
return (EINVAL);
}
bcopy ((char *)END_HADDR(&pDrvCtrl->end), (char *)data,
END_HADDR_LEN(&pDrvCtrl->end));
break;
case EIOCSFLAGS:
value = (long)data;
if (value < 0)
{
value = -value;
value--;
END_FLAGS_CLR (&pDrvCtrl->end, value);
}
else
{
END_FLAGS_SET (&pDrvCtrl->end, value);
}
dm9000Config (pDrvCtrl);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
break;
case EIOCPOLLSTART: /* Begin polled operation */
dm9000PollStart (pDrvCtrl);
break;
case EIOCPOLLSTOP: /* End polled operation */
dm9000PollStop (pDrvCtrl);
break;
case EIOCGMIB2: /* return MIB information */
if (data == NULL)
{
return (EINVAL);
}
/*(char *)&temp_end->mib2Tbl,*/
bcopy((char *)&pDrvCtrl->end.mib2Tbl,
(char *)data,
sizeof(pDrvCtrl->end.mib2Tbl));
break;
/* return minimum First Buffer for chaining */
/*DM9000_MIN_FBUF;*/
case EIOCGFBUF:
if (data == NULL)
{
return (EINVAL);
}
*(int *)data = DM9000_MIN_FBUF;/*64;*/
break;
default:
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 )
{
pDrvCtrl->op_mode = (UCHAR)mode;
if( reset != 0 )
{
dm9000Reset( pDrvCtrl );
dm9000Config( pDrvCtrl );
}
}
else
{
DrvCtrl->op_mode = (UCHAR)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. */
if (END_FLAGS_GET(&pDrvCtrl->end) & IFF_PROMISC)
{
}
else
{
}
/* 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 );
return;
}
static void dm9000needreset( END_DEVICE *pDrvCtrl )
{
int oldv;
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;
}
/*******************************************************************************
*
* 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;
stat = dm9000StatusRead (pDrvCtrl);
/* TODO - If no packet is available return immediately */
if( !(stat&DM9000_RXRDY) )
{
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)))
{
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 ) )
{
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. */
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;
/* 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);
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 oldv=intLock();
if (etherMultiAdd (&pDrvCtrl->end.multiList,
pAddress) == ENETRESET)
{
printf("in dm9000MCastAdd ERROR!\n");
dm9000AddrFilterSet (pDrvCtrl);
dm9000_hash_table( pDrvCtrl );
}
printf("in dm9000MCastAdd!\n");
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 oldv=intLock();
if (etherMultiDel (&pDrvCtrl->end.multiList,
(char *)pAddress) == ENETRESET)
{
printf("in dm9000MCastDel ERROR!\n");
dm9000AddrFilterSet (pDrvCtrl);
dm9000_hash_table( pDrvCtrl );
}
printf("in dm9000MCastDel!\n");
intUnlock(oldv);
return (OK);
}
/*****************************************************************************
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -