Merge trunk head (r43756)
[reactos.git] / reactos / drivers / network / dd / pcnet / pcnet.c
index d0ccb0e..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,9 +66,12 @@ MiniportHandleInterrupt(
 {
   PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
   USHORT Data;
+  UINT i = 0;
 
   DPRINT("Called\n");
 
+  ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
+
   NdisDprAcquireSpinLock(&Adapter->Lock);
 
   NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
@@ -76,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);
@@ -93,6 +96,8 @@ MiniportHandleInterrupt(
         }
       if(Data & CSR0_RINT)
         {
+          BOOLEAN IndicatedData = FALSE;
+
           DPRINT("receive interrupt\n");
 
           while(1)
@@ -133,7 +138,8 @@ 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 =
@@ -146,6 +152,9 @@ MiniportHandleInterrupt(
 
               Adapter->Statistics.RcvGoodFrames++;
             }
+
+            if (IndicatedData)
+                NdisMEthIndicateReceiveComplete(Adapter->MiniportAdapterHandle);
         }
       if(Data & CSR0_TINT)
         {
@@ -526,7 +535,7 @@ MiFreeSharedMemory(
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncStop(
     IN PVOID SynchronizeContext)
 /*
@@ -542,7 +551,7 @@ MiSyncStop(
 }
 
 static VOID
-STDCALL
+NTAPI
 MiniportHalt(
     IN NDIS_HANDLE MiniportAdapterContext)
 /*
@@ -571,6 +580,9 @@ MiniportHalt(
   /* deregister i/o port range */
   NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, (PVOID)Adapter->PortOffset);
 
+  /* deregister the shutdown routine */
+  NdisMDeregisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle);
+
   /* free shared memory */
   MiFreeSharedMemory(Adapter);
 
@@ -585,7 +597,7 @@ MiniportHalt(
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncMediaDetection(
     IN PVOID SynchronizeContext)
 /*
@@ -596,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,
@@ -624,6 +642,8 @@ MiniportMediaDetectionTimer(
 {
   PADAPTER Adapter = (PADAPTER)FunctionContext;
 
+  ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
+
   if (NdisMSynchronizeWithInterrupt(&Adapter->InterruptObject,
                                     MiSyncMediaDetection,
                                     FunctionContext))
@@ -708,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");
 
@@ -777,8 +816,20 @@ MiTestCard(
 }
 #endif
 
+VOID
+NTAPI
+MiniportShutdown( PVOID Context )
+{
+  PADAPTER Adapter = Context;
+
+  DPRINT("Stopping the chip\n");
+
+  NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
+  NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP);
+}
+
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportInitialize(
     OUT PNDIS_STATUS OpenErrorStatus,
     OUT PUINT SelectedMediumIndex,
@@ -811,6 +862,11 @@ 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);
 
   /* Pick a medium */
   for(i = 0; i < MediumArraySize; i++)
@@ -903,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 */
@@ -939,6 +1014,9 @@ MiniportInitialize(
                            Adapter);
       NdisMSetPeriodicTimer(&Adapter->MediaDetectionTimer,
                             MEDIA_DETECTION_INTERVAL);
+      NdisMRegisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle,
+                                          Adapter,
+                                          MiniportShutdown);
     }
 
 #if DBG
@@ -952,7 +1030,7 @@ MiniportInitialize(
 }
 
 static VOID
-STDCALL
+NTAPI
 MiniportISR(
     OUT PBOOLEAN InterruptRecognized,
     OUT PBOOLEAN QueueMiniportHandleInterrupt,
@@ -1005,7 +1083,7 @@ MiniportISR(
 }
 
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportReset(
     OUT PBOOLEAN AddressingReset,
     IN NDIS_HANDLE MiniportAdapterContext)
@@ -1023,6 +1101,8 @@ MiniportReset(
 {
   DPRINT("Called\n");
 
+  ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
+
   /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */
 
   *AddressingReset = FALSE;
@@ -1030,7 +1110,7 @@ MiniportReset(
 }
 
 static BOOLEAN
-STDCALL
+NTAPI
 MiSyncStartTransmit(
     IN PVOID SynchronizeContext)
 /*
@@ -1046,7 +1126,7 @@ MiSyncStartTransmit(
 }
 
 static NDIS_STATUS
-STDCALL
+NTAPI
 MiniportSend(
     IN NDIS_HANDLE MiniportAdapterContext,
     IN PNDIS_PACKET Packet,
@@ -1072,6 +1152,8 @@ MiniportSend(
 
   DPRINT("Called\n");
 
+  ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
+
   NdisDprAcquireSpinLock(&Adapter->Lock);
 
   /* Check if we have free entry in our circular buffer. */
@@ -1135,7 +1217,7 @@ MiniportSend(
 }
 
 static ULONG
-STDCALL
+NTAPI
 MiEthernetCrc(UCHAR *Address)
 /*
  * FUNCTION: Calculate Ethernet CRC32
@@ -1162,7 +1244,7 @@ MiEthernetCrc(UCHAR *Address)
 }
 
 NDIS_STATUS
-STDCALL
+NTAPI
 MiSetMulticast(
     PADAPTER Adapter,
     UCHAR *Addresses,
@@ -1184,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
@@ -1203,7 +1309,7 @@ MiGetMediaState(PADAPTER Adapter)
 }
 
 NTSTATUS
-STDCALL
+NTAPI
 DriverEntry(
     IN PDRIVER_OBJECT DriverObject,
     IN PUNICODE_STRING RegistryPath)
@@ -1237,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)