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

📄 trmpc860.c

📁 ppc860平台上移植uc OS的实例
💻 C
📖 第 1 页 / 共 3 页
字号:
/* 
 * SOURCE FILE FOR Motorola MPC860 QUICC Sample Driver
 *
 * This device driver is derived from the Ethernet Bridge example from
 * Motorola.
 * It has been modified to interface to the Treck TCP/IP stack and to
 * provide readability.
 *
 * Since it is a derived work, it remains the property of Motorola Corp.
 *
 * We have left the definintions of the mpc860 registers as they
 * are in the QUICC user manual
 *
 * This is why they do not match TRECK coding standards.
 */


#include <trsocket.h>
#include <trmpc860.h>


/* 
 * IMPORTANT
 * If the mpc860 device only receives a few frames and stops forever,
 * make sure that you are calling the tfMpc860RefillScc1RecvPool()
 * function from a low priority task
 */


/*    
 * Since we do not accept SHORT frames, we use the SHORT bit to 
 * mean that this frame has been notified
 * IF THIS DRIVER IS CHANGED TO ALLOW SHORT FRAMES, ANOTHER BIT
 * WILL NEED TO BE USED
 */
#define TM_MPC860_NOTIFIED TM_MPC860_RECV_E_SHORT
#define TM_MPC860_ERROR_RECV (TM_MPC860_RECV_ERROR & (~TM_MPC860_NOTIFIED))

/*
 * Local Function Prototypes
 */
void tfMpc860CreateXmitPool(int channel, int maxBd);
void tfMpc860CreateRecvPool(int channel, int maxBd);
void tfMpc860IssueCommand(unsigned short command);
void tfMpc860Busy(ttUserInterface interfaceHandle, int channel);
void tfMpc860RecvFrame(ttUserInterface interfaceHandle,
                      int             channel);
void tfMpc860XmitError(ttUserInterface interfaceHandle,int channel);
void tfMpc860Scc1SendComplete(ttUserInterface interfaceHandle);
void tfMpc860EtherUp(int channel);
void tfMpc860EtherScc1BoardInit(void);
void tfMpc860EtherScc1Init(void);
void tfMpc860RefillScc1RecvPool(void);
void tfMpc860Down(int channel);

int tfMpc860SerialClose(ttUserInterface interfaceHandle);
void tfMpc860SerialUp(int channel);
int tfMpc860SerialOpen(ttUserInterface interfaceHandle);
void tfMpc860SerialScc4BoardInit(void);
void tfMpc860SerialScc4Init(void);


static ttMpc860Ptr tlMpc860Ptr;

static ttMpc860BufDescPtr tlMpc860XmitBufDescPtr;
static ttMpc860BufDescPtr tlMpc860XmitIsrBufDescPtr;
static ttMpc860BufDescPtr tlMpc860XmitBufDescStartPtr;

static ttMpc860BufDescPtr tlMpc860RecvBufDescPtr;
static ttMpc860BufDescPtr tlMpc860RecvIsrBufDescPtr;
static ttMpc860BufDescPtr tlMpc860RecvBufDescStartPtr; 
static ttMpc860BufDescPtr tlScatterBufferStart;

static ttMpc860BufDescPtr tlMpc860RecvRefillBufDescPtr; 
unsigned long     tvMpc860RecvErrorCount;
unsigned long     tvMpc860RecvPacketCount;
unsigned long     tvMpc860SendPacketCount;
unsigned long     tvMpc860BusyPacketCount;
unsigned long     tvMpc860XmitWait;
unsigned long     tvMpc860IsrRecvErrorCount;

/*
 * Four Interface handles for four SCC's 
 */
static ttUserInterface tlInterfaceArray[4];

/*
 * Table of ttUserBuffer Handles
 */
static ttUserBuffer    tlUserBufferList[TM_MPC860_ETHER_MAX_RECV_BUFD];

/*
 * Our index to the ttUserBuffer's
 */
static ttUserBufferPtr tlUserBufferPtr; 
static ttUserBufferPtr tlUserRefillBufferPtr; 



/*
 * Return the Physical Address for the device
 * For the MPC860, it should be read from EEPROM
 * because every ethernet address is Unique
 *
 * THIS ROUTINE MUST BE MODIFIED!
 *
 * To get an ethernet address address block for 
 * your company, you need to contact IEEE Standards
 * or visit http://standards.ieee.org/faqs/OUI.html
 * for information on getting an Company ID/OUI
 */
int tfMpc860GetPhyAddr(ttUserInterface userInterface,
        char *address)
{
/* 
 * We don't use the interface handle here, but we keep the compiler
 * from complaining about unused formal parameters
 */
    userInterface=userInterface;
    address[0]=0x00;
    address[1]=0xea;
    address[2]=0xc0;
    address[3]=0xf0;
    address[4]=0x08;
    address[5]=0x60;
    return 0;
}


/* 
 * Initialize SCC1 to be an ethernet channel
 */
void tfMpc860EtherScc1Init()
{
    char                  etherAddr[6];
    struct ethernet_pram *enet_pram;
    struct scc_regs *regs;

/* Retrieve the Ethernet Address */
    tfMpc860GetPhyAddr((ttUserInterface)0,
            etherAddr);

    enet_pram = &tlMpc860Ptr->pram[0].enet_scc;          
    regs = &tlMpc860Ptr->scc_regs[0];

/* Disable transmit/receive */
    regs->scc_gsmrl = 0;

/* 
 * Initialize paramater ram 
 */

/* points to start of receiving ring */
    enet_pram->rbase =   TM_MPC860_SCC1_RECV_BASE;
/* points to start of transmiting ring */
    enet_pram->tbase =   TM_MPC860_SCC1_XMIT_BASE;   
/* Function Codes for Transmit and Receive */
    enet_pram->rfcr =    TM_MPC860_SCC1_RECV_FUNC_CODE;
    enet_pram->tfcr =    TM_MPC860_SCC1_XMIT_FUNC_CODE;
/* We always receive a full ethernet frame so we set it to 1518 */
    enet_pram->mrblr =   TM_MPC860_SCC1_MAX_RECV_BUF_LEN;
/* A good ethernet CRC */
    enet_pram->c_mask =  TM_MPC860_ETHER_CRC_MASK;
/* The CRC we start with */
    enet_pram->c_pres =  TM_MPC860_ETHER_CRC_PRES;
/* These three registers are cleared for clarity sake */
    enet_pram->crcec =   TM_MPC860_ETHER_CRCEC;
    enet_pram->alec =    TM_MPC860_ETHER_ALEC;
    enet_pram->disfc =   TM_MPC860_ETHER_DISFC;
/* Pad Character */
    enet_pram->pads =    TM_MPC860_ETHER_PADS;
/* Max Retries when we have a collision */
    enet_pram->ret_lim = TM_MPC860_ETHER_RETRY_LIMIT;
/* Maximum Ethernet Frame Length (Always 1518) */
    enet_pram->mflr =    TM_MPC860_ETHER_MAX_FRAME_LEN;
/* Minimum Ethernet Frame Length (Always 64) */
    enet_pram->minflr =  TM_MPC860_ETHER_MIN_FRAME_LEN;
/* Maximum DMA Counts */
    enet_pram->maxd1 =   TM_MPC860_ETHER_MAX_DMA1_COUNT;
    enet_pram->maxd2 =   TM_MPC860_ETHER_MAX_DMA2_COUNT; 
/* Group Addresses */
    enet_pram->gaddr1 =  TM_MPC860_ETHER_GROUP_ADDR1;    
    enet_pram->gaddr2 =  TM_MPC860_ETHER_GROUP_ADDR2;    
    enet_pram->gaddr3 =  TM_MPC860_ETHER_GROUP_ADDR3;    
    enet_pram->gaddr4 =  TM_MPC860_ETHER_GROUP_ADDR4;    
/* 
 * Our physical (Ethernet) address (IN LITTLE ENDIAN)
 * If the physical address is:
 * 0x112233445566
 *
 * It is stored like this:
 * paddr_l=0x2211
 * paddr_m=0x4433
 * paddr_h=0x6655
 * 
 * If not done correctly, the MPC860 will NOT receive any packets
 * with its destination address 
 */
    enet_pram->paddr_l = ((unsigned short)etherAddr[0]        &0x00ff)|
                         ((((unsigned short)etherAddr[1])<<8) &0xff00);
    enet_pram->paddr_m = ((unsigned short)etherAddr[2]        &0x00ff)|
                         ((((unsigned short)etherAddr[3])<<8) &0xff00);
    enet_pram->paddr_h = ((unsigned short)etherAddr[4]        &0x00ff)|
                         ((((unsigned short)etherAddr[5])<<8) &0xff00);

    enet_pram->p_per =   TM_MPC860_ETHER_P_PER;
/* Individual Hash Addresses */
    enet_pram->iaddr1 =  TM_MPC860_ETHER_INDV_ADDR1; 
    enet_pram->iaddr2 =  TM_MPC860_ETHER_INDV_ADDR2; 
    enet_pram->iaddr3 =  TM_MPC860_ETHER_INDV_ADDR3; 
    enet_pram->iaddr4 =  TM_MPC860_ETHER_INDV_ADDR4; 
/* Temp Registers */
    enet_pram->taddr_h = TM_MPC860_ETHER_T_ADDR_H;   
    enet_pram->taddr_m = TM_MPC860_ETHER_T_ADDR_M;
    enet_pram->taddr_l = TM_MPC860_ETHER_T_ADDR_L;
    tvMpc860RecvPacketCount=0L;
    tvMpc860SendPacketCount=0L;
    tvMpc860XmitWait=0L;
    tvMpc860RecvErrorCount=0L;
    tvMpc860IsrRecvErrorCount=0L;
    tlScatterBufferStart=(ttMpc860BufDescPtr)0;

/* Tell the CP to initialize our Recv/Xmit parameters */
    tfMpc860IssueCommand(TM_MPC860_INIT_RXTX_SCC1);
}


/* 
 * Initialize SCC1 to be an ethernet channel    
 */
void tfMpc860EtherScc1BoardInit()
{
    unsigned char  scc1Vector;
    unsigned long  scc1Location;

/*  tlMpc860Ptr->sim_mcr =   0x608f; */

/*
 * IMPLEMENTATION NOTE:
 *
 * This routine is very board specific
 * In this example we use the Atlas Communications Engines
 * DARWIN devlopment board for an example
 * We assume the the ethernet is in SLOT 0 and at SCC1
 * on the DARWIN
 *
 * Please refer to your boards design to modify this routine
 */

/* clear previous scc1 settings */
        tlMpc860Ptr->si_sicr &= ~(0x3f);  
/* Atlas DARWIN Setup */
    tlMpc860Ptr->si_sicr |=  TM_MPC860_SI_SCC1_RCS_CLK1 |
                             TM_MPC860_SI_SCC1_TCS_CLK2;
                             
/* Disconnect the clock routing source */
    tlMpc860Ptr->si_sicr &=  ~TM_MPC860_SI_SCC1_CONNECT;
                            
/* Make PortA Pins 6,7,14,15 for onchip use */
    tlMpc860Ptr->pio_padir &= ~(TM_MPC860_PORTA_PA6 |
                                TM_MPC860_PORTA_PA7 |
                                TM_MPC860_PORTA_PA14 |
                                TM_MPC860_PORTA_PA15);
    
/* 
 * Use PortA pins 15,14 for SCC1 Ethernet RX/TX and 
 * pins 6,7 for Ethernet TCLK and RCLK 
 */
    tlMpc860Ptr->pio_papar |= TM_MPC860_PORTA_PA6 |
                              TM_MPC860_PORTA_PA7 |
                              TM_MPC860_PORTA_PA14 |
                              TM_MPC860_PORTA_PA15;
/* Turn off the Open Drain */
    tlMpc860Ptr->pio_paodr &= ~TM_MPC860_PORTA_PA14;
                            
/* Clear the pending and in-service registers */
    tlMpc860Ptr->intr_cipr = TM_MPC860_SCC1_INT_MASK;
    tlMpc860Ptr->intr_cisr = TM_MPC860_SCC1_INT_MASK;
/* Set the CP mask register to accept interrupts from SCC1 */
    tlMpc860Ptr->intr_cimr |= TM_MPC860_SCC1_INT_MASK;

    tlMpc860Ptr->sdma_sdcr=TM_MPC860_SDMA_ARB_ID; 

    
 /* PortC Pins 10 & 11 are onchip */
    tlMpc860Ptr->pio_pcdir &=   ~(TM_MPC860_PORTC_PC10 |
                                  TM_MPC860_PORTC_PC11);
 /* PortC Pins 10 & 11 are onchip */
    tlMpc860Ptr->pio_pcpar &=   ~(TM_MPC860_PORTC_PC10 |
                                  TM_MPC860_PORTC_PC11);
                                 
/*
 * Use Pins 10 and 11 (SCC1 CD and CTS) for Ethernet RENA and CLSN  
 */
    tlMpc860Ptr->pio_pcso|=    TM_MPC860_PORTC_PC10 |
                               TM_MPC860_PORTC_PC11;
                              
/* Clear the data register for pins 10 and 11 */
    tlMpc860Ptr->pio_pcdat&=   ~(TM_MPC860_PORTC_PC10 |
                                 TM_MPC860_PORTC_PC11);

/*
 * Port B External Signals 
 * PB14,PB15 are clock select
 * PB26 is Link Enable
 * PB27 Is Full Duplex Select
 */
    tlMpc860Ptr->pip_pbdir |= TM_MPC860_PORTB_PB14 |
                              TM_MPC860_PORTB_PB15 |
                              TM_MPC860_PORTB_PB27 |
                              TM_MPC860_PORTB_PB26;
                                
    tlMpc860Ptr->pip_pbpar &= ~(TM_MPC860_PORTB_PB14 |
                                TM_MPC860_PORTB_PB15 |
                                TM_MPC860_PORTB_PB27 |
                                TM_MPC860_PORTB_PB26);
/* Set clock select to 00 */
    tlMpc860Ptr->pip_pbdat &= ~(TM_MPC860_PORTB_PB14 |
                                TM_MPC860_PORTB_PB15);
/* Set Link Enable */
    tlMpc860Ptr->pip_pbdat |=  TM_MPC860_PORTB_PB26;                                

/* Turn OFF Full Duplex Mode */
    tlMpc860Ptr->pip_pbdat &=  ~TM_MPC860_PORTB_PB27;                                
    


/*
 * IMPLEMENTATION NOTE:
 *
 * The Actual SCC1 ISR Wrapper Function in installed here
 * It must call the tfMpc860Scc1HandlerIsr function
 * This routine may be in "C" if it is supported
 * or assembly if not.  It is VERY RTOS dependent
 * so it cannot be provided with the driver
 *
 * With some RTOS's a wrapper function may not be
 * needed.  All the driver cares about is that the
 * function tfMpc860Scc1HandlerIsr function is called
 * when the interrupt occurs.
 *
 */

/* Port B pin 19 is Ethernet TENA for DARWIN */
    tlMpc860Ptr->pip_pbpar |= TM_MPC860_PORTB_PB19;
    tlMpc860Ptr->pip_pbdir |= TM_MPC860_PORTB_PB19;

/* Install the wrapper function */
    tfKernelInstallIsrHandler(tfMpc860Scc1Isr,TM_MPC860_SCCA_INT);
}



/* 
 * Enable the SCC's  to recieve and transmit 
 */
void tfMpc860EtherUp(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;

/* Clear the appropriate bit in the CISR */
    switch (channel)
    {
        case TM_MPC860_SCC1_CHANNEL:
            tlMpc860Ptr->intr_cisr = TM_MPC860_SCC1_INT_MASK;
            break;
        case TM_MPC860_SCC2_CHANNEL:
            tlMpc860Ptr->intr_cisr = TM_MPC860_SCC2_INT_MASK;
            break;
        case TM_MPC860_SCC3_CHANNEL:
            tlMpc860Ptr->intr_cisr = TM_MPC860_SCC3_INT_MASK;
            break;
        case TM_MPC860_SCC4_CHANNEL:
            tlMpc860Ptr->intr_cisr = TM_MPC860_SCC4_INT_MASK;
            break;
        default:
            break;
    }


/* 
 * mask the events we sich to interrupt on
 */
    regs->scc_sccm = 
/* An error in transmitting has occured */
                     TM_MPC860_INTR_ETHER_E_XMIT |
/* A buffer has completed transmitting */
                     TM_MPC860_INTR_ETHER_XMIT_B |
/* A ethernet frame has been received */
                     TM_MPC860_INTR_ETHER_RECV_F |
/* The busy condition has occured */
                     TM_MPC860_INTR_ETHER_BUSY;
    
/* SCC1 data sync reg  (The pattern for Ethernet)*/
    regs->scc_dsr=   TM_MPC860_SCC_FRAME_SYNC_ETHER;         

/* protocol specific mode register */
    regs->scc_psmr = 
/* To disable the reception of Broadcast packets uncomment this line */
/*                     TM_MPC860_ETHER_BROADCAST | */
/* Turn on the CRC for ethernet */
                     TM_MPC860_ETHER_ENABLE_CRC | 
/* Ignore 22 bits for ethernet */
                     TM_MPC860_ETHER_NBITS_IGNORED;


/* SCC general mode reg */
    regs->scc_gsmrh = 0;

/* SCC general mode reg */
    regs->scc_gsmrl = 
/* Transmit Clock Inversion */
                      TM_MPC860_XMIT_CLOCK_INV | 
/* Preamble Bit Length (48 always for ethernet) */
                      TM_MPC860_PREAMBLE_48 | 
/* Preamble Bit Pattern (Alternating '1' and '0' for ethernet */
                      TM_MPC860_PREAMBLE_PAT_10 | 
/* Ethernet Mode */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -