2 * ReactOS AMD PCNet Driver
4 * Copyright (C) 2003 Vizzini <vizzini@plasmic.com>
5 * Copyright (C) 2004 Filip Navara <navaraf@reactos.com>
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 * 09-Sep-2003 vizzini - Created
23 * 10-Oct-2004 navaraf - Fix receive to work on VMware adapters (
24 * need to set busmaster bit on PCI).
25 * - Indicate receive completition.
26 * - Implement packet transmitting.
27 * - Don't read slot number from registry and
28 * report itself as NDIS 5.0 miniport.
29 * 11-Oct-2004 navaraf - Fix nasty bugs in halt code path.
30 * 17-Oct-2004 navaraf - Add multicast support.
31 * - Add media state detection support.
32 * - Protect the adapter context with spinlock
33 * and move code talking to card to inside
34 * NdisMSynchronizeWithInterrupt calls where
38 * - this assumes a 32-bit machine
49 IN PDRIVER_OBJECT DriverObject
,
50 IN PUNICODE_STRING RegistryPath
);
54 MiniportHandleInterrupt(
55 IN NDIS_HANDLE MiniportAdapterContext
)
57 * FUNCTION: Handle an interrupt if told to by MiniportISR
59 * MiniportAdapterContext: context specified to NdisMSetAttributes
61 * - Called by NDIS at DISPATCH_LEVEL
64 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
70 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
72 NdisDprAcquireSpinLock(&Adapter
->Lock
);
74 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
75 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
77 DPRINT("CSR0 is 0x%x\n", Data
);
79 while((Data
& CSR0_INTR
) && i
++ < INTERRUPT_LIMIT
)
81 /* Clear interrupt flags early to avoid race conditions. */
82 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
86 DPRINT("error: %x\n", Data
& (CSR0_MERR
|CSR0_BABL
|CSR0_CERR
|CSR0_MISS
));
88 Adapter
->Statistics
.XmtCollisions
++;
96 BOOLEAN IndicatedData
= FALSE
;
98 DPRINT("receive interrupt\n");
102 PRECEIVE_DESCRIPTOR Descriptor
= Adapter
->ReceiveDescriptorRingVirt
+ Adapter
->CurrentReceiveDescriptorIndex
;
106 if(Descriptor
->FLAGS
& RD_OWN
)
108 DPRINT("no more receive descriptors to process\n");
112 if(Descriptor
->FLAGS
& RD_ERR
)
114 DPRINT("receive descriptor error: 0x%x\n", Descriptor
->FLAGS
);
115 if (Descriptor
->FLAGS
& RD_BUFF
)
116 Adapter
->Statistics
.RcvBufferErrors
++;
117 if (Descriptor
->FLAGS
& RD_CRC
)
118 Adapter
->Statistics
.RcvCrcErrors
++;
119 if (Descriptor
->FLAGS
& RD_OFLO
)
120 Adapter
->Statistics
.RcvOverflowErrors
++;
121 if (Descriptor
->FLAGS
& RD_FRAM
)
122 Adapter
->Statistics
.RcvFramingErrors
++;
126 if(!((Descriptor
->FLAGS
& RD_STP
) && (Descriptor
->FLAGS
& RD_ENP
)))
128 DPRINT("receive descriptor not start&end: 0x%x\n", Descriptor
->FLAGS
);
132 Buffer
= Adapter
->ReceiveBufferPtrVirt
+ Adapter
->CurrentReceiveDescriptorIndex
* BUFFER_SIZE
;
133 ByteCount
= Descriptor
->MCNT
& 0xfff;
135 DPRINT("Indicating a %d-byte packet (index %d)\n", ByteCount
, Adapter
->CurrentReceiveDescriptorIndex
);
137 NdisMEthIndicateReceive(Adapter
->MiniportAdapterHandle
, 0, Buffer
, 14, Buffer
+14, ByteCount
-14, ByteCount
-14);
139 IndicatedData
= TRUE
;
141 RtlZeroMemory(Descriptor
, sizeof(RECEIVE_DESCRIPTOR
));
143 (ULONG
)(Adapter
->ReceiveBufferPtrPhys
+ Adapter
->CurrentReceiveDescriptorIndex
* BUFFER_SIZE
);
144 Descriptor
->BCNT
= (-BUFFER_SIZE
) | 0xf000;
145 Descriptor
->FLAGS
|= RD_OWN
;
147 Adapter
->CurrentReceiveDescriptorIndex
++;
148 Adapter
->CurrentReceiveDescriptorIndex
%= Adapter
->BufferCount
;
150 Adapter
->Statistics
.RcvGoodFrames
++;
154 NdisMEthIndicateReceiveComplete(Adapter
->MiniportAdapterHandle
);
158 PTRANSMIT_DESCRIPTOR Descriptor
;
160 DPRINT("transmit interrupt\n");
162 while (Adapter
->CurrentTransmitStartIndex
!=
163 Adapter
->CurrentTransmitEndIndex
)
165 Descriptor
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitStartIndex
;
167 DPRINT("buffer %d flags %x flags2 %x\n",
168 Adapter
->CurrentTransmitStartIndex
,
169 Descriptor
->FLAGS
, Descriptor
->FLAGS2
);
171 if (Descriptor
->FLAGS
& TD1_OWN
)
173 DPRINT("non-TXed buffer\n");
177 if (Descriptor
->FLAGS
& TD1_STP
)
179 if (Descriptor
->FLAGS
& TD1_ONE
)
180 Adapter
->Statistics
.XmtOneRetry
++;
181 else if (Descriptor
->FLAGS
& TD1_MORE
)
182 Adapter
->Statistics
.XmtMoreThanOneRetry
++;
185 if (Descriptor
->FLAGS
& TD1_ERR
)
187 DPRINT("major error: %x\n", Descriptor
->FLAGS2
);
188 if (Descriptor
->FLAGS2
& TD2_RTRY
)
189 Adapter
->Statistics
.XmtRetryErrors
++;
190 if (Descriptor
->FLAGS2
& TD2_LCAR
)
191 Adapter
->Statistics
.XmtLossesOfCarrier
++;
192 if (Descriptor
->FLAGS2
& TD2_LCOL
)
193 Adapter
->Statistics
.XmtLateCollisions
++;
194 if (Descriptor
->FLAGS2
& TD2_EXDEF
)
195 Adapter
->Statistics
.XmtExcessiveDefferals
++;
196 if (Descriptor
->FLAGS2
& TD2_UFLO
)
197 Adapter
->Statistics
.XmtBufferUnderflows
++;
198 if (Descriptor
->FLAGS2
& TD2_BUFF
)
199 Adapter
->Statistics
.XmtBufferErrors
++;
203 Adapter
->CurrentTransmitStartIndex
++;
204 Adapter
->CurrentTransmitStartIndex
%= Adapter
->BufferCount
;
206 Adapter
->Statistics
.XmtGoodFrames
++;
208 NdisMSendResourcesAvailable(Adapter
->MiniportAdapterHandle
);
210 if(Data
& ~(CSR0_ERR
| CSR0_IDON
| CSR0_RINT
| CSR0_TINT
))
212 DPRINT("UNHANDLED INTERRUPT CSR0 0x%x\n", Data
);
215 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
218 /* re-enable interrupts */
219 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
);
221 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
222 DPRINT("CSR0 is now 0x%x\n", Data
);
224 NdisDprReleaseSpinLock(&Adapter
->Lock
);
231 * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector
233 * MiniportAdapterContext: context supplied to NdisMSetAttributes
235 * NDIS_STATUS_FAILURE on a general error
236 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
237 * NDIS_STATUS_SUCCESS on succes
244 /* Detect the card in the configured slot */
245 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_PCIID
, &buf32
, 4);
248 Status
= NDIS_STATUS_FAILURE
;
249 DPRINT1("NdisReadPciSlotInformation failed\n");
255 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
256 DPRINT1("card in slot isn't our: 0x%x\n", 0, buf32
);
260 /* set busmaster and io space enable bits */
261 buf32
= PCI_BMEN
| PCI_IOEN
;
262 NdisWritePciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_COMMAND
, &buf32
, 4);
264 /* get IO base physical address */
266 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_IOBAR
, &buf32
, 4);
269 Status
= NDIS_STATUS_FAILURE
;
270 DPRINT1("NdisReadPciSlotInformation failed\n");
276 DPRINT1("No base i/o address set\n");
277 return NDIS_STATUS_FAILURE
;
280 buf32
&= ~1; /* even up address - comes out odd for some reason */
282 DPRINT("detected io address 0x%x\n", buf32
);
283 Adapter
->IoBaseAddress
= buf32
;
285 /* get interrupt vector */
286 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_ILR
, &buf8
, 1);
289 Status
= NDIS_STATUS_FAILURE
;
290 DPRINT1("NdisReadPciSlotInformation failed\n");
294 DPRINT("interrupt: 0x%x\n", buf8
);
295 Adapter
->InterruptVector
= buf8
;
297 return NDIS_STATUS_SUCCESS
;
304 * FUNCTION: Free all allocated shared memory
306 * Adapter: pointer to the miniport's adapter struct
309 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
311 PhysicalAddress
.u
.HighPart
= 0;
313 if(Adapter
->InitializationBlockVirt
)
315 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->InitializationBlockPhys
;
316 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
317 FALSE
, Adapter
->InitializationBlockVirt
, PhysicalAddress
);
318 Adapter
->InitializationBlockVirt
= NULL
;
321 if(Adapter
->TransmitDescriptorRingVirt
)
323 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->TransmitDescriptorRingPhys
;
324 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
325 FALSE
, Adapter
->TransmitDescriptorRingVirt
, PhysicalAddress
);
326 Adapter
->TransmitDescriptorRingVirt
= NULL
;
329 if(Adapter
->ReceiveDescriptorRingVirt
)
331 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->ReceiveDescriptorRingPhys
;
332 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
333 FALSE
, Adapter
->ReceiveDescriptorRingVirt
, PhysicalAddress
);
334 Adapter
->ReceiveDescriptorRingVirt
= NULL
;
337 if(Adapter
->TransmitBufferPtrVirt
)
339 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->TransmitBufferPtrPhys
;
340 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
341 TRUE
, Adapter
->TransmitBufferPtrVirt
, PhysicalAddress
);
342 Adapter
->TransmitBufferPtrVirt
= NULL
;
345 if(Adapter
->ReceiveBufferPtrVirt
)
347 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->ReceiveBufferPtrPhys
;
348 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
349 TRUE
, Adapter
->ReceiveBufferPtrVirt
, PhysicalAddress
);
350 Adapter
->ReceiveBufferPtrVirt
= NULL
;
355 MiAllocateSharedMemory(
358 * FUNCTION: Allocate all shared memory used by the miniport
360 * Adapter: Pointer to the miniport's adapter object
362 * NDIS_STATUS_RESOURCES on insufficient memory
363 * NDIS_STATUS_SUCCESS on success
366 PTRANSMIT_DESCRIPTOR TransmitDescriptor
;
367 PRECEIVE_DESCRIPTOR ReceiveDescriptor
;
368 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
370 ULONG BufferCount
= NUMBER_OF_BUFFERS
;
371 ULONG LogBufferCount
= LOG_NUMBER_OF_BUFFERS
;
373 while (BufferCount
!= 0)
375 /* allocate the initialization block (we have this in the loop so we can use MiFreeSharedMemory) */
376 Adapter
->InitializationBlockLength
= sizeof(INITIALIZATION_BLOCK
);
377 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
378 FALSE
, (PVOID
*)&Adapter
->InitializationBlockVirt
, &PhysicalAddress
);
379 if(!Adapter
->InitializationBlockVirt
)
381 /* Buffer backoff won't help us here */
382 DPRINT1("insufficient resources\n");
383 return NDIS_STATUS_RESOURCES
;
386 if(((ULONG
)Adapter
->InitializationBlockVirt
& 0x00000003) != 0)
388 DPRINT1("address 0x%x not dword-aligned\n", Adapter
->InitializationBlockVirt
);
389 return NDIS_STATUS_RESOURCES
;
392 Adapter
->InitializationBlockPhys
= (PINITIALIZATION_BLOCK
)NdisGetPhysicalAddressLow(PhysicalAddress
);
394 /* allocate the transport descriptor ring */
395 Adapter
->TransmitDescriptorRingLength
= sizeof(TRANSMIT_DESCRIPTOR
) * BufferCount
;
396 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
397 FALSE
, (PVOID
*)&Adapter
->TransmitDescriptorRingVirt
, &PhysicalAddress
);
398 if (!Adapter
->TransmitDescriptorRingVirt
)
400 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount
>> 1));
401 BufferCount
= BufferCount
>> 1;
403 MiFreeSharedMemory(Adapter
);
407 if (((ULONG
)Adapter
->TransmitDescriptorRingVirt
& 0x00000003) != 0)
409 DPRINT1("address 0x%x not dword-aligned\n", Adapter
->TransmitDescriptorRingVirt
);
410 return NDIS_STATUS_RESOURCES
;
413 Adapter
->TransmitDescriptorRingPhys
= (PTRANSMIT_DESCRIPTOR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
414 RtlZeroMemory(Adapter
->TransmitDescriptorRingVirt
, sizeof(TRANSMIT_DESCRIPTOR
) * BufferCount
);
416 /* allocate the receive descriptor ring */
417 Adapter
->ReceiveDescriptorRingLength
= sizeof(RECEIVE_DESCRIPTOR
) * BufferCount
;
418 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
419 FALSE
, (PVOID
*)&Adapter
->ReceiveDescriptorRingVirt
, &PhysicalAddress
);
420 if (!Adapter
->ReceiveDescriptorRingVirt
)
422 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount
>> 1));
423 BufferCount
= BufferCount
>> 1;
425 MiFreeSharedMemory(Adapter
);
429 if (((ULONG
)Adapter
->ReceiveDescriptorRingVirt
& 0x00000003) != 0)
431 DPRINT1("address 0x%x not dword-aligned\n", Adapter
->ReceiveDescriptorRingVirt
);
432 return NDIS_STATUS_RESOURCES
;
435 Adapter
->ReceiveDescriptorRingPhys
= (PRECEIVE_DESCRIPTOR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
436 RtlZeroMemory(Adapter
->ReceiveDescriptorRingVirt
, sizeof(RECEIVE_DESCRIPTOR
) * BufferCount
);
438 /* allocate transmit buffers */
439 Adapter
->TransmitBufferLength
= BUFFER_SIZE
* BufferCount
;
440 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
441 TRUE
, (PVOID
*)&Adapter
->TransmitBufferPtrVirt
, &PhysicalAddress
);
442 if(!Adapter
->TransmitBufferPtrVirt
)
444 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount
>> 1));
445 BufferCount
= BufferCount
>> 1;
447 MiFreeSharedMemory(Adapter
);
451 if (((ULONG
)Adapter
->TransmitBufferPtrVirt
& 0x00000003) != 0)
453 DPRINT1("address 0x%x not dword-aligned\n", Adapter
->TransmitBufferPtrVirt
);
454 return NDIS_STATUS_RESOURCES
;
457 Adapter
->TransmitBufferPtrPhys
= (PCHAR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
458 RtlZeroMemory(Adapter
->TransmitBufferPtrVirt
, BUFFER_SIZE
* BufferCount
);
460 /* allocate receive buffers */
461 Adapter
->ReceiveBufferLength
= BUFFER_SIZE
* BufferCount
;
462 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
463 TRUE
, (PVOID
*)&Adapter
->ReceiveBufferPtrVirt
, &PhysicalAddress
);
464 if(!Adapter
->ReceiveBufferPtrVirt
)
466 DPRINT1("Backing off buffer count by %d buffers due to allocation failure\n", (BufferCount
>> 1));
467 BufferCount
= BufferCount
>> 1;
469 MiFreeSharedMemory(Adapter
);
473 if (((ULONG
)Adapter
->ReceiveBufferPtrVirt
& 0x00000003) != 0)
475 DPRINT1("address 0x%x not dword-aligned\n", Adapter
->ReceiveBufferPtrVirt
);
476 return NDIS_STATUS_RESOURCES
;
479 Adapter
->ReceiveBufferPtrPhys
= (PCHAR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
480 RtlZeroMemory(Adapter
->ReceiveBufferPtrVirt
, BUFFER_SIZE
* BufferCount
);
487 DPRINT1("Failed to allocate adapter buffers\n");
488 return NDIS_STATUS_RESOURCES
;
491 Adapter
->BufferCount
= BufferCount
;
492 Adapter
->LogBufferCount
= LogBufferCount
;
494 /* initialize tx descriptors */
495 TransmitDescriptor
= Adapter
->TransmitDescriptorRingVirt
;
496 for(i
= 0; i
< BufferCount
; i
++)
498 (TransmitDescriptor
+i
)->TBADR
= (ULONG
)Adapter
->TransmitBufferPtrPhys
+ i
* BUFFER_SIZE
;
499 (TransmitDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
500 (TransmitDescriptor
+i
)->FLAGS
= TD1_STP
| TD1_ENP
;
503 DPRINT("transmit ring initialized\n");
506 ReceiveDescriptor
= Adapter
->ReceiveDescriptorRingVirt
;
507 for(i
= 0; i
< BufferCount
; i
++)
509 (ReceiveDescriptor
+i
)->RBADR
= (ULONG
)Adapter
->ReceiveBufferPtrPhys
+ i
* BUFFER_SIZE
;
510 (ReceiveDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
511 (ReceiveDescriptor
+i
)->FLAGS
= RD_OWN
;
514 DPRINT("receive ring initialized\n");
516 return NDIS_STATUS_SUCCESS
;
520 MiPrepareInitializationBlock(
523 * FUNCTION: Initialize the initialization block
525 * Adapter: pointer to the miniport's adapter object
530 RtlZeroMemory(Adapter
->InitializationBlockVirt
, sizeof(INITIALIZATION_BLOCK
));
532 /* read burned-in address from card */
533 for(i
= 0; i
< 6; i
++)
534 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, Adapter
->InitializationBlockVirt
->PADR
+ i
);
535 DPRINT("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
536 Adapter
->InitializationBlockVirt
->PADR
[0],
537 Adapter
->InitializationBlockVirt
->PADR
[1],
538 Adapter
->InitializationBlockVirt
->PADR
[2],
539 Adapter
->InitializationBlockVirt
->PADR
[3],
540 Adapter
->InitializationBlockVirt
->PADR
[4],
541 Adapter
->InitializationBlockVirt
->PADR
[5]);
543 /* set up receive ring */
544 DPRINT("Receive ring physical address: 0x%x\n", Adapter
->ReceiveDescriptorRingPhys
);
545 Adapter
->InitializationBlockVirt
->RDRA
= (ULONG
)Adapter
->ReceiveDescriptorRingPhys
;
546 Adapter
->InitializationBlockVirt
->RLEN
= (Adapter
->LogBufferCount
<< 4) & 0xf0;
548 /* set up transmit ring */
549 DPRINT("Transmit ring physical address: 0x%x\n", Adapter
->TransmitDescriptorRingPhys
);
550 Adapter
->InitializationBlockVirt
->TDRA
= (ULONG
)Adapter
->TransmitDescriptorRingPhys
;
551 Adapter
->InitializationBlockVirt
->TLEN
= (Adapter
->LogBufferCount
<< 4) & 0xf0;
557 IN PVOID SynchronizeContext
)
559 * FUNCTION: Stop the adapter
561 * SynchronizeContext: Adapter context
564 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
565 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
566 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
573 IN NDIS_HANDLE MiniportAdapterContext
)
575 * FUNCTION: Stop the adapter and release any per-adapter resources
577 * MiniportAdapterContext: context specified to NdisMSetAttributes
579 * - Called by NDIS at PASSIVE_LEVEL
582 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
583 BOOLEAN TimerCancelled
;
588 /* stop the media detection timer */
589 NdisMCancelTimer(&Adapter
->MediaDetectionTimer
, &TimerCancelled
);
592 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStop
, Adapter
);
594 /* deregister the interrupt */
595 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
597 /* deregister i/o port range */
598 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
600 /* deregister the shutdown routine */
601 NdisMDeregisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
);
603 /* free shared memory */
604 MiFreeSharedMemory(Adapter
);
606 /* free map registers */
607 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
);
610 NdisFreeSpinLock(&Adapter
->Lock
);
612 /* free the adapter */
613 NdisFreeMemory(Adapter
, 0, 0);
618 MiSyncMediaDetection(
619 IN PVOID SynchronizeContext
)
621 * FUNCTION: Stop the adapter
623 * SynchronizeContext: Adapter context
626 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
627 NDIS_MEDIA_STATE MediaState
= MiGetMediaState(Adapter
);
628 UINT MediaSpeed
= MiGetMediaSpeed(Adapter
);
629 BOOLEAN FullDuplex
= MiGetMediaDuplex(Adapter
);
632 DPRINT("MediaState: %d\n", MediaState
);
633 if (MediaState
!= Adapter
->MediaState
||
634 MediaSpeed
!= Adapter
->MediaSpeed
||
635 FullDuplex
!= Adapter
->FullDuplex
)
637 Adapter
->MediaState
= MediaState
;
638 Adapter
->MediaSpeed
= MediaSpeed
;
639 Adapter
->FullDuplex
= FullDuplex
;
647 MiniportMediaDetectionTimer(
648 IN PVOID SystemSpecific1
,
649 IN PVOID FunctionContext
,
650 IN PVOID SystemSpecific2
,
651 IN PVOID SystemSpecific3
)
653 * FUNCTION: Periodially query media state
655 * FunctionContext: Adapter context
657 * - Called by NDIS at DISPATCH_LEVEL
660 PADAPTER Adapter
= (PADAPTER
)FunctionContext
;
662 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
664 if (NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
,
665 MiSyncMediaDetection
,
668 NdisMIndicateStatus(Adapter
->MiniportAdapterHandle
,
669 Adapter
->MediaState
== NdisMediaStateConnected
?
670 NDIS_STATUS_MEDIA_CONNECT
: NDIS_STATUS_MEDIA_DISCONNECT
,
672 NdisMIndicateStatusComplete(Adapter
->MiniportAdapterHandle
);
680 * FUNCTION: Initialize and start the PCNET chip
682 * Adapter: pointer to the miniport's adapter struct
684 * - should be coded to detect failure and return an error
685 * - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that.
693 * first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset
694 * twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the
695 * card is reset by reading from the reset register. on reset it's in 16-bit i/o mode.
697 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET32
, &Data
);
698 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET16
, &Data
);
701 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
702 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
704 /* pause for 1ms so the chip will have time to reset */
705 NdisStallExecution(1);
707 DPRINT("chip stopped\n");
709 /* set the software style to 2 (32 bits) */
710 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR58
);
711 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
715 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
717 /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */
718 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
719 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
721 Data
|= CSR4_APAD_XMT
| /* CSR4_DPOLL |*/ CSR4_TXSTRTM
| CSR4_DMAPLUS
;
722 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
724 /* set up bcr18: burst read/write enable */
725 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR18
);
726 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
728 Data
|= BCR18_BREADE
| BCR18_BWRITE
;
729 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, Data
);
731 /* set up csr1 and csr2 with init block */
732 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR1
);
733 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG
)Adapter
->InitializationBlockPhys
& 0xffff));
734 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR2
);
735 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG
)Adapter
->InitializationBlockPhys
>> 16) & 0xffff);
737 DPRINT("programmed with init block\n");
741 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR15
);
742 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
744 /* load init block and start the card */
745 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
746 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STRT
|CSR0_INIT
|CSR0_IENA
);
748 /* Allow LED programming */
749 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR2
);
750 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR2_LEDPE
);
752 /* LED0 is configured for link status (on = up, off = down) */
753 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
754 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR4_LNKSTE
| BCR4_PSE
);
756 /* LED1 is configured for link duplex (on = full, off = half) */
757 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR5
);
758 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR5_FDLSE
| BCR5_PSE
);
760 /* LED2 is configured for link speed (on = 100M, off = 10M) */
761 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR6
);
762 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR6_E100
| BCR6_PSE
);
764 /* LED3 is configured for trasmit/receive activity */
765 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR7
);
766 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR7_XMTE
| BCR7_RCVE
| BCR7_PSE
);
768 Adapter
->MediaState
= MiGetMediaState(Adapter
);
769 Adapter
->FullDuplex
= MiGetMediaDuplex(Adapter
);
770 Adapter
->MediaSpeed
= MiGetMediaSpeed(Adapter
);
772 DPRINT("card started\n");
774 Adapter
->Flags
&= ~RESET_IN_PROGRESS
;
782 * FUNCTION: Test the NIC
784 * Adapter: pointer to the miniport's adapter struct
786 * TRUE if the test succeeds
789 * - this is where to add diagnostics. This is called
790 * at the very end of initialization.
797 /* see if we can read/write now */
798 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
799 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
800 DPRINT("Port 0x%x RAP 0x%x CSR0 0x%x RDP 0x%x, Interupt status register is 0x%x\n", Adapter
->PortOffset
, RAP
, CSR0
, RDP
, Data
);
803 for(i
= 0; i
< 6; i
++)
804 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, &address
[i
]);
806 DPRINT("burned-in address: %x:%x:%x:%x:%x:%x\n", address
[0], address
[1], address
[2], address
[3], address
[4], address
[5]);
807 /* Read status flags from CSR0 */
808 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
809 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
810 DPRINT("CSR0: 0x%x\n", Data
);
812 /* Read status flags from CSR3 */
813 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR3
);
814 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
816 DPRINT("CSR3: 0x%x\n", Data
);
817 /* Read status flags from CSR4 */
818 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
819 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
820 DPRINT("CSR4: 0x%x\n", Data
);
822 /* Read status flags from CSR5 */
823 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR5
);
824 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
825 DPRINT("CSR5: 0x%x\n", Data
);
827 /* Read status flags from CSR6 */
828 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR6
);
829 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
830 DPRINT("CSR6: 0x%x\n", Data
);
838 MiniportShutdown( PVOID Context
)
840 PADAPTER Adapter
= Context
;
842 DPRINT("Stopping the chip\n");
844 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
845 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
851 OUT PNDIS_STATUS OpenErrorStatus
,
852 OUT PUINT SelectedMediumIndex
,
853 IN PNDIS_MEDIUM MediumArray
,
854 IN UINT MediumArraySize
,
855 IN NDIS_HANDLE MiniportAdapterHandle
,
856 IN NDIS_HANDLE WrapperConfigurationContext
)
858 * FUNCTION: Initialize a new miniport
860 * OpenErrorStatus: pointer to a var to return status info in
861 * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3)
862 * MediumArray: array of media that we can pick from
863 * MediumArraySize: size of MediumArray
864 * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance
865 * WrapperConfigurationContext: temporary NDIS-assigned handle for passing
866 * to configuration APIs
868 * NDIS_STATUS_SUCCESS on success
869 * NDIS_STATUS_FAILURE on general failure
870 * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray
871 * NDIS_STATUS_RESOURCES on insufficient system resources
872 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
874 * - Called by NDIS at PASSIVE_LEVEL, once per detected card
875 * - Will int 3 on failure of MiTestCard if DBG=1
879 PADAPTER Adapter
= 0;
880 NDIS_STATUS Status
= NDIS_STATUS_FAILURE
;
881 BOOLEAN InterruptRegistered
= FALSE
, MapRegistersAllocated
= FALSE
;
882 NDIS_HANDLE ConfigurationHandle
;
883 UINT
*RegNetworkAddress
= 0;
884 UINT RegNetworkAddressLength
= 0;
886 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
889 for(i
= 0; i
< MediumArraySize
; i
++)
890 if(MediumArray
[i
] == NdisMedium802_3
)
893 if(i
== MediumArraySize
)
895 Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
896 DPRINT1("unsupported media\n");
897 *OpenErrorStatus
= Status
;
901 *SelectedMediumIndex
= i
;
903 /* allocate our adapter struct */
904 Status
= NdisAllocateMemoryWithTag((PVOID
*)&Adapter
, sizeof(ADAPTER
), PCNET_TAG
);
905 if(Status
!= NDIS_STATUS_SUCCESS
)
907 Status
= NDIS_STATUS_RESOURCES
;
908 DPRINT1("Insufficient resources\n");
909 *OpenErrorStatus
= Status
;
913 RtlZeroMemory(Adapter
, sizeof(ADAPTER
));
915 Adapter
->MiniportAdapterHandle
= MiniportAdapterHandle
;
917 /* register our adapter structwith ndis */
918 NdisMSetAttributesEx(Adapter
->MiniportAdapterHandle
, Adapter
, 0, NDIS_ATTRIBUTE_BUS_MASTER
, NdisInterfacePci
);
922 /* Card-specific detection and setup */
923 Status
= MiQueryCard(Adapter
);
924 if(Status
!= NDIS_STATUS_SUCCESS
)
926 DPRINT1("MiQueryCard failed\n");
927 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
931 /* register an IO port range */
932 Status
= NdisMRegisterIoPortRange((PVOID
*)&Adapter
->PortOffset
, Adapter
->MiniportAdapterHandle
,
933 (UINT
)Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
);
934 if(Status
!= NDIS_STATUS_SUCCESS
)
936 DPRINT1("NdisMRegisterIoPortRange failed: 0x%x\n", Status
);
940 /* Allocate map registers */
941 Status
= NdisMAllocateMapRegisters(Adapter
->MiniportAdapterHandle
, 0,
942 NDIS_DMA_32BITS
, 8, BUFFER_SIZE
);
943 if(Status
!= NDIS_STATUS_SUCCESS
)
945 DPRINT1("NdisMAllocateMapRegisters failed: 0x%x\n", Status
);
949 MapRegistersAllocated
= TRUE
;
951 /* set up the interrupt */
952 Status
= NdisMRegisterInterrupt(&Adapter
->InterruptObject
, Adapter
->MiniportAdapterHandle
, Adapter
->InterruptVector
,
953 Adapter
->InterruptVector
, TRUE
, TRUE
, NdisInterruptLevelSensitive
);
954 if(Status
!= NDIS_STATUS_SUCCESS
)
956 DPRINT1("NdisMRegisterInterrupt failed: 0x%x\n", Status
);
960 InterruptRegistered
= TRUE
;
962 /* Allocate and initialize shared data structures */
963 Status
= MiAllocateSharedMemory(Adapter
);
964 if(Status
!= NDIS_STATUS_SUCCESS
)
966 Status
= NDIS_STATUS_RESOURCES
;
967 DPRINT1("MiAllocateSharedMemory failed\n", Status
);
971 /* set up the initialization block */
972 MiPrepareInitializationBlock(Adapter
);
974 /* see if someone set a network address manually */
975 NdisOpenConfiguration(&Status
, &ConfigurationHandle
, WrapperConfigurationContext
);
976 if (Status
== NDIS_STATUS_SUCCESS
)
978 NdisReadNetworkAddress(&Status
, (PVOID
*)&RegNetworkAddress
, &RegNetworkAddressLength
, ConfigurationHandle
);
979 if(Status
== NDIS_STATUS_SUCCESS
&& RegNetworkAddressLength
== 6)
982 DPRINT("NdisReadNetworkAddress returned successfully, address %x:%x:%x:%x:%x:%x\n",
983 RegNetworkAddress
[0], RegNetworkAddress
[1], RegNetworkAddress
[2], RegNetworkAddress
[3],
984 RegNetworkAddress
[4], RegNetworkAddress
[5]);
986 for(i
= 0; i
< 6; i
++)
987 Adapter
->InitializationBlockVirt
->PADR
[i
] = RegNetworkAddress
[i
];
990 NdisCloseConfiguration(ConfigurationHandle
);
993 DPRINT("Interrupt registered successfully\n");
995 /* Initialize and start the chip */
998 NdisAllocateSpinLock(&Adapter
->Lock
);
1000 Status
= NDIS_STATUS_SUCCESS
;
1004 if(Status
!= NDIS_STATUS_SUCCESS
&& Adapter
)
1006 DPRINT("Error; freeing stuff\n");
1008 MiFreeSharedMemory(Adapter
);
1010 if(MapRegistersAllocated
)
1011 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
);
1013 if(Adapter
->PortOffset
)
1014 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
1016 if(InterruptRegistered
)
1017 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
1019 NdisFreeMemory(Adapter
, 0, 0);
1022 if(Status
== NDIS_STATUS_SUCCESS
)
1024 NdisMInitializeTimer(&Adapter
->MediaDetectionTimer
,
1025 Adapter
->MiniportAdapterHandle
,
1026 MiniportMediaDetectionTimer
,
1028 NdisMSetPeriodicTimer(&Adapter
->MediaDetectionTimer
,
1029 MEDIA_DETECTION_INTERVAL
);
1030 NdisMRegisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
,
1036 if(!MiTestCard(Adapter
))
1040 DPRINT("returning 0x%x\n", Status
);
1041 *OpenErrorStatus
= Status
;
1048 OUT PBOOLEAN InterruptRecognized
,
1049 OUT PBOOLEAN QueueMiniportHandleInterrupt
,
1050 IN NDIS_HANDLE MiniportAdapterContext
)
1052 * FUNCTION: Miniport interrupt service routine
1054 * InterruptRecognized: the interrupt was ours
1055 * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt
1056 * MiniportAdapterContext: the context originally passed to NdisMSetAttributes
1058 * - called by NDIS at DIRQL
1059 * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt
1065 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1069 /* save the old RAP value */
1070 NdisRawReadPortUshort(Adapter
->PortOffset
+ RAP
, &Rap
);
1073 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1074 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
1076 if(!(Data
& CSR0_INTR
))
1078 DPRINT("not our interrupt.\n");
1079 *InterruptRecognized
= FALSE
;
1080 *QueueMiniportHandleInterrupt
= FALSE
;
1084 DPRINT("detected our interrupt\n");
1086 /* disable interrupts */
1087 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1088 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, 0);
1090 *InterruptRecognized
= TRUE
;
1091 *QueueMiniportHandleInterrupt
= TRUE
;
1094 /* restore the rap */
1095 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, Rap
);
1101 OUT PBOOLEAN AddressingReset
,
1102 IN NDIS_HANDLE MiniportAdapterContext
)
1104 * FUNCTION: Reset the miniport
1106 * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation
1107 * to reset our addresses and filters
1108 * MiniportAdapterContext: context originally passed to NdisMSetAttributes
1110 * NDIS_STATUS_SUCCESS on all requests
1112 * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset
1117 /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */
1119 *AddressingReset
= FALSE
;
1120 return NDIS_STATUS_SUCCESS
;
1125 MiSyncStartTransmit(
1126 IN PVOID SynchronizeContext
)
1128 * FUNCTION: Stop the adapter
1130 * SynchronizeContext: Adapter context
1133 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
1134 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1135 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
| CSR0_TDMD
);
1142 IN NDIS_HANDLE MiniportAdapterContext
,
1143 IN PNDIS_PACKET Packet
,
1146 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out
1148 * MiniportAdapterContext: context originally input to NdisMSetAttributes
1149 * Packet: The NDIS_PACKET to be sent
1150 * Flags: Flags associated with Packet
1152 * NDIS_STATUS_SUCCESS on processed requests
1153 * NDIS_STATUS_RESOURCES if there's no place in buffer ring
1155 * - Called by NDIS at DISPATCH_LEVEL
1158 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1159 PTRANSMIT_DESCRIPTOR Desc
;
1160 PNDIS_BUFFER NdisBuffer
;
1162 UINT TotalPacketLength
, SourceLength
, Position
= 0;
1166 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
1168 NdisDprAcquireSpinLock(&Adapter
->Lock
);
1170 /* Check if we have free entry in our circular buffer. */
1171 if ((Adapter
->CurrentTransmitEndIndex
+ 1 ==
1172 Adapter
->CurrentTransmitStartIndex
) ||
1173 (Adapter
->CurrentTransmitEndIndex
== Adapter
->BufferCount
- 1 &&
1174 Adapter
->CurrentTransmitStartIndex
== 0))
1176 DPRINT1("No free space in circular buffer\n");
1177 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1178 return NDIS_STATUS_RESOURCES
;
1181 Desc
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitEndIndex
;
1183 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, &TotalPacketLength
);
1184 ASSERT(TotalPacketLength
<= BUFFER_SIZE
);
1186 DPRINT("TotalPacketLength: %x\n", TotalPacketLength
);
1190 NdisQueryBuffer(NdisBuffer
, &SourceBuffer
, &SourceLength
);
1192 DPRINT("Buffer: %x Length: %x\n", SourceBuffer
, SourceLength
);
1194 RtlCopyMemory(Adapter
->TransmitBufferPtrVirt
+
1195 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
+ Position
,
1196 SourceBuffer
, SourceLength
);
1198 Position
+= SourceLength
;
1200 NdisGetNextBuffer(NdisBuffer
, &NdisBuffer
);
1205 PUCHAR Ptr
= Adapter
->TransmitBufferPtrVirt
+
1206 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
;
1207 for (Position
= 0; Position
< TotalPacketLength
; Position
++)
1209 if (Position
% 16 == 0)
1211 DbgPrint("%x ", *Ptr
++);
1217 Adapter
->CurrentTransmitEndIndex
++;
1218 Adapter
->CurrentTransmitEndIndex
%= Adapter
->BufferCount
;
1220 Desc
->FLAGS
= TD1_OWN
| TD1_STP
| TD1_ENP
;
1221 Desc
->BCNT
= 0xf000 | -TotalPacketLength
;
1223 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStartTransmit
, Adapter
);
1225 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1227 return NDIS_STATUS_SUCCESS
;
1232 MiEthernetCrc(UCHAR
*Address
)
1234 * FUNCTION: Calculate Ethernet CRC32
1236 * Address: 6-byte ethernet address
1238 * The calculated CRC32 value.
1241 UINT Counter
, Length
;
1244 for (Length
= 0; Length
< 6; Length
++)
1246 Value
^= *Address
++;
1247 for (Counter
= 0; Counter
< 8; Counter
++)
1250 Value
^= (Value
& 1) * 0xedb88320;
1267 NdisZeroMemory(Adapter
->InitializationBlockVirt
->LADR
, 8);
1268 for (Index
= 0; Index
< AddressCount
; Index
++)
1270 CrcIndex
= MiEthernetCrc(Addresses
) >> 26;
1271 Adapter
->InitializationBlockVirt
->LADR
[CrcIndex
>> 3] |= 1 << (CrcIndex
& 15);
1275 /* FIXME: The specification mentions we need to reload the init block here. */
1277 return NDIS_STATUS_SUCCESS
;
1282 MiGetMediaDuplex(PADAPTER Adapter
)
1286 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR5
);
1287 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1289 return (Data
& BCR5_LEDOUT
) != 0;
1294 MiGetMediaSpeed(PADAPTER Adapter
)
1298 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR6
);
1299 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1301 return Data
& BCR6_LEDOUT
? 100 : 10;
1306 MiGetMediaState(PADAPTER Adapter
)
1308 * FUNCTION: Determine the link state
1310 * Adapter: Adapter context
1312 * NdisMediaStateConnected if the cable is connected
1313 * NdisMediaStateDisconnected if the cable is disconnected
1317 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
1318 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1319 return Data
& BCR4_LEDOUT
? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
1325 IN PDRIVER_OBJECT DriverObject
,
1326 IN PUNICODE_STRING RegistryPath
)
1328 * FUNCTION: Start this driver
1330 * DriverObject: Pointer to the system-allocated driver object
1331 * RegistryPath: Pointer to our SCM database entry
1333 * NDIS_STATUS_SUCCESS on success
1334 * NDIS_STATUS_FAILURE on failure
1336 * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL
1337 * - TODO: convert this to NTSTATUS return values
1340 NDIS_HANDLE WrapperHandle
;
1341 NDIS_MINIPORT_CHARACTERISTICS Characteristics
;
1344 RtlZeroMemory(&Characteristics
, sizeof(Characteristics
));
1345 Characteristics
.MajorNdisVersion
= NDIS_MINIPORT_MAJOR_VERSION
;
1346 Characteristics
.MinorNdisVersion
= NDIS_MINIPORT_MINOR_VERSION
;
1347 Characteristics
.HaltHandler
= MiniportHalt
;
1348 Characteristics
.HandleInterruptHandler
= MiniportHandleInterrupt
;
1349 Characteristics
.InitializeHandler
= MiniportInitialize
;
1350 Characteristics
.ISRHandler
= MiniportISR
;
1351 Characteristics
.QueryInformationHandler
= MiniportQueryInformation
;
1352 Characteristics
.ResetHandler
= MiniportReset
;
1353 Characteristics
.SetInformationHandler
= MiniportSetInformation
;
1354 Characteristics
.SendHandler
= MiniportSend
;
1356 NdisMInitializeWrapper(&WrapperHandle
, DriverObject
, RegistryPath
, 0);
1357 if (!WrapperHandle
) return NDIS_STATUS_FAILURE
;
1359 Status
= NdisMRegisterMiniport(WrapperHandle
, &Characteristics
, sizeof(Characteristics
));
1360 if(Status
!= NDIS_STATUS_SUCCESS
)
1362 NdisTerminateWrapper(WrapperHandle
, 0);
1363 return NDIS_STATUS_FAILURE
;
1366 return NDIS_STATUS_SUCCESS
;