cs89x.c

来自「2410 boot loader,usb ftp」· C语言 代码 · 共 375 行

C
375
字号
/*	Copyright 2001-2004 Georges Menie (www.menie.org)	This file is part of Tftpnaive.    Tftpnaive is free software; you can redistribute it and/or modify    it under the terms of the GNU Lesser General Public License as published by    the Free Software Foundation; either version 2 of the License, or    (at your option) any later version.    Tftpnaive 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 Lesser General Public License for more details.    You should have received a copy of the GNU Lesser General Public License    along with Tftpnaive; if not, write to the Free Software    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA*/#include "tftpnaive.h"#include "io.h"#include "net.h"#include "cs89x.h"#include "baselib.h"#include "timer.h"#ifdef CS89_HW_SWAP#define writew_reg(w,r) writew(swapw(w),r)#define readw_reg(r) swapw(readw(r))#define writew_data(w,r) writew(w,r)#define readw_data(r) readw(r)#elif defined(CS89_NO_SWAP)#define writew_reg(w,r) writew(w,r)#define readw_reg(r) readw(r)#define writew_data(w,r) writew(w,r)#define readw_data(r) readw(r)#else#define writew_reg(w,r) writew(w,r)#define readw_reg(r) readw(r)#define writew_data(w,r) writew(swapw(w),r)#define readw_data(r) swapw(readw(r))#endifstatic unsigned short swapw (unsigned short x){	return ((x << 8) | (x >> 8));}int cs89xSend (void *pkt, unsigned short length){	register unsigned short *p = pkt;	register int i;	writew_reg (CS89xTxCMDStartAll, CS89xIOTransmitCommand);	writew_reg (length, CS89xIOTransmitLength);	writew_reg (CS89xBusStatus, CS89xIOPacketPagePointer);	for (i = 10; i >= 0; --i) {		if ((readw_reg (CS89xIOPacketpageDataPort0) & CS89xBusSTRdy4TxNOW))			break;		usleep (30);	}	if (i < 0)		return ERR_TIMEOUT;	for (i = 0; i < (length + 1) >> 1; ++i, ++p) {		writew_data (*p, CS89xIOReceiveTransmitDataPort0);	}	writew_reg (CS89xTransmitterEvent, CS89xIOPacketPagePointer);	for (i = 100; i >= 0; --i) {		if ((readw_reg (CS89xIOPacketpageDataPort0) & CS89xTxEventTxOK))			break;		usleep (30);	}	if (i < 0)		return ERR_TIMEOUT;	return 0;}static void RxEvent (short isq){	int idxi, idxo;	unsigned short i, length;	idxi = idxiPBuf;	idxo = idxoPBuf;	idxi = (++idxi) % MAXPACKETBUF;	writew_reg (CS89xReceiveLength, CS89xIOPacketPagePointer);	length = readw_reg (CS89xIOPacketpageDataPort0);	if (idxi != idxo && length < MAXPACKETLEN) {		unsigned short *p = (unsigned short *) &packetBuf[idxi][0];		for (i = (length + 1) >> 1; i > 0; --i) {			*p++ = readw_data (CS89xIOReceiveTransmitDataPort0);		}		packetBufLen[idxi] = length;		idxiPBuf = idxi;	}	else {		/* no more buffers or packet too big, discard new packet */		for (i = (length + 1) >> 1; i > 0; --i) {			(void) readw (CS89xIOReceiveTransmitDataPort0);		}		++netif.RxQFull;	}}/* * CS89x Interrupt Service Routine * *///void __attribute__ ((interrupt)) cs89xISR (void)void __irq cs89xISR (void){	register unsigned short isq;	++netif.TotalIRQ;		if (rEINTPEND & (1<<9)) {				for (;;) {			isq = readw_reg (CS89xIOInterruptStatusQueue);			if (isq == 0)				break;			++netif.TotalEvent;			switch (isq & 0x3f) {			case 0x4:			// RxEvent				RxEvent (isq >> 6);				++netif.RxEvent;				break;			case 0x8:			// TxEvent				++netif.TxEvent;				break;			case 0xC:			// BufEvent				++netif.BufEvent;				break;			case 0x10:			// RxMiss				netif.RxMiss += isq >> 6;				break;			case 0x12:			// TxColl				netif.TxColl += isq >> 6;				break;			default:				++netif.UnknownEvent;				break;			}		}       rEINTPEND |= (1<<9); // Clear External Interrupt Pending       rSRCPND   |= (1<<5); // Clear Source Pending       rINTPND   |= (1<<5); // Clear Interrupt Pending	}}int cs89xReset (void){	unsigned short pic1, pic2;	int t;	/* software reset */	writew_reg (CS89xSelfControl, CS89xIOPacketPagePointer);	writew_reg (CS89xSelfCTLRESET, CS89xIOPacketpageDataPort0);	for (t = 20; t >= 0; --t) {		if (!(readw_reg (CS89xIOPacketpageDataPort0) & CS89xSelfCTLRESET))			break;		usleep (100);	}	if (t < 0)		return ERR_TIMEOUT;#if 0	/* dummy reads to go 16 bits */	readb (CS89xIOReceiveTransmitDataPort0);	readb (CS89xIOReceiveTransmitDataPort0 + 1);	readb (CS89xIOReceiveTransmitDataPort0);	readb (CS89xIOReceiveTransmitDataPort0 + 1);#endif	/* signature check */	if (readw_reg (CS89xIOPacketPagePointer) != 0x3000)		return ERR_CHIPID;	/* wait on eeprom busy */	writew_reg (CS89xSelfStatus, CS89xIOPacketPagePointer);	for (t = 150; t >= 0; --t) {		if (!(readw_reg (CS89xIOPacketpageDataPort0) & CS89xSelfSTSIBUSY))			break;		usleep (100);	}	if (t < 0)		return ERR_TIMEOUT;	/* wait on init */	writew_reg (CS89xSelfStatus, CS89xIOPacketPagePointer);	for (t = 400; t >= 0; --t) {		if ((readw_reg (CS89xIOPacketpageDataPort0) & CS89xSelfSTINITD))			break;		usleep (100);	}	if (t < 0)		return ERR_TIMEOUT;	/* EISA code check */	writew_reg (CS89xProductIdentificationCode, CS89xIOPacketPagePointer);	pic1 = readw_reg (CS89xIOPacketpageDataPort0);	pic2 = readw_reg (CS89xIOPacketpageDataPort1);		if (pic1 != CS89xEISACODE)		return ERR_CHIPID;	/* Bus control, disable interrupts */	writew_reg (CS89xBusControl, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* Line control, disable Tx and Rx */	writew_reg (CS89xLineControl, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* Disable Receive interrupts */	writew_reg (CS89xReceiverConfiguration, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* Disable Transmit interrupts */	writew_reg (CS89xTransmitConfiguration, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* force the LEDs off */	/*	writew_reg (CS89xSelfControl, CS89xIOPacketPagePointer);	writew_reg (CS89xSelfCTLHC0E | CS89xSelfCTLHC1E,				CS89xIOPacketpageDataPort0);    */    	return 0;}#define STATUSLOOPCOUNT 20int cs89xStatus (void){	int i;	unsigned short lst;	for (i = 0; i < STATUSLOOPCOUNT; ++i) {		writew_reg (CS89xLineStatus, CS89xIOPacketPagePointer);		if ((lst =			 readw_reg (CS89xIOPacketpageDataPort0)) & CS89xLineSTLinkOK)			break;		usleep (100000);	}	if (i >= STATUSLOOPCOUNT)		return ERR_LINK;	if (lst & CS89xLineSTAUI)		Uart_Printf ("AUI port, ");	if (lst & CS89xLineST10BT)		Uart_Printf ("10BT port, ");	if (lst & CS89xLineSTPolarityOK)		Uart_Printf ("normal polarity, ");	else		Uart_Printf ("reverse polarity, ");	Uart_Printf ("IEEEIA ");	for (i = 0; i < 6; i += 2) {		unsigned short w;		writew_reg (CS89xIndividualAddress + i, CS89xIOPacketPagePointer);		w = readw_data (CS89xIOPacketpageDataPort0);		Uart_Printf ("%s%02x:%02x", i ? ":" : "", w & 0xff, (w >> 8) & 0xff);	}	Uart_Printf ("\n");	return 0;}int cs89xProbe(void){	unsigned short rev_type, chip_type, chip_revision;	unsigned short pic1, pic2, self;	    /* SROM nGCS3 Configuration for CS8900 */    rBWSCON = (rBWSCON & ~(BWSCON_ST3 | BWSCON_WS3 | BWSCON_DW3)) |      (BWSCON_ST3 | BWSCON_WS3 | BWSCON_DW(3, BWSCON_DW_16));    rBANKCON3= BANKCON_Tacs0 | BANKCON_Tcos4 | BANKCON_Tacc14 |      BANKCON_Toch1 | BANKCON_Tcah4 | BANKCON_Tacp6 | BANKCON_PMC1;			pic1 = readw_reg(CS89xIOPacketPagePointer);		/* EISA code check */	writew_reg (CS89xProductIdentificationCode, CS89xIOPacketPagePointer);	pic1 = readw_reg (CS89xIOPacketpageDataPort0);	writew_reg (CS89xProductIdentificationCode2, CS89xIOPacketPagePointer);	pic2 = readw_reg (CS89xIOPacketpageDataPort0);	writew_reg (CS89xSelfStatus, CS89xIOPacketPagePointer);	self = readw_reg (CS89xIOPacketpageDataPort0);	    /* get the chip type */    rev_type = pic2;    chip_type = rev_type &~ REVISON_BITS;    chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A';    if (chip_type != CS8900) {      Uart_Printf("cs89xProbe: wrong device driver!\n");	  return -1;    }        Uart_Printf("cs89xProbe: cs89%c0%s rev %c(%s) found at %#3lx\n",	   chip_type==CS8900 ? '0' : '2',	   chip_type==CS8920M ? "M" : "",	   chip_revision,	   self & ACTIVE_33V ? "3.3 Volts" : "5 Volts",	   CS89xIOBASE);		  return 0;	}int cs89xSetup (void){	int i;	/* IEEE Individual Address */	for (i = 0; i < 6; i += 2) {		unsigned short w = (netif.IEEEIA[i+1] << 8) | netif.IEEEIA[i];		writew_reg (CS89xIndividualAddress + i, CS89xIOPacketPagePointer);		writew_data (w, CS89xIOPacketpageDataPort0);	}	/* Receive Frame selection */	writew_reg (CS89xReceiverControl, CS89xIOPacketPagePointer);	writew_reg (CS89xRxCTLRxOKA | CS89xRxCTLIndividualA |				CS89xRxCTLBroadcastA, CS89xIOPacketpageDataPort0);	/* Enable Receive interrupts */	writew_reg (CS89xReceiverConfiguration, CS89xIOPacketPagePointer);	writew_reg (CS89xRxCFGRxOKiE, CS89xIOPacketpageDataPort0);	/* Enable Transmit interrupts */	writew_reg (CS89xTransmitConfiguration, CS89xIOPacketPagePointer);	writew_reg (CS89xTxCFGJaberiE | CS89xTxCFG16ColliE,				CS89xIOPacketpageDataPort0);	/* IRQ selection (INTRQ0) */	writew_reg (CS89xInterruptNumber, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* Line control, enable Tx and Rx */	writew_reg (CS89xLineControl, CS89xIOPacketPagePointer);	writew_reg (CS89xLineCTLSerRxOn | CS89xLineCTLSerTxOn,				CS89xIOPacketpageDataPort0);    /* Buffer configuration */    writew_reg (CS89xBufferConfiguration, CS89xIOPacketPagePointer);    writew_reg (CS89xBufCFGRxMissiE, CS89xIOPacketpageDataPort0);	/* allow status LEDs, disable sleep/standby mode */	writew_reg (CS89xSelfControl, CS89xIOPacketPagePointer);	writew_reg (0, CS89xIOPacketpageDataPort0);	/* Enable interrupts */	writew_reg (CS89xBusControl, CS89xIOPacketPagePointer);	writew_reg (CS89xBusCTLEnableIRQ, CS89xIOPacketpageDataPort0);	return cs89xStatus ();}

⌨️ 快捷键说明

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