⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ne2000.c

📁 该BSP是基于PXA270+WINCE的BSP
💻 C
📖 第 1 页 / 共 3 页
字号:

    // If current_page register is not equal to NextPage
    // then we have a packet in the ring buffer.
    UsePage1();
    new_current_page = ReadByte(NIC_CURRENT);
    UsePage0();

    if ((int_status & NIC_ISR_RCV_ERR) && (!overflowrestartflag)) {
        rsr = ReadByte(NIC_RCV_STATUS);
        if (!(rsr & RSR_PACKET_OK)) {
            //EdbgOutputDebugString("HandleReceive NIC_ISR_RCV_ERR (rsr = %B)\r\n", rsr);
            INSB((NextPage<<8), sizeof(rcv_header), rcv_header);
#ifdef NE2000_DUMP_FRAMES
            DumpNE2000Header();
#endif            
            /*
            if (rsr & RSR_CRC_ERROR) {
                EdbgOutputDebugString("CRC Error\r\n");
            }
            if (rsr & RSR_MULTICAST) {
                EdbgOutputDebugString("MULTICAST\r\n");
            }
            if (rsr & RSR_DISABLED) {
                EdbgOutputDebugString("Receiver is disabled\r\n");
            }
            if (rsr & RSR_DEFERRING) {
                EdbgOutputDebugString("Receiver is deferring\r\n");
            }
            */
#ifdef NE2000_DUMP_FRAMES
            DumpEtherFrame(&(rcv_dest_addr0), 14);
#endif
            InitRcvQueue();
            HWSetBoundary(new_current_page);
            NextPage = new_current_page;
            goto hr_exit;
        }
    }
    if (new_current_page == NextPage) {
        //EdbgOutputDebugString("HandleReceive No new packets\r\n");
        goto hr_exit;
    }

    // There is another packet in the receive buffer.
    // Look at the packet's header
    INSB((NextPage<<8), sizeof(rcv_header), rcv_header);
    if ((adjust = check_rcv_header()) == 0xffff) {
        //EdbgOutputDebugString("HandleReceive check_rcv_header() failed!\r\n");
        // Advance receive buffer pointer on packet errors 
        NextPage = new_current_page;
        goto hr_exit;
    }

    packetlen = (WORD)(rcv_frame_len1<<8)+(WORD)rcv_frame_len0 - NIC_HEADER_LEN;
    rcv_next_buff = NextPage + rcv_frame_len1 + 1;
    if (rcv_next_buff > pstop) {
        rcv_next_buff -= pstop - pstart;
    }

    //
    // Filter out non-ARP broadcast packets.
    //
    if (rcv_status & NIC_RCV_STAT_MC_BC) {
        if ((dwConfigOptions & OPT_BROADCAST_FILTERING) &&
            ((rcv_header[16] != 8) || (rcv_header[17] != 6))) {
            NextPage = rcv_next_buff;
            //EdbgOutputDebugString("HandleReceive Dropping non-ARP broadcast packet!\r\n");
#ifdef NE2000_DUMP_FRAMES
            DumpEtherFrame(&(rcv_dest_addr0), 14);
#endif
            goto hr_more_packets;
        }
    }

    packetptr = (NextPage << 8) + NIC_HEADER_LEN + adjust;
    if (QueueRcv(packetlen, packetptr, rcv_next_buff)) {
        NextPage = rcv_next_buff;
        goto hr_more_packets;
    }

hr_exit:    // Done looking for receive packets

    if (!g_rcv_cnt) {
        //
        // We have caught up with receive packets, advance the boundary ptr
        //
        HWSetBoundary(NextPage);
    }

    if (overflowrestartflag) {
        // Do steps 9 and 10 of overflow recovery        
        WriteByte(NIC_INTR_STATUS, NIC_ISR_OVERWRITE);  // 9. reset the OVW bit        
        WriteByte(NIC_XMIT_CONFIG, NIC_TCR_NORMAL);     // 10. Get out of loopback mode.
        overflowrestartflag = 0;    
    }
    //EdbgOutputDebugString("-HandleReceive\r\n");
}   // HandleReceive

static void HandleTransmit(void)
{
    // check for transmit errors
    if ((int_status & NIC_ISR_XMIT_ERR) || (!(ReadByte(NIC_XMIT_STATUS) & NIC_TSR_SUCCESS))) {
        iodelay(15);
        WriteByte(NIC_XMIT_CONFIG, NIC_TCR_LOOPBACK1);  // place NIC in loopback mode.
        UsePage0();                                     // start in loopback mode.
        ReadCmd();
        WriteByte(NIC_XMIT_CONFIG, NIC_TCR_NORMAL);     // get out of loopback mode.
        UsePage0();                                     // start the NIC
        ReadCmd();
    }
    transmitting = 0;
}

void NE2000_ISR(void)
{

#define ISR_LOOP_MAX 32

    int loopcnt = ISR_LOOP_MAX;

    command_reg = ReadCmd();
    UsePage0();
    int_status = ReadByte(NIC_INTR_STATUS);

    while (int_status & NIC_ISR_MOREWORK) {
        WriteByte(NIC_INTR_STATUS, int_status); // ack the interrupts    
        //
        // Respond to the interrupt status register bits.
        //
        if (int_status & NIC_ISR_OVERWRITE) {
            HandleBufferOverflow();
        }
    
        //if (int_status & (NIC_ISR_PACKET_RCVD|NIC_ISR_RCV_ERR)) {
            HandleReceive();
        //}

        if (int_status & (NIC_ISR_PACKET_XMITD|NIC_ISR_XMIT_ERR)) {
            HandleTransmit();
        }

		if (!-- loopcnt)
			break;
			
	    command_reg = ReadCmd();
		int_status = ReadByte(NIC_INTR_STATUS);
    }
}   // NE2000_ISR


DWORD
NE2000GetPendingInts()
{
    //EdbgOutputDebugString("+NE2000GetPendingInts\r\n");
    NE2000_ISR();
    //EdbgOutputDebugString("-NE2000GetPendingInts\r\n");
    if (g_rcv_cnt) {
#ifdef DEBUG_SINGLE_CHAR
        EdbgOutputDebugString("R"); // indicating a received packet
#endif
        return INTR_TYPE_RX;    
    }
#ifdef DEBUG_SINGLE_CHAR
    EdbgOutputDebugString("B"); // discarding non-ARP broadcast traffic.
#endif
    return 0;    
}   // NE2000GetPendingInts


//
// This routine is polled to find out if a frame has been received.  If there are no frames
//  in the RX FIFO, the routine will return 0.  If there was a frame that was received correctly,
//  it will be stored in pwData, otherwise it will be discarded.  
//
UINT16
NE2000GetFrame(BYTE *pbData, UINT16 *pwLength )
{
    PRCV_ENTRY prcv;
    WORD len;

    //EdbgOutputDebugString("+NE2000GetFrame\r\n");
    EDBG_DEBUGLED(LED_GETFRAME_ENTRY,0);

    len = *pwLength;
    *pwLength = 0;
    if (!g_rcv_cnt) {
        NE2000_ISR();
    }
    if (g_rcv_cnt) {
        prcv = &(g_rcv_list[g_rcv_next]);
        if (prcv->re_state == RCV_USED) {
            //EdbgOutputDebugString("NE2000GetFrame: reading %d (ptr 0x%x, len %d)\r\n",
            //    g_rcv_next, prcv->re_ptr, prcv->re_len);
            if (prcv->re_len < len) {
                len = prcv->re_len;
            }
            INSB(prcv->re_ptr, len, pbData);
            HWSetBoundary(prcv->re_next);
            *pwLength = len;
            prcv->re_state = RCV_FREE;
            g_rcv_cnt--;
            g_rcv_next++;
            if (g_rcv_next == RCV_Q_SIZE) {
                g_rcv_next = 0;
            }
    }
    } else {
#ifdef DEBUG_SINGLE_CHAR
        EdbgOutputDebugString("Z"); // Receive buffer empty
#endif
    }

    //EdbgOutputDebugString("-NE2000GetFrame *pwLength = %d\r\n", *pwLength);
    EDBG_DEBUGLED(LED_GETFRAME_EXIT,0);
    return *pwLength;
} // NE2000GetFrame()


//
// This routine should be called with a pointer to the ethernet frame data.  It is the caller's
//  responsibility to fill in all information including the destination and source addresses and
//  the frame type.  The length parameter gives the number of bytes in the ethernet frame.
// The routine will not return until the frame has been transmitted or an error has occured.  If
//  the frame transmits successfully, 0 is returned.  If an error occured, a message is sent to
//  the serial port and the routine returns non-zero.
//
UINT16
NE2000SendFrame( BYTE *pbData, DWORD dwLength )
{
    int nIters;

    //EdbgOutputDebugString("+NE2000SendFrame\r\n");
    //
    // Loop here until the request is satisfied, or we timeout
    //
    for (nIters = 0; transmitting; nIters ++) {
        iodelay(20);
        NE2000_ISR();
        if (nIters > 1000) {
            EdbgOutputDebugString("NE2000SendFrame Timed out waiting for transmit buffers\n");
            //
            // 2 seconds ought to be enough to transmit a packet!!! Reset for transmit errors
            // 
            iodelay(15);
            WriteByte(NIC_XMIT_CONFIG, NIC_TCR_LOOPBACK1);  // place NIC in loopback mode.
            UsePage0();                                     // start in loopback mode.
            ReadCmd();
            WriteByte(NIC_XMIT_CONFIG, NIC_TCR_NORMAL);     // get out of loopback mode.
            UsePage0();                                     // start the NIC
            ReadCmd();

            HWReset();
            transmitting = 0;
        }
    }

    curr_xmit_len = (WORD)dwLength;
    //EdbgOutputDebugString("NE2000SendFrame %d byte packet\r\n", curr_xmit_len);
#ifdef DEBUG_SINGLE_CHAR
    EdbgOutputDebugString("S"); // Send packet
#endif
    OUTSB(srambase, curr_xmit_len, pbData);      
    WriteByte(NIC_XMIT_START, tbb_start);
    if (curr_xmit_len < 60) {
        curr_xmit_len = 60;
    }
    if (curr_xmit_len > 1536) {
        curr_xmit_len = 1536;
    }
    WriteByte(NIC_XMIT_COUNT_LSB, (BYTE)curr_xmit_len);
    WriteByte(NIC_XMIT_COUNT_MSB, (BYTE)(curr_xmit_len>>8));
    transmitting = 1;
    WriteCmd(NIC_Transmit);
    iodelay(80);
    NE2000_ISR();
    //EdbgOutputDebugString("-NE2000SendFrame\r\n");
    return 0;
} // NE2000SendFrame()


#ifdef NE2000_DUMP_FRAMES
static void
DumpEtherFrame( BYTE *pFrame, WORD cwFrameLength )
{
    int i,j;

    EdbgOutputDebugString( "Frame Buffer Address: 0x%X\r\n", pFrame );
    EdbgOutputDebugString( "To: %B:%B:%B:%B:%B:%B  From: %B:%B:%B:%B:%B:%B  Type: 0x%H  Length: %u\r\n",
        pFrame[0], pFrame[1], pFrame[2], pFrame[3], pFrame[4], pFrame[5],
        pFrame[6], pFrame[7], pFrame[8], pFrame[9], pFrame[10], pFrame[11],
        ntohs(*((UINT16 *)(pFrame + 12))), cwFrameLength );
    for( i = 0; i < cwFrameLength / 16; i++ ) {
        for( j = 0; j < 16; j++ )
            EdbgOutputDebugString( " %B", pFrame[i*16 + j] );
        EdbgOutputDebugString( "\r\n" );
    }
    for( j = 0; j < cwFrameLength % 16; j++ )
        EdbgOutputDebugString( " %B", pFrame[i*16 + j] );
    EdbgOutputDebugString( "\r\n" );
}

static void
DumpNE2000Header(void)
{
    EdbgOutputDebugString( "NE2000 Frame Header at %B: Status: %B, Next Buffer: %B, Len0: %B, Len1: %B\r\n",
        NextPage, rcv_status, rcv_next_buff, rcv_frame_len0, rcv_frame_len1);
}
#endif  // NE2000_DUMP_FRAMES

BOOL
NE2000ReadEEPROM( UINT16 EEPROMAddress , UINT16 *pwVal)
{
    return FALSE;
}

BOOL
NE2000WriteEEPROM( UINT16 EEPROMAddress, UINT16 Data )
{
    return FALSE;
}

//
// This routine is used by the OAL to configure the debug Ethernet driver. Currently
// the following options are defined:
//     OPT_BROADCAST_FILTERING  -- If set, filter out all broadcast packets except ARP packets
// 
DWORD
NE2000SetOptions(DWORD dwOptions)
{
    DWORD dwOldOptions = dwConfigOptions;
    dwConfigOptions = dwOptions;
    return dwOldOptions;
}

