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