📄 405gp_enet.c
字号:
emac_ip_addr = *srcaddr;
#endif
if(first_init ==0)
{
/*
* Connect interrupt service routines
*/
irq_install_handler(9, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(10, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(11, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(12, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(13, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(14, (interrupt_handler_t *)enetInt, NULL);
irq_install_handler(15, (interrupt_handler_t *)enetInt, NULL);
}
/* set up interrupt handler */
/* setup interrupt controler to take interrupts from the MAL &
EMAC */
if(first_init ==0)
mtdcr(uicer, mfdcr(uicer) | MAL_UIC_DEF | EMAC_UIC_DEF);
/* set the MAL IER ??? names may change with new spec ??? */
mal_ier = MAL_IER_DE | MAL_IER_NE | MAL_IER_TE | MAL_IER_OPBE |
MAL_IER_PLBE;
mtdcr(malier, mal_ier);
/* Set EMAC IER */
emac_ier = EMAC_ISR_PTLE |
EMAC_ISR_BFCS | EMAC_ISR_PTLE |
EMAC_ISR_ORE | EMAC_ISR_IRE;
if(speed == _100BASET)
emac_ier = emac_ier | EMAC_ISR_SYE;
out32 (EMAC_IER, emac_ier);
/* if(first_init ==0)*/ /* test-only */
set_msr(msr); /* enable external */
first_init =1;
return (0);
}
/*-----------------------------------------------------------------------------+
+-----------------------------------------------------------------------------*/
int eth_send(volatile void *ptr, int len)
{
struct enet_frame *ef_ptr;
ulong time_start, time_now;
unsigned long temp_txm0;
ef_ptr = (struct enet_frame *) ptr;
/*-----------------------------------------------------------------------+
| Copy in our address into the frame.
+-----------------------------------------------------------------------*/
(void) memcpy (ef_ptr->source_addr, emac_hwd_addr, ENET_ADDR_LENGTH);
/*-----------------------------------------------------------------------+
| If frame is too long or too short, modify length.
+-----------------------------------------------------------------------*/
if (len > ENET_MAX_MTU)
len = ENET_MAX_MTU;
// memcpy ((void *) &tx_buff[tx_slot], (const void *) ptr, len);
memcpy ((void *) txbuf_ptr, (const void *) ptr, len);
/*-----------------------------------------------------------------------+
| set TX Buffer busy, and send it
+-----------------------------------------------------------------------*/
tx[tx_slot].ctrl = (MAL_TX_CTRL_LAST |
EMAC_TX_CTRL_GFCS | EMAC_TX_CTRL_GP) &
~(EMAC_TX_CTRL_ISA | EMAC_TX_CTRL_RSA);
if ((NUM_TX_BUFF - 1) == tx_slot)
tx[tx_slot].ctrl |= MAL_TX_CTRL_WRAP;
tx[tx_slot].data_len = (short) len;
tx[tx_slot].ctrl |= MAL_TX_CTRL_READY;
out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0);
/*-----------------------------------------------------------------------+
| poll unitl the packet is sent and then make sure it is OK
+-----------------------------------------------------------------------*/
time_start = get_timer (0);
while (1)
{
temp_txm0 = in32(EMAC_TXM0);
/* loop until either TINT turns on or 3 seconds elapse */
if ((temp_txm0 & EMAC_TXM0_GNP0) != 0)
{
/* transmit is done, so now check for errors */
/* there is an error, an inerrupt should hapen when we
return */
time_now = get_timer (0);
if ((time_now-time_start) > 3000)
{
return(-1);
}
} else
return (0);
} /* while */
}
/*-----------------------------------------------------------------------------+
| EnetInt.
| EnetInt is the interrupt handler. It will determine the
| cause of the interrupt and call the apporpriate servive
| routine.
+-----------------------------------------------------------------------------*/
int
enetInt ()
{
int serviced;
int rc = -1; /* default to not us */
unsigned long mal_isr;
unsigned long emac_isr;
unsigned long mal_rx_eob;
unsigned long my_uicmsr;
/* enter loop that stays in interrupt code until nothing to service */
do
{
serviced = 0;
my_uicmsr = mfdcr(uicmsr);
if ((my_uicmsr & (MAL_UIC_DEF | EMAC_UIC_DEF)) == 0)
{ /* not for us */
return (rc);
}
/* get and clear controller status interrupts */
/* look at Mal and EMAC interrupts */
if ((MAL_UIC_DEF & my_uicmsr) != 0)
{ /* we have a MAL interrupt */
mal_isr = mfdcr(malesr);
/* look for mal error */
if ((my_uicmsr & MAL_UIC_ERR) !=0)
{
mal_err (mal_isr, my_uicmsr,MAL_UIC_DEF,MAL_UIC_ERR);
serviced = 1;
rc = 0;
}
}
if ((EMAC_UIC_DEF & my_uicmsr) !=0)
{ /* look for EMAC errors */
emac_isr = in32 (EMAC_ISR);
if ((emac_ier & emac_isr)!=0)
{
emac_err (emac_isr);
serviced = 1;
rc = 0;
}
}
if (((emac_ier & emac_isr)!=0) | ((MAL_UIC_ERR & my_uicmsr) != 0))
{
mtdcr(uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
return(rc); /* we had errors so get out */
}
/* handle MAL RX EOB interupt from a receive */
/* check for EOB on valid channels */
if ((my_uicmsr & UIC_MAL_RXEOB) !=0)
{
mal_rx_eob = mfdcr(malrxeobisr);
if ((mal_rx_eob & 0x80000000) !=0)
{ /* call emac routine for channel 0 */
/* clear EOB
mtdcr(malrxeobisr, mal_rx_eob); */
enet_rcv (emac_isr);
/* indicate that we serviced an interrupt */
serviced = 1;
rc = 0;
}
}
mtdcr(uicsr, MAL_UIC_DEF | EMAC_UIC_DEF); /* Clear */
}
while (serviced);
if (rc != 0)
{
}
return (rc);
}
/*-----------------------------------------------------------------------------+
| MAL Error Routine
+-----------------------------------------------------------------------------*/
void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef,
unsigned long mal_errr)
{
mtdcr(malesr, isr); /* clear interrupt */
printf ("MAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n\r",
isr, uic, maldef, mal_errr);
#if 0
eth_init(NULL);
#endif
mtdcr(malrxcarr, 0x80000000);
mtdcr(malrxcarr, 0x00000000);
mtdcr(malrxcasr, 0x80000000);
mtdcr(maltxcarr, 0x80000000); /* 2 channels */
mtdcr(maltxcarr, 0x00000000);
mtdcr(maltxcasr, 0x80000000); /* 1 channel */
}
/*-----------------------------------------------------------------------------+
| EMAC Error Routine
+-----------------------------------------------------------------------------*/
void emac_err (unsigned long isr)
{
printf ("EMAC error occured.... ISR = %lx\n\r", isr);
out32(EMAC_ISR, isr);
}
/*-----------------------------------------------------------------------------+
| enet_rcv() handles the ethernet receive data
+-----------------------------------------------------------------------------*/
static void enet_rcv (unsigned long malisr)
{
struct enet_frame *ef_ptr;
unsigned long data_len;
unsigned long rx_eob_isr;
int handled=0;
int i;
rx_eob_isr = mfdcr(malrxeobisr);
if ((0x80000000 >>( EMAC_RXCHL-1)) & rx_eob_isr)
{
/* clear EOB */
mtdcr(malrxeobisr, rx_eob_isr);
/* EMAC RX done */
while (1)
{ /* do all */
i = rx_slot;
if (MAL_RX_CTRL_EMPTY & rx[i].ctrl)
break;
rx_slot++;
if (NUM_RX_BUFF == rx_slot)
rx_slot = 0;
handled++;
data_len = (unsigned long) rx[i].data_len; /* Get len */
if (data_len)
{
if (data_len > ENET_MAX_MTU) /* Check len */
data_len = 0;
else
{
if (EMAC_RX_ERRORS & rx[i].ctrl)
{ /* Check Errors */
data_len = 0;
stats.rx_err_log[rx_err_index] = rx[i].ctrl;
rx_err_index++;
if (rx_err_index == MAX_ERR_LOG)
rx_err_index = 0;
} /* emac_erros */
} /* data_len < max mtu */
} /* if data_len */
if (!data_len)
{ /* no data */
rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */
stats.emac.data_len_err++; /* Error at Rx */
} /* !data_len */
else
{
stats.emac.rx_frames++;
stats.emac.rx += data_len;
ef_ptr = (struct enet_frame *) rx[i].data_ptr;
/*
* Set rx pointer
*/
rx_ptr = i;
// printf("X"); /* test-only */
rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */
} /* if data_len */
} /* while */
} /* if EMACK_RXCHL */
}
int eth_rx(void)
{
int length;
int i;
unsigned long msr;
for (;;)
{
if (rx_ptr == -1)
{
length = -1;
break; /* nothing received - leave for() loop */
}
msr = get_msr();
set_msr(msr & ~(MSR_EE));
i = rx_ptr;
length = rx[i].data_len;
/* Pass the packet up to the protocol layers. */
// NetReceive(NetRxPackets[rxIdx], length - 4);
// NetReceive(NetRxPackets[i], length);
NetReceive(NetRxPackets[i], length - 4);
rx_ptr = -1;
set_msr(msr); /* Enable IRQ's */
}
return length;
}
#endif /* CONFIG_PPC405GP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -