⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 card.c

📁 使用网络驱动器接口标准开发的ne2000网卡的NT驱动.
💻 C
📖 第 1 页 / 共 5 页
字号:
    //
    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 + -