#ifdef USE_ISA_PNP_STUFF
BYTE *
NE2000InitISAPNP(DWORD dwIOBase, DWORD dwIRQ)
{
    ULONG nTmpVal = 0;
    ISA_PNP_CONFIG      PnPInfo;
    ISA_PNP_RESOURCES   PnPResources;
    int                 nCSN;
    DWORD               nLogicalDevice;
    DWORD               i;
    BOOL                bFoundIt;
    ULONG               ulReturn;
    BYTE * pbRet;

	EdbgOutputDebugString("NE2000InitISAPNP: Init\r\n");

    bFoundIt = FALSE;
    pbRet = (BYTE *) dwIOBase;
    
    //
    // Scan the PnP ISA cards for an NE2000
    //
    for (nCSN = 1; ; nCSN++) {
        ulReturn = ISAGetBusDataByOffset(0, nCSN << 8, &PnPInfo, 0, sizeof(PnPInfo));

        if (ulReturn == 0) {
            // Couldn't even get the card data, though it's supposed to exist.
            EdbgOutputDebugString("NE2000InitISAPNP: Couldn't find a ISA PnP NE2000.\r\n");
            return NULL;
        }

        switch (PnPInfo.VendorID) {            
            case 0x07052201:    // LINKSYS
                break;

            default:
                //
                // Not a recognized NE2000 ISA PNP card, skip to the next CSN...
                //
                continue;
        }

        EdbgOutputDebugString("NE2000InitISAPNP: Found NE2000 ISA PNP card: serial# 0x%x\r\n", PnPInfo.SerialNumber);

        for (nLogicalDevice = 0; nLogicalDevice < PnPInfo.NumberLogicalDevices; nLogicalDevice++) {

            EdbgOutputDebugString("NE2000InitISAPNP: LogicalDeviceID[%d] = 0x%x\r\n",
                nLogicalDevice, PnPInfo.LogicalDeviceInfo[nLogicalDevice].LogicalDeviceID);

            switch (PnPInfo.LogicalDeviceInfo[nLogicalDevice].LogicalDeviceID) {
            case 0x7052201:    // LINKSYS ISA PNP NE2000
                bFoundIt = TRUE;
                break;

            default:
                continue;
            }

            break;
        }

        if (bFoundIt) {
            break;
        }
    }

    EdbgOutputDebugString("Out of scan loop\r\n");
    
    if (!bFoundIt) {
        EdbgOutputDebugString("NE2000InitISAPNP: Couldn't find a ISA PnP NE2000\r\n");
        return NULL;
    }

    //
    // Get the resource information for this card.
    //
    ulReturn = ISAGetBusDataByOffset(0, (nCSN << 8) | nLogicalDevice, &PnPResources, 1, sizeof(PnPResources));
    if (ulReturn == 0) {
        EdbgOutputDebugString("NE2000InitISAPNP: Couldn't read resources\r\n");
        return NULL;
    }

    EdbgOutputDebugString("After Reading 1st.\r\n");
    //if (!(PnPResources.Flags & ISA_PNP_RESOURCE_FLAG_ACTIVE)) {
        //
        // Need to set the resources and activate the device
        //
        EdbgOutputDebugString("Setup the resources\r\n");
        PnPResources.IoPortDescriptors[0] = (USHORT) dwIOBase;
        PnPResources.IRQDescriptors[0].IRQLevel = (UCHAR) dwIRQ;
        PnPResources.IRQDescriptors[0].IRQType = 2;     // High Edge Triggered
        PnPResources.Flags = ISA_PNP_RESOURCE_FLAG_ACTIVE;

        EdbgOutputDebugString("After Assigning.\r\n");
        
        EdbgOutputDebugString("About to Set the resources\r\n");
        ulReturn = ISASetBusDataByOffset(0, (nCSN << 8) | nLogicalDevice, &PnPResources, 1, sizeof(PnPResources));
        if (ulReturn == 0) {
            EdbgOutputDebugString("NE2000InitISAPNP: Error writing resources\r\n");
            return NULL;
        }

        EdbgOutputDebugString("After Setting.\r\n");
        
        ulReturn = ISAGetBusDataByOffset(0, (nCSN << 8) | nLogicalDevice, &PnPResources, 1, sizeof(PnPResources));    
        if (ulReturn == 0) {
            EdbgOutputDebugString("NE2000InitISAPNP: Couldn't read resources\r\n");
            return NULL;
        }

    
        EdbgOutputDebugString("NE2000InitISAPNP: Current settings: IOBase = 0x%x, IRQ = %d\r\n",
            PnPResources.IoPortDescriptors[0], PnPResources.IRQDescriptors[0].IRQLevel);
/*
    } else {
        EdbgOutputDebugString("second option on resources\r\n");
        pbRet = (BYTE*)PnPResources.IoPortDescriptors[0];
        dwIRQ = PnPResources.IRQDescriptors[0].IRQLevel;
*/        
    //}

    //
    // For now disable the other logical devices
    //
    EdbgOutputDebugString("Disable logical devices\r\n");
    memset(&PnPResources, 0, sizeof(PnPResources));

    for (i = 0; i < PnPInfo.NumberLogicalDevices; i++) {
        if (i != nLogicalDevice) {
            ulReturn = ISASetBusDataByOffset(0, (nCSN << 8) | i, &PnPResources, 1, sizeof(PnPResources));
        }
    }

	EdbgOutputDebugString("NE2000InitISAPNP Detected, Interrupt = %d, I/O = 0x%x\r\n",
	    dwIRQ, pbRet);

	ISAPNP_Sleep(100);	// allow .1Sec stabilization
    return pbRet;
}
#endif // x86

⌨️ 快捷键说明

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