xref: /reactos/drivers/network/dd/ne2000/ne2000/main.c (revision c2c66aff)
1 /*
2  * COPYRIGHT:   See COPYING in the top level directory
3  * PROJECT:     ReactOS Novell Eagle 2000 driver
4  * FILE:        ne2000/main.c
5  * PURPOSE:     Driver entry point
6  * PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
7  * REVISIONS:
8  *   CSH 27/08-2000 Created
9  */
10 
11 #include <ne2000.h>
12 
13 NTSTATUS
14 NTAPI
15 DriverEntry(
16     PDRIVER_OBJECT DriverObject,
17     PUNICODE_STRING RegistryPath);
18 
19 
20 #if DBG
21 
22 /* See debug.h for debug/trace constants */
23 ULONG DebugTraceLevel = 0;
24 
25 #endif /* DBG */
26 
27 
28 /* List of supported OIDs */
29 static ULONG MiniportOIDList[] = {
30     OID_GEN_SUPPORTED_LIST,
31     OID_GEN_HARDWARE_STATUS,
32     OID_GEN_MEDIA_SUPPORTED,
33     OID_GEN_MEDIA_IN_USE,
34     OID_GEN_MAXIMUM_LOOKAHEAD,
35     OID_GEN_MAXIMUM_FRAME_SIZE,
36     OID_GEN_LINK_SPEED,
37     OID_GEN_TRANSMIT_BUFFER_SPACE,
38     OID_GEN_RECEIVE_BUFFER_SPACE,
39     OID_GEN_TRANSMIT_BLOCK_SIZE,
40     OID_GEN_RECEIVE_BLOCK_SIZE,
41     OID_GEN_VENDOR_ID,
42     OID_GEN_VENDOR_DESCRIPTION,
43     OID_GEN_VENDOR_DRIVER_VERSION,
44     OID_GEN_CURRENT_PACKET_FILTER,
45     OID_GEN_CURRENT_LOOKAHEAD,
46     OID_GEN_DRIVER_VERSION,
47     OID_GEN_MAXIMUM_TOTAL_SIZE,
48     OID_GEN_PROTOCOL_OPTIONS,
49     OID_GEN_MAC_OPTIONS,
50     OID_GEN_MEDIA_CONNECT_STATUS,
51     OID_GEN_MAXIMUM_SEND_PACKETS,
52     OID_802_3_PERMANENT_ADDRESS,
53     OID_802_3_CURRENT_ADDRESS,
54     OID_802_3_MULTICAST_LIST,
55     OID_802_3_MAXIMUM_LIST_SIZE,
56     OID_802_3_MAC_OPTIONS
57 };
58 
59 DRIVER_INFORMATION      DriverInfo = { NULL, NULL, { NULL, NULL } };
60 NDIS_PHYSICAL_ADDRESS   HighestAcceptableMax = NDIS_PHYSICAL_ADDRESS_CONST(-1, -1);
61 
62 
MiniportCheckForHang(IN NDIS_HANDLE MiniportAdapterContext)63 static BOOLEAN NTAPI MiniportCheckForHang(
64     IN  NDIS_HANDLE MiniportAdapterContext)
65 /*
66  * FUNCTION: Examines if an adapter has hung
67  * ARGUMENTS:
68  *     MiniportAdapterContext = Pointer to adapter context area
69  * RETURNS:
70  *     TRUE if the adapter has hung, FALSE if not
71  */
72 {
73     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
74 
75     return FALSE;
76 }
77 
78 
MiniportDisableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)79 static VOID NTAPI MiniportDisableInterrupt(
80     IN  NDIS_HANDLE MiniportAdapterContext)
81 /*
82  * FUNCTION: Disables interrupts from an adapter
83  * ARGUMENTS:
84  *     MiniportAdapterContext = Pointer to adapter context area
85  */
86 {
87     NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportDisableInterrupt).\n"));
88 #ifndef NOCARD
89     NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
90 #endif
91 }
92 
93 
MiniportEnableInterrupt(IN NDIS_HANDLE MiniportAdapterContext)94 static VOID NTAPI MiniportEnableInterrupt(
95     IN  NDIS_HANDLE MiniportAdapterContext)
96 /*
97  * FUNCTION: Enables interrupts from an adapter
98  * ARGUMENTS:
99  *     MiniportAdapterContext = Pointer to adapter context area
100  */
101 {
102     NDIS_DbgPrint(MAX_TRACE, ("Called. (MiniportEnableInterrupt).\n"));
103 #ifndef NOCARD
104     NICEnableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
105 #endif
106 }
107 
108 
MiniportHalt(IN NDIS_HANDLE MiniportAdapterContext)109 static VOID NTAPI MiniportHalt(
110     IN  NDIS_HANDLE MiniportAdapterContext)
111 /*
112  * FUNCTION: Deallocates resources for and halts an adapter
113  * ARGUMENTS:
114  *     MiniportAdapterContext = Pointer to adapter context area
115  */
116 {
117     PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
118 
119     ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
120 
121     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
122 #ifndef NOCARD
123     /* Stop the NIC */
124     NICStop(Adapter);
125 #endif
126     /* Wait for any DPCs to complete. FIXME: Use something else */
127     NdisStallExecution(250000);
128 
129     if (Adapter->InterruptRegistered)
130         /* Deregister interrupt */
131         NdisMDeregisterInterrupt(&Adapter->Interrupt);
132 
133     if (Adapter->IOPortRangeRegistered)
134         /* Deregister I/O port range */
135         NdisMDeregisterIoPortRange(
136             Adapter->MiniportAdapterHandle,
137             Adapter->IoBaseAddress,
138             0x20,
139             Adapter->IOBase);
140 
141     if (Adapter->ShutdownHandlerRegistered)
142         NdisMDeregisterAdapterShutdownHandler(Adapter->MiniportAdapterHandle);
143 
144     /* Remove adapter from global adapter list */
145     if ((&Adapter->ListEntry)->Blink != NULL) {
146         RemoveEntryList(&Adapter->ListEntry);
147     }
148 
149     /* Free adapter context area */
150     NdisFreeMemory(Adapter, sizeof(NIC_ADAPTER), 0);
151 }
152 
153 
MiQueryResources(OUT PNDIS_STATUS Status,IN PNIC_ADAPTER Adapter,IN NDIS_HANDLE WrapperConfigurationContext)154 static VOID NTAPI MiQueryResources(
155     OUT PNDIS_STATUS    Status,
156     IN  PNIC_ADAPTER    Adapter,
157     IN  NDIS_HANDLE     WrapperConfigurationContext)
158 {
159     PNDIS_RESOURCE_LIST AssignedResources;
160     UINT BufferSize = 0;
161     PCM_PARTIAL_RESOURCE_DESCRIPTOR Descriptor;
162     UINT i;
163 
164     NdisMQueryAdapterResources(Status,
165                                WrapperConfigurationContext,
166                                NULL,
167                                &BufferSize);
168     if (*Status == NDIS_STATUS_SUCCESS)
169         return;
170 
171     *Status = NdisAllocateMemory((PVOID)&AssignedResources,
172                                  BufferSize,
173                                  0,
174                                  HighestAcceptableMax);
175     if (*Status != NDIS_STATUS_SUCCESS)
176         return;
177 
178     NdisMQueryAdapterResources(Status,
179                                WrapperConfigurationContext,
180                                AssignedResources,
181                                &BufferSize);
182     if (*Status != NDIS_STATUS_SUCCESS)
183         return;
184 
185     for (i = 0; i < AssignedResources->Count; i++)
186     {
187         Descriptor = AssignedResources->PartialDescriptors + i;
188         switch (Descriptor->Type)
189         {
190             case CmResourceTypeInterrupt:
191                  Adapter->InterruptLevel = Descriptor->u.Interrupt.Level;
192                  Adapter->InterruptVector = Descriptor->u.Interrupt.Vector;
193                  Adapter->InterruptShared = (Descriptor->ShareDisposition == CmResourceShareShared);
194                  Adapter->InterruptMode = Descriptor->Flags & CM_RESOURCE_INTERRUPT_LATCHED ?
195                                           NdisInterruptLatched : NdisInterruptLevelSensitive;
196                  break;
197             case CmResourceTypePort:
198                  Adapter->IoBaseAddress = Descriptor->u.Port.Start.LowPart;
199                  break;
200         }
201     }
202 }
203 
204 VOID
205 NTAPI
MiniportShutdown(PVOID Context)206 MiniportShutdown(PVOID Context)
207 {
208   #ifndef NOCARD
209     NICStop((PNIC_ADAPTER)Context);
210   #endif
211 }
212 
MiniportInitialize(OUT PNDIS_STATUS OpenErrorStatus,OUT PUINT SelectedMediumIndex,IN PNDIS_MEDIUM MediumArray,IN UINT MediumArraySize,IN NDIS_HANDLE MiniportAdapterHandle,IN NDIS_HANDLE WrapperConfigurationContext)213 static NDIS_STATUS NTAPI MiniportInitialize(
214     OUT PNDIS_STATUS    OpenErrorStatus,
215     OUT PUINT           SelectedMediumIndex,
216     IN  PNDIS_MEDIUM    MediumArray,
217     IN  UINT            MediumArraySize,
218     IN  NDIS_HANDLE     MiniportAdapterHandle,
219     IN  NDIS_HANDLE     WrapperConfigurationContext)
220 /*
221  * FUNCTION: Adapter initialization function
222  * ARGUMENTS:
223  *     OpenErrorStatus             = Address of buffer to place additional status information
224  *     SelectedMediumIndex         = Address of buffer to place selected medium index
225  *     MediumArray                 = Pointer to an array of NDIS_MEDIUMs
226  *     MediaArraySize              = Number of elements in MediumArray
227  *     MiniportAdapterHandle       = Miniport adapter handle assigned by NDIS
228  *     WrapperConfigurationContext = Handle used to identify configuration context
229  * RETURNS:
230  *     Status of operation
231  */
232 {
233     UINT i;
234     NDIS_STATUS Status;
235     PNIC_ADAPTER Adapter;
236     NDIS_HANDLE ConfigurationHandle;
237     UINT *RegNetworkAddress = 0;
238     UINT RegNetworkAddressLength = 0;
239 
240     ASSERT_IRQL_EQUAL(PASSIVE_LEVEL);
241 
242     NDIS_DbgPrint(MAX_TRACE, ("Called (Adapter %X).\n", MiniportAdapterHandle));
243 
244     /* Search for 802.3 media which is the only one we support */
245     for (i = 0; i < MediumArraySize; i++) {
246         if (MediumArray[i] == NdisMedium802_3)
247             break;
248     }
249 
250     if (i == MediumArraySize) {
251         NDIS_DbgPrint(MIN_TRACE, ("No supported media.\n"));
252         return NDIS_STATUS_UNSUPPORTED_MEDIA;
253     }
254 
255     *SelectedMediumIndex = i;
256 
257     Status = NdisAllocateMemory((PVOID)&Adapter,
258                                 sizeof(NIC_ADAPTER),
259                                 0,
260                                 HighestAcceptableMax);
261     if (Status != NDIS_STATUS_SUCCESS) {
262         NDIS_DbgPrint(MIN_TRACE, ("Insufficient resources.\n"));
263         return Status;
264     }
265 
266     NdisZeroMemory(Adapter, sizeof(NIC_ADAPTER));
267     Adapter->MiniportAdapterHandle  = MiniportAdapterHandle;
268     Adapter->IoBaseAddress          = DRIVER_DEFAULT_IO_BASE_ADDRESS;
269     Adapter->InterruptLevel         = DRIVER_DEFAULT_INTERRUPT_NUMBER;
270     Adapter->InterruptVector        = DRIVER_DEFAULT_INTERRUPT_NUMBER;
271     Adapter->InterruptShared        = DRIVER_DEFAULT_INTERRUPT_SHARED;
272     Adapter->InterruptMode          = DRIVER_DEFAULT_INTERRUPT_MODE;
273     Adapter->MaxMulticastListSize   = DRIVER_MAX_MULTICAST_LIST_SIZE;
274     Adapter->InterruptMask          = DRIVER_INTERRUPT_MASK;
275     Adapter->LookaheadSize          = DRIVER_MAXIMUM_LOOKAHEAD;
276 
277     /* Query the resources from PnP. */
278     MiQueryResources(&Status, Adapter, WrapperConfigurationContext);
279 
280     /* Get the port, irq, and MAC address from registry if the PnP
281        failed. */
282     if (Status != NDIS_STATUS_SUCCESS)
283     {
284         PNDIS_CONFIGURATION_PARAMETER ConfigurationParameter;
285         UNICODE_STRING Keyword;
286 
287         NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext);
288         if (Status == NDIS_STATUS_SUCCESS)
289         {
290             NdisInitUnicodeString(&Keyword, L"Irq");
291             NdisReadConfiguration(&Status, &ConfigurationParameter, ConfigurationHandle, &Keyword, NdisParameterHexInteger);
292             if(Status == NDIS_STATUS_SUCCESS)
293             {
294                 NDIS_DbgPrint(MID_TRACE,("NdisReadConfiguration for Irq returned successfully, irq 0x%x\n",
295                         ConfigurationParameter->ParameterData.IntegerData));
296                 Adapter->InterruptLevel =
297                 Adapter->InterruptVector = ConfigurationParameter->ParameterData.IntegerData;
298             }
299 
300             NdisInitUnicodeString(&Keyword, L"Port");
301             NdisReadConfiguration(&Status, &ConfigurationParameter, ConfigurationHandle, &Keyword, NdisParameterHexInteger);
302             if(Status == NDIS_STATUS_SUCCESS)
303             {
304                 NDIS_DbgPrint(MID_TRACE,("NdisReadConfiguration for Port returned successfully, port 0x%x\n",
305                         ConfigurationParameter->ParameterData.IntegerData));
306                 Adapter->IoBaseAddress = ConfigurationParameter->ParameterData.IntegerData;
307             }
308 
309             NdisCloseConfiguration(ConfigurationHandle);
310         }
311         else
312         {
313             NDIS_DbgPrint(MIN_TRACE,("NdisOpenConfiguration returned error 0x%x\n", Status));
314         }
315     }
316 
317      /* find the nic */
318     if (!NICCheck(Adapter)) {
319         NDIS_DbgPrint(MID_TRACE, ("No adapter found at (0x%X).\n", Adapter->IoBaseAddress));
320         NdisFreeMemory(Adapter, sizeof(NIC_ADAPTER), 0);
321         return NDIS_STATUS_ADAPTER_NOT_FOUND;
322     } else
323         NDIS_DbgPrint(MID_TRACE, ("Adapter found at (0x%X).\n", Adapter->IoBaseAddress));
324 
325     NdisMSetAttributes(
326         MiniportAdapterHandle,
327         (NDIS_HANDLE)Adapter,
328         FALSE,
329         NdisInterfaceIsa);
330 
331     Status = NdisMRegisterIoPortRange(
332         (PVOID*)&Adapter->IOBase,
333         MiniportAdapterHandle,
334         Adapter->IoBaseAddress,
335         0x20);
336 
337     if (Status != NDIS_STATUS_SUCCESS) {
338         NDIS_DbgPrint(MIN_TRACE, ("Cannot register port range. Status (0x%X).\n", Status));
339         MiniportHalt((NDIS_HANDLE)Adapter);
340         return Status;
341     }
342 
343     Adapter->IOPortRangeRegistered = TRUE;
344 
345     /* Initialize NIC */
346 #ifndef NOCARD
347     Status = NICInitialize(Adapter);
348     if (Status != NDIS_STATUS_SUCCESS) {
349         NDIS_DbgPrint(MIN_TRACE,("No NE2000 or compatible network adapter found at address 0x%X.\n",
350             Adapter->IOBase));
351 
352         NDIS_DbgPrint(MID_TRACE, ("Status (0x%X).\n", Status));
353         MiniportHalt((NDIS_HANDLE)Adapter);
354         return Status;
355     }
356 
357     NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext);
358     if (Status == NDIS_STATUS_SUCCESS)
359     {
360          NdisReadNetworkAddress(&Status, (PVOID *)&RegNetworkAddress, &RegNetworkAddressLength, ConfigurationHandle);
361          if(Status == NDIS_STATUS_SUCCESS && RegNetworkAddressLength == DRIVER_LENGTH_OF_ADDRESS)
362          {
363              int i;
364              NDIS_DbgPrint(MID_TRACE,("NdisReadNetworkAddress returned successfully, address %x:%x:%x:%x:%x:%x\n",
365                      RegNetworkAddress[0], RegNetworkAddress[1], RegNetworkAddress[2], RegNetworkAddress[3],
366                      RegNetworkAddress[4], RegNetworkAddress[5]));
367              for(i = 0; i < DRIVER_LENGTH_OF_ADDRESS; i++)
368                  Adapter->StationAddress[i] = RegNetworkAddress[i];
369          }
370 
371          NdisCloseConfiguration(ConfigurationHandle);
372     }
373 
374     if (Status != NDIS_STATUS_SUCCESS || RegNetworkAddressLength != DRIVER_LENGTH_OF_ADDRESS)
375     {
376         int i;
377         for (i = 0; i < DRIVER_LENGTH_OF_ADDRESS; i++)
378              Adapter->StationAddress[i] = Adapter->PermanentAddress[i];
379     }
380 
381     NDIS_DbgPrint(MID_TRACE, ("BOARDDATA:\n"));
382     for (i = 0; i < 4; i++) {
383         NDIS_DbgPrint(MID_TRACE, ("%02X %02X %02X %02X\n",
384             Adapter->SAPROM[i*4+0],
385             Adapter->SAPROM[i*4+1],
386             Adapter->SAPROM[i*4+2],
387             Adapter->SAPROM[i*4+3]));
388     }
389 
390     /* Setup adapter structure */
391     Adapter->TXStart   = ((ULONG_PTR)Adapter->RamBase >> 8);
392     Adapter->TXCount   = DRIVER_DEFAULT_TX_BUFFER_COUNT;
393     Adapter->TXFree    = DRIVER_DEFAULT_TX_BUFFER_COUNT;
394     Adapter->TXCurrent = -1;
395     Adapter->PageStart = Adapter->TXStart + Adapter->TXCount;
396     Adapter->PageStop  = Adapter->TXStart + (Adapter->RamSize >> 8);
397 
398     /* Initialize multicast address mask to accept all */
399     for (i = 0; i < 8; i++)
400         Adapter->MulticastAddressMask[i] = 0xFF;
401 
402     /* Setup the NIC */
403     NICSetup(Adapter);
404 
405     NDIS_DbgPrint(MID_TRACE, ("TXStart (0x%X)  TXCount (0x%X)  PageStart (0x%X)\n",
406         Adapter->TXStart,
407         Adapter->TXCount,
408         Adapter->PageStart));
409 
410     NDIS_DbgPrint(MID_TRACE, ("PageStop (0x%X)  CurrentPage (0x%X)  NextPacket (0x%X).\n",
411         Adapter->PageStop,
412         Adapter->CurrentPage,
413         Adapter->NextPacket));
414 #endif
415     /* Register the interrupt */
416     Status = NdisMRegisterInterrupt(
417         &Adapter->Interrupt,
418         MiniportAdapterHandle,
419         Adapter->InterruptVector,
420         Adapter->InterruptLevel,
421         FALSE,
422         Adapter->InterruptShared,
423         Adapter->InterruptMode);
424     if (Status != NDIS_STATUS_SUCCESS) {
425         NDIS_DbgPrint(MIN_TRACE, ("Cannot register interrupt. Status (0x%X).\n", Status));
426         MiniportHalt((NDIS_HANDLE)Adapter);
427         return Status;
428     }
429 
430     Adapter->InterruptRegistered = TRUE;
431 #ifndef NOCARD
432     /* Start the NIC */
433     NICStart(Adapter);
434 #endif
435 
436     /* Register the shutdown handler */
437     NdisMRegisterAdapterShutdownHandler(MiniportAdapterHandle, Adapter, MiniportShutdown);
438 
439     Adapter->ShutdownHandlerRegistered = TRUE;
440 
441     /* Add adapter to the global adapter list */
442     InsertTailList(&DriverInfo.AdapterListHead, &Adapter->ListEntry);
443 
444     NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
445 
446     return NDIS_STATUS_SUCCESS;
447 }
448 
449 
MiniportISR(OUT PBOOLEAN InterruptRecognized,OUT PBOOLEAN QueueMiniportHandleInterrupt,IN NDIS_HANDLE MiniportAdapterContext)450 static VOID NTAPI MiniportISR(
451     OUT PBOOLEAN    InterruptRecognized,
452     OUT PBOOLEAN    QueueMiniportHandleInterrupt,
453     IN  NDIS_HANDLE MiniportAdapterContext)
454 /*
455  * FUNCTION: Interrupt Service Routine for controlled adapters
456  * ARGUMENTS:
457  *     InterruptRecognized          = Address of buffer to place wether
458  *                                    the adapter generated the interrupt
459  *     QueueMiniportHandleInterrupt = Address of buffer to place wether
460  *                                    MiniportHandleInterrupt should be called
461  *     MiniportAdapterContext       = Pointer to adapter context area
462  * NOTES:
463  *     All pending interrupts are handled
464  */
465 {
466     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
467 
468     NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
469 
470     *InterruptRecognized          = TRUE;
471     *QueueMiniportHandleInterrupt = TRUE;
472 }
473 
474 
MiniportQueryInformation(IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_OID Oid,IN PVOID InformationBuffer,IN ULONG InformationBufferLength,OUT PULONG BytesWritten,OUT PULONG BytesNeeded)475 static NDIS_STATUS NTAPI MiniportQueryInformation(
476     IN  NDIS_HANDLE MiniportAdapterContext,
477     IN  NDIS_OID    Oid,
478     IN  PVOID       InformationBuffer,
479     IN  ULONG       InformationBufferLength,
480     OUT PULONG      BytesWritten,
481     OUT PULONG      BytesNeeded)
482 /*
483  * FUNCTION: Handler to process queries
484  * ARGUMENTS:
485  *     MiniportAdapterContext  = Pointer to adapter context area
486  *     Oid                     = OID code designating query operation
487  *     InformationBuffer       = Address of return buffer
488  *     InformationBufferLength = Length of return buffer
489  *     BytesWritten            = Address of buffer to place number of bytes returned
490  *     BytesNeeded             = Address of buffer to place number of bytes needed
491  *                               in InformationBuffer for specified OID
492  * RETURNS:
493  *     Status of operation
494  */
495 {
496     NDIS_STATUS Status;
497     PVOID CopyFrom;
498     UINT CopySize;
499     ULONG GenericULONG;
500     USHORT GenericUSHORT;
501     NDIS_MEDIUM Medium   = NdisMedium802_3;
502     PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
503 
504     NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
505 
506     Status   = NDIS_STATUS_SUCCESS;
507     CopyFrom = (PVOID)&GenericULONG;
508     CopySize = sizeof(ULONG);
509 
510     switch (Oid) {
511     case OID_GEN_SUPPORTED_LIST:
512         CopyFrom = (PVOID)&MiniportOIDList;
513         CopySize = sizeof(MiniportOIDList);
514         break;
515     case OID_GEN_HARDWARE_STATUS:
516         GenericULONG = (ULONG)NdisHardwareStatusReady;
517         break;
518     case OID_GEN_MEDIA_SUPPORTED:
519     case OID_GEN_MEDIA_IN_USE:
520         CopyFrom = (PVOID)&Medium;
521         CopySize = sizeof(NDIS_MEDIUM);
522         break;
523     case OID_GEN_MAXIMUM_LOOKAHEAD:
524         GenericULONG = DRIVER_MAXIMUM_LOOKAHEAD;
525         break;
526     case OID_GEN_MAXIMUM_FRAME_SIZE:
527         GenericULONG = DRIVER_FRAME_SIZE - DRIVER_HEADER_SIZE;
528         break;
529     case OID_GEN_LINK_SPEED:
530         GenericULONG = 100000;  /* 10Mbps */
531         break;
532     case OID_GEN_TRANSMIT_BUFFER_SPACE:
533         GenericULONG = Adapter->TXCount * DRIVER_BLOCK_SIZE;
534         break;
535     case OID_GEN_RECEIVE_BUFFER_SPACE:
536         GenericULONG = Adapter->RamSize -
537                        (ULONG_PTR)Adapter->RamBase -
538                        (Adapter->TXCount * DRIVER_BLOCK_SIZE);
539         break;
540     case OID_GEN_TRANSMIT_BLOCK_SIZE:
541         GenericULONG = DRIVER_BLOCK_SIZE;
542         break;
543     case OID_GEN_RECEIVE_BLOCK_SIZE:
544         GenericULONG = DRIVER_BLOCK_SIZE;
545         break;
546     case OID_GEN_VENDOR_ID:
547         NdisMoveMemory(&GenericULONG, &Adapter->PermanentAddress, 3);
548         GenericULONG &= 0xFFFFFF00;
549         GenericULONG |= 0x01;
550         break;
551     case OID_GEN_VENDOR_DESCRIPTION:
552         CopyFrom = (PVOID)&DRIVER_VENDOR_DESCRIPTION;
553         CopySize = sizeof(DRIVER_VENDOR_DESCRIPTION);
554         break;
555     case OID_GEN_VENDOR_DRIVER_VERSION:
556         GenericUSHORT = (USHORT)DRIVER_VENDOR_DRIVER_VERSION;
557         CopyFrom      = (PVOID)&GenericUSHORT;
558         CopySize      = sizeof(USHORT);
559         break;
560     case OID_GEN_CURRENT_PACKET_FILTER:
561         GenericULONG = Adapter->PacketFilter;
562         break;
563     case OID_GEN_CURRENT_LOOKAHEAD:
564         GenericULONG = Adapter->LookaheadSize;
565         break;
566     case OID_GEN_DRIVER_VERSION:
567         GenericUSHORT = ((USHORT)DRIVER_NDIS_MAJOR_VERSION << 8) | DRIVER_NDIS_MINOR_VERSION;
568         CopyFrom      = (PVOID)&GenericUSHORT;
569         CopySize      = sizeof(USHORT);
570         break;
571     case OID_GEN_MAXIMUM_TOTAL_SIZE:
572         GenericULONG = DRIVER_FRAME_SIZE;
573         break;
574     case OID_GEN_PROTOCOL_OPTIONS:
575         NDIS_DbgPrint(MID_TRACE, ("OID_GEN_PROTOCOL_OPTIONS.\n"));
576         Status = NDIS_STATUS_NOT_SUPPORTED;
577         break;
578     case OID_GEN_MAC_OPTIONS:
579         GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
580                        NDIS_MAC_OPTION_RECEIVE_SERIALIZED  |
581                        NDIS_MAC_OPTION_TRANSFERS_NOT_PEND  |
582                        NDIS_MAC_OPTION_NO_LOOPBACK;
583         break;
584     case OID_GEN_MEDIA_CONNECT_STATUS:
585         GenericULONG = (ULONG)NdisMediaStateConnected;
586         break;
587     case OID_GEN_MAXIMUM_SEND_PACKETS:
588         GenericULONG = 1;
589         break;
590     case OID_802_3_PERMANENT_ADDRESS:
591         CopyFrom = (PVOID)&Adapter->PermanentAddress;
592         CopySize = DRIVER_LENGTH_OF_ADDRESS;
593         break;
594     case OID_802_3_CURRENT_ADDRESS:
595         CopyFrom = (PVOID)&Adapter->StationAddress;
596         CopySize = DRIVER_LENGTH_OF_ADDRESS;
597         break;
598     case OID_802_3_MULTICAST_LIST:
599         NDIS_DbgPrint(MID_TRACE, ("OID_802_3_MULTICAST_LIST.\n"));
600         Status = NDIS_STATUS_NOT_SUPPORTED;
601         break;
602     case OID_802_3_MAXIMUM_LIST_SIZE:
603         GenericULONG = Adapter->MaxMulticastListSize;
604         break;
605     case OID_802_3_MAC_OPTIONS:
606         NDIS_DbgPrint(MID_TRACE, ("OID_802_3_MAC_OPTIONS.\n"));
607         Status = NDIS_STATUS_NOT_SUPPORTED;
608         break;
609     default:
610         NDIS_DbgPrint(MIN_TRACE, ("Unknown OID (0x%X).\n", Oid));
611         Status = NDIS_STATUS_INVALID_OID;
612         break;
613     }
614 
615     if (Status == NDIS_STATUS_SUCCESS) {
616         if (CopySize > InformationBufferLength) {
617             *BytesNeeded  = (CopySize - InformationBufferLength);
618             *BytesWritten = 0;
619             Status        = NDIS_STATUS_INVALID_LENGTH;
620         } else {
621             NdisMoveMemory(InformationBuffer, CopyFrom, CopySize);
622             *BytesWritten = CopySize;
623             *BytesNeeded  = 0;
624          }
625     }
626 
627     NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status is (0x%X).\n", Status));
628 
629     return Status;
630 }
631 
632 
MiniportReconfigure(OUT PNDIS_STATUS OpenErrorStatus,IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_HANDLE WrapperConfigurationContext)633 static NDIS_STATUS NTAPI MiniportReconfigure(
634     OUT PNDIS_STATUS    OpenErrorStatus,
635     IN  NDIS_HANDLE     MiniportAdapterContext,
636     IN  NDIS_HANDLE     WrapperConfigurationContext)
637 /*
638  * FUNCTION: Reconfigures an adapter
639  * ARGUMENTS:
640  *     OpenErrorStatus             = Address of buffer to place additional status information
641  *     MiniportAdapterContext      = Pointer to adapter context area
642  *     WrapperConfigurationContext = Handle used to identify configuration context
643  * RETURNS:
644  *     Status of operation
645  * NOTES:
646  *     Never called by NDIS library
647  */
648 {
649     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
650 
651     return NDIS_STATUS_FAILURE;
652 }
653 
654 
655 
MiniportReset(OUT PBOOLEAN AddressingReset,IN NDIS_HANDLE MiniportAdapterContext)656 static NDIS_STATUS NTAPI MiniportReset(
657     OUT PBOOLEAN    AddressingReset,
658     IN  NDIS_HANDLE MiniportAdapterContext)
659 /*
660  * FUNCTION: Resets an adapter
661  * ARGUMENTS:
662  *     AddressingReset        = Address of a buffer to place value indicating
663  *                              wether NDIS library should call MiniportSetInformation
664  *                              to restore addressing information
665  *     MiniportAdapterContext = Pointer to adapter context area
666  * RETURNS:
667  *     Status of operation
668  */
669 {
670     NDIS_STATUS NdisStatus = NDIS_STATUS_SUCCESS;
671 
672     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
673 
674 #ifndef NOCARD
675     NdisStatus = NICReset((PNIC_ADAPTER)MiniportAdapterContext);
676 #endif
677 
678     *AddressingReset = TRUE;
679 
680     return NdisStatus;
681 }
682 
683 
MiniportSend(IN NDIS_HANDLE MiniportAdapterContext,IN PNDIS_PACKET Packet,IN UINT Flags)684 static NDIS_STATUS NTAPI MiniportSend(
685     IN  NDIS_HANDLE     MiniportAdapterContext,
686     IN  PNDIS_PACKET    Packet,
687     IN  UINT            Flags)
688 /*
689  * FUNCTION: Transmits a packet
690  * ARGUMENTS:
691  *     MiniportAdapterContext = Pointer to adapter context area
692  *     Packet                 = Pointer to a packet descriptor specifying
693  *                              the data to be transmitted
694  *     Flags                  = Specifies optional packet flags
695  * RETURNS:
696  *     Status of operation
697  */
698 {
699     PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
700 
701     ASSERT_IRQL_EQUAL(DISPATCH_LEVEL);
702 
703 #ifndef NOCARD
704     NDIS_DbgPrint(MID_TRACE, ("Queueing packet.\n"));
705 
706     /* Queue the packet on the transmit queue */
707     RESERVED(Packet)->Next = NULL;
708     if (Adapter->TXQueueHead == NULL) {
709         Adapter->TXQueueHead = Packet;
710     } else {
711         RESERVED(Adapter->TXQueueTail)->Next = Packet;
712     }
713 
714     Adapter->TXQueueTail = Packet;
715 
716     /* Transmit the packet */
717     NICTransmit(Adapter);
718 
719     return NDIS_STATUS_PENDING;
720 #else
721     return NDIS_STATUS_SUCCESS;
722 #endif
723 }
724 
725 
MiniportSetInformation(IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_OID Oid,IN PVOID InformationBuffer,IN ULONG InformationBufferLength,OUT PULONG BytesRead,OUT PULONG BytesNeeded)726 static NDIS_STATUS NTAPI MiniportSetInformation(
727     IN  NDIS_HANDLE MiniportAdapterContext,
728     IN  NDIS_OID    Oid,
729     IN  PVOID       InformationBuffer,
730     IN  ULONG       InformationBufferLength,
731     OUT PULONG      BytesRead,
732     OUT PULONG      BytesNeeded)
733 /*
734  * FUNCTION: Changes state information in the driver
735  * ARGUMENTS:
736  *     MiniportAdapterContext  = Pointer to adapter context area
737  *     Oid                     = OID code designating set operation
738  *     InformationBuffer       = Pointer to buffer with state information
739  *     InformationBufferLength = Length of InformationBuffer
740  *     BytesRead               = Address of buffer to place number of bytes read
741  *     BytesNeeded             = Address of buffer to place number of extra bytes
742  *                               needed in InformationBuffer for specified OID
743  * RETURNS:
744  *     Status of operation
745  */
746 {
747     ULONG GenericULONG;
748     NDIS_STATUS Status   = NDIS_STATUS_SUCCESS;
749     PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
750 
751     NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
752 
753     switch (Oid) {
754     case OID_GEN_CURRENT_PACKET_FILTER:
755         /* Verify length */
756         if (InformationBufferLength < sizeof(ULONG)) {
757             *BytesRead   = 0;
758             *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
759             Status       = NDIS_STATUS_INVALID_LENGTH;
760             break;
761         }
762 
763         NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
764         /* Check for properties the driver don't support */
765         if (GenericULONG &
766            (NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
767             NDIS_PACKET_TYPE_FUNCTIONAL     |
768             NDIS_PACKET_TYPE_GROUP          |
769             NDIS_PACKET_TYPE_MAC_FRAME      |
770             NDIS_PACKET_TYPE_SMT            |
771             NDIS_PACKET_TYPE_SOURCE_ROUTING)) {
772             *BytesRead   = 4;
773             *BytesNeeded = 0;
774             Status       = NDIS_STATUS_NOT_SUPPORTED;
775             break;
776         }
777 
778         Adapter->PacketFilter = GenericULONG;
779 
780         /* FIXME: Set filter on hardware */
781 
782         break;
783     case OID_GEN_CURRENT_LOOKAHEAD:
784         /* Verify length */
785         if (InformationBufferLength < sizeof(ULONG)) {
786             *BytesRead   = 0;
787             *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
788             Status = NDIS_STATUS_INVALID_LENGTH;
789             break;
790         }
791 
792         NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
793         if (GenericULONG > DRIVER_MAXIMUM_LOOKAHEAD)
794             Status = NDIS_STATUS_INVALID_LENGTH;
795         else
796             Adapter->LookaheadSize = GenericULONG;
797         break;
798     case OID_802_3_MULTICAST_LIST:
799         /* Verify length. Must be multiple of hardware address length */
800         if ((InformationBufferLength % DRIVER_LENGTH_OF_ADDRESS) != 0) {
801             *BytesRead   = 0;
802             *BytesNeeded = 0;
803             Status       = NDIS_STATUS_INVALID_LENGTH;
804             break;
805         }
806 
807         /* Set new multicast address list */
808         NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength);
809 
810         /* FIXME: Update hardware */
811 
812         break;
813     default:
814         NDIS_DbgPrint(MIN_TRACE, ("Invalid object ID (0x%X).\n", Oid));
815         *BytesRead   = 0;
816         *BytesNeeded = 0;
817         Status       = NDIS_STATUS_INVALID_OID;
818         break;
819     }
820 
821     if (Status == NDIS_STATUS_SUCCESS) {
822         *BytesRead   = InformationBufferLength;
823         *BytesNeeded = 0;
824     }
825 
826     NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
827 
828     return Status;
829 }
830 
831 
MiniportTransferData(OUT PNDIS_PACKET Packet,OUT PUINT BytesTransferred,IN NDIS_HANDLE MiniportAdapterContext,IN NDIS_HANDLE MiniportReceiveContext,IN UINT ByteOffset,IN UINT BytesToTransfer)832 static NDIS_STATUS NTAPI MiniportTransferData(
833     OUT PNDIS_PACKET    Packet,
834     OUT PUINT           BytesTransferred,
835     IN  NDIS_HANDLE     MiniportAdapterContext,
836     IN  NDIS_HANDLE     MiniportReceiveContext,
837     IN  UINT            ByteOffset,
838     IN  UINT            BytesToTransfer)
839 /*
840  * FUNCTION: Transfers data from a received frame into an NDIS packet
841  * ARGUMENTS:
842  *     Packet                 = Address of packet to copy received data into
843  *     BytesTransferred       = Address of buffer to place number of bytes transmitted
844  *     MiniportAdapterContext = Pointer to adapter context area
845  *     MiniportReceiveContext = Pointer to receive context area (actually NULL)
846  *     ByteOffset             = Offset within received packet to begin copying
847  *     BytesToTransfer        = Number of bytes to copy into packet
848  * RETURNS:
849  *     Status of operation
850  */
851 {
852     PNDIS_BUFFER DstBuffer;
853     UINT BytesCopied, BytesToCopy, DstSize;
854     ULONG SrcData;
855     PUCHAR DstData;
856     UINT RecvStart;
857     UINT RecvStop;
858     PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
859 
860     NDIS_DbgPrint(MAX_TRACE, ("Called. Packet (0x%X)  ByteOffset (0x%X)  BytesToTransfer (%d).\n",
861         Packet, ByteOffset, BytesToTransfer));
862 
863     if (BytesToTransfer == 0) {
864         *BytesTransferred = 0;
865         return NDIS_STATUS_SUCCESS;
866     }
867 
868     RecvStart = Adapter->PageStart * DRIVER_BLOCK_SIZE;
869     RecvStop  = Adapter->PageStop  * DRIVER_BLOCK_SIZE;
870 
871     NdisQueryPacket(Packet, NULL, NULL, &DstBuffer, NULL);
872     NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
873 
874     SrcData = Adapter->PacketOffset + sizeof(DISCARD_HEADER) + ByteOffset;
875     if (ByteOffset + sizeof(DISCARD_HEADER) + BytesToTransfer >
876 	Adapter->PacketHeader.PacketLength)
877         BytesToTransfer = Adapter->PacketHeader.PacketLength -
878 	    sizeof(DISCARD_HEADER) - ByteOffset;
879 
880     /* Start copying the data */
881     BytesCopied = 0;
882     for (;;) {
883         BytesToCopy = (DstSize < BytesToTransfer) ? DstSize : BytesToTransfer;
884         if (SrcData + BytesToCopy > RecvStop)
885             BytesToCopy = (RecvStop - SrcData);
886 
887         NICReadData(Adapter, DstData, SrcData, BytesToCopy);
888 
889         BytesCopied     += BytesToCopy;
890         SrcData         += BytesToCopy;
891         DstData          = (PUCHAR)((ULONG_PTR) DstData + BytesToCopy);
892         BytesToTransfer -= BytesToCopy;
893         if (BytesToTransfer == 0)
894             break;
895 
896         DstSize -= BytesToCopy;
897         if (DstSize == 0) {
898             /* No more bytes in destination buffer. Proceed to
899                the next buffer in the destination buffer chain */
900             NdisGetNextBuffer(DstBuffer, &DstBuffer);
901             if (!DstBuffer)
902                 break;
903 
904             NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
905         }
906 
907         if (SrcData == RecvStop)
908             SrcData = RecvStart;
909     }
910 
911     NDIS_DbgPrint(MID_TRACE, ("Transferred (%d) bytes.\n", BytesToTransfer));
912 
913     *BytesTransferred = BytesCopied;
914 
915     return NDIS_STATUS_SUCCESS;
916 }
917 
918 
919 NTSTATUS
920 NTAPI
DriverEntry(PDRIVER_OBJECT DriverObject,PUNICODE_STRING RegistryPath)921 DriverEntry(
922     PDRIVER_OBJECT DriverObject,
923     PUNICODE_STRING RegistryPath)
924 /*
925  * FUNCTION: Main driver entry point
926  * ARGUMENTS:
927  *     DriverObject = Pointer to a driver object for this driver
928  *     RegistryPath = Registry node for configuration parameters
929  * RETURNS:
930  *     Status of driver initialization
931  */
932 {
933     NDIS_STATUS Status;
934     NDIS_HANDLE NdisWrapperHandle;
935     NDIS_MINIPORT_CHARACTERISTICS Miniport;
936 
937     NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
938 
939     NdisZeroMemory(&Miniport, sizeof(Miniport));
940     Miniport.MajorNdisVersion           = DRIVER_NDIS_MAJOR_VERSION;
941     Miniport.MinorNdisVersion           = DRIVER_NDIS_MINOR_VERSION;
942     Miniport.CheckForHangHandler        = MiniportCheckForHang;
943     Miniport.DisableInterruptHandler    = MiniportDisableInterrupt;
944     Miniport.EnableInterruptHandler     = MiniportEnableInterrupt;
945     Miniport.HaltHandler                = MiniportHalt;
946     Miniport.HandleInterruptHandler     = MiniportHandleInterrupt;
947     Miniport.InitializeHandler          = MiniportInitialize;
948     Miniport.ISRHandler                 = MiniportISR;
949     Miniport.QueryInformationHandler    = MiniportQueryInformation;
950     Miniport.ReconfigureHandler         = MiniportReconfigure;
951     Miniport.ResetHandler               = MiniportReset;
952     Miniport.SendHandler                = MiniportSend;
953     Miniport.SetInformationHandler      = MiniportSetInformation;
954     Miniport.TransferDataHandler        = MiniportTransferData;
955 
956     NdisMInitializeWrapper(&NdisWrapperHandle,
957                            DriverObject,
958                            RegistryPath,
959                            NULL);
960 
961     if (!NdisWrapperHandle) {
962         NDIS_DbgPrint(MIN_TRACE, ("NdisMInitializeWrapper() failed\n"));
963         return STATUS_UNSUCCESSFUL;
964     }
965 
966     DriverInfo.NdisWrapperHandle = NdisWrapperHandle;
967     DriverInfo.NdisMacHandle     = NULL;
968     InitializeListHead(&DriverInfo.AdapterListHead);
969 
970     Status = NdisMRegisterMiniport(NdisWrapperHandle,
971                                    &Miniport,
972                                    sizeof(NDIS_MINIPORT_CHARACTERISTICS));
973     if (Status != NDIS_STATUS_SUCCESS) {
974         NDIS_DbgPrint(MIN_TRACE, ("NdisMRegisterMiniport() failed with status code (0x%X).\n", Status));
975         NdisTerminateWrapper(NdisWrapperHandle, NULL);
976         return STATUS_UNSUCCESSFUL;
977     }
978 
979     return STATUS_SUCCESS;
980 }
981 
982 #if 0
983         /* while i'm here - some basic registry sanity checks */
984         {
985             /* write tests */
986             NDIS_CONFIGURATION_PARAMETER ParameterValue;
987 
988             ParameterValue.ParameterType = NdisParameterInteger;
989             ParameterValue.ParameterData.IntegerData = 0x12345678;
990             NdisInitUnicodeString(&Keyword, L"DwordTest");
991             NdisWriteConfiguration(&Status, ConfigurationHandle, &Keyword, &ParameterValue);
992 
993             if(Status != NDIS_STATUS_SUCCESS)
994             {
995                 DbgPrint("ne2000!MiniportInitialize: failed to set DwordTest: 0x%x\n", Status);
996                 DbgBreakPoint();
997             }
998 
999             DbgPrint("ne2000!MiniportInitialize: DwordTest successfully set\n");
1000 
1001             NdisInitUnicodeString(&Keyword, L"StringTest");
1002             ParameterValue.ParameterType = NdisParameterString;
1003             NdisInitUnicodeString(&ParameterValue.ParameterData.StringData, L"Testing123");
1004 
1005             NdisWriteConfiguration(&Status, ConfigurationHandle, &Keyword, &ParameterValue);
1006 
1007             if(Status != NDIS_STATUS_SUCCESS)
1008             {
1009                 DbgPrint("ne2000!MiniportInitialize: failed to set StringTest: 0x%x\n", Status);
1010                 DbgBreakPoint();
1011             }
1012 
1013             DbgPrint("ne2000!MiniportInitialize: StringTest successfully set\n");
1014         }
1015 
1016         {
1017             /* read back the test values */
1018             NDIS_CONFIGURATION_PARAMETER *ParameterValue = 0;
1019 
1020             NdisInitUnicodeString(&Keyword, L"DwordTest");
1021             NdisReadConfiguration(&Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterInteger);
1022 
1023             if(Status != NDIS_STATUS_SUCCESS)
1024             {
1025                 DbgPrint("ne2000!MiniportInitialize: failed to read DwordTest: 0x%x\n", Status);
1026                 DbgBreakPoint();
1027             }
1028 
1029             if(ParameterValue->ParameterData.IntegerData != 0x12345678)
1030             {
1031                 DbgPrint("ne2000!MiniportInitialize: DwordTest value is wrong: 0x%x\n",
1032                     ParameterValue->ParameterData.IntegerData);
1033                 DbgBreakPoint();
1034             }
1035 
1036             DbgPrint("ne2000!MiniportInitialize: DwordTest value was correctly read\n");
1037 
1038             NdisInitUnicodeString(&Keyword, L"StringTest");
1039             NdisReadConfiguration(&Status, &ParameterValue, ConfigurationHandle, &Keyword, NdisParameterString);
1040 
1041             if(Status != NDIS_STATUS_SUCCESS)
1042             {
1043                 DbgPrint("ne2000!MiniportInitialize: failed to read StringTest: 0x%x\n", Status);
1044                 DbgBreakPoint();
1045             }
1046 
1047             if(wcsncmp(ParameterValue->ParameterData.StringData.Buffer, L"Testing123",
1048                     wcslen(L"Testing123")))
1049             {
1050                 DbgPrint("ne2000!MiniportInitialize: StringTest value is wrong: %wZ\n",
1051                     &ParameterValue->ParameterData.StringData);
1052                 DbgBreakPoint();
1053             }
1054 
1055             DbgPrint("ne2000!MiniportInitialize: StringTest value was correctly read\n");
1056         }
1057 
1058 #endif
1059 
1060 /* EOF */
1061