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

📄 cs8900.c

📁 ARM的bootloader代码.rar
💻 C
字号:
/* * Cirrus Logic CS8900A Ethernet * * (C) Copyright 2002 * Sysgo Real-Time Solutions, GmbH <www.elinos.com> * Marius Groeger <mgroeger@sysgo.de> * * Copyright (C) 1999 Ben Williamson <benw@pobox.com> * * See file CREDITS for list of people who contributed to this * project. * * This program is loaded into SRAM in bootstrap mode, where it waits * for commands on UART1 to read and write memory, jump to code etc. * A design goal for this program is to be entirely independent of the * target board.  Anything with a CL-PS7111 or EP7211 should be able to run * this code in bootstrap mode.  All the board specifics can be handled on * the host. * * 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., 675 Mass Ave, Cambridge, MA 02139, USA. */#include "armboot.h"#include "command.h"#include "cs8900.h"#include "net.h"#ifdef CONFIG_DRIVER_CS8900#if (CONFIG_COMMANDS & CFG_CMD_NET)/* packet page register access functions */#ifdef CS8900_BUS32/* we don't need 16 bit initialisation on 32 bit bus */#define get_reg_init_bus(x) get_reg((x))#elsestatic unsigned short get_reg_init_bus(int regno){    /* force 16 bit busmode */    volatile unsigned char c;    c = CS8900_BUS16_0;    c = CS8900_BUS16_1;    c = CS8900_BUS16_0;    c = CS8900_BUS16_1;    c = CS8900_BUS16_0;    CS8900_PPTR = regno;    return (unsigned short) CS8900_PDATA;}#endifstatic unsigned shortget_reg(int regno){    CS8900_PPTR = regno;    return (unsigned short) CS8900_PDATA;}static void put_reg(int regno, unsigned short val){    CS8900_PPTR = regno;    CS8900_PDATA = val;}static void eth_reset(void){    int tmo;    unsigned short us;    /* reset NIC */    put_reg(PP_SelfCTL, get_reg(PP_SelfCTL) | PP_SelfCTL_Reset );    /* wait for 200ms */    udelay(200000);    /* Wait until the chip is reset */    tmo = get_timer(0) + 1 * CFG_HZ;    while ((((us = get_reg_init_bus(PP_SelfSTAT)) & PP_SelfSTAT_InitD) == 0)	   && tmo < get_timer(0))      /*NOP*/;}void cs8900_get_enetaddr (uchar *addr){    int i;    /* verify chip id */    if (get_reg_init_bus(PP_ChipID) != 0x630e)	return;    eth_reset();        if ((get_reg(PP_SelfST) & (PP_SelfSTAT_EEPROM | PP_SelfSTAT_EEPROM_OK)) == 	      (PP_SelfSTAT_EEPROM|PP_SelfSTAT_EEPROM_OK)) {	/* Load the MAC from EEPROM */      	for (i=0; i<6/2; i++) {	    unsigned int Addr;	    Addr = get_reg(PP_IA+i*2);	    addr[i*2] = Addr & 0xFF;	    addr[i*2+1] = Addr >> 8;	}    }		}void eth_halt( void ){    /* disable transmitter/receiver mode */    put_reg(PP_LineCTL, 0);    /* "shutdown" to show ChipID or kernel wouldn't find he cs8900 ... */    get_reg_init_bus(PP_ChipID);}int eth_init( bd_t *bd ){        /* verify chip id */    if (get_reg_init_bus(PP_ChipID) != 0x630e)    {	printf( "CS8900 Ethernet chip not found?!\n" );	return 0;    }    eth_reset();    /* set the ethernet address */    put_reg(PP_IA + 0, bd->bi_enetaddr[0] | (bd->bi_enetaddr[1] << 8));    put_reg(PP_IA + 2, bd->bi_enetaddr[2] | (bd->bi_enetaddr[3] << 8));    put_reg(PP_IA + 4, bd->bi_enetaddr[4] | (bd->bi_enetaddr[5] << 8));	         /* receive only error free packets addressed to this card */    put_reg(PP_RxCTL, PP_RxCTL_IA | PP_RxCTL_Broadcast | PP_RxCTL_RxOK);    /* do not generate any interrupts on receive operations */    put_reg(PP_RxCFG, 0);    /* do not generate any interrupts on transmit operations */    put_reg(PP_TxCFG, 0);    /* do not generate any interrupts on buffer operations */    put_reg(PP_BufCFG, 0);    /* enable transmitter/receiver mode */    put_reg(PP_LineCTL, PP_LineCTL_Rx | PP_LineCTL_Tx);    return 0;}/* Get a data block via Ethernet */extern int eth_rx(void){    int i;    unsigned short rxlen;    unsigned short *addr;    unsigned short status;    status = get_reg(PP_RER);    if ((status & PP_RER_RxOK) == 0)      return 0;    status = CS8900_RTDATA;       /* stat */    rxlen = CS8900_RTDATA;        /* len */    if(rxlen > PKTSIZE_ALIGN + PKTALIGN)      printf("packet too big!\n");    for(addr = (unsigned short *)NetRxPackets[0], i = rxlen >> 1; i > 0; i-- )      *addr++ = CS8900_RTDATA;    if(rxlen & 1)      *addr++ = CS8900_RTDATA;    /* Pass the packet up to the protocol layers. */    NetReceive(NetRxPackets[0], rxlen);    return rxlen;}/* Send a data block via Ethernet. */extern int eth_send(volatile void *packet, int length){    volatile unsigned short *addr;    int tmo;    unsigned short s;retry:    /* initiate a transmit sequence */    CS8900_TxCMD = PP_TxCmd_TxStart_Full;    CS8900_TxLEN = length;        /* Test to see if the chip has allocated memory for the packet */    if ((get_reg(PP_BusSTAT) & PP_BusSTAT_TxRDY) == 0) {    	/* Oops... this should not happen! */	printf("cs: unable to send packet; retrying...\n");	for (tmo = get_timer(0) + 5 * CFG_HZ; get_timer(0) < tmo; )	  /*NOP*/;	eth_reset();	goto retry;     }    /* Write the contents of the packet */    /* assume even number of bytes */    for(addr = packet; length > 0; length -= 2 )      CS8900_RTDATA = *addr++;    /* wait for transfer to succeed */    tmo = get_timer(0) + 5 * CFG_HZ;    while((s = get_reg(PP_TER) & ~0x1F) == 0)     {	if (get_timer(0) >= tmo)	  break;    }           /* nothing */ ;    if ((s & (PP_TER_CRS | PP_TER_TxOK)) != PP_TER_TxOK) {	printf("\ntransmission error %#x\n", s);    }    return 0;}#endif /* COMMANDS & CFG_NET */#endif /* CONFIG_DRIVER_CS8900 */

⌨️ 快捷键说明

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