📄 etherdev.c
字号:
/* * This source code has been made available to you by IBM on an AS-IS * basis. Anyone receiving this source is licensed under IBM * copyrights to use it in any way he or she deems fit, including * copying it, modifying it, compiling it, and redistributing it either * with or without modifications. No license under IBM patents or * patent applications is to be implied by the copyright license. * * Any user of this software should understand that IBM cannot provide * technical support for this software and will not be responsible for * any consequences resulting from the use of this software. * * Any person who transfers this source code or any derivative work * must include the IBM copyright notice, this paragraph, and the * preceding two paragraphs in the transferred software. * * COPYRIGHT I B M CORPORATION 1995 * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M * * File Name: etherdev.c (originally enetemac.c) * * Function: Device driver for the ethernet EMAC3 macro on the 405GP. * * Author: Mark Wisner * * Change Activity- * * Date Description of Change BY * --------- --------------------- * 05-May-99 Created MKW * 27-Jun-99 Clean up JWB * 16-Jul-99 Added MAL error recovery and better IP packet MKW handling. * 29-Jul-99 Added Full duplex support MKW * 06-Aug-99 Changed names for Mal CR reg MKW * 23-Aug-99 Turned off SYE when running at 10Mbs MKW * 24-Aug-99 Marked descriptor empty after call_xlc MKW * 07-Sep-99 Set MAL RX buffer size reg to ENET_MAX_MTU_ALIGNED / 16 MCG * to avoid chaining maximum sized packets. Push starting * RX descriptor address up to the next cache line boundary. * 19-Apr-00 Integrated enetemac.c (now etherdev.c) into MicroMonitor ELS * platform. Changed some register names to match the names * used in the manual. * 26-Sep-00 Added PHY interface, auto-negotiation, and selftest. ELS * Also fixed a bug where the descriptor tables must start * on an 8-byte boundary. * * General notice: * This code is part of a boot-monitor package developed as a generic base * platform for embedded system designs. As such, it is likely to be * distributed to various projects beyond the control of the original * author. Please notify the author of any enhancements made or bugs found * so that all may benefit from the changes. In addition, notification back * to the author will allow the new user to pick up changes that may have * been made by other users after this version of the code was distributed. * * Author: Ed Sutter * email: esutter@lucent.com (home: lesutter@worldnet.att.net) * phone: 908-582-2351 (home: 908-889-5161) * */#include "config.h"#include "genlib.h"#include "stddefs.h"#include "enetemac.h"#include "cpuio.h"#include "phy.h"#include "ppcmal.h"#include "ppcuic.h"#include "ether.h"#if INCLUDE_ETHERNET/* defines for EtherSpeed status */#define Is10BaseT 0x1#define Is100BaseT 0x2#define IsFullDuplex 0x4#define AutoNeg 0x8#define AutoNegFailed 0x10/* Defines for number of buffers. */#define NUM_TX_BUFF 1#define NUM_RX_BUFF 10/* define the number of channels implemented */#define EMAC_RXCHL 1#define EMAC_TXCHL 1/* definitions used to check link status */#define LINK_NULL 0#define LINK_UP 1#define LINK_DOWN 2/* Global variables. TX and RX descriptors and buffers. */static mal_desc_t *tx;static mal_desc_t *rx;static mal_desc_t tx_desctbl[NUM_TX_BUFF+2];static mal_desc_t rx_desctbl[NUM_RX_BUFF+2];static struct memblock *tx_buff;static struct memblock *rx_buff;static ulong xmit_buffer[(400*NUM_TX_BUFF)];static ulong recv_buffer[(400*NUM_RX_BUFF)];static int rx_slot; /* MAL Receive Slot */static int rx_ready[NUM_RX_BUFF]; /* Receive Ready Queue */static int tx_slot; /* MAL Transmit Slot */static int tx_run[NUM_TX_BUFF]; /* Transmit Running Queue */static ulong EtherSpeed;/* * enreset(): * Reset the ethernet-related hardware. */voidenreset(void){ volatile int delay; /* PHY reset */ phy_reset(); /* MAL reset */ ppcMtmalcr(MAL_CR_MMSR); /* Disable MAL interrupts: */ ppcMtmalier(0); /* EMAC reset */ *(ulong *)(EM0MR0) = EM0MR0_SRST; for (delay=0;delay<1000;delay++); *(ulong *)(EM0MR0) = *(ulong *)(EM0MR0) & ~EM0MR0_SRST; /* Disable EMAC interrupts: */ *(ulong *)(EMAC_IER) = 0;}/* * eninit() - Initialize the Mal and the Emac macros. */inteninit(void){ int i; char *p; ulong reg, emac_ier; unsigned mode_reg; rx_slot = 0; /* MAL Receive Slot */ tx_slot = 0; /* MAL Transmit Slot */ /* The descriptor tables must be aligned on an 8-byte boundary * (least significant 3 bits must be 0). */ tx = (mal_desc_t *)((ulong)(&tx_desctbl[1]) & 0xfffffff8); rx = (mal_desc_t *)((ulong)(&rx_desctbl[1]) & 0xfffffff8); /* Set MAL configuration reg: * - Burst transactions enabled; * - Lock OPB during xfers to/from the EMAC; * - Handle errors in locked mode; */ ppcMtmalcr(MAL_CR_PLBB|MAL_CR_OPBBL|MAL_CR_LEA|MAL_CR_PLBLT_DEFAULT); /* Set up the TX and RX descriptors */ tx_buff = (struct memblock *)xmit_buffer; rx_buff = (struct memblock *)recv_buffer; for (i=0;i<NUM_TX_BUFF;i++) { tx[i].ctrl = 0; tx[i].data_len = 0; tx[i].data_ptr = (char *) &tx_buff[i]; if ((NUM_TX_BUFF - 1) == i) tx[i].ctrl |= MAL_TX_CTRL_WRAP; tx_run[i] = -1; } for (i=0;i<NUM_RX_BUFF;i++) { rx[i].ctrl = 0; rx[i].data_len = 0; rx[i].data_ptr = (char *) &rx_buff[i]; if ((NUM_RX_BUFF - 1) == i) rx[i].ctrl |= MAL_RX_CTRL_WRAP; rx[i].ctrl |= MAL_RX_CTRL_EMPTY | MAL_RX_CTRL_INTR; rx_ready[i] = -1; } /* Write the ethernet address (6 bytes) into the EMAC Individual * Address High and Low registers: */ reg = 0; reg |= BinEnetAddr[0]; reg = reg << 8; reg |= BinEnetAddr[1]; *(ulong *)(EM0IAH) = reg; reg = 0; reg |= BinEnetAddr[2]; reg = reg << 8; reg |= BinEnetAddr[3]; reg = reg << 8; reg |= BinEnetAddr[4]; reg = reg << 8; reg |= BinEnetAddr[5]; *(ulong *)(EM0IAL) = reg; /* Setup MAL tx & rx channel pointers */ ppcMtmaltxctp0r((int)tx); ppcMtmalrxctp0r((int)rx); /* Reset transmit and receive channels */ ppcMtmalrxcarr(0x80000000); /* 2 channels */ ppcMtmaltxcarr(0x80000000); /* 2 channels */ /* Enable MAL transmit and receive channels */ ppcMtmaltxcasr(0x80000000); /* 1 channel */ ppcMtmalrxcasr(0x80000000); /* 1 channel */ /* Set RX buffer size */ ppcMtmalrcbs0(ENET_MAX_MTU_ALIGNED / 16); /* Set transmit enable & receive enable */ *(ulong *)(EM0MR0) = (EM0MR0_TXE | EM0MR0_RXE); /* Set receive fifo to 4k and tx fifo to 2k */ mode_reg = EM0MR1_RFS_4K | EM0MR1_TX_FIFO_2K; /* Set speed based on content of ETHERSPEED shell variable... */ if ((p = getenv("ETHERSPEED")) == 0) { EtherSpeed = Is10BaseT; phy_write(PHY_BMCR,PHY_BMCR_10MB); } else { if(!strcmp(p, "10")) { EtherSpeed = Is10BaseT; phy_write(PHY_BMCR,PHY_BMCR_10MB); } else if(!strcmp(p, "100")) { EtherSpeed = Is100BaseT; phy_write(PHY_BMCR,PHY_BMCR_100MB); } else if(!strcmp(p, "10FULL")) { EtherSpeed = Is10BaseT | IsFullDuplex; phy_write(PHY_BMCR,PHY_BMCR_10MB | PHY_BMCR_FDPLX); } else if(!strcmp(p, "100FULL")) { EtherSpeed = Is100BaseT | IsFullDuplex; phy_write(PHY_BMCR,PHY_BMCR_100MB | PHY_BMCR_FDPLX); } else if (!strcmp(p, "AUTO")) { int is100BaseT, isFullDuplex; EtherSpeed = AutoNeg; isFullDuplex = is100BaseT = 1; if (phy_autoneg(0, &is100BaseT, &isFullDuplex)) { printf("Ethernet auto negotiate failed, "); printf("defaulting to 10BaseT half duplex.\n"); EtherSpeed = AutoNegFailed | Is10BaseT; phy_write(PHY_BMCR,PHY_BMCR_10MB); } else { if(isFullDuplex && is100BaseT) { EtherSpeed = Is100BaseT | IsFullDuplex; } else if(!isFullDuplex && is100BaseT) { EtherSpeed = Is100BaseT; } else if(!isFullDuplex && !is100BaseT) { EtherSpeed = Is10BaseT; } else if(isFullDuplex && is100BaseT) { EtherSpeed = Is10BaseT | IsFullDuplex; } } } else { printf("ETHERSPEED not valid, defaulting to 10BaseT half duplex\n"); EtherSpeed |= Is10BaseT; phy_write(PHY_BMCR,PHY_BMCR_10MB); } } if (EtherSpeed & Is100BaseT) mode_reg |= EM0MR1_MF_100MBPS; else mode_reg &= ~EM0MR1_MF_SPEED; /* 10 MBPS */ if(EtherSpeed & IsFullDuplex) mode_reg |= EM0MR1_FDE; /* Load EM0MR1: */ *(ulong *)(EM0MR1) = mode_reg; /* Configure receive mode: * - Accept broadcast addresses; * - Accept individual address; * - Allow runt packets (< 64 bytes); * - Strip Frame Check Sequence and padding; */ *(ulong *)(EM0RMR) = (EMAC_RMR_BAE|EMAC_RMR_IAE|EMAC_RMR_ARRP|EMAC_RMR_SFCS|EMAC_RMR_SP); /* we probably need to set the tx mode1 reg? maybe at tx time */ /* set transmit request threshold register */ *(ulong *)(EMAC_TRTR) = 0x18000000; /* 256 byte threshold */ /* set recieve low/high water mark register */ *(ulong *)(EMAC_RX_HI_LO_WMARK) = 0x0f002000;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -