📄 drv8139.c
字号:
}
else
TxHdrFreeHead = tx_hdr->next;
intRaise(V_LAN);
//Write destination and source address to the header.
for (i = 0; i < 6; ++i)
{
tx_hdr->daddr.byte[i] = hwa_p[i];
tx_hdr->saddr.byte[i] = SelfAddr[i];
}
//Write type to header, after switching to network order.
tx_hdr->type = htons(type);
//Save address of message block triplet in transmit header, along
//with total number of descriptors needed to transmit frame.
tx_hdr->msg_ptr = msgBlk;
tx_hdr->NoRetFlag = 0;
tx_hdr->len = len;
//Put this transmit header at the end of the queued message list.
tx_hdr->next = NULL;
intClear(V_LAN);
if (TxHdrOutHead == NULL)
TxHdrOutHead = TxHdrOutTail = tx_hdr;
else
{
TxHdrOutTail->next = tx_hdr;
TxHdrOutTail = tx_hdr;
}
//intRESTORE_IEN(ien);
intRaise(V_LAN);
//Try to keep the transmit buffer descriptors full.
TxFillDesc();
return 0;
}
/****************************************************************************
* function name: ni_isr
* design date:?2001-5-8,
* function description: Interrupt service routine
* call: ni_poll
* called: tmIntInit
* input parameter: no
* output parameter: no
* return value: 0
* change record: no
*****************************************************************************/
static void ni_isr(void)
{
#pragma TCS_handler
//DP8139("go in ni_isr\n");
//pSOS interrupt service routine entry routine.
ienter();
AppModel_run_on_sstack((Pointer)ni_poll, Null);
//pSOS interrupt service routine exit routine.
ireturn();
}
/****************************************************************************
* function name: ni_poll
* design date:?2001-5-8,
* function description: Check for and process interrupt events
* call: TxFillDesc,ni_init,SendArpPacket,SendNetCheckMsg,RxBufRcv,IoWriteReg16
* called: ni_isr
* input parameter: no
* output parameter: no
* return value: 0
* change record: no
*****************************************************************************/
static void ni_poll(void)
{
USHORT isrValue;
int i;
//While there is an interrupt pending, service it.
// for (;;)
{
//Read interrupt status register and break if none set.
isrValue = IoReadReg16(ISR);
//Clear ISR so that new events continue to generate interrupts.
IoWriteReg16(ISR, isrValue);
if(!(isrValue & (ISR_NIS|ISR_AIS)))
{
//_dp("isrValue = %d, break out of ni_poll\n", isrValue);
DP(("[ni_poll]isrValue = 0x%x, break out of ni_poll\n", isrValue)) ;
// break;
}
// printf("[ni_poll]isrValue = 0x%x.\n", isrValue) ;
if(isrValue & 0x807a) //ISR_AIS)
{
enet_ais++;
if(isrValue & ISR_SERR) //System error
{
int command = LAN_DS_MA | LAN_DS_RTA | LAN_DS_SERR; //new
DP(("------[ni_poll] System error!\n")) ;
command &= PciRdCfg16(CF_STATUS);
PciWrCfg16(CF_STATUS, command);
enet_serr++;
if(enet_serr % 100 == 0)
_dp("ni_poll: System error, enet_serr = %d, enet_rok = %d\n", enet_serr, enet_rok);
}
//If transmit errors, detach buffers.
if(isrValue & ISR_TER)
{
DP(("------[ni_poll] transmit errors!\n")) ;
enet_ter++;
TxFillDesc();
if(enet_ter % 10 == 0)
_dp("ni_poll: transmit error, enet_ter = %d, enet_tok = %d\n", enet_ter, enet_tok);
}
//if link change
if(isrValue & ISR_LNKCHG)
{
DP(("------[ni_poll] link change!\n")) ;
ni_init();
SendArpPacket(DefGateWay);
SendArpPacket(LanIPaddr);
//SendArpPacket();
}
// Check if receive error.
if(isrValue & ISR_RER)
{
DP(("------[ni_poll] receive error!\n")) ;
enet_rer++;
ni_init();
if(enet_rer % 10 == 0)
_dp("ni_poll: receive error, enet_rer = %d, enet_rok = %d\n", enet_rer, enet_rok);
}
if(isrValue & (ISR_FOVW| ISR_RXOVW))
{
if(isrValue & ISR_FOVW)
{
DP(("------[ni_poll] receive fifo overflow!\n")) ;
enet_fovw++;
if(enet_fovw % 10 == 0)
_dp("ni_poll: rx overflow, enet_fovw = %d, enet_rok = %d\n", enet_fovw, enet_rok);
}
if(isrValue & ISR_RXOVW)
{
DP(("------[ni_poll] receive buffer overflow!\n")) ;
enet_rxovw++;
RxOffset = IoReadReg16(CBR) % (RX_BUF_SIZE - 16);
RxOffset = (RxOffset + 3) & ~3;
IoWriteReg16(CAPR, RxOffset - 16);
if(enet_rxovw % 10 == 0)
_dp("ni_poll: rx overflow, enet_rxovw = %d, enet_rok = %d\n", enet_rxovw, enet_rok);
}
IoWriteReg16(ISR, 1);
}
}
//Check for Normal Interrupt Summary.
if(isrValue & 0x5)//ISR_NIS)
{
enet_nis++;
//If normal receive interrupt occurred, receive packets.
if(isrValue & 0x1)//ISR_ROK)
{
enet_rok++;
if(bFirst == 1)
{
bFirst = 0;
bLanCheck = 1;
//SendNetCheckMsg();
}
RxBufRcv();
//_dp("ni_poll: receive OK\n");
}
//If normal transmit interrupt occurred, recover headers.
if(isrValue & 0x4)//ISR_TOK)
{
enet_tok++;
TxFillDesc();
//_dp("ni_poll: transmit OK\n");
}
}
//zzm [2006-2-22]
}
}
/****************************************************************************
* function name: ni_pna_init
* design date:?2001-5-8,
* function description: Called from ni_ioctl() to tell driver that pNA has
* re/initialized.This driver needs to be sure that any
* mblks still being used by the transmitter are NOT
* returned to the mblk pool. This is because pna has just
* re/initialize the mblk pool and if the driver did a
* freemsg on those mblks still in the command queue
* the result would be those mblks would show up twice
* in the free list!
* call: no
* called: ni_ioctl
* input parameter: no
* output parameter: no
* return value: 0
* change record: no
*****************************************************************************/
static void ni_pna_init(void)
{
LAN_TX_HDR *tx_hdr;
Bool ien;
intClear(V_LAN);
//If there are any frames waiting to be put into the transmit
//descriptor ring flag them so they will not be returned.
tx_hdr = TxHdrOutHead;
while (tx_hdr != NULL)
{
tx_hdr->NoRetFlag = 1;
tx_hdr = tx_hdr->next;
}
intRaise(V_LAN);
}
/****************************************************************************
* function name: NiLan
* design date:?2001-5-8,
* function description: Main function interface between pNA+ and the NI
* call: LanPciInit,enable_tm_sdram_access_ie,ni_init,MakeArpPacket,
* SendArpPacket,ni_send,ni_ioctl
* called: pNA+
* input parameter: function = function code of the function to execute
* p = pointer to parameter block set up by pNA+
* output parameter: no
* return value: Varies with function -- see function headers
* change record: no
*****************************************************************************/
long NiLan(ULONG function, union nientry *p)
{
long rc = 0;
switch(function)
{
case NI_INIT:
LanPciInit();
enable_tm_sdram_access_ie();
//Save global interface number and function pointers.
Announce = p->niinit.ap_addr;
IfNum = p->niinit.if_num;
NiFuncs = *(p->niinit.funcs);
rc = ni_init();
MakeArpPacket();
SendArpPacket(DefGateWay);
SendArpPacket(LanIPaddr);
DP8139("sendarppacket1\n");
/*
SendArpPacket();
DP8139("sendarppacket2\n");
SendArpPacket();
DP8139("sendarppacket3\n");
SendArpPacket();
DP8139("sendarppacket4\n");
*/
break;
case NI_GETPKB:
case NI_RETPKB:
rc = -1;
break;
case NI_SEND:
++OutUcastPkts;
OutOctets += p->nisend.count + 18;
rc = ni_send(p->nisend.hwa_ptr, p->nisend.buff_addr,
(USHORT)p->nisend.count, (USHORT)p->nisend.type);
break;
case NI_POLL:
ni_poll();
break;
case NI_BROADCAST:
++outnucastpkts;
OutOctets += p->nibrdcast.count + 18;
ni_send("\xFF\xFF\xFF\xFF\xFF\xFF", p->nibrdcast.buff_addr,
(USHORT)p->nibrdcast.count, (USHORT)p->nibrdcast.type);
break;
case NI_IOCTL:
rc = ni_ioctl(p->niioctl.cmd, p->niioctl.arg);
break;
default:
rc = EINVALID;
break;
}
return (rc);
}
BOOL get_netstatus()
{
unsigned char n;
n = IoReadReg8(MSR);
n &= 4;
if(n)
return FALSE;
return TRUE;
//IoReadReg16(DIS);
//return IoReadReg8(MSR);
}
/****************************************************************************
* function name: ni_ioctl
* design date:?2001-5-8,
* function description: IOCTL call of the NiLan,The descriptions in quotes
* below come from rfc1213
* call: ni_pna_init
* called: NiLan
* input parameter: cmd = MIB-II or SNMP command
* output parameter: mib_ifreq structure return through *arg
* return value: 0, EINVALID (cmd invalid), or -1.
* change record: no
*****************************************************************************/
static ULONG ni_ioctl(long cmd, long *arg)
{
struct mib_ifreq *ifrp = (struct mib_ifreq *) arg;
//Determine the requested command and perform the request.
//printf("[ni_ioctl]: default cmd[0x%x].\n", cmd) ;
switch((ULONG)cmd)
{
//pNA+ re/initialize
case SIOCPSOSINIT:
ni_pna_init();
break;
//Inform NI of IP address change :: No action required
case SIOCSIFADDR:
break ;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -