⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 dc2114x.c

📁 嵌入式linux的bsp
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * (C) Copyright 2001 * Stefan Roese, esd gmbh germany, stefan.roese@esd-electronics.com * * See file CREDITS for list of people who contributed to this * project. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as * published by the Free Software Foundation; either version 2 of * the License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, * MA 02111-1307 USA */#include <ppcboot.h>#include <net.h>/* phy seed setup */#define AUTO			99#define _100BASET		100#define _10BASET		10#define HALF			22#define FULL			44/* phy register offsets */#define PHY_BMCR		0x00#define PHY_BMSR		0x01#define PHY_PHY1DR1		0x02#define PHY_PHYIDR2		0x03#define PHY_ANAR		0x04#define PHY_ANLPAR		0x05#define PHY_ANER		0x06#define PHY_ANNPTR		0x07#define PHY_PHYSTS		0x10#define PHY_MIPSCR		0x11#define PHY_MIPGSR		0x12#define PHY_DCR			0x13#define PHY_FCSCR		0x14#define PHY_RECR		0x15#define PHY_PCSR		0x16#define PHY_LBR			0x17#define PHY_10BTSCR		0x18#define PHY_PHYCTRL		0x19/*phy ANLPAR */#define PHY_ANLPAR_NP		0x8000#define PHY_ANLPAR_ACK		0x4000#define PHY_ANLPAR_RF		0x2000#define PHY_ANLPAR_T4		0x0200#define PHY_ANLPAR_TXFD		0x0100#define PHY_ANLPAR_TX		0x0080#define PHY_ANLPAR_10FD		0x0040#define PHY_ANLPAR_10		0x0020#define PHY_ANLPAR_100		0x0380	/* we can run at 100 *//* PCI Registers. */#define PCI_VENDOR_ID		0x00#define PCI_COMMAND		0x04#define PCI_CLASS_REVISION	0x08#define PCI_LATENCY_TIMER	0x0d#define PCI_BASE_ADDRESS_0	0x10#define PCI_BASE_ADDRESS_1	0x14#define PCI_BASE_ADDRESS_2	0x18#define PCI_CFDA_PSM		0x43#define PCI_COMMAND_IO		0x1#define PCI_COMMAND_MEM		0x2#define PCI_COMMAND_MASTER	0x4#define CFRV_RN		0x000000f0	/* Revision Number */#define CBIO_MASK	-128#define WAKEUP		0x00		/* Power Saving Wakeup */#define SLEEP		0x80		/* Power Saving Sleep Mode */#define DC2114x_VID	0x1011		/* DC2114[23] Manufacturer */#define DC2114x_DID	0x1900		/* Unique Device ID # */#define DC2114x_BRK	0x0020		/* CFRV break between DC21142 & DC21143 */#define DC21142		(DC2114x_DID | 0x0010)#define DC21143		(DC2114x_DID | 0x0030)#define is_DC2114x ((vendor == DC2114x_VID) && (device == DC2114x_DID))/* Ethernet chip registers.	 */#define DE4X5_BMR	iobase + 0x000	/* Bus Mode Register */#define DE4X5_TPD	iobase + 0x008	/* Transmit Poll Demand Reg */#define DE4X5_RRBA	iobase + 0x018	/* RX Ring Base Address Reg */#define DE4X5_TRBA	iobase + 0x020	/* TX Ring Base Address Reg */#define DE4X5_STS	iobase + 0x028	/* Status Register */#define DE4X5_OMR	iobase + 0x030	/* Operation Mode Register */#define DE4X5_SICR	iobase + 0x068	/* SIA Connectivity Register */#define DE4X5_APROM	iobase + 0x048	/* Ethernet Address PROM *//* Register bits.	 */#define BMR_SWR		0x00000001	/* Software Reset */#define STS_TS		0x00700000	/* Transmit Process State */#define STS_RS		0x000e0000	/* Receive Process State */#define OMR_ST		0x00002000	/* Start/Stop Transmission Command */#define OMR_SR		0x00000002	/* Start/Stop Receive */#define OMR_PS		0x00040000	/* Port Select */#define OMR_SDP		0x02000000	/* SD Polarity - MUST BE ASSERTED */#define OMR_PM		0x00000080	/* Pass All Multicast *//* Descriptor bits.	 */#define R_OWN		0x80000000	/* Own Bit */#define RD_RER		0x02000000	/* Receive End Of Ring */#define RD_LS		0x00000100	/* Last Descriptor */#define RD_ES		0x00008000	/* Error Summary */#define TD_TER		0x02000000	/* Transmit End Of Ring */#define T_OWN		0x80000000	/* Own Bit */#define TD_LS		0x40000000	/* Last Segment */#define TD_FS		0x20000000	/* First Segment */#define TD_ES		0x00008000	/* Error Summary */#define TD_SET		0x08000000	/* Setup Packet */#define SROM_HWADD	    0x0014	/* Hardware Address offset in SROM */#define SROM_RD		0x00004000	/* Read from Boot ROM */#define SROM_SR		0x00000800	/* Select Serial ROM when set */#define DT_IN		0x00000004	/* Serial Data In */#define DT_CLK		0x00000002	/* Serial ROM Clock */#define DT_CS		0x00000001	/* Serial ROM Chip Select */#define POLL_DEMAND	1#define RESET_DE4X5 {\    int i;\    i=inl(DE4X5_BMR);\    udelay(1000);\    outl(i | BMR_SWR, DE4X5_BMR);\    udelay(1000);\    outl(i, DE4X5_BMR);\    udelay(1000);\    for (i=0;i<5;i++) {inl(DE4X5_BMR); udelay(10000);}\    udelay(1000);\}#define START_DE4X5 {\    s32 omr; \    omr = inl(DE4X5_OMR);\    omr |= OMR_ST | OMR_SR;\    outl(omr, DE4X5_OMR);		/* Enable the TX and/or RX */\}#define STOP_DE4X5 {\    s32 omr; \    omr = inl(DE4X5_OMR);\    omr &= ~(OMR_ST|OMR_SR);\    outl(omr, DE4X5_OMR);		/* Disable the TX and/or RX */ \}#define NUM_RX_DESC PKTBUFSRX#define NUM_TX_DESC 1			/* Number of TX descriptors   */#define RX_BUFF_SZ  PKTSIZE_ALIGN#define TOUT_LOOP   1000000#define SETUP_FRAME_LEN 192#define ETH_ALEN	6struct de4x5_desc {	volatile s32 status;	u32 des1;	u32 buf;	u32 next;};static struct de4x5_desc rx_ring[NUM_RX_DESC]; /* RX descriptor ring         */static struct de4x5_desc tx_ring[NUM_TX_DESC]; /* TX descriptor ring         */static int rx_new;                             /* RX descriptor ring pointer */static int tx_new;                             /* TX descriptor ring pointer */static char rxRingSize;static char txRingSize;static u_long iobase;unsigned int     PCI_Read_CFG_Reg(int BusDevFunc, int Reg, int Width);int    PCI_Write_CFG_Reg(int BusDevFunc, int Reg, unsigned int Value, int Width);static void  send_setup_frame(bd_t * bis);static void  check_hw_addr(bd_t * bis);static short srom_rd(u_long address, u_char offset);static void  srom_latch(u_int command, u_long address);static void  srom_command(u_int command, u_long address);static void  srom_address(u_int command, u_long address, u_char offset);static short srom_data(u_int command, u_long address);static void  sendto_srom(u_int command, u_long addr);static int   getfrom_srom(u_long addr);static void updateSRom(bd_t *bis);static unsigned long dcCsrRead(unsigned long, int);static int inl(u_long addr){  return le32_to_cpu(*(volatile u_long *)(addr));}static void outl (int command, u_long addr){  *(volatile u_long *)(addr) = cpu_to_le32(command);}int eth_init(bd_t *bis){  int             i, status          = 0;  int             vendor, device, l;  int             cfrv;  unsigned char   timer;  unsigned long   bmcr;#if 0 // test-only  {    int val;    for (l=0; l<6; l++)      {        printf("%02x: ", l*0x10);        for (i=0; i<4; i++)          {            val = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, l*16+i*4, 4);            printf("%08x ", val);          }        printf("\n");      }    printf("\n");  }#endif  l = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_CLASS_REVISION, 4);  l >>= 8;  if (l != 0x00020000)    {      printf("Error: Can not find an ethernet card on the PCI bus %d "             "in slot %d\n", CFG_ETH_DEV_FN >> 16,             (CFG_ETH_DEV_FN & 0xFFFF) >> 11);      goto Done;    }  vendor = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_VENDOR_ID, 4);  device = (vendor >> 16) & 0xffff;  vendor = vendor & 0xffff;  device = device << 8;  if (! is_DC2114x)    {      printf("Error: The chip is not DC2114x.\n");      goto Done;    }  /* Get the chip configuration revision register.   */  cfrv = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_CLASS_REVISION, 4);  device = ((cfrv & CFRV_RN) < DC2114x_BRK ? DC21142 : DC21143);  if (device != DC21143)    {      printf("Error: The chip is not DC21143.\n");      goto Done;    }  status = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_COMMAND, 2);  status |= PCI_COMMAND_MASTER | PCI_COMMAND_IO | PCI_COMMAND_MEM;  PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_COMMAND, status, 2);  /* Check the latency timer for values >= 0x60.   */  timer = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_LATENCY_TIMER, 1);  if (timer < 0x60)    {      PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_LATENCY_TIMER, 0x60, 1);    }  /* Set I/O base register.   */  PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_BASE_ADDRESS_0, CFG_ETH_IOBASE, 4);  iobase = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_BASE_ADDRESS_0, 4);  PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_BASE_ADDRESS_1, CFG_ETH_IOBASE, 4);  iobase = PCI_Read_CFG_Reg(CFG_ETH_DEV_FN, PCI_BASE_ADDRESS_1, 4);  if (iobase == 0xffffffff)    {      printf("Error: Can not set I/O base register.\n");      goto Done;    }  iobase &= CBIO_MASK;  iobase += 0xc0000000; // test-only  /* Ensure we're not sleeping.   */  PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_CFDA_PSM, WAKEUP, 1);  udelay(10 * 1000);  check_hw_addr(bis);  RESET_DE4X5;  if ((inl(DE4X5_STS) & (STS_TS | STS_RS)) != 0)    {      printf("Error: Can not reset ethernet controller.\n");      goto Done;    }  outl(OMR_SDP | OMR_PS | OMR_PM, DE4X5_OMR);  for (i = 0; i < NUM_RX_DESC; i++)    {      rx_ring[i].status = cpu_to_le32(R_OWN);      rx_ring[i].des1 = cpu_to_le32(RX_BUFF_SZ);      rx_ring[i].buf = cpu_to_le32((u_long)NetRxPackets[i]);      rx_ring[i].next = 0;    }  for (i=0; i < NUM_TX_DESC; i++)    {      tx_ring[i].status = 0;      tx_ring[i].des1 = 0;      tx_ring[i].buf = 0;      tx_ring[i].next = 0;    }  rxRingSize = NUM_RX_DESC;  txRingSize = NUM_TX_DESC;  /* Write the end of list marker to the descriptor lists.   */  rx_ring[rxRingSize - 1].des1 |= cpu_to_le32(RD_RER);  tx_ring[txRingSize - 1].des1 |= cpu_to_le32(TD_TER);  /* Tell the adapter where the TX/RX rings are located.   */  outl((u_long)&rx_ring, DE4X5_RRBA);  outl((u_long)&tx_ring, DE4X5_TRBA);  START_DE4X5;  tx_new = 0;  rx_new = 0;  bmcr = dcCsrRead(0, PHY_ANLPAR);  printf("ENET Speed is %d Mbps - %s duplex connection\n",         ((bmcr & PHY_ANLPAR_100) != 0) ? 100 : 10,         ((bmcr & (PHY_ANLPAR_10FD | PHY_ANLPAR_TXFD)) != 0) ? "FULL" : "HALF");  send_setup_frame(bis); Done:  return 0;}int eth_send(volatile void *packet, int length){  int    status = 0;  int i;  if (length <= 0)    {      printf("eth: bad packet size: %d\n", length);      goto out;    }  for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++)    {      if (i >= TOUT_LOOP)        {          printf("eth: tx error buffer not ready\n");          goto out;        }    }  tx_ring[tx_new].buf = cpu_to_le32((u_long)packet);  tx_ring[tx_new].des1 = cpu_to_le32(TD_TER | TD_LS | TD_FS | length);  tx_ring[tx_new].status = cpu_to_le32(T_OWN);  outl(POLL_DEMAND, DE4X5_TPD);  for(i = 0; tx_ring[tx_new].status & cpu_to_le32(T_OWN); i++)    {      if (i >= TOUT_LOOP)        {          printf("eth: tx buffer not ready\n");          goto out;        }    }#if 0 // test-only  if (le32_to_cpu(tx_ring[tx_new].status) & TD_ES)    {      printf("TX error status = 0x%08X\n",             le32_to_cpu(tx_ring[tx_new].status));      status++;    }#endif out:  return status;}int eth_rx(void){  s32 status;  int length    = 0;  for ( ; ; )    {      status = (s32)le32_to_cpu(rx_ring[rx_new].status);      if (status & R_OWN)        {          break;        }      if (status & RD_LS)        {				/* Valid frame status.				 */          if (status & RD_ES)            {              /* There was an error.               */              printf("RX error status = 0x%08X\n", status);            }          else            {              /* A valid frame received.               */              length = (le32_to_cpu(rx_ring[rx_new].status) >>                        16);              /* Pass the packet up to the protocol               * layers.               */              NetReceive(NetRxPackets[rx_new], length - 4);            }				/* Change buffer ownership for this frame, back				 * to the adapter.				 */          rx_ring[rx_new].status = cpu_to_le32(R_OWN);        }      /* Update entry information.       */      rx_new = (++rx_new) % rxRingSize;    }  return length;}void eth_halt(void){#if 1	if (iobase != CFG_ETH_IOBASE) {		/* Ethernet has not been initialized yet.  */		return;	}	STOP_DE4X5;	outl(0, DE4X5_SICR);	PCI_Write_CFG_Reg(CFG_ETH_DEV_FN, PCI_CFDA_PSM, SLEEP, 1);#endif}static void check_hw_addr(bd_t *bis){  unsigned char hw_addr[ETH_ALEN];  u_short tmp, *p = (short *)(&hw_addr[0]);  int i, j = 0;  for (i = 0; i < (ETH_ALEN >> 1); i++)    {      tmp = srom_rd(DE4X5_APROM, (SROM_HWADD >> 1) + i);      *p = le16_to_cpu(tmp);      j += *p++;    }  if ((j == 0) || (j == 0x2fffd))    {      printf("Warning: can't read HW address from SROM.\n");      if ((bis->bi_enetaddr[0] != 0) || (bis->bi_enetaddr[1] != 0) ||          (bis->bi_enetaddr[2] != 0) || (bis->bi_enetaddr[3] != 0) ||          (bis->bi_enetaddr[4] != 0) || (bis->bi_enetaddr[5] != 0))        {          printf("Updating SROM data - please wait...\n");          updateSRom(bis);        }      goto Done;    }  for (i = 0; i < ETH_ALEN; i++)    {      if (hw_addr[i] != bis->bi_enetaddr[i])        {          printf("Warning: HW addresses don't match:\n");          printf("Address in SROM is         "                 "%02X:%02X:%02X:%02X:%02X:%02X\n",                 hw_addr[0], hw_addr[1], hw_addr[2],                 hw_addr[3], hw_addr[4], hw_addr[5]);          printf("Address used by ppcboot is "                 "%02X:%02X:%02X:%02X:%02X:%02X\n",                 bis->bi_enetaddr[0], bis->bi_enetaddr[1],                 bis->bi_enetaddr[2], bis->bi_enetaddr[3],

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -