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

📄 sed.c

📁 单片机上实现TCP的小程序
💻 C
字号:
/* 
 * Ethernet Driver.
 * A Very Simple set of ethernet driver primitives.  The ethernet (3com Mbus)
 * interface is controlled by busy-waiting, the application is handed the
 * location of on-board packet buffers, and allowed to fill in the
 * transmit buffer directly.  The interface is entirely blocking.
 * 
 * Written March, 1986 by Geoffrey Cooper
 *
 * Copyright (C) 1986, IMAGEN Corporation
 *  "This code may be duplicated in whole or in part provided that [1] there
 *   is no commercial gain involved in the duplication, and [2] that this
 *   copyright notice is preserved on all copies.  Any other duplication
 *   requires written notice of the author (Geoffrey H. Cooper)."
 * 
 * Primitives:
 *  sed_Init()  -- Initialize the package
 *  sed_FormatPacket( destEAddr ) => location of transmit buffer
 *  sed_Send( pkLength ) -- send the packet that is in the transmit buffer
 *  sed_Receive( recBufLocation ) -- enable receiving packets.
 *  sed_IsPacket() => location of packet in receive buffer
 *  sed_CheckPacket( recBufLocation, expectedType )
 *
 * Global Variables:
 *  sed_lclEthAddr -- Ethernet address of this host.
 *  sed_ethBcastAddr -- Ethernet broadcast address.
 */

#include "tinytcp.h"
#include "sed.h"

#define en10pages        ((en10size) >> pageshift)

octet *sed_va;                          /* virtual address of ethernet card */
eth_HwAddress sed_lclEthAddr;           /* local ethernet address */
eth_HwAddress sed_ethBcastAddr;         /* Ethernet broadcast address */
BOOL sed_respondARPreq;                 /* controls responses to ARP req's */
char bufAinUse, bufBinUse;              /* tell whether bufs are in use */

/* 
 *  Initialize the Ethernet Interface, and this package.  Enable input on
 * both buffers.
 */
sed_Init()
{
    int recState;
    register i, j;

    recState = 7;                       /* == mine + broad - errors */

    /* Map the Ethernet Interface in, and initialize sed_va */
    sed_va = (octet *)SED3CVA;        /* our virtual addr */

    /* Map memory for 3Com board (must be 8k boundary) */
    /* INSERT CODE HERE */
    map_ethernet_board();

    /* Reset the Ethernet controller */
    MECSR(sed_va) = RESET;
    for (i=0; i<10; i++);           /* delay a bit... */

    /* just copy on-board ROM to on-board RAM, to use std. address */
    Move(MEAROM(sed_va), sed_lclEthAddr, 6);
    Move(sed_lclEthAddr, MEARAM(sed_va), 6);
    
    MECSR(sed_va) |= AMSW;        /* and tell board we did it */

    /*
     * and initialize the exported variable which gives the Eth broadcast
     * address, for everyone else to use. 
     */
    for (i=0; i<3; i++) sed_ethBcastAddr[i] = 0xFFFF;
    
    /* accept packets addressed for us and broadcast packets */

    MECSR(sed_va) = (MECSR(sed_va)&~PA) | recState;

    /* declare both buffers in use... */
    bufAinUse = bufBinUse = TRUE;

}

/* 
 * Format an ethernet header in the transmit buffer, and say where it is.
 * Note that because of the way the 3Com interface works, we need to know
 * how long the packet is before we know where to put it.  The solution is
 * that we format the packet at the BEGINNING of the transmit buffer, and
 * later copy it (carefully) to where it belongs.  Another hack would be
 * to be inefficient about the size of the packet to be sent (always send
 * a larger ethernet packet than you need to, but copying should be ok for
 * now.
 */
octet *
sed_FormatPacket( destEAddr, ethType )
        register octet *destEAddr;
{
    register octet *xMitBuf;
    
    xMitBuf = &((octet *)MEXBUF(sed_va))[-0x800];
    Move( destEAddr, xMitBuf, 6 );
    Move( sed_lclEthAddr, xMitBuf + 6, 6 );
    *((short *)(xMitBuf+12)) = ethType;
    return ( xMitBuf+14 );
}

