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