Merge trunk head (r43756)
[reactos.git] / reactos / drivers / network / dd / pcnet / pcnet.c
index f1fbf06..5be9d6e 100644 (file)
 #include <debug.h>
 
 NTSTATUS
-STDCALL
+NTAPI
 DriverEntry(
     IN PDRIVER_OBJECT DriverObject,
     IN PUNICODE_STRING RegistryPath);
 
 static VOID
-STDCALL
+NTAPI
 MiniportHandleInterrupt(
     IN NDIS_HANDLE MiniportAdapterContext)
 /*
@@ -66,6 +66,7 @@ MiniportHandleInterrupt(
 {
   PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
   USHORT Data;
+  UINT i = 0;
 
   DPRINT("Called\n");
 
@@ -78,7 +79,7 @@ MiniportHandleInterrupt(
 
   DPRINT("CSR0 is 0x%x\n", Data);
 
-  while(Data & CSR0_INTR)
+  while((Data & CSR0_INTR) && i++ < INTERRUPT_LIMIT)
     {
       /* Clear interrupt flags early to avoid race conditions. */
       NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
@@ -95,6 +96,8 @@ MiniportHandleInterrupt(
         }
       if(Data & CSR0_RINT)
         {
+          BOOLEAN IndicatedData = FALSE;
+
           DPRINT("receive interrupt\n");
 
           while(1)
@@ -135,11 +138,12 @@ MiniportHandleInterrupt(
               DPRINT("Indicating a %d-byte packet (index %d)\n", ByteCount, Adapter->CurrentReceiveDescriptorIndex);
 
               NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, 0, Buffer, 14, Buffer+14, ByteCount-14, ByteCount-14);
-              NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
+
+              IndicatedData = TRUE;
 
               RtlZeroMemory(Descriptor, sizeof(RECEIVE_DESCRIPTOR));
               Descriptor->RBADR =
-                  (ULONG)(Adapter->ReceiveBufferPtrPhys + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE);
+                  (ULONG_PTR)(Adapter->ReceiveBufferPtrPhys + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE);
               Descriptor->BCNT = (-BUFFER_SIZE) | 0xf000;
               Descriptor->FLAGS |= RD_OWN;
 
@@ -148,6 +152,9 @@ MiniportHandleInterrupt(
 
               Adapter->Statistics.RcvGoodFrames++;
             }
+
+            if (IndicatedData)
+                NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
         }
       if(Data & CSR0_TINT)
         {
@@ -325,14 +332,14 @@ MiAllocateSharedMemory(
       return NDIS_STATUS_RESOURCES;
     }
 
-  if(((ULONG)Adapter->InitializationBlockVirt & 0x00000003) != 0)
+  if(((ULONG_PTR)Adapter->InitializationBlockVirt & 0x00000003) != 0)
     {
       DPRINT("address 0x%x not dword-aligned\n", Adapter->InitializationBlockVirt);
       BREAKPOINT;
       return NDIS_STATUS_RESOURCES;
     }
 
-  Adapter->InitializationBlockPhys = (PINITIALIZATION_BLOCK)NdisGetPhysicalAddressLow(PhysicalAddress);
+  Adapter->InitializationBlockPhys = (PINITIALIZATION_BLOCK)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress);
 
   /* allocate the transport descriptor ring */
   Adapter->TransmitDescriptorRingLength = sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS;
@@ -345,14 +352,14 @@ MiAllocateSharedMemory(
       return NDIS_STATUS_RESOURCES;
     }
 
-  if(((ULONG)Adapter->TransmitDescriptorRingVirt & 0x00000003) != 0)
+  if(((ULONG_PTR)Adapter->TransmitDescriptorRingVirt & 0x00000003) != 0)
     {
       DPRINT("address 0x%x not dword-aligned\n", Adapter->TransmitDescriptorRingVirt);
       BREAKPOINT;
       return NDIS_STATUS_RESOURCES;
     }
 
-  Adapter->TransmitDescriptorRingPhys = (PTRANSMIT_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress);
+  Adapter->TransmitDescriptorRingPhys = (PTRANSMIT_DESCRIPTOR)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress);
   RtlZeroMemory(Adapter->TransmitDescriptorRingVirt, sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS);
 
   /* allocate the receive descriptor ring */
@@ -366,14 +373,14 @@ MiAllocateSharedMemory(
       return NDIS_STATUS_RESOURCES;
     }
 
-  if(((ULONG)Adapter->ReceiveDescriptorRingVirt & 0x00000003) != 0)
+  if(((ULONG_PTR)Adapter->ReceiveDescriptorRingVirt & 0x00000003) != 0)
     {
       DPRINT("address 0x%x not dword-aligned\n", Adapter->ReceiveDescriptorRingVirt);
       BREAKPOINT;
       return NDIS_STATUS_RESOURCES;
     }
 
-  Adapter->ReceiveDescriptorRingPhys = (PRECEIVE_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress);
+  Adapter->ReceiveDescriptorRingPhys = (PRECEIVE_DESCRIPTOR)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress);
   RtlZeroMemory(Adapter->ReceiveDescriptorRingVirt, sizeof(RECEIVE_DESCRIPTOR) * NUMBER_OF_BUFFERS);
 
   /* allocate transmit buffers */
@@ -387,14 +394,14 @@ MiAllocateSharedMemory(
       return NDIS_STATUS_RESOURCES;
     }
 
-  if(((ULONG)Adapter->TransmitBufferPtrVirt & 0x00000003) != 0)
+  if(((ULONG_PTR)Adapter->TransmitBufferPtrVirt & 0x00000003) != 0)
     {
       DPRINT("address 0x%x not dword-aligned\n", Adapter->TransmitBufferPtrVirt);
       BREAKPOINT;
       return NDIS_STATUS_RESOURCES;
     }
 
-  Adapter->TransmitBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress);
+  Adapter->TransmitBufferPtrPhys = (PCHAR)(ULONG_PTR)NdisGetPhysicalAddressLow(PhysicalAddress);
   RtlZeroMemory(Adapter->TransmitBufferPtrVirt, BUFFER_SIZE * NUMBER_OF_BUFFERS);
 
   /* allocate receive buffers */
@@ -408,21 +415,21 @@ MiAllocateSharedMemory(
       return NDIS_STATUS_RESOURCES;
     }
 
-  if(((ULONG)Adapter->ReceiveBufferPtrVirt & 0x00000003) != 0)
+  if(((ULONG_PTR)Adapter->ReceiveBufferPtrVirt & 0x00000003) != 0)
     {
       DPRINT("address 0x%x not dword-aligned\n", Adapter->ReceiveBufferPtrVirt);
       BREAKPOINT;
       return NDIS_STATUS_RESOURCES;
     }
 
-  Adapter->ReceiveBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress);
+  Adapter->ReceiveBufferPtrPhys = (PCHAR)(ULONG_PTR)NdisGetPhysicalAddressLow(PhysicalAddress);
   RtlZeroMemory(Adapter->ReceiveBufferPtrVirt, BUFFER_SIZE * NUMBER_OF_BUFFERS);
 
   /* initialize tx descriptors */
   TransmitDescriptor = Adapter->TransmitDescriptorRingVirt;
   for(i = 0; i < NUMBER_OF_BUFFERS; i++)
     {
-      (TransmitDescriptor+i)->TBADR = (ULONG)Adapter->TransmitBufferPtrPhys + i * BUFFER_SIZE;
+      (TransmitDescriptor+i)->TBADR = (ULONG_PTR)Adapter->TransmitBufferPtrPhys + i * BUFFER_SIZE;
       (TransmitDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment  + set top 4 bits */
       (TransmitDescriptor+i)->FLAGS = TD1_STP | TD1_ENP;
     }
@@ -433,7 +440,7 @@ MiAllocateSharedMemory(
   ReceiveDescriptor = Adapter->ReceiveDescriptorRingVirt;
   for(i = 0; i < NUMBER_OF_BUFFERS; i++)
     {
-      (ReceiveDescriptor+i)->RBADR = (ULONG)Adapter->ReceiveBufferPtrPhys + i * BUFFER_SIZE;
+      (ReceiveDescriptor+i)->RBADR = (ULONG_PTR)Adapter->ReceiveBufferPtrPhys + i * BUFFER_SIZE;
       (ReceiveDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment  + set top 4 bits */
       (ReceiveDescriptor+i)->FLAGS = RD_OWN;
     }
@@ -469,12 +476,12 @@ MiPrepareInitializationBlock(
 
   /* set up receive ring */
   DPRINT("Receive ring physical address: 0x%x\n", Adapter->ReceiveDescriptorRingPhys);
-  Adapter->InitializationBlockVirt->RDRA = (ULONG)Adapter->ReceiveDescriptorRingPhys;
+  Adapter->InitializationBlockVirt->RDRA = (ULONG_PTR)Adapter->ReceiveDescriptorRingPhys;
   Adapter->InitializationBlockVirt->RLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
 
   /* set up transmit ring */
   DPRINT("Transmit ring physical address: 0x%x\n", Adapter->TransmitDescriptorRingPhys);
-  Adapter->InitializationBlockVirt->TDRA = (ULONG)Adapter->TransmitDescriptorRingPhys;
+  Adapter->InitializationBlockVirt->TDRA = (ULONG_PTR)Adapter->TransmitDescriptorRingPhys;
   Adapter->InitializationBlockVirt->TLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
 }
 
@@ -493,42 +500,42 @@ MiFreeSharedMemory(
 
   if(Adapter->InitializationBlockVirt)
     {
-      PhysicalAddress.u.LowPart = (ULONG)Adapter->InitializationBlockPhys;
+      PhysicalAddress.u.LowPart = (ULONG_PTR)Adapter->InitializationBlockPhys;
       NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength,
           FALSE, Adapter->InitializationBlockVirt, PhysicalAddress);
     }
 
   if(Adapter->TransmitDescriptorRingVirt)
     {
-      PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitDescriptorRingPhys;
+      PhysicalAddress.u.LowPart = (ULONG_PTR)Adapter->TransmitDescriptorRingPhys;
       NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength,
         FALSE, Adapter->TransmitDescriptorRingVirt, PhysicalAddress);
     }
 
   if(Adapter->ReceiveDescriptorRingVirt)
     {
-      PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveDescriptorRingPhys;
+      PhysicalAddress.u.LowPart = (ULONG_PTR)Adapter->ReceiveDescriptorRingPhys;
       NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength,
           FALSE, Adapter->ReceiveDescriptorRingVirt, PhysicalAddress);
     }
 
   if(Adapter->TransmitBufferPtrVirt)
     {
-      PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitBufferPtrPhys;
+      PhysicalAddress.u.LowPart = (ULONG_PTR)Adapter->TransmitBufferPtrPhys;
       NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength,
           FALSE, Adapter->TransmitBufferPtrVirt, PhysicalAddress);
     }
 
   if(Adapter->ReceiveBufferPtrVirt)
     {
-      PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveBufferPtrPhys;
+      PhysicalAddress.u.LowPart = (ULONG_PTR)Adapter->ReceiveBufferPtrPhys;
       NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength,
           FALSE, Adapter->ReceiveBufferPtrVirt, PhysicalAddress);
     }
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncStop(
     IN PVOID SynchronizeContext)
 /*
@@ -544,7 +551,7 @@ MiSyncStop(
 }
 
 static VOID
-STDCALL
+NTAPI
 MiniportHalt(
     IN NDIS_HANDLE MiniportAdapterContext)
 /*
@@ -590,7 +597,7 @@ MiniportHalt(
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncMediaDetection(
     IN PVOID SynchronizeContext)
 /*
@@ -601,19 +608,25 @@ MiSyncMediaDetection(
 {
   PADAPTER Adapter = (PADAPTER)SynchronizeContext;
   NDIS_MEDIA_STATE MediaState = MiGetMediaState(Adapter);
+  UINT MediaSpeed = MiGetMediaSpeed(Adapter);
+  BOOLEAN FullDuplex = MiGetMediaDuplex(Adapter);
 
   DPRINT("Called\n");
   DPRINT("MediaState: %d\n", MediaState);
-  if (MediaState != Adapter->MediaState)
+  if (MediaState != Adapter->MediaState ||
+      MediaSpeed != Adapter->MediaSpeed ||
+      FullDuplex != Adapter->FullDuplex)
     {
       Adapter->MediaState = MediaState;
+      Adapter->MediaSpeed = MediaSpeed;
+      Adapter->FullDuplex = FullDuplex;
       return TRUE;
     }
   return FALSE;
 }
 
 static VOID
-STDCALL
+NTAPI
 MiniportMediaDetectionTimer(
     IN PVOID SystemSpecific1,
     IN PVOID FunctionContext,
@@ -700,9 +713,9 @@ MiInitChip(
 
   /* set up csr1 and csr2 with init block */
   NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR1);
-  NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys & 0xffff));
+  NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG_PTR)Adapter->InitializationBlockPhys & 0xffff));
   NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR2);
-  NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys >> 16) & 0xffff);
+  NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG_PTR)Adapter->InitializationBlockPhys >> 16) & 0xffff);
 
   DPRINT("programmed with init block\n");
 
@@ -715,10 +728,29 @@ MiInitChip(
   NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
   NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA);
 
-  /* detect the media state */
+  /* Allow LED programming */
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR2);
+  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR2_LEDPE);
+
+  /* LED0 is configured for link status (on = up, off = down) */
   NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR4);
-  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR4_LNKSTE|BCR4_FDLSE);
+  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR4_LNKSTE | BCR4_PSE);
+
+  /* LED1 is configured for link duplex (on = full, off = half) */
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR5);
+  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR5_FDLSE | BCR5_PSE);
+
+  /* LED2 is configured for link speed (on = 100M, off = 10M) */
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR6);
+  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR6_E100 | BCR6_PSE);
+
+  /* LED3 is configured for trasmit/receive activity */
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR7);
+  NdisRawWritePortUshort(Adapter->PortOffset + BDP, BCR7_XMTE | BCR7_RCVE | BCR7_PSE);
+
   Adapter->MediaState = MiGetMediaState(Adapter);
+  Adapter->FullDuplex = MiGetMediaDuplex(Adapter);
+  Adapter->MediaSpeed = MiGetMediaSpeed(Adapter);
 
   DPRINT("card started\n");
 
@@ -785,7 +817,7 @@ MiTestCard(
 #endif
 
 VOID
-STDCALL
+NTAPI
 MiniportShutdown( PVOID Context )
 {
   PADAPTER Adapter = Context;
@@ -797,7 +829,7 @@ MiniportShutdown( PVOID Context )
 }
 
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportInitialize(
     OUT PNDIS_STATUS OpenErrorStatus,
     OUT PUINT SelectedMediumIndex,
@@ -830,6 +862,9 @@ MiniportInitialize(
   PADAPTER Adapter = 0;
   NDIS_STATUS Status = NDIS_STATUS_FAILURE;
   BOOLEAN InterruptRegistered = FALSE;
+  NDIS_HANDLE ConfigurationHandle;
+  UINT *RegNetworkAddress = 0;
+  UINT RegNetworkAddressLength = 0;
 
   ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
 
@@ -924,6 +959,25 @@ MiniportInitialize(
       /* set up the initialization block */
       MiPrepareInitializationBlock(Adapter);
 
+      /* see if someone set a network address manually */
+      NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext);
+      if (Status == NDIS_STATUS_SUCCESS)
+      {
+         NdisReadNetworkAddress(&Status, (PVOID *)&RegNetworkAddress, &RegNetworkAddressLength, ConfigurationHandle);
+         if(Status == NDIS_STATUS_SUCCESS && RegNetworkAddressLength == 6)
+         {
+             int i;
+             DPRINT("NdisReadNetworkAddress returned successfully, address %x:%x:%x:%x:%x:%x\n",
+                     RegNetworkAddress[0], RegNetworkAddress[1], RegNetworkAddress[2], RegNetworkAddress[3],
+                     RegNetworkAddress[4], RegNetworkAddress[5]);
+
+             for(i = 0; i < 6; i++)
+                 Adapter->InitializationBlockVirt->PADR[i] = RegNetworkAddress[i];
+         }
+
+         NdisCloseConfiguration(ConfigurationHandle);
+      }
+
       DPRINT("Interrupt registered successfully\n");
 
       /* Initialize and start the chip */
@@ -960,6 +1014,9 @@ MiniportInitialize(
                            Adapter);
       NdisMSetPeriodicTimer(&Adapter->MediaDetectionTimer,
                             MEDIA_DETECTION_INTERVAL);
+      NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle,
+                                          Adapter,
+                                          MiniportShutdown);
     }
 
 #if DBG
@@ -967,15 +1024,13 @@ MiniportInitialize(
     ASSERT(0);
 #endif
 
-  NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle, Adapter, MiniportShutdown);
-
   DPRINT("returning 0x%x\n", Status);
   *OpenErrorStatus = Status;
   return Status;
 }
 
 static VOID
-STDCALL
+NTAPI
 MiniportISR(
     OUT PBOOLEAN InterruptRecognized,
     OUT PBOOLEAN QueueMiniportHandleInterrupt,
@@ -1028,7 +1083,7 @@ MiniportISR(
 }
 
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportReset(
     OUT PBOOLEAN AddressingReset,
     IN NDIS_HANDLE MiniportAdapterContext)
@@ -1055,7 +1110,7 @@ MiniportReset(
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncStartTransmit(
     IN PVOID SynchronizeContext)
 /*
@@ -1071,7 +1126,7 @@ MiSyncStartTransmit(
 }
 
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportSend(
     IN NDIS_HANDLE MiniportAdapterContext,
     IN PNDIS_PACKET Packet,
@@ -1162,7 +1217,7 @@ MiniportSend(
 }
 
 static ULONG
-STDCALL
+NTAPI
 MiEthernetCrc(UCHAR *Address)
 /*
  * FUNCTION: Calculate Ethernet CRC32
@@ -1189,7 +1244,7 @@ MiEthernetCrc(UCHAR *Address)
 }
 
 NDIS_STATUS
-STDCALL
+NTAPI
 MiSetMulticast(
     PADAPTER Adapter,
     UCHAR *Addresses,
@@ -1211,8 +1266,32 @@ MiSetMulticast(
   return NDIS_STATUS_SUCCESS;
 }
 
+BOOLEAN
+NTAPI
+MiGetMediaDuplex(PADAPTER Adapter)
+{
+  ULONG Data;
+
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR5);
+  NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data);
+
+  return Data & BCR5_LEDOUT;
+}
+
+UINT
+NTAPI
+MiGetMediaSpeed(PADAPTER Adapter)
+{
+  ULONG Data;
+
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR6);
+  NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data);
+
+  return Data & BCR6_LEDOUT ? 100 : 10;
+}
+
 NDIS_MEDIA_STATE
-STDCALL
+NTAPI
 MiGetMediaState(PADAPTER Adapter)
 /*
  * FUNCTION: Determine the link state
@@ -1230,7 +1309,7 @@ MiGetMediaState(PADAPTER Adapter)
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 DriverEntry(
     IN PDRIVER_OBJECT DriverObject,
     IN PUNICODE_STRING RegistryPath)
@@ -1264,6 +1343,7 @@ DriverEntry(
   Characteristics.SendHandler = MiniportSend;
 
   NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0);
+  if (!WrapperHandle) return NDIS_STATUS_FAILURE;
 
   Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
   if(Status != NDIS_STATUS_SUCCESS)