/*
Автор:	Дьячков Петр
Дата:	12.05.2011
Версия:	1.1

Программа, реализующая ICMP-сервера на микроконтроллере 1986ВЕ91Т1 и Ethernet-контроллере 5600ВГ1У.
Используется параллельный интерфейс.

1986ВЕ91Т1: Частота тактирования микроконтроллера: 8 МГц.

5600ВГ1У: MAC-адрес: 0A.1B.2C.3D.4E.5F
          Прием широковещательных пакетов и с полным совпадением MAC-адреса

          IP-адрес: 192.168.1.87
          контроллер по ICMP-протоколу может принимать пакеты от 0 до 1472 байт
		  фрагментированные пакеты не поддерживаются.
*/

#define NUMRXDESCRIPTOR	16	//количество дескрипротов принимаемых пакетов (минимум 1, максимум 32)
#define NUMTXDESCRIPTOR	16	//количество дескрипротов отправляемых пакетов (минимум 1, максимум 32)

#define PRINTSTATUSON	1	//компилляция программы с подключением отладочной информацией (1 - включено, 0 - отключено)

//Структура для дескриптора принимаемых пакетов
typedef struct
{
	unsigned int	StartAddress;			//начальный адрес дескриптора в памяти контроллера 1986ВЕ91Т1
	unsigned short	Status;					//стату дескриптора
	unsigned short	PacketLength;			//длина принятого пакета
	unsigned short	PacketStartAddressH;	//адрес в буфере, где расположен первый байт пакета (старшая часть, всегда 0х0000)
	unsigned short	PacketStartAddressL;	//адрес в буфере, где расположен первый байт пакета (младшая часть)
	unsigned short	LastDesc;				//признак последнего дескриптора (1 - последний дескриптор, 0 - не последний дескриптор)
} _rx_descriptor;

//Структура для работы с текущим дескриптором принимаемых пакетов
typedef struct
{
	_rx_descriptor* RxCurrentDescriptor;	//указатель на текущий дескриптор принимаемых пакетов
	unsigned short Number;					//номер текущего дескриптора (принимает значения от 0 до NUMRXDESCRIPTOR-1)
} _rx_current_descriptor;

//Структура для дескриптора отправляемых пакетов
typedef struct
{
	unsigned int	StartAddress;			//начальный адрес дескриптора в памяти контроллера 1986ВЕ91Т1
	unsigned short	Status;					//стату дескриптора
	unsigned short	PacketLength;			//длина принятого пакета
	unsigned short	PacketStartAddressH;	//адрес в буфере, где расположен первый байт пакета (старшая часть, всегда 0х0000)
	unsigned short	PacketStartAddressL;	//адрес в буфере, где расположен первый байт пакета (младшая часть)
	unsigned short	LastDesc;				//признак последнего дескриптора (1 - последний дескриптор, 0 - не последний дескриптор)
} _tx_descriptor;

//Структура для работы с текущим дескриптором отпарвляемых пакетов
typedef struct
{
	_tx_descriptor* TxCurrentDescriptor;	//указатель на текущий дескриптор отправляемых пакетов
	unsigned short Number;					//номер текущего дескриптора (принимает значения от 0 до NUMTXDESCRIPTOR-1)
	unsigned int FirstEmptyWord;			//адрес первого свободного слова в буфере передатчика
} _tx_current_descriptor;

#include "config.h"
	 
//Структура для работы с принятыми Ethernet-пакетами
typedef struct
{
        unsigned char Data[1600];       //Данные пакета
        unsigned short Length;          //Размер принятого пакета
        unsigned short Address;         //Адрес, по которому расположен пакет в буфере приемника
        unsigned char Remote_IP[4];     //удаленный IP-адрес (IP-адрес отправителя принятого пакета)
        unsigned char Remote_MAC[6];    //удаленный MAC-адрес (MAC-адрес отправителя принятого пакета)

#if PRINTSTATUSON
		unsigned int CounterTxPacket;	//Счетчик отправленных пакетов
		unsigned int CounterRxPacket;	//Счетчик принятых пакетов
#endif	//PRINTSTATUSON

} _ethernet_packet;
						   
int Read_Packet(_ethernet_packet*);			//функция для считывания принятого пакета
unsigned short CheckSum_IP(_ethernet_packet*);		//функция для вычисления контрольной суммы IP-пакета
unsigned short CheckSum_ICMP(_ethernet_packet*);	//функция для вычисления контрольной суммы ICMP-пакета
void InitTxDescriptor(void);						//функция инициализации дескрипторов отправляемых пакетов
void InitRxDescriptor(void);						//функция инициализации дескрипторов принимаемых пакетов
int Answear_ARP(_ethernet_packet*);					//функция формирования ответа на ARP-запрос
int Answear_ICMP(_ethernet_packet*,unsigned char*);	//функция формирования ответа на ICMP-запрос

#if PRINTSTATUSON
void Request_Status(_ethernet_packet*);
#endif	//PRINTSTATUSON

//массив дескрипторов отправляемых пакетов
_tx_descriptor ATxDescriptor[32] =  {{0x60006000,0x0000,0,0,0,0},{0x60006010,0x0000,0,0,0,0},{0x60006020,0x0000,0,0,0,0},{0x60006030,0x0000,0,0,0,0},
									 {0x60006040,0x0000,0,0,0,0},{0x60006050,0x0000,0,0,0,0},{0x60006060,0x0000,0,0,0,0},{0x60006070,0x0000,0,0,0,0},
									 {0x60006080,0x0000,0,0,0,0},{0x60006090,0x0000,0,0,0,0},{0x600060A0,0x0000,0,0,0,0},{0x600060B0,0x0000,0,0,0,0},
									 {0x600060C0,0x0000,0,0,0,0},{0x600060D0,0x0000,0,0,0,0},{0x600060E0,0x0000,0,0,0,0},{0x600060F0,0x0000,0,0,0,0},
									 {0x60006100,0x0000,0,0,0,0},{0x60006110,0x0000,0,0,0,0},{0x60006120,0x0000,0,0,0,0},{0x60006130,0x0000,0,0,0,0},
									 {0x60006140,0x0000,0,0,0,0},{0x60006150,0x0000,0,0,0,0},{0x60006160,0x0000,0,0,0,0},{0x60006170,0x0000,0,0,0,0},
									 {0x60006180,0x0000,0,0,0,0},{0x60006190,0x0000,0,0,0,0},{0x600061A0,0x0000,0,0,0,0},{0x600061B0,0x0000,0,0,0,0},
									 {0x600061C0,0x0000,0,0,0,0},{0x600061D0,0x0000,0,0,0,0},{0x600061E0,0x0000,0,0,0,0},{0x600061F0,0x4000,0,0,0,1}};

//массив дескрипторов принимаемых пакетов
_rx_descriptor	ARxDescriptor[32] = {{0x60002000,0x8000,0,0,0,0},{0x60002010,0x8000,0,0,0,0},{0x60002020,0x8000,0,0,0,0},{0x60002030,0x8000,0,0,0,0},
									 {0x60002040,0x8000,0,0,0,0},{0x60002050,0x8000,0,0,0,0},{0x60002060,0x8000,0,0,0,0},{0x60002070,0x8000,0,0,0,0},
									 {0x60002080,0x8000,0,0,0,0},{0x60002090,0x8000,0,0,0,0},{0x600020A0,0x8000,0,0,0,0},{0x600020B0,0x8000,0,0,0,0},
									 {0x600020C0,0x8000,0,0,0,0},{0x600020D0,0x8000,0,0,0,0},{0x600020E0,0x8000,0,0,0,0},{0x600020F0,0x8000,0,0,0,0},
									 {0x60002100,0x8000,0,0,0,0},{0x60002110,0x8000,0,0,0,0},{0x60002120,0x8000,0,0,0,0},{0x60002130,0x8000,0,0,0,0},
									 {0x60002140,0x8000,0,0,0,0},{0x60002150,0x8000,0,0,0,0},{0x60002160,0x8000,0,0,0,0},{0x60002170,0x8000,0,0,0,0},
									 {0x60002180,0x8000,0,0,0,0},{0x60002190,0x8000,0,0,0,0},{0x600021A0,0x8000,0,0,0,0},{0x600021B0,0x8000,0,0,0,0},
									 {0x600021C0,0x8000,0,0,0,0},{0x600021D0,0x8000,0,0,0,0},{0x600021E0,0x8000,0,0,0,0},{0x600021F0,0xC000,0,0,0,1}};

