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