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 + -
显示快捷键?