📄 driver.c
字号:
// length is destined to be even.
// and of cource, the packet should bigger than
// 64 bytes.
tempss = length << 1;
if ( tempss < 60 )
tempss = 60;
outportb( TBCR0ADD, tempss % 256 );
outportb( TBCR1ADD, tempss / 256 );
PacketDelivered = 0;
STARTTRANSMIT
// This is also very important, as if we enable interrupt here
// and in interrupt service, there destined to be a "SETTOPAGE0".
// refer to SETTOPAGE0, read CR out(TXP bit still exist), then
// write CR in( now TXP don't exist), dual-transmition occur!!!
i = 0;
while( 1 )
{
regtemp = inportb( CRADD );
if ( !(regtemp & 0x04) )
break;
wait(1);
if ( i++ > NET_TMO_TMIT )
break;
}
if ( i > NET_TMO_TMIT )
{
//NU_Control_Interrupts( pre_int_lev );
ENABLENETINTERRUPT
NU_Change_Preemption( NU_PREEMPT );
return ( NET_ERROR_TRANSBLOCK );
}
// first of all, open interrupt to make sure we
// can receive now.
//NU_Control_Interrupts( pre_int_lev );
// See if we get the packet delivered, if it is not delivered,
// just wait for a while, and when we are waiting, other
// tasks who should call "TransmitAPacket" will not be allowed.
// Attention!!! transmit interrupt may happen here, in this case,
// we will not get ISR set in the following lines, so, we use
// "PacketDelivered" to help us out.
i = 0;
while( 1 )
{
// No need to SETTOPAGE0 and mask interrupt, as in interrupt service,
// after each time of "SETTOPAGE1", there is a "SETTOPAGE0".
regtemp = inportb( ISRADD );
if ( ( regtemp & 0x08 ) || ( regtemp & 0x02 ) || ( 1 == PacketDelivered ) )
{
outportb( ISRADD, 0x0a );
break;
}
wait(1);
if ( i++ > NET_TMO_TMIT )
break;
}
ENABLENETINTERRUPT
NU_Change_Preemption( NU_PREEMPT );
// NU_Change_Preemption( NU_PREEMPT );
if ( i > NET_TMO_TMIT )
return( NET_ERROR_TRANSBLOCK );
else
return( NET_NO_ERROR );
}
/****************************************************************************/
/* FUNCTION */
/* */
/* NU_Xmit_Packet */
/* */
/* DESCRIPTION */
/* */
/* This function will handle placing the passed in packet onto the actual*/
/* wire. This routine will make sure that each packet is at least 60 */
/* bytes long. */
/* */
/* CALLED BY */
/* */
/* dlayersend in net.c file */
/* */
/* CALLS */
/* */
/* */
/* INPUTS */
/* */
/* uchar : pointer to the packet which is to be sent over the wire. */
/* sshort : number of schar's which will be sent total. */
/* */
/* OUTPUTS */
/* */
/* sshort : Returns NU_FALSE (0) if ok, else -1 due to wait for trans */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* */
/****************************************************************************/
sshort NU_Xmit_Packet (uchar *pack_addr, uint16 num_msg_bytes)
{
// according to IEEE802.3, packet length not including checksum
// should be at least 60 bytes.
// and the hardware will add CRC automatically.
// we say that CRC will be appended by transmitter, what's the
// meaning of it? length is actual size of the packet or
// the size should be actual size plus 4(CRC length?).
// refer to data sheet, size is only actual size.
if ( num_msg_bytes % 2 )
num_msg_bytes++;
if ( num_msg_bytes < TRANSMIT_BUF_MIN_SIZE )
num_msg_bytes = TRANSMIT_BUF_MIN_SIZE; // add PAD.
else if ( num_msg_bytes > TRANSMIT_BUF_SIZE )
return( -1 ); // MTU exceeded.
if ( NET_NO_ERROR != TransmitAPacket( (UINT16 *)pack_addr, num_msg_bytes / 2 ) )
return( -1 );
return( NU_SUCCESS );
}
/*
Name: OnTransmit
Description: The interrupt routine core when a packet is transmit.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnTransmit(void)
{
UCHAR tempc,regtemp;
MacState.Tmt.TransmitTimes++;
// read the state in.
// SETTOPAGE0
regtemp = inportb(TSRADD);
if ( regtemp & 0x80 )
MacState.Tmt.TransmitOWCErr++;
if ( regtemp & 0x08 )
MacState.Tmt.TransmitABTErr++;
if ( regtemp & 0x02 )
MacState.Tmt.TransmitColTimes++;
if ( regtemp & 0x01 )
MacState.Tmt.TransmitPTXTimes++;
TransmitHappen = 1;
PacketDelivered = 1;
}
/*
Name: OnReceiveWithError
Description: The interrupt routine core when a packet is received,
but error is found.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnReceiveWithError(void)
{
UCHAR tempc,regtemp;
MacState.Rcv.PacketReceivedWithError++;
// read the state in.
// SETTOPAGE0
regtemp = inportb(RSRADD);
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 & 0x40 )
MacState.Rcv.PacketReceivedDisabled++;
}
/*
Name: OnTransmitWithError
Description: The interrupt routine core when a packet is transmitted,
but an error is found.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnTransmitWithError(void)
{
UCHAR tempc,regtemp;
MacState.Tmt.TransmitTimesWithError++;
// read the state in.
// SETTOPAGE0
regtemp = inportb(TSRADD);
if ( regtemp & 0x80 )
MacState.Tmt.TransmitOWCErr++;
if ( regtemp & 0x08 )
MacState.Tmt.TransmitABTErr++;
if ( regtemp & 0x02 )
MacState.Tmt.TransmitColTimes++;
PacketDelivered = 1;
}
/*
Name: RecoverFromBufShortage
Descriptioin: This routine will be used to recover from
the buffer shortage error. please refer to 796 data sheet.
Parameters: None.
Return: None.
Test and revision:
Ason. 2001.8
*/
void RecoverFromBufShortage()
{
uint16 txp, resend;
UCHAR tempc;
// following lines are according to 88796 data sheet which
// says very detailed about what to do when buffer overflows.
// I change a little with throwing away all the packets waiting
// on the buffer link and make buffer empty.
// step 1, save TXP in
tempc = inportb(CRADD);
if ( tempc & 0x04 )
txp = 1;
else
txp = 0;
// step 2, stop 796
outportb(CRADD,0x21);
// step 3. wait for at least 1.5 ms.
wait(2);
// step 4, clear RBCR0 and RBCR1.
SETTOPAGE0
outportb(RBCR0ADD,0x00);
outportb(RBCR1ADD,0x00);
// step 5
if ( 1 == txp )
{
tempc = inportb(ISRADD);
if ( ( tempc & 0x02 ) || ( tempc & 0x08 ) )
resend = 0;
else
resend = 1;
}
else
{
resend = 0;
}
// step 6 loop, i know, this will shut the data link from out side.
tempc = TcrSaver & 0xf9;
tempc = TcrSaver | 0x02;
outportb( TCRADD, tempc );
// step 8. remove all the packet from the receive buffer.
// as the packet has already been lost, just throw
// all the packets in the buffer away.
// the method is set the two dynamic read and write
// registers.
outportb(BNRYADD,0x46);
SETTOPAGE1
outportb(CPRADD,0x47);
SETTOPAGE0
ReadPage = 0x47;
// step 9.
outportb(ISRADD,0x10);
// step 10.
outportb(TCRADD, TcrSaver);
// step 7. start. data sheet got some errors here,
// if i start it really in step 7, data could
// still be flowed in of step 8,9,10, that could
// make trouble.
// step 6 will do this, but why do i find problems?
outportb(CRADD,0x22);
// step 11.
if ( 1 == resend )
{
outportb(CRADD,0x26);
}
// step 12. this is for my application environment.
// when buffer shortage happens, there should be
// also an receive interrupt.
ReceiveIntHappen = 0;
BufShortHappen = 0;
}
/*
Name: OnShortBufferInReceive
Description: The interrupt routine core when there is no buffer
to save packet coming in.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnShortBufferInReceive(void)
{
MacState.ShortBufferTimes++;
BufShortHappen = 1;
}
/*
Name: OnCounterOverflow
Description: The interrupt routine core when the error counter
is owverflow.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnCounterOverflow(void)
{
// nothing to do.
MacState.CouterOverflowTimes++;
}
/*
Name: OnReset
Description: The interrupt routine core when the MAC controller
is reset.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnReset(void)
{
// nothing to do.
MacState.ResetTimes++;
}
/*
Name: OnRemoteDMAComplete
Description: The interrupt routine core when remote DMA finish the
data transfer.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void OnRemoteDMAComplete(void)
{
MacState.RemoteDMACompleteTimes++;
}
/*
Name: MacInt
Description: The MAC controller interrupt routine.
Parameters: None.
Return: None.
Test and revisioin: Ason. 2001.5
*/
void MacInt(void)
{
UCHAR tempc;
UCHAR cr_saver;
// first of all, read the CR, Command Register
cr_saver = inportb( CRADD );
if ( cr_saver & 0x40 )
{
// say, this is page 1
// set to page 0, and there should be no problem
// to generate retransmiting, as when we set to
// page0, there are destined to be no transmit.
SETTOPAGE0
}
tempc = inportb(ISRADD);
if ( tempc & 0x01 ) // this is a receive interrupt without any error.
{
OnReceive();
outportb(ISRADD,0x01);
}
if ( tempc & 0x02 )
{
OnTransmit();
outportb(ISRADD,0x02);
}
if ( tempc & 0x04 )
{
OnReceiveWithError();
outportb(ISRADD,0x04);
}
if ( tempc & 0x08 )
{
OnTransmitWithError();
outportb(ISRADD,0x08);
}
if ( tempc & 0x10 )
{
OnShortBufferInReceive();
outportb(ISRADD,0x10);
}
if ( tempc & 0x20 )
{
OnCounterOverflow();
outportb(ISRADD,0x20);
}
if ( tempc & 0x40 )
{
OnRemoteDMAComplete();
// As we will clear this bit in polling mode,
// we don't deal with it here.
}
if ( tempc & 0x80 )
{
OnReset();
}
NU_Activate_HISR( &NetControllerHisr );
// and, return CR.
if ( cr_saver & 0x40 )
// only recover when interrupt context is page1.
outportb( CRADD, cr_saver );
}
/*
Name: RemoteRead
Description: read data into a buffer use 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 save data.
Return: NET_NO_ERROR or error code.
Test and Revision: Ason, 2001.5
*/
INT16 RemoteRead(UINT16 cur_page, UINT16 len, UINT16 *buf)
{
UCHAR tempc;
UCHAR regtemp;
UINT16 i;
UINT16 tempss;
UINT32 pre_int_level;
// pre_int_level = NU_Control_Interrupts( MACINTLEVEL << 8 );
// DISABLENETINTERRUPT
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 read.
outportb( CRADD,0x0a );
for (i = 0; i <len; i++ )
*( buf + i ) = inport( DATAPORTADD );
// wait for the read DMA to finish.
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 )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -