home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / ndissrc.zip / CARD.C next >
C/C++ Source or Header  |  1996-02-07  |  73KB  |  3,248 lines

  1.  
  2. /*++
  3.  
  4.  
  5. Module Name:
  6.  
  7.     card.c
  8.  
  9. Abstract:
  10.  
  11.     Card-specific functions for the NDIS 3.0 UMC 9008 driver.
  12.  
  13.  
  14. --*/
  15.  
  16. #include <ndis.h>
  17. #include "UM9008hw.h"
  18. #include "UM9008sw.h"
  19.  
  20. //
  21. // The 8930 chip set requires  4 bus clocks between chip selects
  22. // 4 bus clocks at 8 MHZ is .5 uS, for a PPC running at 66 MHZ
  23. // that works out to about 33 PPC instructions.  A 1 uS delay was
  24. // added to gaurantee no chip selects within this window.
  25. //
  26.  
  27. #define UM9008_WRITE_PORT_BUFFER_UCHAR(x, y, z) {                                \
  28.     PUCHAR writeBuffer = y;                                               \
  29.     ULONG writeCount;                                                     \
  30.     for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) {   \
  31.         *(volatile UCHAR * const)(x) = *writeBuffer;                      \
  32.         KeFlushWriteBuffer();                                             \
  33.         KeStallExecutionProcessor(1); \
  34.     }                                                                     \
  35. }
  36.  
  37. #define UM9008_WRITE_PORT_BUFFER_USHORT(x, y, z) {                               \
  38.     PUSHORT writeBuffer = y;                                              \
  39.     ULONG writeCount;                                                     \
  40.     for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) {   \
  41.         *(volatile USHORT * const)(x) = *writeBuffer;                     \
  42.         KeFlushWriteBuffer();                                             \
  43.         KeStallExecutionProcessor(1); \
  44.     }                                                                     \
  45. }
  46.  
  47. #define UM9008_WRITE_PORT_BUFFER_ULONG(x, y, z) {                                \
  48.     PULONG writeBuffer = y;                                               \
  49.     ULONG writeCount;                                                     \
  50.     for (writeCount = 0; writeCount < z; writeCount++, writeBuffer++) {   \
  51.         *(volatile ULONG * const)(x) = *writeBuffer;                      \
  52.         KeFlushWriteBuffer();                                             \
  53.         KeStallExecutionProcessor(1); \
  54.     }                                                                     \
  55. }
  56.  
  57. #define UM9008RawWritePortBufferUchar(Port,Buffer,Length) \
  58. { \
  59.         ULONG _Port = (ULONG)(Port); \
  60.         PUCHAR _Current = (Buffer); \
  61.         PUCHAR _End = _Current + (Length); \
  62.         for ( ; _Current < _End; ++_Current) { \
  63.             WRITE_PORT_UCHAR((PUCHAR)_Port,*(UNALIGNED UCHAR *)_Current); \
  64.             KeStallExecutionProcessor(1); \
  65.         } \
  66. }
  67.  
  68. #define UM9008RawWritePortBufferUshort(Port,Buffer,Length) \
  69. { \
  70.         ULONG _Port = (ULONG)(Port); \
  71.         PUSHORT _Current = (Buffer); \
  72.         PUSHORT _End = _Current + (Length); \
  73.         for ( ; _Current < _End; ++_Current) { \
  74.             WRITE_PORT_USHORT((PUSHORT)_Port,*(UNALIGNED USHORT *)_Current); \
  75.             KeStallExecutionProcessor(1); \
  76.         } \
  77. }
  78.  
  79. #define UM9008RawWritePortBufferUlong(Port,Buffer,Length) \
  80. { \
  81.         ULONG _Port = (ULONG)(Port); \
  82.         PULONG _Current = (Buffer); \
  83.         PULONG _End = _Current + (Length); \
  84.         for ( ; _Current < _End; ++_Current) { \
  85.             WRITE_PORT_ULONG((PULONG)_Port,*(UNALIGNED ULONG *)_Current); \
  86.             KeStallExecutionProcessor(1); \
  87.         } \
  88. }
  89.  
  90. BOOLEAN
  91. CardSlotTest(
  92.     IN PUM9008_ADAPTER Adapter
  93.     );
  94.  
  95. BOOLEAN
  96. CardRamTest(
  97.     IN PUM9008_ADAPTER Adapter
  98.     );
  99.  
  100.  
  101. #pragma NDIS_INIT_FUNCTION(CardCheckParameters)
  102.  
  103. BOOLEAN CardCheckParameters(
  104.     IN PUM9008_ADAPTER Adapter
  105. )
  106.  
  107. /*++
  108.  
  109. Routine Description:
  110.  
  111.     Checks that the I/O base address is correct.
  112.  
  113. Arguments:
  114.  
  115.     Adapter - pointer to the adapter block.
  116.  
  117. Return Value:
  118.  
  119.     TRUE, if IoBaseAddress appears correct.
  120.  
  121. --*/
  122.  
  123. {
  124.     UCHAR Tmp;
  125.  
  126.     //
  127.     // If adapter responds to a stop command correctly -- assume it is there.
  128.     //
  129.  
  130.     //
  131.     // Turn off interrupts first.
  132.     //
  133.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0);
  134.  
  135.     //
  136.     // Stop the card.
  137.     //
  138.     SyncCardStop(Adapter);
  139.  
  140.     //
  141.     // Pause
  142.     //
  143.     NdisStallExecution(2000);
  144.  
  145.     //
  146.     // Read response
  147.     //
  148.     NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  149.  
  150.     if ((Tmp == (CR_NO_DMA | CR_STOP)) ||
  151.         (Tmp == (CR_NO_DMA | CR_STOP | CR_START))
  152.     )
  153.     {
  154.         return(TRUE);
  155.     }
  156.     else
  157.     {
  158.         return(FALSE);
  159.     }
  160. }
  161. #ifdef UM9008
  162.  
  163. #pragma NDIS_INIT_FUNCTION(CardSlotTest)
  164.  
  165.  
  166. BOOLEAN CardSlotTest(
  167.     IN PUM9008_ADAPTER Adapter
  168. )
  169.  
  170. /*++
  171.  
  172. Routine Description:
  173.  
  174.     Checks if the card is in an 8 or 16 bit slot and sets a flag in the
  175.     adapter structure.
  176.  
  177. Arguments:
  178.  
  179.     Adapter - pointer to the adapter block.
  180.  
  181. Return Value:
  182.  
  183.     TRUE, if all goes well, else FALSE.
  184.  
  185. --*/
  186.  
  187. {
  188.     UCHAR Tmp;
  189.     UCHAR RomCopy[32];
  190.     UCHAR i;
  191.         BOOLEAN found;
  192.  
  193.     //
  194.     // Reset the chip
  195.     //
  196.     NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
  197.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
  198.  
  199.     //
  200.     // Go to page 0 and stop
  201.     //
  202.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_STOP | CR_NO_DMA);
  203.  
  204.     //
  205.     // Pause
  206.     //
  207.     NdisStallExecution(2000);
  208.  
  209.     //
  210.     // Check that it is stopped
  211.     //
  212.     NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  213.     if (Tmp != (CR_NO_DMA | CR_STOP))
  214.     {
  215.         IF_LOUD(DbgPrint("Could not stop the card\n");)
  216.  
  217.         return(FALSE);
  218.     }
  219.  
  220.     //
  221.     // Setup to read from ROM
  222.     //
  223.     NdisRawWritePortUchar(
  224.         Adapter->IoPAddr + NIC_DATA_CONFIG,
  225.         DCR_BYTE_WIDE | DCR_FIFO_8_BYTE | DCR_NORMAL
  226.     );
  227.  
  228.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
  229.  
  230.     //
  231.     // Ack any interrupts that may be hanging around
  232.     //
  233.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  234.  
  235.     //
  236.     // Setup to read in the ROM, the address and byte count.
  237.     //
  238.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0x0);
  239.  
  240.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0x0);
  241.  
  242.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 32);
  243.  
  244.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  245.  
  246.     NdisRawWritePortUchar(
  247.         Adapter->IoPAddr + NIC_COMMAND,
  248.         CR_DMA_READ | CR_START
  249.     );
  250.  
  251.     //
  252.     // Read first 32 bytes in 16 bit mode
  253.     //
  254.     if (UM9008_ISA == Adapter->CardType)
  255.     {
  256.         for (i = 0; i < 32; i++)
  257.         {
  258.             NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, RomCopy + i);
  259.         }
  260.     }
  261.  
  262.     IF_VERY_LOUD( DbgPrint("Resetting the chip\n"); )
  263.  
  264.     //
  265.     // Reset the chip
  266.     //
  267.     NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RESET, &Tmp);
  268.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RESET, 0xFF);
  269.  
  270.     //
  271.     // Check ROM for 'B' (byte) or 'W' (word)
  272.     // NOTE: If the buffer has bot BB and WW then use WW instead of BB
  273.     IF_VERY_LOUD( DbgPrint("Checking slot type\n"); )
  274.  
  275.     found = FALSE;
  276.  
  277.     if (UM9008_ISA == Adapter->CardType)
  278.     {
  279.         for (i = 16; i < 31; i++)
  280.         {
  281.             if (((RomCopy[i] == 'B') && (RomCopy[i+1] == 'B')) ||
  282.                 ((RomCopy[i] == 'W') && (RomCopy[i+1] == 'W'))
  283.             )
  284.             {
  285.                 if (RomCopy[i] == 'B')
  286.                 {
  287.                     Adapter->EightBitSlot = TRUE;
  288.                                 found = TRUE;
  289.                 }
  290.                 else
  291.                 {
  292.                     Adapter->EightBitSlot = FALSE;
  293.                                 found = TRUE;
  294.                                 break;          // Go no farther
  295.                 }
  296.             }
  297.         }
  298.  
  299.         if (found)
  300.             {
  301.                 IF_VERY_LOUD( (Adapter->EightBitSlot?DbgPrint("8 bit slot\n"):
  302.                                   DbgPrint("16 bit slot\n")); )
  303.             }
  304.             else
  305.             {
  306.                 //
  307.                 // If neither found -- then not an UM9008
  308.                 //
  309.                 IF_VERY_LOUD( DbgPrint("Failed slot type\n"); )
  310.             }
  311.     }
  312.  
  313.     return(found);
  314. }
  315.  
  316. #endif // UM9008
  317.  
  318.  
  319.  
  320.  
  321. #pragma NDIS_INIT_FUNCTION(CardRamTest)
  322.  
  323. BOOLEAN
  324. CardRamTest(
  325.     IN PUM9008_ADAPTER Adapter
  326.     )
  327.  
  328. /*++
  329.  
  330. Routine Description:
  331.  
  332.     Finds out how much RAM the adapter has.  It starts at 1K and checks thru
  333.     60K.  It will set Adapter->RamSize to the appropriate value iff this
  334.     function returns TRUE.
  335.  
  336. Arguments:
  337.  
  338.     Adapter - pointer to the adapter block.
  339.  
  340. Return Value:
  341.  
  342.     TRUE, if all goes well, else FALSE.
  343.  
  344. --*/
  345.  
  346. {
  347.     PUCHAR RamBase, RamPointer;
  348.     PUCHAR RamEnd;
  349.  
  350.         UCHAR TestPattern[]={ 0xAA, 0x55, 0xFF, 0x00 };
  351.         PULONG pTestPattern = (PULONG)TestPattern;
  352.         UCHAR ReadPattern[4];
  353.         PULONG pReadPattern = (PULONG)ReadPattern;
  354.  
  355.     for (RamBase = (PUCHAR)0x400; RamBase < (PUCHAR)0x10000; RamBase += 0x400) {
  356.  
  357.         //
  358.         // Write Test pattern
  359.         //
  360.  
  361.         if (!CardCopyDown(Adapter, RamBase, TestPattern, 4)) {
  362.  
  363.             continue;
  364.  
  365.         }
  366.  
  367.         //
  368.         // Read pattern
  369.         //
  370.  
  371.         if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
  372.  
  373.             continue;
  374.  
  375.         }
  376.  
  377.         IF_VERY_LOUD( DbgPrint("Addr 0x%x: 0x%x, 0x%x, 0x%x, 0x%x\n",
  378.                                RamBase,
  379.                                ReadPattern[0],
  380.                                ReadPattern[1],
  381.                                ReadPattern[2],
  382.                                ReadPattern[3]
  383.                               );
  384.                     )
  385.  
  386.  
  387.         //
  388.         // If they are the same, find the end
  389.         //
  390.  
  391.         if (*pReadPattern == *pTestPattern) {
  392.  
  393.             for (RamEnd = RamBase; !((ULONG)RamEnd & 0xFFFF0000); RamEnd += 0x400) {
  394.  
  395.                 //
  396.                 // Write test pattern
  397.                 //
  398.  
  399.                 if (!CardCopyDown(Adapter, RamEnd, TestPattern, 4)) {
  400.  
  401.                     break;
  402.  
  403.                 }
  404.  
  405.                 //
  406.                 // Read pattern
  407.                 //
  408.  
  409.                 if (!CardCopyUp(Adapter, ReadPattern, RamEnd, 4)) {
  410.  
  411.                     break;
  412.  
  413.                 }
  414.  
  415.                 if (*pReadPattern != *pTestPattern) {
  416.  
  417.                     break;
  418.  
  419.                 }
  420.  
  421.             }
  422.  
  423.             break;
  424.  
  425.         }
  426.  
  427.     }
  428.  
  429.     IF_LOUD( DbgPrint("RamBase 0x%x, RamEnd 0x%x\n", RamBase, RamEnd); )
  430.  
  431.     //
  432.     // If not found, error out
  433.     //
  434.  
  435.     if ((RamBase >= (PUCHAR)0x10000) || (RamBase == RamEnd)) {
  436.  
  437.         return(FALSE);
  438.  
  439.     }
  440.  
  441.     //
  442.     // Watch for boundary case when RamEnd is maximum value
  443.     //
  444.  
  445.     if ((ULONG)RamEnd & 0xFFFF0000) {
  446.  
  447.         RamEnd -= 0x100;
  448.  
  449.     }
  450.  
  451.     //
  452.     // Check all of ram
  453.     //
  454.  
  455.     for (RamPointer = RamBase; RamPointer < RamEnd; RamPointer += 4) {
  456.  
  457.         //
  458.         // Write test pattern
  459.         //
  460.  
  461.         if (!CardCopyDown(Adapter, RamPointer, TestPattern, 4)) {
  462.  
  463.             return(FALSE);
  464.  
  465.         }
  466.  
  467.         //
  468.         // Read pattern
  469.         //
  470.  
  471.         if (!CardCopyUp(Adapter, ReadPattern, RamBase, 4)) {
  472.  
  473.             return(FALSE);
  474.  
  475.         }
  476.  
  477.         if (*pReadPattern != *pTestPattern) {
  478.  
  479.             return(FALSE);
  480.  
  481.         }
  482.  
  483.     }
  484.  
  485.     //
  486.     // Store Results
  487.     //
  488.  
  489.     Adapter->RamBase = RamBase;
  490.     Adapter->RamSize = (ULONG)(RamEnd - RamBase);
  491.  
  492.     return(TRUE);
  493.  
  494. }
  495.  
  496. #pragma NDIS_INIT_FUNCTION(CardInitialize)
  497.  
  498. BOOLEAN
  499. CardInitialize(
  500.     IN PUM9008_ADAPTER Adapter
  501.     )
  502.  
  503. /*++
  504.  
  505. Routine Description:
  506.  
  507.     Initializes the card into a running state.
  508.  
  509. Arguments:
  510.  
  511.     Adapter - pointer to the adapter block.
  512.  
  513. Return Value:
  514.  
  515.     TRUE, if all goes well, else FALSE.
  516.  
  517. --*/
  518.  
  519. {
  520.     UCHAR Tmp;
  521.     USHORT i;
  522.  
  523.     //
  524.     // Stop the card.
  525.     //
  526.     SyncCardStop(Adapter);
  527.  
  528.     //
  529.     // Initialize the Data Configuration register.
  530.     //
  531.     NdisRawWritePortUchar(
  532.         Adapter->IoPAddr + NIC_DATA_CONFIG,
  533.         DCR_AUTO_INIT | DCR_FIFO_8_BYTE
  534.     );
  535.  
  536.     //
  537.     // Set Xmit start location
  538.     //
  539.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_START, 0xA0);
  540.  
  541.     //
  542.     // Set Xmit configuration
  543.     //
  544.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0x0);
  545.  
  546.     //
  547.     // Set Receive configuration
  548.     //
  549.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, RCR_MONITOR);
  550.  
  551.     //
  552.     // Set Receive start
  553.     //
  554.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_START, 0x4);
  555.  
  556.     //
  557.     // Set Receive end
  558.     //
  559.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_PAGE_STOP, 0xFF);
  560.  
  561.     //
  562.     // Set Receive boundary
  563.     //
  564.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_BOUNDARY, 0x4);
  565.  
  566.     //
  567.     // Set Xmit bytes
  568.     //
  569.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_LSB, 0x3C);
  570.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_COUNT_MSB, 0x0);
  571.  
  572.     //
  573.     // Pause
  574.     //
  575.     NdisStallExecution(2000);
  576.  
  577.     //
  578.     // Ack all interrupts that we might have produced
  579.     //
  580.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  581.  
  582.     //
  583.     // Change to page 1
  584.     //
  585.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE1 | CR_STOP);
  586.  
  587.     //
  588.     // Set current
  589.     //
  590.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_CURRENT, 0x4);
  591.  
  592.     //
  593.     // Back to page 0
  594.     //
  595.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 | CR_STOP);
  596.  
  597.     //
  598.     // Pause
  599.     //
  600.     NdisStallExecution(2000);
  601.  
  602.     //
  603.     // Check that Command register reflects this last command
  604.     //
  605.     NdisRawReadPortUchar(Adapter->IoPAddr + NIC_COMMAND, &Tmp);
  606.     if (!(Tmp & CR_STOP))
  607.     {
  608.         IF_LOUD(DbgPrint("Invalid command register\n");)
  609.  
  610.         return(FALSE);
  611.     }
  612.  
  613.     //
  614.     // Do initialization errata
  615.     //
  616.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 55);
  617.  
  618.     //
  619.     // Setup for a read
  620.     //
  621.     NdisRawWritePortUchar(
  622.         Adapter->IoPAddr + NIC_COMMAND,
  623.         CR_DMA_READ | CR_START
  624.     );
  625.  
  626.     //
  627.     // Check if the slot is 8 or 16 bit (affects data transfer rate).
  628.     //
  629.  
  630.     if(Adapter->BusType == NdisInterfaceMca)
  631.     {
  632.         Adapter->EightBitSlot = FALSE;
  633.     }
  634.     else
  635.     {
  636.         IF_VERY_LOUD(DbgPrint("CardSlotTest\n");)
  637.  
  638.         if (CardSlotTest(Adapter) == FALSE)
  639.         {
  640.             //
  641.             // Stop chip
  642.             //
  643.             SyncCardStop(Adapter);
  644.  
  645.             IF_LOUD(DbgPrint("  -- Failed\n");)
  646.             return(FALSE);
  647.         }
  648.  
  649.     }
  650.  
  651.  
  652.     //
  653.     // Mask Interrupts
  654.     //
  655.  
  656.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_MASK, 0x0);
  657.  
  658.     //
  659.     // Setup the Adapter for reading ram
  660.     //
  661.  
  662.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0);
  663.  
  664.     if (Adapter->EightBitSlot)
  665.     {
  666.         NdisRawWritePortUchar(
  667.             Adapter->IoPAddr + NIC_DATA_CONFIG,
  668.             DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_BYTE_WIDE
  669.         );
  670.     }
  671.     else
  672.     {
  673.         NdisRawWritePortUchar(
  674.             Adapter->IoPAddr + NIC_DATA_CONFIG,
  675.             DCR_FIFO_8_BYTE | DCR_NORMAL | DCR_WORD_WIDE
  676.         );
  677.     }
  678.  
  679.     //
  680.     // Clear transmit configuration.
  681.     //
  682.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, 0);
  683.  
  684.     //
  685.     // Clear receive configuration.
  686.     //
  687.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RCV_CONFIG, 0);
  688.  
  689.     //
  690.     // Clear any interrupts
  691.     //
  692.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xFF);
  693.  
  694.     //
  695.     // Stop the chip
  696.     //
  697.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_NO_DMA | CR_STOP);
  698.  
  699.     //
  700.     // Clear any DMA values
  701.     //
  702.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  703.  
  704.     //
  705.     // Clear any DMA values
  706.     //
  707.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  708.  
  709.     //
  710.     // Wait for the reset to complete.
  711.     //
  712.     i = 0x3FFF;
  713.  
  714.     while (--i)
  715.     {
  716.         NdisRawReadPortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp);
  717.  
  718.         if (Tmp & ISR_RESET)
  719.             break;
  720.  
  721.         NdisStallExecution(4);
  722.     }
  723.  
  724.     //
  725.     // Put card in loopback mode
  726.     //
  727.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
  728.  
  729.     //
  730.     // Start the chip.
  731.     //
  732.     NdisRawWritePortUchar(
  733.         Adapter->IoPAddr + NIC_COMMAND,
  734.         CR_NO_DMA | CR_START
  735.     );
  736.  
  737.     //
  738.     // Test for the amount of RAM
  739.     //
  740.     if (UM9008_ISA == Adapter->CardType)
  741.     {
  742.         if (CardRamTest(Adapter) == FALSE)
  743.         {
  744.             //
  745.             // Stop the chip
  746.             //
  747.             SyncCardStop(Adapter);
  748.  
  749.             return(FALSE);
  750.         }
  751.     }
  752.     else
  753.     {
  754.         //
  755.         //  We know what it is for the pcmcia adapters,
  756.         //  so don't waste time on detecting it.
  757.         //
  758.         Adapter->RamBase = (PUCHAR)0x4000;
  759.         Adapter->RamSize = 0x4000;
  760.     }
  761.  
  762.     //
  763.     // Stop the chip
  764.     //
  765.     SyncCardStop(Adapter);
  766.  
  767.     return(TRUE);
  768. }
  769.  
  770.  
  771. #pragma NDIS_INIT_FUNCTION(CardReadEthernetAddress)
  772.  
  773. BOOLEAN CardReadEthernetAddress(
  774.     IN PUM9008_ADAPTER Adapter
  775. )
  776.  
  777. /*++
  778.  
  779. Routine Description:
  780.  
  781.     Reads in the Ethernet address from the Novell 2000.
  782.  
  783. Arguments:
  784.  
  785.     Adapter - pointer to the adapter block.
  786.  
  787. Return Value:
  788.  
  789.     The address is stored in Adapter->PermanentAddress, and StationAddress if it
  790.     is currently zero.
  791.  
  792. --*/
  793.  
  794. {
  795.     UINT    c;
  796.  
  797.     //
  798.     //  Things are done a little differently for PCMCIA adapters.
  799.     //
  800.     if (UM9008_PCMCIA == Adapter->CardType)
  801.     {
  802.         NDIS_STATUS             Status;
  803.         PUCHAR                  pAttributeWindow;
  804.         NDIS_PHYSICAL_ADDRESS   AttributePhysicalAddress;
  805.  
  806.         //
  807.         //  Setup the physical address for the attribute window.
  808.         //
  809.         NdisSetPhysicalAddressHigh(AttributePhysicalAddress, 0);
  810.         NdisSetPhysicalAddressLow(
  811.             AttributePhysicalAddress,
  812.             Adapter->AttributeMemoryAddress
  813.         );
  814.  
  815.         //
  816.         //  We need to get the pcmcia information from the tuple.
  817.         //
  818.         Status = NdisMMapIoSpace(
  819.                      (PVOID *)&pAttributeWindow,
  820.                      Adapter->MiniportAdapterHandle,
  821.                      AttributePhysicalAddress,
  822.                      Adapter->AttributeMemorySize
  823.                  );
  824.         if (NDIS_STATUS_SUCCESS != Status)
  825.         {
  826.             //
  827.             //  Failed to setup the attribute window.
  828.             //
  829.             return(FALSE);
  830.         }
  831.  
  832.         //
  833.         //  Read the ethernet address from the card.
  834.         //
  835.         for (c = 0; c < ETH_LENGTH_OF_ADDRESS; c++)
  836.         {
  837.             Adapter->PermanentAddress[c] =
  838.                         pAttributeWindow[CIS_NET_ADDR_OFFSET + c * 2];
  839.         }
  840.     }
  841.     else
  842.     {
  843.         //
  844.         // Setup to read the ethernet address
  845.         //
  846.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 12);
  847.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  848.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB, 0);
  849.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB, 0);
  850.         NdisRawWritePortUchar(
  851.             Adapter->IoPAddr + NIC_COMMAND,
  852.             CR_START | CR_DMA_READ
  853.         );
  854.  
  855.         //
  856.         // Read in the station address. (We have to read words -- 2 * 6 -- bytes)
  857.         //
  858.         for (c = 0; c < UM9008_LENGTH_OF_ADDRESS; c++)
  859.         {
  860.             NdisRawReadPortUchar(
  861.                 Adapter->IoPAddr + NIC_RACK_NIC,
  862.                 &Adapter->PermanentAddress[c]
  863.             );
  864.         }
  865.     }
  866.  
  867.     IF_LOUD(
  868.         DbgPrint(
  869.             "UM9008: PermanentAddress [ %02x-%02x-%02x-%02x-%02x-%02x ]\n",
  870.             Adapter->PermanentAddress[0],
  871.             Adapter->PermanentAddress[1],
  872.             Adapter->PermanentAddress[2],
  873.             Adapter->PermanentAddress[3],
  874.             Adapter->PermanentAddress[4],
  875.             Adapter->PermanentAddress[5]
  876.         );
  877.     )
  878.  
  879.     //
  880.     // Use the burned in address as the station address, unless the
  881.     // registry specified an override value.
  882.     //
  883.     if ((Adapter->StationAddress[0] == 0x00) &&
  884.         (Adapter->StationAddress[1] == 0x00) &&
  885.         (Adapter->StationAddress[2] == 0x00) &&
  886.         (Adapter->StationAddress[3] == 0x00) &&
  887.         (Adapter->StationAddress[4] == 0x00) &&
  888.         (Adapter->StationAddress[5] == 0x00)
  889.     )
  890.     {
  891.         Adapter->StationAddress[0] = Adapter->PermanentAddress[0];
  892.         Adapter->StationAddress[1] = Adapter->PermanentAddress[1];
  893.         Adapter->StationAddress[2] = Adapter->PermanentAddress[2];
  894.         Adapter->StationAddress[3] = Adapter->PermanentAddress[3];
  895.         Adapter->StationAddress[4] = Adapter->PermanentAddress[4];
  896.         Adapter->StationAddress[5] = Adapter->PermanentAddress[5];
  897.     }
  898.  
  899.     return(TRUE);
  900. }
  901.  
  902.  
  903. BOOLEAN
  904. CardSetup(
  905.     IN PUM9008_ADAPTER Adapter
  906.     )
  907.  
  908. /*++
  909.  
  910. Routine Description:
  911.  
  912.     Sets up the card.
  913.  
  914. Arguments:
  915.  
  916.     Adapter - pointer to the adapter block, which must be initialized.
  917.  
  918. Return Value:
  919.  
  920.     TRUE if successful.
  921.  
  922. --*/
  923.  
  924. {
  925.     UINT i;
  926.     UINT Filter;
  927.     UCHAR Tmp;
  928.  
  929.  
  930.     //
  931.     // Write to and read from CR to make sure it is there.
  932.     //
  933.     NdisRawWritePortUchar(
  934.         Adapter->IoPAddr + NIC_COMMAND,
  935.         CR_STOP | CR_NO_DMA | CR_PAGE0
  936.     );
  937.  
  938.     NdisRawReadPortUchar(
  939.         Adapter->IoPAddr + NIC_COMMAND,
  940.         &Tmp
  941.     );
  942.     if ((Tmp & (CR_STOP | CR_NO_DMA | CR_PAGE0)) !=
  943.         (CR_STOP | CR_NO_DMA | CR_PAGE0)
  944.     )
  945.     {
  946.         return(FALSE);
  947.     }
  948.  
  949.     //
  950.     // Set up the registers in the correct sequence, as defined by
  951.     // the 8390 specification.
  952.     //
  953.     if (Adapter->EightBitSlot)
  954.     {
  955.         NdisRawWritePortUchar(
  956.             Adapter->IoPAddr + NIC_DATA_CONFIG,
  957.             DCR_BYTE_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
  958.         );
  959.     }
  960.     else
  961.     {
  962.         NdisRawWritePortUchar(
  963.             Adapter->IoPAddr + NIC_DATA_CONFIG,
  964.             DCR_WORD_WIDE | DCR_NORMAL | DCR_FIFO_8_BYTE
  965.         );
  966.     }
  967.  
  968.  
  969.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  970.  
  971.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  972.  
  973.     NdisRawWritePortUchar(
  974.         Adapter->IoPAddr + NIC_RCV_CONFIG,
  975.         Adapter->NicReceiveConfig
  976.     );
  977.  
  978.     NdisRawWritePortUchar(
  979.         Adapter->IoPAddr + NIC_XMIT_CONFIG,
  980.         TCR_LOOPBACK
  981.     );
  982.  
  983.     NdisRawWritePortUchar(
  984.         Adapter->IoPAddr + NIC_BOUNDARY,
  985.         Adapter->NicPageStart
  986.     );
  987.  
  988.     NdisRawWritePortUchar(
  989.         Adapter->IoPAddr + NIC_PAGE_START,
  990.         Adapter->NicPageStart
  991.     );
  992.  
  993.     NdisRawWritePortUchar(
  994.         Adapter->IoPAddr + NIC_PAGE_STOP,
  995.         Adapter->NicPageStop
  996.     );
  997.  
  998.     Adapter->Current = Adapter->NicPageStart + (UCHAR)1;
  999.     Adapter->NicNextPacket = Adapter->NicPageStart + (UCHAR)1;
  1000.     Adapter->BufferOverflow = FALSE;
  1001.  
  1002.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_INTR_STATUS, 0xff);
  1003.  
  1004.     NdisRawWritePortUchar(
  1005.         Adapter->IoPAddr + NIC_INTR_MASK,
  1006.         Adapter->NicInterruptMask
  1007.     );
  1008.  
  1009.  
  1010.     //
  1011.     // Move to page 1 to write the station address
  1012.     //
  1013.     NdisRawWritePortUchar(
  1014.         Adapter->IoPAddr + NIC_COMMAND,
  1015.         CR_STOP | CR_NO_DMA | CR_PAGE1
  1016.     );
  1017.  
  1018.     for (i = 0; i < UM9008_LENGTH_OF_ADDRESS; i++)
  1019.     {
  1020.         NdisRawWritePortUchar(
  1021.             Adapter->IoPAddr + (NIC_PHYS_ADDR + i),
  1022.             Adapter->StationAddress[i]
  1023.         );
  1024.     }
  1025.  
  1026.     Filter = Adapter->PacketFilter;
  1027.  
  1028.     //
  1029.     // Write out the multicast addresses
  1030.     //
  1031.     for (i = 0; i < 8; i++)
  1032.     {
  1033.         NdisRawWritePortUchar(
  1034.             Adapter->IoPAddr + (NIC_MC_ADDR + i),
  1035.             (UCHAR)((Filter & NDIS_PACKET_TYPE_ALL_MULTICAST) ?
  1036.                     0xff : Adapter->NicMulticastRegs[i])
  1037.         );
  1038.     }
  1039.  
  1040.     //
  1041.     // Write out the current receive buffer to receive into
  1042.     //
  1043.     NdisRawWritePortUchar(
  1044.         Adapter->IoPAddr + NIC_CURRENT,
  1045.         Adapter->Current
  1046.     );
  1047.  
  1048.  
  1049.     //
  1050.     // move back to page 0 and start the card...
  1051.     //
  1052.     NdisRawWritePortUchar(
  1053.         Adapter->IoPAddr + NIC_COMMAND,
  1054.         CR_STOP | CR_NO_DMA | CR_PAGE0
  1055.     );
  1056.  
  1057.     NdisRawWritePortUchar(
  1058.         Adapter->IoPAddr + NIC_COMMAND,
  1059.         CR_START | CR_NO_DMA | CR_PAGE0
  1060.     );
  1061.  
  1062.     //
  1063.     // ... but it is still in loopback mode.
  1064.     //
  1065.     return(TRUE);
  1066. }
  1067.  
  1068. VOID CardStop(
  1069.     IN PUM9008_ADAPTER Adapter
  1070. )
  1071.  
  1072. /*++
  1073.  
  1074. Routine Description:
  1075.  
  1076.     Stops the card.
  1077.  
  1078. Arguments:
  1079.  
  1080.     Adapter - pointer to the adapter block
  1081.  
  1082. Return Value:
  1083.  
  1084.     None.
  1085.  
  1086. --*/
  1087.  
  1088. {
  1089.     UINT i;
  1090.     UCHAR Tmp;
  1091.  
  1092.     //
  1093.     // Turn on the STOP bit in the Command register.
  1094.     //
  1095.     SyncCardStop(Adapter);
  1096.  
  1097.     //
  1098.     // Clear the Remote Byte Count register so that ISR_RESET
  1099.     // will come on.
  1100.     //
  1101.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0);
  1102.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0);
  1103.  
  1104.  
  1105.     //
  1106.     // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  1107.     // described in the March 1991 8390 addendum), since that
  1108.     // is the maximum time for a software reset to occur.
  1109.     //
  1110.     //
  1111.     for (i = 0; i < 4; i++)
  1112.     {
  1113.         NdisRawReadPortUchar(Adapter->IoPAddr+NIC_INTR_STATUS, &Tmp);
  1114.         if (Tmp & ISR_RESET)
  1115.             break;
  1116.  
  1117.         NdisStallExecution(500);
  1118.     }
  1119.  
  1120.     if (i == 4)
  1121.     {
  1122.         IF_LOUD( DbgPrint("RESET\n");)
  1123.         IF_LOG( UM9008Log('R');)
  1124.     }
  1125.  
  1126.     //
  1127.     // Put the card in loopback mode, then start it.
  1128.     //
  1129.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_XMIT_CONFIG, TCR_LOOPBACK);
  1130.     NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_START | CR_NO_DMA);
  1131.  
  1132.     //
  1133.     // At this point the card is still in loopback mode.
  1134.     //
  1135. }
  1136.  
  1137. BOOLEAN CardReset(
  1138.     IN PUM9008_ADAPTER Adapter
  1139. )
  1140.  
  1141. /*++
  1142.  
  1143. Routine Description:
  1144.  
  1145.     Resets the card.
  1146.  
  1147. Arguments:
  1148.  
  1149.     Adapter - pointer to the adapter block
  1150.  
  1151. Return Value:
  1152.  
  1153.     TRUE if everything is OK.
  1154.  
  1155. --*/
  1156.  
  1157. {
  1158.     //
  1159.     // Stop the chip
  1160.     //
  1161.     CardStop(Adapter);
  1162.  
  1163.     //
  1164.     // Wait for the card to finish any receives or transmits
  1165.     //
  1166.     NdisStallExecution(2000);
  1167.  
  1168.     //
  1169.     // CardSetup() does a software reset.
  1170.     //
  1171.     if (!CardSetup(Adapter))
  1172.     {
  1173.         NdisWriteErrorLogEntry(
  1174.             Adapter->MiniportAdapterHandle,
  1175.             NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1176.             2,
  1177.             cardReset,
  1178.             UM9008_ERRMSG_CARD_SETUP
  1179.         );
  1180.  
  1181.         return(FALSE);
  1182.     }
  1183.  
  1184.     //
  1185.     // Restart the chip
  1186.     //
  1187.     CardStart(Adapter);
  1188.  
  1189.     return TRUE;
  1190. }
  1191.  
  1192.  
  1193.  
  1194. BOOLEAN CardCopyDownPacket(
  1195.     IN PUM9008_ADAPTER  Adapter,
  1196.     IN PNDIS_PACKET     Packet,
  1197.     OUT PUINT           Length
  1198. )
  1199.  
  1200. /*++
  1201.  
  1202. Routine Description:
  1203.  
  1204.     Copies the packet Packet down starting at the beginning of
  1205.     transmit buffer XmitBufferNum, fills in Length to be the
  1206.     length of the packet.
  1207.  
  1208. Arguments:
  1209.  
  1210.     Adapter - pointer to the adapter block
  1211.     Packet - the packet to copy down
  1212.  
  1213. Return Value:
  1214.  
  1215.     Length - the length of the data in the packet in bytes.
  1216.     TRUE if the transfer completed with no problems.
  1217.  
  1218. --*/
  1219.  
  1220. {
  1221.     //
  1222.     // Addresses of the Buffers to copy from and to.
  1223.     //
  1224.     PUCHAR CurBufAddress;
  1225.     PUCHAR OddBufAddress;
  1226.     PUCHAR XmitBufAddress;
  1227.  
  1228.     //
  1229.     // Length of each of the above buffers
  1230.     //
  1231.     UINT CurBufLen;
  1232.     UINT PacketLength;
  1233.  
  1234.     //
  1235.     // Was the last transfer of an odd length?
  1236.     //
  1237.     BOOLEAN OddBufLen = FALSE;
  1238.  
  1239.     //
  1240.     // Current NDIS_BUFFER that is being copied from
  1241.     //
  1242.     PNDIS_BUFFER CurBuffer;
  1243.  
  1244.     //
  1245.     // Programmed I/O, have to transfer the data.
  1246.     //
  1247.     NdisQueryPacket(Packet, NULL, NULL, &CurBuffer, &PacketLength);
  1248.  
  1249.     //
  1250.     // Skip 0 length copies
  1251.     //
  1252.     if (PacketLength == 0) {
  1253.         return(TRUE);
  1254.     }
  1255.  
  1256.     //
  1257.     // Get the starting buffer address
  1258.     //
  1259.     XmitBufAddress = (PUCHAR)Adapter->XmitStart +
  1260.                     Adapter->NextBufToFill*TX_BUF_SIZE;
  1261.  
  1262.     //
  1263.     // Get address and length of the first buffer in the packet
  1264.     //
  1265.     NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1266.  
  1267.     while (CurBuffer && (CurBufLen == 0)) {
  1268.  
  1269.         NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1270.  
  1271.         NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1272.  
  1273.     }
  1274.  
  1275.     //
  1276.     // set up the card
  1277.     //
  1278.     {
  1279.  
  1280.         //
  1281.         // Temporary places for holding values for transferring to
  1282.         // an odd aligned address on 16-bit slots.
  1283.         //
  1284.         UCHAR Tmp;
  1285.         UCHAR Tmp1;
  1286.         USHORT TmpShort;
  1287.  
  1288.         //
  1289.         // Values for waiting for noticing when a DMA completes.
  1290.         //
  1291.         USHORT OldAddr, NewAddr;
  1292.  
  1293.         //
  1294.         // Count of transfers to do
  1295.         //
  1296.         USHORT Count;
  1297.  
  1298.         //
  1299.         // Buffer to read from for odd aligned transfers
  1300.         //
  1301.         PUCHAR ReadBuffer;
  1302.  
  1303.         if (!Adapter->EightBitSlot && ((ULONG)XmitBufAddress & 0x1)) {
  1304.  
  1305.             //
  1306.             // Avoid transfers to odd addresses in word mode.
  1307.             //
  1308.             // For odd addresses we need to read first to get the previous
  1309.             // byte and then merge it with our first byte.
  1310.             //
  1311.  
  1312.             //
  1313.             // Set Count and Source address
  1314.             //
  1315.  
  1316.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0);
  1317.  
  1318.             NdisRawWritePortUchar(
  1319.                 Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1320.                 LSB((XmitBufAddress - 1))
  1321.             );
  1322.  
  1323.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1324.                                   MSB((XmitBufAddress - 1))
  1325.                                  );
  1326.  
  1327. // UM9008 PCMCIA CHANGE START
  1328.  
  1329.             //
  1330.             //  UM9008 PCMCIA CHANGE!!!
  1331.             //
  1332.             //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1 );
  1333.             //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  1334.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  1335.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  1336.  
  1337.             //
  1338.             // Set direction (Read)
  1339.             //
  1340.  
  1341.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  1342.                            CR_START | CR_PAGE0 | CR_DMA_READ );
  1343.  
  1344.             //
  1345.             //  UM9008 PCMCIA CHANGE!!!
  1346.             //
  1347.             //NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp1 );
  1348.             NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  1349.             Tmp1 = LSB(TmpShort);
  1350.  
  1351. // UM9008 PCMCIA CHANGE END
  1352.  
  1353.             //
  1354.             // Do Write errata as described on pages 1-143 and
  1355.             // 1-144 of the 1992 LAN databook
  1356.             //
  1357.  
  1358.             //
  1359.             // Set Count and destination address
  1360.             //
  1361.             ReadBuffer = XmitBufAddress + ((ULONG)XmitBufAddress & 1);
  1362.  
  1363.             OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1364.  
  1365.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND,
  1366.                                   CR_PAGE0
  1367.                                  );
  1368.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1369.                                   LSB(ReadBuffer)
  1370.                                  );
  1371.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1372.                                   MSB(ReadBuffer)
  1373.                                  );
  1374.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  1375.             NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  1376.  
  1377.             //
  1378.             // Set direction (Read)
  1379.             //
  1380.             NdisRawWritePortUchar(
  1381.                            Adapter->IoPAddr + NIC_COMMAND,
  1382.                            CR_START | CR_PAGE0 | CR_DMA_READ
  1383.                            );
  1384.  
  1385.             //
  1386.             // Read from port
  1387.             //
  1388.             NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  1389.  
  1390.             //
  1391.             // Wait for addr to change
  1392.             //
  1393.             TmpShort = 0xFFFF;
  1394.  
  1395.             while (TmpShort != 0) {
  1396.  
  1397.                 NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
  1398.                 NewAddr = Tmp;
  1399.                 NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
  1400.                 NewAddr |= (Tmp << 8);
  1401.  
  1402.                 if (NewAddr != OldAddr) {
  1403.  
  1404.                     break;
  1405.  
  1406.                 }
  1407.  
  1408.                 NdisStallExecution(1);
  1409.  
  1410.                 TmpShort--;
  1411.             }
  1412.  
  1413.             if (NewAddr == OldAddr) {
  1414.  
  1415.                 NdisWriteErrorLogEntry(
  1416.                     Adapter->MiniportAdapterHandle,
  1417.                     NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1418.                     2,
  1419.                     cardCopyDownPacket,
  1420.                     (ULONG)XmitBufAddress
  1421.                     );
  1422.  
  1423.                 return(FALSE);
  1424.  
  1425.             }
  1426.  
  1427.             //
  1428.             // Set Count and destination address
  1429.             //
  1430.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1431.                                LSB((XmitBufAddress - 1)) );
  1432.  
  1433.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1434.                                MSB((XmitBufAddress - 1)) );
  1435.  
  1436.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2 );
  1437.  
  1438.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0 );
  1439.  
  1440.             //
  1441.             // Set direction (Write)
  1442.             //
  1443.             NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  1444.                            CR_START | CR_PAGE0 | CR_DMA_WRITE );
  1445.  
  1446.             //
  1447.             // It seems that the card stores words in LOW:HIGH order
  1448.             //
  1449.             NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
  1450.                            (USHORT)(Tmp1 | ((*CurBufAddress) << 8)) );
  1451.  
  1452.             //
  1453.             // Wait for DMA to complete
  1454.             //
  1455.             Count = 0xFFFF;
  1456.  
  1457.             while (Count) {
  1458.  
  1459.                 NdisRawReadPortUchar( Adapter->IoPAddr + NIC_INTR_STATUS, &Tmp1 );
  1460.  
  1461.                 if (Tmp1 & ISR_DMA_DONE) {
  1462.  
  1463.                     break;
  1464.  
  1465.                 } else {
  1466.  
  1467.                     Count--;
  1468.                     NdisStallExecution(4);
  1469.  
  1470.                 }
  1471.  
  1472.             }
  1473.  
  1474.             CurBufAddress++;
  1475.             XmitBufAddress++;
  1476.             PacketLength--;
  1477.             CurBufLen--;
  1478.  
  1479.         }
  1480.  
  1481.         //
  1482.         // Do Write errata as described on pages 1-143 and 1-144 of
  1483.         // the 1992 LAN databook
  1484.         //
  1485.  
  1486.         //
  1487.         // Set Count and destination address
  1488.         //
  1489.         ReadBuffer = XmitBufAddress + ((ULONG)XmitBufAddress & 1);
  1490.  
  1491.         OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1492.  
  1493.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND,
  1494.                               CR_PAGE0
  1495.                              );
  1496.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1497.                               LSB(ReadBuffer)
  1498.                              );
  1499.  
  1500.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1501.                               MSB(ReadBuffer)
  1502.                              );
  1503.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1504.                               0x2
  1505.                              );
  1506.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1507.                               0x0
  1508.                              );
  1509.  
  1510.         //
  1511.         // Set direction (Read)
  1512.         //
  1513.         NdisRawWritePortUchar(
  1514.                        Adapter->IoPAddr + NIC_COMMAND,
  1515.                        CR_START | CR_PAGE0 | CR_DMA_READ
  1516.                        );
  1517.  
  1518.         if (Adapter->EightBitSlot) {
  1519.  
  1520.             //
  1521.             // Read from port
  1522.             //
  1523.             NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
  1524.             NdisRawReadPortUchar( Adapter->IoPAddr + NIC_RACK_NIC, &Tmp );
  1525.  
  1526.         } else {
  1527.  
  1528.             //
  1529.             // Read from port
  1530.             //
  1531.             NdisRawReadPortUshort( Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort );
  1532.  
  1533.         }
  1534.  
  1535.         //
  1536.         // Wait for addr to change
  1537.         //
  1538.         TmpShort = 0xFFFF;
  1539.  
  1540.         while (TmpShort != 0) {
  1541.  
  1542.             NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_LSB, &Tmp );
  1543.             NewAddr = Tmp;
  1544.             NdisRawReadPortUchar( Adapter->IoPAddr + NIC_CRDA_MSB, &Tmp );
  1545.             NewAddr |= (Tmp << 8);
  1546.  
  1547.             if (NewAddr != OldAddr) {
  1548.  
  1549.                 break;
  1550.  
  1551.             }
  1552.  
  1553.             NdisStallExecution(1);
  1554.  
  1555.             TmpShort--;
  1556.         }
  1557.  
  1558.         if (NewAddr == OldAddr) {
  1559.  
  1560.             NdisWriteErrorLogEntry(
  1561.                 Adapter->MiniportAdapterHandle,
  1562.                 NDIS_ERROR_CODE_HARDWARE_FAILURE,
  1563.                 2,
  1564.                 cardCopyDownPacket,
  1565.                 (ULONG)XmitBufAddress
  1566.                 );
  1567.  
  1568.             return(FALSE);
  1569.  
  1570.         }
  1571.  
  1572.         //
  1573.         // Set Count and destination address
  1574.         //
  1575.  
  1576.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0 );
  1577.  
  1578.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1579.                            LSB(XmitBufAddress) );
  1580.  
  1581.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1582.                            MSB(XmitBufAddress) );
  1583.  
  1584.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  1585.                            LSB(PacketLength) );
  1586.  
  1587.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  1588.                            MSB(PacketLength) );
  1589.         //
  1590.         // Set direction (Write)
  1591.         //
  1592.         NdisRawWritePortUchar( Adapter->IoPAddr + NIC_COMMAND,
  1593.                        CR_START | CR_PAGE0 | CR_DMA_WRITE );
  1594.  
  1595.     } // setup
  1596.  
  1597.     //
  1598.     // Copy the data now
  1599.     //
  1600.  
  1601.     do {
  1602.  
  1603.         UINT Count;
  1604.         UCHAR Tmp;
  1605.  
  1606.         //
  1607.         // Write the previous byte with this one
  1608.         //
  1609.         if (OddBufLen) {
  1610.  
  1611.             //
  1612.             // It seems that the card stores words in LOW:HIGH order
  1613.             //
  1614.             NdisRawWritePortUshort( Adapter->IoPAddr + NIC_RACK_NIC,
  1615.                        (USHORT)(*OddBufAddress | ((*CurBufAddress) << 8)) );
  1616.  
  1617.             OddBufLen = FALSE;
  1618.             CurBufAddress++;
  1619.             CurBufLen--;
  1620.  
  1621.         }
  1622.  
  1623.         if (Adapter->EightBitSlot) { // byte mode
  1624.  
  1625.             UM9008RawWritePortBufferUchar(
  1626.                 Adapter->IoPAddr + NIC_RACK_NIC,
  1627.                 CurBufAddress,
  1628.                 CurBufLen
  1629.                 );
  1630.  
  1631.         } else { // word mode
  1632.  
  1633.             UM9008RawWritePortBufferUshort(
  1634.                 Adapter->IoPAddr + NIC_RACK_NIC,
  1635.                 (PUSHORT)CurBufAddress,
  1636.                 (CurBufLen >> 1));
  1637.  
  1638.             //
  1639.             // Save trailing byte (if an odd lengthed transfer)
  1640.             //
  1641.             if (CurBufLen & 0x1) {
  1642.                 OddBufAddress = CurBufAddress + (CurBufLen - 1);
  1643.                 OddBufLen = TRUE;
  1644.             }
  1645.  
  1646.         }
  1647.  
  1648.         //
  1649.         // Wait for DMA to complete
  1650.         //
  1651.         Count = 0xFFFF;
  1652.         while (Count) {
  1653.  
  1654.             NdisRawReadPortUchar(
  1655.                 Adapter->IoPAddr + NIC_INTR_STATUS,
  1656.                 &Tmp );
  1657.  
  1658.             if (Tmp & ISR_DMA_DONE) {
  1659.  
  1660.                 break;
  1661.  
  1662.             } else {
  1663.  
  1664.                 Count--;
  1665.                 NdisStallExecution(4);
  1666.  
  1667.             }
  1668.  
  1669.         }
  1670.  
  1671.         //
  1672.         // Move to the next buffer
  1673.         //
  1674.         NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1675.  
  1676.         if (CurBuffer){
  1677.             NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1678.         }
  1679.  
  1680.         //
  1681.         // Get address and length of the next buffer
  1682.         //
  1683.         while (CurBuffer && (CurBufLen == 0)) {
  1684.  
  1685.             NdisGetNextBuffer(CurBuffer, &CurBuffer);
  1686.  
  1687.             if (CurBuffer){
  1688.                 NdisQueryBuffer(CurBuffer, (PVOID *)&CurBufAddress, &CurBufLen);
  1689.             }
  1690.  
  1691.         }
  1692.  
  1693.     } while (CurBuffer);
  1694.  
  1695.     //
  1696.     // Write trailing byte (if necessary)
  1697.     //
  1698.     if (OddBufLen)
  1699.     {
  1700. //  UM9008 PCMCIA CHANGE!!! start
  1701.         USHORT  TmpShort;
  1702.  
  1703.         TmpShort = (USHORT)*OddBufAddress;
  1704.         NdisRawWritePortUshort(Adapter->IoPAddr + NIC_RACK_NIC, TmpShort);
  1705.  
  1706.         //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RACK_NIC, *OddBufAddress);
  1707.  
  1708. //  UM9008 PCMCIA CHANGE!!! end
  1709.     }
  1710.  
  1711.     //
  1712.     // Return length written
  1713.     //
  1714.     *Length = PacketLength;
  1715.  
  1716.     return TRUE;
  1717. }
  1718.  
  1719. BOOLEAN
  1720. CardCopyDown(
  1721.     IN PUM9008_ADAPTER Adapter,
  1722.     IN PUCHAR TargetBuffer,
  1723.     IN PUCHAR SourceBuffer,
  1724.     IN UINT Length
  1725.     )
  1726.  
  1727. /*++
  1728.  
  1729. Routine Description:
  1730.  
  1731.     Copies Length bytes from the SourceBuffer to the card buffer space
  1732.     at card address TargetBuffer.
  1733.  
  1734. Arguments:
  1735.  
  1736.     Adapter - pointer to the adapter block
  1737.  
  1738.     SourceBuffer - Buffer in virtual address space
  1739.  
  1740.     TargetBuffer - Buffer in card address space
  1741.  
  1742.     Length - number of bytes to transfer to card
  1743.  
  1744. Return Value:
  1745.  
  1746.     TRUE if the transfer completed with no problems.
  1747.  
  1748. --*/
  1749.  
  1750. {
  1751.     //
  1752.     // Temporary place holders for odd alignment transfers
  1753.     //
  1754.     UCHAR Tmp, TmpSave;
  1755.     USHORT TmpShort;
  1756.  
  1757.     //
  1758.     // Values for waiting for noticing when a DMA completes.
  1759.     //
  1760.     USHORT OldAddr, NewAddr;
  1761.  
  1762.     //
  1763.     // Count of transfers to do
  1764.     //
  1765.     USHORT Count;
  1766.  
  1767.     //
  1768.     // Address the copy if coming from
  1769.     //
  1770.     PUCHAR ReadBuffer;
  1771.  
  1772.  
  1773.     //
  1774.     // Skip 0 length copies
  1775.     //
  1776.  
  1777.     if (Length == 0) {
  1778.  
  1779.         return(TRUE);
  1780.  
  1781.     }
  1782.  
  1783.  
  1784.     if (!Adapter->EightBitSlot && ((ULONG)TargetBuffer & 0x1)) {
  1785.  
  1786.         //
  1787.         // For odd addresses we need to read first to get the previous
  1788.         // byte and then merge it with our first byte.
  1789.         //
  1790.  
  1791.         //
  1792.         // Set Count and Source address
  1793.         //
  1794.         NdisRawWritePortUchar(
  1795.             Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1796.             LSB((TargetBuffer - 1))
  1797.         );
  1798.  
  1799.         NdisRawWritePortUchar(
  1800.             Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1801.             MSB((TargetBuffer - 1))
  1802.         );
  1803.  
  1804. // UM9008 PCMCIA CHANGE!!!  start
  1805.         //NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x1);
  1806.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1807.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1808. // UM9008 PCMCIA CHANGE!!!  end
  1809.  
  1810.         //
  1811.         // Set direction (Read)
  1812.         //
  1813.  
  1814.         NdisRawWritePortUchar(
  1815.             Adapter->IoPAddr + NIC_COMMAND,
  1816.             CR_START | CR_PAGE0 | CR_DMA_READ
  1817.         );
  1818.  
  1819. // UM9008 PCMCIA CHANGE!!!  start
  1820.         //NdisRawReadPortUchar(Adapter->IoPAddr + NIC_RACK_NIC, &TmpSave);
  1821.         NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
  1822.         TmpSave = LSB(TmpShort);
  1823. // UM9008 PCMCIA CHANGE!!!  end
  1824.  
  1825.         //
  1826.         // Do Write errata as described on pages 1-143 and 1-144 of the 1992
  1827.         // LAN databook
  1828.         //
  1829.  
  1830.         //
  1831.         // Set Count and destination address
  1832.         //
  1833.  
  1834.         ReadBuffer = TargetBuffer + ((ULONG)TargetBuffer & 1);
  1835.  
  1836.         OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1837.  
  1838.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_COMMAND, CR_PAGE0);
  1839.  
  1840.         NdisRawWritePortUchar(
  1841.             Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1842.             LSB(ReadBuffer)
  1843.         );
  1844.  
  1845.         NdisRawWritePortUchar(
  1846.             Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1847.             MSB(ReadBuffer)
  1848.         );
  1849.  
  1850.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1851.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1852.  
  1853.         //
  1854.         // Set direction (Read)
  1855.         //
  1856.  
  1857.         NdisRawWritePortUchar(
  1858.             Adapter->IoPAddr + NIC_COMMAND,
  1859.             CR_START | CR_PAGE0 | CR_DMA_READ
  1860.         );
  1861.  
  1862.         //
  1863.         // Read from port
  1864.         //
  1865.  
  1866.         NdisRawReadPortUshort(Adapter->IoPAddr + NIC_RACK_NIC, &TmpShort);
  1867.  
  1868.         //
  1869.         // Wait for addr to change
  1870.         //
  1871.  
  1872.         TmpShort = 0xFFFF;
  1873.  
  1874.         while (TmpShort != 0) {
  1875.  
  1876.             NdisRawReadPortUchar(
  1877.                           Adapter->IoPAddr + NIC_CRDA_LSB,
  1878.                           &Tmp
  1879.                          );
  1880.  
  1881.             NewAddr = Tmp;
  1882.  
  1883.             NdisRawReadPortUchar(
  1884.                           Adapter->IoPAddr + NIC_CRDA_MSB,
  1885.                           &Tmp
  1886.                          );
  1887.  
  1888.             NewAddr |= (Tmp << 8);
  1889.  
  1890.             if (NewAddr != OldAddr) {
  1891.  
  1892.                 break;
  1893.             }
  1894.  
  1895.             NdisStallExecution(1);
  1896.  
  1897.             TmpShort--;
  1898.  
  1899.         }
  1900.  
  1901.         if (NewAddr == OldAddr) {
  1902.  
  1903.             return(FALSE);
  1904.  
  1905.         }
  1906.  
  1907.         //
  1908.         // Set Count and destination address
  1909.         //
  1910.         NdisRawWritePortUchar(
  1911.             Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1912.             LSB((TargetBuffer - 1))
  1913.         );
  1914.  
  1915.         NdisRawWritePortUchar(
  1916.             Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1917.             MSB((TargetBuffer - 1))
  1918.         );
  1919.  
  1920.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_LSB, 0x2);
  1921.         NdisRawWritePortUchar(Adapter->IoPAddr + NIC_RMT_COUNT_MSB, 0x0);
  1922.  
  1923.         //
  1924.         // Set direction (Write)
  1925.         //
  1926.  
  1927.         NdisRawWritePortUchar(
  1928.             Adapter->IoPAddr + NIC_COMMAND,
  1929.             CR_START | CR_PAGE0 | CR_DMA_WRITE
  1930.         );
  1931.  
  1932.         //
  1933.         // It seems that the card stores words in LOW:HIGH order
  1934.         //
  1935.  
  1936.         NdisRawWritePortUshort(
  1937.                        Adapter->IoPAddr + NIC_RACK_NIC,
  1938.                        (USHORT)(TmpSave | ((*SourceBuffer) << 8))
  1939.                        );
  1940.  
  1941.         //
  1942.         // Wait for DMA to complete
  1943.         //
  1944.  
  1945.         Count = 0xFFFF;
  1946.  
  1947.         while (Count) {
  1948.  
  1949.             NdisRawReadPortUchar(
  1950.                           Adapter->IoPAddr + NIC_INTR_STATUS,
  1951.                           &Tmp
  1952.                          );
  1953.  
  1954.             if (Tmp & ISR_DMA_DONE) {
  1955.  
  1956.                 break;
  1957.  
  1958.             } else {
  1959.  
  1960.                 Count--;
  1961.  
  1962.                 NdisStallExecution(4);
  1963.  
  1964.             }
  1965.  
  1966.         }
  1967.  
  1968.         SourceBuffer++;
  1969.         TargetBuffer++;
  1970.         Length--;
  1971.  
  1972.     }
  1973.  
  1974.     //
  1975.     // Do Write errata as described on pages 1-143 and 1-144 of the 1992
  1976.     // LAN databook
  1977.     //
  1978.  
  1979.     //
  1980.     // Set Count and destination address
  1981.     //
  1982.  
  1983.     ReadBuffer = TargetBuffer + ((ULONG)TargetBuffer & 1);
  1984.  
  1985.     OldAddr = NewAddr = (USHORT)(ReadBuffer);
  1986.  
  1987.     NdisRawWritePortUchar(
  1988.                        Adapter->IoPAddr + NIC_COMMAND,
  1989.                        CR_PAGE0
  1990.                       );
  1991.  
  1992.     NdisRawWritePortUchar(
  1993.                        Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  1994.                        LSB(ReadBuffer)
  1995.                       );
  1996.  
  1997.     NdisRawWritePortUchar(
  1998.                        Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  1999.                        MSB(ReadBuffer)
  2000.                       );
  2001.  
  2002.     NdisRawWritePortUchar(
  2003.                        Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2004.                        0x2
  2005.                       );
  2006.  
  2007.     NdisRawWritePortUchar(
  2008.                        Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2009.                        0x0
  2010.                       );
  2011.  
  2012.     //
  2013.     // Set direction (Read)
  2014.     //
  2015.  
  2016.     NdisRawWritePortUchar(
  2017.                    Adapter->IoPAddr + NIC_COMMAND,
  2018.                    CR_START | CR_PAGE0 | CR_DMA_READ
  2019.                   );
  2020.  
  2021.     if (Adapter->EightBitSlot) {
  2022.  
  2023.         //
  2024.         // Read from port
  2025.         //
  2026.  
  2027.         NdisRawReadPortUchar(
  2028.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2029.                        &Tmp
  2030.                       );
  2031.  
  2032.  
  2033.         NdisRawReadPortUchar(
  2034.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2035.                        &Tmp
  2036.                       );
  2037.  
  2038.     } else {
  2039.  
  2040.         //
  2041.         // Read from port
  2042.         //
  2043.  
  2044.         NdisRawReadPortUshort(
  2045.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2046.                        &TmpShort
  2047.                       );
  2048.  
  2049.     }
  2050.  
  2051.     //
  2052.     // Wait for addr to change
  2053.     //
  2054.  
  2055.     TmpShort = 0xFFFF;
  2056.  
  2057.     while (TmpShort != 0) {
  2058.  
  2059.         NdisRawReadPortUchar(
  2060.                       Adapter->IoPAddr + NIC_CRDA_LSB,
  2061.                       &Tmp
  2062.                      );
  2063.  
  2064.         NewAddr = Tmp;
  2065.  
  2066.         NdisRawReadPortUchar(
  2067.                       Adapter->IoPAddr + NIC_CRDA_MSB,
  2068.                       &Tmp
  2069.                      );
  2070.  
  2071.         NewAddr |= (Tmp << 8);
  2072.  
  2073.         if (NewAddr != OldAddr) {
  2074.  
  2075.             break;
  2076.         }
  2077.  
  2078.         NdisStallExecution(1);
  2079.  
  2080.         TmpShort--;
  2081.  
  2082.     }
  2083.  
  2084.     if (NewAddr == OldAddr) {
  2085.  
  2086.         return(FALSE);
  2087.  
  2088.     }
  2089.  
  2090.     //
  2091.     // Set Count and destination address
  2092.     //
  2093.  
  2094.     NdisRawWritePortUchar(
  2095.                        Adapter->IoPAddr + NIC_COMMAND,
  2096.                        CR_PAGE0
  2097.                       );
  2098.  
  2099.     NdisRawWritePortUchar(
  2100.                        Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  2101.                        LSB(TargetBuffer)
  2102.                       );
  2103.  
  2104.     NdisRawWritePortUchar(
  2105.                        Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  2106.                        MSB(TargetBuffer)
  2107.                       );
  2108.  
  2109.     NdisRawWritePortUchar(
  2110.                        Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2111.                        LSB(Length)
  2112.                       );
  2113.  
  2114.     NdisRawWritePortUchar(
  2115.                        Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2116.                        MSB(Length)
  2117.                       );
  2118.  
  2119.     //
  2120.     // Set direction (Write)
  2121.     //
  2122.  
  2123.     NdisRawWritePortUchar(
  2124.                    Adapter->IoPAddr + NIC_COMMAND,
  2125.                    CR_START | CR_PAGE0 | CR_DMA_WRITE
  2126.                   );
  2127.  
  2128.     if (Adapter->EightBitSlot) {
  2129.  
  2130.         //
  2131.         // Repeatedly write to out port
  2132.         //
  2133.  
  2134.         UM9008RawWritePortBufferUchar(
  2135.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2136.                        SourceBuffer,
  2137.                        Length);
  2138.  
  2139.     } else {
  2140.  
  2141.         //
  2142.         // Write words to out ports
  2143.         //
  2144.  
  2145.         UM9008RawWritePortBufferUshort(
  2146.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2147.                        (PUSHORT)SourceBuffer,
  2148.                        (Length >> 1));
  2149.  
  2150.         //
  2151.         // Write trailing byte (if necessary)
  2152.         //
  2153.         if (Length & 0x1)
  2154.         {
  2155.             SourceBuffer += (Length - 1);
  2156.  
  2157. // UM9008 PCMCIA CHANGE!!!  start
  2158.  
  2159.             //NdisRawWritePortUchar(
  2160.             //    Adapter->IoPAddr + NIC_RACK_NIC,
  2161.             //    *SourceBuffer
  2162.             //);
  2163.  
  2164.             TmpShort = (USHORT)(*SourceBuffer);
  2165.             NdisRawWritePortUshort(
  2166.                 Adapter->IoPAddr + NIC_RACK_NIC,
  2167.                 TmpShort
  2168.             );
  2169. // UM9008 PCMCIA CHANGE!!!  end
  2170.  
  2171.  
  2172.         }
  2173.  
  2174.     }
  2175.  
  2176.     //
  2177.     // Wait for DMA to complete
  2178.     //
  2179.  
  2180.     Count = 0xFFFF;
  2181.  
  2182.     while (Count) {
  2183.  
  2184.         NdisRawReadPortUchar(
  2185.                       Adapter->IoPAddr + NIC_INTR_STATUS,
  2186.                       &Tmp
  2187.                      );
  2188.  
  2189.         if (Tmp & ISR_DMA_DONE) {
  2190.  
  2191.             break;
  2192.  
  2193.         } else {
  2194.  
  2195.             Count--;
  2196.  
  2197.             NdisStallExecution(4);
  2198.  
  2199.         }
  2200.  
  2201. #if DBG
  2202.         if (!(Tmp & ISR_DMA_DONE)) {
  2203.  
  2204.             DbgPrint("CopyDownDMA didn't finish!");
  2205.  
  2206.         }
  2207. #endif // DBG
  2208.  
  2209.     }
  2210.  
  2211.     IF_LOG(UM9008Log('>');)
  2212.  
  2213.     return TRUE;
  2214. }
  2215.  
  2216.  
  2217. BOOLEAN
  2218. CardCopyUp(
  2219.     IN PUM9008_ADAPTER Adapter,
  2220.     IN PUCHAR TargetBuffer,
  2221.     IN PUCHAR SourceBuffer,
  2222.     IN UINT BufferLength
  2223.     )
  2224.  
  2225. /*++
  2226.  
  2227. Routine Description:
  2228.  
  2229.     Copies data from the card to memory.
  2230.  
  2231. Arguments:
  2232.  
  2233.     Adapter - pointer to the adapter block
  2234.  
  2235.     Target - the target address
  2236.  
  2237.     Source - the source address (on the card)
  2238.  
  2239.     BufferLength - the number of bytes to copy
  2240.  
  2241. Return Value:
  2242.  
  2243.     TRUE if the transfer completed with no problems.
  2244.  
  2245. --*/
  2246.  
  2247. {
  2248.  
  2249.     //
  2250.     // Used to check when the dma is done
  2251.     //
  2252.     UCHAR IsrValue;
  2253.  
  2254.     //
  2255.     // Count of the number of transfers to do
  2256.     //
  2257.     USHORT Count;
  2258.  
  2259.     //
  2260.     // Place holder for port values
  2261.     //
  2262.     UCHAR Temp;
  2263.  
  2264.     if (BufferLength == 0) {
  2265.  
  2266.         return TRUE;
  2267.  
  2268.     }
  2269.  
  2270.     //
  2271.     // Read the Command Register, to make sure it is ready for a write
  2272.     //
  2273.     NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Temp);
  2274.  
  2275.     if (Adapter->EightBitSlot) {
  2276.  
  2277.         //
  2278.         // If byte mode
  2279.         //
  2280.  
  2281.         //
  2282.         // Set Count and destination address
  2283.         //
  2284.  
  2285.         NdisRawWritePortUchar(
  2286.                            Adapter->IoPAddr + NIC_COMMAND,
  2287.                            CR_PAGE0
  2288.                           );
  2289.  
  2290.         NdisRawWritePortUchar(
  2291.                            Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  2292.                            LSB(SourceBuffer)
  2293.                           );
  2294.  
  2295.         NdisRawWritePortUchar(
  2296.                            Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  2297.                            MSB(SourceBuffer)
  2298.                           );
  2299.  
  2300.         NdisRawWritePortUchar(
  2301.                            Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2302.                            LSB(BufferLength)
  2303.                           );
  2304.  
  2305.         NdisRawWritePortUchar(
  2306.                            Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2307.                            MSB(BufferLength)
  2308.                           );
  2309.  
  2310.         //
  2311.         // Set direction (Read)
  2312.         //
  2313.  
  2314.         NdisRawWritePortUchar(
  2315.                        Adapter->IoPAddr + NIC_COMMAND,
  2316.                        CR_START | CR_PAGE0 | CR_DMA_READ
  2317.                       );
  2318.         //
  2319.         // Repeatedly read from port
  2320.         //
  2321.  
  2322.         NdisRawReadPortBufferUchar(
  2323.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2324.                        TargetBuffer,
  2325.                        BufferLength
  2326.                       );
  2327.  
  2328.     } else {
  2329.  
  2330.         //
  2331.         // Else word mode
  2332.         //
  2333.  
  2334.         USHORT Tmp;
  2335.  
  2336.         NdisRawWritePortUchar(
  2337.                                Adapter->IoPAddr + NIC_COMMAND,
  2338.                                CR_PAGE0
  2339.                               );
  2340.  
  2341.         //
  2342.         // Avoid transfers to odd addresses
  2343.         //
  2344.  
  2345.         if ((ULONG)SourceBuffer & 0x1) {
  2346.  
  2347.             //
  2348.             // For odd addresses we need to read previous word and store the
  2349.             // second byte
  2350.             //
  2351.  
  2352.             //
  2353.             // Set Count and Source address
  2354.             //
  2355.  
  2356.             NdisRawWritePortUchar(
  2357.                                Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  2358.                                LSB((SourceBuffer - 1))
  2359.                               );
  2360.  
  2361.             NdisRawWritePortUchar(
  2362.                                Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  2363.                                MSB((SourceBuffer - 1))
  2364.                               );
  2365.  
  2366.             NdisRawWritePortUchar(
  2367.                                Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2368.                                0x2
  2369.                               );
  2370.  
  2371.             NdisRawWritePortUchar(
  2372.                                Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2373.                                0x0
  2374.                               );
  2375.  
  2376.             //
  2377.             // Set direction (Read)
  2378.             //
  2379.  
  2380.             NdisRawWritePortUchar(
  2381.                            Adapter->IoPAddr + NIC_COMMAND,
  2382.                            CR_START | CR_PAGE0 | CR_DMA_READ
  2383.                           );
  2384.  
  2385.             NdisRawReadPortUshort(
  2386.                            Adapter->IoPAddr + NIC_RACK_NIC,
  2387.                            &Tmp
  2388.                            );
  2389.  
  2390.             *TargetBuffer = MSB(Tmp);
  2391.  
  2392.             //
  2393.             // Wait for DMA to complete
  2394.             //
  2395.  
  2396.             Count = 0xFFFF;
  2397.  
  2398.             while (Count) {
  2399.  
  2400.                 NdisRawReadPortUchar(
  2401.                               Adapter->IoPAddr + NIC_INTR_STATUS,
  2402.                               &IsrValue
  2403.                              );
  2404.  
  2405.                 if (IsrValue & ISR_DMA_DONE) {
  2406.  
  2407.                     break;
  2408.  
  2409.                 } else {
  2410.  
  2411.                     Count--;
  2412.  
  2413.                     NdisStallExecution(4);
  2414.  
  2415.                 }
  2416.  
  2417. #if DBG
  2418.                 if (!(IsrValue & ISR_DMA_DONE)) {
  2419.  
  2420.                     DbgPrint("CopyUpDMA didn't finish!");
  2421.  
  2422.                 }
  2423. #endif // DBG
  2424.  
  2425.             }
  2426.  
  2427.             SourceBuffer++;
  2428.             TargetBuffer++;
  2429.             BufferLength--;
  2430.         }
  2431.  
  2432.         //
  2433.         // Set Count and destination address
  2434.         //
  2435.  
  2436.         NdisRawWritePortUchar(
  2437.                            Adapter->IoPAddr + NIC_RMT_ADDR_LSB,
  2438.                            LSB(SourceBuffer)
  2439.                           );
  2440.  
  2441.         NdisRawWritePortUchar(
  2442.                            Adapter->IoPAddr + NIC_RMT_ADDR_MSB,
  2443.                            MSB(SourceBuffer)
  2444.                           );
  2445.  
  2446. // UM9008 PCMCIA CHANGE!!!  start
  2447.  
  2448. //        NdisRawWritePortUchar(
  2449. //            Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2450. //            LSB(BufferLength)
  2451. //        );
  2452. //
  2453. //        NdisRawWritePortUchar(
  2454. //            Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2455. //            MSB(BufferLength)
  2456. //        );
  2457.  
  2458.         if (BufferLength & 1)
  2459.         {
  2460.             NdisRawWritePortUchar(
  2461.                 Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2462.                 LSB(BufferLength + 1)
  2463.             );
  2464.  
  2465.             NdisRawWritePortUchar(
  2466.                 Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2467.                 MSB(BufferLength + 1)
  2468.             );
  2469.         }
  2470.         else
  2471.         {
  2472.             NdisRawWritePortUchar(
  2473.                 Adapter->IoPAddr + NIC_RMT_COUNT_LSB,
  2474.                 LSB(BufferLength)
  2475.             );
  2476.  
  2477.             NdisRawWritePortUchar(
  2478.                 Adapter->IoPAddr + NIC_RMT_COUNT_MSB,
  2479.                 MSB(BufferLength)
  2480.             );
  2481.         }
  2482.  
  2483. // UM9008 PCMCIA CHANGE!!!  end
  2484.  
  2485.  
  2486.         //
  2487.         // Set direction (Read)
  2488.         //
  2489.  
  2490.         NdisRawWritePortUchar(
  2491.                        Adapter->IoPAddr + NIC_COMMAND,
  2492.                        CR_START | CR_PAGE0 | CR_DMA_READ
  2493.                       );
  2494.  
  2495.         //
  2496.         // Read words from port
  2497.         //
  2498.  
  2499.         NdisRawReadPortBufferUshort(
  2500.                        Adapter->IoPAddr + NIC_RACK_NIC,
  2501.                        (PUSHORT)TargetBuffer,
  2502.                        (BufferLength >> 1));
  2503.  
  2504.         //
  2505.         // Read trailing byte (if necessary)
  2506.         //
  2507.  
  2508.         if (BufferLength & 1) {
  2509.  
  2510.             TargetBuffer += (BufferLength - 1);
  2511.  
  2512. // UM9008 PCMCIA CHANGE!!!  start
  2513.  
  2514.             //NdisRawReadPortUchar(
  2515.             //    Adapter->IoPAddr + NIC_RACK_NIC,
  2516.             //    TargetBuffer
  2517.             //);
  2518.  
  2519.             NdisRawReadPortUshort(
  2520.                 Adapter->IoPAddr + NIC_RACK_NIC,
  2521.                 &Tmp
  2522.             );
  2523.  
  2524.             *TargetBuffer = LSB(Tmp);
  2525.  
  2526. // UM9008 PCMCIA CHANGE!!!  end
  2527.         }
  2528.  
  2529.     }
  2530.  
  2531.     //
  2532.     // Wait for DMA to complete
  2533.     //
  2534.  
  2535.     Count = 0xFFFF;
  2536.  
  2537.     while (Count) {
  2538.  
  2539.         NdisRawReadPortUchar(
  2540.                       Adapter->IoPAddr + NIC_INTR_STATUS,
  2541.                       &IsrValue
  2542.                      );
  2543.  
  2544.         if (IsrValue & ISR_DMA_DONE) {
  2545.  
  2546.             break;
  2547.  
  2548.         } else {
  2549.  
  2550.             Count--;
  2551.  
  2552.             NdisStallExecution(4);
  2553.  
  2554.         }
  2555.  
  2556.     }
  2557.  
  2558. #if DBG
  2559.     if (!(IsrValue & ISR_DMA_DONE)) {
  2560.  
  2561.         DbgPrint("CopyUpDMA didn't finish!\n");
  2562.  
  2563.     }
  2564.  
  2565.     IF_LOG(UM9008Log('<');)
  2566.  
  2567. #endif // DBG
  2568.  
  2569.     return TRUE;
  2570.  
  2571. }
  2572.  
  2573. ULONG
  2574. CardComputeCrc(
  2575.     IN PUCHAR Buffer,
  2576.     IN UINT Length
  2577.     )
  2578.  
  2579. /*++
  2580.  
  2581. Routine Description:
  2582.  
  2583.     Runs the AUTODIN II CRC algorithm on buffer Buffer of
  2584.     length Length.
  2585.  
  2586. Arguments:
  2587.  
  2588.     Buffer - the input buffer
  2589.  
  2590.     Length - the length of Buffer
  2591.  
  2592. Return Value:
  2593.  
  2594.     The 32-bit CRC value.
  2595.  
  2596. Note:
  2597.  
  2598.     This is adapted from the comments in the assembly language
  2599.     version in _GENREQ.ASM of the DWB NE2000 driver.
  2600.  
  2601. --*/
  2602.  
  2603. {
  2604.     ULONG Crc, Carry;
  2605.     UINT i, j;
  2606.     UCHAR CurByte;
  2607.  
  2608.     Crc = 0xffffffff;
  2609.  
  2610.     for (i = 0; i < Length; i++) {
  2611.  
  2612.         CurByte = Buffer[i];
  2613.  
  2614.         for (j = 0; j < 8; j++) {
  2615.  
  2616.             Carry = ((Crc & 0x80000000) ? 1 : 0) ^ (CurByte & 0x01);
  2617.  
  2618.             Crc <<= 1;
  2619.  
  2620.             CurByte >>= 1;
  2621.  
  2622.             if (Carry) {
  2623.  
  2624.                 Crc = (Crc ^ 0x04c11db6) | Carry;
  2625.  
  2626.             }
  2627.  
  2628.         }
  2629.  
  2630.     }
  2631.  
  2632.     return Crc;
  2633.  
  2634. }
  2635.  
  2636.  
  2637. VOID
  2638. CardGetMulticastBit(
  2639.     IN UCHAR Address[UM9008_LENGTH_OF_ADDRESS],
  2640.     OUT UCHAR * Byte,
  2641.     OUT UCHAR * Value
  2642.     )
  2643.  
  2644. /*++
  2645.  
  2646. Routine Description:
  2647.  
  2648.     For a given multicast address, returns the byte and bit in
  2649.     the card multicast registers that it hashes to. Calls
  2650.     CardComputeCrc() to determine the CRC value.
  2651.  
  2652. Arguments:
  2653.  
  2654.     Address - the address
  2655.  
  2656.     Byte - the byte that it hashes to
  2657.  
  2658.     Value - will have a 1 in the relevant bit
  2659.  
  2660. Return Value:
  2661.  
  2662.     None.
  2663.  
  2664. --*/
  2665.  
  2666. {
  2667.     ULONG Crc;
  2668.     UINT BitNumber;
  2669.  
  2670.     //
  2671.     // First compute the CRC.
  2672.     //
  2673.  
  2674.     Crc = CardComputeCrc(Address, UM9008_LENGTH_OF_ADDRESS);
  2675.  
  2676.  
  2677.     //
  2678.     // The bit number is now in the 6 most significant bits of CRC.
  2679.     //
  2680.  
  2681.     BitNumber = (UINT)((Crc >> 26) & 0x3f);
  2682.  
  2683.     *Byte = (UCHAR)(BitNumber / 8);
  2684.     *Value = (UCHAR)((UCHAR)1 << (BitNumber % 8));
  2685. }
  2686.  
  2687. VOID
  2688. CardFillMulticastRegs(
  2689.     IN PUM9008_ADAPTER Adapter
  2690.     )
  2691.  
  2692. /*++
  2693.  
  2694. Routine Description:
  2695.  
  2696.     Erases and refills the card multicast registers. Used when
  2697.     an address has been deleted and all bits must be recomputed.
  2698.  
  2699. Arguments:
  2700.  
  2701.     Adapter - pointer to the adapter block
  2702.  
  2703. Return Value:
  2704.  
  2705.     None.
  2706.  
  2707. --*/
  2708.  
  2709. {
  2710.     UINT i;
  2711.     UCHAR Byte, Bit;
  2712.  
  2713.     //
  2714.     // First turn all bits off.
  2715.     //
  2716.  
  2717.     for (i=0; i<8; i++) {
  2718.  
  2719.         Adapter->NicMulticastRegs[i] = 0;
  2720.  
  2721.     }
  2722.  
  2723.     //
  2724.     // Now turn on the bit for each address in the multicast list.
  2725.     //
  2726.  
  2727.     for ( ; i > 0; ) {
  2728.  
  2729.         i--;
  2730.  
  2731.         CardGetMulticastBit(Adapter->Addresses[i], &Byte, &Bit);
  2732.  
  2733.         Adapter->NicMulticastRegs[Byte] |= Bit;
  2734.  
  2735.     }
  2736.  
  2737. }
  2738.  
  2739.  
  2740.  
  2741.  
  2742.  
  2743.  
  2744.  
  2745.  
  2746. BOOLEAN SyncCardStop(
  2747.     IN PVOID SynchronizeContext
  2748. )
  2749.  
  2750. /*++
  2751.  
  2752. Routine Description:
  2753.  
  2754.     Sets the NIC_COMMAND register to stop the card.
  2755.  
  2756. Arguments:
  2757.  
  2758.     SynchronizeContext - pointer to the adapter block
  2759.  
  2760. Return Value:
  2761.  
  2762.     TRUE if the power has failed.
  2763.  
  2764. --*/
  2765.  
  2766. {
  2767.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  2768.  
  2769.     NdisRawWritePortUchar(
  2770.         Adapter->IoPAddr + NIC_COMMAND,
  2771.         CR_STOP | CR_NO_DMA
  2772.     );
  2773.  
  2774.     return(FALSE);
  2775. }
  2776.  
  2777. VOID
  2778. CardStartXmit(
  2779.     IN PUM9008_ADAPTER Adapter
  2780.     )
  2781.  
  2782. /*++
  2783.  
  2784. Routine Description:
  2785.  
  2786.     Sets the NIC_COMMAND register to start a transmission.
  2787.     The transmit buffer number is taken from Adapter->CurBufXmitting
  2788.     and the length from Adapter->PacketLens[Adapter->CurBufXmitting].
  2789.  
  2790. Arguments:
  2791.  
  2792.     Adapter - pointer to the adapter block
  2793.  
  2794. Return Value:
  2795.  
  2796.     TRUE if the power has failed.
  2797.  
  2798. --*/
  2799.  
  2800. {
  2801.     UINT Length = Adapter->PacketLens[Adapter->CurBufXmitting];
  2802.     UCHAR Tmp;
  2803.  
  2804.     //
  2805.     // Prepare the NIC registers for transmission.
  2806.     //
  2807.  
  2808.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_START,
  2809.         (UCHAR)(Adapter->NicXmitStart + (UCHAR)(Adapter->CurBufXmitting*BUFS_PER_TX)));
  2810.  
  2811.     //
  2812.     // Pad the length to 60 (plus CRC will be 64) if needed.
  2813.     //
  2814.  
  2815.     if (Length < 60) {
  2816.  
  2817.         Length = 60;
  2818.  
  2819.     }
  2820.  
  2821.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_MSB, MSB(Length));
  2822.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_XMIT_COUNT_LSB, LSB(Length));
  2823.  
  2824.     //
  2825.     // Start transmission, check for power failure first.
  2826.     //
  2827.  
  2828.     NdisRawReadPortUchar(Adapter->IoPAddr+NIC_COMMAND, &Tmp);
  2829.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2830.             CR_START | CR_XMIT | CR_NO_DMA);
  2831.  
  2832.     IF_LOG( UM9008Log('x');)
  2833.  
  2834. }
  2835.  
  2836. BOOLEAN
  2837. SyncCardGetCurrent(
  2838.     IN PVOID SynchronizeContext
  2839.     )
  2840.  
  2841. /*++
  2842.  
  2843. Routine Description:
  2844.  
  2845.     Gets the value of the CURRENT NIC register and stores it in Adapter->Current
  2846.  
  2847. Arguments:
  2848.  
  2849.     SynchronizeContext - pointer to the adapter block
  2850.  
  2851. Return Value:
  2852.  
  2853.     None.
  2854.  
  2855. --*/
  2856.  
  2857. {
  2858.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  2859.  
  2860.     //
  2861.     // Have to go to page 1 to read this register
  2862.     //
  2863.  
  2864.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2865.                        CR_START | CR_NO_DMA | CR_PAGE1);
  2866.  
  2867.     NdisRawReadPortUchar(Adapter->IoPAddr+NIC_CURRENT,
  2868.                        &Adapter->Current);
  2869.  
  2870.     NdisRawWritePortUchar(Adapter->IoPAddr+NIC_COMMAND,
  2871.                        CR_START | CR_NO_DMA | CR_PAGE0);
  2872.  
  2873.     return FALSE;
  2874.  
  2875. }
  2876.  
  2877. BOOLEAN
  2878. SyncCardGetXmitStatus(
  2879.     IN PVOID SynchronizeContext
  2880.     )
  2881.  
  2882. /*++
  2883.  
  2884. Routine Description:
  2885.  
  2886.     Gets the value of the "transmit status" NIC register and stores
  2887.     it in Adapter->XmitStatus.
  2888.  
  2889. Arguments:
  2890.  
  2891.     SynchronizeContext - pointer to the adapter block
  2892.  
  2893. Return Value:
  2894.  
  2895.     None.
  2896.  
  2897. --*/
  2898.  
  2899. {
  2900.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  2901.  
  2902.     NdisRawReadPortUchar( Adapter->IoPAddr+NIC_XMIT_STATUS, &Adapter->XmitStatus);
  2903.  
  2904.     return FALSE;
  2905.  
  2906. }
  2907.  
  2908. VOID
  2909. CardSetBoundary(
  2910.     IN PUM9008_ADAPTER Adapter
  2911.     )
  2912.  
  2913. /*++
  2914.  
  2915. Routine Description:
  2916.  
  2917.     Sets the value of the "boundary" NIC register to one behind
  2918.     Adapter->NicNextPacket, to prevent packets from being received
  2919.     on top of un-indicated ones.
  2920.  
  2921. Arguments:
  2922.  
  2923.     Adapter - pointer to the adapter block
  2924.  
  2925. Return Value:
  2926.  
  2927.     None.
  2928.  
  2929. --*/
  2930.  
  2931. {
  2932.     //
  2933.     // Have to be careful with "one behind NicNextPacket" when
  2934.     // NicNextPacket is the first buffer in receive area.
  2935.     //
  2936.  
  2937.     if (Adapter->NicNextPacket == Adapter->NicPageStart) {
  2938.  
  2939.         NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
  2940.                     (UCHAR)(Adapter->NicPageStop-(UCHAR)1));
  2941.  
  2942.     } else {
  2943.  
  2944.         NdisRawWritePortUchar( Adapter->IoPAddr+NIC_BOUNDARY,
  2945.                     (UCHAR)(Adapter->NicNextPacket-(UCHAR)1));
  2946.  
  2947.     }
  2948.  
  2949. }
  2950.  
  2951. BOOLEAN
  2952. SyncCardSetReceiveConfig(
  2953.     IN PVOID SynchronizeContext
  2954.     )
  2955.  
  2956. /*++
  2957.  
  2958. Routine Description:
  2959.  
  2960.     Sets the value of the "receive configuration" NIC register to
  2961.     the value of Adapter->NicReceiveConfig.
  2962.  
  2963. Arguments:
  2964.  
  2965.     SynchronizeContext - pointer to the adapter block
  2966.  
  2967. Return Value:
  2968.  
  2969.     None.
  2970.  
  2971. --*/
  2972.  
  2973. {
  2974.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  2975.  
  2976.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RCV_CONFIG, Adapter->NicReceiveConfig);
  2977.  
  2978.     return FALSE;
  2979.  
  2980. }
  2981.  
  2982. BOOLEAN
  2983. SyncCardSetAllMulticast(
  2984.     IN PVOID SynchronizeContext
  2985.     )
  2986.  
  2987. /*++
  2988.  
  2989. Routine Description:
  2990.  
  2991.     Turns on all the bits in the multicast register. Used when
  2992.     the card must receive all multicast packets.
  2993.  
  2994. Arguments:
  2995.  
  2996.     SynchronizeContext - pointer to the adapter block
  2997.  
  2998. Return Value:
  2999.  
  3000.     None.
  3001.  
  3002. --*/
  3003.  
  3004. {
  3005.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  3006.     UINT i;
  3007.  
  3008.     //
  3009.     // Have to move to page 1 to set these registers.
  3010.     //
  3011.  
  3012.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  3013.                     CR_START | CR_NO_DMA | CR_PAGE1);
  3014.  
  3015.     for (i=0; i<8; i++) {
  3016.  
  3017.         NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i), 0xff);
  3018.  
  3019.     }
  3020.  
  3021.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  3022.                     CR_START | CR_NO_DMA | CR_PAGE0);
  3023.  
  3024.     return FALSE;
  3025.  
  3026. }
  3027.  
  3028. BOOLEAN
  3029. SyncCardCopyMulticastRegs(
  3030.     IN PVOID SynchronizeContext
  3031.     )
  3032.  
  3033. /*++
  3034.  
  3035. Routine Description:
  3036.  
  3037.     Sets the eight bytes in the card multicast registers.
  3038.  
  3039. Arguments:
  3040.  
  3041.     SynchronizeContext - pointer to the adapter block
  3042.  
  3043. Return Value:
  3044.  
  3045.     None.
  3046.  
  3047. --*/
  3048.  
  3049. {
  3050.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  3051.     UINT i;
  3052.  
  3053.     //
  3054.     // Have to move to page 1 to set these registers.
  3055.     //
  3056.  
  3057.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  3058.                     CR_START | CR_NO_DMA | CR_PAGE1);
  3059.  
  3060.     for (i=0; i<8; i++) {
  3061.  
  3062.         NdisRawWritePortUchar( Adapter->IoPAddr+(NIC_MC_ADDR+i),
  3063.                         Adapter->NicMulticastRegs[i]);
  3064.  
  3065.     }
  3066.  
  3067.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND,
  3068.                     CR_START | CR_NO_DMA | CR_PAGE0);
  3069.  
  3070.     return FALSE;
  3071.  
  3072. }
  3073.  
  3074. BOOLEAN
  3075. SyncCardAcknowledgeOverflow(
  3076.     IN PVOID SynchronizeContext
  3077.     )
  3078.  
  3079. /*++
  3080.  
  3081. Routine Description:
  3082.  
  3083.     Sets the "buffer overflow" bit in the NIC interrupt status register,
  3084.     which re-enables interrupts of that type.
  3085.  
  3086. Arguments:
  3087.  
  3088.     SynchronizeContext - pointer to the adapter block
  3089.  
  3090. Return Value:
  3091.  
  3092.     None.
  3093.  
  3094. --*/
  3095.  
  3096. {
  3097.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  3098.     UCHAR AcknowledgeMask = 0;
  3099.  
  3100.     if (Adapter->InterruptStatus & ISR_RCV_ERR) {
  3101.  
  3102.         SyncCardUpdateCounters(Adapter);
  3103.  
  3104.     }
  3105.  
  3106.     return FALSE;
  3107.  
  3108. }
  3109.  
  3110. BOOLEAN
  3111. SyncCardUpdateCounters(
  3112.     IN PVOID SynchronizeContext
  3113.     )
  3114.  
  3115. /*++
  3116.  
  3117. Routine Description:
  3118.  
  3119.     Updates the values of the three counters (frame alignment errors,
  3120.     CRC errors, and missed packets).
  3121.  
  3122. Arguments:
  3123.  
  3124.     SynchronizeContext - pointer to the adapter block
  3125.  
  3126. Return Value:
  3127.  
  3128.     None.
  3129.  
  3130. --*/
  3131.  
  3132. {
  3133.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  3134.     UCHAR Tmp;
  3135.  
  3136.     NdisRawReadPortUchar( Adapter->IoPAddr+NIC_FAE_ERR_CNTR, &Tmp);
  3137.     Adapter->FrameAlignmentErrors += Tmp;
  3138.  
  3139.     NdisRawReadPortUchar( Adapter->IoPAddr+NIC_CRC_ERR_CNTR, &Tmp);
  3140.     Adapter->CrcErrors += Tmp;
  3141.  
  3142.     NdisRawReadPortUchar( Adapter->IoPAddr+NIC_MISSED_CNTR, &Tmp);
  3143.     Adapter->MissedPackets += Tmp;
  3144.  
  3145.     return FALSE;
  3146.  
  3147. }
  3148.  
  3149. BOOLEAN
  3150. SyncCardHandleOverflow(
  3151.     IN PVOID SynchronizeContext
  3152.     )
  3153.  
  3154. /*++<
  3155.  
  3156. Routine Description:
  3157.  
  3158.     Sets all the flags for dealing with a receive overflow, stops the card
  3159.     and acknowledges all outstanding interrupts.
  3160.  
  3161. Arguments:
  3162.  
  3163.     SynchronizeContext - pointer to the adapter block
  3164.  
  3165. Return Value:
  3166.  
  3167.     None.
  3168.  
  3169. --*/
  3170.  
  3171. {
  3172.     PUM9008_ADAPTER Adapter = ((PUM9008_ADAPTER)SynchronizeContext);
  3173.     UCHAR Status;
  3174.  
  3175.     IF_LOG( UM9008Log('F');)
  3176.  
  3177.     //
  3178.     // Turn on the STOP bit in the Command register.
  3179.     //
  3180.  
  3181.     SyncCardStop(Adapter);
  3182.  
  3183.     //
  3184.     // Wait for ISR_RESET, but only for 1.6 milliseconds (as
  3185.     // described in the March 1991 8390 addendum), since that
  3186.     // is the maximum time for a software reset to occur.
  3187.     //
  3188.     //
  3189.  
  3190.     NdisStallExecution(2000);
  3191.  
  3192.     //
  3193.     // Save whether we were transmitting to avoid a timing problem
  3194.     // where an indication resulted in a send.
  3195.     //
  3196.  
  3197.     if (!(Adapter->InterruptStatus & (ISR_XMIT | ISR_XMIT_ERR))) {
  3198.  
  3199.         CardGetInterruptStatus(Adapter,&Status);
  3200.         if (!(Status & (ISR_XMIT | ISR_XMIT_ERR))) {
  3201.  
  3202.             Adapter->OverflowRestartXmitDpc = Adapter->TransmitInterruptPending;
  3203.  
  3204.             IF_LOUD( DbgPrint("ORXD=%x\n",Adapter->OverflowRestartXmitDpc); )
  3205.         }
  3206.  
  3207.     }
  3208.  
  3209.     Adapter->TransmitInterruptPending = FALSE;
  3210.  
  3211.     //
  3212.     // Clear the Remote Byte Count register so that ISR_RESET
  3213.     // will come on.
  3214.     //
  3215.  
  3216.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_MSB, 0);
  3217.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_RMT_COUNT_LSB, 0);
  3218.  
  3219.     //
  3220.     // According to National Semiconductor, the next check is necessary
  3221.     // See Step 5. of the overflow process
  3222.     //
  3223.     // NOTE: The setting of variables to check if the transmit has completed
  3224.     // cannot be done here because anything in the ISR has already been ack'ed
  3225.     // inside the main DPC.  Thus, the setting of the variables, described in
  3226.     // the Handbook was moved to the main DPC.
  3227.     //
  3228.     // Continued: If you did the check here, you will doubly transmit most
  3229.     // packets that happened to be on the card when the overflow occurred.
  3230.     //
  3231.  
  3232.     //
  3233.     // Put the card in loopback mode, then start it.
  3234.     //
  3235.  
  3236.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_XMIT_CONFIG, TCR_LOOPBACK);
  3237.  
  3238.     //
  3239.     // Start the card.  This does not Undo the loopback mode.
  3240.     //
  3241.  
  3242.     NdisRawWritePortUchar( Adapter->IoPAddr+NIC_COMMAND, CR_START | CR_NO_DMA);
  3243.  
  3244.     return FALSE;
  3245.  
  3246. }
  3247.  
  3248.