_tx_current_descriptor TxCurrentDesc;	//экземпляр структуры _tx_current_descriptor
_rx_current_descriptor RxCurrentDesc;	//экземпляр структуры _rx_current_descriptor
_ethernet_packet Packet;				//экземпляр структуры _ethernet_packet
unsigned short Temp, TypeOfProtocol;	//Temp - временная переменная, TypeOfProtocol - тип протокола пакета, вложенного в Eth2 пакет.
unsigned char My_IP[4], My_MAC[6];		//переменные, содржащие наш IP и MAC-адреса
unsigned char Receive_IP[4];			//IP-адрес принятого пакета
unsigned char ICMP_Packet[1500];  		//буфер для формирования ответного ICMP-пакета.

#if PRINTSTATUSON
_ethernet* MyEth;						//указатель на структуру _ethernet (введен для просмотр состояния регистров Ethernet-контроллера 5600ВГ1У)
#endif	//PRINTSTATUSON


//unsigned int *MyPtrTx, *MyPtrRx, *ptrTD, *ptrRD;
//unsigned int adr, len, i;
//unsigned int ArrayRead[1000];

int main()
{
        ClkCfg();		
        PortConfig();	
		ExtBusCfg();	

#if	PRINTSTATUSON
		MyEth = Ethernet;
#endif	//PRINTSTATUSON

        My_IP[0] =  0xC0;
        My_IP[1] =  0xA8;
        My_IP[2] =  0x01;
        My_IP[3] =  0x57;

        My_MAC[0] = 0x0A;
        My_MAC[1] = 0x1B;
        My_MAC[2] = 0x2C;
        My_MAC[3] = 0x3D;
        My_MAC[4] = 0x4E;
        My_MAC[5] = 0x5F;

		InitTxDescriptor();	
		InitRxDescriptor();

		EthCfg();
		PORTB->PORTx_SET=0x8000;

#if	PRINTSTATUSON
		Packet.CounterRxPacket = 0;
		Packet.CounterTxPacket = 0;
#endif	//PRINTSTATUSON

//модуль Ethernet сконфигурирован
        while(1)
        {
                if(Read_Rx_Descriptor(RxCurrentDesc.RxCurrentDescriptor) == 0) //проверка наличия принятого пакета
                {
                        PORTD->RXTX |= 1 << 11;

                        Packet.Length = Read_Packet_Length(RxCurrentDesc.RxCurrentDescriptor);
                        Packet.Address = Read_Packet_Start_Address(RxCurrentDesc.RxCurrentDescriptor);
                        Read_Packet(&Packet);				   //считали полученный пакет

						Ready_Rx_Descriptor(RxCurrentDesc.RxCurrentDescriptor);

#if	PRINTSTATUSON
						Packet.CounterRxPacket++;
#endif	//PRINTSTATUSON						

						Ethernet->RXBF_HEAD = (Ethernet->RXBF_TAIL-1)&0x07FF;

                        TypeOfProtocol = (Packet.Data[12]<<8)|Packet.Data[13];

                        switch(TypeOfProtocol) //0x0006 //слова в памяти разбиты по 2 байта! (считывать массив кратный 2 байтам!)
                        {
                                case 0x0806:    //receive ARP-packet
                                        Receive_IP[0] = Packet.Data[38];
                                        Receive_IP[1] = Packet.Data[39];
                                        Receive_IP[2] = Packet.Data[40];
                                        Receive_IP[3] = Packet.Data[41];

                                        if( (Receive_IP[0] == My_IP[0])&&(Receive_IP[1] == My_IP[1])&&(Receive_IP[2] == My_IP[2])&&(Receive_IP[3] == My_IP[3]))         //полное совпадение IP в пакете и нашего. Надо отвечать
                                        {
                                                        Packet.Remote_IP[0] = Packet.Data[28];
                                                        Packet.Remote_IP[1] = Packet.Data[29];
                                                        Packet.Remote_IP[2] = Packet.Data[30];
                                                        Packet.Remote_IP[3] = Packet.Data[31];

                                                        Packet.Remote_MAC[0] = Packet.Data[22];
                                                        Packet.Remote_MAC[1] = Packet.Data[23];
                                                        Packet.Remote_MAC[2] = Packet.Data[24];
                                                        Packet.Remote_MAC[3] = Packet.Data[25];
                                                        Packet.Remote_MAC[4] = Packet.Data[26];
                                                        Packet.Remote_MAC[5] = Packet.Data[27];

                                                        Answear_ARP(&Packet);
                                        }
                                        PORTD->RXTX &= 0xF7FF;
                                        break;

                                case 0x0800:    //receive IP-packet     //реализуем ICMP-протокол
                                        Receive_IP[0] = Packet.Data[30];
                                        Receive_IP[1] = Packet.Data[31];
                                        Receive_IP[2] = Packet.Data[32];
                                        Receive_IP[3] = Packet.Data[33];

                                        if((Receive_IP[0] == My_IP[0])&&(Receive_IP[1] == My_IP[1])&&(Receive_IP[2] == My_IP[2])&&(Receive_IP[3] == My_IP[3]))  //получили IP-пакет с нашим IP адресом
                                        {
                                                        Temp = CheckSum_IP(&Packet);
                                                        if(Temp == ((Packet.Data[24] << 8)&0xFF00|Packet.Data[25]))  //если контрольная сумма IP-протокола пакета и вычисленная совпадают, то работаем дальше, иначе откидываем пакет
                                                        {
                                                                Packet.Remote_IP[0] = Packet.Data[26];
                                                                Packet.Remote_IP[1] = Packet.Data[27];
                                                                Packet.Remote_IP[2] = Packet.Data[28];
                                                                Packet.Remote_IP[3] = Packet.Data[29];

                                                                Packet.Remote_MAC[0] = Packet.Data[6];
                                                                Packet.Remote_MAC[1] = Packet.Data[7];
                                                                Packet.Remote_MAC[2] = Packet.Data[8];
                                                                Packet.Remote_MAC[3] = Packet.Data[9];
                                                                Packet.Remote_MAC[4] = Packet.Data[10];
                                                                Packet.Remote_MAC[5] = Packet.Data[11];

                                                                //проверить следующий протокол (ICMP)
                                                                if(Packet.Data[23] == 0x01)     //далее следует ICMP-протокол
                                                                {																			
																		if(Packet.Data[34] == 0x08) //приняли echo request
                                                                        {
                                                                                Temp = CheckSum_ICMP(&Packet);
                                                                                if(Temp == ((Packet.Data[36] << 8)&0xFF00|Packet.Data[37]))	//проверка совпадения контрольной суммы ICMP-пакета и вычисленной
                                                                                {
                                                                                        Answear_ICMP(&Packet, ICMP_Packet);
                                                                                }
                                                                        }
                                                                }
                                                        }
                                        }
                                        PORTD->RXTX &= 0xF7FF;
                                        break;
                        }
                } //if(Read_Rx_Descriptor(RxCurrentDescriptor) == 0) //we receive Eth. packet
                PORTD->RXTX &= 0xF7FF;

				//переход к следующему дескриптору
				RxCurrentDesc.RxCurrentDescriptor++;
				RxCurrentDesc.Number++;
				if(RxCurrentDesc.Number == NUMRXDESCRIPTOR)
				{
					RxCurrentDesc.RxCurrentDescriptor = ARxDescriptor;
					RxCurrentDesc.Number = 0;	
				}
        }
}

//--------------------------------------------------------------------------------------
//Функция для вычисления контрольной суммы IP-пакета
//Параметр:	указатель на принятый Ethernet-пакет
//Возвращает контрольную сумму IP-пакета
//--------------------------------------------------------------------------------------
unsigned short CheckSum_IP(_ethernet_packet* Dt)
{
        unsigned long Temp, Check = 0;
        for(Temp = 0; Temp < 20; Temp += 2)
        {
                if(Temp == 10) continue;
                else Check += ((Dt->Data[Temp + 14] << 8)&0xFF00)|Dt->Data[Temp + 15];
        }
        Check = (Check >> 16) + (Check & 0xFFFF);
        return (unsigned short)(~Check);
}
//--------------------------------------------------------------------------------------
//Функция для вычисления контрольной суммы ICMP-пакета
//Параметр:	указатель на принятый Ethernet-пакет
//Возвращает контрольную сумму ICMP-пакета
//--------------------------------------------------------------------------------------
unsigned short CheckSum_ICMP(_ethernet_packet* Dt)
{
        unsigned long Temp, Check = 0;
        for(Temp = 0; Temp < Dt->Length - 38; Temp += 2)      //реализовано для пакета ICMP объёмом до 1450 байт
        {                                                     //Dt->Length - 38,т.к. 34 байта - это Eth2 и IP заголовки, 4 байта - CRС32 Eth2 пакета
                if(Temp == 2) continue;
                else Check += ((Dt->Data[Temp + 34] << 8)&0xFF00)|Dt->Data[Temp + 35];
        }
        Check = (Check >> 16) + (Check & 0xFFFF);
        return (unsigned short)(~Check);
}
//--------------------------------------------------------------------------------------
//Функция для считывания пакета
//Параметр:	указатель на принятый Ethernet-пакет
//Возвращает 0
//--------------------------------------------------------------------------------------
int Read_Packet(_ethernet_packet* Dt)
{
        unsigned short Temp,Val;
		unsigned int* MyPointer;
		MyPointer = (unsigned int*)((unsigned int)RxBuffer + (unsigned int)(Dt->Address<<2));
		for(Temp=0;Temp<Dt->Length;Temp+=2)
		{
			Val = *MyPointer++;
			Dt->Data[Temp] = (unsigned char)Val;
			Dt->Data[Temp+1] = (unsigned char)(Val>>8);
			if( ((int)MyPointer & 0x00002000) == 0x00002000) MyPointer = RxBuffer;
		}
        if((Dt->Length & 0x0001) == 1)  //если пакет содержит нечетное кол-во байт, то необходимо занулить предпоследний
                                        //считанный байт в буфере, так как он влияет на контрольную сумму ICMP-пакета.
        {
                Dt->Data[Dt->Length-4] = 0;
        }
		
        return 0;
}

//--------------------------------------------------------------------------------------
//Функция для формирования ответа на ARP-запрос
//Параметр:	указатель на принятый Ethernet-пакет
//Возвращает 0
//--------------------------------------------------------------------------------------
int Answear_ARP(_ethernet_packet* Dt)
{
        unsigned char Send[42];
        unsigned short Temp;
		unsigned int* MyPointer;
	
        while(Read_Tx_Descriptor(TxCurrentDesc.TxCurrentDescriptor) != 0)
		{
			TxCurrentDesc.TxCurrentDescriptor++;
			TxCurrentDesc.Number++;
			if(TxCurrentDesc.Number == NUMTXDESCRIPTOR)
			{
				TxCurrentDesc.Number = 0;
				TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
			}	
		}
		
        //первые 6 байт - удаленный MAC - адрес
        Send[0] = Dt->Remote_MAC[0];
        Send[1] = Dt->Remote_MAC[1];
        Send[2] = Dt->Remote_MAC[2];
        Send[3] = Dt->Remote_MAC[3];
        Send[4] = Dt->Remote_MAC[4];
        Send[5] = Dt->Remote_MAC[5];

        //далее 6 байт - мой MAC-адрес
        Send[6] = My_MAC[0];
        Send[7] = My_MAC[1];
        Send[8] = My_MAC[2];
        Send[9] = My_MAC[3];
        Send[10] = My_MAC[4];
        Send[11] = My_MAC[5];

        //далее заполняем всё так же как в полученном пакете до 19 байта (включительно)
        for(Temp = 12; Temp < 20; Temp++)
        {
                Send[Temp] = Dt->Data[Temp];
        }

        //20 и 21 байты - Opcode: для ответа должен быть равен 2
        Send[21] = 0x02;
        Send[20] = 0x00;

        //с 22 по 27 (включительно) идет мой MAC

        Send[22] = My_MAC[0];
        Send[23] = My_MAC[1];
        Send[24] = My_MAC[2];
        Send[25] = My_MAC[3];
        Send[26] = My_MAC[4];
        Send[27] = My_MAC[5];

        //с 28 по 31 (включительно) идет мой IP

        Send[28] = My_IP[0];
        Send[29] = My_IP[1];
        Send[30] = My_IP[2];
        Send[31] = My_IP[3];

        //с 32 по 37 (включительно) идет удаленный MAC

        Send[32] = Dt->Remote_MAC[0];
        Send[33] = Dt->Remote_MAC[1];
        Send[34] = Dt->Remote_MAC[2];
        Send[35] = Dt->Remote_MAC[3];
        Send[36] = Dt->Remote_MAC[4];
        Send[37] = Dt->Remote_MAC[5];

        //с 38 по 41 (включительно) идет удаленный IP

        Send[38] = Dt->Remote_IP[0];
        Send[39] = Dt->Remote_IP[1];
        Send[40] = Dt->Remote_IP[2];
        Send[41] = Dt->Remote_IP[3];
		
		MyPointer = (unsigned int*)TxCurrentDesc.FirstEmptyWord;

		for(Temp=0;Temp<42;Temp+=2)
		{
			*MyPointer++ = Send[Temp]|(Send[Temp+1]<<8);
			if((unsigned int)MyPointer > 0x60005FFC) MyPointer = (unsigned int*)0x60004000;
		}
        
        Write_Tx_Descriptor(0x002A,&TxCurrentDesc);     //42 bytes

 		TxCurrentDesc.TxCurrentDescriptor++;
		TxCurrentDesc.Number++;
		if(TxCurrentDesc.Number == NUMTXDESCRIPTOR)
		{
			TxCurrentDesc.Number = 0;
			TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
		}

#if PRINTSTATUSON
		Packet.CounterTxPacket++;
#endif	//PRINTSTATUSON

		return 0;
}
//--------------------------------------------------------------------------------------
//Функция для формирования ответа на ICMP-запрос
//Параметр:	указатель на принятый Ethernet-пакет
//Возвращает 0
//--------------------------------------------------------------------------------------
int Answear_ICMP(_ethernet_packet* Dt , unsigned char* ICMP_Packet)
{
        unsigned short Temp;
		unsigned int* MyPointer;

        while(Read_Tx_Descriptor(TxCurrentDesc.TxCurrentDescriptor) != 0)
		{
			TxCurrentDesc.TxCurrentDescriptor++;
			TxCurrentDesc.Number++;
			if(TxCurrentDesc.Number == NUMTXDESCRIPTOR)
			{
				TxCurrentDesc.Number = 0;
				TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
			}
		}
		
        //Remote MAC-Address
        ICMP_Packet[0] = Dt->Remote_MAC[0];
        ICMP_Packet[1] = Dt->Remote_MAC[1];
        ICMP_Packet[2] = Dt->Remote_MAC[2];
        ICMP_Packet[3] = Dt->Remote_MAC[3];
        ICMP_Packet[4] = Dt->Remote_MAC[4];
        ICMP_Packet[5] = Dt->Remote_MAC[5];

        //My MAC-Address
        ICMP_Packet[6] = My_MAC[0];
        ICMP_Packet[7] = My_MAC[1];
        ICMP_Packet[8] = My_MAC[2];
        ICMP_Packet[9] = My_MAC[3];
        ICMP_Packet[10] = My_MAC[4];
        ICMP_Packet[11] = My_MAC[5];

        //IP-protocol
        ICMP_Packet[12] = 0x08;
        ICMP_Packet[13] = 0x00;
//Закнчили формировать Eth2-пакет

//Формируем IP-пакет
        //Field of IP-protocol
        for(Temp = 14; Temp < 24; Temp++)
        {
                ICMP_Packet[Temp] = Dt->Data[Temp];
        }
        ICMP_Packet[26] = Dt->Data[30];
        ICMP_Packet[27] = Dt->Data[31];
        ICMP_Packet[28] = Dt->Data[32];
        ICMP_Packet[29] = Dt->Data[33];
        //Remote IP
        ICMP_Packet[30] = Dt->Data[26];
        ICMP_Packet[31] = Dt->Data[27];
        ICMP_Packet[32] = Dt->Data[28];
        ICMP_Packet[33] = Dt->Data[29];

        Temp = CheckSum_IP(Dt);

        //IP CheckSum
        ICMP_Packet[24] = (unsigned char)(Temp >> 8);
        ICMP_Packet[25] = (unsigned char)Temp;

//Закнчили формировать IP-пакет
//Формируем ICMP-пакет
        ICMP_Packet[34] = 0x00; //Echo reply
        ICMP_Packet[35] = 0x00;

        Dt->Data[34] = 0x00;
        Dt->Data[35] = 0x00;

        Temp = CheckSum_ICMP(Dt);
        ICMP_Packet[36] = (unsigned char)(Temp >> 8);
        ICMP_Packet[37] = (unsigned char)Temp;

        for(Temp = 38; Temp < Dt->Length - 4; Temp++)
        {
                ICMP_Packet[Temp] = Dt->Data[Temp];
        }

		MyPointer = (unsigned int*)TxCurrentDesc.FirstEmptyWord;

        if((Dt->Length & 0x0001) == 1)
        {
                ICMP_Packet[Dt->Length - 4] = Dt->Data[Dt->Length - 4];
                for(Temp=0;Temp<Dt->Length - 3;Temp+=2)
				{
					*MyPointer++ = ICMP_Packet[Temp]|(ICMP_Packet[Temp+1]<<8);
					if((unsigned int)MyPointer > 0x60005FFC) MyPointer = (unsigned int*)0x60004000;
				}
        }
        else
        {
                for(Temp=0;Temp<Dt->Length - 4;Temp+=2)
				{
					*MyPointer++ = ICMP_Packet[Temp]|(ICMP_Packet[Temp+1]<<8);
					if((unsigned int)MyPointer > 0x60005FFC) MyPointer = (unsigned int*)0x60004000;
				}
        }
//Закончили формировать ICMP-пакет

        Write_Tx_Descriptor(Dt->Length-4,&TxCurrentDesc);     //74 bytes

		TxCurrentDesc.TxCurrentDescriptor++;
		TxCurrentDesc.Number++;
		if(TxCurrentDesc.Number == NUMTXDESCRIPTOR)
		{
			TxCurrentDesc.Number = 0;
			TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
		}

#if PRINTSTATUSON
		Packet.CounterTxPacket++;
#endif	//PRINTSTATUSON

        return 0;
}
//--------------------------------------------------------------------------------------
//Функция для инициализации дескрипторов передаваемых пакетов
//Параметр:	нет
//Возвращаемых значений нет
//--------------------------------------------------------------------------------------
void InitTxDescriptor()
{
	unsigned int* TDescPointer;

	TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
	TxCurrentDesc.FirstEmptyWord = 0x60004000;

	for(Temp=0;Temp<NUMTXDESCRIPTOR;Temp++)
	{
		TDescPointer = (unsigned int*)(TxCurrentDesc.TxCurrentDescriptor->StartAddress);
		*TDescPointer = TxCurrentDesc.TxCurrentDescriptor->Status;
		TxCurrentDesc.TxCurrentDescriptor++;
	}

	TxCurrentDesc.TxCurrentDescriptor--;
	TxCurrentDesc.TxCurrentDescriptor->LastDesc = 1;	//установка признака последнего дескриптора
	TDescPointer = (unsigned int*)(TxCurrentDesc.TxCurrentDescriptor->StartAddress);
	*TDescPointer = 0x4000;								//последний обрабатываемый дескриптор

	TxCurrentDesc.Number = 0;
	TxCurrentDesc.TxCurrentDescriptor = ATxDescriptor;
}
//--------------------------------------------------------------------------------------
//Функция для инициализации дескрипторов принимаемых пакетов
//Параметр:	нет
//Возвращаемых значений нет
//--------------------------------------------------------------------------------------
void InitRxDescriptor()
{
	unsigned int* RDescPointer;

	RxCurrentDesc.RxCurrentDescriptor = ARxDescriptor;

	for(Temp=0;Temp<NUMRXDESCRIPTOR;Temp++)
	{
		RDescPointer = (unsigned int*)(RxCurrentDesc.RxCurrentDescriptor->StartAddress);
		*RDescPointer = RxCurrentDesc.RxCurrentDescriptor->Status;
		RxCurrentDesc.RxCurrentDescriptor++;
	}

	RxCurrentDesc.RxCurrentDescriptor--;
	RxCurrentDesc.RxCurrentDescriptor->LastDesc = 1;	//установка признака последнего дескриптора
	RDescPointer = (unsigned int*)(RxCurrentDesc.RxCurrentDescriptor->StartAddress);
	*RDescPointer = 0xC000;								//последний обрабатываемый дескриптор

	RxCurrentDesc.Number = 0;
	RxCurrentDesc.RxCurrentDescriptor = ARxDescriptor;
}



