📄 netdrv.cpp
字号:
// 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 ( TRUE == 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
cr_saver = inportb( CRADD );
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();
}
// and, return CR.
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;
UINT32 pre_int_level;
// pre_int_level = NU_Control_Interrupts( MACINTLEVEL << 8 );
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 )
{
// NU_Control_Interrupts( pre_int_level );
return( NET_ERROR_DMATMO );
}
outportb( ISRADD, 0x40 );
// NU_Control_Interrupts( pre_int_level );
return( NET_NO_ERROR );
}
/*
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
*/
BOOL 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_lev;
// 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)
// 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 );
return_value = RemoteWrite( ((UINT16)WritePage) << 8 , length, buf );
if ( NET_NO_ERROR != return_value )
{
// NU_Change_Preemption( NU_PREEMPT );
//NU_Control_Interrupts( pre_int_lev );
return( return_value );
}
outportb( TPSRADD,WritePage );
// length is destined to be even.
outportb(TBCR0ADD,(length<<1) % 256);
outportb(TBCR1ADD,(length<<1) / 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( TRUE )
{
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 );
// 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( TRUE )
{
// 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 ) )
break;
wait(1);
if ( i++ > NET_TMO_TMIT )
break;
}
//NU_Change_Preemption( NU_PREEMPT );
if ( i > NET_TMO_TMIT )
return( NET_ERROR_TRANSBLOCK );
else
return( NET_NO_ERROR );
}
/*
Name: ConfigMacMii
Description: set neccessary things in MII register set,
as 10M/100M, duplex and such staff.
Parameters: mode, 0 - 10M, 1-100M, 2- autonegotiation.
Return: TRUE, success, FALSE, fail.
Test and revision:
Ason, 2001.7.
*/
INT16 ConfigMacMii(INT16 mode)
{
INT16 return_value;
UINT32 i;
UINT16 tempus;
UCHAR tempc;
SETTOPAGE0
outportb(CRADD,0x21);
wait(3);
// reset MII register set.
tempus = 0x8000;
WriteMiiRegister(0x10,0x00,tempus); // 0x10 is the PHY ID of our internal PHY,
// you may refer to 88796 data sheet.
i = 0;
while( TRUE )
{
return_value = ReadMiiRegister(0x10,0x00,&tempus);
if ( NET_NO_ERROR != return_value )
return( NET_ERROR_PHYREAD );
if ( ! ( tempus & 0x8000 ) )
break;
wait(1);
if ( i++ > NET_TMO_MIIRST )
return( NET_ERROR_MIIRST );
}
tempus &= 0xcfff; // clear 10/100/auto-negotiation bit.
if ( 2 == mode)
tempus |= 0x1000; // set auto negotiation.
else if ( 1 == mode )
tempus |= 0x2000; // set to 100M.
tempus &= 0xfeff; // set to half duplex.
WriteMiiRegister(0x10,0x00,tempus);
// say i am not capable of 100Base-TX and 100Base-T.
// Why say I am not capable of 100M?s
// WriteMiiRegister(0x10,0x04,0x0061);
// say i will see interrupt of link state/jabber/remote fault/false carrier.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -