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

📄 trmpc860.c

📁 ppc860平台上移植uc OS的实例
💻 C
📖 第 1 页 / 共 3 页
字号:
                      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 + -