📄 dp83815.c
字号:
MLB: 0 MAC Loopback
ATP: 1 Automatic Transmit Padding
IFG: 00 Interframe Gap Time
n/a: 00 Reserved
ECRETRY: 1 Excessive Collision Retry Enable
MXDMA: 100 Max DMA burst size (32 bytes)
n/a: 000000 Unused
FLTH: 000010 Tx Fill Threshold ( (2x32)=64 bytes)
n/a: 00 Unused
DRTH: 110000 Tx Drain Threshold ((48x32)=1536 bytes)*/
DPDelay(1);
// Configure Rx register
DPWriteLong( DP_OPS_RXCFG, DP_allbits, 0x00500008 );
/* This one write breaks out like this: (MSB down to LSB)
AEP: 0 Accept Errored Packets
ARP: 0 Accept Runt Packets
n/a: 0 Unused bits
ATX: 0 Accept Transmit Packet (immediate loopback)
ALP: 0 Accept Long Packets
n/a: 0 Another unused bit
n/a: 000 Still more unused bits
MXDMA: 101 Max DMA Burst Size (64 bytes)
n/a: 00000000000000 Anybody wanna bit?
DRTH: 00100 Rx Drain Threshold ((8x8bytes)=64bytes)
n/a: 0 Come on...anybody? */
DPDelay( 1 );
DPWriteLong(DP_OPS_IMR,DP_allbits,0x0); // mask all interrupts
DPModifyLong(DP_OPS_CR,DP_OPS_cr_RXR,DP_OPS_cr_RXR); // Reset the receiver. Write only the Rx reset bit.
while(!(dwScrap=DPReadLong(DP_OPS_ISR,DP_OPS_isr_RXRCMP))) // this tells us when Rx reset is complete and also clears the ISR.
{
PRINTF (1, ("DP83815: Waiting for Receiver reset\r\n"));
DPDelay(100);
}
// Receive Filter: set to receive All Broadcast, Perfect match, all ARP (for now).
DPWriteLong( DP_OPS_RFCR,DP_allbits ,(DP_OPS_rfcr_RFEN
|DP_OPS_rfcr_AAB
//|DP_OPS_rfcr_AAM
|DP_OPS_rfcr_APM
//|DP_OPS_rfcr_AAU
|DP_OPS_rfcr_AARP
));
// Give DMA registers to controller - check that we've initialized the DMA
// buffers first.
if (!MyDP.pCurrentRxDescriptor || !MyDP.pCurrentTxDescriptor)
{
PRINTF (1, ("DP83815: Error - must call DP83815InitDMABuffer before calling DP83815Init.\r\n"));
return(FALSE);
}
// Insert current Rx and Tx pointers into DP83815 device registers
DPWriteLong(DP_OPS_RXDP,DP_OPS_rxdp_RXDP,(DWORD) TO_PHYS(MyDP.pCurrentRxDescriptor));
DPDelay(100);
DPWriteLong(DP_OPS_TXDP,DP_OPS_txdp_TXDP,(DWORD) TO_PHYS(MyDP.pCurrentTxDescriptor));
DPReadLong(DP_OPS_ISR,DP_allbits) ; // not quite sure why, but have to clear ISR before proceeding.
return TRUE;
} // DP83815Init()
////////////////////////////////////////////////////////////////////////////////
// DP83815EnableInts()
//
void
DP83815EnableInts(void)
{
PRINTF (1, ("DP83815: Enter DP83815EnableInts \r\n"));
// Enable all interrupt bits EXCEPT TXIDLE and TXOK, since we don't want to know every time we send a packet.
DPWriteLong(DP_OPS_IMR,DP_allbits,~(DP_OPS_isr_TXIDLE|DP_OPS_isr_TXOK));
DPWriteLong(DP_OPS_IER,DP_OPS_ier_IE,DP_OPS_ier_IE); // enables the INTR hardware line.
// Enable the Receiver. We don't do this in the init routine because
// the Rx FIFO may overflow if we're polling, by the time we read the
// first frame (problem seen during DHCP transactions).
//
DPModifyLong(DP_OPS_CR, DP_OPS_cr_RXE, DP_OPS_cr_RXE);
} // DP83815EnableInts()
////////////////////////////////////////////////////////////////////////////////
// DP83815DisableInts()
//
void
DP83815DisableInts(void)
{
PRINTF (1, ("DP83815: Enter DP83815DisableInts \r\n"));
DPWriteLong(DP_OPS_IER,DP_OPS_ier_IE,0); // disables the INTR hardware line.
//return TRUE;
} // DP83815DisableInts()
////////////////////////////////////////////////////////////////////////////////
// DP83815GetFrame()
// Fill up pbData with the next availabe packet in the RX FIFO.
// Return 0 if you have no waiting frames, return 1 if you do.
//
UINT16
DP83815GetFrame(BYTE *pbData, UINT16 *pwLength)
{
BOOL MoreDescInThisPacket= FALSE;
int retval=0;
//int Scrap;
BYTE* pbCallerBuffer=pbData;
DWORD BuffLen,TotalBuffLen=0;
// Enable the Receiver. We don't do this in the init routine because
// the Rx FIFO may overflow if we're polling, by the time we read the
// first frame (problem seen during DHCP transactions).
//
DPModifyLong(DP_OPS_CR, DP_OPS_cr_RXE, DP_OPS_cr_RXE);
// see if current descriptor belongs to me and that there were no errors in receiving it
// and that MORE is clear.
// KITL doesn't call GetPendingInts to clear the interrupt at the card
// therefore we need to do it here.
//
DPReadLong(DP_OPS_ISR,DP_allbits);
do
{
if(!(MyDP.pCurrentRxDescriptor->cmdsts&DP83815_cmdsts_OWN)) //This descriptor's buffer is empty.
goto GFExit;
retval=1;
// so we have a descriptor that we own. Copy the buffer into pbData
BuffLen=MyDP.pCurrentRxDescriptor->cmdsts&DP83815_cmdsts_SIZE;
MoreDescInThisPacket=(BOOL)MyDP.pCurrentRxDescriptor->cmdsts&DP83815_cmdsts_MORE;
TotalBuffLen+=BuffLen;
memcpy((VOID *)pbCallerBuffer,(VOID *)TO_VIRT(MyDP.pCurrentRxDescriptor->bufptr),BuffLen);
// copy total length of packet into pwLength
*pwLength=(UINT16)TotalBuffLen;
pbCallerBuffer+=BuffLen; // now we advance the pointer to the end of what we just copied
// in case we need to put more there later. (if cmdsts MORE bit is set)
// reset the descriptor to default values.
MyDP.pCurrentRxDescriptor->cmdsts = ((BUFFSIZE & DP83815_cmdsts_SIZE)|DP83815_cmdsts_MORE); // reset the buffer size to BUFFSIZE and set MORE bit.
MyDP.pCurrentRxDescriptor=(pDP83815FrameDescriptor)TO_VIRT(MyDP.pCurrentRxDescriptor->link); // seek to the next descriptor.
} while(MoreDescInThisPacket);
// Okay - we include the packet CRC in our buffer that's passed up. We
// have the space for it, but a max packet that also includes the CRC
// will be filtered by NDIS, so we need to reduce the reported buffer
// size by 4 bytes.
*pwLength -= sizeof(ULONG);
if (DPReadLong(DP_OPS_ISR,DP_OPS_isr_RXIDLE))
DPModifyLong(DP_OPS_CR,DP_OPS_cr_RXE,DP_OPS_cr_RXE); // turn on the receiver.
if(MyDP.pCurrentRxDescriptor->cmdsts&DP83815_cmdsts_OWN) // If the next descriptor is also ready....
{
DPModifyLong(DP_OPS_CR,DP_OPS_cr_SWI,DP_OPS_cr_SWI); // we'd better ask for another interrupt (polling mode OK too).
}
GFExit:
return retval;
} // DP83815GetFrame()
////////////////////////////////////////////////////////////////////////////////
// DP83815SendFrame()
// This routine should be called with a pointer to the ethernet frame data.
// It is the caller's responsibility to fill in all information including
// the destination and source addresses and the frame type.
// The length parameter gives the number of bytes in the ethernet frame.
// The routine will return immediately regardless of whether transmission
// has successfully been performed.
//
UINT16
DP83815SendFrame(BYTE *pbData, DWORD dwLength)
{
pDP83815FrameDescriptor Cruiser=MyDP.pCurrentTxDescriptor;
if (dwLength > BUFFSIZE) // Uh-oh, this packet size exceeds our buffer size.
{
PRINTF (1, ("DP83815: Can't handle packet of 0x%x bytes. BUFFSIZE too small? Spin Forever. \r\n",dwLength));
while(1);
}
while((Cruiser->cmdsts)&DP83815_cmdsts_OWN) // This loop executes until we find an unused descriptor.
{
Cruiser=(pDP83815FrameDescriptor)TO_VIRT(Cruiser->link); // go to the next descriptor.
if(Cruiser==MyDP.pCurrentTxDescriptor) // we have traversed the entire descriptor ring and all of them are in use.
{
// Lets see if we are idle for some reason.
PRINTF (1, ("DP83815: Checking to see if TXIDLE is set.\r\n"));
if( DPReadLong(DP_OPS_ISR, DP_OPS_isr_TXIDLE)) // the Tx state machine is idle, which is goofy since if we got
// here there is a Tx descriptor that is OWNed by the Tx state machine.
{
PRINTF (1, ("DP83815: TXIDLE was set. Now resetting TXE.\r\n"));
DPModifyLong(DP_OPS_CR, DP_OPS_cr_TXE, DP_OPS_cr_TXE); // Re-enable the Tx state machine.
Cruiser=(pDP83815FrameDescriptor)TO_VIRT(Cruiser->link); // move the the next descriptor and lets try again.
} // end if(Tx state machine is idle)
} // end if(we have traversed the entire ring)
} // end while(the current descriptor is in use.)
// We have found an unused descriptor
MyDP.pCurrentTxDescriptor=Cruiser; //Cruiser is now pointing to the next available descriptor.
MyDP.pCurrentTxDescriptor->cmdsts &= ~(DP83815_cmdsts_SIZE|DP83815_cmdsts_MORE); // clear the buffer size bits and the MORE bit in this descriptor.
memcpy( (void *) TO_VIRT(MyDP.pCurrentTxDescriptor->bufptr), (void *)pbData, dwLength ); // copy the packet data into the descriptor buffer.
MyDP.pCurrentTxDescriptor->cmdsts |= ((dwLength & DP83815_cmdsts_SIZE)|DP83815_cmdsts_OWN); // then stuff descriptor with the size of this data packet and turn on the OWN bit.
MyDP.pCurrentTxDescriptor=(pDP83815FrameDescriptor)TO_VIRT(MyDP.pCurrentTxDescriptor->link); // get set for the next SendPacket request.
DPModifyLong(DP_OPS_CR, DP_OPS_cr_TXE, DP_OPS_cr_TXE); // Enable Tx state machine.
return 0x00;
} // DP83815SendFrame()
////////////////////////////////////////////////////////////////////////////////
// DP83815GetPendingInts()
// EDBG only cares about INTR_TYPE_RX, we handle all others internally.
//
DWORD
DP83815GetPendingInts(void)
{
DWORD dwCurInts;
//PRINTF (1, ("DP83815: GetPendingInts() entered.\r\n"));
dwCurInts=DPReadLong(DP_OPS_ISR,DP_allbits);
if(dwCurInts&DP_OPS_isr_RXOK)
return INTR_TYPE_RX;
if(dwCurInts&DP_OPS_isr_SWI)
return INTR_TYPE_RX;
if(dwCurInts&DP_OPS_isr_TXERR)
{
PRINTF (1, ("DP83815: Tx error detected. Ignoring.\r\n"));
dwCurInts &= ~DP_OPS_isr_TXERR; // clear the TXERR bit in our copy.
}
if(dwCurInts&DP_OPS_isr_RXERR)
{
PRINTF (1, ("DP83815: Rx error detected. Ignoring.\r\n"));
dwCurInts &= ~DP_OPS_isr_RXERR; // clear the RXERR bit in our copy.
}
if(dwCurInts)
{
PRINTF (1, ("DP83815: Other interrupt types detected. ISR=0x%x Ignoring.\r\n",dwCurInts));
}
return 0;
} // DP83815GetPendingInts()
////////////////////////////////////////////////////////////////////////////////
// DP83815ReadEEPROM()
//
BOOL
DP83815ReadEEPROM(UINT16 uiEEPROMAddress , UINT16 *pwVal)
{
PRINTF (1, ("DP83815ReadEEPROM not implemented..\r\n"));
return FALSE;
} // DP83815ReadEEPROM()
////////////////////////////////////////////////////////////////////////////////
// DP83815WriteEEPROM()
//
BOOL
DP83815WriteEEPROM(UINT16 uiEEPROMAddress, UINT16 uiData)
{
PRINTF (1, ("DP83815WriteEEPROM not implemented..\r\n"));
return FALSE;
} // DP83815WriteEEPROM()
////////////////////////////////////////////////////////////////////////////////
// DP83815SetOptions()
//
DWORD
DP83815SetOptions(DWORD dwOptions)
{
if(dwOptions==OPT_BROADCAST_FILTERING)
{
PRINTF (1, ("DP83815: Setting receive filter to Perfect Match and ARP only.\r\n"));
// Receive Filter: set to receive only Perfect match and all ARP .
DPWriteLong( DP_OPS_RFCR,DP_allbits ,(DP_OPS_rfcr_RFEN
//|DP_OPS_rfcr_AAB
//|DP_OPS_rfcr_AAM
|DP_OPS_rfcr_APM
//|DP_OPS_rfcr_AAU
|DP_OPS_rfcr_AARP
));
}
return 0x00;
} // DP83815SetOptions()
////////////////////////////////////////////////////////////////////////////////
// DP83815ReadMacAddr()
//
BOOL
DP83815ReadMacAddr(USHORT MacAddr[3])
{
//USHORT usData;
DPWriteLong(DP_OPS_RFCR,DP_allbits,0x00000000); // set all filters off, and point RFADDR at PMATCH octets 1-0
MacAddr[0]=(USHORT)DPReadLong(DP_OPS_RFDR, DP_OPS_rfdr_RFDATA);// read the first two octets.
DPWriteLong(DP_OPS_RFCR,DP_OPS_rfcr_RFADDR,0x00000002); // set all filters off, and point RFADDR at PMATCH octets 3-2
MacAddr[1]=(USHORT)DPReadLong(DP_OPS_RFDR, DP_OPS_rfdr_RFDATA);// read the second two octets.
DPWriteLong(DP_OPS_RFCR,DP_OPS_rfcr_RFADDR,0x00000004); // set all filters off, and point RFADDR at PMATCH octets 5-4
MacAddr[2]=(USHORT)DPReadLong(DP_OPS_RFDR, DP_OPS_rfdr_RFDATA);// read the third two octets.
return TRUE;
} // end DP83815ReadMacAddr()
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -