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