📄 driver.c
字号:
return_value = NET_ERROR_DMAERR;
}
// wait for DMA to complete.
i = 0;
while(1)
{
tempc = inportb(ISRADD);
if ( tempc & 0x40 )
{
MacState.RemoteDMACompleteTimes++;
break;
}
wait(1);
if ( i++ > NET_TMO_DMA )
break;
}
if ( i > NET_TMO_DMA )
return( NET_ERROR_DMATMO );
// clear the interrupt.
outportb(ISRADD,0xff);
ABORTDMA
return( return_value );
}
/*
Name: InitMacCntlr
Description: Initialize MAC controller of 88796
Parameters: A string witch holds MAC address.
Return: mode - 0, loop; 1, normal.
Only the work mode is set, the intrrupt routines
are not set anyway.
Test and revisioin: Ason. 2001.5
*/
void InitMacCntlr(UCHAR *mac_addr, INT16 mode)
{
UCHAR tempc;
// Step 1, turn to page 0 and set all those
// important things in page 0,
SETTOPAGE0
// step 1.1
// 0x21, stop the controller and abort remote DMA.
outportb(CRADD,0x21);
wait(3);
// step 1.2 clear all interrupt and disable all interrupt.
outportb(ISRADD,0xff);
// the reset bit will not generate interrupt actually in 796
outportb(IMRADD,0x00);
// step 1.3
// 0x03, DCR. 16-bit DMA transfering, byte order 68K
// Dual 16-bit DMA mode, remote DMA is not always complete,
outportb(DCRADD,0x03);
// step 1.4
// 0x00, TCR. CRC appended by Transmitter.
// No loop back.
// Half duplex, PAD enabled, Retransmite in
// later collision, 88796 loop back.
if ( 0 == mode )
outportb(TCRADD,0x22);
else
outportb(TCRADD,0x20);
TcrSaver = 0x20;
// step 1.5
// 0x24, RCR. Packets with receive errors are rejected.
// reject runt packet.
// accept broadcast.
// not check multicast packet. !!!
// Non promiscuous mode.
// normal mode.
// Low active interrupt.
outportb(RCRADD,0x44);
// step 1.6
// DMA registers.
// PSTARD set to 0x46. Attention, this is start address for receiving.
outportb(PSTARTADD,0x46);
// PSTOP set to 0x80.
outportb(PSTOPADD,0x80);
// BNRY set to 0x46. Same as PSTARD.
outportb(BNRYADD,0x46);
// TSR, This is no use actually.
outportb(TSRADD,0x40);
// TBCR0
outportb(TBCR0ADD,0x00);
// TBCR1
outportb(TBCR1ADD,0x00);
// ISR, clear all ISR.
outportb(ISRADD,0xff);
// RSAR0ADD,
outportb(RSAR0ADD,0x00);
// RSAR1ADD,
outportb(RSAR1ADD,0x40);
// RBCR0ADD.
outportb(RBCR0ADD,0x00);
// RBCR1ADD.
outportb(RBCR1ADD,0x00);
// 1.7 Gap registers?
// outportb(IFGS1ADD,0x00);
// outportb(IFGS2ADD,0x00);
// outportb(IFGADD,0x00);
// 1.8 TPSRADD.
outportb( TPSRADD,WritePage );
// now, change to page 1.
SETTOPAGE1
// step 2.1
// CURR
outportb(CPRADD,0x47);
// step 2.2
// MAC Address 00001b182202 plus bednumber.
outportb(PARA0ADD,*mac_addr);
outportb(PARA1ADD,*(mac_addr+1));
outportb(PARA2ADD,*(mac_addr+2));
outportb(PARA3ADD,*(mac_addr+3));
outportb(PARA4ADD,*(mac_addr+4));
outportb(PARA5ADD,*(mac_addr+5));
// step 2.3
// multicast address, don't use multicast.
outportb(MAR0ADD,0x00);
outportb(MAR1ADD,0x00);
outportb(MAR2ADD,0x00);
outportb(MAR3ADD,0x00);
outportb(MAR4ADD,0x00);
outportb(MAR5ADD,0x00);
outportb(MAR6ADD,0x00);
outportb(MAR7ADD,0x00);
ReadPage = 0x47; // read page should be same with current page.
WritePage = 0x40; // actually, this will not change.
}
/*
Name: SetIntRt
Description: open interrupt and let NIC to work.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void SetIntRt(void)
{
CHAR tempc;
UINT16 temps;
// enable the MAC controller in terrupt.
// first of all, set to page 0.
SETTOPAGE0
// set all IMR.
outportb(IMRADD,0x3f); // a reserve bit, and don't generate interrupt
// when remote DMA is finished.
ImrSaver = 0x3f;
// clear all interrupt once more.
SETTOPAGE0
outportb(ISRADD,0xff);
// clear CPU IMR.
temps = *( (UINT16 *) ( IMR_ADDR ));
temps &= 0xfffb;
*( (UINT16 *) ( IMR_ADDR )) = temps;
// start the controller.
STARTCNTLR
}
/*
Name: OnReceive
Description: The interrupt routine when a packet is received.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnReceive(void)
{
UCHAR tempc;
UCHAR regtemp;
MacState.Rcv.PacketReceived++;
// read the state in.
// don't set to page0 to make sure there are
// no retransmit of a same packet.
// SETTOPAGE0
regtemp = inportb(RSRADD);
if ( regtemp & 0x01 )
MacState.Rcv.PacketReceivedIntact++;
if ( regtemp & 0x02 )
MacState.Rcv.PacketReceviedCRCErr++;
if ( regtemp & 0x04 )
MacState.Rcv.PacketReceviedFAEErr++;
if ( regtemp & 0x08 )
MacState.Rcv.PacketReceivedFIFOErr++;
if ( regtemp & 0x10 )
MacState.Rcv.PacketReceivedMissErr++;
if ( regtemp & 0x20 )
MacState.Rcv.PacketReceivedBMpTimes++;
if ( regtemp & 0x40 )
MacState.Rcv.PacketReceivedDisabled++;
ReceiveIntHappen = 1;
}
/****************************************************************************/
/* FUNCTION */
/* */
/* NU_Get_Address */
/* */
/* DESCRIPTION */
/* */
/* This function will handle reading the Ethernet address of the board from*/
/* its internal memory. The base address of the board will be passed in */
/* for calculation offset to where the Ethernet address registers are. */
/* The Ethernet address will be checksumed when read in and tested to make */
/* sure that the board is actually there. If the checksumming and masking */
/* shows that the board is missing, I/O address is wrong, etc and error */
/* will be returned. */
/* */
/* */
/* CALLED BY */
/* */
/* initbuffer, net.c file. */
/* */
/* CALLS */
/* */
/* */
/* INPUTS */
/* */
/* uchar * : pointer to the location to store the read Ethernet address. */
/* ulint : Shared memory buffer for TCP/IP packets, not used. */
/* ulint : I/O base address of the board. */
/* */
/* OUTPUTS */
/* */
/* sshort : Returns a value of NU_FALSE if ok, else NU_TRUE on error. */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* */
/****************************************************************************/
sshort NU_Get_Address (uchar *ether_addr, ulint not_used, ulint io_base)
{
/* This routine is responsible for extracting the hardware address
* from the hardware. The hardware address should be copied into
* the location pointed to by ether_addr. If the hardware address is
* successfully extracted a value of NU_SUCCESS (0) should be returned.
* Else an error code should be returned (anything other than 0).
*/
*ether_addr = 0x52;
*(ether_addr + 1) = 0x54;
*(ether_addr + 2) = 0x4c;
*(ether_addr + 3) = 0xbd;
*(ether_addr + 4) = 0xa1;
*(ether_addr + 5) = 0x1a;
return (NU_SUCCESS);
} /* end NU_Get_Address routine */
/****************************************************************************/
/* FUNCTION */
/* */
/* NU_Set_Address */
/* */
/* DESCRIPTION */
/* */
/* This function will handle loading the Ethernet address of the board into*/
/* its internal memory. The base address of the board will be passed in */
/* for calculation offset to where the Ethernet address registers are. */
/* */
/* CALLED BY */
/* */
/* No functions call this function. */
/* */
/* CALLS */
/* */
/* */
/* INPUTS */
/* */
/* uchar * : pointer to the location to the read Ethernet address from. */
/* ulint : Shared memory buffer for TCP/IP packets, not used. */
/* ulint : I/O base address of the board. */
/* */
/* OUTPUTS */
/* */
/* No outputs from this function. */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* */
/****************************************************************************/
void NU_Set_Address (uchar *ether_addr, ulint not_used, ulint io_base)
{
/* This function will handle loading the Ethernet address of the board
* into its internal memory. The base address of the board will be passed
* in for calculation offset to where the Ethernet address registers are.
*/
} /* end NU_Set_Address routine */
/****************************************************************************/
/* FUNCTION */
/* */
/* NU_Recv_Packet */
/* */
/* DESCRIPTION */
/* */
/* This function will handle the incomming data packets to the Ehternet */
/* board. The routine can be called though the use of and interrupt or */
/* polling. It will handle the parsing and storing of the current packet */
/* from the wire. */
/* */
/* CALLED BY */
/* */
/* demux in file net.c */
/* NU_Ether_Inter_RTX */
/* NU_Ether_Inter_PLUS */
/* */
/* CALLS */
/* */
/* memcpy (uchar *, uchar *, int); */
/* dll_update_lists */
/* */
/* INPUTS */
/* */
/* No inputs to this function. */
/* */
/* OUTPUTS */
/* */
/* sshort : Returns status as to buffer processing NU_TRUE if ok */
/* NU_FALSE if and error. */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/****************************************************************************/
sshort NU_Recv_Packet (void)
{
uchar *recv_data_ptr; /* pointer to the received data in shared memory */
ushort total_bytes; /* total byte for this packet */
struct pqueue HUGE *buf_ptr;
/* This function is called from the receive HISR. It is responsible
* for moving received packets from shared memory into the packet buffers.
*/
/* An example of how a buffer is allocated and used. */
/* Allocate a partition into which the received packet will be copied. */
buf_ptr = dll_update_lists(&buffer_freelist, &buffer_list);
/* If the allocation failed then cleanup and return.
*/
if (buf_ptr == NU_NULL)
{
/* If the partition allocation failed for any reason other than
* there were no partitions currently available, generate an
* error message.
*/
if (buf_ptr == NU_NULL)
{
NU_Tcp_Log_Error (TCP_PARTITION_ERROR, TCP_RECOVERABLE,
__FILE__, __LINE__);
}
/* return that there was an error with a packet reception */
return NU_FALSE;
} /* end check for room in our buffer */
/*
* Transfer the data from the packet to our memory.
*/
/* transfer the frame(s) from the shared memory to ours */
if (total_bytes != 0)
{
/* store the contiguous message */
memmove(buf_ptr->packet, recv_data_ptr, total_bytes);
} /* end transfer the data from the shared mem, to our buffer */
return NU_TRUE;
} /* end NU_Recv_Packet routine */
/*
Name: RemoteWrite
Description: write data into a buffer using remote DMA.
Parameters: cur_page: current page to start, may start at the middle
possition of a page.
len: lenth of the DMA, words.
buf: where to copy the data.
Return: NET_NO_ERROR or Error code.
Test and Revision: Ason, 2001.5
*/
int16 RemoteWrite(UINT16 cur_page, UINT16 len, UINT16 *buf)
{
CHAR tempc;
UCHAR regtemp;
UINT16 i;
SETTOPAGE0
regtemp = (cur_page & 0xff00) >> 8;
outportb(RSAR1ADD, regtemp);
regtemp = cur_page & 0xff;
outportb(RSAR0ADD,regtemp);
regtemp = (( (len<<1) & 0xff00) >> 8) & 0xff;
outportb(RBCR1ADD,regtemp);
regtemp = (len<<1) & 0xff;
outportb(RBCR0ADD,regtemp);
// start remote DMA to write.
outportb( CRADD,0x12 );
// buf maybe exceed the scope for adding pads, but
// it just read, do no harm.
for (i = 0; i <len; i++ )
outport(DATAPORTADD, *(buf + i));
// wait for the read DMA to finish.
i = 0;
while(1)
{
tempc = inportb(ISRADD);
if ( 0x40 & tempc )
{
MacState.RemoteDMACompleteTimes++;
break;
}
wait(1);
if ( i++ > NET_TMO_DMA )
break;
}
if ( i > NET_TMO_DMA )
{
return( NET_ERROR_DMATMO );
}
outportb(ISRADD,0x40); // clear DMA interrupt.
return( NET_NO_ERROR );
}
/*
Name: TransmitAPacket
Description: Transmit a packet promptly.
Parameters: buf - buffer to hold the packet, point to word.
length - length in word
Returns: NET_NO_ERROR or Error code.
Test and revision:
Ason. 2001.7
*/
INT16 TransmitAPacket( UINT16 *buf, UINT16 length )
{
UCHAR tempc,regtemp;
UINT16 temps;
INT16 return_value,i;
UINT32 pre_int_level;
UINT16 tempss;
// I am pretty sure this will be called only in
// tasks, so, change to NO_PREEMPTION to solve
// conflict of the two protocols.( TCP/IP and VB)
// Attention, this change of "preempt" feature is
// used to protect seed of "protect"!!!
NU_Change_Preemption( NU_NO_PREEMPT );
// I could not use IMR in 88796(don't know why?), and
// I don't wanna disabling of this interrupt influence
// low level interrupts, so, I just use CPU IMR. IMR could
// only mask low level interrupt, back to CR.
//pre_int_lev = NU_Control_Interrupts( MACINTLEVEL << 8 );
DISABLENETINTERRUPT
return_value = RemoteWrite( ((UINT16)WritePage) << 8 , length, buf );
if ( NET_NO_ERROR != return_value )
{
//NU_Control_Interrupts( pre_int_lev );
ENABLENETINTERRUPT
NU_Change_Preemption( NU_PREEMPT );
return( return_value );
}
outportb( TPSRADD,WritePage );
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -