📄 dm9000end.c
字号:
*(int *)data = END_FLAGS_GET(&pDrvCtrl->end);
break;
case EIOCMULTIADD:
status = dm9000MCastAdd ((void*)pDrvCtrl, (char *) data);
break;
case EIOCMULTIDEL:
status = dm9000MCastDel((void*)pDrvCtrl, (char *) data);
break;
case EIOCMULTIGET:
status = dm9000MCastGet ((void*)pDrvCtrl, (MULTI_TABLE *) data);
break;
case EIOCPOLLSTART: /* Begin polled operation */
dm9000PollStart ((void*)pDrvCtrl);
break;
case EIOCPOLLSTOP: /* End polled operation */
dm9000PollStop ((void*)pDrvCtrl);
break;
case EIOCGMIB2: /* return MIB information */
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 */
if (data == NULL)
return (EINVAL);
*(int *)data = DM9000_MIN_FBUF;
break;
case EIOCGHDRLEN:
if(data == NULL) return EINVAL;
*(int *)data = EH_SIZE;
break;
default:
status = EINVAL;
}
return (status);
}
/******************************************************************************
*
* 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)
{
#ifdef DM_DEBUG_PRINT
logMsg ("dm9000Config() Setting promiscuous mode on!\n", 0, 0, 0, 0, 0, 0);
#endif
}
else
{
#ifdef DM_DEBUG_PRINT
logMsg ("dm9000Config() Setting promiscuous mode off!\n", 0, 0, 0, 0, 0, 0);
#endif
/* Set up address filter for multicasting. */
dm9000AddrFilterSet (pDrvCtrl);
}
/*initialise the hardware according to flags */
dmfe_config_dm9000( pDrvCtrl, 2 );
return;
}
/******************************************************************************
*
* 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.
*/
static void dm9000AddrFilterSet( END_DEVICE *pDrvCtrl )
{
ETHER_MULTI* pCurr;
unsigned long crc;
unsigned long hash_table[4];
/*Get the first Mcast address from Mcast list */
pCurr = END_MULTI_LST_FIRST (&pDrvCtrl->end);
while (pCurr != NULL)
{
pCurr = END_MULTI_LST_NEXT(pCurr);
}
}
/*******************************************************************************
*
* 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 *pV, /* device to be polled */
M_BLK_ID pMblk ) /* ptr to buffer */
{
u_short stat;
char* pPacket;
int len = 64;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
#ifdef DM_DEBUG_PRINT
logMsg("dm9000PollRcv()\n", 0, 0, 0, 0, 0, 0);
#endif
stat = dm9000StatusRead (pDrvCtrl);
/* TODO - If no packet is available return immediately */
if( !(stat&DM9000_RXRDY) )
{
logMsg("dm9000PollRcv: no data.\n", 0, 0, 0, 0, 0, 0);
return (EAGAIN);
}
/* Upper layer must provide a valid buffer. */
if ((pMblk->mBlkHdr.mLen < len) || (!(pMblk->mBlkHdr.mFlags & M_EXT)))
{
logMsg("dm9000PollRcv: PRX bad mblk.\n", 0, 0, 0, 0, 0, 0);
return (EAGAIN);
}
END_ERR_ADD (&pDrvCtrl->end, MIB2_IN_UCAST, +1);
/* TODO - Process device packet into net buffer */
while(dmfe_Get_NextPacket() != 0)
{
len = dmfe_Copy_RxFrame( pDrvCtrl, pMblk->mBlkHdr.mData+2, 0 );
}
if(len == ERROR)
{
logMsg("dm9000PollRcv: packet receive FAIL.\n", 0, 0, 0, 0, 0, 0);
return (EAGAIN);
}
pMblk->mBlkHdr.mData += 2;
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 */
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 *pV, /* device to be polled */
M_BLK_ID pMblk ) /* packet to send */
{
static UCHAR txBuf[DM9000_FRAME_BUFSIZE];
int len,lastone;
u_short stat;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
#ifdef DM_DEBUG_PRINT
logMsg("dm9000PollSend: dm9000PollSend()\n", 0, 0, 0, 0, 0, 0);
#endif
/* TODO - test to see if tx is busy */
stat = dm9000StatusRead (pDrvCtrl); /* dummy code */
if ((stat & (DM9000_TINT|DM9000_TFULL)) == 0)
return ((STATUS) EAGAIN);
/* Get data from Mblk to tx buffer. */
len = netMblkToBufCopy (pMblk, (char*)txBuf, NULL);
len = max (len, ETHERSMALL);
/*transmit packet*/
lastone = intLock();
dmfe_Copy_TxFrame(pDrvCtrl, txBuf ,len);
/*check a Completion Flag*/
intUnlock( lastone );
/* Bump the statistic counter. */
END_ERR_ADD (&pDrvCtrl->end, MIB2_OUT_UCAST, +1);
/* Free the data if it was accepted by device */
netMblkClFree (pMblk);
#ifdef DM_DEBUG_PRINT
logMsg("dm9000PollSend: leaving dm9000PollSend.\n", 0, 0, 0, 0, 0, 0);
#endif
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 *pV, /* device pointer */
char *pAddress ) /* new address to add */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
if ((etherMultiAdd (&pDrvCtrl->end.multiList,pAddress)) == ENETRESET)
{
dm9000Config(pDrvCtrl);
}
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 *pV, /* device pointer */
char *pAddress ) /* address to be deleted */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
if ((etherMultiDel (&pDrvCtrl->end.multiList, (char *)pAddress)) == ENETRESET)
{
dm9000Config(pDrvCtrl);
}
return (OK);
}
/*****************************************************************************
*
* 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 *pV, /* device pointer */
MULTI_TABLE *pTable ) /* address table to be filled in */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
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 *pV ) /* device to be stopped */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
intDisable(pDrvCtrl->ilevel);
/* TODO - stop/disable the device. */
dmfe_Stop_Chip( pDrvCtrl );
return (OK);
}
/******************************************************************************
*
* 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 *pV ) /* device to be unloaded */
{
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
#ifdef DM_DEBUG_PRINT
logMsg("dm9000Unload()\n", 0, 0, 0, 0, 0, 0);
#endif
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 *pV ) /* device to be polled */
{
int lastone;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
lastone = intLock ();
/* TODO - turn off interrupts */
(pDrvCtrl->flags) |= DM9000_POLLING;
dm9000Reset( pDrvCtrl );
dm9000Config( pDrvCtrl ); /* reconfigure device */
intUnlock (lastone); /* now dm9000Int won't get confused */
logMsg("dm9000PollStart Poll Mode Start.\n", 0, 0, 0, 0, 0, 0);
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 *pV ) /* device to be polled */
{
int lastone;
END_DEVICE *pDrvCtrl;
pDrvCtrl=(END_DEVICE *)pV;
lastone = intLock (); /* disable ints during register updates */
(pDrvCtrl->flags) &= ~DM9000_POLLING;
dm9000Reset( pDrvCtrl );
dm9000Config( pDrvCtrl ); /* reconfigure device */
intUnlock (lastone);
logMsg ("dm9000PollStart Poll Mode Stop.\n", 0, 0, 0, 0, 0, 0);
return (OK);
}
/*******************************************************************************
*
* dm9000Reset - reset device
*
* RETURNS: N/A.
*/
static void dm9000Reset( END_DEVICE *pDrvCtrl )
{
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_REG( 0xfe, status );
DM9000_OUT_REG( 0xfe, status );
DM9000_IN_REG( 0xf0, rxbyte ); /* Dummy read */
DM9000_IN_REG( 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 )
{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -