📄 etherdev.c
字号:
/* etherdev.c: * Micromonitor Ethernet support * for the NE2000 compatible AX88196 FE MAC controller. * * Based on the respective polling driver for mpc860. * and on the NE2000 driver for Linux by D.Becker. * * TODO: statistics not yet implemented properly. * * by Thomas E. Arvanitis (tharvan@inaccessnetworks.com) */#include "config.h"#if INCLUDE_ETHERNET#include "cpuio.h"#include "ether.h"#include "stddefs.h"#include "genlib.h"#include "8390.h"#include "SA-1100.h"extern void docommand(char *cmdline,int verbose);int EtherRLCnt, EtherDEFCnt, EtherLCCnt, EtherDRVRETRYCnt;int eninit();int txbuf_lock;long e8390_base = NE_BASE;static uchar txbuf[1600];static uchar rxbuf[RBUFCNT][1600];int rx_index;/* * Routines for easy acces to the data fifo. * They assume that the 8390 is in 68000 mode. * i.e. | LSB | MSB | * 15 8 7 0 * Len in bytes. */inline static void memcpy_to_dataport(unsigned int port, const void *from, int len){ register int i; register const unsigned short *f = from; register volatile unsigned short *t = (unsigned short *)port; for (i = 0; i < len / 2; i++) { *t = *f; f++; }}inline static void memcpy_from_dataport(unsigned int port, void *to, int len){ register int i; register volatile unsigned short *f = (unsigned short *)port; register unsigned short *t = to; for (i = 0; i < len / 2; i++) { *t = *f; t++; }}/* ShowEtherdevStats(): Called by the command "ether stat" on the monitor's command line. This function and a common ShowEthernetStats() are used to dump generic as well as device-specific ethernet driver statistics.*/voidShowEtherdevStats(){ printf("Driver retry count: %d\n",EtherDRVRETRYCnt); printf("Retry-count exceeded: %d times\n",EtherRLCnt); printf("Late-collision count: %d\n",EtherLCCnt); printf("Defer-indication count: %d\n",EtherDEFCnt);}/* EtherdevStartup(): Called by EthernetStartup(). Initialize all device-specific counters, reset and initialized the ethernet device.*/intEtherdevStartup(int verbose){ EtherRLCnt = 0; EtherLCCnt = 0; EtherDEFCnt = 0; EtherDRVRETRYCnt = 0; /* Put ethernet controller in reset: */ enreset(); /* Initialize controller: */ eninit(); return(0);}/* DisableEtherdev(): Called by DisableEthernet() to do the device-specific portion of the turn-down.*/voidDisableEtherdev(){ enreset();}voidenreset(){ volatile int i; int timeout; ulong msk; /* * Issue the timeout command to the controller, and then wait * for the completion. * Should make the timeout configurable (or simply a define?) */ outb(inb(NE_BASE + NE_RESET), NE_BASE + NE_RESET); timeout = 500000; while ((inb(NE_BASE+EN0_ISR) & ENISR_RESET) == 0) { timeout--; if (timeout <=0) break; } /* * Ack intr. */ outb(ENISR_RESET, NE_BASE + EN0_ISR); /* * inAccess Networks BlueArch board specific. * Toggle the reset pin of both the MAC and PHY. */ msk = 0x00000001UL << 3; msk &= 0x0FFFFFFF; GPDR |= msk; GPCR = msk; for (i = 0; i < 100000; i++); GPDR |= msk; GPSR = msk; msk = 0x00000001UL << 13; msk &= 0x0FFFFFFF; GPDR |= msk; GPCR = msk; for (i = 0; i < 100000; i++); GPDR |= msk; GPSR = msk;}/* * eninit(): * These is following the guidelines of National App. Note 874 * along with what D.Becker has done on the respective Linux driver. */inteninit(){ int i; int endcfg; ulong msk; if (sizeof(struct e8390_pkt_hdr)!=4) { printf("etherdev.c: header struct mispacked\n"); return(-1); } /* * inAccess Networks BlueArch board specific. * Initialize clocks for xilinx * and then call xlnx to program the xilinx. * It expects an oprouter.bit file in TFS. */ msk = 0x00000001UL << 26; msk &= 0x0FFFFFFF; GAFR |= msk; GPDR |= msk; outl(0x80000000, 0x90030008); docommand("xlnx -f oprouter.bit", 0); /* * Follow National Semi's recommendations for initing the DP8390. */ /* * Select Page 0 */ outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); /* 0x21 */ /* * Select: word-wide DMA transfers, 68k byte order. */ endcfg = 0x3; outb(endcfg, e8390_base + EN0_DCFG); /* * Clear the remote byte count registers. */ outb(0x00, e8390_base + EN0_RCNTLO); outb(0x00, e8390_base + EN0_RCNTHI); /* * Initialize Receive Configuration Register * Just set to monitor mode. */ outb(E8390_RXOFF, e8390_base + EN0_RXCR); /* 0x20 */ /* * Initialize Trasnmit Configuration Register * Just set to internal loopback mode. */ outb(E8390_TXOFF, e8390_base + EN0_TXCR); /* 0x02 */ /* * Set the transmit page and receive ring. */ outb(NESM_TX_START_PG, e8390_base + EN0_TPSR); outb(NESM_RX_START_PG, e8390_base + EN0_STARTPG); outb(NESM_RX_START_PG, e8390_base + EN0_BOUNDARY); outb(NESM_RX_STOP_PG, e8390_base + EN0_STOPPG); /* * Clear the pending interrupts and mask. */ outb(0xff, e8390_base + EN0_ISR); outb(0x00, e8390_base + EN0_IMR); /* * Copy the station address into the DS8390 registers. */ outb(E8390_NODMA + E8390_PAGE1 + E8390_STOP, e8390_base+E8390_CMD); /* 0x61 */ for(i = 1; i < 7; i++) { outb(BinEnetAddr[i-1], e8390_base + EI_SHIFT(i)); if(inb(e8390_base + EI_SHIFT(i))!=BinEnetAddr[i-1]) printf("Hw. address read/write mismap %d\n",i); } /* * Finally initialize the Current page reg; */ outb(NESM_RX_START_PG+1, e8390_base + EN1_CURPAG); outb(E8390_NODMA+E8390_PAGE0+E8390_STOP, e8390_base+E8390_CMD); rx_index = 0; /* * Clear ISR, mask all in IMR, issue start and enable tx and rx. */ outb(0xff, e8390_base + EN0_ISR); outb(0x00, e8390_base + EN0_IMR); outb(E8390_NODMA+E8390_PAGE0+E8390_START, e8390_base+E8390_CMD); outb(E8390_TXCONFIG, e8390_base + EN0_TXCR); /* xmit on. */ outb(E8390_RXCONFIG, e8390_base + EN0_RXCR); /* rx on, */ return(0);}/* enselftest(): 1. Enable ethernet interface. 2. Put the PHY in loopback. 3. Send a packet, and see if that packet is received. 4. Disable the ethernet interface. Return 1 if passed, else -1. Curently not implemented.*/intenselftest(int verbose){ if (verbose) printf("Self test not available\n"); return(1);}/* geteinbuf(): Get ethernet input buffer... Do whatever is necessary to pull the packet out of the ethernet device and pass that packet (along with the size of the packet) to the processPACKET() function.*/static intgeteinbuf(){ int rx_pkt_count; int pkt_len, pkt_stat; unsigned short current_offset; struct e8390_pkt_hdr rx_frame_hdr; register unsigned char rxing_page, this_frame, next_frame; rx_pkt_count = 0; while (1) { /* * Get the rx page (incoming packet pointer).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -