📄 lan8xx.c
字号:
splx(old_level);
}
}
/***********************************************************************/
/* ni_init: Initialize the network interface. */
/* */
/* INPUTS: ap_addr: pNA+'s announce packet entry point. */
/* if_num: interface number */
/* funcs: pointer to pNA memory mgmnt functions */
/* RETURNS: Pointer to hardware address of NI, or -1 if failure */
/* */
/***********************************************************************/
static long ni_init(long (*ap_addr)(ULONG, char *, ULONG, ULONG, char *,
char *), long if_num, struct ni_funcs *funcs)
{
extern long ifadminstatus;
UINT i;
/*---------------------------------------------------------------------*/
/* Assign input parameters to global variables. */
/*---------------------------------------------------------------------*/
Announce = ap_addr;
If_Num = if_num;
Ni_funcs = *funcs;
/*---------------------------------------------------------------------*/
/* Arrest all Ethernet activity and initialize the receive buffers and */
/* transmit headers. */
/*---------------------------------------------------------------------*/
LanStop();
InitBuffers();
/*---------------------------------------------------------------------*/
/* Allocate Dual Ported RAM for the Receive Buffer Descriptors. */
/*---------------------------------------------------------------------*/
RxUsedPtr = RxNewPtr = RxFirstBdPtr = (BuffDescType *)
dpram_alloc(LAN_PORT, BD_SCC_RX_BDS * sizeof(BuffDescType));
RxLastBdPtr = RxFirstBdPtr + BD_SCC_RX_BDS - 1;
if(RxFirstBdPtr == (BuffDescType *)0)
return -1;
/*---------------------------------------------------------------------*/
/* Clear the Receive Buffer Descriptors. */
/*---------------------------------------------------------------------*/
for (i = 0; i < BD_SCC_RX_BDS; i++)
{
(RxFirstBdPtr + i)->status = 0;
(RxFirstBdPtr + i)->length = 0;
(RxFirstBdPtr + i)->address = NULL;
}
RxLastBdPtr->status = WRAP;
AssignRxBuffers();
/*---------------------------------------------------------------------*/
/* Allocate Dual Ported RAM for the Transmit Buffer Descriptors. */
/*---------------------------------------------------------------------*/
TxUsedPtr = TxNewPtr = TxFirstBdPtr = (BuffDescType *)
dpram_alloc(LAN_PORT, NrTxBds * sizeof(BuffDescType));
if(TxFirstBdPtr == (BuffDescType *)0)
return -1;
/*---------------------------------------------------------------------*/
/* Clear the Transmit Buffer Descriptors. */
/*---------------------------------------------------------------------*/
TxLastBdPtr = TxFirstBdPtr + NrTxBds - 1;
for (i = 0; i < NrTxBds; i++)
{
(TxFirstBdPtr + i)->status = 0;
(TxFirstBdPtr + i)->length = 0;
(TxFirstBdPtr + i)->address = NULL;
}
TxLastBdPtr->status = WRAP;
TxFreeBDs = NrTxBds;
/*---------------------------------------------------------------------*/
/* Initialize the interrupt vector, and the pSOS and ISR state flags. */
/*---------------------------------------------------------------------*/
#if (BD_HAS_SLAVE == 1)
IsrAddHandler(V_SCC1, (void*)ni_isr, (void *)V_SCC1);
#else /* BD_HAS_SLAVE */
IsrAddHandler(V_SCC1, (void *)ni_isr, (void *)V_SCC1);
#endif /* BD_HAS_SLAVE */
pSOS_Is_Up = FALSE;
/*---------------------------------------------------------------------*/
/* Get the Ethernet Address. This is set in bpdialog.c. */
/*---------------------------------------------------------------------*/
for (i = 0; i < 6; ++i)
OurAddress.byte[i] = EthernetAddress[i];
/*---------------------------------------------------------------------*/
/* Initialize MIB variables. */
/*---------------------------------------------------------------------*/
clear(&MG_stat, sizeof(MG_stat));
MG_stat.ifDescr = "Motorola PowerQUICC SCC1";
#if ((BSP_LAN1_FLAGS) & (IFF_MULTICAST))
/*-----------------------------------------------------------------*/
/* Clear the multicast address table. */
/*-----------------------------------------------------------------*/
lan_mcast.num_used = 0;
#endif
ifadminstatus = 1;
/*---------------------------------------------------------------------*/
/* Initialize SCC1 in Ethernet mode. */
/*---------------------------------------------------------------------*/
InitSCC1();
/*---------------------------------------------------------------------*/
/* No errors if we got here, so return pointer to Ethernet address. */
/*---------------------------------------------------------------------*/
return (long)&OurAddress;
}
/***********************************************************************/
/* ReturnBuffer: Return a receive buffer to the free list */
/* */
/* INPUTS: buf_ptr: Pointer to the buffer being returned */
/* */
/***********************************************************************/
static void ReturnBuffer(RX_BUFF *buf_ptr)
{
ULONG old_level;
/*---------------------------------------------------------------------*/
/* Link returned envelope to the envelope previously at the top of the */
/* free queue and point "free_head" to the newly returned envelope. */
/*---------------------------------------------------------------------*/
old_level = splx(MAX_ILEV);
buf_ptr->next = RxbFreeHead;
RxbFreeHead = buf_ptr;
splx(old_level);
AssignRxBuffers();
}
/***********************************************************************/
/* ni_send: Send a packet to another node. */
/* */
/* INPUTS: hwa_ptr = pointer to the destination hardware address */
/* pkb_ptr = pointer to packet (msg block triplet) */
/* size = number of bytes in packet buffer */
/* type = flag indicating either IP, ARP, or RARP */
/* */
/***********************************************************************/
/* static */
void ni_send(char *hwa_ptr, char *pkb_ptr, USHORT size,
USHORT type)
{
mblk_t *m, *tmp, *m_prev;
ULONG old_level;
UINT NrBDs, FrameLength;
TX_HDR *TxhPtr;
int i, length;
int copy_size;
UCHAR *src;
BuffDescType *FirstBdPtr;
BuffDescType *PrevBdPtr=NULL; /* 必须检查pkt_ptr不为NULL,否则有可能出错*/
ReclaimTxFrames();
m = (mblk_t *)pkb_ptr;
if(m==NULL){
return; /* An error or bug */
}
/*---------------------------------------------------------------------*/
/* Obtain a transmit header from the free list. If there are none */
/* available, we can't send the packet. Just return the triplet. */
/*---------------------------------------------------------------------*/
old_level = splx(MAX_ILEV);
if ((TxhPtr = TxhFreeHead) == NULL)
{
outdiscards++;
splx(old_level);
Ni_funcs.freemsg(m);
return;
}
else
TxhFreeHead = TxhPtr->next;
splx(old_level);
/*---------------------------------------------------------------------*/
/* Write destination and source address, type, and size to the header. */
/*---------------------------------------------------------------------*/
for (i = 0; i < 6; i++)
TxhPtr->daddr.byte[i] = *hwa_ptr++;
TxhPtr->saddr.word1 = OurAddress.word1;
TxhPtr->saddr.word2 = OurAddress.word2;
TxhPtr->saddr.word3 = OurAddress.word3;
TxhPtr->type = type;
TxhPtr->msg_ptr = m;
TxhPtr->size = size;
/*---------------------------------------------------------------------*/
/* If there are not at least three BDs queue the frame for later */
/* transmission. */
/*---------------------------------------------------------------------*/
old_level = splx(MAX_ILEV);
if (TxFreeBDs < 3)
{
Postponed++;
TxhPtr->next = NULL;
if (TxhOutHead == NULL)
TxhOutHead = TxhOutTail = TxhPtr;
else
{
TxhOutTail->next = TxhPtr;
TxhOutTail = TxhPtr;
}
splx(old_level);
return;
}
/*---------------------------------------------------------------------*/
/* If there is one or more elements on the transmit queue, and the new */
/* frame to the end of the queue. Then remove the head of the queue */
/* and try to transmit it. */
/*---------------------------------------------------------------------*/
if (TxhOutHead != NULL)
{
TxhPtr->next = NULL;
TxhOutTail->next = TxhPtr;
TxhOutTail = TxhPtr;
TxhPtr = TxhOutHead;
TxhOutHead = TxhPtr->next;
/*-----------------------------------------------------------------*/
/* There was at least one element on the queue and we added */
/* another. So, there are at least two queue elements. Which means */
/* we can skip the normal check of the head becoming null. */
/*-----------------------------------------------------------------*/
}
TxhPtr->next = NULL;
FirstBdPtr = TxNewPtr;
/*---------------------------------------------------------------------*/
/* Add the transmit header to the BD list. Don't set the READY bit */
/* until all BDs for this frame have been added. */
/*---------------------------------------------------------------------*/
TxNewPtr->address = TxhPtr;
TxNewPtr->length = 14;
if (TxNewPtr == TxLastBdPtr)
TxNewPtr->status = (USHORT)WRAP | PAD | TX_CRC;
else
TxNewPtr->status = PAD | TX_CRC;
IncTxBDptr(TxNewPtr);
#if (BRD_DCACHE == YES) && (BRD_DCACHE_WRITE_THRU == NO)
FlushDcache();
#endif
TxFreeBDs--;
FrameLength = 14;
NrBDs = 1;
/*---------------------------------------------------------------------*/
/* Now put the buffers pointed to by the message block triplet in. If */
/* the packet is less than 64 bytes long we pad it up to 64. This is a */
/* workaround for a bug in the 68360. */
/*---------------------------------------------------------------------*/
m = TxhPtr->msg_ptr;
m_prev = m;
while (m)
{
/*-----------------------------------------------------------------*/
/* Skip all zero length elements in the mblk list, since adding a */
/* buffer of length zero to the BD pool is bad. Free the zero */
/* length element and "close" the hole in the chain. */
/*-----------------------------------------------------------------*/
length = m->b_wptr - m->b_rptr;
if (length == 0)
{
m_prev->b_cont = m->b_cont;
m->b_cont = NULL;
Ni_funcs.freemsg(m);
m = m_prev->b_cont;
continue;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -