📄 trmpc860.c
字号:
TM_MPC860_ETHERNET_PORT;
/* enable SCC1 receive/transmit operation */
regs->scc_gsmrl |= TM_MPC860_ENABLE_RECV | TM_MPC860_ENABLE_XMIT;
}
void tfMpc860Down(int channel)
{
struct scc_regs *regs;
regs = &tlMpc860Ptr->scc_regs[channel];
/* clear all events on the SCC event register and CP event reg*/
regs->scc_scce=0xffff;
/* Disable SCCx receive/transmit operation */
regs->scc_gsmrl &= ~(TM_MPC860_ENABLE_RECV | TM_MPC860_ENABLE_XMIT);
}
/*
* Disable the Ethernet on SCC1
*/
int tfMpc860EtherClose(ttUserInterface interfaceHandle)
{
tfMpc860Down(TM_MPC860_SCC1_CHANNEL);
return 0;
}
/*
* The main initialization routine for the mpc860 and the scc's
*/
int tfMpc860EtherOpen(ttUserInterface interfaceHandle)
{
unsigned long mpc860Registers;
mpc860Registers=TM_MPC860_IMMR_LOC;
tlMpc860Ptr = (ttMpc860 *)(mpc860Registers&0xfffffffc);
/* Interface handle is not used, but could be for multiple ethernets */
interfaceHandle=interfaceHandle;
/* Initialize default Ethernet parameters */
tfMpc860EtherScc1Init();
/* Create our transmit pool */
tfMpc860CreateXmitPool(TM_MPC860_SCC1_CHANNEL,
TM_MPC860_ETHER_MAX_XMIT_BUFD);
/* Create our receive pool (with receive buffers) */
tfMpc860CreateRecvPool(TM_MPC860_SCC1_CHANNEL,
TM_MPC860_ETHER_MAX_RECV_BUFD);
/* Initial board specific parameters */
tfMpc860EtherScc1BoardInit();
/* Bring the ethernet scc port online */
tfMpc860EtherUp(TM_MPC860_SCC1_CHANNEL);
/* Save our interfaceHandle for ISR use */
tlInterfaceArray[TM_MPC860_SCC1_CHANNEL]=interfaceHandle;
return TM_ENOERROR;
}
/*
* Interrupt service routine called from actual
* ISR handlers
*/
void tfMpc860Scc1HandlerIsr()
{
register unsigned short event;
ttUserInterface interfaceHandle;
struct scc_regs *regs;
int channel;
unsigned short *bdStatusPtr;
#ifdef TM_TASK_SEND
void **bdDataPtrPtr;
#endif /* TM_TASK_SEND */
channel=TM_MPC860_SCC1_CHANNEL;
interfaceHandle=tlInterfaceArray[channel];
/* Points to SCC regs */
regs = &tlMpc860Ptr->scc_regs[channel];
/* Check to see what events have occured */
event = regs->scc_scce;
/* Cleared event bits we hill handle */
regs->scc_scce= event;
#ifdef TM_TASK_SEND
if( event & TM_MPC860_INTR_ETHER_XMIT_B )
{
bdStatusPtr = &tlMpc860XmitIsrBufDescPtr->bdStatus;
bdDataPtrPtr = &tlMpc860XmitIsrBufDescPtr->bdDataPtr;
/* An ethernet frame has completed transmitting so notify the user*/
while (((*bdStatusPtr & TM_MPC860_XMIT_READY)==0)
&& (*bdDataPtrPtr != (void TM_FAR *)0))
{
/* Zero it out so we know that we have freed this one before */
*bdDataPtrPtr=(void TM_FAR *)0;
if (*bdStatusPtr & TM_MPC860_XMIT_WRAP)
{
tlMpc860XmitIsrBufDescPtr = tlMpc860XmitBufDescStartPtr;
}
else
{
tlMpc860XmitIsrBufDescPtr++;
}
bdStatusPtr = &tlMpc860XmitIsrBufDescPtr->bdStatus;
bdDataPtrPtr = &tlMpc860XmitIsrBufDescPtr->bdDataPtr;
tfNotifySentInterfaceIsr(interfaceHandle,tlMpc860XmitIsrBufDescPtr->bdLength);
}
}
#endif /* TM_TASK_SEND */
if ( event & TM_MPC860_INTR_ETHER_RECV_F )
{
/* loop on frames with the Empty bit and SHORT (notify) bit is NOT set "==0" */
/* Only notify while the frames are not empty */
bdStatusPtr = &tlMpc860RecvIsrBufDescPtr->bdStatus;
while (!(*bdStatusPtr & (TM_MPC860_RECV_EMPTY|TM_MPC860_NOTIFIED)))
{
tfNotifyReceiveInterfaceIsr(interfaceHandle);
*bdStatusPtr |= TM_MPC860_NOTIFIED;
if (*bdStatusPtr & TM_MPC860_RECV_WRAP)
{
tlMpc860RecvIsrBufDescPtr = tlMpc860RecvBufDescStartPtr;
}
else
{
tlMpc860RecvIsrBufDescPtr++;
}
bdStatusPtr = &tlMpc860RecvIsrBufDescPtr->bdStatus;
}
}
if ( event & TM_MPC860_INTR_ETHER_E_XMIT )
{
/* An error on Transmit has occured */
tfMpc860XmitError(interfaceHandle,channel);
}
if ( event & TM_MPC860_INTR_ETHER_BUSY )
{
/* Busy Condition has been set */
tfMpc860Busy(interfaceHandle,channel);
}
/* Clear the appropriate bit in the CISR */
tlMpc860Ptr->intr_cisr |= TM_MPC860_SCC1_INT_MASK;
}
/*
* Send a packet to the network
*/
int tfMpc860Send(ttUserInterface interfaceHandle,
char TM_FAR *bufferPtr,
int length,
int flag)
{
ttMpc860BufDescPtr bufDescPtr;
ttMpc860BufDescPtr startBufDescPtr;
unsigned short *bdStatusPtr;
void **bdDataPtrPtr;
/* Wait for a free buffer descriptor */
while (tlMpc860XmitBufDescPtr->bdStatus & TM_MPC860_XMIT_READY)
{
tvMpc860XmitWait++;
}
bufDescPtr=tlMpc860XmitBufDescPtr++;
bdStatusPtr=&bufDescPtr->bdStatus;
if (*bdStatusPtr & TM_MPC860_XMIT_WRAP)
{
tlMpc860XmitBufDescPtr = tlMpc860XmitBufDescStartPtr;
}
bufDescPtr->bdDataPtr=(void TM_FAR *)bufferPtr;
bufDescPtr->bdLength=length;
/* Clear the previous status (but preserve the WRAP bit) */
bufDescPtr->bdStatus &= TM_MPC860_XMIT_WRAP;
/* If this is the last buffer in the frame then xmit it */
if (flag==TM_USER_BUFFER_LAST)
{
/* Now mark the last bd ready */
bdStatusPtr=&bufDescPtr->bdStatus;
*bdStatusPtr |= (TM_MPC860_XMIT_READY |
TM_MPC860_XMIT_PAD |
#ifdef TM_TASK_SEND
TM_MPC860_XMIT_INTR |
#endif /* TM_TASK_SEND */
TM_MPC860_XMIT_LAST |
TM_MPC860_XMIT_CRC);
/* Check to see if we are xmitting scattered data */
if (tlScatterBufferStart != (ttMpc860BufDescPtr)0)
{
/* We have at least one more piece to xmit if we are here */
startBufDescPtr=tlScatterBufferStart;
tlScatterBufferStart=(ttMpc860BufDescPtr)0;
/*
* Go ahead and xmit the first packets (with more set)
* by walking the list backwards
* We do this so that we don't need a critical section
* in order to keep from getting gaps inbetween the
* pieces
* All we need to do here is update the
* ready flag
*/
do
{
if (bufDescPtr==tlMpc860XmitBufDescStartPtr)
{
/* We are at the front of the list so go to the end */
bufDescPtr += TM_MPC860_ETHER_MAX_XMIT_BUFD;
}
else
{
/* Go back one buffer descriptor */
bufDescPtr--;
}
bdStatusPtr=&bufDescPtr->bdStatus;
*bdStatusPtr |= TM_MPC860_XMIT_READY;
} while (bufDescPtr != startBufDescPtr);
}
}
else
{
/* More buffers to come */
if (tlScatterBufferStart == (ttMpc860BufDescPtr)0)
{
tlScatterBufferStart=bufDescPtr;
}
}
tvMpc860SendPacketCount++;
#ifndef TM_TASK_SEND
/* Inlined send complete */
bdStatusPtr = &tlMpc860XmitIsrBufDescPtr->bdStatus;
bdDataPtrPtr = &tlMpc860XmitIsrBufDescPtr->bdDataPtr;
/* An ethernet frame has completed transmitting so notify the user*/
while (((*bdStatusPtr & TM_MPC860_XMIT_READY)==0 &&
tlMpc860XmitIsrBufDescPtr != tlScatterBufferStart)
&& (*bdDataPtrPtr != (void TM_FAR *)0))
/*
* Watch out for a scattered frame we have not yet finished
* loading up
*/
{
/* Zero it out so we know that we have freed this one before */
*bdDataPtrPtr=(void TM_FAR *)0;
if (*bdStatusPtr & TM_MPC860_XMIT_WRAP)
{
tlMpc860XmitIsrBufDescPtr = tlMpc860XmitBufDescStartPtr;
}
else
{
tlMpc860XmitIsrBufDescPtr++;
}
/* Only call send complete when the last piece has been transmitted */
if (*bdStatusPtr & TM_MPC860_XMIT_LAST)
{
tfSendCompleteInterface(interfaceHandle,TM_DEV_SEND_COMPLETE_DRIVER);
}
bdStatusPtr = &tlMpc860XmitIsrBufDescPtr->bdStatus;
bdDataPtrPtr = &tlMpc860XmitIsrBufDescPtr->bdDataPtr;
}
#endif /* NOT TM_TASK_SEND */
return TM_ENOERROR;
}
/*
* A Transmit Error has occured
*/
void tfMpc860XmitError(ttUserInterface interfaceHandle,int channel)
{
interfaceHandle=interfaceHandle;
/* issue the RESTART TRANSMIT command to the CP */
tfMpc860IssueCommand(TM_MPC860_RESTART_TX | ( channel << 6));
}
/*
* tfMpc860Receive
* Receive a buffer from the chip and pass back to the stack
*/
int tfMpc860Receive(ttUserInterface interfaceHandle,
char TM_FAR **dataPtrPtr,
int TM_FAR *lengthPtr,
ttUserBufferPtr userBufferHandlePtr)
{
int errorCode;
ttMpc860BufDescPtr bufDescPtr;
unsigned short *bdStatusPtr;
errorCode=TM_ENOERROR;
bdStatusPtr = &tlMpc860RecvBufDescPtr->bdStatus;
/* Skip pass error packets who are not empty */
if ((!(*bdStatusPtr & TM_MPC860_RECV_EMPTY)) &&
(*bdStatusPtr & TM_MPC860_ERROR_RECV))
{
tvMpc860RecvErrorCount++;
/* Return the userBuffer Handle for this data pointer */
if (*bdStatusPtr & TM_MPC860_RECV_WRAP)
{
tlMpc860RecvBufDescPtr = tlMpc860RecvBufDescStartPtr;
tlUserBufferPtr=tlUserBufferList;
}
else
{
tlMpc860RecvBufDescPtr++;
tlUserBufferPtr++;
}
errorCode=TM_EWOULDBLOCK;
}
else
{
/* Check to see if we own the Buffer Descriptor */
if (*bdStatusPtr & TM_MPC860_RECV_EMPTY)
{
/* Will only happen when refill cleans up error before we are called here */
tvMpc860RecvErrorCount++;
/* Return the userBuffer Handle for this data pointer */
if (*bdStatusPtr & TM_MPC860_RECV_WRAP)
{
tlMpc860RecvBufDescPtr = tlMpc860RecvBufDescStartPtr;
tlUserBufferPtr=tlUserBufferList;
}
else
{
tlMpc860RecvBufDescPtr++;
tlUserBufferPtr++;
}
errorCode=TM_EWOULDBLOCK;
}
else
{
bufDescPtr=tlMpc860RecvBufDescPtr++;
/* Return the userBuffer Handle for this data pointer */
*userBufferHandlePtr = *tlUserBufferPtr++;
if (*bdStatusPtr & TM_MPC860_RECV_WRAP)
{
tlMpc860RecvBufDescPtr = tlMpc860RecvBufDescStartPtr;
tlUserBufferPtr=tlUserBufferList;
}
/* We are returning the pointer to the data */
*dataPtrPtr = (char TM_FAR *)(bufDescPtr->bdDataPtr);
/* Zero out the bufferPtr so we can refill it later */
bufDescPtr->bdDataPtr=(void TM_FAR *)0;
/* We are returning the length */
*lengthPtr = bufDescPtr->bdLength;
/* Up our packet count */
tvMpc860RecvPacketCount++;
}
}
return(errorCode);
}
/*
* Interrupt called on a busy condition on the line.
* Lost some frames here.
*/
void tfMpc860Busy(ttUserInterface interfaceHandle, int channel)
{
interfaceHandle=interfaceHandle;
channel=channel;
tvMpc860BusyPacketCount++;
}
/*
* tfMpc860IssueCmd() is used to send commands to the communication processor
* and waits till the command is completed
*/
void tfMpc860IssueCommand(unsigned short command)
{
unsigned short *commandReg;
/* Save the command register for the CP */
commandReg = &tlMpc860Ptr->cp_cr;
/* Issue the command */
*commandReg = (command | TM_MPC860_COMMAND_FLAG);
/* wait for the CP zero the CMD_FLG */
while( (*(volatile short *)commandReg) & TM_MPC860_COMMAND_FLAG )
{
/*
* If this loop never exits:
*
* 1) check to make sure that the TM_MPC860_IMMR_LOC is correct
*
* 2) that the tlMpc860 value is correct and has been initialized
*
* 3) Make sure the compiler has generated good code
* Some compilers have been known to just AND a CPU register with
* TM_MPC860_COMMAND_FLAG instead of ANDING the contents of the
* memory location for commandReg with TM_MPC860_COMMAND_FLAG.
* WORK AROUND: move the check into a seperate function
* and call that function from inside this loop.
*/
;
}
}
/*
* This routine is preparing for each SCC a pool of READY buffer
* descriptors that are ready to recieve. The last buffer descriptor
* has the wrap bit set.
*/
void tfMpc860CreateRecvPool(int channel, int maxBd)
{
int i;
ttMpc860BufDescPtr tempBufDescPtr;
struct ethernet_pram *enetPramAddr;
struct scc_regs *regs;
ttUserBuffer userBuffer;
enetPramAddr = &tlMpc860Ptr->pram[channel].enet_scc;
regs = &tlMpc860Ptr->scc_regs[channel];
tempBufDescPtr = TM_MPC860_RECV_BD_ADDR(tlMpc860Ptr,enetPramAddr);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -