📄 netdrv.cpp
字号:
// but i don't know why the two bits writable can not be set.
// WriteMiiRegister(0x10,31,0x0);
return( NET_NO_ERROR );
}
/*
Name: ReceiveAPacket
Description: This routine will received a packet now
dangling on the MAC buffer, and "ReadPage" is
a global thing.
Parameters: buf - the buffer used to hold the packet.
Returns: 0 - A packet is successfully received.
1 - No packet is found.
2 - this is a viewbed packet, and we care about it, saved.
3 - this is a viewbed packet, but we don't care about it, discard.
-1 - NET_ERROR_PAKLEN.
Test and revision:
Ason. 2001.7
*/
// for debug
unsigned long thistimesernum;
unsigned long lasttimesernum;
unsigned long serialnumerror = 0;
unsigned long trigger = 0;
INT16 ReceiveAPacket( UCHAR *tcpip_buf, UCHAR *vb_buf, UINT16 *type )
{
UCHAR tempc, cur_page;
UINT16 packet_len;
UINT16 return_value = NET_NO_ERROR;
UINT16 packet_type;
// UCHAR temp_buf[18]; // temporary buffer to hold packet head.
UCHAR temp_buf[24]; // temporary buffer to hold packet head.
*type = packet_type = NET_PTL_NOONE;
SETTOPAGE0
tempc = inportb(RSRADD);
// when set to page1, there should be an interrupt entry protection.
SETTOPAGE1
cur_page = inportb(CPRADD);
SETTOPAGE0
if ( ReadPage == cur_page )
return( NET_ERROR_NOPAKIN );
else
{
// read packet head.
// return_value = RemoteRead( ((UINT16)ReadPage) << 8 , 9, (UINT16*)temp_buf );
// for debug.
return_value = RemoteRead( ((UINT16)ReadPage) << 8 , 12, (UINT16*)temp_buf );
if ( NET_NO_ERROR != return_value )
return( return_value );
// here, something must be done to make sure VB protocol
// packets goes else where.
if ( 0xff == temp_buf[10]
&& 0xff == temp_buf[11]
&& 0xff == temp_buf[12]
&& 0xff == temp_buf[13] )
{
if ( temp_buf[14] & 0x80 )
// this is a packet holding general information.
packet_type = NET_PTL_VIEWBEDCARE;
else
{
// this is a packet holding real-time data.
//if ( temp_buf[15] == VBCtrl.ViewBedFocus )
packet_type = NET_PTL_VIEWBEDCARE;
//else
// packet_type = NET_PTL_VIEWBEDNOTCARE;
}
// for debug only.
thistimesernum = *((unsigned long *)&temp_buf[18]);
if ( trigger > 10 )
{
if ( thistimesernum != lasttimesernum + 1 )
serialnumerror++;
}
else
trigger++;
lasttimesernum = thistimesernum;
}
else
packet_type = NET_PTL_TCPIP;
*type = packet_type;
packet_len = ((UINT16)256) * temp_buf[3] + temp_buf[2]
- 14;
if ( packet_len > RECEIVE_BUF_SIZE - 14 )
return( NET_ERROR_PAKLEN );
if ( NET_PTL_TCPIP == packet_type )
{
memcpy(tcpip_buf,&temp_buf[4],14);
// read the whole packet in.
return_value = RemoteRead( (((UINT16)ReadPage) << 8) + 18, ( packet_len + 1 ) >> 1, (UINT16 *)(tcpip_buf + 14) );
}
else if ( packet_type == NET_PTL_VIEWBEDCARE )
{
memcpy(vb_buf,&temp_buf[4],14);
return_value = RemoteRead( (((UINT16)ReadPage) << 8) + 18, ( packet_len + 1 ) >> 1, (UINT16 *)(vb_buf + 14) );
}
if ( NET_NO_ERROR == return_value )
{
MacState.Rcv.PacketReallyReceived++;
if ( NET_PTL_TCPIP == packet_type )
MacState.Rcv.PacketReallyReceivedTcpip++;
else if ( NET_PTL_VIEWBEDCARE == packet_type )
MacState.Rcv.PacketReallyReceivedVBCare++;
else if ( NET_PTL_VIEWBEDNOTCARE == packet_type )
MacState.Rcv.PacketReallyReceivedVBNotCare++;
}
// move the BNYR to next page.
SETTOPAGE0
outportb( BNRYADD,ReadPage );
ReadPage = temp_buf[1];
SETTOPAGE1
cur_page = inportb(CPRADD);
SETTOPAGE0
return( NET_NO_ERROR );
}
}
/*
Name: MacLoopTest
Description: Do two kinds of loop test: 1. internal loop
2. internal loop with HPY
Parameters: None.
Returns: Error code or NET_NO_ERROR
Test and revision:
Ason. 2001.7
*/
INT16 MacLoopTest(void)
{
INT16 i,return_value,looptimes;
UCHAR tempc,cur_page;
UINT16 tempus;
UINT16 packet_type;
BOOL return_value_bool;
for ( i = 0; i < 256; i++ )
SndLoopBuf[i] = i;
SndLoopBuf[0] = 0xff; // make it a broadcast address.
SndLoopBuf[1] = 0xff;
SndLoopBuf[2] = 0xff;
SndLoopBuf[3] = 0xff;
SndLoopBuf[4] = 0xff;
SndLoopBuf[5] = 0xff; // must make sure that [6],[7],[8],[9] will never be
// 0xff to make it a non-viewbed packet.
// first of all, set loop mode 1.
SETTOPAGE0
outportb(TCRADD,0x22);
// start the MAC controller.
STARTCNTLR
for ( looptimes = 0; looptimes < 1000; looptimes++ )
{
// clear receive buffer.
for ( i = 0; i < 260; i++ )
RcvLoopBuf[i] = i + 1;
// "RemoteWrite" will not change register page.
return_value = TransmitAPacket( (UINT16*)SndLoopBuf, 128 );
if ( NET_NO_ERROR != return_value )
return( return_value );
// polling for received state.
i = 0;
while( TRUE )
{
tempc = inportb(ISRADD);
if ( tempc & 0x01 )
break;
wait(3);
if ( i++ > NET_TMO_LOOPWT )
break;
}
if ( i > NET_TMO_LOOPWT )
return( NET_ERROR_LOOPRSP );
return_value = ReceiveAPacket(RcvLoopBuf,RcvLoopBuf,&packet_type);
if ( NET_NO_ERROR != return_value )
return( return_value );
if ( memcmp( SndLoopBuf, &(RcvLoopBuf[0]), 256 ) )
return( NET_ERROR_LOOPERR );
// clear receive bit.
SETTOPAGE0
outportb(ISRADD,0x01);
}
// first of all, set loop mode 2.
outportb(TCRADD,0x24); // 0xa4 for internal loop with PHY,
if ( NET_NO_ERROR != ReadMiiRegister(0x10,0x00,&tempus) )
return( NET_ERROR_MIIRD );
tempus |= 0x4000; // set PHY loop;
WriteMiiRegister(0x10,0x00,tempus);
for ( looptimes = 0; looptimes < 1000; looptimes++ )
{
// clear all the received bytes.
for ( i = 0; i < 260; i++ )
RcvLoopBuf[i] = i + 1;
// transmit a packet.
return_value = TransmitAPacket( (UINT16*)SndLoopBuf, 128 );
if ( NET_NO_ERROR != return_value )
return( return_value );
i = 0;
while( TRUE )
{
tempc = inportb(ISRADD);
if ( tempc & 0x01 )
break;
wait(3);
if ( i++ > NET_TMO_LOOPWT )
break;
}
if ( i > NET_TMO_LOOPWT )
return( NET_ERROR_LOOPRSP );
return_value = ReceiveAPacket(RcvLoopBuf, RcvLoopBuf, &packet_type );
if ( NET_NO_ERROR != return_value )
return(return_value);
if ( memcmp( SndLoopBuf, &(RcvLoopBuf[0]), 256 ) )
return( NET_ERROR_LOOPERR );
// clear receive bit.
SETTOPAGE0
outportb(ISRADD,0x01);
}
return( NET_NO_ERROR );
}
/*
Name: NU_Get_Address
Description: This file is used to return MAC address, as we don't use EEPROM
or such things to determine MAC address, we just return it from
bed number.
Parameters: ether_addr - hold MAC address to return.
not_used - things not used, but required by interface.
io_base - io base of MAC, as we don't use it, let it be, required
by interface.
Return: always return success.
Test and revision:
Ason. 2001.7
*/
INT16 NU_Get_Address (UCHAR *ether_addr, UINT32 not_used, UINT32 io_base)
{
*ether_addr = BED_ETHER_ADDR_AREA1;
*(ether_addr + 1) = BED_ETHER_ADDR_AREA2;
*(ether_addr + 2) = BED_ETHER_ADDR_AREA3;
*(ether_addr + 3) = BED_ETHER_ADDR_AREA4;
*(ether_addr + 4) = BED_ETHER_ADDR_AREA5;
*(ether_addr + 5) = BED_ETHER_ADDR_AREA6 + 0;
return 0;
}
/*
Name: RemedyHardwareBug
Description:
According to datasheet version-16, a software reset of
at least 2.5s must be employed to PHY to remedy hardware
bugs.
Parameters:
None.
Test and revision:
Ason. 2001.11.20 <E>
*/
void RemedyHardwareBug(void)
{
WriteMiiRegister(0x10,0x00,0x800);
wait( 1000 * 5 );
// force to autonegotiation and restart it.
WriteMiiRegister(0x10,0x00,0x00);
// wait for 5 more seconds to make sure
// that the autonegotiation will finish.
wait( 1000 * 5 );
}
/*
Name: NU_Etopen
Description: 1. Initialize hardware, 2. load interrupt service. This
is also the interface required by TCP/IP layer.
Parameters: ether_addr - MAC address of the card.
irq_num - external interrupt number.
buff_addr - shared memory or such things, as we don't
use shared memory anyway, this is lefted.
base_addr - base address of the I/O.
Return: NU_SUCCESS if the the procedure is success,
error code if fail. NU_SUCCESS = 0;
-1, Reg Error.
-2, Ram Error.
Test and revision:
Ason. 2001.7
*/
INT16 NU_Etopen (UCHAR *ether_addr, UINT16 irq_num,
UINT32 buff_addr, UINT32 base_addr)
{
INT16 return_value;
UCHAR tempc;
RemedyHardwareBug();
// step1, initialize statistics of MAC layer.
InitStatistics();
// step2, test NE2000 registers.
return_value = TestMacReg();
if ( NET_NO_ERROR != return_value )
return( return_value );
// step3, test SRAM.
return_value = TestMacRam();
if ( NET_NO_ERROR != return_value )
return( return_value );
/*
// step4, initialize things in MII registers of 88796.
return_value = ConfigMacMii(0);
if ( NET_NO_ERROR != return_value )
return( return_value );
*/
// step5, config 88796 to work.
InitMacCntlr( ether_addr, 0 );
// step6, loop test, both with PHY and without PHY, pooling.
return_value = MacLoopTest();
if ( NET_NO_ERROR != return_value )
return( return_value );
// step7, reinitialize things in MII of 88796.
// beause in step 6, some MII register settings are changed.
// and set PHY to autonegotiation mode.
/* // input: 0:10M, 1:100M, 2:Autonegotiation.
return_value = ConfigMacMii(0);
if ( NET_NO_ERROR != return_value )
return( return_value );
*/
// step8, config 88796 to work once again.
// because in step 6, some register settings are changed,
// so, you must reinitialize the registers.
// and set to normal mode.
InitMacCntlr( ether_addr, 1 );
// step9, clear IMR of CPU and let interrupt work.
// SetIntRt();
return ( NET_NO_ERROR );
}
/*
Name: NU_Xmit_Packet
Description: interface function, transmit a packet immediately.
Parameters: pack_addr - the packet address
num_msg_bytes - the packet length.
Return: .
Test and revision:
Ason. 2001.7.
*/
INT16 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( 0 );
}
/*
Name: Net_Lisr
Description: Low level interrupt service of MAC controller 88796.
Parameter: None
Return: None
Test and revision:
Ason. 2001.7
*/
void Net_Lisr(void)
{
MacInt();
outportb(0x10000010,0x00); // clear the interrupt. this
// is not necessary actually
// when hardware changed.
}
// following are debug functions.
// restart autonegotiation.
INT16 RestartAutoNeg(void)
{
INT16 return_value;
UINT16 tempus;
return_value = ReadMiiRegister(0x10,0x00,&tempus);
if ( NET_NO_ERROR != return_value )
return( -1 );
tempus |= 0x0200; // restart autonegotiation.
WriteMiiRegister(0x10,0x00,tempus);
return(0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -