📄 nic.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 + -