/*#######################################################################################
AVR Small Webserver 

Copyright (C) 2004 Ulrich Radig

#######################################################################################*/

#include "main.h"
#include "rtl8019.h"

//Routinen zum ansteuern der Netzwerkkarte 

//############################################################################
// Schreibt ein Byte in ein angegebenes Register der Netzwerkkarte
void WriteRTL (unsigned char rtl_addr,unsigned char rtl_data)
//############################################################################
{
	//Der Datenport wird auf output gesetzt vom µC zum NIC schreiben
	DATA_CTRL_RLT = OUTPUT;
	//write Adress to Port
	ADDR_PORT_RLT &= ~0x1F; //by Arne
	ADDR_PORT_RLT |= rtl_addr;
	//write Data to Port
	DATA_PORT_RLT_WRITE = rtl_data;
	//set write Pin to Low
	RTL_WR_OFF();
	//wait a short time
        nop(); //gib mal ein bißchen GAS Ulrich ;)
        nop();
	//by Arne:
        nop();
        nop();
        nop();

	//set write Pin to High
	RTL_WR_ON();	
	//write to RTL complete
}


//############################################################################
// Auslesen eines Byte von einen angegebenes Register der Netzwerkkarte
unsigned char ReadRTL (unsigned char rtl_addr)
//############################################################################
{
	unsigned char rtl_data;
	//Der Datenport wir auf input gesetzt vom NIC zum µC lesen
	DATA_CTRL_RLT = INPUT;
	//write Adress to Port
	ADDR_PORT_RLT &= ~0x1F; //by Arne
	ADDR_PORT_RLT |= rtl_addr;
	//set read Pin to Low
	RTL_RD_OFF();
	//wait a short time	
        nop();
        nop();
	//by Arne:
        nop();
        nop();
        nop();

	//read from port rtldata
	rtl_data = DATA_PORT_RLT_READ;	
	//set Read Pin to High
	RTL_RD_ON();	
	//read from RTL complete
	return (rtl_data);
}

//############################################################################
//Hier wird die Netzwerkkarte Grundinizialisiert
void Init_Realtek_Network_Card (void)
//############################################################################
{

	/* 
	#if defined (__AVR_ATmega128__)
		//Set Addr Port Direction = Output
		DATA_ADDR_RLT = OUTPUT;
	#endif

	#if defined (__AVR_ATmega32__)
		//Set Addr Port Direction = Output
		DATA_ADDR_RLT = OUTPUT;
	#endif
	*/
	
	//by Arne:
	ADDR_CTRL_RLT = 0x1F; //DDRC, PC5 = input
	CTRL_CTRL_RLT &= ~(1<<IRQ_PIN);
	CTRL_CTRL_RLT |= (1<<READ_PIN) | (1<<WRITE_PIN) | (1<<RESET_PIN) | 0x18; //DDRD; PD3, PD4 = outputs

	//Set all Addrport High
/*    #ifndef ISP_CTRL
	ADDR_PORT_RLT = OUTPUT;
	#else
	// für ISP-CTRL  
	ADDR_PORT_RLT = ADDR_OUTPUT;                  // nur die 5 Adressleitungen
	CTRL_LINES_DIR |=  (1<<READ_PIN);
    CTRL_LINES_DIR |= (1<<RESET_PIN);
	CTRL_LINES_DIR |= (1<<WRITE_PIN);
	#endif	
*/
	//by Arne:
	ADDR_PORT_RLT |= 0x1F | 0x20; // Adressleitungen auf HIGH (and enable Pullup for Input PC5)
	CTRL_PORT_RLT |=  (1<<IRQ_PIN) | (1<<READ_PIN) | (1<<WRITE_PIN); //IRQ = Pullup, Read/Write = invertiert
	RTL_RESET_ON();
	
	//set Data Port Direction = Input
	DATA_CTRL_RLT = INPUT;

//	printf ("\n\n\n\nInit Network Card: ");
	//by Arne:
	unsigned long i = 0;
	//while (i < 60000 * 5) i++; by arne: this gets compiled away!
	for (i = 0; i < 5000; i++) nop();

	//Set Reset Pin Low
	RTL_RESET_OFF();		

	//added by holgi
	//meine Karten laufen nur wenn man hier noch ca. 100ms wartet
	//wait a long time
//	i = 0;
	for (i = 0; i < 5000; i++) nop();
//	while (i < 60000 * 5) i++;
	//end added by holgi
	
	ReadRTL (RSTPORT);
	WriteRTL (RSTPORT , 0xFF);
	
	//wait a short time
//	int a = 0;
//	while (a < 1000)
//	{
//	a++;
//	}
	for (i = 0; i < 5000; i++) nop();
	
//	printf (".");			//Point 1
	WriteRTL (CR , (1<<STP| 1<<RD2));

	//wait a short time
//	a = 0;
//	while (a < 1000)
//	{
//	a++;
//	}
	for (i = 0; i < 5000; i++) nop();
	
//	printf (".");			//Point 2
	WriteRTL (DCR , DCRVAL);
	WriteRTL (RBCR0 , 0x00);
	WriteRTL (RBCR1 , 0x00);
	WriteRTL (RCR , 0x04);
	WriteRTL (TPSR , RXSTART);
	WriteRTL (TCR , 0x02);
	WriteRTL (PSTART , RXSTART);
	WriteRTL (BNRY , RXSTART);
	WriteRTL (PSTOP , RXSTOP);
	WriteRTL (CR ,(1<<STP| 1<<RD2|1<<PS0));

	//wait a schort time	
//	for (int a = 0; a < 1000; a++)
//		{
//		}
	for (i = 0; i < 5000; i++) nop();

//	printf (".");			//Point 3
	WriteRTL (CURR , RXSTART);
	
	for(int a = 0; a<=5; a++)
		{
		WriteRTL ((PAR0 + a) , mymac[a]);
//		printf (".");		//Point 4,5,6,7,8,9
		}

	WriteRTL (CR , (1<<STP| 1<<RD2));
	WriteRTL (DCR , DCRVAL);
	WriteRTL (CR , (1<<STA| 1<<RD2));
	WriteRTL (ISR ,(1<<PRX|1<<PTX|1<<RXE|1<<TXE|1<<OVW|1<<CNT|1<<RDC|1<<RST));
	WriteRTL (IMR , IMRVAL);
	WriteRTL (TCR , TCRVAL);
//	printf (" Init Ready! \n");
	
	//startet die Network Card
	WriteRTL (CR ,(1<<STA| 1<<RD2));
    DATA_PORT_RLT_WRITE = 255; //Schreibt eine 255 auf den BUS
}


//############################################################################
void Write_Ethernet_Frame (char *buffer,unsigned int bufferlen)
//############################################################################
{
 unsigned int a;

	//Buffer auf eine min. länge von 60Bytes überprüfen
	//wenn kleiner dann auffüllen
	if (bufferlen < 0x40)
		{
		for (a = (bufferlen-4);a <= 0x44;a++)
			{
			buffer[a] = 0x20;
			}
		bufferlen = 0x40;
		}
		
	WriteRTL (CR,(1<<STA| 1<<RD2));
	WriteRTL (TPSR,TXSTART);
	WriteRTL (RSAR0,0x00);
	WriteRTL (RSAR1,0x40);
	WriteRTL (ISR,(1<<PRX|1<<PTX|1<<RXE|1<<TXE|1<<OVW|1<<CNT|1<<RDC|1<<RST));
	WriteRTL (RBCR0,(bufferlen & 0x00ff) - 4);
	WriteRTL (RBCR1,(bufferlen & 0xff00) >>8);
	WriteRTL (CR,(1<<STA| 1<<RD1));

//07.10.2004 Holger Klabunde
//WriteRTL(x) in der Schleife quasi durch den INHALT von WriteRTL(x) ersetzt
// 
//DATA_CTRL_RLT = OUTPUT; und ADDR_PORT_RLT = (96 + RDMAPORT);
//aus der Schleife rausgenommen und darüber gesetzt. 
//Beide Befehle wurden unnötigerweise mehrfach ausgeführt.
//Da man in der Schleife jetzt auch keine Funktion WriteRTL(x) mit Parameterübergabe
//mehr aufruft wird eine Menge Rechenzeit gespart.

	//Der Datenport wir auf output gesetzt vom µC zum NIC schreiben
	DATA_CTRL_RLT = OUTPUT;
	//write Adress to Port
	ADDR_PORT_RLT &= ~0x1F; //by Arne
	ADDR_PORT_RLT |= RDMAPORT;

	for (a = 0; a < (bufferlen - 4);a++)
	{
		//write Data to Port
		DATA_PORT_RLT_WRITE = buffer[a];
		//set write Pin to Low
		RTL_WR_OFF();
		//wait a short time
        	nop(); //gib mal ein bißchen GAS Ulrich ;) Holgi
        	nop();
		//by Arne:
        	nop();
        	nop();
        	nop();

		//set write Pin to High
		RTL_WR_ON();	
		//write to RTL complete
	}
	
	//loop_until_bit_is_set(ReadRTL(isr),rdc);
	while ((ReadRTL(ISR)&(1<<RDC)) == 0) {}

	WriteRTL (TBCR0,(bufferlen & 0x00ff) - 4);
	WriteRTL (TBCR1,(bufferlen & 0xff00) >>8);
	WriteRTL (CR,(1<<TXP| 1<<RD2));
}

//############################################################################
void Read_Ethernet_Frame (char *buffer,unsigned int *bufferlen)
//############################################################################
{
	unsigned int tmp1,tmp2;
	unsigned int a;
	unsigned char by = 0;

	WriteRTL(CR ,(1<<STA| 1<<RD0| 1<<RD1));	
	ReadRTL(RDMAPORT);
	ReadRTL(RDMAPORT);
	tmp1 = ReadRTL(RDMAPORT);
	*bufferlen = (ReadRTL(RDMAPORT)<<8)+tmp1;
	  
//07.10.2004 Holger Klabunde
//ReadRTL(x) in der Schleife quasi durch den INHALT von ReadRTL(x) ersetzt
// 
//DATA_CTRL_RLT = INTPUT; und ADDR_PORT_RLT = (96 + RDMAPORT);
//aus der Schleife rausgenommen und darüber gesetzt. 
//Beide Befehle wurden unnötigerweise mehrfach ausgeführt.
//Da man in der Schleife jetzt auch keine Funktion ReadRTL(x) mit Parameterübergabe
//mehr aufruft wird eine Menge Rechenzeit gespart.

	//Der Datenport wir auf input gesetzt vom NIC zum µC lesen
	DATA_CTRL_RLT = INPUT;
	//write Adress to Port
	ADDR_PORT_RLT &= ~0x1F; //by Arne
	ADDR_PORT_RLT |= RDMAPORT;

//14.10.2004 Holger Klabunde
//RAM Zugriffe über die Größe des Buffers hinaus verhindern
//Die Abfrage dazu stand vorher in der Byteleseschleife.
//Das dauerte aber viel zu lange.
//Jetzt sind es zwei Schleifen. Bringt nochmal ca. 10%.

        tmp1=*bufferlen; //Annehmen *bufferlen passt in den Buffer
        tmp2=0;          //Rest ist erstmal 0
        
        if(*bufferlen>(MTU_SIZE-1)) //Mehr Daten vorhanden als in den Buffer passen
         {
          tmp1=(MTU_SIZE-1);    //Daten nur bis MTU_SIZE-1 in den Buffer übernehmen
          tmp2=*bufferlen-tmp1; //den Rest abholen, aber ignorieren !
         } 

         //Daten in den Buffer übernehmen solange sie reinpassen
         for(a=0; a<tmp1; a++)
          {
	   //set read Pin to Low
	   RTL_RD_OFF();
	   //wait a short time	
           nop();
           nop();
	   //by Arne:
           nop();
           nop();
           nop();
           //read from port rtldata
	   buffer[a] = DATA_PORT_RLT_READ;	
	   //set Read Pin to High
	   RTL_RD_ON();	
	   //read from RTL complete
          }

         //Daten abholen die NICHT mehr in den Buffer passen
         //Anmerkung holgi: Kommt das überhaupt einmal vor ?
         for(a=0; a<tmp2; a++)
          {
	   //set read Pin to Low
	   RTL_RD_OFF();
	   //wait a short time	
           nop();
           nop();
	   //by Arne:
           nop();
           nop();
           nop();
           //read from port rtldata
	   by = DATA_PORT_RLT_READ;	
	   //set Read Pin to High
	   RTL_RD_ON();	
	   //read from RTL complete
          }
	buffer[tmp1 + 1] = 0;	

	by = by & RDC;
	
	if ( by != 64 )
		{
		ReadRTL(ISR);
		}
}
