📄 csend.c
字号:
if( errorCount != 0 )
{
#ifdef CS_DEBUG_ENABLE
logMsg("csVerifyChip: ERROR SRAM test failed, errorCount %d\n",
errorCount,0,0,0,0,0 );
#endif
return( ERROR );
}
return OK;
}
/*******************************************************************************
*
* csStart - start the device
*
* This function calls BSP functions to connect interrupts and start the
* device running in interrupt mode.
*
* RETURNS: OK or ERROR
*
*/
LOCAL STATUS csStart(END_OBJ *pV )
{
CS_END_DEVICE *pCS;
/* @Conexant ARM 940 specific code
extern CS_END_DEVICE *EndObject;
*/
pCS=(CS_END_DEVICE *)pV;
/* @Conexant ARM 940 specific code
EndObject = pCS;
*/
/* For @Conexant ARM 940 User:
Comment out the following code.*/
/* Setup the interrupt handler and the IDT table entry */
if ( intConnect(INUM_TO_IVEC((ULONG)pCS->IntVector), csIntr, (int)pCS) == ERROR )
{
#ifdef CS_DEBUG_ENABLE
logMsg("csStart: CS_END_DEVICE %d, Can not connect intertupt\n",
pCS->unit,0,0,0,0,0 );
#endif
return NULL;
}
#ifdef CS_DEBUG_ENABLE
logMsg("csStart: unit=%d, Initializing interface\n",
pCS->unit, 0,0,0,0,0 );
#endif
/* Initialize the chip */
csInitChip( pCS );
/* Enable CS8900 interrupts at the system level */
if ( sysEnetIntEnable(pCS) == ERROR )
{
#ifdef CS_DEBUG_ENABLE
logMsg("csStart: CS_END_DEVICE %d, sysEnetIntEnable failed\n",
pCS->unit,0,0,0,0,0 );
#endif
return( NULL );
}
/* Mark the interface as up and running */
END_FLAGS_SET (&pCS->end, IFF_UP | IFF_RUNNING);
return OK;
}
/*******************************************************************************
*
* csStop - stop the device
*
* This function calls BSP functions to disconnect interrupts and stop
* the device from operating in interrupt mode.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS csStop(END_OBJ *pV)
{
CS_END_DEVICE *pCS;
pCS=(CS_END_DEVICE *)pV;
/* disable CS8900 interrupts at the system level */
if ( sysEnetIntDisable(pCS) == ERROR )
{
#ifdef CS_DEBUG_ENABLE
logMsg("csStop: CS_END_DEVICE %d, sysEnetIntDisable failed\n",
pCS->unit,0,0,0,0,0 );
#endif
return( NULL );
}
/* set the flags to indicate NIC status */
/* Mark the interface as down */
END_FLAGS_CLR (&pCS->end, IFF_UP | IFF_RUNNING);
/* Stop the chip */
if ( csResetChip(pCS) == ERROR )
{
#ifdef CS_DEBUG_ENABLE
logMsg("csStop: CS_END_DEVICE %d, Can not reset the chip\n",
pCS->unit, 0,0,0,0,0 );
#endif
return ERROR;
}
#ifdef CS_DEBUG_ENABLE
logMsg("csStop(): unit=%d, The CS8900 device has been stopped.\n",
pCS->unit,0,0,0,0,0 );
#endif
return OK;
}
/******************************************************************************
*
* csUnload - 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.
*/
LOCAL STATUS csUnload ( END_OBJ *pV /* device to be unloaded */
)
{
CS_END_DEVICE *pCS;
pCS=(CS_END_DEVICE *)pV;
END_OBJECT_UNLOAD (&pCS->end);
#ifdef CS_DEBUG_ENABLE
logMsg("csUnLoad(): unit=%d, CS8900 driver is unloaded!\n",
pCS->unit,0,0,0,0,0 );
#endif
return (OK);
}
/*******************************************************************************
*
* csIoctl -
*
* This routine is a major entry point and is called by the protocol stack to
* modify characteristics of this network interface driver.
*/
LOCAL int csIoctl(
END_OBJ *pV, /* device receiving command */
int cmd, /* ioctl command code */
caddr_t data /* command argument */
)
{
int status = 0;
long value;
CS_END_DEVICE *pCS;
pCS=(CS_END_DEVICE *)pV;
switch( cmd )
{
case EIOCSADDR:
if (data == NULL)
return (EINVAL);
bcopy ((char *)data, (char *)END_HADDR(&pCS->end),
END_HADDR_LEN(&pCS->end));
bcopy( (char *)data, (char *)pCS->enetAddr, 6);
csConfig(pCS);
break;
case EIOCGADDR:
if (data == NULL) return (EINVAL);
bcopy ((char *)END_HADDR(&pCS->end), (char *)data,
END_HADDR_LEN(&pCS->end));
break;
case EIOCSFLAGS: /* set Promiscuous Mode */
value = (long)data;
if (value < 0)
{
value = -(--value);
END_FLAGS_CLR (&pCS->end, value);
}
else
{
END_FLAGS_SET (&pCS->end, value);
}
csConfig (pCS);
break;
case EIOCGFLAGS:
*(int *)data = END_FLAGS_GET(&pCS->end);
break;
case EIOCMULTIADD:
status = csMCastAdd ((void*)pCS, (char *) data);
break;
case EIOCMULTIDEL:
status = csMCastDel ((void*)pCS, (char *) data);
break;
case EIOCMULTIGET:
status = csMCastGet ((void*)pCS, (MULTI_TABLE *) data);
break;
case EIOCPOLLSTART:
csPollStart ((void*)pCS);
break;
case EIOCPOLLSTOP:
csPollStop ((void*)pCS);
break;
case EIOCGMIB2:
if (data == NULL) return (EINVAL);
bcopy((char *)&pCS->end.mib2Tbl, (char *)data,
sizeof(pCS->end.mib2Tbl));
break;
case EIOCGFBUF:
if (data == NULL)
return (EINVAL);
*(int *)data = CS_MIN_FBUF;
break;
default:
status = EINVAL;
}
return (status);
}
/*******************************************************************************
*
* csSend - the driver send routine
*
* This routine takes a M_BLK_ID sends off the data in the M_BLK_ID.
* The buffer must already have the addressing information properly installed
* in it. This is done by a higher layer.
*
* RETURNS: OK or ERROR.
*/
LOCAL STATUS csSend ( END_OBJ *pV, /* device ptr */
M_BLK_ID pMBuff /* data to send */
)
{
int oldLevel=0;
CS_END_DEVICE *pCS;
pCS=(CS_END_DEVICE *)pV;
/*
* Obtain exclusive access to transmitter. This is necessary because
* we might have more than one stack transmitting at once.
*/
if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
END_TX_SEM_TAKE (&pCS->end, WAIT_FOREVER);
/* This is the normal case where all the data is in one M_BLK_ID */
/* Set pointers in local structures to point to data. */
/* place a transmit request */
if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
{
/* disable interrupts*/
oldLevel=INT_LOCK();
}
/* initiate device transmit */
csStartOutput(pCS, pMBuff);
if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
{
/* enable interrupts*/
INT_UNLOCK(oldLevel);
}
/* Advance our management index */
if (!(pCS->ConfigFlags & CFGFLG_POLL_MODE))
END_TX_SEM_GIVE (&pCS->end);
return (OK);
}
/* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ *
* Interrupt-handler Routines *
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */
/*******************************************************************************
*
* csIntr -
*
* This routine in the interrupt service routine. This routine is called by
* VxWorks wrapper code whenever the CS8900 chip generates and interrupt. The
* wrapper code issues an EOI command.
*
* This routine processes the events on the Interrupt Status Queue. The events
* are read one at a time from the ISQ and the appropriate event handlers are
* called. The ISQ is read until it is empty. Reading a zero from the ISQ will
* deassert the interrupt request line.
*
* RETURNS: Nothing
*
*/
LOCAL void csIntr(CS_END_DEVICE *pCS)
{
USHORT Event;
/* Ignore any interrupts that happen while the chip is being reset */
if( pCS->Resetting )
return;
/* Set locale flag */
pCS->InISR = TRUE;
/* Read an event from the Interrupt Status Queue */
if( pCS->InMemoryMode )
Event = csReadPacketPage( pCS, PKTPG_ISQ );
else
Event = SYS_ENET_IN_WORD( (pCS->IOAddr)+PORT_ISQ );
/* Process all the events in the Interrupt Status Queue */
while( Event != 0 )
{
/* Dispatch to an event handler based on the register number */
switch ( Event & REG_NUM_MASK )
{
case REG_NUM_RX_EVENT:
csReceiveEvent( pCS, Event );
break;
case REG_NUM_TX_EVENT:
csTransmitEvent( pCS, Event );
break;
case REG_NUM_BUF_EVENT:
csBufferEvent( pCS, Event );
break;
case REG_NUM_RX_MISS:
/* Read the Rx Miss count (clears the counter). */
/* Miss count is in the 10 MSBs */
/*pCS->ArpCom.ac_if.if_ierrors += ( (BYTE_SWAP(Event)) >> 6); */
END_ERR_ADD (&pCS->end, MIB2_IN_ERRS,( (BYTE_SWAP(Event)) >> 6) );
#ifdef CS_DEBUG_ENABLE
logMsg("csRxMissEvent: CS_END_DEVICE %d,, %d added to RX miss counter\n",
pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
#endif
break;
case REG_NUM_TX_COL:
/* Read the collision counter (clears the counter). */
/* Collision count is in the 10 MSBs */
pCS->Collisions += ( (BYTE_SWAP(Event)) >> 6);
#ifdef CS_DEBUG_ENABLE
logMsg("csTxColEvent: CS_END_DEVICE %d, %d added to collision counter\n",
pCS->unit, ( (BYTE_SWAP(Event)) >> 6),0,0,0,0 );
#endif
break;
default:
#ifdef CS_DEBUG_ENABLE
logMsg("csIntr: CS_END_DEVICE %d, Unknown interrupt event: %04X\n",
pCS->unit, (BYTE_SWAP(Event)),0,0,0,0 );
#endif
break;
}
/* Read another event from the Interrupt Status Queue */
if ( pCS->InMemoryMode )
Event = csReadPacketPage( pCS, PKTPG_ISQ );
else
Event = SYS_ENET_IN_WORD( (pCS->IOAddr)+PORT_ISQ );
}
/* Ensure task-level event handler is running */
if( pCS->NetJobDepth < 2 )
{
pCS->NetJobDepth++;
netJobAdd( (FUNCPTR)csEventHandler, (int)pCS, 0, 0, 0, 0 );
}
/* Clear locale flag */
pCS->InISR = FALSE;
}
/*******************************************************************************
*
* csBufferEvent -
*
* The routine is called whenever an event occurs regarding the transmit and
* receive buffers within the CS8900 chip. The only buffer events we
* currently handle are Rdy4TX interrupts, Tx Underruns, and SW ints.
*
*/
LOCAL void csBufferEvent( CS_END_DEVICE *pCS, USHORT BufEvent )
{
USHORT BusStatus;
if ( BufEvent & BUF_EVENT_TX_UNDR )
{
/* TX underrun occured */
pCS->TxUnderruns++;
/* Modify start command if total underruns > threshold value */
/* by setting TX start command to next increment */
if( pCS->TxUnderruns == CS_TX_UNDRUN_TRHSHOLD )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -