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
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, 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
52 IN PDRIVER_OBJECT DriverObject
,
53 IN PUNICODE_STRING RegistryPath
);
57 MiniportHandleInterrupt(
58 IN NDIS_HANDLE MiniportAdapterContext
)
60 * FUNCTION: Handle an interrupt if told to by MiniportISR
62 * MiniportAdapterContext: context specified to NdisMSetAttributes
64 * - Called by NDIS at DISPATCH_LEVEL
67 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
72 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
74 NdisDprAcquireSpinLock(&Adapter
->Lock
);
76 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
77 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
79 DPRINT("CSR0 is 0x%x\n", Data
);
81 while(Data
& CSR0_INTR
)
83 /* Clear interrupt flags early to avoid race conditions. */
84 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
88 DPRINT("error: %x\n", Data
& (CSR0_MERR
|CSR0_BABL
|CSR0_CERR
|CSR0_MISS
));
90 Adapter
->Statistics
.XmtCollisions
++;
98 BOOLEAN IndicatedData
= FALSE
;
100 DPRINT("receive interrupt\n");
104 PRECEIVE_DESCRIPTOR Descriptor
= Adapter
->ReceiveDescriptorRingVirt
+ Adapter
->CurrentReceiveDescriptorIndex
;
108 if(Descriptor
->FLAGS
& RD_OWN
)
110 DPRINT("no more receive descriptors to process\n");
114 if(Descriptor
->FLAGS
& RD_ERR
)
116 DPRINT("receive descriptor error: 0x%x\n", Descriptor
->FLAGS
);
117 if (Descriptor
->FLAGS
& RD_BUFF
)
118 Adapter
->Statistics
.RcvBufferErrors
++;
119 if (Descriptor
->FLAGS
& RD_CRC
)
120 Adapter
->Statistics
.RcvCrcErrors
++;
121 if (Descriptor
->FLAGS
& RD_OFLO
)
122 Adapter
->Statistics
.RcvOverflowErrors
++;
123 if (Descriptor
->FLAGS
& RD_FRAM
)
124 Adapter
->Statistics
.RcvFramingErrors
++;
128 if(!((Descriptor
->FLAGS
& RD_STP
) && (Descriptor
->FLAGS
& RD_ENP
)))
130 DPRINT("receive descriptor not start&end: 0x%x\n", Descriptor
->FLAGS
);
134 Buffer
= Adapter
->ReceiveBufferPtrVirt
+ Adapter
->CurrentReceiveDescriptorIndex
* BUFFER_SIZE
;
135 ByteCount
= Descriptor
->MCNT
& 0xfff;
137 DPRINT("Indicating a %d-byte packet (index %d)\n", ByteCount
, Adapter
->CurrentReceiveDescriptorIndex
);
139 NdisMEthIndicateReceive(Adapter
->MiniportAdapterHandle
, 0, Buffer
, 14, Buffer
+14, ByteCount
-14, ByteCount
-14);
141 IndicatedData
= TRUE
;
143 RtlZeroMemory(Descriptor
, sizeof(RECEIVE_DESCRIPTOR
));
145 (ULONG
)(Adapter
->ReceiveBufferPtrPhys
+ Adapter
->CurrentReceiveDescriptorIndex
* BUFFER_SIZE
);
146 Descriptor
->BCNT
= (-BUFFER_SIZE
) | 0xf000;
147 Descriptor
->FLAGS
|= RD_OWN
;
149 Adapter
->CurrentReceiveDescriptorIndex
++;
150 Adapter
->CurrentReceiveDescriptorIndex
%= NUMBER_OF_BUFFERS
;
152 Adapter
->Statistics
.RcvGoodFrames
++;
156 NdisMEthIndicateReceiveComplete(Adapter
->MiniportAdapterHandle
);
160 PTRANSMIT_DESCRIPTOR Descriptor
;
162 DPRINT("transmit interrupt\n");
164 while (Adapter
->CurrentTransmitStartIndex
!=
165 Adapter
->CurrentTransmitEndIndex
)
167 Descriptor
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitStartIndex
;
169 DPRINT("buffer %d flags %x flags2 %x\n",
170 Adapter
->CurrentTransmitStartIndex
,
171 Descriptor
->FLAGS
, Descriptor
->FLAGS2
);
173 if (Descriptor
->FLAGS
& TD1_OWN
)
175 DPRINT("non-TXed buffer\n");
179 if (Descriptor
->FLAGS
& TD1_STP
)
181 if (Descriptor
->FLAGS
& TD1_ONE
)
182 Adapter
->Statistics
.XmtOneRetry
++;
183 else if (Descriptor
->FLAGS
& TD1_MORE
)
184 Adapter
->Statistics
.XmtMoreThanOneRetry
++;
187 if (Descriptor
->FLAGS
& TD1_ERR
)
189 DPRINT("major error: %x\n", Descriptor
->FLAGS2
);
190 if (Descriptor
->FLAGS2
& TD2_RTRY
)
191 Adapter
->Statistics
.XmtRetryErrors
++;
192 if (Descriptor
->FLAGS2
& TD2_LCAR
)
193 Adapter
->Statistics
.XmtLossesOfCarrier
++;
194 if (Descriptor
->FLAGS2
& TD2_LCOL
)
195 Adapter
->Statistics
.XmtLateCollisions
++;
196 if (Descriptor
->FLAGS2
& TD2_EXDEF
)
197 Adapter
->Statistics
.XmtExcessiveDefferals
++;
198 if (Descriptor
->FLAGS2
& TD2_UFLO
)
199 Adapter
->Statistics
.XmtBufferUnderflows
++;
200 if (Descriptor
->FLAGS2
& TD2_BUFF
)
201 Adapter
->Statistics
.XmtBufferErrors
++;
205 Adapter
->CurrentTransmitStartIndex
++;
206 Adapter
->CurrentTransmitStartIndex
%= NUMBER_OF_BUFFERS
;
208 Adapter
->Statistics
.XmtGoodFrames
++;
210 NdisMSendResourcesAvailable(Adapter
->MiniportAdapterHandle
);
212 if(Data
& ~(CSR0_ERR
| CSR0_IDON
| CSR0_RINT
| CSR0_TINT
))
214 DPRINT("UNHANDLED INTERRUPT CSR0 0x%x\n", Data
);
217 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
220 /* re-enable interrupts */
221 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
);
223 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
224 DPRINT("CSR0 is now 0x%x\n", Data
);
226 NdisDprReleaseSpinLock(&Adapter
->Lock
);
233 * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector
235 * MiniportAdapterContext: context supplied to NdisMSetAttributes
237 * NDIS_STATUS_FAILURE on a general error
238 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
239 * NDIS_STATUS_SUCCESS on succes
246 /* Detect the card in the configured slot */
247 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_PCIID
, &buf32
, 4);
250 Status
= NDIS_STATUS_FAILURE
;
251 DPRINT("NdisReadPciSlotInformation failed\n");
258 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
259 DPRINT("card in slot isn't our: 0x%x\n", 0, buf32
);
264 /* set busmaster and io space enable bits */
265 buf32
= PCI_BMEN
| PCI_IOEN
;
266 NdisWritePciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_COMMAND
, &buf32
, 4);
268 /* get IO base physical address */
270 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_IOBAR
, &buf32
, 4);
273 Status
= NDIS_STATUS_FAILURE
;
274 DPRINT("NdisReadPciSlotInformation failed\n");
281 DPRINT("No base i/o address set\n");
282 return NDIS_STATUS_FAILURE
;
285 buf32
&= ~1; /* even up address - comes out odd for some reason */
287 DPRINT("detected io address 0x%x\n", buf32
);
288 Adapter
->IoBaseAddress
= buf32
;
290 /* get interrupt vector */
291 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_ILR
, &buf8
, 1);
294 Status
= NDIS_STATUS_FAILURE
;
295 DPRINT1("NdisReadPciSlotInformation failed\n");
300 DPRINT("interrupt: 0x%x\n", buf8
);
301 Adapter
->InterruptVector
= buf8
;
303 return NDIS_STATUS_SUCCESS
;
307 MiAllocateSharedMemory(
310 * FUNCTION: Allocate all shared memory used by the miniport
312 * Adapter: Pointer to the miniport's adapter object
314 * NDIS_STATUS_RESOURCES on insufficient memory
315 * NDIS_STATUS_SUCCESS on success
318 PTRANSMIT_DESCRIPTOR TransmitDescriptor
;
319 PRECEIVE_DESCRIPTOR ReceiveDescriptor
;
320 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
323 /* allocate the initialization block */
324 Adapter
->InitializationBlockLength
= sizeof(INITIALIZATION_BLOCK
);
325 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
326 FALSE
, (PVOID
*)&Adapter
->InitializationBlockVirt
, &PhysicalAddress
);
327 if(!Adapter
->InitializationBlockVirt
)
329 DPRINT1("insufficient resources\n");
331 return NDIS_STATUS_RESOURCES
;
334 if(((ULONG
)Adapter
->InitializationBlockVirt
& 0x00000003) != 0)
336 DPRINT("address 0x%x not dword-aligned\n", Adapter
->InitializationBlockVirt
);
338 return NDIS_STATUS_RESOURCES
;
341 Adapter
->InitializationBlockPhys
= (PINITIALIZATION_BLOCK
)NdisGetPhysicalAddressLow(PhysicalAddress
);
343 /* allocate the transport descriptor ring */
344 Adapter
->TransmitDescriptorRingLength
= sizeof(TRANSMIT_DESCRIPTOR
) * NUMBER_OF_BUFFERS
;
345 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
346 FALSE
, (PVOID
*)&Adapter
->TransmitDescriptorRingVirt
, &PhysicalAddress
);
347 if(!Adapter
->TransmitDescriptorRingVirt
)
349 DPRINT1("insufficient resources\n");
351 return NDIS_STATUS_RESOURCES
;
354 if(((ULONG
)Adapter
->TransmitDescriptorRingVirt
& 0x00000003) != 0)
356 DPRINT("address 0x%x not dword-aligned\n", Adapter
->TransmitDescriptorRingVirt
);
358 return NDIS_STATUS_RESOURCES
;
361 Adapter
->TransmitDescriptorRingPhys
= (PTRANSMIT_DESCRIPTOR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
362 RtlZeroMemory(Adapter
->TransmitDescriptorRingVirt
, sizeof(TRANSMIT_DESCRIPTOR
) * NUMBER_OF_BUFFERS
);
364 /* allocate the receive descriptor ring */
365 Adapter
->ReceiveDescriptorRingLength
= sizeof(RECEIVE_DESCRIPTOR
) * NUMBER_OF_BUFFERS
;
366 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
367 FALSE
, (PVOID
*)&Adapter
->ReceiveDescriptorRingVirt
, &PhysicalAddress
);
368 if(!Adapter
->ReceiveDescriptorRingVirt
)
370 DPRINT1("insufficient resources\n");
372 return NDIS_STATUS_RESOURCES
;
375 if(((ULONG
)Adapter
->ReceiveDescriptorRingVirt
& 0x00000003) != 0)
377 DPRINT("address 0x%x not dword-aligned\n", Adapter
->ReceiveDescriptorRingVirt
);
379 return NDIS_STATUS_RESOURCES
;
382 Adapter
->ReceiveDescriptorRingPhys
= (PRECEIVE_DESCRIPTOR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
383 RtlZeroMemory(Adapter
->ReceiveDescriptorRingVirt
, sizeof(RECEIVE_DESCRIPTOR
) * NUMBER_OF_BUFFERS
);
385 /* allocate transmit buffers */
386 Adapter
->TransmitBufferLength
= BUFFER_SIZE
* NUMBER_OF_BUFFERS
;
387 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
388 FALSE
, (PVOID
*)&Adapter
->TransmitBufferPtrVirt
, &PhysicalAddress
);
389 if(!Adapter
->TransmitBufferPtrVirt
)
391 DPRINT1("insufficient resources\n");
393 return NDIS_STATUS_RESOURCES
;
396 if(((ULONG
)Adapter
->TransmitBufferPtrVirt
& 0x00000003) != 0)
398 DPRINT("address 0x%x not dword-aligned\n", Adapter
->TransmitBufferPtrVirt
);
400 return NDIS_STATUS_RESOURCES
;
403 Adapter
->TransmitBufferPtrPhys
= (PCHAR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
404 RtlZeroMemory(Adapter
->TransmitBufferPtrVirt
, BUFFER_SIZE
* NUMBER_OF_BUFFERS
);
406 /* allocate receive buffers */
407 Adapter
->ReceiveBufferLength
= BUFFER_SIZE
* NUMBER_OF_BUFFERS
;
408 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
409 FALSE
, (PVOID
*)&Adapter
->ReceiveBufferPtrVirt
, &PhysicalAddress
);
410 if(!Adapter
->ReceiveBufferPtrVirt
)
412 DPRINT1("insufficient resources\n");
414 return NDIS_STATUS_RESOURCES
;
417 if(((ULONG
)Adapter
->ReceiveBufferPtrVirt
& 0x00000003) != 0)
419 DPRINT("address 0x%x not dword-aligned\n", Adapter
->ReceiveBufferPtrVirt
);
421 return NDIS_STATUS_RESOURCES
;
424 Adapter
->ReceiveBufferPtrPhys
= (PCHAR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
425 RtlZeroMemory(Adapter
->ReceiveBufferPtrVirt
, BUFFER_SIZE
* NUMBER_OF_BUFFERS
);
427 /* initialize tx descriptors */
428 TransmitDescriptor
= Adapter
->TransmitDescriptorRingVirt
;
429 for(i
= 0; i
< NUMBER_OF_BUFFERS
; i
++)
431 (TransmitDescriptor
+i
)->TBADR
= (ULONG
)Adapter
->TransmitBufferPtrPhys
+ i
* BUFFER_SIZE
;
432 (TransmitDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
433 (TransmitDescriptor
+i
)->FLAGS
= TD1_STP
| TD1_ENP
;
436 DPRINT("transmit ring initialized\n");
439 ReceiveDescriptor
= Adapter
->ReceiveDescriptorRingVirt
;
440 for(i
= 0; i
< NUMBER_OF_BUFFERS
; i
++)
442 (ReceiveDescriptor
+i
)->RBADR
= (ULONG
)Adapter
->ReceiveBufferPtrPhys
+ i
* BUFFER_SIZE
;
443 (ReceiveDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
444 (ReceiveDescriptor
+i
)->FLAGS
= RD_OWN
;
447 DPRINT("receive ring initialized\n");
449 return NDIS_STATUS_SUCCESS
;
453 MiPrepareInitializationBlock(
456 * FUNCTION: Initialize the initialization block
458 * Adapter: pointer to the miniport's adapter object
463 RtlZeroMemory(Adapter
->InitializationBlockVirt
, sizeof(INITIALIZATION_BLOCK
));
465 /* read burned-in address from card */
466 for(i
= 0; i
< 6; i
++)
467 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, Adapter
->InitializationBlockVirt
->PADR
+ i
);
468 DPRINT("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
469 Adapter
->InitializationBlockVirt
->PADR
[0],
470 Adapter
->InitializationBlockVirt
->PADR
[1],
471 Adapter
->InitializationBlockVirt
->PADR
[2],
472 Adapter
->InitializationBlockVirt
->PADR
[3],
473 Adapter
->InitializationBlockVirt
->PADR
[4],
474 Adapter
->InitializationBlockVirt
->PADR
[5]);
476 /* set up receive ring */
477 DPRINT("Receive ring physical address: 0x%x\n", Adapter
->ReceiveDescriptorRingPhys
);
478 Adapter
->InitializationBlockVirt
->RDRA
= (ULONG
)Adapter
->ReceiveDescriptorRingPhys
;
479 Adapter
->InitializationBlockVirt
->RLEN
= (LOG_NUMBER_OF_BUFFERS
<< 4) & 0xf0;
481 /* set up transmit ring */
482 DPRINT("Transmit ring physical address: 0x%x\n", Adapter
->TransmitDescriptorRingPhys
);
483 Adapter
->InitializationBlockVirt
->TDRA
= (ULONG
)Adapter
->TransmitDescriptorRingPhys
;
484 Adapter
->InitializationBlockVirt
->TLEN
= (LOG_NUMBER_OF_BUFFERS
<< 4) & 0xf0;
491 * FUNCTION: Free all allocated shared memory
493 * Adapter: pointer to the miniport's adapter struct
496 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
498 PhysicalAddress
.u
.HighPart
= 0;
500 if(Adapter
->InitializationBlockVirt
)
502 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->InitializationBlockPhys
;
503 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
504 FALSE
, Adapter
->InitializationBlockVirt
, PhysicalAddress
);
507 if(Adapter
->TransmitDescriptorRingVirt
)
509 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->TransmitDescriptorRingPhys
;
510 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
511 FALSE
, Adapter
->TransmitDescriptorRingVirt
, PhysicalAddress
);
514 if(Adapter
->ReceiveDescriptorRingVirt
)
516 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->ReceiveDescriptorRingPhys
;
517 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
518 FALSE
, Adapter
->ReceiveDescriptorRingVirt
, PhysicalAddress
);
521 if(Adapter
->TransmitBufferPtrVirt
)
523 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->TransmitBufferPtrPhys
;
524 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
525 FALSE
, Adapter
->TransmitBufferPtrVirt
, PhysicalAddress
);
528 if(Adapter
->ReceiveBufferPtrVirt
)
530 PhysicalAddress
.u
.LowPart
= (ULONG
)Adapter
->ReceiveBufferPtrPhys
;
531 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
532 FALSE
, Adapter
->ReceiveBufferPtrVirt
, PhysicalAddress
);
539 IN PVOID SynchronizeContext
)
541 * FUNCTION: Stop the adapter
543 * SynchronizeContext: Adapter context
546 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
547 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
548 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
555 IN NDIS_HANDLE MiniportAdapterContext
)
557 * FUNCTION: Stop the adapter and release any per-adapter resources
559 * MiniportAdapterContext: context specified to NdisMSetAttributes
561 * - Called by NDIS at PASSIVE_LEVEL
564 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
565 BOOLEAN TimerCancelled
;
570 /* stop the media detection timer */
571 NdisMCancelTimer(&Adapter
->MediaDetectionTimer
, &TimerCancelled
);
574 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStop
, Adapter
);
576 /* deregister the interrupt */
577 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
579 /* deregister i/o port range */
580 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
582 /* deregister the shutdown routine */
583 NdisMDeregisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
);
585 /* free shared memory */
586 MiFreeSharedMemory(Adapter
);
588 /* free map registers */
589 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
);
592 NdisFreeSpinLock(&Adapter
->Lock
);
594 /* free the adapter */
595 NdisFreeMemory(Adapter
, 0, 0);
600 MiSyncMediaDetection(
601 IN PVOID SynchronizeContext
)
603 * FUNCTION: Stop the adapter
605 * SynchronizeContext: Adapter context
608 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
609 NDIS_MEDIA_STATE MediaState
= MiGetMediaState(Adapter
);
610 UINT MediaSpeed
= MiGetMediaSpeed(Adapter
);
611 BOOLEAN FullDuplex
= MiGetMediaDuplex(Adapter
);
614 DPRINT("MediaState: %d\n", MediaState
);
615 if (MediaState
!= Adapter
->MediaState
||
616 MediaSpeed
!= Adapter
->MediaSpeed
||
617 FullDuplex
!= Adapter
->FullDuplex
)
619 Adapter
->MediaState
= MediaState
;
620 Adapter
->MediaSpeed
= MediaSpeed
;
621 Adapter
->FullDuplex
= FullDuplex
;
629 MiniportMediaDetectionTimer(
630 IN PVOID SystemSpecific1
,
631 IN PVOID FunctionContext
,
632 IN PVOID SystemSpecific2
,
633 IN PVOID SystemSpecific3
)
635 * FUNCTION: Periodially query media state
637 * FunctionContext: Adapter context
639 * - Called by NDIS at DISPATCH_LEVEL
642 PADAPTER Adapter
= (PADAPTER
)FunctionContext
;
644 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
646 if (NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
,
647 MiSyncMediaDetection
,
650 NdisMIndicateStatus(Adapter
->MiniportAdapterHandle
,
651 Adapter
->MediaState
== NdisMediaStateConnected
?
652 NDIS_STATUS_MEDIA_CONNECT
: NDIS_STATUS_MEDIA_DISCONNECT
,
654 NdisMIndicateStatusComplete(Adapter
->MiniportAdapterHandle
);
662 * FUNCTION: Initialize and start the PCNET chip
664 * Adapter: pointer to the miniport's adapter struct
666 * - should be coded to detect failure and return an error
667 * - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that.
675 * first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset
676 * twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the
677 * card is reset by reading from the reset register. on reset it's in 16-bit i/o mode.
679 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET32
, &Data
);
680 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET16
, &Data
);
683 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
684 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
686 /* pause for 1ms so the chip will have time to reset */
687 NdisStallExecution(1);
689 DPRINT("chip stopped\n");
691 /* set the software style to 2 (32 bits) */
692 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR58
);
693 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
697 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
699 /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */
700 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
701 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
703 Data
|= CSR4_APAD_XMT
| /* CSR4_DPOLL |*/ CSR4_TXSTRTM
| CSR4_DMAPLUS
;
704 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
706 /* set up bcr18: burst read/write enable */
707 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR18
);
708 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
710 Data
|= BCR18_BREADE
| BCR18_BWRITE
;
711 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, Data
);
713 /* set up csr1 and csr2 with init block */
714 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR1
);
715 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG
)Adapter
->InitializationBlockPhys
& 0xffff));
716 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR2
);
717 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG
)Adapter
->InitializationBlockPhys
>> 16) & 0xffff);
719 DPRINT("programmed with init block\n");
723 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR15
);
724 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
726 /* load init block and start the card */
727 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
728 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STRT
|CSR0_INIT
|CSR0_IENA
);
730 /* Allow LED programming */
731 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR2
);
732 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR2_LEDPE
);
734 /* LED0 is configured for link status (on = up, off = down) */
735 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
736 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR4_LNKSTE
| BCR4_PSE
);
738 /* LED1 is configured for link duplex (on = full, off = half) */
739 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR5
);
740 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR5_FDLSE
| BCR5_PSE
);
742 /* LED2 is configured for link speed (on = 100M, off = 10M) */
743 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR6
);
744 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR6_E100
| BCR6_PSE
);
746 /* LED3 is configured for trasmit/receive activity */
747 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR7
);
748 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR7_XMTE
| BCR7_RCVE
| BCR7_PSE
);
750 Adapter
->MediaState
= MiGetMediaState(Adapter
);
751 Adapter
->FullDuplex
= MiGetMediaDuplex(Adapter
);
752 Adapter
->MediaSpeed
= MiGetMediaSpeed(Adapter
);
754 DPRINT("card started\n");
756 Adapter
->Flags
&= ~RESET_IN_PROGRESS
;
764 * FUNCTION: Test the NIC
766 * Adapter: pointer to the miniport's adapter struct
768 * TRUE if the test succeeds
771 * - this is where to add diagnostics. This is called
772 * at the very end of initialization.
779 /* see if we can read/write now */
780 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
781 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
782 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
);
785 for(i
= 0; i
< 6; i
++)
786 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, &address
[i
]);
788 DPRINT("burned-in address: %x:%x:%x:%x:%x:%x\n", address
[0], address
[1], address
[2], address
[3], address
[4], address
[5]);
789 /* Read status flags from CSR0 */
790 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
791 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
792 DPRINT("CSR0: 0x%x\n", Data
);
794 /* Read status flags from CSR3 */
795 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR3
);
796 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
798 DPRINT("CSR3: 0x%x\n", Data
);
799 /* Read status flags from CSR4 */
800 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
801 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
802 DPRINT("CSR4: 0x%x\n", Data
);
804 /* Read status flags from CSR5 */
805 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR5
);
806 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
807 DPRINT("CSR5: 0x%x\n", Data
);
809 /* Read status flags from CSR6 */
810 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR6
);
811 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
812 DPRINT("CSR6: 0x%x\n", Data
);
820 MiniportShutdown( PVOID Context
)
822 PADAPTER Adapter
= Context
;
824 DPRINT("Stopping the chip\n");
826 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
827 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
833 OUT PNDIS_STATUS OpenErrorStatus
,
834 OUT PUINT SelectedMediumIndex
,
835 IN PNDIS_MEDIUM MediumArray
,
836 IN UINT MediumArraySize
,
837 IN NDIS_HANDLE MiniportAdapterHandle
,
838 IN NDIS_HANDLE WrapperConfigurationContext
)
840 * FUNCTION: Initialize a new miniport
842 * OpenErrorStatus: pointer to a var to return status info in
843 * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3)
844 * MediumArray: array of media that we can pick from
845 * MediumArraySize: size of MediumArray
846 * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance
847 * WrapperConfigurationContext: temporary NDIS-assigned handle for passing
848 * to configuration APIs
850 * NDIS_STATUS_SUCCESS on success
851 * NDIS_STATUS_FAILURE on general failure
852 * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray
853 * NDIS_STATUS_RESOURCES on insufficient system resources
854 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
856 * - Called by NDIS at PASSIVE_LEVEL, once per detected card
857 * - Will int 3 on failure of MiTestCard if DBG=1
861 PADAPTER Adapter
= 0;
862 NDIS_STATUS Status
= NDIS_STATUS_FAILURE
;
863 BOOLEAN InterruptRegistered
= FALSE
;
864 NDIS_HANDLE ConfigurationHandle
;
865 UINT
*RegNetworkAddress
= 0;
866 UINT RegNetworkAddressLength
= 0;
868 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
871 for(i
= 0; i
< MediumArraySize
; i
++)
872 if(MediumArray
[i
] == NdisMedium802_3
)
875 if(i
== MediumArraySize
)
877 Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
878 DPRINT1("unsupported media\n");
880 *OpenErrorStatus
= Status
;
884 *SelectedMediumIndex
= i
;
886 /* allocate our adapter struct */
887 Status
= NdisAllocateMemoryWithTag((PVOID
*)&Adapter
, sizeof(ADAPTER
), PCNET_TAG
);
888 if(Status
!= NDIS_STATUS_SUCCESS
)
890 Status
= NDIS_STATUS_RESOURCES
;
891 DPRINT1("Insufficient resources\n");
893 *OpenErrorStatus
= Status
;
897 RtlZeroMemory(Adapter
, sizeof(ADAPTER
));
899 Adapter
->MiniportAdapterHandle
= MiniportAdapterHandle
;
901 /* register our adapter structwith ndis */
902 NdisMSetAttributesEx(Adapter
->MiniportAdapterHandle
, Adapter
, 0, NDIS_ATTRIBUTE_BUS_MASTER
, NdisInterfacePci
);
906 /* Card-specific detection and setup */
907 Status
= MiQueryCard(Adapter
);
908 if(Status
!= NDIS_STATUS_SUCCESS
)
910 DPRINT1("MiQueryCard failed\n");
911 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
916 /* register an IO port range */
917 Status
= NdisMRegisterIoPortRange((PVOID
*)&Adapter
->PortOffset
, Adapter
->MiniportAdapterHandle
,
918 (UINT
)Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
);
919 if(Status
!= NDIS_STATUS_SUCCESS
)
921 DPRINT1("NdisMRegisterIoPortRange failed: 0x%x\n", Status
);
926 /* Allocate map registers */
927 Status
= NdisMAllocateMapRegisters(Adapter
->MiniportAdapterHandle
, 0,
928 NDIS_DMA_32BITS
, 8, BUFFER_SIZE
);
929 if(Status
!= NDIS_STATUS_SUCCESS
)
931 DPRINT1("NdisMAllocateMapRegisters failed: 0x%x\n", Status
);
936 /* set up the interrupt */
937 Status
= NdisMRegisterInterrupt(&Adapter
->InterruptObject
, Adapter
->MiniportAdapterHandle
, Adapter
->InterruptVector
,
938 Adapter
->InterruptVector
, TRUE
, TRUE
, NdisInterruptLevelSensitive
);
939 if(Status
!= NDIS_STATUS_SUCCESS
)
941 DPRINT("NdisMRegisterInterrupt failed: 0x%x\n", Status
);
946 InterruptRegistered
= TRUE
;
948 /* Allocate and initialize shared data structures */
949 Status
= MiAllocateSharedMemory(Adapter
);
950 if(Status
!= NDIS_STATUS_SUCCESS
)
952 Status
= NDIS_STATUS_RESOURCES
;
953 DPRINT("MiAllocateSharedMemory failed", Status
);
958 /* set up the initialization block */
959 MiPrepareInitializationBlock(Adapter
);
961 /* see if someone set a network address manually */
962 NdisOpenConfiguration(&Status
, &ConfigurationHandle
, WrapperConfigurationContext
);
963 if (Status
== NDIS_STATUS_SUCCESS
)
965 NdisReadNetworkAddress(&Status
, (PVOID
*)&RegNetworkAddress
, &RegNetworkAddressLength
, ConfigurationHandle
);
966 if(Status
== NDIS_STATUS_SUCCESS
&& RegNetworkAddressLength
== 6)
969 DPRINT("NdisReadNetworkAddress returned successfully, address %x:%x:%x:%x:%x:%x\n",
970 RegNetworkAddress
[0], RegNetworkAddress
[1], RegNetworkAddress
[2], RegNetworkAddress
[3],
971 RegNetworkAddress
[4], RegNetworkAddress
[5]);
973 for(i
= 0; i
< 6; i
++)
974 Adapter
->InitializationBlockVirt
->PADR
[i
] = RegNetworkAddress
[i
];
977 NdisCloseConfiguration(ConfigurationHandle
);
980 DPRINT("Interrupt registered successfully\n");
982 /* Initialize and start the chip */
985 NdisAllocateSpinLock(&Adapter
->Lock
);
987 Status
= NDIS_STATUS_SUCCESS
;
991 if(Status
!= NDIS_STATUS_SUCCESS
&& Adapter
)
993 DPRINT("Error; freeing stuff\n");
995 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
); /* doesn't hurt to free if we never alloc'd? */
997 if(Adapter
->PortOffset
)
998 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
1000 if(InterruptRegistered
)
1001 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
1003 MiFreeSharedMemory(Adapter
);
1005 NdisFreeMemory(Adapter
, 0, 0);
1008 if(Status
== NDIS_STATUS_SUCCESS
)
1010 NdisMInitializeTimer(&Adapter
->MediaDetectionTimer
,
1011 Adapter
->MiniportAdapterHandle
,
1012 MiniportMediaDetectionTimer
,
1014 NdisMSetPeriodicTimer(&Adapter
->MediaDetectionTimer
,
1015 MEDIA_DETECTION_INTERVAL
);
1016 NdisMRegisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
,
1022 if(!MiTestCard(Adapter
))
1026 DPRINT("returning 0x%x\n", Status
);
1027 *OpenErrorStatus
= Status
;
1034 OUT PBOOLEAN InterruptRecognized
,
1035 OUT PBOOLEAN QueueMiniportHandleInterrupt
,
1036 IN NDIS_HANDLE MiniportAdapterContext
)
1038 * FUNCTION: Miniport interrupt service routine
1040 * InterruptRecognized: the interrupt was ours
1041 * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt
1042 * MiniportAdapterContext: the context originally passed to NdisMSetAttributes
1044 * - called by NDIS at DIRQL
1045 * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt
1051 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1055 /* save the old RAP value */
1056 NdisRawReadPortUshort(Adapter
->PortOffset
+ RAP
, &Rap
);
1059 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1060 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
1062 if(!(Data
& CSR0_INTR
))
1064 DPRINT("not our interrupt.\n");
1065 *InterruptRecognized
= FALSE
;
1066 *QueueMiniportHandleInterrupt
= FALSE
;
1070 DPRINT("detected our interrupt\n");
1072 /* disable interrupts */
1073 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1074 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, 0);
1076 *InterruptRecognized
= TRUE
;
1077 *QueueMiniportHandleInterrupt
= TRUE
;
1080 /* restore the rap */
1081 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, Rap
);
1087 OUT PBOOLEAN AddressingReset
,
1088 IN NDIS_HANDLE MiniportAdapterContext
)
1090 * FUNCTION: Reset the miniport
1092 * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation
1093 * to reset our addresses and filters
1094 * MiniportAdapterContext: context originally passed to NdisMSetAttributes
1096 * NDIS_STATUS_SUCCESS on all requests
1098 * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset
1103 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
1105 /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */
1107 *AddressingReset
= FALSE
;
1108 return NDIS_STATUS_SUCCESS
;
1113 MiSyncStartTransmit(
1114 IN PVOID SynchronizeContext
)
1116 * FUNCTION: Stop the adapter
1118 * SynchronizeContext: Adapter context
1121 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
1122 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1123 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
| CSR0_TDMD
);
1130 IN NDIS_HANDLE MiniportAdapterContext
,
1131 IN PNDIS_PACKET Packet
,
1134 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out
1136 * MiniportAdapterContext: context originally input to NdisMSetAttributes
1137 * Packet: The NDIS_PACKET to be sent
1138 * Flags: Flags associated with Packet
1140 * NDIS_STATUS_SUCCESS on processed requests
1141 * NDIS_STATUS_RESOURCES if there's no place in buffer ring
1143 * - Called by NDIS at DISPATCH_LEVEL
1146 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1147 PTRANSMIT_DESCRIPTOR Desc
;
1148 PNDIS_BUFFER NdisBuffer
;
1150 UINT TotalPacketLength
, SourceLength
, Position
= 0;
1154 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
1156 NdisDprAcquireSpinLock(&Adapter
->Lock
);
1158 /* Check if we have free entry in our circular buffer. */
1159 if ((Adapter
->CurrentTransmitEndIndex
+ 1 ==
1160 Adapter
->CurrentTransmitStartIndex
) ||
1161 (Adapter
->CurrentTransmitEndIndex
== NUMBER_OF_BUFFERS
- 1 &&
1162 Adapter
->CurrentTransmitStartIndex
== 0))
1164 DPRINT1("No free space in circular buffer\n");
1165 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1166 return NDIS_STATUS_RESOURCES
;
1169 Desc
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitEndIndex
;
1171 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, &TotalPacketLength
);
1172 ASSERT(TotalPacketLength
<= BUFFER_SIZE
);
1174 DPRINT("TotalPacketLength: %x\n", TotalPacketLength
);
1178 NdisQueryBuffer(NdisBuffer
, &SourceBuffer
, &SourceLength
);
1180 DPRINT("Buffer: %x Length: %x\n", SourceBuffer
, SourceLength
);
1182 RtlCopyMemory(Adapter
->TransmitBufferPtrVirt
+
1183 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
+ Position
,
1184 SourceBuffer
, SourceLength
);
1186 Position
+= SourceLength
;
1188 NdisGetNextBuffer(NdisBuffer
, &NdisBuffer
);
1193 PUCHAR Ptr
= Adapter
->TransmitBufferPtrVirt
+
1194 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
;
1195 for (Position
= 0; Position
< TotalPacketLength
; Position
++)
1197 if (Position
% 16 == 0)
1199 DbgPrint("%x ", *Ptr
++);
1205 Adapter
->CurrentTransmitEndIndex
++;
1206 Adapter
->CurrentTransmitEndIndex
%= NUMBER_OF_BUFFERS
;
1208 Desc
->FLAGS
= TD1_OWN
| TD1_STP
| TD1_ENP
;
1209 Desc
->BCNT
= 0xf000 | -TotalPacketLength
;
1211 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStartTransmit
, Adapter
);
1213 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1215 return NDIS_STATUS_SUCCESS
;
1220 MiEthernetCrc(UCHAR
*Address
)
1222 * FUNCTION: Calculate Ethernet CRC32
1224 * Address: 6-byte ethernet address
1226 * The calculated CRC32 value.
1229 UINT Counter
, Length
;
1232 for (Length
= 0; Length
< 6; Length
++)
1234 Value
^= *Address
++;
1235 for (Counter
= 0; Counter
< 8; Counter
++)
1238 Value
^= (Value
& 1) * 0xedb88320;
1255 NdisZeroMemory(Adapter
->InitializationBlockVirt
->LADR
, 8);
1256 for (Index
= 0; Index
< AddressCount
; Index
++)
1258 CrcIndex
= MiEthernetCrc(Addresses
) >> 26;
1259 Adapter
->InitializationBlockVirt
->LADR
[CrcIndex
>> 3] |= 1 << (CrcIndex
& 15);
1263 /* FIXME: The specification mentions we need to reload the init block here. */
1265 return NDIS_STATUS_SUCCESS
;
1270 MiGetMediaDuplex(PADAPTER Adapter
)
1274 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR5
);
1275 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1277 return Data
& BCR5_LEDOUT
;
1282 MiGetMediaSpeed(PADAPTER Adapter
)
1286 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR6
);
1287 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1289 return Data
& BCR6_LEDOUT
? 100 : 10;
1294 MiGetMediaState(PADAPTER Adapter
)
1296 * FUNCTION: Determine the link state
1298 * Adapter: Adapter context
1300 * NdisMediaStateConnected if the cable is connected
1301 * NdisMediaStateDisconnected if the cable is disconnected
1305 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
1306 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1307 return Data
& BCR4_LEDOUT
? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
1313 IN PDRIVER_OBJECT DriverObject
,
1314 IN PUNICODE_STRING RegistryPath
)
1316 * FUNCTION: Start this driver
1318 * DriverObject: Pointer to the system-allocated driver object
1319 * RegistryPath: Pointer to our SCM database entry
1321 * NDIS_STATUS_SUCCESS on success
1322 * NDIS_STATUS_FAILURE on failure
1324 * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL
1325 * - TODO: convert this to NTSTATUS return values
1328 NDIS_HANDLE WrapperHandle
;
1329 NDIS_MINIPORT_CHARACTERISTICS Characteristics
;
1332 RtlZeroMemory(&Characteristics
, sizeof(Characteristics
));
1333 Characteristics
.MajorNdisVersion
= NDIS_MINIPORT_MAJOR_VERSION
;
1334 Characteristics
.MinorNdisVersion
= NDIS_MINIPORT_MINOR_VERSION
;
1335 Characteristics
.HaltHandler
= MiniportHalt
;
1336 Characteristics
.HandleInterruptHandler
= MiniportHandleInterrupt
;
1337 Characteristics
.InitializeHandler
= MiniportInitialize
;
1338 Characteristics
.ISRHandler
= MiniportISR
;
1339 Characteristics
.QueryInformationHandler
= MiniportQueryInformation
;
1340 Characteristics
.ResetHandler
= MiniportReset
;
1341 Characteristics
.SetInformationHandler
= MiniportSetInformation
;
1342 Characteristics
.SendHandler
= MiniportSend
;
1344 NdisMInitializeWrapper(&WrapperHandle
, DriverObject
, RegistryPath
, 0);
1345 if (!WrapperHandle
) return NDIS_STATUS_FAILURE
;
1347 Status
= NdisMRegisterMiniport(WrapperHandle
, &Characteristics
, sizeof(Characteristics
));
1348 if(Status
!= NDIS_STATUS_SUCCESS
)
1350 NdisTerminateWrapper(WrapperHandle
, 0);
1351 return NDIS_STATUS_FAILURE
;
1354 return NDIS_STATUS_SUCCESS
;