📄 cs89x.c
字号:
/* 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 "68vz328.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)#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))#endifinline static 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){ register unsigned short isq; ++netif.TotalIRQ; if (readl (ISR) & (1 << IRQ_NUM)) { 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; } } orl (1 << IRQ_NUM, ISR); }}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) printf ("AUI port, "); if (lst & CS89xLineST10BT) printf ("10BT port, "); if (lst & CS89xLineSTPolarityOK) printf ("normal polarity, "); else printf ("reverse polarity, "); printf ("IEEEIA "); for (i = 0; i < 6; i += 2) { unsigned short w; writew_reg (CS89xIndividualAddress + i, CS89xIOPacketPagePointer); w = readw_data (CS89xIOPacketpageDataPort0); printf ("%s%02x:%02x", i ? ":" : "", (w >> 8) & 0xff, w & 0xff); } printf ("\n"); return 0;}int cs89xSetup (void){ int i; /* IEEE Individual Address */ for (i = 0; i < 6; i += 2) { unsigned short w = (netif.IEEEIA[i] << 8) | netif.IEEEIA[i + 1]; 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); /* 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 + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -