📄 440gx_enet.c.svn-base
字号:
emac_err (dev, emac_isr); serviced = 1; rc = 0; } } if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */ mtdcr (uic1sr, UIC_ETH0 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ return (rc); /* we had errors so get out */ } } if (hw_p->devnum == 1) { if (UIC_ETH1 & my_uic1msr) { /* look for EMAC errors */ emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; rc = 0; } } if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */ mtdcr (uic1sr, UIC_ETH1 | UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ return (rc); /* we had errors so get out */ } }#if defined (CONFIG_440_GX) if (hw_p->devnum == 2) { if (UIC_ETH2 & my_uic2msr) { /* look for EMAC errors */ emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; rc = 0; } } if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */ mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ mtdcr (uic2sr, UIC_ETH2); return (rc); /* we had errors so get out */ } } if (hw_p->devnum == 3) { if (UIC_ETH3 & my_uic2msr) { /* look for EMAC errors */ emac_isr = in32 (EMAC_ISR + hw_p->hw_addr); if ((hw_p->emac_ier & emac_isr) != 0) { emac_err (dev, emac_isr); serviced = 1; rc = 0; } } if ((hw_p->emac_ier & emac_isr) || (my_uic1msr & (UIC_MS | UIC_MTDE | UIC_MRDE))) { mtdcr (uic0sr, UIC_MRE | UIC_MTE); /* Clear */ mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ mtdcr (uic2sr, UIC_ETH3); return (rc); /* we had errors so get out */ } }#endif /* CONFIG_440_GX */ /* handle MAX TX EOB interrupt from a tx */ if (my_uic0msr & UIC_MTE) { mal_rx_eob = mfdcr (maltxeobisr); mtdcr (maltxeobisr, mal_rx_eob); mtdcr (uic0sr, UIC_MTE); } /* 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 >> hw_p->devnum)) != 0) { /* call emac routine for channel x */ /* clear EOB mtdcr(malrxeobisr, mal_rx_eob); */ enet_rcv (dev, emac_isr); /* indicate that we serviced an interrupt */ serviced = 1; rc = 0; } } mtdcr (uic0sr, UIC_MRE); /* Clear */ mtdcr (uic1sr, UIC_MS | UIC_MTDE | UIC_MRDE); /* Clear */ switch (hw_p->devnum) { case 0: mtdcr (uic1sr, UIC_ETH0); break; case 1: mtdcr (uic1sr, UIC_ETH1); break;#if defined (CONFIG_440_GX) case 2: mtdcr (uic2sr, UIC_ETH2); break; case 3: mtdcr (uic2sr, UIC_ETH3); break;#endif /* CONFIG_440_GX */ default: break; } } while (serviced); return (rc);}/*-----------------------------------------------------------------------------+ * MAL Error Routine *-----------------------------------------------------------------------------*/static void mal_err (struct eth_device *dev, unsigned long isr, unsigned long uic, unsigned long maldef, unsigned long mal_errr){ EMAC_440GX_HW_PST hw_p = dev->priv; mtdcr (malesr, isr); /* clear interrupt */ /* clear DE interrupt */ mtdcr (maltxdeir, 0xC0000000); mtdcr (malrxdeir, 0x80000000);#ifdef INFO_440_ENET printf ("\nMAL error occured.... ISR = %lx UIC = = %lx MAL_DEF = %lx MAL_ERR= %lx \n", isr, uic, maldef, mal_errr);#endif eth_init (hw_p->bis); /* start again... */}/*-----------------------------------------------------------------------------+ * EMAC Error Routine *-----------------------------------------------------------------------------*/static void emac_err (struct eth_device *dev, unsigned long isr){ EMAC_440GX_HW_PST hw_p = dev->priv; printf ("EMAC%d error occured.... ISR = %lx\n", hw_p->devnum, isr); out32 (EMAC_ISR + hw_p->hw_addr, isr);}/*-----------------------------------------------------------------------------+ * enet_rcv() handles the ethernet receive data *-----------------------------------------------------------------------------*/static void enet_rcv (struct eth_device *dev, unsigned long malisr){ struct enet_frame *ef_ptr; unsigned long data_len; unsigned long rx_eob_isr; EMAC_440GX_HW_PST hw_p = dev->priv; int handled = 0; int i; int loop_count = 0; rx_eob_isr = mfdcr (malrxeobisr); if ((0x80000000 >> hw_p->devnum) & rx_eob_isr) { /* clear EOB */ mtdcr (malrxeobisr, rx_eob_isr); /* EMAC RX done */ while (1) { /* do all */ i = hw_p->rx_slot; if ((MAL_RX_CTRL_EMPTY & hw_p->rx[i].ctrl) || (loop_count >= NUM_RX_BUFF)) break; loop_count++; hw_p->rx_slot++; if (NUM_RX_BUFF == hw_p->rx_slot) hw_p->rx_slot = 0; handled++; data_len = (unsigned long) hw_p->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 & hw_p->rx[i].ctrl) { /* Check Errors */ data_len = 0; hw_p->stats.rx_err_log[hw_p-> rx_err_index] = hw_p->rx[i].ctrl; hw_p->rx_err_index++; if (hw_p->rx_err_index == MAX_ERR_LOG) hw_p->rx_err_index = 0; } /* emac_erros */ } /* data_len < max mtu */ } /* if data_len */ if (!data_len) { /* no data */ hw_p->rx[i].ctrl |= MAL_RX_CTRL_EMPTY; /* Free Recv Buffer */ hw_p->stats.data_len_err++; /* Error at Rx */ } /* !data_len */ /* AS.HARNOIS */ /* Check if user has already eaten buffer */ /* if not => ERROR */ else if (hw_p->rx_ready[hw_p->rx_i_index] != -1) { if (hw_p->is_receiving) printf ("ERROR : Receive buffers are full!\n"); break; } else { hw_p->stats.rx_frames++; hw_p->stats.rx += data_len; ef_ptr = (struct enet_frame *) hw_p->rx[i]. data_ptr;#ifdef INFO_440_ENET hw_p->stats.pkts_rx++;#endif /* AS.HARNOIS * use ring buffer */ hw_p->rx_ready[hw_p->rx_i_index] = i; hw_p->rx_i_index++; if (NUM_RX_BUFF == hw_p->rx_i_index) hw_p->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_440x_eth_rx (struct eth_device *dev){ int length; int user_index; unsigned long msr; EMAC_440GX_HW_PST hw_p = dev->priv; hw_p->is_receiving = 1; /* tell driver */ for (;;) { /* AS.HARNOIS * use ring buffer and * get index from rx buffer desciptor queue */ user_index = hw_p->rx_ready[hw_p->rx_u_index]; if (user_index == -1) { length = -1; break; /* nothing received - leave for() loop */ } msr = mfmsr (); mtmsr (msr & ~(MSR_EE)); length = hw_p->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 */ hw_p->rx[user_index].ctrl |= MAL_RX_CTRL_EMPTY; /* Free rx buffer descriptor queue */ hw_p->rx_ready[hw_p->rx_u_index] = -1; hw_p->rx_u_index++; if (NUM_RX_BUFF == hw_p->rx_u_index) hw_p->rx_u_index = 0;#ifdef INFO_440_ENET hw_p->stats.pkts_handled++;#endif mtmsr (msr); /* Enable IRQ's */ } hw_p->is_receiving = 0; /* tell driver */ return length;}int ppc_440x_eth_initialize (bd_t * bis){ static int virgin = 0; unsigned long pfc1; struct eth_device *dev; int eth_num = 0; EMAC_440GX_HW_PST hw = NULL; mfsdr (sdr_pfc1, pfc1); pfc1 &= ~(0x01e00000); pfc1 |= 0x01200000; mtsdr (sdr_pfc1, pfc1); /* set phy num and mode */ bis->bi_phynum[0] = CONFIG_PHY_ADDR; bis->bi_phynum[1] = CONFIG_PHY1_ADDR; bis->bi_phynum[2] = CONFIG_PHY2_ADDR; bis->bi_phynum[3] = CONFIG_PHY3_ADDR; bis->bi_phymode[0] = 0; bis->bi_phymode[1] = 0; bis->bi_phymode[2] = 2; bis->bi_phymode[3] = 2; for (eth_num = 0; eth_num < EMAC_NUM_DEV; eth_num++) { /* See if we can actually bring up the interface, otherwise, skip it */ switch (eth_num) { case 0: if (memcmp (bis->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0) { bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; continue; } break; case 1: if (memcmp (bis->bi_enet1addr, "\0\0\0\0\0\0", 6) == 0) { bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; continue; } break; case 2: if (memcmp (bis->bi_enet2addr, "\0\0\0\0\0\0", 6) == 0) { bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; continue; } break; case 3: if (memcmp (bis->bi_enet3addr, "\0\0\0\0\0\0", 6) == 0) { bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; continue; } break; default: if (memcmp (bis->bi_enetaddr, "\0\0\0\0\0\0", 6) == 0) { bis->bi_phymode[eth_num] = BI_PHYMODE_NONE; continue; } break; } /* Allocate device structure */ dev = (struct eth_device *) malloc (sizeof (*dev)); if (dev == NULL) { printf ("ppc_440x_eth_initialize: " "Cannot allocate eth_device %d\n", eth_num); return (-1); } /* Allocate our private use data */ hw = (EMAC_440GX_HW_PST) malloc (sizeof (*hw)); if (hw == NULL) { printf ("ppc_440x_eth_initialize: " "Cannot allocate private hw data for eth_device %d", eth_num); free (dev); return (-1); } switch (eth_num) { case 0: hw->hw_addr = 0; memcpy (dev->enetaddr, bis->bi_enetaddr, 6); break; case 1: hw->hw_addr = 0x100; memcpy (dev->enetaddr, bis->bi_enet1addr, 6); break; case 2: hw->hw_addr = 0x400; memcpy (dev->enetaddr, bis->bi_enet2addr, 6); break; case 3: hw->hw_addr = 0x600; memcpy (dev->enetaddr, bis->bi_enet3addr, 6); break; default: hw->hw_addr = 0; memcpy (dev->enetaddr, bis->bi_enetaddr, 6); break; } hw->devnum = eth_num; sprintf (dev->name, "ppc_440x_eth%d", eth_num); dev->priv = (void *) hw; dev->init = ppc_440x_eth_init; dev->halt = ppc_440x_eth_halt; dev->send = ppc_440x_eth_send; dev->recv = ppc_440x_eth_rx; if (0 == virgin) { /* 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); /* install MAL interrupt handler */ irq_install_handler (VECNUM_MS, (interrupt_handler_t *) enetInt, dev); irq_install_handler (VECNUM_MTE, (interrupt_handler_t *) enetInt, dev); irq_install_handler (VECNUM_MRE, (interrupt_handler_t *) enetInt, dev); irq_install_handler (VECNUM_TXDE, (interrupt_handler_t *) enetInt, dev); irq_install_handler (VECNUM_RXDE, (interrupt_handler_t *) enetInt, dev); virgin = 1; } eth_register (dev); } /* end for each supported device */ return (1);}#endif /* CONFIG_440 && CONFIG_NET_MULTI */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -