b4178a2800c141c6a83c82f15a06d8fa4a9110ba
[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 DbgPrint("No NE2000 or compatible network adapter found at address 0x%X.\n",
221 Adapter->IOBase);
222
223 NDIS_DbgPrint(MID_TRACE, ("Status (0x%X).\n", Status));
224 MiniportHalt((NDIS_HANDLE)Adapter);
225 return Status;
226 }
227
228 NDIS_DbgPrint(MAX_TRACE, ("BOARDDATA:\n"));
229 for (i = 0; i < 4; i++) {
230 NDIS_DbgPrint(MAX_TRACE, ("%02X %02X %02X %02X\n",
231 Adapter->SAPROM[i*4+0],
232 Adapter->SAPROM[i*4+1],
233 Adapter->SAPROM[i*4+2],
234 Adapter->SAPROM[i*4+3]));
235 }
236
237 /* Setup adapter structure */
238 Adapter->TXStart = ((ULONG_PTR)Adapter->RamBase >> 8);
239 Adapter->TXCount = DRIVER_DEFAULT_TX_BUFFER_COUNT;
240 Adapter->TXFree = DRIVER_DEFAULT_TX_BUFFER_COUNT;
241 Adapter->TXCurrent = -1;
242 Adapter->PageStart = Adapter->TXStart + Adapter->TXCount;
243 Adapter->PageStop = Adapter->TXStart + (Adapter->RamSize >> 8);
244
245 /* Initialize multicast address mask to accept all */
246 for (i = 0; i < 8; i++)
247 Adapter->MulticastAddressMask[i] = 0xFF;
248
249 /* Setup the NIC */
250 NICSetup(Adapter);
251
252 NDIS_DbgPrint(MAX_TRACE, ("TXStart (0x%X) TXCount (0x%X) PageStart (0x%X)\n",
253 Adapter->TXStart,
254 Adapter->TXCount,
255 Adapter->PageStart));
256
257 NDIS_DbgPrint(MAX_TRACE, ("PageStop (0x%X) CurrentPage (0x%X) NextPacket (0x%X).\n",
258 Adapter->PageStop,
259 Adapter->CurrentPage,
260 Adapter->NextPacket));
261 #endif
262 /* Register the interrupt */
263 Status = NdisMRegisterInterrupt(
264 &Adapter->Interrupt,
265 MiniportAdapterHandle,
266 Adapter->InterruptNumber,
267 Adapter->InterruptNumber,
268 FALSE,
269 FALSE,
270 NdisInterruptLatched);
271 if (Status != NDIS_STATUS_SUCCESS) {
272 NDIS_DbgPrint(MIN_TRACE, ("Cannot register interrupt. Status (0x%X).\n", Status));
273 MiniportHalt((NDIS_HANDLE)Adapter);
274 return Status;
275 }
276
277 Adapter->InterruptRegistered = TRUE;
278 #ifndef NOCARD
279 /* Start the NIC */
280 NICStart(Adapter);
281 #endif
282 /* Add adapter to the global adapter list */
283 InsertTailList(&DriverInfo.AdapterListHead, &Adapter->ListEntry);
284
285 NDIS_DbgPrint(MAX_TRACE, ("Leaving.\n"));
286
287 return NDIS_STATUS_SUCCESS;
288 }
289
290
291 VOID MiniportISR(
292 OUT PBOOLEAN InterruptRecognized,
293 OUT PBOOLEAN QueueMiniportHandleInterrupt,
294 IN NDIS_HANDLE MiniportAdapterContext)
295 /*
296 * FUNCTION: Interrupt Service Routine for controlled adapters
297 * ARGUMENTS:
298 * InterruptRecognized = Address of buffer to place wether
299 * the adapter generated the interrupt
300 * QueueMiniportHandleInterrupt = Address of buffer to place wether
301 * MiniportHandleInterrupt should be called
302 * MiniportAdapterContext = Pointer to adapter context area
303 * NOTES:
304 * All pending interrupts are handled
305 */
306 {
307 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
308
309 NICDisableInterrupts((PNIC_ADAPTER)MiniportAdapterContext);
310
311 *InterruptRecognized = TRUE;
312 *QueueMiniportHandleInterrupt = TRUE;
313 }
314
315
316 NDIS_STATUS MiniportQueryInformation(
317 IN NDIS_HANDLE MiniportAdapterContext,
318 IN NDIS_OID Oid,
319 IN PVOID InformationBuffer,
320 IN ULONG InformationBufferLength,
321 OUT PULONG BytesWritten,
322 OUT PULONG BytesNeeded)
323 /*
324 * FUNCTION: Handler to process queries
325 * ARGUMENTS:
326 * MiniportAdapterContext = Pointer to adapter context area
327 * Oid = OID code designating query operation
328 * InformationBuffer = Address of return buffer
329 * InformationBufferLength = Length of return buffer
330 * BytesWritten = Address of buffer to place number of bytes returned
331 * BytesNeeded = Address of buffer to place number of bytes needed
332 * in InformationBuffer for specified OID
333 * RETURNS:
334 * Status of operation
335 */
336 {
337 NDIS_STATUS Status;
338 PVOID CopyFrom;
339 UINT CopySize;
340 ULONG GenericULONG;
341 USHORT GenericUSHORT;
342 NDIS_MEDIUM Medium = NdisMedium802_3;
343 PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
344
345 NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
346
347 Status = NDIS_STATUS_SUCCESS;
348 CopyFrom = (PVOID)&GenericULONG;
349 CopySize = sizeof(ULONG);
350
351 switch (Oid) {
352 case OID_GEN_SUPPORTED_LIST:
353 CopyFrom = (PVOID)&MiniportOIDList;
354 CopySize = sizeof(MiniportOIDList);
355 break;
356 case OID_GEN_HARDWARE_STATUS:
357 GenericULONG = (ULONG)NdisHardwareStatusReady;
358 break;
359 case OID_GEN_MEDIA_SUPPORTED:
360 case OID_GEN_MEDIA_IN_USE:
361 CopyFrom = (PVOID)&Medium;
362 CopySize = sizeof(NDIS_MEDIUM);
363 break;
364 case OID_GEN_MAXIMUM_LOOKAHEAD:
365 GenericULONG = DRIVER_MAXIMUM_LOOKAHEAD;
366 break;
367 case OID_GEN_MAXIMUM_FRAME_SIZE:
368 GenericULONG = DRIVER_FRAME_SIZE - DRIVER_HEADER_SIZE;
369 break;
370 case OID_GEN_LINK_SPEED:
371 GenericULONG = 100000; /* 10Mbps */
372 break;
373 case OID_GEN_TRANSMIT_BUFFER_SPACE:
374 GenericULONG = Adapter->TXCount * DRIVER_BLOCK_SIZE;
375 break;
376 case OID_GEN_RECEIVE_BUFFER_SPACE:
377 GenericULONG = Adapter->RamSize -
378 (ULONG_PTR)Adapter->RamBase -
379 (Adapter->TXCount * DRIVER_BLOCK_SIZE);
380 break;
381 case OID_GEN_TRANSMIT_BLOCK_SIZE:
382 GenericULONG = DRIVER_BLOCK_SIZE;
383 break;
384 case OID_GEN_RECEIVE_BLOCK_SIZE:
385 GenericULONG = DRIVER_BLOCK_SIZE;
386 break;
387 case OID_GEN_VENDOR_ID:
388 NdisMoveMemory(&GenericULONG, &Adapter->PermanentAddress, 3);
389 GenericULONG &= 0xFFFFFF00;
390 GenericULONG |= 0x01;
391 break;
392 case OID_GEN_VENDOR_DESCRIPTION:
393 CopyFrom = (PVOID)&DRIVER_VENDOR_DESCRIPTION;
394 CopySize = sizeof(DRIVER_VENDOR_DESCRIPTION);
395 break;
396 case OID_GEN_VENDOR_DRIVER_VERSION:
397 GenericUSHORT = (USHORT)DRIVER_VENDOR_DRIVER_VERSION;
398 CopyFrom = (PVOID)&GenericUSHORT;
399 CopySize = sizeof(USHORT);
400 break;
401 case OID_GEN_CURRENT_PACKET_FILTER:
402 GenericULONG = Adapter->PacketFilter;
403 break;
404 case OID_GEN_CURRENT_LOOKAHEAD:
405 GenericULONG = Adapter->LookaheadSize;
406 break;
407 case OID_GEN_DRIVER_VERSION:
408 GenericUSHORT = ((USHORT)DRIVER_NDIS_MAJOR_VERSION << 8) | DRIVER_NDIS_MINOR_VERSION;
409 CopyFrom = (PVOID)&GenericUSHORT;
410 CopySize = sizeof(USHORT);
411 break;
412 case OID_GEN_MAXIMUM_TOTAL_SIZE:
413 GenericULONG = DRIVER_FRAME_SIZE;
414 break;
415 case OID_GEN_PROTOCOL_OPTIONS:
416 NDIS_DbgPrint(MAX_TRACE, ("OID_GEN_PROTOCOL_OPTIONS.\n"));
417 Status = NDIS_STATUS_NOT_SUPPORTED;
418 break;
419 case OID_GEN_MAC_OPTIONS:
420 GenericULONG = NDIS_MAC_OPTION_COPY_LOOKAHEAD_DATA |
421 NDIS_MAC_OPTION_RECEIVE_SERIALIZED |
422 NDIS_MAC_OPTION_TRANSFERS_NOT_PEND |
423 NDIS_MAC_OPTION_NO_LOOPBACK;
424 break;
425 case OID_GEN_MEDIA_CONNECT_STATUS:
426 GenericULONG = (ULONG)NdisMediaStateConnected;
427 break;
428 case OID_GEN_MAXIMUM_SEND_PACKETS:
429 GenericULONG = 1;
430 break;
431 case OID_802_3_PERMANENT_ADDRESS:
432 CopyFrom = (PVOID)&Adapter->PermanentAddress;
433 CopySize = DRIVER_LENGTH_OF_ADDRESS;
434 break;
435 case OID_802_3_CURRENT_ADDRESS:
436 CopyFrom = (PVOID)&Adapter->StationAddress;
437 CopySize = DRIVER_LENGTH_OF_ADDRESS;
438 break;
439 case OID_802_3_MULTICAST_LIST:
440 NDIS_DbgPrint(MAX_TRACE, ("OID_802_3_MULTICAST_LIST.\n"));
441 Status = NDIS_STATUS_NOT_SUPPORTED;
442 break;
443 case OID_802_3_MAXIMUM_LIST_SIZE:
444 GenericULONG = Adapter->MaxMulticastListSize;
445 break;
446 case OID_802_3_MAC_OPTIONS:
447 NDIS_DbgPrint(MAX_TRACE, ("OID_802_3_MAC_OPTIONS.\n"));
448 Status = NDIS_STATUS_NOT_SUPPORTED;
449 break;
450 default:
451 NDIS_DbgPrint(MIN_TRACE, ("Unknown OID (0x%X).\n", Oid));
452 Status = NDIS_STATUS_INVALID_OID;
453 break;
454 }
455
456 if (Status == NDIS_STATUS_SUCCESS) {
457 if (CopySize > InformationBufferLength) {
458 *BytesNeeded = (CopySize - InformationBufferLength);
459 *BytesWritten = 0;
460 Status = NDIS_STATUS_INVALID_LENGTH;
461 } else {
462 NdisMoveMemory(InformationBuffer, CopyFrom, CopySize);
463 *BytesWritten = CopySize;
464 *BytesNeeded = 0;
465 }
466 }
467
468 NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status is (0x%X).\n", Status));
469
470 return Status;
471 }
472
473
474 NDIS_STATUS MiniportReconfigure(
475 OUT PNDIS_STATUS OpenErrorStatus,
476 IN NDIS_HANDLE MiniportAdapterContext,
477 IN NDIS_HANDLE WrapperConfigurationContext)
478 /*
479 * FUNCTION: Reconfigures an adapter
480 * ARGUMENTS:
481 * OpenErrorStatus = Address of buffer to place additional status information
482 * MiniportAdapterContext = Pointer to adapter context area
483 * WrapperConfigurationContext = Handle used to identify configuration context
484 * RETURNS:
485 * Status of operation
486 * NOTES:
487 * Never called by NDIS library
488 */
489 {
490 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
491
492 return NDIS_STATUS_FAILURE;
493 }
494
495
496
497 NDIS_STATUS MiniportReset(
498 OUT PBOOLEAN AddressingReset,
499 IN NDIS_HANDLE MiniportAdapterContext)
500 /*
501 * FUNCTION: Resets an adapter
502 * ARGUMENTS:
503 * AddressingReset = Address of a buffer to place value indicating
504 * wether NDIS library should call MiniportSetInformation
505 * to restore addressing information
506 * MiniportAdapterContext = Pointer to adapter context area
507 * RETURNS:
508 * Status of operation
509 */
510 {
511 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
512
513 return NDIS_STATUS_FAILURE;
514 }
515
516
517 NDIS_STATUS MiniportSend(
518 IN NDIS_HANDLE MiniportAdapterContext,
519 IN PNDIS_PACKET Packet,
520 IN UINT Flags)
521 /*
522 * FUNCTION: Transmits a packet
523 * ARGUMENTS:
524 * MiniportAdapterContext = Pointer to adapter context area
525 * Packet = Pointer to a packet descriptor specifying
526 * the data to be transmitted
527 * Flags = Specifies optional packet flags
528 * RETURNS:
529 * Status of operation
530 */
531 {
532 PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
533
534 NDIS_DbgPrint(MAX_TRACE, ("Queueing packet.\n"));
535
536 #ifdef NOCARD
537 NdisMSendComplete(Adapter->MiniportAdapterHandle,
538 Packet,
539 NDIS_STATUS_SUCCESS);
540 #else
541 /* Queue the packet on the transmit queue */
542 RESERVED(Packet)->Next = NULL;
543 if (Adapter->TXQueueHead == NULL) {
544 Adapter->TXQueueHead = Packet;
545 } else {
546 RESERVED(Adapter->TXQueueTail)->Next = Packet;
547 }
548
549 Adapter->TXQueueTail = Packet;
550
551 /* Transmit the packet */
552 NICTransmit(Adapter);
553 #endif
554 return NDIS_STATUS_PENDING;
555 }
556
557
558 NDIS_STATUS MiniportSetInformation(
559 IN NDIS_HANDLE MiniportAdapterContext,
560 IN NDIS_OID Oid,
561 IN PVOID InformationBuffer,
562 IN ULONG InformationBufferLength,
563 OUT PULONG BytesRead,
564 OUT PULONG BytesNeeded)
565 /*
566 * FUNCTION: Changes state information in the driver
567 * ARGUMENTS:
568 * MiniportAdapterContext = Pointer to adapter context area
569 * Oid = OID code designating set operation
570 * InformationBuffer = Pointer to buffer with state information
571 * InformationBufferLength = Length of InformationBuffer
572 * BytesRead = Address of buffer to place number of bytes read
573 * BytesNeeded = Address of buffer to place number of extra bytes
574 * needed in InformationBuffer for specified OID
575 * RETURNS:
576 * Status of operation
577 */
578 {
579 ULONG GenericULONG;
580 NDIS_STATUS Status = NDIS_STATUS_SUCCESS;
581 PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
582
583 NDIS_DbgPrint(MAX_TRACE, ("Called. Oid (0x%X).\n", Oid));
584
585 switch (Oid) {
586 case OID_GEN_CURRENT_PACKET_FILTER:
587 /* Verify length */
588 if (InformationBufferLength < sizeof(ULONG)) {
589 *BytesRead = 0;
590 *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
591 Status = NDIS_STATUS_INVALID_LENGTH;
592 break;
593 }
594
595 NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
596 /* Check for properties the driver don't support */
597 if (GenericULONG &
598 (NDIS_PACKET_TYPE_ALL_FUNCTIONAL |
599 NDIS_PACKET_TYPE_FUNCTIONAL |
600 NDIS_PACKET_TYPE_GROUP |
601 NDIS_PACKET_TYPE_MAC_FRAME |
602 NDIS_PACKET_TYPE_SMT |
603 NDIS_PACKET_TYPE_SOURCE_ROUTING)) {
604 *BytesRead = 4;
605 *BytesNeeded = 0;
606 Status = NDIS_STATUS_NOT_SUPPORTED;
607 break;
608 }
609
610 Adapter->PacketFilter = GenericULONG;
611
612 /* FIXME: Set filter on hardware */
613
614 break;
615 case OID_GEN_CURRENT_LOOKAHEAD:
616 /* Verify length */
617 if (InformationBufferLength < sizeof(ULONG)) {
618 *BytesRead = 0;
619 *BytesNeeded = sizeof(ULONG) - InformationBufferLength;
620 Status = NDIS_STATUS_INVALID_LENGTH;
621 break;
622 }
623
624 NdisMoveMemory(&GenericULONG, InformationBuffer, sizeof(ULONG));
625 if (GenericULONG > DRIVER_MAXIMUM_LOOKAHEAD)
626 Status = NDIS_STATUS_INVALID_LENGTH;
627 else
628 Adapter->LookaheadSize = GenericULONG;
629 break;
630 case OID_802_3_MULTICAST_LIST:
631 /* Verify length. Must be multiplum of hardware address length */
632 if ((InformationBufferLength % DRIVER_LENGTH_OF_ADDRESS) != 0) {
633 *BytesRead = 0;
634 *BytesNeeded = 0;
635 Status = NDIS_STATUS_INVALID_LENGTH;
636 break;
637 }
638
639 /* Set new multicast address list */
640 NdisMoveMemory(Adapter->Addresses, InformationBuffer, InformationBufferLength);
641
642 /* FIXME: Update hardware */
643
644 break;
645 default:
646 NDIS_DbgPrint(MIN_TRACE, ("Invalid object ID (0x%X).\n", Oid));
647 *BytesRead = 0;
648 *BytesNeeded = 0;
649 Status = NDIS_STATUS_INVALID_OID;
650 break;
651 }
652
653 if (Status == NDIS_STATUS_SUCCESS) {
654 *BytesRead = InformationBufferLength;
655 *BytesNeeded = 0;
656 }
657
658 NDIS_DbgPrint(MAX_TRACE, ("Leaving. Status (0x%X).\n", Status));
659
660 return Status;
661 }
662
663
664 NDIS_STATUS MiniportTransferData(
665 OUT PNDIS_PACKET Packet,
666 OUT PUINT BytesTransferred,
667 IN NDIS_HANDLE MiniportAdapterContext,
668 IN NDIS_HANDLE MiniportReceiveContext,
669 IN UINT ByteOffset,
670 IN UINT BytesToTransfer)
671 /*
672 * FUNCTION: Transfers data from a received frame into an NDIS packet
673 * ARGUMENTS:
674 * Packet = Address of packet to copy received data into
675 * BytesTransferred = Address of buffer to place number of bytes transmitted
676 * MiniportAdapterContext = Pointer to adapter context area
677 * MiniportReceiveContext = Pointer to receive context area (actually NULL)
678 * ByteOffset = Offset within received packet to begin copying
679 * BytesToTransfer = Number of bytes to copy into packet
680 * RETURNS:
681 * Status of operation
682 */
683 {
684 PNDIS_BUFFER DstBuffer;
685 UINT BytesCopied, BytesToCopy, DstSize;
686 ULONG SrcData;
687 PUCHAR DstData;
688 UINT RecvStart;
689 UINT RecvStop;
690 PNIC_ADAPTER Adapter = (PNIC_ADAPTER)MiniportAdapterContext;
691
692 NDIS_DbgPrint(MAX_TRACE, ("Called. Packet (0x%X) ByteOffset (0x%X) BytesToTransfer (%d).\n",
693 Packet, ByteOffset, BytesToTransfer));
694
695 if (BytesToTransfer == 0) {
696 *BytesTransferred = 0;
697 return NDIS_STATUS_SUCCESS;
698 }
699
700 RecvStart = Adapter->PageStart * DRIVER_BLOCK_SIZE;
701 RecvStop = Adapter->PageStop * DRIVER_BLOCK_SIZE;
702
703 NdisQueryPacket(Packet, NULL, NULL, &DstBuffer, NULL);
704 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
705
706 SrcData = Adapter->PacketOffset + sizeof(PACKET_HEADER) + ByteOffset;
707 if (ByteOffset + sizeof(PACKET_HEADER) + BytesToTransfer > Adapter->PacketHeader.PacketLength)
708 BytesToTransfer = Adapter->PacketHeader.PacketLength- sizeof(PACKET_HEADER) - ByteOffset;
709
710 /* Start copying the data */
711 BytesCopied = 0;
712 for (;;) {
713 BytesToCopy = (DstSize < BytesToTransfer)? DstSize : BytesToTransfer;
714 if (SrcData + BytesToCopy > RecvStop)
715 BytesToCopy = (RecvStop - SrcData);
716
717 NICReadData(Adapter, DstData, SrcData, BytesToCopy);
718
719 BytesCopied += BytesToCopy;
720 SrcData += BytesToCopy;
721 (ULONG_PTR)DstData += BytesToCopy;
722 BytesToTransfer -= BytesToCopy;
723 if (BytesToTransfer == 0)
724 break;
725
726 DstSize -= BytesToCopy;
727 if (DstSize == 0) {
728 /* No more bytes in destination buffer. Proceed to
729 the next buffer in the destination buffer chain */
730 NdisGetNextBuffer(DstBuffer, &DstBuffer);
731 if (!DstBuffer)
732 break;
733
734 NdisQueryBuffer(DstBuffer, (PVOID)&DstData, &DstSize);
735 }
736
737 if (SrcData == RecvStop)
738 SrcData = RecvStart;
739 }
740
741 NDIS_DbgPrint(MAX_TRACE, ("Transferred (%d) bytes.\n", BytesToTransfer));
742
743 *BytesTransferred = BytesCopied;
744
745 return NDIS_STATUS_SUCCESS;
746 }
747
748
749 NTSTATUS
750 #ifndef _MSC_VER
751 STDCALL
752 #endif
753 DriverEntry(
754 PDRIVER_OBJECT DriverObject,
755 PUNICODE_STRING RegistryPath)
756 /*
757 * FUNCTION: Main driver entry point
758 * ARGUMENTS:
759 * DriverObject = Pointer to a driver object for this driver
760 * RegistryPath = Registry node for configuration parameters
761 * RETURNS:
762 * Status of driver initialization
763 */
764 {
765 NDIS_STATUS Status;
766 NDIS_HANDLE NdisWrapperHandle;
767 NDIS_MINIPORT_CHARACTERISTICS Miniport;
768
769 NDIS_DbgPrint(MAX_TRACE, ("Called.\n"));
770
771 NdisZeroMemory(&Miniport, sizeof(Miniport));
772 Miniport.MajorNdisVersion = DRIVER_NDIS_MAJOR_VERSION;
773 Miniport.MinorNdisVersion = DRIVER_NDIS_MINOR_VERSION;
774 Miniport.CheckForHangHandler = NULL; //MiniportCheckForHang;
775 Miniport.DisableInterruptHandler = MiniportDisableInterrupt;
776 Miniport.EnableInterruptHandler = MiniportEnableInterrupt;
777 Miniport.HaltHandler = MiniportHalt;
778 Miniport.HandleInterruptHandler = MiniportHandleInterrupt;
779 Miniport.InitializeHandler = MiniportInitialize;
780 Miniport.ISRHandler = MiniportISR;
781 Miniport.QueryInformationHandler = MiniportQueryInformation;
782 Miniport.ReconfigureHandler = MiniportReconfigure;
783 Miniport.ResetHandler = MiniportReset;
784 Miniport.u1.SendHandler = MiniportSend;
785 Miniport.SetInformationHandler = MiniportSetInformation;
786 Miniport.u2.TransferDataHandler = MiniportTransferData;
787
788 NdisMInitializeWrapper(&NdisWrapperHandle,
789 DriverObject,
790 RegistryPath,
791 NULL);
792
793 DriverInfo.NdisWrapperHandle = NdisWrapperHandle;
794 DriverInfo.NdisMacHandle = NULL;
795 InitializeListHead(&DriverInfo.AdapterListHead);
796
797 Status = NdisMRegisterMiniport(NdisWrapperHandle,
798 &Miniport,
799 sizeof(NDIS_MINIPORT_CHARACTERISTICS));
800 if (Status != NDIS_STATUS_SUCCESS) {
801 NDIS_DbgPrint(MIN_TRACE, ("NdisMRegisterMiniport() failed with status code (0x%X).\n", Status));
802 NdisTerminateWrapper(NdisWrapperHandle, NULL);
803 return STATUS_UNSUCCESSFUL;
804 }
805
806 return STATUS_SUCCESS;
807 }
808
809 /* EOF */