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 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);
138 NdisMEthIndicateReceiveComplete(Adapter
->MiniportAdapterHandle
);
140 RtlZeroMemory(Descriptor
, sizeof(RECEIVE_DESCRIPTOR
));
142 (ULONG_PTR
)(Adapter
->ReceiveBufferPtrPhys
+ Adapter
->CurrentReceiveDescriptorIndex
* BUFFER_SIZE
);
143 Descriptor
->BCNT
= (-BUFFER_SIZE
) | 0xf000;
144 Descriptor
->FLAGS
|= RD_OWN
;
146 Adapter
->CurrentReceiveDescriptorIndex
++;
147 Adapter
->CurrentReceiveDescriptorIndex
%= NUMBER_OF_BUFFERS
;
149 Adapter
->Statistics
.RcvGoodFrames
++;
154 PTRANSMIT_DESCRIPTOR Descriptor
;
156 DPRINT("transmit interrupt\n");
158 while (Adapter
->CurrentTransmitStartIndex
!=
159 Adapter
->CurrentTransmitEndIndex
)
161 Descriptor
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitStartIndex
;
163 DPRINT("buffer %d flags %x flags2 %x\n",
164 Adapter
->CurrentTransmitStartIndex
,
165 Descriptor
->FLAGS
, Descriptor
->FLAGS2
);
167 if (Descriptor
->FLAGS
& TD1_OWN
)
169 DPRINT("non-TXed buffer\n");
173 if (Descriptor
->FLAGS
& TD1_STP
)
175 if (Descriptor
->FLAGS
& TD1_ONE
)
176 Adapter
->Statistics
.XmtOneRetry
++;
177 else if (Descriptor
->FLAGS
& TD1_MORE
)
178 Adapter
->Statistics
.XmtMoreThanOneRetry
++;
181 if (Descriptor
->FLAGS
& TD1_ERR
)
183 DPRINT("major error: %x\n", Descriptor
->FLAGS2
);
184 if (Descriptor
->FLAGS2
& TD2_RTRY
)
185 Adapter
->Statistics
.XmtRetryErrors
++;
186 if (Descriptor
->FLAGS2
& TD2_LCAR
)
187 Adapter
->Statistics
.XmtLossesOfCarrier
++;
188 if (Descriptor
->FLAGS2
& TD2_LCOL
)
189 Adapter
->Statistics
.XmtLateCollisions
++;
190 if (Descriptor
->FLAGS2
& TD2_EXDEF
)
191 Adapter
->Statistics
.XmtExcessiveDefferals
++;
192 if (Descriptor
->FLAGS2
& TD2_UFLO
)
193 Adapter
->Statistics
.XmtBufferUnderflows
++;
194 if (Descriptor
->FLAGS2
& TD2_BUFF
)
195 Adapter
->Statistics
.XmtBufferErrors
++;
199 Adapter
->CurrentTransmitStartIndex
++;
200 Adapter
->CurrentTransmitStartIndex
%= NUMBER_OF_BUFFERS
;
202 Adapter
->Statistics
.XmtGoodFrames
++;
204 NdisMSendResourcesAvailable(Adapter
->MiniportAdapterHandle
);
206 if(Data
& ~(CSR0_ERR
| CSR0_IDON
| CSR0_RINT
| CSR0_TINT
))
208 DPRINT("UNHANDLED INTERRUPT CSR0 0x%x\n", Data
);
211 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
214 /* re-enable interrupts */
215 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
);
217 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
218 DPRINT("CSR0 is now 0x%x\n", Data
);
220 NdisDprReleaseSpinLock(&Adapter
->Lock
);
227 * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector
229 * MiniportAdapterContext: context supplied to NdisMSetAttributes
231 * NDIS_STATUS_FAILURE on a general error
232 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
233 * NDIS_STATUS_SUCCESS on succes
240 /* Detect the card in the configured slot */
241 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_PCIID
, &buf32
, 4);
244 Status
= NDIS_STATUS_FAILURE
;
245 DPRINT("NdisReadPciSlotInformation failed\n");
252 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
253 DPRINT("card in slot isn't our: 0x%x\n", 0, buf32
);
258 /* set busmaster and io space enable bits */
259 buf32
= PCI_BMEN
| PCI_IOEN
;
260 NdisWritePciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_COMMAND
, &buf32
, 4);
262 /* get IO base physical address */
264 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_IOBAR
, &buf32
, 4);
267 Status
= NDIS_STATUS_FAILURE
;
268 DPRINT("NdisReadPciSlotInformation failed\n");
275 DPRINT("No base i/o address set\n");
276 return NDIS_STATUS_FAILURE
;
279 buf32
&= ~1; /* even up address - comes out odd for some reason */
281 DPRINT("detected io address 0x%x\n", buf32
);
282 Adapter
->IoBaseAddress
= buf32
;
284 /* get interrupt vector */
285 Status
= NdisReadPciSlotInformation(Adapter
->MiniportAdapterHandle
, 0, PCI_ILR
, &buf8
, 1);
288 Status
= NDIS_STATUS_FAILURE
;
289 DPRINT1("NdisReadPciSlotInformation failed\n");
294 DPRINT("interrupt: 0x%x\n", buf8
);
295 Adapter
->InterruptVector
= buf8
;
297 return NDIS_STATUS_SUCCESS
;
301 MiAllocateSharedMemory(
304 * FUNCTION: Allocate all shared memory used by the miniport
306 * Adapter: Pointer to the miniport's adapter object
308 * NDIS_STATUS_RESOURCES on insufficient memory
309 * NDIS_STATUS_SUCCESS on success
312 PTRANSMIT_DESCRIPTOR TransmitDescriptor
;
313 PRECEIVE_DESCRIPTOR ReceiveDescriptor
;
314 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
317 /* allocate the initialization block */
318 Adapter
->InitializationBlockLength
= sizeof(INITIALIZATION_BLOCK
);
319 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
320 FALSE
, (PVOID
*)&Adapter
->InitializationBlockVirt
, &PhysicalAddress
);
321 if(!Adapter
->InitializationBlockVirt
)
323 DPRINT1("insufficient resources\n");
325 return NDIS_STATUS_RESOURCES
;
328 if(((ULONG_PTR
)Adapter
->InitializationBlockVirt
& 0x00000003) != 0)
330 DPRINT("address 0x%x not dword-aligned\n", Adapter
->InitializationBlockVirt
);
332 return NDIS_STATUS_RESOURCES
;
335 Adapter
->InitializationBlockPhys
= (PINITIALIZATION_BLOCK
)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress
);
337 /* allocate the transport descriptor ring */
338 Adapter
->TransmitDescriptorRingLength
= sizeof(TRANSMIT_DESCRIPTOR
) * NUMBER_OF_BUFFERS
;
339 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
340 FALSE
, (PVOID
*)&Adapter
->TransmitDescriptorRingVirt
, &PhysicalAddress
);
341 if(!Adapter
->TransmitDescriptorRingVirt
)
343 DPRINT1("insufficient resources\n");
345 return NDIS_STATUS_RESOURCES
;
348 if(((ULONG_PTR
)Adapter
->TransmitDescriptorRingVirt
& 0x00000003) != 0)
350 DPRINT("address 0x%x not dword-aligned\n", Adapter
->TransmitDescriptorRingVirt
);
352 return NDIS_STATUS_RESOURCES
;
355 Adapter
->TransmitDescriptorRingPhys
= (PTRANSMIT_DESCRIPTOR
)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress
);
356 RtlZeroMemory(Adapter
->TransmitDescriptorRingVirt
, sizeof(TRANSMIT_DESCRIPTOR
) * NUMBER_OF_BUFFERS
);
358 /* allocate the receive descriptor ring */
359 Adapter
->ReceiveDescriptorRingLength
= sizeof(RECEIVE_DESCRIPTOR
) * NUMBER_OF_BUFFERS
;
360 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
361 FALSE
, (PVOID
*)&Adapter
->ReceiveDescriptorRingVirt
, &PhysicalAddress
);
362 if(!Adapter
->ReceiveDescriptorRingVirt
)
364 DPRINT1("insufficient resources\n");
366 return NDIS_STATUS_RESOURCES
;
369 if(((ULONG_PTR
)Adapter
->ReceiveDescriptorRingVirt
& 0x00000003) != 0)
371 DPRINT("address 0x%x not dword-aligned\n", Adapter
->ReceiveDescriptorRingVirt
);
373 return NDIS_STATUS_RESOURCES
;
376 Adapter
->ReceiveDescriptorRingPhys
= (PRECEIVE_DESCRIPTOR
)(ptrdiff_t)NdisGetPhysicalAddressLow(PhysicalAddress
);
377 RtlZeroMemory(Adapter
->ReceiveDescriptorRingVirt
, sizeof(RECEIVE_DESCRIPTOR
) * NUMBER_OF_BUFFERS
);
379 /* allocate transmit buffers */
380 Adapter
->TransmitBufferLength
= BUFFER_SIZE
* NUMBER_OF_BUFFERS
;
381 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
382 FALSE
, (PVOID
*)&Adapter
->TransmitBufferPtrVirt
, &PhysicalAddress
);
383 if(!Adapter
->TransmitBufferPtrVirt
)
385 DPRINT1("insufficient resources\n");
387 return NDIS_STATUS_RESOURCES
;
390 if(((ULONG_PTR
)Adapter
->TransmitBufferPtrVirt
& 0x00000003) != 0)
392 DPRINT("address 0x%x not dword-aligned\n", Adapter
->TransmitBufferPtrVirt
);
394 return NDIS_STATUS_RESOURCES
;
397 Adapter
->TransmitBufferPtrPhys
= (PCHAR
)(ULONG_PTR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
398 RtlZeroMemory(Adapter
->TransmitBufferPtrVirt
, BUFFER_SIZE
* NUMBER_OF_BUFFERS
);
400 /* allocate receive buffers */
401 Adapter
->ReceiveBufferLength
= BUFFER_SIZE
* NUMBER_OF_BUFFERS
;
402 NdisMAllocateSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
403 FALSE
, (PVOID
*)&Adapter
->ReceiveBufferPtrVirt
, &PhysicalAddress
);
404 if(!Adapter
->ReceiveBufferPtrVirt
)
406 DPRINT1("insufficient resources\n");
408 return NDIS_STATUS_RESOURCES
;
411 if(((ULONG_PTR
)Adapter
->ReceiveBufferPtrVirt
& 0x00000003) != 0)
413 DPRINT("address 0x%x not dword-aligned\n", Adapter
->ReceiveBufferPtrVirt
);
415 return NDIS_STATUS_RESOURCES
;
418 Adapter
->ReceiveBufferPtrPhys
= (PCHAR
)(ULONG_PTR
)NdisGetPhysicalAddressLow(PhysicalAddress
);
419 RtlZeroMemory(Adapter
->ReceiveBufferPtrVirt
, BUFFER_SIZE
* NUMBER_OF_BUFFERS
);
421 /* initialize tx descriptors */
422 TransmitDescriptor
= Adapter
->TransmitDescriptorRingVirt
;
423 for(i
= 0; i
< NUMBER_OF_BUFFERS
; i
++)
425 (TransmitDescriptor
+i
)->TBADR
= (ULONG_PTR
)Adapter
->TransmitBufferPtrPhys
+ i
* BUFFER_SIZE
;
426 (TransmitDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
427 (TransmitDescriptor
+i
)->FLAGS
= TD1_STP
| TD1_ENP
;
430 DPRINT("transmit ring initialized\n");
433 ReceiveDescriptor
= Adapter
->ReceiveDescriptorRingVirt
;
434 for(i
= 0; i
< NUMBER_OF_BUFFERS
; i
++)
436 (ReceiveDescriptor
+i
)->RBADR
= (ULONG_PTR
)Adapter
->ReceiveBufferPtrPhys
+ i
* BUFFER_SIZE
;
437 (ReceiveDescriptor
+i
)->BCNT
= 0xf000 | -BUFFER_SIZE
; /* 2's compliment + set top 4 bits */
438 (ReceiveDescriptor
+i
)->FLAGS
= RD_OWN
;
441 DPRINT("receive ring initialized\n");
443 return NDIS_STATUS_SUCCESS
;
447 MiPrepareInitializationBlock(
450 * FUNCTION: Initialize the initialization block
452 * Adapter: pointer to the miniport's adapter object
457 RtlZeroMemory(Adapter
->InitializationBlockVirt
, sizeof(INITIALIZATION_BLOCK
));
459 /* read burned-in address from card */
460 for(i
= 0; i
< 6; i
++)
461 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, Adapter
->InitializationBlockVirt
->PADR
+ i
);
462 DPRINT("MAC address: %02x-%02x-%02x-%02x-%02x-%02x\n",
463 Adapter
->InitializationBlockVirt
->PADR
[0],
464 Adapter
->InitializationBlockVirt
->PADR
[1],
465 Adapter
->InitializationBlockVirt
->PADR
[2],
466 Adapter
->InitializationBlockVirt
->PADR
[3],
467 Adapter
->InitializationBlockVirt
->PADR
[4],
468 Adapter
->InitializationBlockVirt
->PADR
[5]);
470 /* set up receive ring */
471 DPRINT("Receive ring physical address: 0x%x\n", Adapter
->ReceiveDescriptorRingPhys
);
472 Adapter
->InitializationBlockVirt
->RDRA
= (ULONG_PTR
)Adapter
->ReceiveDescriptorRingPhys
;
473 Adapter
->InitializationBlockVirt
->RLEN
= (LOG_NUMBER_OF_BUFFERS
<< 4) & 0xf0;
475 /* set up transmit ring */
476 DPRINT("Transmit ring physical address: 0x%x\n", Adapter
->TransmitDescriptorRingPhys
);
477 Adapter
->InitializationBlockVirt
->TDRA
= (ULONG_PTR
)Adapter
->TransmitDescriptorRingPhys
;
478 Adapter
->InitializationBlockVirt
->TLEN
= (LOG_NUMBER_OF_BUFFERS
<< 4) & 0xf0;
485 * FUNCTION: Free all allocated shared memory
487 * Adapter: pointer to the miniport's adapter struct
490 NDIS_PHYSICAL_ADDRESS PhysicalAddress
;
492 PhysicalAddress
.u
.HighPart
= 0;
494 if(Adapter
->InitializationBlockVirt
)
496 PhysicalAddress
.u
.LowPart
= (ULONG_PTR
)Adapter
->InitializationBlockPhys
;
497 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->InitializationBlockLength
,
498 FALSE
, Adapter
->InitializationBlockVirt
, PhysicalAddress
);
501 if(Adapter
->TransmitDescriptorRingVirt
)
503 PhysicalAddress
.u
.LowPart
= (ULONG_PTR
)Adapter
->TransmitDescriptorRingPhys
;
504 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitDescriptorRingLength
,
505 FALSE
, Adapter
->TransmitDescriptorRingVirt
, PhysicalAddress
);
508 if(Adapter
->ReceiveDescriptorRingVirt
)
510 PhysicalAddress
.u
.LowPart
= (ULONG_PTR
)Adapter
->ReceiveDescriptorRingPhys
;
511 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveDescriptorRingLength
,
512 FALSE
, Adapter
->ReceiveDescriptorRingVirt
, PhysicalAddress
);
515 if(Adapter
->TransmitBufferPtrVirt
)
517 PhysicalAddress
.u
.LowPart
= (ULONG_PTR
)Adapter
->TransmitBufferPtrPhys
;
518 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->TransmitBufferLength
,
519 FALSE
, Adapter
->TransmitBufferPtrVirt
, PhysicalAddress
);
522 if(Adapter
->ReceiveBufferPtrVirt
)
524 PhysicalAddress
.u
.LowPart
= (ULONG_PTR
)Adapter
->ReceiveBufferPtrPhys
;
525 NdisMFreeSharedMemory(Adapter
->MiniportAdapterHandle
, Adapter
->ReceiveBufferLength
,
526 FALSE
, Adapter
->ReceiveBufferPtrVirt
, PhysicalAddress
);
533 IN PVOID SynchronizeContext
)
535 * FUNCTION: Stop the adapter
537 * SynchronizeContext: Adapter context
540 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
541 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
542 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
549 IN NDIS_HANDLE MiniportAdapterContext
)
551 * FUNCTION: Stop the adapter and release any per-adapter resources
553 * MiniportAdapterContext: context specified to NdisMSetAttributes
555 * - Called by NDIS at PASSIVE_LEVEL
558 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
559 BOOLEAN TimerCancelled
;
564 /* stop the media detection timer */
565 NdisMCancelTimer(&Adapter
->MediaDetectionTimer
, &TimerCancelled
);
568 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStop
, Adapter
);
570 /* deregister the interrupt */
571 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
573 /* deregister i/o port range */
574 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
576 /* deregister the shutdown routine */
577 NdisMDeregisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
);
579 /* free shared memory */
580 MiFreeSharedMemory(Adapter
);
582 /* free map registers */
583 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
);
586 NdisFreeSpinLock(&Adapter
->Lock
);
588 /* free the adapter */
589 NdisFreeMemory(Adapter
, 0, 0);
594 MiSyncMediaDetection(
595 IN PVOID SynchronizeContext
)
597 * FUNCTION: Stop the adapter
599 * SynchronizeContext: Adapter context
602 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
603 NDIS_MEDIA_STATE MediaState
= MiGetMediaState(Adapter
);
606 DPRINT("MediaState: %d\n", MediaState
);
607 if (MediaState
!= Adapter
->MediaState
)
609 Adapter
->MediaState
= MediaState
;
617 MiniportMediaDetectionTimer(
618 IN PVOID SystemSpecific1
,
619 IN PVOID FunctionContext
,
620 IN PVOID SystemSpecific2
,
621 IN PVOID SystemSpecific3
)
623 * FUNCTION: Periodially query media state
625 * FunctionContext: Adapter context
627 * - Called by NDIS at DISPATCH_LEVEL
630 PADAPTER Adapter
= (PADAPTER
)FunctionContext
;
632 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
634 if (NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
,
635 MiSyncMediaDetection
,
638 NdisMIndicateStatus(Adapter
->MiniportAdapterHandle
,
639 Adapter
->MediaState
== NdisMediaStateConnected
?
640 NDIS_STATUS_MEDIA_CONNECT
: NDIS_STATUS_MEDIA_DISCONNECT
,
642 NdisMIndicateStatusComplete(Adapter
->MiniportAdapterHandle
);
650 * FUNCTION: Initialize and start the PCNET chip
652 * Adapter: pointer to the miniport's adapter struct
654 * - should be coded to detect failure and return an error
655 * - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that.
663 * first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset
664 * twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the
665 * card is reset by reading from the reset register. on reset it's in 16-bit i/o mode.
667 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET32
, &Data
);
668 NdisRawReadPortUshort(Adapter
->PortOffset
+ RESET16
, &Data
);
671 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
672 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
674 /* pause for 1ms so the chip will have time to reset */
675 NdisStallExecution(1);
677 DPRINT("chip stopped\n");
679 /* set the software style to 2 (32 bits) */
680 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR58
);
681 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
685 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
687 /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */
688 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
689 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
691 Data
|= CSR4_APAD_XMT
| /* CSR4_DPOLL |*/ CSR4_TXSTRTM
| CSR4_DMAPLUS
;
692 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
694 /* set up bcr18: burst read/write enable */
695 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR18
);
696 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
698 Data
|= BCR18_BREADE
| BCR18_BWRITE
;
699 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, Data
);
701 /* set up csr1 and csr2 with init block */
702 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR1
);
703 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG_PTR
)Adapter
->InitializationBlockPhys
& 0xffff));
704 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR2
);
705 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, (USHORT
)((ULONG_PTR
)Adapter
->InitializationBlockPhys
>> 16) & 0xffff);
707 DPRINT("programmed with init block\n");
711 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR15
);
712 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, Data
);
714 /* load init block and start the card */
715 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
716 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STRT
|CSR0_INIT
|CSR0_IENA
);
718 /* detect the media state */
719 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
720 NdisRawWritePortUshort(Adapter
->PortOffset
+ BDP
, BCR4_LNKSTE
|BCR4_FDLSE
);
721 Adapter
->MediaState
= MiGetMediaState(Adapter
);
723 DPRINT("card started\n");
725 Adapter
->Flags
&= ~RESET_IN_PROGRESS
;
733 * FUNCTION: Test the NIC
735 * Adapter: pointer to the miniport's adapter struct
737 * TRUE if the test succeeds
740 * - this is where to add diagnostics. This is called
741 * at the very end of initialization.
748 /* see if we can read/write now */
749 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
750 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
751 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
);
754 for(i
= 0; i
< 6; i
++)
755 NdisRawReadPortUchar(Adapter
->PortOffset
+ i
, &address
[i
]);
757 DPRINT("burned-in address: %x:%x:%x:%x:%x:%x\n", address
[0], address
[1], address
[2], address
[3], address
[4], address
[5]);
758 /* Read status flags from CSR0 */
759 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
760 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
761 DPRINT("CSR0: 0x%x\n", Data
);
763 /* Read status flags from CSR3 */
764 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR3
);
765 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
767 DPRINT("CSR3: 0x%x\n", Data
);
768 /* Read status flags from CSR4 */
769 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR4
);
770 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
771 DPRINT("CSR4: 0x%x\n", Data
);
773 /* Read status flags from CSR5 */
774 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR5
);
775 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
776 DPRINT("CSR5: 0x%x\n", Data
);
778 /* Read status flags from CSR6 */
779 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR6
);
780 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
781 DPRINT("CSR6: 0x%x\n", Data
);
789 MiniportShutdown( PVOID Context
)
791 PADAPTER Adapter
= Context
;
793 DPRINT("Stopping the chip\n");
795 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
796 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_STOP
);
802 OUT PNDIS_STATUS OpenErrorStatus
,
803 OUT PUINT SelectedMediumIndex
,
804 IN PNDIS_MEDIUM MediumArray
,
805 IN UINT MediumArraySize
,
806 IN NDIS_HANDLE MiniportAdapterHandle
,
807 IN NDIS_HANDLE WrapperConfigurationContext
)
809 * FUNCTION: Initialize a new miniport
811 * OpenErrorStatus: pointer to a var to return status info in
812 * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3)
813 * MediumArray: array of media that we can pick from
814 * MediumArraySize: size of MediumArray
815 * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance
816 * WrapperConfigurationContext: temporary NDIS-assigned handle for passing
817 * to configuration APIs
819 * NDIS_STATUS_SUCCESS on success
820 * NDIS_STATUS_FAILURE on general failure
821 * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray
822 * NDIS_STATUS_RESOURCES on insufficient system resources
823 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
825 * - Called by NDIS at PASSIVE_LEVEL, once per detected card
826 * - Will int 3 on failure of MiTestCard if DBG=1
830 PADAPTER Adapter
= 0;
831 NDIS_STATUS Status
= NDIS_STATUS_FAILURE
;
832 BOOLEAN InterruptRegistered
= FALSE
;
834 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
837 for(i
= 0; i
< MediumArraySize
; i
++)
838 if(MediumArray
[i
] == NdisMedium802_3
)
841 if(i
== MediumArraySize
)
843 Status
= NDIS_STATUS_UNSUPPORTED_MEDIA
;
844 DPRINT1("unsupported media\n");
846 *OpenErrorStatus
= Status
;
850 *SelectedMediumIndex
= i
;
852 /* allocate our adapter struct */
853 Status
= NdisAllocateMemoryWithTag((PVOID
*)&Adapter
, sizeof(ADAPTER
), PCNET_TAG
);
854 if(Status
!= NDIS_STATUS_SUCCESS
)
856 Status
= NDIS_STATUS_RESOURCES
;
857 DPRINT1("Insufficient resources\n");
859 *OpenErrorStatus
= Status
;
863 RtlZeroMemory(Adapter
, sizeof(ADAPTER
));
865 Adapter
->MiniportAdapterHandle
= MiniportAdapterHandle
;
867 /* register our adapter structwith ndis */
868 NdisMSetAttributesEx(Adapter
->MiniportAdapterHandle
, Adapter
, 0, NDIS_ATTRIBUTE_BUS_MASTER
, NdisInterfacePci
);
872 /* Card-specific detection and setup */
873 Status
= MiQueryCard(Adapter
);
874 if(Status
!= NDIS_STATUS_SUCCESS
)
876 DPRINT1("MiQueryCard failed\n");
877 Status
= NDIS_STATUS_ADAPTER_NOT_FOUND
;
882 /* register an IO port range */
883 Status
= NdisMRegisterIoPortRange((PVOID
*)&Adapter
->PortOffset
, Adapter
->MiniportAdapterHandle
,
884 (UINT
)Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
);
885 if(Status
!= NDIS_STATUS_SUCCESS
)
887 DPRINT1("NdisMRegisterIoPortRange failed: 0x%x\n", Status
);
892 /* Allocate map registers */
893 Status
= NdisMAllocateMapRegisters(Adapter
->MiniportAdapterHandle
, 0,
894 NDIS_DMA_32BITS
, 8, BUFFER_SIZE
);
895 if(Status
!= NDIS_STATUS_SUCCESS
)
897 DPRINT1("NdisMAllocateMapRegisters failed: 0x%x\n", Status
);
902 /* set up the interrupt */
903 Status
= NdisMRegisterInterrupt(&Adapter
->InterruptObject
, Adapter
->MiniportAdapterHandle
, Adapter
->InterruptVector
,
904 Adapter
->InterruptVector
, TRUE
, TRUE
, NdisInterruptLevelSensitive
);
905 if(Status
!= NDIS_STATUS_SUCCESS
)
907 DPRINT("NdisMRegisterInterrupt failed: 0x%x\n", Status
);
912 InterruptRegistered
= TRUE
;
914 /* Allocate and initialize shared data structures */
915 Status
= MiAllocateSharedMemory(Adapter
);
916 if(Status
!= NDIS_STATUS_SUCCESS
)
918 Status
= NDIS_STATUS_RESOURCES
;
919 DPRINT("MiAllocateSharedMemory failed", Status
);
924 /* set up the initialization block */
925 MiPrepareInitializationBlock(Adapter
);
927 DPRINT("Interrupt registered successfully\n");
929 /* Initialize and start the chip */
932 NdisAllocateSpinLock(&Adapter
->Lock
);
934 Status
= NDIS_STATUS_SUCCESS
;
938 if(Status
!= NDIS_STATUS_SUCCESS
&& Adapter
)
940 DPRINT("Error; freeing stuff\n");
942 NdisMFreeMapRegisters(Adapter
->MiniportAdapterHandle
); /* doesn't hurt to free if we never alloc'd? */
944 if(Adapter
->PortOffset
)
945 NdisMDeregisterIoPortRange(Adapter
->MiniportAdapterHandle
, Adapter
->IoBaseAddress
, NUMBER_OF_PORTS
, (PVOID
)Adapter
->PortOffset
);
947 if(InterruptRegistered
)
948 NdisMDeregisterInterrupt(&Adapter
->InterruptObject
);
950 MiFreeSharedMemory(Adapter
);
952 NdisFreeMemory(Adapter
, 0, 0);
955 if(Status
== NDIS_STATUS_SUCCESS
)
957 NdisMInitializeTimer(&Adapter
->MediaDetectionTimer
,
958 Adapter
->MiniportAdapterHandle
,
959 MiniportMediaDetectionTimer
,
961 NdisMSetPeriodicTimer(&Adapter
->MediaDetectionTimer
,
962 MEDIA_DETECTION_INTERVAL
);
966 if(!MiTestCard(Adapter
))
970 NdisMRegisterAdapterShutdownHandler(Adapter
->MiniportAdapterHandle
, Adapter
, MiniportShutdown
);
972 DPRINT("returning 0x%x\n", Status
);
973 *OpenErrorStatus
= Status
;
980 OUT PBOOLEAN InterruptRecognized
,
981 OUT PBOOLEAN QueueMiniportHandleInterrupt
,
982 IN NDIS_HANDLE MiniportAdapterContext
)
984 * FUNCTION: Miniport interrupt service routine
986 * InterruptRecognized: the interrupt was ours
987 * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt
988 * MiniportAdapterContext: the context originally passed to NdisMSetAttributes
990 * - called by NDIS at DIRQL
991 * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt
997 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1001 /* save the old RAP value */
1002 NdisRawReadPortUshort(Adapter
->PortOffset
+ RAP
, &Rap
);
1005 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1006 NdisRawReadPortUshort(Adapter
->PortOffset
+ RDP
, &Data
);
1008 if(!(Data
& CSR0_INTR
))
1010 DPRINT("not our interrupt.\n");
1011 *InterruptRecognized
= FALSE
;
1012 *QueueMiniportHandleInterrupt
= FALSE
;
1016 DPRINT("detected our interrupt\n");
1018 /* disable interrupts */
1019 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1020 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, 0);
1022 *InterruptRecognized
= TRUE
;
1023 *QueueMiniportHandleInterrupt
= TRUE
;
1026 /* restore the rap */
1027 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, Rap
);
1033 OUT PBOOLEAN AddressingReset
,
1034 IN NDIS_HANDLE MiniportAdapterContext
)
1036 * FUNCTION: Reset the miniport
1038 * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation
1039 * to reset our addresses and filters
1040 * MiniportAdapterContext: context originally passed to NdisMSetAttributes
1042 * NDIS_STATUS_SUCCESS on all requests
1044 * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset
1049 ASSERT_IRQL_EQUAL(PASSIVE_LEVEL
);
1051 /* MiniportReset doesn't do anything at the moment... perhaps this should be fixed. */
1053 *AddressingReset
= FALSE
;
1054 return NDIS_STATUS_SUCCESS
;
1059 MiSyncStartTransmit(
1060 IN PVOID SynchronizeContext
)
1062 * FUNCTION: Stop the adapter
1064 * SynchronizeContext: Adapter context
1067 PADAPTER Adapter
= (PADAPTER
)SynchronizeContext
;
1068 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, CSR0
);
1069 NdisRawWritePortUshort(Adapter
->PortOffset
+ RDP
, CSR0_IENA
| CSR0_TDMD
);
1076 IN NDIS_HANDLE MiniportAdapterContext
,
1077 IN PNDIS_PACKET Packet
,
1080 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out
1082 * MiniportAdapterContext: context originally input to NdisMSetAttributes
1083 * Packet: The NDIS_PACKET to be sent
1084 * Flags: Flags associated with Packet
1086 * NDIS_STATUS_SUCCESS on processed requests
1087 * NDIS_STATUS_RESOURCES if there's no place in buffer ring
1089 * - Called by NDIS at DISPATCH_LEVEL
1092 PADAPTER Adapter
= (PADAPTER
)MiniportAdapterContext
;
1093 PTRANSMIT_DESCRIPTOR Desc
;
1094 PNDIS_BUFFER NdisBuffer
;
1096 UINT TotalPacketLength
, SourceLength
, Position
= 0;
1100 ASSERT_IRQL_EQUAL(DISPATCH_LEVEL
);
1102 NdisDprAcquireSpinLock(&Adapter
->Lock
);
1104 /* Check if we have free entry in our circular buffer. */
1105 if ((Adapter
->CurrentTransmitEndIndex
+ 1 ==
1106 Adapter
->CurrentTransmitStartIndex
) ||
1107 (Adapter
->CurrentTransmitEndIndex
== NUMBER_OF_BUFFERS
- 1 &&
1108 Adapter
->CurrentTransmitStartIndex
== 0))
1110 DPRINT1("No free space in circular buffer\n");
1111 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1112 return NDIS_STATUS_RESOURCES
;
1115 Desc
= Adapter
->TransmitDescriptorRingVirt
+ Adapter
->CurrentTransmitEndIndex
;
1117 NdisQueryPacket(Packet
, NULL
, NULL
, &NdisBuffer
, &TotalPacketLength
);
1118 ASSERT(TotalPacketLength
<= BUFFER_SIZE
);
1120 DPRINT("TotalPacketLength: %x\n", TotalPacketLength
);
1124 NdisQueryBuffer(NdisBuffer
, &SourceBuffer
, &SourceLength
);
1126 DPRINT("Buffer: %x Length: %x\n", SourceBuffer
, SourceLength
);
1128 RtlCopyMemory(Adapter
->TransmitBufferPtrVirt
+
1129 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
+ Position
,
1130 SourceBuffer
, SourceLength
);
1132 Position
+= SourceLength
;
1134 NdisGetNextBuffer(NdisBuffer
, &NdisBuffer
);
1139 PUCHAR Ptr
= Adapter
->TransmitBufferPtrVirt
+
1140 Adapter
->CurrentTransmitEndIndex
* BUFFER_SIZE
;
1141 for (Position
= 0; Position
< TotalPacketLength
; Position
++)
1143 if (Position
% 16 == 0)
1145 DbgPrint("%x ", *Ptr
++);
1151 Adapter
->CurrentTransmitEndIndex
++;
1152 Adapter
->CurrentTransmitEndIndex
%= NUMBER_OF_BUFFERS
;
1154 Desc
->FLAGS
= TD1_OWN
| TD1_STP
| TD1_ENP
;
1155 Desc
->BCNT
= 0xf000 | -TotalPacketLength
;
1157 NdisMSynchronizeWithInterrupt(&Adapter
->InterruptObject
, MiSyncStartTransmit
, Adapter
);
1159 NdisDprReleaseSpinLock(&Adapter
->Lock
);
1161 return NDIS_STATUS_SUCCESS
;
1166 MiEthernetCrc(UCHAR
*Address
)
1168 * FUNCTION: Calculate Ethernet CRC32
1170 * Address: 6-byte ethernet address
1172 * The calculated CRC32 value.
1175 UINT Counter
, Length
;
1178 for (Length
= 0; Length
< 6; Length
++)
1180 Value
^= *Address
++;
1181 for (Counter
= 0; Counter
< 8; Counter
++)
1184 Value
^= (Value
& 1) * 0xedb88320;
1201 NdisZeroMemory(Adapter
->InitializationBlockVirt
->LADR
, 8);
1202 for (Index
= 0; Index
< AddressCount
; Index
++)
1204 CrcIndex
= MiEthernetCrc(Addresses
) >> 26;
1205 Adapter
->InitializationBlockVirt
->LADR
[CrcIndex
>> 3] |= 1 << (CrcIndex
& 15);
1209 /* FIXME: The specification mentions we need to reload the init block here. */
1211 return NDIS_STATUS_SUCCESS
;
1216 MiGetMediaState(PADAPTER Adapter
)
1218 * FUNCTION: Determine the link state
1220 * Adapter: Adapter context
1222 * NdisMediaStateConnected if the cable is connected
1223 * NdisMediaStateDisconnected if the cable is disconnected
1227 NdisRawWritePortUshort(Adapter
->PortOffset
+ RAP
, BCR4
);
1228 NdisRawReadPortUshort(Adapter
->PortOffset
+ BDP
, &Data
);
1229 return Data
& BCR4_LEDOUT
? NdisMediaStateConnected
: NdisMediaStateDisconnected
;
1235 IN PDRIVER_OBJECT DriverObject
,
1236 IN PUNICODE_STRING RegistryPath
)
1238 * FUNCTION: Start this driver
1240 * DriverObject: Pointer to the system-allocated driver object
1241 * RegistryPath: Pointer to our SCM database entry
1243 * NDIS_STATUS_SUCCESS on success
1244 * NDIS_STATUS_FAILURE on failure
1246 * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL
1247 * - TODO: convert this to NTSTATUS return values
1250 NDIS_HANDLE WrapperHandle
;
1251 NDIS_MINIPORT_CHARACTERISTICS Characteristics
;
1254 RtlZeroMemory(&Characteristics
, sizeof(Characteristics
));
1255 Characteristics
.MajorNdisVersion
= NDIS_MINIPORT_MAJOR_VERSION
;
1256 Characteristics
.MinorNdisVersion
= NDIS_MINIPORT_MINOR_VERSION
;
1257 Characteristics
.HaltHandler
= MiniportHalt
;
1258 Characteristics
.HandleInterruptHandler
= MiniportHandleInterrupt
;
1259 Characteristics
.InitializeHandler
= MiniportInitialize
;
1260 Characteristics
.ISRHandler
= MiniportISR
;
1261 Characteristics
.QueryInformationHandler
= MiniportQueryInformation
;
1262 Characteristics
.ResetHandler
= MiniportReset
;
1263 Characteristics
.SetInformationHandler
= MiniportSetInformation
;
1264 Characteristics
.SendHandler
= MiniportSend
;
1266 NdisMInitializeWrapper(&WrapperHandle
, DriverObject
, RegistryPath
, 0);
1268 Status
= NdisMRegisterMiniport(WrapperHandle
, &Characteristics
, sizeof(Characteristics
));
1269 if(Status
!= NDIS_STATUS_SUCCESS
)
1271 NdisTerminateWrapper(WrapperHandle
, 0);
1272 return NDIS_STATUS_FAILURE
;
1275 return NDIS_STATUS_SUCCESS
;