📄 405gp_enet.c.svn-base
字号:
} /* set up interrupt handler */ /* setup interrupt controler to take interrupts from the MAL & EMAC */ mtdcr (uicsr, 0xffffffff); /* clear pending interrupts */ 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 (malesr, 0xffffffff); /* clear pending interrupts */ mtdcr (maltxdeir, 0xffffffff); /* clear pending interrupts */ mtdcr (malrxdeir, 0xffffffff); /* clear pending interrupts */ 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_ISR, 0xffffffff); /* clear pending interrupts */ out32 (EMAC_IER, emac_ier); mtmsr (msr); /* enable interrupts again */ bis_save = bis; first_init = 1; return (1);}static int ppc_4xx_eth_send (struct eth_device *dev, 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; __asm__ volatile ("eieio"); out32 (EMAC_TXM0, in32 (EMAC_TXM0) | EMAC_TXM0_GNP0);#ifdef INFO_405_ENET packetSent++;#endif /*-----------------------------------------------------------------------+ * 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 * If there is an error, an interrupt should * happen when we return */ time_now = get_timer (0); if ((time_now - time_start) > 3000) { return (-1); } } else { return (len); } }}#if defined(CONFIG_440)/*-----------------------------------------------------------------------------+| 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 = 0; unsigned long mal_rx_eob; unsigned long my_uic0msr, my_uic1msr; /* enter loop that stays in interrupt code until nothing to service */ do { serviced = 0; my_uic0msr = mfdcr (uic0msr); my_uic1msr = mfdcr (uic1msr); if (!(my_uic0msr & UIC_MRE) && !(my_uic1msr & (UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE))) { /* not for us */ return (rc); } /* get and clear controller status interrupts */ /* look at Mal and EMAC interrupts */ if ((my_uic0msr & UIC_MRE) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { /* we have a MAL interrupt */ mal_isr = mfdcr (malesr); /* look for mal error */ if (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE)) { mal_err (mal_isr, my_uic0msr, MAL_UIC_DEF, MAL_UIC_ERR); serviced = 1; rc = 0; } } if (UIC_ETH0 & my_uic1msr) { /* 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) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (uic0sr, UIC_MRE); /* Clear */ mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* 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_uic0msr & UIC_MRE) { 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 (uic0sr, UIC_MRE); /* Clear */ mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ } while (serviced); return (rc);}#else /* CONFIG_440 *//*-----------------------------------------------------------------------------+ * 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 = 0; 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); return (rc);}#endif /* CONFIG_440 *//*-----------------------------------------------------------------------------+ * MAL Error Routine *-----------------------------------------------------------------------------*/static void mal_err (unsigned long isr, unsigned long uic, unsigned long maldef, unsigned long mal_errr){ mtdcr (malesr, isr); /* clear interrupt */ /* clear DE interrupt */ mtdcr (maltxdeir, 0xC0000000); mtdcr (malrxdeir, 0x80000000);#ifdef INFO_405_ENET printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);#else#if 0 /* * MAL error is RX DE error (out of rx buffers)! This is OK here, upon * many incoming packets with only 4 rx buffers. */ printf ("M"); /* just to see something upon mal error */#endif#endif eth_init (bis_save); /* start again... */}/*-----------------------------------------------------------------------------+ * EMAC Error Routine *-----------------------------------------------------------------------------*/static void emac_err (unsigned long isr){ printf ("EMAC error occured.... ISR = %lx\n", 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; int loop_count = 0; 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) || (loop_count >= NUM_RX_BUFF)) break; loop_count++; 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 */ /* AS.HARNOIS */ /* Check if user has already eaten buffer */ /* if not => ERROR */ else if (rx_ready[rx_i_index] != -1) { if (is_receiving) printf ("ERROR : Receive buffers are full!\n"); break; } else { stats.emac.rx_frames++; stats.emac.rx += data_len; ef_ptr = (struct enet_frame *) rx[i].data_ptr;#ifdef INFO_405_ENET packetReceived++;#endif /* AS.HARNOIS * use ring buffer */ rx_ready[rx_i_index] = i; rx_i_index++; if (NUM_RX_BUFF == rx_i_index) rx_i_index = 0; /* printf("X"); /|* test-only *|/ */ /* AS.HARNOIS * free receive buffer only when * buffer has been handled (eth_rx) rx[i].ctrl |= MAL_RX_CTRL_EMPTY; */ } /* if data_len */ } /* while */ } /* if EMACK_RXCHL */}static int ppc_4xx_eth_rx (struct eth_device *dev){ int length; int user_index; unsigned long msr; is_receiving = 1; /* tell driver */ for (;;) { /* AS.HARNOIS * use ring buffer and * get index from rx buffer desciptor queue */ user_index = rx_ready[rx_u_index]; if (user_index == -1) { length = -1; break; /* nothing received - leave for() loop */ } msr = mfmsr (); mtmsr (msr & ~(MSR_EE)); length = rx[user_index].data_len; /* Pass the packet up to the protocol layers. */ /* NetReceive(NetRxPackets[rxIdx], length - 4); */ /* NetReceive(NetRxPackets[i], length); */ NetReceive (NetRxPackets[user_index], length - 4); /* Free Recv Buffer */ rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY; /* Free rx buffer descriptor queue */ rx_ready[rx_u_index] = -1; rx_u_index++; if (NUM_RX_BUFF == rx_u_index) rx_u_index = 0;#ifdef INFO_405_ENET packetHandled++;#endif mtmsr (msr); /* Enable IRQ's */ } is_receiving = 0; /* tell driver */ return length;}#if defined(CONFIG_NET_MULTI)int ppc_4xx_eth_initialize(bd_t *bis){ struct eth_device *dev; int eth_num = 0; dev = malloc (sizeof *dev); if (dev == NULL) { printf(__FUNCTION__ ": Cannot allocate eth_device\n"); return (-1); } sprintf(dev->name, "ppc_4xx_eth%d", eth_num); dev->priv = (void *) eth_num; dev->init = ppc_4xx_eth_init; dev->halt = ppc_4xx_eth_halt; dev->send = ppc_4xx_eth_send; dev->recv = ppc_4xx_eth_rx; eth_register (dev);}#else /* !defined(CONFIG_NET_MULTI) */void eth_halt (void){ ppc_4xx_eth_halt(NULL);}int eth_init (bd_t *bis){ return (ppc_4xx_eth_init(NULL, bis));}int eth_send(volatile void *packet, int length){ return (ppc_4xx_eth_send(NULL, packet, length));}int eth_rx(void){ return (ppc_4xx_eth_rx(NULL));}#endif /* !defined(CONFIG_NET_MULTI) */#endif /* CONFIG_405GP */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -