📄 driver.c
字号:
{
//NU_Control_Interrupts( pre_int_level );
//ENABLENETINTERRUPT
return( NET_ERROR_DMATMO );
}
outportb( ISRADD, 0x40 );
//NU_Control_Interrupts( pre_int_level );
//ENABLENETINTERRUPT
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( 1 )
{
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.
// 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
*/
int16 ReceiveAPacket( unsigned char *tcpip_buf, unsigned char *vb_buf, uint16 *type )
{
UCHAR tempc, cur_page;
UINT16 packet_len;
UINT16 return_value = NET_NO_ERROR;
UINT16 packet_type;
UCHAR temp_buf[24]; // temporary buffer to hold packet head.
DISABLENETINTERRUPT
*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 )
{
ENABLENETINTERRUPT
return( NET_ERROR_NOPAKIN ); //packet len error
}
else
{
// read packet head.
return_value = RemoteRead( ((UINT16)ReadPage) << 8 , 12, (UINT16*)temp_buf );
if ( NET_NO_ERROR != return_value )
{
ENABLENETINTERRUPT
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
{
#if 0
// this is a packet holding real-time data.
if ( temp_buf[15] == VBCtlr.ViewBedFocus )
packet_type = NET_PTL_VIEWBEDCARE;
else
packet_type = NET_PTL_VIEWBEDNOTCARE;
#endif
}
}
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 )
{
ENABLENETINTERRUPT
return( NET_ERROR_PAKLEN ); //packet len error
}
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) );
// here, judge if the packet is for upgrading.
}
else if ( NET_PTL_VIEWBEDCARE == packet_type )
{
memcpy(vb_buf,&temp_buf[4],14);
return_value = RemoteRead( (((UINT16)ReadPage) << 8) + 18, ( packet_len + 1 ) >> 1, (UINT16 *)(vb_buf + 14) );
}
else
{
}
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
ENABLENETINTERRUPT
return( NET_NO_ERROR );
}
}
/*
Name: NUTransmit
Description: 1. place buffer used by transmitter back to freelist.
2. if there are some packet waiting to be transmitted,
transmitte it.
3. Why this is never called? Let me probe in TCP/IP stack
But at least obviously, for UDP, buffer could be released
when transmit, TCP, when acknowledge comes in, it also
can be released by TCP/IP stack.
Parameters: None.
Return: None.
Test and revision:
Ason. 2001.8
*/
void NUTransmit(void)
{
struct transq *item;
if( trans_list.head )
{
// Dequeue the transmitted item.
item = (struct transq *) dll_dequeue ((tqe_t *) &trans_list);
// If this buffer does not contain a TCP data segment deallocate
// the buffer. If it does it will be deallocated when an ack for
// the data is received.
if(item->pkt_type == OTHER_PKT)
{
// Place the buffer back on the freelist.
dll_enqueue((tqe_t *)&buffer_freelist, (tqe_t *)item->buffer);
}
// Place the transmit item on the freelist to be reused.
dll_enqueue((tqe_t *)&trans_freelist, (tqe_t *)item);
// If there is another item on the list, transmit it.
if(trans_list.head) // why should this happen?
{
// enable interrupt and transmit the next packet.
// maybe will never come here as we use PACKET mode
// in upper layer which delivers packets promptly.
// NU_Xmit_Packet((uchar *)trans_list.head->pkt,
// (uint16) trans_list.head->length);
// for debug.
}
}
}
/*
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);
NU_Sleep( 100 * 5 );
// force to autonegotiation and restart it.
WriteMiiRegister(0x10,0x00,0x1200);
// wait for 5 more seconds to make sure
// that the autonegotiation will finish.
NU_Sleep( 100 * 5 );
}
/*
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()
{
TestCount++;
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);
}
/*
Name: NetCtlrHisr
Description: HISR routine for received data from NIC.
Parameters: None.
Return: None.
Test and revision:
Ason. 2001.7
*/
void NetCtlrHisr(void)
{
struct pqueue HUGE *buf_ptr;
UCHAR *bufp_tcpip, *bufp_vb;
UINT16 packet_type;
UCHAR buf_flag; // 1 - RcvLoopBuf; 0 - Recv_List
UCHAR tempc;
if ( 1 == BufShortHappen )
RecoverFromBufShortage();
if ( 1 == ReceiveIntHappen )
{
while( 1 )
{
//step1, allocate buffer for receive packet
if ( NU_NULL == (( buf_ptr = dll_update_lists(&buffer_freelist, &Recv_List )) ))
{
bufp_tcpip = RcvLoopBuf; // give a buffer
MacState.IPBufShortTimes++;
buf_flag = 1;
}
else
{
bufp_tcpip = buf_ptr->packet;
buf_flag = 0;
}
//step2, begin receive packet
// if receive error, quit while loop
if ( NET_NO_ERROR != ReceiveAPacket( bufp_tcpip, bufp_vb, &packet_type ) )
{
// error, free the buffer.
if ( 0 == buf_flag )
{
dll_update_lists( &Recv_List, &buffer_freelist );
// ReleaseVBBuffer( bufp_vb );
}
break;
}
//if receive success, when packet tppe is tcp, set tcp event
else
{
if ( NET_PTL_TCPIP == packet_type )
{
dll_update_lists(&Recv_List, &buffer_list);
NU_Set_Events(&Buffers_Available, (UNSIGNED)2, NU_OR);
}
else
{
if ( 0 == buf_flag )
dll_update_lists( &Recv_List, &buffer_freelist );
}
}
}
ReceiveIntHappen = 0;
}
if ( 1 == TransmitHappen )
{
NUTransmit();
TransmitHappen = 0;
}
}
/****************************************************************************/
/* FUNCTION */
/* */
/* NU_Etopen */
/* */
/* DESCRIPTION */
/* */
/* This function will handle the initilization of the Ethernet H/W you */
/* are using for communication, and will load the interrupt information */
/* if you are using it. */
/* */
/* CALLED BY */
/* */
/* dlayerinit in file net.c */
/* */
/* CALLS */
/* */
/* */
/* INPUTS */
/* */
/* schar * : pointer to the string containing the ethernet address */
/* sshort : interrupt level that the ethernet board should use to */
/* inform the driver software of changing conditions. */
/* ulint : Starting address of the current buffer being used for */
/* storing recv and xmit buffers. */
/* ulint : I/0 base address of the current ethernet board, should be */
/* defined in the chipint.h file. Used to offset base and */
/* setup the internal register. */
/* */
/* OUTPUTS */
/* */
/* sshort : Returns NU_FALSE always. */
/* */
/* HISTORY */
/* */
/* NAME DATE REMARKS */
/* */
/* */
/****************************************************************************/
sshort NU_Etopen (uchar *ether_addr, uint16 irq_num,
ulint buff_addr, ulint base_addr)
{
INT16 i;
INT16 return_value;
UCHAR tempc;
STATUS status;
VOID *pointer;
RemedyHardwareBug();
// step0, initialize protection instructure.
for ( i = 0; i < NU_PROTECT_SIZE; i++ )
MacProtect.words[i] = 0;
// step1, initialize statistics of MAC layer.
InitStatistics();
// step2, test NE2000 registers.
return_value = TestMacReg();
if ( NET_NO_ERROR != return_value )
{
//TriggerAlarm(0x0001, STR_ALM_NETINITERRROM );
return( return_value );
}
// step3, test SRAM.
return_value = TestMacRam();
if ( NET_NO_ERROR != return_value )
{
//TriggerAlarm(0x0001,STR_ALM_NETINITERRRAM );
return( return_value );
}
// step5, config 88796 to work.
InitMacCntlr( ether_addr, 0 );
// 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 );
//here, we init lisr and hisr, no like ason, who register lisr in init.s file,
//and create hisr in main func -lili
/* read old, load new */
// #if 0
status = NU_Register_LISR (irq_num, Net_Lisr, &NU_old_vect_routine);
if(status != NU_SUCCESS)
{
return NU_FALSE;
}
// #endif
// create the HISR for receiving packets from the Ethernet card
status = NU_Allocate_Memory (&System_Memory, &pointer, 1024, NU_NO_SUSPEND);
if (status != NU_SUCCESS)
{
return NU_FALSE;
}
status = NU_Create_HISR (&NetControllerHisr, "NetCtlr",
NetCtlrHisr, 1, pointer, 1024);
if (status != NU_SUCCESS)
{
return NU_FALSE;
}
// step9, clear IMR of CPU and let interrupt work.
SetIntRt();
return (NU_SUCCESS);
} /* end NU_Etopen routine */
void Write_Printer(unsigned char dat)
{
outportb(PDPRADD,dat);
}
void Test_Printer()
{
outportb(PCPRADD,0x08); //init printer
while(1)
{
Write_Printer(0x55); //write data to port
wait(3);
Write_Printer(0xAA);
wait(3);
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -