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