/*
 *  Send a packet out over the ethernet.  The packet is sitting at the
 * beginning of the transmit buffer.  The routine returns when the
 * packet has been successfully sent.
 */
sed_Send( pkLengthInOctets )
    register int pkLengthInOctets;
{
    register octet *fromO, *toO;
    register pkLength;
    register csr;

    pkLengthInOctets += 14;             /* account for Ethernet header */
    pkLengthInOctets = (pkLengthInOctets + 1) & (~1);

    if (pkLengthInOctets < E10P_MIN) 
        pkLengthInOctets = E10P_MIN; /* and min. ethernet len */

    /*  and copy the packet where it belongs */
    pkLength = pkLengthInOctets;
    fromO = &((octet *)MEXBUF(sed_va))[-0x800] + pkLength;
    toO = ((octet *)MEXBUF(sed_va));

    while ( pkLength-- ) *--toO = *--fromO;
    
    /* send the packet */
    
    MEXHDR(sed_va) = 2048 - pkLengthInOctets;
    MECSR(sed_va) |= TBSW;

    /* and wait until it has really been sent. */

    for (pkLength=0; pkLength < 15; pkLength++) {
        while ( (! ((csr = MECSR(sed_va)) & JAM)) && (csr & TBSW) )
            ;
        if (csr & JAM ) {
            /* Ethernet Collision detected... */
#ifdef DEBUG
            printf("sed: JAM: MECSR=%x\n", csr);
#endif
            MEBACK(sed_va) = clock_ValueRough();
            MECSR(sed_va) |= JAM;
        } else break;
    }
    if ( pkLength == 15 ) SysBug("Go and Buy a New Ethernet Interface.");

    /*  else we sent the packet ok. */
}

/* 
 *  Enable the Ethernet interface to receive packets from the network.  If
 * the argument is zero, enable both buffers.  If the argument is nonzero,
 * take it as the address of the buffer to be enabled.
 */
sed_Receive( recBufLocation )
    octet *recBufLocation;
{
    word enables = 0;

    if (recBufLocation == 0) {
        bufAinUse = FALSE;
        bufBinUse = FALSE;
        enables = (ABSW | BBSW);
    }
    recBufLocation -= 16;
    if (recBufLocation == ((octet *)MEAHDR(sed_va))) {
        bufAinUse = FALSE;
        enables = ABSW;
        }
    if (recBufLocation == ((octet *)MEBHDR(sed_va))) {
        bufBinUse = FALSE;
        enables = BBSW;
    }

    MECSR (sed_va) |= enables;
}

/* 
 * Test for the arrival of a packet on the Ethernet interface.  The packet may
 * arrive in either buffer A or buffer B; the location of the packet is
 * returned.  If no packet is returned withing 'timeout' milliseconds,
 * then the routine returns zero.
 * 
 * Note: ignores ethernet errors.  may occasionally return something
 * which was received in error.
 */

octet *
sed_IsPacket()
{
    register oldStatus;
    register octet *pb;
    
    pb = 0;
    if ( ! bufAinUse && (MECSR(sed_va)&ABSW) == 0 ) 
        pb = (octet *)MEAHDR(sed_va);
    if ( ! pb && ! bufBinUse && (MECSR(sed_va)&BBSW) == 0 )
        pb = (octet *)MEBHDR(sed_va);

    if ( pb ) {
        if ( ((octet *)pb) == ((octet *)MEAHDR(sed_va)) ) bufAinUse = 1;
        else bufBinUse = 1;
        pb += 16;                       /* get past the ethernet header */
    }

    return ( pb );
}

/* 
 *  Check to make sure that the packet that you received was the one that
 * you expected to get.
 */
sed_CheckPacket( recBufLocation, expectedType )
    word *recBufLocation;
    word expectedType;
{
    register recHeader = recBufLocation[-8];
    if ( (recHeader&R_ERROR) != 0 ||
         (recHeader&R_OFFSET) < E10P_MIN ) {
         return ( -1 );
    }
    if ( recBufLocation[-1] != expectedType ) {
        return ( 0 );
    }
    return (1);
}

⌨️ 快捷键说明

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