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