2 * ReactOS AMD PCNet Driver
3 * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 * PROJECT: ReactOS AMD PCNet Driver
20 * FILE: drivers/net/dd/pcnet/pcnet.c
21 * PURPOSE: PCNet Device Driver
22 * PROGRAMMER: Vizzini (vizzini@plasmic.com)
24 * 9-Sept-2003 vizzini - Created
26 * - this is hard-coded to NDIS4
27 * - this assumes a little-endian machine
28 * - this assumes a 32-bit machine
29 * - this doesn't handle multiple PCNET NICs yet
30 * - this driver includes both NdisRaw and NdisImmediate calls
31 * for NDIS testing purposes. Pick your poison below.
42 IN NDIS_HANDLE MiniportAdapterContext)
44 * FUNCTION: Stop the miniport and prepare for unload
46 * MiniportAdapterContext: context specified to NdisMSetAttributes
48 * - Called by NDIS at PASSIVE_LEVEL
51 /* XXX Implement me */
52 PCNET_DbgPrint(("Called\n"));
58 MiniportHandleInterrupt(
59 IN NDIS_HANDLE MiniportAdapterContext)
61 * FUNCTION: Handle an interrupt if told to by MiniportISR
63 * MiniportAdapterContext: context specified to NdisMSetAttributes
65 * - Called by NDIS at DISPATCH_LEVEL
68 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
70 BOOLEAN ErrorHandled = FALSE;
71 BOOLEAN ReceiveHandled = FALSE;
72 BOOLEAN IdonHandled = FALSE;
75 PCNET_DbgPrint(("Called\n"));
77 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
78 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
80 PCNET_DbgPrint(("CSR0 is 0x%x\n", Data));
82 while(Data & CSR0_INTR)
88 PCNET_DbgPrint(("ERROR HANDLED TWO TIMES\n"));
94 PCNET_DbgPrint(("clearing an error\n"));
95 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_MERR|CSR0_BABL|CSR0_CERR|CSR0_MISS);
96 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Temp);
97 PCNET_DbgPrint(("CSR0 is now 0x%x\n", Temp));
99 else if(Data & CSR0_IDON)
103 PCNET_DbgPrint(("IDON HANDLED TWO TIMES\n"));
109 PCNET_DbgPrint(("clearing IDON\n"));
110 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IDON);
111 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Temp);
112 PCNET_DbgPrint(("CSR0 is now 0x%x\n", Temp));
114 else if(Data & CSR0_RINT)
118 PCNET_DbgPrint(("RECEIVE HANDLED TWO TIMES\n"));
122 ReceiveHandled = TRUE;
124 PCNET_DbgPrint(("receive interrupt - clearing\n"));
125 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_RINT);
126 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Temp);
127 PCNET_DbgPrint(("CSR0 is now 0x%x\n", Temp));
131 PRECEIVE_DESCRIPTOR Descriptor = Adapter->ReceiveDescriptorRingVirt + Adapter->CurrentReceiveDescriptorIndex;
135 if(Descriptor->FLAGS & RD_OWN)
137 PCNET_DbgPrint(("no more receive descriptors to process\n"));
141 if(Descriptor->FLAGS & RD_ERR)
143 PCNET_DbgPrint(("receive descriptor error: 0x%x\n", Descriptor->FLAGS));
147 if(!((Descriptor->FLAGS & RD_STP) && (Descriptor->FLAGS & RD_ENP)))
149 PCNET_DbgPrint(("receive descriptor not start&end: 0x%x\n", Descriptor->FLAGS));
153 Buffer = Adapter->ReceiveBufferPtrVirt + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE;
154 ByteCount = Descriptor->MCNT & 0xfff;
156 PCNET_DbgPrint(("Indicating a %d-byte packet (index %d)\n", ByteCount, Adapter->CurrentReceiveDescriptorIndex));
158 NdisMEthIndicateReceive(Adapter->MiniportAdapterHandle, 0, Buffer, 14, Buffer+14, ByteCount-14, ByteCount-14);
160 memset(Descriptor, 0, sizeof(RECEIVE_DESCRIPTOR));
162 (ULONG)(Adapter->ReceiveBufferPtrPhys + Adapter->CurrentReceiveDescriptorIndex * BUFFER_SIZE);
163 Descriptor->BCNT = (-BUFFER_SIZE) | 0xf000;
164 Descriptor->FLAGS &= RD_OWN;
166 Adapter->CurrentReceiveDescriptorIndex++;
168 if(Adapter->CurrentReceiveDescriptorIndex == NUMBER_OF_BUFFERS)
169 Adapter->CurrentReceiveDescriptorIndex = 0;
174 PCNET_DbgPrint(("UNHANDLED INTERRUPT\n"));
178 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
181 /* re-enable interrupts */
182 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_IENA);
184 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
185 PCNET_DbgPrint(("CSR0 is now 0x%x\n", Data));
193 * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector
195 * MiniportAdapterContext: context supplied to NdisMSetAttributes
197 * NDIS_STATUS_FAILURE on a general error
198 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
199 * NDIS_STATUS_SUCCESS on succes
206 /* Detect the card in the configured slot */
207 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_PCIID, &buf32, 4);
210 Status = NDIS_STATUS_FAILURE;
211 PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n"));
218 Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
219 PCNET_DbgPrint(("card in slot 0x%x isn't us: 0x%x\n", Adapter->SlotNumber, buf32));
224 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber,
225 PCI_COMMAND, &buf32, 4);
228 PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n"));
230 return NDIS_STATUS_FAILURE;
233 PCNET_DbgPrint(("config/status register: 0x%x\n", buf32));
237 PCNET_DbgPrint(("io space access is enabled.\n"));
241 PCNET_DbgPrint(("io space is NOT enabled!\n"));
243 return NDIS_STATUS_FAILURE;
246 /* get IO base physical address */
248 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_IOBAR, &buf32, 4);
251 Status = NDIS_STATUS_FAILURE;
252 PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n"));
259 PCNET_DbgPrint(("No base i/o address set\n"));
260 return NDIS_STATUS_FAILURE;
263 buf32 &= ~1; /* even up address - comes out odd for some reason */
265 PCNET_DbgPrint(("detected io address 0x%x\n", buf32));
266 Adapter->IoBaseAddress = buf32;
268 /* get interrupt vector */
269 Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_ILR, &buf8, 1);
272 Status = NDIS_STATUS_FAILURE;
273 PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n"));
278 PCNET_DbgPrint(("interrupt: 0x%x\n", buf8));
279 Adapter->InterruptVector = buf8;
281 return NDIS_STATUS_SUCCESS;
288 NDIS_HANDLE WrapperConfigurationContext)
290 * FUNCTION: Get configuration parameters from the registry
292 * Adapter: pointer to the Adapter struct for this NIC
293 * WrapperConfigurationContext: Context passed into MiniportInitialize
295 * NDIS_STATUS_SUCCESS on success
296 * NDIS_STATUS_{something} on failure (return val from other Ndis calls)
299 PNDIS_CONFIGURATION_PARAMETER Parameter;
300 NDIS_HANDLE ConfigurationHandle = 0;
301 UNICODE_STRING Keyword;
304 NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext);
305 if(Status != NDIS_STATUS_SUCCESS)
307 PCNET_DbgPrint(("Unable to open configuration: 0x%x\n", Status));
312 RtlInitUnicodeString(&Keyword, L"SlotNumber");
313 NdisReadConfiguration(&Status, &Parameter, ConfigurationHandle, &Keyword, NdisParameterInteger);
314 if(Status != NDIS_STATUS_SUCCESS)
316 PCNET_DbgPrint(("Unable to read slot number: 0x%x\n", Status));
320 Adapter->SlotNumber = Parameter->ParameterData.IntegerData;
322 NdisCloseConfiguration(ConfigurationHandle);
324 return NDIS_STATUS_SUCCESS;
329 MiAllocateSharedMemory(
332 * FUNCTION: Allocate all shared memory used by the miniport
334 * Adapter: Pointer to the miniport's adapter object
336 * NDIS_STATUS_RESOURCES on insufficient memory
337 * NDIS_STATUS_SUCCESS on success
340 PTRANSMIT_DESCRIPTOR TransmitDescriptor;
341 PRECEIVE_DESCRIPTOR ReceiveDescriptor;
342 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
345 /* allocate the initialization block */
346 Adapter->InitializationBlockLength = sizeof(INITIALIZATION_BLOCK);
347 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength,
348 FALSE, (PVOID *)&Adapter->InitializationBlockVirt, &PhysicalAddress);
349 if(!Adapter->InitializationBlockVirt)
351 PCNET_DbgPrint(("insufficient resources\n"));
353 return NDIS_STATUS_RESOURCES;
356 if(((ULONG)Adapter->InitializationBlockVirt & 0x00000003) != 0)
358 PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->InitializationBlockVirt));
360 return NDIS_STATUS_RESOURCES;
363 Adapter->InitializationBlockPhys = (PINITIALIZATION_BLOCK)NdisGetPhysicalAddressLow(PhysicalAddress);
364 memset(Adapter->InitializationBlockVirt, 0, sizeof(INITIALIZATION_BLOCK));
366 /* allocate the transport descriptor ring */
367 Adapter->TransmitDescriptorRingLength = sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS;
368 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength,
369 FALSE, (PVOID *)&Adapter->TransmitDescriptorRingVirt, &PhysicalAddress);
370 if(!Adapter->TransmitDescriptorRingVirt)
372 PCNET_DbgPrint(("insufficient resources\n"));
374 return NDIS_STATUS_RESOURCES;
377 if(((ULONG)Adapter->TransmitDescriptorRingVirt & 0x00000003) != 0)
379 PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->TransmitDescriptorRingVirt));
381 return NDIS_STATUS_RESOURCES;
384 Adapter->TransmitDescriptorRingPhys = (PTRANSMIT_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress);
385 memset(Adapter->TransmitDescriptorRingVirt, 0, sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS);
387 /* allocate the receive descriptor ring */
388 Adapter->ReceiveDescriptorRingLength = sizeof(RECEIVE_DESCRIPTOR) * NUMBER_OF_BUFFERS;
389 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength,
390 FALSE, (PVOID *)&Adapter->ReceiveDescriptorRingVirt, &PhysicalAddress);
391 if(!Adapter->ReceiveDescriptorRingVirt)
393 PCNET_DbgPrint(("insufficient resources\n"));
395 return NDIS_STATUS_RESOURCES;
398 if(((ULONG)Adapter->ReceiveDescriptorRingVirt & 0x00000003) != 0)
400 PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->ReceiveDescriptorRingVirt));
402 return NDIS_STATUS_RESOURCES;
405 Adapter->ReceiveDescriptorRingPhys = (PRECEIVE_DESCRIPTOR)NdisGetPhysicalAddressLow(PhysicalAddress);
406 memset(Adapter->ReceiveDescriptorRingVirt, 0, sizeof(RECEIVE_DESCRIPTOR) * NUMBER_OF_BUFFERS);
408 /* allocate transmit buffers */
409 Adapter->TransmitBufferLength = BUFFER_SIZE * NUMBER_OF_BUFFERS;
410 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength,
411 FALSE, (PVOID *)&Adapter->TransmitBufferPtrVirt, &PhysicalAddress);
412 if(!Adapter->TransmitBufferPtrVirt)
414 PCNET_DbgPrint(("insufficient resources\n"));
416 return NDIS_STATUS_RESOURCES;
419 if(((ULONG)Adapter->TransmitBufferPtrVirt & 0x00000003) != 0)
421 PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->TransmitBufferPtrVirt));
423 return NDIS_STATUS_RESOURCES;
426 Adapter->TransmitBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress);
427 memset(Adapter->TransmitBufferPtrVirt, 0, BUFFER_SIZE * NUMBER_OF_BUFFERS);
429 /* allocate receive buffers */
430 Adapter->ReceiveBufferLength = BUFFER_SIZE * NUMBER_OF_BUFFERS;
431 NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength,
432 FALSE, (PVOID *)&Adapter->ReceiveBufferPtrVirt, &PhysicalAddress);
433 if(!Adapter->ReceiveBufferPtrVirt)
435 PCNET_DbgPrint(("insufficient resources\n"));
437 return NDIS_STATUS_RESOURCES;
440 if(((ULONG)Adapter->ReceiveBufferPtrVirt & 0x00000003) != 0)
442 PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->ReceiveBufferPtrVirt));
444 return NDIS_STATUS_RESOURCES;
447 Adapter->ReceiveBufferPtrPhys = (PCHAR)NdisGetPhysicalAddressLow(PhysicalAddress);
448 memset(Adapter->ReceiveBufferPtrVirt, 0, BUFFER_SIZE * NUMBER_OF_BUFFERS);
450 /* initialize tx descriptors */
451 TransmitDescriptor = Adapter->TransmitDescriptorRingVirt;
452 for(i = 0; i < NUMBER_OF_BUFFERS; i++)
454 (TransmitDescriptor+i)->TBADR = (ULONG)Adapter->TransmitBufferPtrPhys + i * BUFFER_SIZE;
455 (TransmitDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */
456 (TransmitDescriptor+i)->FLAGS = TD1_STP | TD1_ENP;
459 PCNET_DbgPrint(("transmit ring initialized\n"));
462 ReceiveDescriptor = Adapter->ReceiveDescriptorRingVirt;
463 for(i = 0; i < NUMBER_OF_BUFFERS; i++)
465 (ReceiveDescriptor+i)->RBADR = (ULONG)Adapter->ReceiveBufferPtrPhys + i * BUFFER_SIZE;
466 (ReceiveDescriptor+i)->BCNT = 0xf0000 | -BUFFER_SIZE; /* 2's compliment + set top 4 bits */
467 (ReceiveDescriptor+i)->FLAGS |= RD_OWN;
470 PCNET_DbgPrint(("receive ring initialized\n"));
472 return NDIS_STATUS_SUCCESS;
477 MiPrepareInitializationBlock(
480 * FUNCTION: Initialize the initialization block
482 * Adapter: pointer to the miniport's adapter object
487 /* read burned-in address from card */
488 for(i = 0; i < 6; i++)
489 NdisRawReadPortUchar(Adapter->PortOffset + i, Adapter->InitializationBlockVirt->PADR + i);
491 /* set up receive ring */
492 PCNET_DbgPrint(("Receive ring physical address: 0x%x\n", Adapter->ReceiveDescriptorRingPhys));
493 Adapter->InitializationBlockVirt->RDRA = (ULONG)Adapter->ReceiveDescriptorRingPhys;
494 Adapter->InitializationBlockVirt->RLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
496 /* set up transmit ring */
497 PCNET_DbgPrint(("Transmit ring physical address: 0x%x\n", Adapter->TransmitDescriptorRingPhys));
498 Adapter->InitializationBlockVirt->TDRA = (ULONG)Adapter->TransmitDescriptorRingPhys;
499 Adapter->InitializationBlockVirt->TLEN = (LOG_NUMBER_OF_BUFFERS << 4) & 0xf0;
507 * FUNCTION: Free all allocated shared memory
509 * Adapter: pointer to the miniport's adapter struct
512 NDIS_PHYSICAL_ADDRESS PhysicalAddress;
514 PhysicalAddress.u.HighPart = 0;
516 if(Adapter->InitializationBlockVirt)
518 PhysicalAddress.u.LowPart = (ULONG)Adapter->InitializationBlockPhys;
519 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength,
520 FALSE, (PVOID *)&Adapter->InitializationBlockVirt, PhysicalAddress);
523 if(Adapter->TransmitDescriptorRingVirt)
525 PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitDescriptorRingPhys;
526 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength,
527 FALSE, (PVOID *)&Adapter->TransmitDescriptorRingVirt, PhysicalAddress);
530 if(Adapter->ReceiveDescriptorRingVirt)
532 PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveDescriptorRingPhys;
533 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength,
534 FALSE, (PVOID *)&Adapter->ReceiveDescriptorRingVirt, PhysicalAddress);
537 if(Adapter->TransmitBufferPtrVirt)
539 PhysicalAddress.u.LowPart = (ULONG)Adapter->TransmitBufferPtrPhys;
540 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength,
541 FALSE, (PVOID *)&Adapter->TransmitBufferPtrVirt, PhysicalAddress);
544 if(Adapter->ReceiveBufferPtrVirt)
546 PhysicalAddress.u.LowPart = (ULONG)Adapter->ReceiveBufferPtrPhys;
547 NdisMFreeSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength,
548 FALSE, (PVOID *)&Adapter->ReceiveBufferPtrVirt, PhysicalAddress);
557 * FUNCTION: Initialize and start the PCNET chip
559 * Adapter: pointer to the miniport's adapter struct
561 * - should be coded to detect failure and return an error
562 * - the vmware virtual lance chip doesn't support 32-bit i/o so don't do that.
567 PCNET_DbgPrint(("Called\n"));
570 * first reset the chip - 32-bit reset followed by 16-bit reset. if it's in 32-bit mode, it'll reset
571 * twice. if it's in 16-bit mode, the first read will be nonsense and the second will be a reset. the
572 * card is reset by reading from the reset register. on reset it's in 16-bit i/o mode.
574 NdisRawReadPortUshort(Adapter->PortOffset + RESET32, &Data);
575 NdisRawReadPortUshort(Adapter->PortOffset + RESET16, &Data);
578 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
579 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STOP);
581 /* pause for 1ms so the chip will have time to reset */
582 NdisStallExecution(1);
584 PCNET_DbgPrint(("chip stopped\n"));
586 /* set the software style to 2 (32 bits) */
587 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR58);
588 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
592 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
594 /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */
595 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4);
596 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
598 Data |= CSR4_APAD_XMT | /* CSR4_DPOLL |*/ CSR4_TXSTRTM | CSR4_DMAPLUS;
599 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
601 /* set up bcr18: burst read/write enable */
602 NdisRawWritePortUshort(Adapter->PortOffset + RAP, BCR18);
603 NdisRawReadPortUshort(Adapter->PortOffset + BDP, &Data);
605 Data |= BCR18_BREADE | BCR18_BWRITE ;
606 NdisRawWritePortUshort(Adapter->PortOffset + BDP, Data);
608 /* set up csr1 and csr2 with init block */
609 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR1);
610 NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys & 0xffff));
611 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR2);
612 NdisRawWritePortUshort(Adapter->PortOffset + RDP, (USHORT)((ULONG)Adapter->InitializationBlockPhys >> 16) & 0xffff);
614 PCNET_DbgPrint(("programmed with init block\n"));
618 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR15);
619 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
621 /* load init block and start the card */
622 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
623 NdisRawWritePortUshort(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA);
625 PCNET_DbgPrint(("card started\n"));
627 Adapter->Flags &= ~RESET_IN_PROGRESS;
635 * FUNCTION: Test the NIC
637 * Adapter: pointer to the miniport's adapter struct
639 * TRUE if the test succeeds
642 * - this is where to add diagnostics. This is called
643 * at the very end of initialization.
650 /* see if we can read/write now */
651 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
652 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
653 PCNET_DbgPrint(("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));
656 for(i = 0; i < 6; i++)
657 NdisRawReadPortUchar(Adapter->PortOffset + i, &address[i]);
659 PCNET_DbgPrint(("burned-in address: %x:%x:%x:%x:%x:%x\n", address[0], address[1], address[2], address[3], address[4], address[5]));
660 /* Read status flags from CSR0 */
661 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
662 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
663 PCNET_DbgPrint(("CSR0: 0x%x\n", Data));
665 /* Read status flags from CSR3 */
666 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR3);
667 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
669 PCNET_DbgPrint(("CSR3: 0x%x\n", Data));
670 /* Read status flags from CSR4 */
671 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4);
672 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
673 PCNET_DbgPrint(("CSR4: 0x%x\n", Data));
675 /* Read status flags from CSR5 */
676 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR5);
677 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
678 PCNET_DbgPrint(("CSR5: 0x%x\n", Data));
680 /* Read status flags from CSR6 */
681 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR6);
682 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
683 PCNET_DbgPrint(("CSR6: 0x%x\n", Data));
685 /* finally, fire a test interrupt to test the ISR */
686 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR4);
687 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
688 Data |= CSR4_UINTCMD;
689 NdisRawWritePortUshort(Adapter->PortOffset + RDP, Data);
690 PCNET_DbgPrint(("just wrote 0x%x to CSR4 for test interrupt\n", Data));
699 OUT PNDIS_STATUS OpenErrorStatus,
700 OUT PUINT SelectedMediumIndex,
701 IN PNDIS_MEDIUM MediumArray,
702 IN UINT MediumArraySize,
703 IN NDIS_HANDLE MiniportAdapterHandle,
704 IN NDIS_HANDLE WrapperConfigurationContext)
706 * FUNCTION: Initialize a new miniport
708 * OpenErrorStatus: pointer to a var to return status info in
709 * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3)
710 * MediumArray: array of media that we can pick from
711 * MediumArraySize: size of MediumArray
712 * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance
713 * WrapperConfigurationContext: temporary NDIS-assigned handle for passing
714 * to configuration APIs
716 * NDIS_STATUS_SUCCESS on success
717 * NDIS_STATUS_FAILURE on general failure
718 * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray
719 * NDIS_STATUS_RESOURCES on insufficient system resources
720 * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter
722 * - Called by NDIS at PASSIVE_LEVEL, once per detected card
723 * - Will int 3 on failure of MiTestCard if DBG=1
727 PADAPTER Adapter = 0;
728 NDIS_STATUS Status = NDIS_STATUS_FAILURE;
729 BOOLEAN InterruptRegistered = FALSE;
732 for(i = 0; i < MediumArraySize; i++)
733 if(MediumArray[i] == NdisMedium802_3)
736 if(i == MediumArraySize)
738 Status = NDIS_STATUS_UNSUPPORTED_MEDIA;
739 PCNET_DbgPrint(("unsupported media\n"));
741 *OpenErrorStatus = Status;
745 *SelectedMediumIndex = i;
747 /* allocate our adapter struct */
748 Status = NdisAllocateMemoryWithTag((PVOID *)&Adapter, sizeof(ADAPTER), PCNET_TAG);
749 if(Status != NDIS_STATUS_SUCCESS)
751 Status = NDIS_STATUS_RESOURCES;
752 PCNET_DbgPrint(("Insufficient resources\n"));
754 *OpenErrorStatus = Status;
758 memset(Adapter,0,sizeof(ADAPTER));
760 Adapter->MiniportAdapterHandle = MiniportAdapterHandle;
762 /* register our adapter structwith ndis */
763 NdisMSetAttributesEx(Adapter->MiniportAdapterHandle, Adapter, 0, NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci);
767 /* get registry config */
768 Status = MiGetConfig(Adapter, WrapperConfigurationContext);
769 if(Status != NDIS_STATUS_SUCCESS)
771 PCNET_DbgPrint(("MiGetConfig failed\n"));
772 Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
777 /* Card-specific detection and setup */
778 Status = MiQueryCard(Adapter);
779 if(Status != NDIS_STATUS_SUCCESS)
781 PCNET_DbgPrint(("MiQueryCard failed\n"));
782 Status = NDIS_STATUS_ADAPTER_NOT_FOUND;
787 /* register an IO port range */
788 Status = NdisMRegisterIoPortRange(&Adapter->PortOffset, Adapter->MiniportAdapterHandle,
789 Adapter->IoBaseAddress, NUMBER_OF_PORTS);
790 if(Status != NDIS_STATUS_SUCCESS)
792 PCNET_DbgPrint(("NdisMRegisterIoPortRange failed: 0x%x\n", Status));
797 /* Allocate map registers */
798 Status = NdisMAllocateMapRegisters(Adapter->MiniportAdapterHandle, 0,
799 NDIS_DMA_32BITS, 8, BUFFER_SIZE);
800 if(Status != NDIS_STATUS_SUCCESS)
802 PCNET_DbgPrint(("NdisMAllocateMapRegisters failed: 0x%x\n", Status));
807 /* set up the interrupt */
808 memset(&Adapter->InterruptObject, 0, sizeof(NDIS_MINIPORT_INTERRUPT));
809 Status = NdisMRegisterInterrupt(&Adapter->InterruptObject, Adapter->MiniportAdapterHandle, Adapter->InterruptVector,
810 Adapter->InterruptVector, FALSE, TRUE, NdisInterruptLevelSensitive);
811 if(Status != NDIS_STATUS_SUCCESS)
813 PCNET_DbgPrint(("NdisMRegisterInterrupt failed: 0x%x\n", Status));
818 InterruptRegistered = TRUE;
820 /* Allocate and initialize shared data structures */
821 Status = MiAllocateSharedMemory(Adapter);
822 if(Status != NDIS_STATUS_SUCCESS)
824 Status = NDIS_STATUS_RESOURCES;
825 PCNET_DbgPrint(("MiAllocateSharedMemory failed", Status));
830 /* set up the initialization block */
831 MiPrepareInitializationBlock(Adapter);
833 PCNET_DbgPrint(("Interrupt registered successfully\n"));
835 /* Initialize and start the chip */
838 Status = NDIS_STATUS_SUCCESS;
842 if(Status != NDIS_STATUS_SUCCESS && Adapter)
844 PCNET_DbgPrint(("Error; freeing stuff\n"));
846 NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); /* doesn't hurt to free if we never alloc'd? */
848 if(Adapter->PortOffset)
849 NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, Adapter->PortOffset);
851 if(InterruptRegistered)
852 NdisMDeregisterInterrupt(&Adapter->InterruptObject);
854 MiFreeSharedMemory(Adapter);
856 NdisFreeMemory(Adapter, 0, 0);
860 if(!MiTestCard(Adapter))
864 PCNET_DbgPrint(("returning 0x%x\n", Status));
865 *OpenErrorStatus = Status;
873 OUT PBOOLEAN InterruptRecognized,
874 OUT PBOOLEAN QueueMiniportHandleInterrupt,
875 IN NDIS_HANDLE MiniportAdapterContext)
877 * FUNCTION: Miniport interrupt service routine
879 * InterruptRecognized: the interrupt was ours
880 * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt
881 * MiniportAdapterContext: the context originally passed to NdisMSetAttributes
883 * - called by NDIS at DIRQL
884 * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt
890 PADAPTER Adapter = (PADAPTER)MiniportAdapterContext;
892 PCNET_DbgPrint(("Called\n"));
894 /* save the old RAP value */
895 NdisRawReadPortUshort(Adapter->PortOffset + RAP, &Rap);
898 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
899 NdisRawReadPortUshort(Adapter->PortOffset + RDP, &Data);
901 if(!(Data & CSR0_INTR))
903 PCNET_DbgPrint(("not our interrupt.\n"));
904 *InterruptRecognized = FALSE;
905 *QueueMiniportHandleInterrupt = FALSE;
909 PCNET_DbgPrint(("detected our interrupt\n"));
911 /* disable interrupts */
912 NdisRawWritePortUshort(Adapter->PortOffset + RAP, CSR0);
913 NdisRawWritePortUshort(Adapter->PortOffset + RDP, 0);
915 *InterruptRecognized = TRUE;
916 *QueueMiniportHandleInterrupt = TRUE;
919 /* restore the rap */
920 NdisRawWritePortUshort(Adapter->PortOffset + RAP, Rap);
926 MiniportQueryInformation(
927 IN NDIS_HANDLE MiniportAdapterContext,
929 IN PVOID InformationBuffer,
930 IN ULONG InformationBufferLength,
931 OUT PULONG BytesWritten,
932 OUT PULONG BytesNeeded)
934 * FUNCTION: Query an OID from the driver
936 * MiniportAdapterContext: context originally passed to NdisMSetAttributes
937 * Oid: OID NDIS is querying
938 * InformationBuffer: pointer to buffer into which to write the results of the query
939 * InformationBufferLength: size in bytes of InformationBuffer
940 * BytesWritten: number of bytes written into InformationBuffer in response to the query
941 * BytesNeeded: number of bytes needed to answer the query
943 * NDIS_STATUS_SUCCESS on all queries
945 * - Called by NDIS at PASSIVE_LEVEL
946 * - If InformationBufferLength is insufficient to store the results, return the amount
947 * needed in BytesNeeded and return NDIS_STATUS_INVALID_LENGTH
950 PCNET_DbgPrint(("Called\n"));
951 return NDIS_STATUS_SUCCESS;
958 OUT PBOOLEAN AddressingReset,
959 IN NDIS_HANDLE MiniportAdapterContext)
961 * FUNCTION: Reset the miniport
963 * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation
964 * to reset our addresses and filters
965 * MiniportAdapterContext: context originally passed to NdisMSetAttributes
967 * NDIS_STATUS_SUCCESS on all requests
969 * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset
972 PCNET_DbgPrint(("Called\n"));
973 return NDIS_STATUS_SUCCESS;
979 MiniportSetInformation(
980 IN NDIS_HANDLE MiniportAdapterContext,
982 IN PVOID InformationBuffer,
983 IN ULONG InformationBufferLength,
984 OUT PULONG BytesRead,
985 OUT PULONG BytesNeeded)
987 * FUNCTION: Set a miniport variable (OID)
989 * MiniportAdapterContext: context originally passed into NdisMSetAttributes
990 * Oid: the variable being set
991 * InformationBuffer: the data to set the variable to
992 * InformationBufferLength: number of bytes in InformationBuffer
993 * BytesRead: number of bytes read by us out of the buffer
994 * BytesNeeded: number of bytes required to satisfy the request if InformationBufferLength
997 * NDIS_STATUS_SUCCESS on all requests
999 * - Called by NDIS at PASSIVE_LEVEL
1002 PCNET_DbgPrint(("Called\n"));
1003 return NDIS_STATUS_SUCCESS;
1010 IN NDIS_HANDLE MiniportAdapterContext,
1011 IN PNDIS_PACKET Packet,
1014 * FUNCTION: Called by NDIS when it has a packet for the NIC to send out
1016 * MiniportAdapterContext: context originally input to NdisMSetAttributes
1017 * Packet: The NDIS_PACKET to be sent
1018 * Flags: Flags associated with Packet
1020 * NDIS_STATUS_SUCCESS on all requests
1022 * - Called by NDIS at DISPATCH_LEVEL
1025 PCNET_DbgPrint(("Called\n"));
1026 return NDIS_STATUS_SUCCESS;
1033 IN PDRIVER_OBJECT DriverObject,
1034 IN PUNICODE_STRING RegistryPath)
1036 * FUNCTION: Start this driver
1038 * DriverObject: Pointer to the system-allocated driver object
1039 * RegistryPath: Pointer to our SCM database entry
1041 * NDIS_STATUS_SUCCESS on success
1042 * NDIS_STATUS_FAILURE on failure
1044 * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL
1045 * - TODO: convert this to NTSTATUS return values
1048 NDIS_HANDLE WrapperHandle;
1049 NDIS_MINIPORT_CHARACTERISTICS Characteristics;
1052 memset(&Characteristics, 0, sizeof(Characteristics));
1053 Characteristics.MajorNdisVersion = 4;
1054 Characteristics.HaltHandler = MiniportHalt;
1055 Characteristics.HandleInterruptHandler = MiniportHandleInterrupt;
1056 Characteristics.InitializeHandler = MiniportInitialize;
1057 Characteristics.ISRHandler = MiniportISR;
1058 Characteristics.QueryInformationHandler = MiniportQueryInformation;
1059 Characteristics.ResetHandler = MiniportReset;
1060 Characteristics.SetInformationHandler = MiniportSetInformation;
1061 Characteristics.u1.SendHandler = MiniportSend;
1063 NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0);
1065 Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics));
1066 if(Status != NDIS_STATUS_SUCCESS)
1068 NdisTerminateWrapper(WrapperHandle, 0);
1069 return NDIS_STATUS_FAILURE;
1072 return NDIS_STATUS_SUCCESS;