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

📄 nic.c

📁 Pic Nic 16f877/18f452控制 rtl8019as 原代码
💻 C
字号:
/*
 * nic.c
 *
 * NIC Specific functions for interfacing and exchanginda data with the nic
 *
 */

//rtl8019 cannot send packets smaller than this
#define  ETHERNET_MIN_PACKET_LENGTH  60

//Function prototypes
void  init_nic(void);
void  outport(int address, int data);
void  outportw(int address, long int data);
int inport(int address);
void  remote_dma_setup(short w_r, int address);
void  read_phy_addr(void);
int8 poll_nic(void);
void  calc_chksum(long int data);
void  tcp_listen(void);
void  tcp_syn_rcvd(void);
void  tcp_estab(void);
int1 overrun(void);

//Poll NIC checking if a new packet arrived
int8 poll_nic(void) {

	int8 i, bnry, header[4];
	int8 len;


	if(overrun()) {  //check rx overrun

		outport(CR,0x62);
		i = inport(CURR); //get current page pointer
		outport(CR,0x22);
		bnry = inport(BNDRY);   //get last page pointer we have read

		//if pointers are same there is no new packet
		if (bnry == i) {
			return(0);
		}

		outport(ISR, 1);  //clear rx interrupt flag

		if( (bnry >= XMT_BUF_START)
		 || (bnry < RCV_BUF_START)
		 || (i >= XMT_BUF_START)
		 || (i < RCV_BUF_START)) {   //make sure pointer is valid

			outport(BNDRY, RCV_BUF_START);
			outport(CR, 0x62);
			outport(CURR, RCV_BUF_START);
			outport(CR, 0x22);
			return(0);
		}


		remote_dma_setup(READ, bnry);
		for(i=0; i<4; i++) {
			header[i] = inport(NIC_DATA);   //read 4byte header
		}

		len = header[2];
		next_page = header[1];
		current_rx_address = bnry + 4;
		return (len-4);
	}
	else {
		return 0;
   	}

}

//Get Data from a packet from the NIC
void getNicData(int8 * buffer, int len) {

   int i;

   //Remote_dma_setup(READ, current_rx_address);
   for(i=0;i<len;i++)
    {
      *(buffer+i) = inport(NIC_DATA);
   }
}

//Stops RX Operation and prepares nic for next operations
void fin_rx(void) {

	unsigned char i;

	outport(CR, 0x22);   //end dma operation

	// Wait until dma is finished
	for(i = 0; i <= 20; i++) {
		if (bit_test(inport(ISR),6)) {
			break;
		}
	}

	outport(ISR, 0x40);
	outport(BNDRY, next_page);   //set to start of next packet
}


//Configure PIC I/O pins directions and initial states
void init_pic(void) {

  set_tris_a(0b00000000);		//Port A is being used for output
  set_tris_b(0b00000000);	//Address Port
  set_tris_c(0b10100111);
  set_tris_d(0xFF);		// Data port
  set_tris_e(0b00000000);   	// Watch TRISE as it controls some Port D functions.

  output_low(RESET);		// Pull Reset Low to complete reset cycle
  output_high(IOW);		// Set IOW and IOR high (they are active low)
  output_high(IOR);

  ADDR = 0;			// Set a default address of 0
}

//Initialize and configure NIC
void init_nic(void) {

	int i;

	//Reset NIC
	outport(CR, 0x21);			// Page 0, Abort DMA, Stop NIC
	delay_ms(25);				// Wait for it to stop
	outport(NIC_RESET, 0xFF);		// Reset the NIC 0x18
	delay_ms(25);				// Wait for it to reset

	outport(DCR, 0x48);			// byte DMA, Byte order 8086 (Check if we can change from 8086 to other arch and give more work to nic and less to pic)
	// outport(DCR, 0x58);			// Dual 16-bit DMA mode, Normal Operation

	// Send CMD not executed, FIFO theshold 8 bytes
	outport(RBCR0, 0x00);			// Clear remote byte count registers
	outport(RBCR1, 0x00);
	outport(RCR, 0x0C);			// Monitor off, Promiscuous off

	// outport(RCR, 0x04);			// Accept Multicast, Accept Broadcast

	// Reject Runts, Reject Error
	outport(TCR, 0x02);			// Internal Loop Back
	outport(BNDRY,  RCV_BUF_START);		// Start of Buffer RAM
	outport(PSTART, RCV_BUF_START);		// Start of Buffer RAM
	outport(PSTOP,  XMT_BUF_START);		// 8-bit mode so we need room for transmit buffers
	outport(CURR, RCV_BUF_START);

	//Interrupts config
	outport(ISR, 0xFF);   			// Clear Interrupt Status Register
	outport(IMR, 0x00);   			// Setup Interrupt Mask Register (No Interrupts)
	//outport(IMR, 0x11);

	outport(CR, 0x61);			// Page 1

	//Sets MAC Address
   //Comentado: Versao EDTP
	outport(PAR0, physical_address[0]);	// Physical_Address is not initialized on the
	outport(PAR1, physical_address[1]);	// first pass.  We need to read it from the
	outport(PAR2, physical_address[2]);	// EPROM and set it later
	outport(PAR3, physical_address[3]);
	outport(PAR4, physical_address[4]);
	outport(PAR5, physical_address[5]);


	for (i=0; i<8; i++) {
		outport(MAR0+i, 0xFF);
	}

	outport(CR, 0x22);			// Put the NIC in Start mode
}


void set_phy_addr(void) {

  physical_address[0] = 0x00;
  physical_address[1] = 0x01;
  physical_address[2] = 0xBE;
  physical_address[3] = 0xC0;
  physical_address[4] = 0x10;
  physical_address[5] = 0x06;
}



//Check if any overrun is happening
int1 overrun(void) {

//domingo, 11 de setembro de 2005 - descobri que eh o overrun que trava o pic de vez em quanto
//vou tentar comentar e ver o que acontece sem ele


	_isr = inport(0X07);			//Read nic's interrupt status register

	if (bit_test(_isr, 0X04)) {
		printf("OVERRUN!\n\r");

      //Teste, reiniciar a placa de rede!
      delay_ms(500);
      delay_ms(500);
      delay_ms(500);
      init_nic();
      delay_ms(300);
      set_phy_addr();
      init_nic();
      delay_ms(250);
      outport(TCR, 0x00);
      html_socket = LISTEN;
		printf("Reset nic\n\r");

     lcd_pos_xy(16,1);
     lcd_escreve('O');


/*
		outport(CR, 0x21);
		delay_ms(2);
		outport(RBCR0, 0x00);		//clear byte count registers
		outport(RBCR1, 0x00);
		outport(TCR, 0x02);		//set to internal loopback
		outport(CR, 0x22);		//set to remote write
		outport(BNDRY, RCV_BUF_START);	//last receive buffer
		outport(CR, 0x62);		//set page to 1
		outport(CURR, RCV_BUF_START);	//points to first page address of the first rx buffer page to be used for packet reception
		outport(CR, 0x22);		//set to page 0
		outport(ISR, 0x10);		//overflow (OVW) (ISR bits are cleared by setting to 1)
		outport(TCR, 0X00); 		//transmit control register
		outport(ISR, 0xFF);
*/
		return 0;
	}

	return 1;
}

//Read NIC's MAC Address and write to physical_address
//Comentado na versao EDTP
/*
void read_phy_addr(void) {

  int ignore;

  remote_dma_setup(READ, 0x00);

  //TODO: Transform this in a loop
  physical_address[0] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
  physical_address[1] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
  physical_address[2] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
  physical_address[3] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
  physical_address[4] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
  physical_address[5] = inport(NIC_DATA);
  ignore = inport(NIC_DATA);
}
*/




//Setup NIC for RDMA Operation - This gives PIC Remote Direct access to nic's Memory
void remote_dma_setup(short w_r, int address) {

	outport(CR,0x22);	       //start, abort dma

	while (inport(CR) & 0x04) {}   //Busy wait: wait for last packet to finish

	//Set dma read count
	outport(RBCR0, 0xFF);
	outport(RBCR1, 0xFF);
	outport(RSAR0, 0x00);
	outport(RSAR1,  address);

	//Configure RDMA for read or write acording to params
	if(w_r)
		outport(CR, 0x12);
	else
		outport(CR, 0x0A);

}

//Write 'data' to the next NIC free buffer
void outdata(int data) {

  ADDR = 0x10;

  set_tris_d(0x00);

  DATA = data;
  output_low(IOW);
  output_high(IOW);

  set_tris_d(0xff);
}

//Read and return the value stored on the nic's register at address
int inport(int address) {

  int data;

  ADDR = address;     // Output the correct register address

  output_low(IOR);    // Activate the I/O read request
  data = DATA;        // Input data from the bus
  output_high(IOR);   // Deactivate the I/O read request

  ADDR =0;

  //For more debuggind information: prints what is coming from the nic
#ifdef DEBUG_IO
  printf("Read %X at %X\n\r", data, address);
#endif

  return data;
}

//Output one byte of 'data' to the specified address
void outport(int address, int data) {

  ADDR = address;     // Put the register address on the address pins

  set_tris_d(0x00);   // Switch the data pins to output

  output_low(IOW);    // Activate the I/O write request
  DATA = data;        // Put the data on the bus
  output_high(IOW);   // Deactivate the I/O write request

  set_tris_d(0xFF);   // Reset data port to input

  ADDR =0;

   #ifdef DEBUG_IO
  //For more debuggind information: prints what is going to the nic
  printf("Sent %X to %X\n\r", data, address);
  #endif
}

//Puts data into the tx buffer to be sent as a packet.  This routine puts
// data into the tx buffer, it does not send the packet yet.  You can
// incrementally call this routine to incrementally add data to the buffer
// (for example, call it 25 times with 20 bytes each to add 500 bytes off
// data to buffer instead of having to put 500 bytes of data to the buffer
// at once).
// nic_begin_packet_tx() MUST be called first to configure the rtl8019
// to receive data for this packet.
void writeNicTxBuffer(int8 *buffer, int16 len) {

   int16 i;

   for(i=0; i<len; i++) {
	   outport(NIC_DATA, buffer[i]);
   }
}

//Issue a command to the NIC to send the data in its buffer
//len: tells the function how many bytes we want to send
void sendPacket(long int len) {
  outport(CR, 0x22);
  outport(TBCR0, len );
  outport(TBCR1, len >> 8);
  outport(TPSR, XMT_BUF_START);
  outport(CR, 0x26);

  #ifdef DEBUG
   printf("Sent\n\r");
  #endif
}

//Output one word of 'data' to the specified 'address' of NIC
void outportw(int address, int16 data) {

  int16 prev_chksum;		// Declare temporary storage for checksum

  prev_chksum = chksum;		// Keep a copy of the current checksum
  ADDR = address;   		// Put the register address we want to access on the bus

  set_tris_d(0x00);   		// Switch the data pins to output

  output_low(IOW);    		// Activate the I/O write request

  DATA = data>>8;     		// Put the High byte of the data word on the bus
  output_high(IOW);   		// Deactivate the I/O write request
  output_low(IOW);    		// Activate the I/O write request
  DATA = data;     	        // Put the Low byte of the data word on the bus
  output_high(IOW);   		// Deactivate the I/O write request

  set_tris_d(0xFF);  	        // Reset the data port to input

  chksum += data;               // Add the data word to the checksum
  if( chksum < prev_chksum )    // Check if a carry was generated
 	 chksum++; 		// Do the ones compliment if requred
}

⌨️ 快捷键说明

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