?? dec21140.c
字號:
/*-----------------------------------------------------------------*/
/* Set tx_hdr to the transmit header associated with the frame, */
/* and return the message block triplet. */
/*-----------------------------------------------------------------*/
tx_hdr = TxUsedBD->buffAddr1;
if (tx_hdr->NoRetFlag == 0)
NiFuncs.freemsg(tx_hdr->msg_ptr);
/*-----------------------------------------------------------------*/
/* Advance TxUsedBD to next descriptor following this frame. */
/*-----------------------------------------------------------------*/
for (i = 0; i < tx_hdr->num_desc; ++i)
{
TxUsedBD->buffAddr1 = NULL;
TxUsedBD->status = NULL;
TxUsedBD->ctrlNsize = LAN_XMTD_TCH;
COPYBACK((void *)TxUsedBD, 1);
TxUsedBD = TxUsedBD->nextDesc;
++TxFreeDesc;
}
/*-----------------------------------------------------------------*/
/* Finally, return the transmit header to the free list. */
/*-----------------------------------------------------------------*/
tx_hdr->next = TxHdrFreeHead;
TxHdrFreeHead = tx_hdr;
/*-----------------------------------------------------------------*/
/* Here's a window for interrupts */
/*-----------------------------------------------------------------*/
intRESTORE_IEN(ien);
ien = intCLEAR_IEN();
}
intRESTORE_IEN(ien);
}
/***********************************************************************/
/* TxFillDesc: Move from outgoing queue to transmit descriptor ring */
/* */
/* OUTPUTS: TxUsedBD is updated */
/* */
/***********************************************************************/
static void TxFillDesc(void)
{
LAN_BUFF_DESC *first_desc;
LAN_TX_HDR *tx_hdr;
mblk_t *msgBlk;
ULONG length, frameLen;
Bool ien;
if (FlushFlag) return;
/*-------------------------------------------------------------------*/
/* Free up some descriptors if possible. */
/*-------------------------------------------------------------------*/
TxBufDetach();
for (;;)
{
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
ien = intCLEAR_IEN();
/*-----------------------------------------------------------------*/
/* If no messages queued or not enough descriptors available for */
/* the first queued frame, we can't do anything. */
/*-----------------------------------------------------------------*/
if ((TxHdrOutHead == NULL) || (TxFreeDesc < TxHdrOutHead->num_desc))
break;
/*-----------------------------------------------------------------*/
/* Extract first message. */
/*-----------------------------------------------------------------*/
tx_hdr = TxHdrOutHead;
TxHdrOutHead = TxHdrOutHead->next;
/*-----------------------------------------------------------------*/
/* Fill first transmit descriptor. We save a pointer to this */
/* buffer descriptor and we don't give ownership to the MAC for */
/* this first descriptor until after all the other descriptors for */
/* this frame are set up. */
/*-----------------------------------------------------------------*/
first_desc = TxNewBD;
TxBufAttach((void *)tx_hdr, 14, LAN_XMTD_FS, 0);
frameLen = 14;
/*-----------------------------------------------------------------*/
/* Now add buffers pointed to by message block triplet. */
/*-----------------------------------------------------------------*/
msgBlk = tx_hdr->msg_ptr;
while (msgBlk)
{
length = msgBlk->b_wptr - msgBlk->b_rptr;
frameLen += length;
/*---------------------------------------------------------------*/
/* Interrupt bit is set only for last descriptor in frame. */
/*---------------------------------------------------------------*/
if (msgBlk->b_cont)
{
TxBufAttach(msgBlk->b_rptr, length, 0, MAC_OWNS_DESC);
}
else
{
if (frameLen < 64)
length += (64 - frameLen);
TxBufAttach(msgBlk->b_rptr, length, LAN_XMTD_IC | LAN_XMTD_LS,
MAC_OWNS_DESC);
}
msgBlk = msgBlk->b_cont;
}
/*-----------------------------------------------------------------*/
/* Give descriptor to MAC and request transmission. */
/*-----------------------------------------------------------------*/
first_desc->status = MAC_OWNS_DESC;
COPYBACK((void *)first_desc, 1);
ioLongWrite(CSR1, 1);
/*-----------------------------------------------------------------*/
/*-----------------------------------------------------------------*/
intRESTORE_IEN(ien);
}
intRESTORE_IEN(ien);
}
/***********************************************************************/
/* bzero: Zero memory at specified address */
/* */
/***********************************************************************/
static void bzero(UCHAR *ptr, int length)
{
while (length--)
*ptr++ = 0;
}
static struct ether_addr
{
ULONG word_1; /* first 2 bytes of address in least sig 16-bits */
ULONG word_2; /* next 2 bytes of address in least sig 16-bits */
ULONG word_3; /* last 2 bytes of ethernet in least sig 16-bits */
} EtherBlock[16];
static struct eth_other
{
UCHAR count; /* open count */
UCHAR next; /* index of next free address slot */
} EtherOther[16];
static ULONG EtherAddrNum;
static ULONG EtherAddrEmpty;
/***********************************************************************/
static void lan_addr_clear(void)
{
int i;
for (i = 0; i < 16; ++i)
{
EtherBlock[i].word_1 = 0xFFFF;
EtherBlock[i].word_2 = 0xFFFF;
EtherBlock[i].word_3 = 0xFFFF;
EtherOther[i].count = 0;
EtherOther[i].next = i + 1;
}
EtherOther[15].next = 0; /* points to nothing else */
EtherOther[0].count = 1; /* this one is also considered used */
EtherAddrNum = 1;
EtherAddrEmpty = 1;
}
/***********************************************************************/
static ULONG lan_add_mcast(UCHAR *addr)
{
ULONG i;
USHORT addr1, addr2, addr3;
Bool ien;
addr1 = (addr[1] << 8) | addr[0];
addr2 = (addr[3] << 8) | addr[2];
addr3 = (addr[5] << 8) | addr[4];
ien = intCLEAR_IEN();
/* If the address is already in the list, merely increment its counter */
for (i = 1; i < 16; ++i) /* Skip the broadcast address in slot 0 */
{
if ((addr3 == EtherBlock[i].word_3) &&
(addr2 == EtherBlock[i].word_2) &&
(addr1 == EtherBlock[i].word_1))
{
/* The address is in the list */
EtherOther[i].count++;
intRESTORE_IEN(ien);
return 0;
}
}
if (EtherAddrEmpty)
{
EtherAddrEmpty = EtherOther[EtherAddrEmpty].next;
EtherBlock[EtherAddrEmpty].word_1 = addr1;
EtherBlock[EtherAddrEmpty].word_2 = addr2;
EtherBlock[EtherAddrEmpty].word_3 = addr3;
EtherOther[EtherAddrEmpty].count = 1;
++EtherAddrNum;
intRESTORE_IEN(ien);
lan_addr_write();
return 0;
}
intRESTORE_IEN(ien);
return ENFILE;
}
/***********************************************************************/
static ULONG lan_del_mcast(UCHAR *addr)
{
ULONG i;
USHORT addr1, addr2, addr3;
Bool ien;
addr1 = (addr[1] << 8) | addr[0];
addr2 = (addr[3] << 8) | addr[2];
addr3 = (addr[5] << 8) | addr[4];
ien = intCLEAR_IEN();
/* Find the address in the list */
for (i = 1; i < 16; ++i) /* Skip the broadcast address in slot 0 */
{
if ((addr3 == EtherBlock[i].word_3) &&
(addr2 == EtherBlock[i].word_2) &&
(addr1 == EtherBlock[i].word_1))
{
/* The address is in the list. Write the broadcast pattern */
/* Into the address slot to tag it 'empty' */
if (--EtherOther[i].count == 0)
{
EtherBlock[i].word_1 = 0xFFFF;
EtherBlock[i].word_2 = 0xFFFF;
EtherBlock[i].word_3 = 0xFFFF;
EtherOther[i].next = EtherAddrEmpty;
EtherAddrEmpty = i;
--EtherAddrNum;
intRESTORE_IEN(ien);
lan_addr_write();
}
else
intRESTORE_IEN(ien);
return 0;
}
}
intRESTORE_IEN(ien);
return ENXIO;
}
/***********************************************************************/
/* enable_tm_sdram_access: */
/* */
/***********************************************************************/
static void enable_tm_sdram_access(void)
{
unsigned cfg_data;
cfg_data = pci_read_config_dword(0, 9, 0, 4);
pci_write_config_dword(0, 9, 0, 4, cfg_data | 2);
cfg_data = pci_read_config_dword(0, 9, 0, 4);
}
/***********************************************************************/
/* lan_addr_write: "Send" the setup packet to the chip */
/* */
/***********************************************************************/
static void lan_addr_write(void)
{
int command;
volatile ULONG i;
ULONG saved_csr6, saved_csr7;
/*-------------------------------------------------------------------*/
/* Stops TxFillDesc() from filling any more descriptors */
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -