📄 scceth.c
字号:
/*
* File: scceth.c
* Purpose: Driver for MPC8XX Ethernet on SCCx
*
* Notes: This file included by sccXeth.c
*
* Author: Eric DeVolder
* Date:
*
* Modifications:
*
*/
/********************************************************************/
/*
* In order to use this dBUG driver, the following assumptions are made:
*
* Ethernet on SCC1
* o the appropriate CLKx pins are configured for Eth Tx & Rx clocks
* o Pin PA14 allocated for SCC1 TXD1
* o Pin PA15 allocated for SCC1 RXD1
* o Pin PB19 allocated for SCC1 RTS1
* o Pin PC10 allocated for SCC1 CD1
* o Pin PC11 allocated for SCC1 CTS1
* o the macro BD_SCC1_TX exists for allocating a BD for Eth Tx
* o the macro BD_SCC1_RX exists for allocating a BD for Eth Rx
* o the macro BD_SCC1_RX_NUM exists indicating size of Rx pool
* o the Ethernet transceiver is enabled and in normal mode
* o the interrupt handler mpc8xx_scc1_handler() is installed elsewhere
*
* Ethernet on SCC2
* o the appropriate CLKx pins are configured for Eth Tx & Rx clocks
* o Pin PA12 allocated for SCC2 TXD2
* o Pin PA13 allocated for SCC2 RXD2
* o Pin PB18 allocated for SCC2 RTS2
* o Pin PC8 allocated for SCC2 CD2
* o Pin PC9 allocated for SCC2 CTS2
* o the macro BD_SCC2_TX exists for allocating a BD for Eth Tx
* o the macro BD_SCC2_RX exists for allocating a BD for Eth Rx
* o the macro BD_SCC2_RX_NUM exists indicating size of Rx pool
* o the Ethernet transceiver is enabled and in normal mode
* o the interrupt handler mpc8xx_scc2_handler() is installed elsewhere
*
* The pin configurations are normally performed in mpcinit.c, and the
* macros defined in board.h.
*/
#include <dbug.h>
#include "scceth.h"
/********************************************************************/
#if (defined(SCC1ETH))
#define _BD_SCC_TX_ BD_SCC1_TX
#define _BD_SCC_RX_ BD_SCC1_RX
#define _BD_SCC_RX_NUM_ BD_SCC1_RX_NUM
#define _MPC8XX_CP_CPCR_CHANNEL_SCCx_ MPC8XX_CP_CPCR_CHANNEL_SCC1
#define SCC_RESET mpc8xx_scc1_reset
#define SCC_SEND mpc8xx_scc1_send
#define SCC_RECEIVE mpc8xx_scc1_receive
#define SCC_START mpc8xx_scc1_start
#define SCC_STOP mpc8xx_scc1_stop
#define SCC_HANDLER mpc8xx_scc1_handler
#elif (defined(SCC2ETH))
#define _BD_SCC_TX_ BD_SCC2_TX
#define _BD_SCC_RX_ BD_SCC2_RX
#define _BD_SCC_RX_NUM_ BD_SCC2_RX_NUM
#define _MPC8XX_CP_CPCR_CHANNEL_SCCx_ MPC8XX_CP_CPCR_CHANNEL_SCC2
#define SCC_RESET mpc8xx_scc2_reset
#define SCC_SEND mpc8xx_scc2_send
#define SCC_RECEIVE mpc8xx_scc2_receive
#define SCC_START mpc8xx_scc2_start
#define SCC_STOP mpc8xx_scc2_stop
#define SCC_HANDLER mpc8xx_scc2_handler
#else
#error "Unsupported configuration"
#endif
/********************************************************************/
/*
* Local buffers for DMA'ing Ethernet frames
*/
/* The ELB must be long aligned */
typedef uint32
ELB[1520/4];
static ELB
erx_buf[ _BD_SCC_RX_NUM_ ];
static ELB
etx_buf;
/********************************************************************/
static int
SCC_RESET (NIF *eth_nif)
{
/*
* This routine initializes the SCC for Ethernet, 10Mbit/S.
* The receiver and transmitter are disabled upon exit.
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
MPC8XX_SCC *scc;
MPC8XX_PRAM_SCCETH *sccpram;
MPC8XX_BD *rxbd, *txbd;
unsigned int i;
scc = (MPC8XX_SCC *)&imm-> _SCC_ ;
sccpram = (MPC8XX_PRAM_SCCETH *)&imm->dpram. _SCC_ ;
#if (defined(SCC1ETH))
/*
* Configure SCC1 pins
*/
imm->portio.PAPAR |= ( 0
| MPC8XX_PORTIO_PAPAR_PA14 /* PA14=1, TXD1 */
| MPC8XX_PORTIO_PAPAR_PA15 /* PA15=1, RXD1 */
) ;
imm->portio.PADIR &= ~( 0
| MPC8XX_PORTIO_PADIR_PA14 /* PA14=0, TXD1 */
| MPC8XX_PORTIO_PADIR_PA15 /* PA15=0, RXD1 */
) ;
imm->portio.PAODR &= ~( 0
| MPC8XX_PORTIO_PAODR_PA14 /* PA14=0, Active */
| 0 /* Bit 15 reserved */
) ;
imm->pip.PBPAR &= ~( 0
| MPC8XX_PIP_PBPAR_PB19 /* PB19=0, input until configed */
) ;
imm->pip.PBDIR &= ~( 0
| MPC8XX_PIP_PBDIR_PB19 /* PB19=0, input until configed */
) ;
imm->portio.PCPAR &= ~( 0
| MPC8XX_PORTIO_PCPAR_PC10 /* PC10=0, CD1 */
| MPC8XX_PORTIO_PCPAR_PC11 /* PC11=0, CTS1 */
) ;
imm->portio.PCDIR &= ~( 0
| MPC8XX_PORTIO_PCDIR_PC10 /* PC10=0, CD1 */
| MPC8XX_PORTIO_PCDIR_PC11 /* PC11=0, CTS1 */
) ;
imm->portio.PCSO |= ( 0
| MPC8XX_PORTIO_PCSO_PC10 /* PC10=1, CD1 */
| MPC8XX_PORTIO_PCSO_PC11 /* PC11=1, CTS1 */
) ;
#endif
#if (defined(SCC2ETH))
/*
* Configure SCC2 pins
*/
imm->portio.PAPAR |= ( 0
| MPC8XX_PORTIO_PAPAR_PA12 /* PA12=1, TXD2 */
| MPC8XX_PORTIO_PAPAR_PA13 /* PA13=1, RXD2 */
) ;
imm->portio.PADIR &= ~( 0
| MPC8XX_PORTIO_PADIR_PA12 /* PA12=0, TXD2 */
| MPC8XX_PORTIO_PADIR_PA13 /* PA13=0, RXD2 */
) ;
imm->portio.PAODR &= ~( 0
| MPC8XX_PORTIO_PAODR_PA12 /* PA12=0, Active */
| 0 /* Bit 13 reserved */
) ;
imm->pip.PBPAR &= ~( 0
| MPC8XX_PIP_PBPAR_PB18 /* PB18=0, input until configed */
) ;
imm->pip.PBDIR &= ~( 0
| MPC8XX_PIP_PBDIR_PB18 /* PB18=0, input until configed */
) ;
imm->portio.PCPAR &= ~( 0
| MPC8XX_PORTIO_PCPAR_PC8 /* PC8=0, CD2 */
| MPC8XX_PORTIO_PCPAR_PC9 /* PC9=0, CTS2 */
) ;
imm->portio.PCDIR &= ~( 0
| MPC8XX_PORTIO_PCDIR_PC8 /* PC8=0, CD2 */
| MPC8XX_PORTIO_PCDIR_PC9 /* PC9=0, CTS2 */
) ;
imm->portio.PCSO |= ( 0
| MPC8XX_PORTIO_PCSO_PC8 /* PC8=1, CD2 */
| MPC8XX_PORTIO_PCSO_PC9 /* PC9=1, CTS2 */
) ;
#endif
/*
* Setup buffers for use by SCC
*/
txbd = &imm->dpram.bd[ _BD_SCC_TX_ ];
txbd->status = ( 0
| MPC8XX_BD_SCCETH_TX_STATUS_PAD
| MPC8XX_BD_SCCETH_TX_STATUS_W
| MPC8XX_BD_SCCETH_TX_STATUS_I
| MPC8XX_BD_SCCETH_TX_STATUS_L
| MPC8XX_BD_SCCETH_TX_STATUS_TC
) ;
txbd->length = 0;
txbd->address = (uint32)&etx_buf;
rxbd = &imm->dpram.bd[ _BD_SCC_RX_ ];
eth_nif->next_receive = (int)rxbd; /* point to first rx buf */
for (i = 0; i < _BD_SCC_RX_NUM_; ++i)
{
rxbd->status = ( 0
| MPC8XX_BD_SCCETH_RX_STATUS_E
| MPC8XX_BD_SCCETH_RX_STATUS_I
) ;
rxbd->length = 0;
rxbd->address = (uint32)&erx_buf[i];
++rxbd;
}
/*
* Mark last receive buffer
*/
--rxbd;
rxbd->status |= MPC8XX_BD_SCCETH_RX_STATUS_W;
/*
* Ethernet Parameter RAM
*/
sccpram->scc.RFCR = MPC8XX_PRAM_SCC_FCR_BO_BE;
sccpram->scc.TFCR = MPC8XX_PRAM_SCC_FCR_BO_BE;
sccpram->scc.MRBLR = 1520;
sccpram->scc.TBASE = (uint16)((uint32)&imm->dpram.bd[_BD_SCC_TX_]);
sccpram->scc.RBASE = (uint16)((uint32)&imm->dpram.bd[_BD_SCC_RX_]);
sccpram->eth.C_PRES = ~0;
sccpram->eth.C_MASK = 0xdebb20e3;
sccpram->eth.CRCEC = 0;
sccpram->eth.ALEC = 0;
sccpram->eth.DISFC = 0;
sccpram->eth.PADS = 0;
sccpram->eth.RET_LIM = 15;
sccpram->eth.MFLR = 1520;
sccpram->eth.MAXD1 = 1520;
sccpram->eth.MAXD2 = 1520;
sccpram->eth.MINFLR = ETH_MIN_SIZE;
sccpram->eth.GADDR1 = 0;
sccpram->eth.GADDR2 = 0;
sccpram->eth.GADDR3 = 0;
sccpram->eth.GADDR4 = 0;
sccpram->eth.P_PER = 0;
sccpram->eth.IADDR1 = 0;
sccpram->eth.IADDR2 = 0;
sccpram->eth.IADDR3 = 0;
sccpram->eth.IADDR4 = 0;
sccpram->eth.TADDR_H = 0;
sccpram->eth.TADDR_M = 0;
sccpram->eth.TADDR_L = 0;
sccpram->eth.PADDR1_L = (eth_nif->hwa[1] << 8) | eth_nif->hwa[0];
sccpram->eth.PADDR1_M = (eth_nif->hwa[3] << 8) | eth_nif->hwa[2];
sccpram->eth.PADDR1_H = (eth_nif->hwa[5] << 8) | eth_nif->hwa[4];
/*
* Initialize Tx and Rx Parameters and wait for Ack
*/
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
imm->cp.CPCR = ( 0
| MPC8XX_CP_CPCR_OPCODE_INIT_RX_TX
| _MPC8XX_CP_CPCR_CHANNEL_SCCx_
| MPC8XX_CP_CPCR_FLG
) ;
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
/*
* Configured RTS _after_ SCC is configured, otherwise
* errant transmissions occur!
*/
#if (defined(SCC1ETH))
imm->pip.PBPAR |= MPC8XX_PIP_PBPAR_PB19;
imm->pip.PBDIR |= MPC8XX_PIP_PBDIR_PB19;
#endif
#if (defined(SCC2ETH))
imm->pip.PBPAR |= MPC8XX_PIP_PBPAR_PB18;
imm->pip.PBDIR |= MPC8XX_PIP_PBDIR_PB18;
#endif
/*
* Clear SCC Events
*/
scc->SCCE = ~0;
/*
* Enable ALL Ethernet interrupts
*/
scc->SCCM = ( 0
| MPC8XX_SCC_ETH_SCCM_GRA
| MPC8XX_SCC_ETH_SCCM_TXE
| MPC8XX_SCC_ETH_SCCM_RXF
| MPC8XX_SCC_ETH_SCCM_BSY
| MPC8XX_SCC_ETH_SCCM_TXB
| MPC8XX_SCC_ETH_SCCM_RXB
) ;
/*
* Initialize DSR
*/
scc->DSR = MPC8XX_SCC_ETH_DSR;
/*
* Initialize the PSMR
*/
scc->PSMR = ( 0
| MPC8XX_SCC_ETH_PSMR_CRC_32BIT
/* | MPC8XX_SCC_ETH_PSMR_PRO */
| MPC8XX_SCC_ETH_PSMR_NIB_22
) ;
/*
* Configure SCC as Ethernet
*/
scc->GSMR_H = 0;
scc->GSMR_L = ( 0
| MPC8XX_SCC_GSMR_L_TCI
| MPC8XX_SCC_GSMR_L_TPL_48BIT
| MPC8XX_SCC_GSMR_L_TPP_10
| MPC8XX_SCC_GSMR_L_TDCR_1X
| MPC8XX_SCC_GSMR_L_RDCR_1X
| MPC8XX_SCC_GSMR_L_RENC_NRZ
| MPC8XX_SCC_GSMR_L_TENC_NRZ
| MPC8XX_SCC_GSMR_L_MODE_ETHERNET
) ;
return TRUE;
}
/********************************************************************/
static int
SCC_SEND (
NIF * eth_nif,
HWA_ADDR_P eth_dest,
HWA_ADDR_P eth_src,
uint16 eth_type,
int data_length,
uint8 *eth_data
)
{
/*
* This routine transmits a frame over the ethernet.
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
MPC8XX_PRAM_SCCETH *sccpram;
MPC8XX_BD *txbd;
int i;
uint8 *data;
(void)eth_nif;
sccpram = (MPC8XX_PRAM_SCCETH *)&imm->dpram. _SCC_ ;
txbd = (MPC8XX_BD *)((uint32)sccpram->scc.TBASE + (uint32)imm);
/*
* Make sure buffer is available before proceeding.
*/
while (txbd->status & MPC8XX_BD_SCCETH_TX_STATUS_R)
;
data = (uint8 *)txbd->address;
/*
* Write the destination address
*/
*data++ = eth_dest[0];
*data++ = eth_dest[1];
*data++ = eth_dest[2];
*data++ = eth_dest[3];
*data++ = eth_dest[4];
*data++ = eth_dest[5];
/*
* Write the source address
*/
*data++ = eth_src[0];
*data++ = eth_src[1];
*data++ = eth_src[2];
*data++ = eth_src[3];
*data++ = eth_src[4];
*data++ = eth_src[5];
/*
* Write the type code
*/
*data++ = ((eth_type &0xFF00) >> 8);
*data++ = (eth_type &0x00FF);
/*
* Write the data, the SCC will automatically pad
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -