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