📄 if_ne2kd.c
字号:
/****************************************************************************** if_ne2k.c - NE2000 specific functions (or simply NE2000 driver)** portions Copyright (c) 2001 by Partner Voxtream A/S.** The authors hereby grant permission to use, copy, modify, distribute,* and license this software and its documentation for any purpose, provided* that existing copyright notices are retained in all copies and that this* notice and the following disclaimer are included verbatim in any* distributions. No written agreement, license, or royalty fee is required* for any of the authorized uses.** THIS SOFTWARE IS PROVIDED BY THE CONTRIBUTORS *AS IS* AND ANY EXPRESS OR* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.* IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.******************************************************************************** REVISION HISTORY (please don't use tabs!)**(yyyy-mm-dd)* 2001-03-01 Mads Christiansen <mads@mogi.dk>, Partner Voxtream.* Original file.** 2001-10-01 Craig Graham <c_graham@hinge.mistral.co.uk>.* NBuf's all the way...*****************************************************************************///#include <config.h>#include <stdio.h>#include <string.h>#include "../../netconf.h"#include "../../netbuf.h"#include "if_ne2kr.h"#include "if_ne2k.h"#include "if_os.h"#include "../../netifdev.h"
// ***** INTERNAL TYPE DEFINEStypedef struct{ u_char Status; u_char NextPage; u_short Length;} BufferHeader;typedef union{ u_short Word; u_char Uchar[2];} Word;// ***** PROTOTYPESstatic int ReadBuffer(BufferHeader *, u_char *, u_short);static NBuf *ReadBufferNBuf(BufferHeader *header, u_short length);// ***** DEFINES// Interrupt Mask Register Setup// Packet received, packet sent, receive error, transmit error, buffer overflow// No interrupt for counter overflow!#define IMR IMR_PRXE | IMR_PTXE | IMR_RXEE | IMR_TXEE | IMR_OVWE// Minimum packet size for the ethernet (this is without the trailing CRC)#define MIN_PACKET_SIZE 60// ***** LOCAL VARIABLES// Specific NIC info (first 6 bytes are cards MAC address)static u_char CardInfo[16];// Driver statisticsstatic Ne2kStatistics Statistics;// Next packet buffer pointer, used by Ne2kReceivestatic u_char NextPacket;u_char Ne2k_MacAddress[6];int Ne2k_MacAddressSet=0;/** * Override the cards default MAC address * @param pointer to a 6byte array containing the MAC address to use */void Ne2kSetMacAddress(const u_char *address){ memcpy(Ne2k_MacAddress,address,6); Ne2k_MacAddressSet=1;}static u_char Ne2kInitialize(u_char* address){ u_char ReadData; UINT32 Test0; UINT32 Test1; int Count; printf("Ne2kInitialise\n"); // ***** Reset statistics memset(&Statistics, 0, sizeof(Statistics)); printf("0\n"); // ***** Stop NIC OUTPORTB(NIC_CR, CR_STOP | CR_NO_DMA | CR_PAGE0); // Do a long wait to let the NIC finish receive/sending // THIS IS MANDATORY! LONGPAUSE; printf("1\n"); // ***** Detect NIC // Write 0x55 to 'Boundary Pointer Register' on page 0 OUTPORTB(PG0W_BNRY, 0x55); PAUSE; printf("2\n"); // Write 0xaa to 'Physical Address Pointer Register2' on page 1 OUTPORTB(NIC_CR, CR_STOP | CR_NO_DMA | CR_PAGE1); PAUSE; OUTPORTB(PG1W_PAR2, 0xaa); PAUSE; printf("3\n"); // Read 'Boundary Pointer Register' on page 0 OUTPORTB(NIC_CR, CR_STOP | CR_NO_DMA | CR_PAGE0); PAUSE; Test0 = INPORTB(PG0R_BNRY); PAUSE; printf("4\n"); // Read 'Physical Address Pointer Register2' on page 1 OUTPORTB(NIC_CR, CR_STOP | CR_NO_DMA | CR_PAGE1); PAUSE; Test1 = INPORTB(PG1R_PAR2); PAUSE; printf("5\n"); // ***** IF NIC is not found THEN RETURN FALSE if ((Test0 != 0x55) || (Test1 != 0xaa)) { printf("NIC not found Test0=%lx Test1=%lx\n",Test0,Test1); return FALSE; } printf("Detected Ne2k NIC :)\n"); // ***** Read NIC's MAC address // We want to read MAC address, select transfer mode (word), no loopback, FIFO 4 words OUTPORTB(NIC_CR, CR_PAGE0 | CR_NO_DMA | CR_STOP ); PAUSE; OUTPORTB(PG0W_DCR, DCR_FT1 | DCR_LS | DCR_WTS); PAUSE; // Setup Remote Byte Count Register // We need 16 bytes (value must be doubled) OUTPORTB(PG0W_RBCR0, 0x20); PAUSE; OUTPORTB(PG0W_RBCR1, 0x00); PAUSE; // Setup Remote Start Address Register OUTPORTB(PG0W_RSAR0, 0x00); PAUSE; OUTPORTB(PG0W_RSAR1, 0x00); PAUSE; // DMA Remote Read and Start NIC OUTPORTB(NIC_CR, CR_PAGE0 | CR_DMA_READ | CR_START); PAUSE; // Read 16 bytes of data (first 6 is our MAC address), the rest is currently not used for (Count = 0; Count < 16; Count++) CardInfo[Count] = INPORTB(NIC_DATAPORT); //++cg[25/09/2001]: allow overrider of MAC address, as current ls808 design doesn't include the bootrom/e2 with the MAC in it... if(Ne2k_MacAddressSet) { printf("ne2k reports"); memcpy(CardInfo,Ne2k_MacAddress,6); } else { printf("override"); } printf(" MAC address = %x:%x:%x:%x:%x:%x\n",CardInfo[0],CardInfo[1],CardInfo[2],CardInfo[3],CardInfo[4],CardInfo[5]); // ***** Reset NIC // Stop NS 8390 CHIP, somewhere it states that issuing a read to // NIC address + 1fh (NIC_RESET) will issue a reset on the NIC! SO THIS IS DONE! ReadData = INPORTB(NIC_RESET); // Do a long wait for the 8390 to reset. // THIS IS MANDATORY! LONGPAUSE; OUTPORTB(NIC_RESET, ReadData); // THIS IS DONE IN A PACKET DRIVER ? PAUSE; // *********************************************************************************** // ***** The following initialization procedure is taken from the datasheet // ***** DP8390D/NS32490D NIC Network Interface Controller (July 1995) from National // ***** Semiconductor. // ***** 1. Stop NIC (again...) OUTPORTB(NIC_CR, CR_PAGE0 | CR_STOP | CR_NO_DMA ); // Don't do a longpause, the NIC should already be stopped PAUSE; // ***** 2. Initialize Data Configuration Register (DCR) to normal operation, // word wide transfer, 4 words FIFO threshold OUTPORTB(PG0W_DCR, DCR_FT1 | DCR_LS | DCR_WTS); PAUSE; // ***** 3. Clear Remote Byte Count Registers (RBCR0, RBCR1) OUTPORTB(PG0W_RBCR0, 0x00); PAUSE; OUTPORTB(PG0W_RBCR1, 0x00); PAUSE; // ***** 4. Initialize Receive Configuration Register (RCR) to accept broadcast packets and // packets addressed to this NIC (MAC address). // NOTICE THAT SOME NE2000 CLONES HAVE ACCEPT BROADCAST AND ACCEPT MULTICAST BITS HARDWIRED TOGETHER! // SO IF YOU SET ONE YOU ALSO SET THE OTHER! OUTPORTB(PG0W_RCR, RCR_AB | RCR_AM); PAUSE; // ***** 5. Place the NIC in Loopback Mode 1, internal loopback (Transmit Configuration Register). OUTPORTB(PG0W_TCR, TCR_LB0); PAUSE; // ***** 6. Initialize Page Start Register, Boundary Pointer & Page Stop Register OUTPORTB(PG0W_PSTART, RSTART_PG); PAUSE; OUTPORTB(PG0W_BNRY, RSTART_PG); PAUSE; OUTPORTB(PG0W_PSTOP, RSTOP_PG); PAUSE; // ***** 7. Clear Interrupt Status Register (ISR) by writing 0FFh to it.. OUTPORTB(PG0W_ISR, 0xFF); PAUSE; // ***** 8. Initialize IMR (Interrupt Mask Register) to accept: OUTPORTB(PG0W_IMR, IMR); PAUSE; // ***** 9. Initialize Physical Address Registers (PAR0-PAR5) (MAC Address) // Select PAGE 1 OUTPORTB(NIC_CR, CR_PAGE1 | CR_NO_DMA | CR_STOP); PAUSE; // Setup MAC address for (Count = 0; Count < 6; Count++) { OUTPORTB(PG1W_PAR0 + Count, CardInfo[Count]); PAUSE; } // ***** Initialize Multicast Address Registers to 00h (MAR0-MAR7) (don't accept multicast packets) for (Count = 0; Count < 8; Count++) { OUTPORTB(PG1W_MAR0 + Count, 0x00); PAUSE; } // ***** Initialize CURRent pointer to Boundary Pointer + 1 OUTPORTB(PG1W_CURR, RSTART_PG+1); PAUSE; NextPacket = RSTART_PG + 1; // ***** 10. Start NIC OUTPORTB(NIC_CR, CR_PAGE0 | CR_NO_DMA | CR_START); PAUSE; // ***** 11. Initialize the Transmit Configuration Register for normal operation (out of loopback mode) OUTPORTB(PG0W_TCR, 0x00); PAUSE; // ***** Copy the 6 bytes long MAC address if (address) memcpy(address, CardInfo, 6); // ***** RETURN TRUE return TRUE;}static u_char Ne2kStop(void){ // ***** Stop NIC OUTPORTB(NIC_CR, CR_STOP | CR_NO_DMA | CR_PAGE0); PAUSE; // ***** Disable interrupts from NIC OUTPORTB(PG0W_IMR, 0x00); PAUSE; // Clear any generated interrupts OUTPORTB(PG0W_ISR, 0xff); PAUSE; return 0;}void Ne2kProcessInterrupts(void){ register unsigned char i; // ***** Disable netcard IRQ DISABLE_NE2K_IRQ; // ***** Disable interrupts from NIC (IMR = 0) OUTPORTB(PG0W_IMR, 0x00); PAUSE; i = INPORTB(PG0R_ISR); // ***** WHILE (ISR > 0) while (i = INPORTB(PG0R_ISR) & 0x3F) { PAUSE; // ***** ALL INTERRUPTS MUST BE CLEARED // ***** (except for OVW, which is cleared when calling Ne2kReceive) // ***** IF overwrite warning interrupt THEN if (i & ISR_OVW) { //printf("nei-OVW\n"); PAUSE; // ***** CALL Ne2kReceiveEvent() Ne2kReceiveEvent(); } else PAUSE; // ***** IF packet received interrupt THEN if (i & ISR_PRX) { //printf("nei-Rx\n"); PAUSE; // ***** clear packet received interrupt status bit OUTPORTB(PG0W_ISR, ISR_PRX); PAUSE; // ***** CALL Ne2kReceiveEvent() Ne2kReceiveEvent(); } else PAUSE; // ***** IF packet transmitted interrupt THEN if (i & ISR_PTX) { //printf("nei-Tx\n"); PAUSE; // ***** clear packet transmitted interrupt status bit OUTPORTB(PG0W_ISR, ISR_PTX); PAUSE; // ***** CALL Ne2kTransmitEvent() Ne2kTransmitEvent(); } else PAUSE; // ***** IF receive error interrupt THEN if (i & ISR_RXE) { //printf("nei-4\n"); PAUSE; // ***** clear receive error interrupt status bit OUTPORTB(PG0W_ISR, ISR_RXE); PAUSE; // ***** update receive error statistics Statistics.ReceiveErrors++; } else PAUSE; // ***** IF transmit error interrupt THEN if (i & ISR_TXE) { //printf("nei-5\n"); PAUSE; // ***** clear transmit error interrupt status bit OUTPORTB(PG0W_ISR, ISR_TXE); PAUSE; // ***** update transmit error statistics Statistics.TransmitErrors++; // ***** CALL Ne2kTransmitEvent() Ne2kTransmitEvent(); } else PAUSE; /* NETWORK TALLY COUNTERS ARE NOT USED, THEY COULD BE USED FOR MORE PRECISE STATISTICS // ***** IF counter overflow interrupt THEN if (i & ISR_CNT) { PAUSE; // ***** clear counter overflow interrupt status bit OUTPORTB(PG0W_ISR, ISR_CNT); PAUSE; // ***** empty tally counters INPORTB(PG0R_CNTR0); PAUSE; INPORTB(PG0R_CNTR2); PAUSE; INPORTB(PG0R_CNTR3); PAUSE; } else PAUSE; */ } // Enabling interrupts again, don't change this order or you might loose interrupts! DISABLE_INTERRUPTS; ENABLE_NE2K_IRQ; SIGNAL_EOI; ENABLE_INTERRUPTS;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -