?? card.c
字號:
//
PUCHAR CurBufAddress;
PUCHAR OddBufAddress;
PUCHAR XmitBufAddress;
//
// Length of each of the above buffers
//
UINT CurBufLen;
UINT PacketLength;
//
// Was the last transfer of an odd length?
//
BOOLEAN OddBufLen = FALSE;
//
// Current NDIS_BUFFER that is being copied from
//
PNDIS_BUFFER CurBuffer;
//
// Programmed I/O, have to transfer the data.
//
NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, &PacketLength);
//
// Skip 0 length copies
//
if (PacketLength == 0) {
return(TRUE);
}
//
// Get the starting buffer address
//
XmitBufAddress = (PUCHAR)Adapter->XmitStart +
Adapter->NextBufToFill*TX_BUF_SIZE;
//
// Get address and length of the first buffer in the packet
//
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
while (CurBuffer && (CurBufLen == 0)) {
NdisGetNextBuffer(CurBuffer, &CurBuffer);
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
//
// set up the card
//
{
//
// Temporary places for holding values for transferring to
// an odd aligned address on 16-bit slots.
//
UCHAR Tmp;
UCHAR Tmp1;
USHORT TmpShort;
//
// Values for waiting for noticing when a DMA completes.
//
USHORT OldAddr, NewAddr;
//
// Count of transfers to do
//
USHORT Count;
//
// Buffer to read from for odd aligned transfers
//
PUCHAR ReadBuffer;
if (!Adapter->EightBitSlot && ((ULONG_PTR)XmitBufAddress & 0x1)) {
//
// Avoid transfers to odd addresses in word mode.
//
// For odd addresses we need to read first to get the previous
// byte and then merge it with our first byte.
//
//
// Set Count and Source address
//
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0); // robin
NdisRawWritePortUchar(
Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
LSB(PtrToUlong(XmitBufAddress - 1))
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
MSB((PtrToUlong(XmitBufAddress) - 1))
);
// NE2000 PCMCIA CHANGE START
//
// NE2000 PCMCIA CHANGE!!!
//
//NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1 );
//NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
//
// Set direction (Read)
//
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
CR_START | CR_PAGE0 | CR_DMA_READ );
//
// NE2000 PCMCIA CHANGE!!!
//
//NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp1 );
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
Tmp1 = LSB(TmpShort);
// NE2000 PCMCIA CHANGE END
//
// Do Write errata as described on pages 1-143 and
// 1-144 of the 1992 LAN databook
//
//
// Set Count and destination address
//
ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
OldAddr = NewAddr = (USHORT)(ReadBuffer);
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
// CR_PAGE0 // robin
// ); // robin
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
LSB(PtrToUlong(ReadBuffer))
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
MSB(PtrToUlong(ReadBuffer))
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
//
// Set direction (Read)
//
NdisRawWritePortUchar(
Adapter->IoPAddr + NIC_COMMAND,
CR_START | CR_PAGE0 | CR_DMA_READ
);
//
// Read from port
//
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
//
// Wait for addr to change
//
TmpShort = 0xFFFF;
while (TmpShort != 0) {
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
NewAddr = Tmp;
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
NewAddr |= (Tmp << 8);
if (NewAddr != OldAddr) {
break;
}
NdisStallExecution(1);
TmpShort--;
}
if (NewAddr == OldAddr) {
NdisWriteErrorLogEntry(
Adapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
2,
cardCopyDownPacket,
(ULONG_PTR)XmitBufAddress
);
return(FALSE);
}
//
// Set Count and destination address
//
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
LSB(PtrToUlong(XmitBufAddress - 1)) );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
MSB(PtrToUlong(XmitBufAddress - 1)) );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
//
// Set direction (Write)
//
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
CR_START | CR_PAGE0 | CR_DMA_WRITE );
//
// It seems that the card stores words in LOW:HIGH order
//
NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
(USHORT)(Tmp1 | ((*CurBufAddress) << 8)) );
//
// Wait for DMA to complete
//
Count = 0xFFFF;
while (Count) {
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp1 );
if (Tmp1 & ISR_DMA_DONE) {
break;
} else {
Count--;
NdisStallExecution(4);
}
}
CurBufAddress++;
XmitBufAddress++;
PacketLength--;
CurBufLen--;
}
//
// Do Write errata as described on pages 1-143 and 1-144 of
// the 1992 LAN databook
//
//
// Set Count and destination address
//
ReadBuffer = XmitBufAddress + ((ULONG_PTR)XmitBufAddress & 1);
OldAddr = NewAddr = (USHORT)(ReadBuffer);
// NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, // robin
// CR_PAGE0 // robin
// ); // robin
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
LSB(PtrToUlong(ReadBuffer))
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
MSB(PtrToUlong(ReadBuffer))
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
0x2
);
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
0x0
);
//
// Set direction (Read)
//
NdisRawWritePortUchar(
Adapter->IoPAddr + NIC_COMMAND,
CR_START | CR_PAGE0 | CR_DMA_READ
);
if (Adapter->EightBitSlot) {
//
// Read from port
//
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
} else {
//
// Read from port
//
NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
}
//
// Wait for addr to change
//
TmpShort = 0xFFFF;
while (TmpShort != 0) {
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
NewAddr = Tmp;
NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
NewAddr |= (Tmp << 8);
if (NewAddr != OldAddr) {
break;
}
NdisStallExecution(1);
TmpShort--;
}
if (NewAddr == OldAddr) {
NdisWriteErrorLogEntry(
Adapter->MiniportAdapterHandle,
NDIS_ERROR_CODE_HARDWARE_FAILURE,
2,
cardCopyDownPacket,
(ULONG_PTR)XmitBufAddress
);
return(FALSE);
}
//
// Set Count and destination address
//
// NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 ); // robin
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
LSB(PtrToUlong(XmitBufAddress)) );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
MSB(PtrToUlong(XmitBufAddress)) );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
LSB(PacketLength) );
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
MSB(PacketLength) );
//
// Set direction (Write)
//
NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
CR_START | CR_PAGE0 | CR_DMA_WRITE );
} // setup
//
// Copy the data now
//
do {
UINT Count;
UCHAR Tmp;
//
// Write the previous byte with this one
//
if (OddBufLen) {
//
// It seems that the card stores words in LOW:HIGH order
//
NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
(USHORT)(*OddBufAddress | ((*CurBufAddress) << 8)) );
OddBufLen = FALSE;
CurBufAddress++;
CurBufLen--;
}
if (Adapter->EightBitSlot) { // byte mode
NdisRawWritePortBufferUchar(
Adapter->IoPAddr + NIC_RACK_NIC,
CurBufAddress,
CurBufLen
);
} else { // word mode
NdisRawWritePortBufferUshort(
Adapter->IoPAddr + NIC_RACK_NIC,
(PUSHORT)CurBufAddress,
(CurBufLen >> 1));
//
// Save trailing byte (if an odd lengthed transfer)
//
if (CurBufLen & 0x1) {
OddBufAddress = CurBufAddress + (CurBufLen - 1);
OddBufLen = TRUE;
}
}
//
// Wait for DMA to complete
//
Count = 0xFFFF;
while (Count) {
NdisRawReadPortUchar(
Adapter->IoPAddr + NIC_INTR_STATUS,
&Tmp );
if (Tmp & ISR_DMA_DONE) {
break;
} else {
Count--;
NdisStallExecution(4);
}
}
//
// Move to the next buffer
//
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer){
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
//
// Get address and length of the next buffer
//
while (CurBuffer && (CurBufLen == 0)) {
NdisGetNextBuffer(CurBuffer, &CurBuffer);
if (CurBuffer){
NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
}
}
} while (CurBuffer);
//
// Write trailing byte (if necessary)
//
if (OddBufLen)
{
UINT Count;
UCHAR Tmp;
USHORT TmpShort;
if (NE2000_PCMCIA == Adapter->CardType) {
// NE2000 PCMCIA CHANGE!!! start
TmpShort = (USHORT)*OddBufAddress;
NdisRawWritePortUshort(Adapter->IoPAddr + NIC_RACK_NIC, TmpShort);
// NE2000 PCMCIA CHANGE!!! end
}
else {
NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RACK_NIC, *OddBufAddress);
}
//
// Wait for DMA to complete robin-2
//
Count = 0xFFFF;
while (Count) {
NdisRawReadPortUchar(
Adapter->IoPAddr + NIC_INTR_STATUS,
&Tmp );
if (Tmp & ISR_DMA_DONE) {
break;
} else {
Count--;
NdisStallExecution(4);
}
}
}
//
// Return length written
//
*Length = PacketLength;
return TRUE;
}
BOOLEAN
CardCopyDown(
IN PNE2000_ADAPTER Adapter,
IN PUCHAR TargetBuffer,
IN PUCHAR SourceBuffer,
IN UINT Length
)
/*++
Routine Description:
Copies Length bytes from the SourceBuffer to the card buffer space
at card address TargetBuffer.
Arguments:
Adapter - pointer to the adapter block
SourceBuffer - Buffer in virtual address space
TargetBuffer - Buffer in card address space
Length - number of bytes to transfer to card
Return Value:
TRUE if the transfer completed with no problems.
--*/
{
//
// Temporary place holders for odd alignment transfers
//
UCHAR Tmp, TmpSave;
USHORT TmpShort;
//
// Values for waiting for noticing when a DMA completes.
//
USHORT OldAddr, NewAddr;
//
// Count of transfers to do
//
USHORT Count;
//
// Address the copy if coming from
//
PUCHAR ReadBuffer;
//
// Skip 0 length copies
//
if (Length == 0) {
return(TRUE);
}
if (!Adapter->EightBitSlot && ((ULONG_PTR)TargetBuffer & 0x1)) {
//
// For odd addresses we need to read first to get the previous
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -