📄 scceth.c
字号:
for (i = 0; i < data_length; i++)
{
*data++ = eth_data[i];
}
for (i = data_length; i < ETH_MIN_SIZE; ++i)
{
*data++ = 0x00;
}
if (data_length < ETH_MIN_SIZE)
{
data_length = ETH_MIN_SIZE;
}
/*
* The SCC will compute the CRC for us.
*/
/*
* Update the BD and send it off!
*/
txbd->length = 6 + 6 + 2 + data_length;
txbd->status = ( 0
| MPC8XX_BD_SCCETH_TX_STATUS_R
| 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
) ;
return TRUE;
}
/********************************************************************/
static void
SCC_RECEIVE (NIF *eth_nif)
{
/*
* This routine pulls one or more ethernet frames from
* the ethernet buffers.
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
MPC8XX_BD *rxbd, *nextbd;
ETH_ADDR eth_src, eth_dest;
uint16 eth_type;
NBUF *frame;
int i, frame_length;
uint8 *rdata;
rxbd = (MPC8XX_BD *)eth_nif->next_receive;
eth_type = 0;
frame = NULL;
frame_length = 0;
do
{
if (rxbd->status & MPC8XX_BD_SCCETH_RX_STATUS_EMASK)
{
/*
* Record the error and clear this BD for future use.
*/
++eth_nif->f_rx_err;
/*
* Update pointer to next valid Rx buffer
*/
goto next_frame;
}
rdata = (uint8 *)rxbd->address;
frame_length = rxbd->length;
/* receive the frame */
eth_dest[0] = *rdata++;
eth_dest[1] = *rdata++;
eth_dest[2] = *rdata++;
eth_dest[3] = *rdata++;
eth_dest[4] = *rdata++;
eth_dest[5] = *rdata++;
eth_src[0] = *rdata++;
eth_src[1] = *rdata++;
eth_src[2] = *rdata++;
eth_src[3] = *rdata++;
eth_src[4] = *rdata++;
eth_src[5] = *rdata++;
eth_type = ((*rdata++) << 8);
eth_type |= *rdata++;
/*
* FIX !!! This is a temporary solution to prevent sending up
* un-necessary packets due to the fragile implementation of TFTP.
*/
if ((eth_dest[0] == 0xFF) && (eth_dest[1] == 0xFF) &&
(eth_dest[2] == 0xFF) && (eth_dest[3] == 0xFF) &&
(eth_dest[4] == 0xFF) && (eth_dest[5] == 0xFF))
{
/*
printf("RX: Ethernet Broadcast hdr FF FF FF FF FF FF\n");
*/
goto next_frame;
}
#if 0
printf("Dst: %02X:%02X:%02X:%02X:%02X:%02X\n",
eth_dest[0],
eth_dest[1],
eth_dest[2],
eth_dest[3],
eth_dest[4],
eth_dest[5]);
printf("Src: %02X:%02X:%02X:%02X:%02X:%02X\n",
eth_src[0],
eth_src[1],
eth_src[2],
eth_src[3],
eth_src[4],
eth_src[5]);
printf("Typ: %04X\n", eth_type);
#endif
if (!nif_proto(eth_nif, eth_type))
goto next_frame;
#if 0
not_me = FALSE;
for (i = 0; i < sizeof(ETH_ADDR); i++)
{
if (eth_src[i] != eth_nif->hwa[i])
{
not_me = TRUE;
break;
}
}
if (!not_me)
goto next_frame;
#endif
/*
* Obtain system RAM buffer for the frame.
*/
if ((frame = nbuf_allocate(frame_length)) == NULL)
{
/*
printf("\n Failed in nbuf_allocate()\n");
*/
goto next_frame;
}
frame_length -= (6 + 6 + 2 + 0/*CRC*/);
for (i = 0; i < frame_length; ++i)
{
frame->data[i] = *rdata++;
}
frame->length = frame_length;
/*
Check if there is any request to abort
*/
if (board_getchar_present()) {
if (board_getchar() == 0x03)
{ /* check for ctrl-c */
printf("\nINFO: SCC received Ctrl-C, abort!\n");
nbuf_allocate(frame_length);
eth_nif->f_err=1;
}
}
nif_proto_handler(eth_nif, eth_type,
&frame->data[0], frame_length);
/*
* This frame has been processed, move on to the next
*/
next_frame:
if (board_getchar_present()) {
if (board_getchar() == 0x03)
{ /* check for ctrl-c */
printf("\nINFO: SCC received Ctrl-C, Abort!\n");
eth_nif->f_err=1;
/*allocate nbuf to allow polling function to read C-c*/
nbuf_allocate(frame_length);
nif_proto_handler(eth_nif, eth_type,
&frame->data[0], frame_length);
}
}
/*
* Update pointer to next valid Rx buffer
*/
rxbd->length = 0;
if (rxbd->status & MPC8XX_BD_SCCETH_RX_STATUS_W)
{
rxbd->status = ( 0
| MPC8XX_BD_SCCETH_RX_STATUS_E
| MPC8XX_BD_SCCETH_RX_STATUS_W
| MPC8XX_BD_SCCETH_RX_STATUS_I
) ;
nextbd = &imm->dpram.bd[_BD_SCC_RX_];
}
else
{
rxbd->status = ( 0
| MPC8XX_BD_SCCETH_RX_STATUS_E
| MPC8XX_BD_SCCETH_RX_STATUS_I
) ;
nextbd = rxbd;
++nextbd;
}
eth_nif->next_receive = (int)nextbd;
rxbd = nextbd;
} while (!(rxbd->status & MPC8XX_BD_SCCETH_RX_STATUS_E));
}
/********************************************************************/
static void
SCC_START (NIF *eth_nif)
{
/*
* This function allows the MPC8XX SCC Ethernet channel to
* start receiving frames from the network.
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
(void)eth_nif;
/*
* Turn off transmitter by giving graceful stop command.
*/
imm->cp.CPCR = ( 0
| MPC8XX_CP_CPCR_OPCODE_GR_STOP_TX
| MPC8XX_CP_CPCR_FLG
| _MPC8XX_CP_CPCR_CHANNEL_SCCx_
) ;
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
/*
* 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)
;
/*
* Enable the Transmitter and Receiver and we're done!
*/
imm-> _SCC_ .GSMR_L |= ( 0
| MPC8XX_SCC_GSMR_L_ENR
| MPC8XX_SCC_GSMR_L_ENT
) ;
}
/********************************************************************/
static void
SCC_STOP (NIF *eth_nif)
{
/*
* This function stops the MPC8XX SCC Ethernet channel from
* receiving frames from the network.
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
(void)eth_nif;
/*
* Turn off the receiver
*/
imm-> _SCC_ .GSMR_L &= ~MPC8XX_SCC_GSMR_L_ENR;
/*
* Turn off transmitter by giving graceful stop command.
*/
imm->cp.CPCR = ( 0
| MPC8XX_CP_CPCR_OPCODE_GR_STOP_TX
| MPC8XX_CP_CPCR_FLG
| _MPC8XX_CP_CPCR_CHANNEL_SCCx_
) ;
/*
* Wait for completion
*/
#if 0
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
#endif
board_second_wait(1);
}
/********************************************************************/
int
SCC_HANDLER (void *dev, void *arg)
{
/*
* This is the interrupt service routine for SCC Ethernet
*/
MPC8XX_IMM *imm = mpc8xx_get_immp();
MPC8XX_PRAM_SCCETH *sccpram;
uint16 scce;
MPC8XX_BD *bd;
NIF *eth_nif = (NIF *)arg;
(void)dev;
sccpram = (MPC8XX_PRAM_SCCETH *)&imm->dpram. _SCC_ ;
/*
* Check the cause of interrupts in SCC
*/
scce = imm-> _SCC_ .SCCE;
if (scce == 0)
{
return FALSE; /* wasn't me! */
}
if (scce & MPC8XX_SCC_ETH_SCCE_GRA)
{
/* printf("Graceful Stop\n"); */
}
if (scce & MPC8XX_SCC_ETH_SCCE_TXE)
{
bd = (MPC8XX_BD *)((uint32)sccpram->scc.TBASE + (uint32)imm);
printf("TXE, BD->status: %04X\n",bd->status);
printf("TXE, BD->length: %04X\n",bd->length);
/*
* Send TRANSMIT RESTART
*/
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
imm->cp.CPCR = ( 0
| MPC8XX_CP_CPCR_OPCODE_RESTART_TX
| _MPC8XX_CP_CPCR_CHANNEL_SCCx_
| MPC8XX_CP_CPCR_FLG
) ;
while (imm->cp.CPCR & MPC8XX_CP_CPCR_FLG)
;
/*
* Resend the packet!
*/
bd->status = ( 0
| MPC8XX_BD_SCCETH_TX_STATUS_R
| 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
) ;
}
if (scce & MPC8XX_SCC_ETH_SCCE_RXF)
{
SCC_RECEIVE (eth_nif);
}
if (scce & MPC8XX_SCC_ETH_SCCE_BSY)
{
/*printf("RX Buf\n");*/
}
if (scce & MPC8XX_SCC_ETH_SCCE_TXB)
{
}
if (scce & MPC8XX_SCC_ETH_SCCE_RXB)
{
printf("RXE\n");
}
/*
* Clear the interrupt
*/
imm-> _SCC_ .SCCE = ~0;
return TRUE;
}
/********************************************************************/
int
mpc8xx_eth_init (NIF *eth_nif)
{
/*
* This function initializes the network interface.
*/
void board_get_ethaddr(uint8 *);
nif_create (eth_nif, "mpc8xx SCC");
eth_nif->nic = (void *)mpc8xx_get_immp();
board_get_ethaddr(ð_nif->hwa[0]);
eth_nif->hwa_size = 6;
eth_nif->mtu = 1500;
eth_nif->reset = SCC_RESET ;
eth_nif->start = SCC_START ;
eth_nif->stop = SCC_STOP ;
eth_nif->send = SCC_SEND ;
eth_nif->receive = (void *)SCC_RECEIVE ;
return TRUE;
}
/********************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -