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