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