From 8a5da0236781a56dd9354fe54b84ed7da13cd617 Mon Sep 17 00:00:00 2001 From: Vizzini Date: Wed, 3 Sep 2003 23:59:56 +0000 Subject: [PATCH] started pcnet driver - incomplete but builds and loads svn path=/trunk/; revision=5970 --- reactos/drivers/net/dd/pcnet/Makefile | 14 + reactos/drivers/net/dd/pcnet/pci.h | 69 ++ reactos/drivers/net/dd/pcnet/pcnet.c | 949 +++++++++++++++++++++++++ reactos/drivers/net/dd/pcnet/pcnet.h | 111 +++ reactos/drivers/net/dd/pcnet/pcnet.rc | 38 + reactos/drivers/net/dd/pcnet/pcnethw.h | 399 +++++++++++ 6 files changed, 1580 insertions(+) create mode 100644 reactos/drivers/net/dd/pcnet/Makefile create mode 100644 reactos/drivers/net/dd/pcnet/pci.h create mode 100644 reactos/drivers/net/dd/pcnet/pcnet.c create mode 100644 reactos/drivers/net/dd/pcnet/pcnet.h create mode 100644 reactos/drivers/net/dd/pcnet/pcnet.rc create mode 100644 reactos/drivers/net/dd/pcnet/pcnethw.h diff --git a/reactos/drivers/net/dd/pcnet/Makefile b/reactos/drivers/net/dd/pcnet/Makefile new file mode 100644 index 00000000000..c9f5f3ad671 --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/Makefile @@ -0,0 +1,14 @@ +PATH_TO_TOP = ../../../.. +TARGET_TYPE = driver +TARGET_NAME = pcnet + +# +# - must define NDIS40 to get the right characteristics struct +# - must define anonymous unions to make physical addresses work right +# +TARGET_CFLAGS = -I. -DDBG=1 -Wall -Werror -DNDIS40 -DANONYMOUSUNIONS + +TARGET_OBJECTS = pcnet.o +TARGET_DDKLIBS = ndis.a +include $(PATH_TO_TOP)/rules.mak +include $(TOOLS_PATH)/helper.mk diff --git a/reactos/drivers/net/dd/pcnet/pci.h b/reactos/drivers/net/dd/pcnet/pci.h new file mode 100644 index 00000000000..7e79a5fefba --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/pci.h @@ -0,0 +1,69 @@ +/* + * ReactOS AMD PCNet Driver + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * PROJECT: ReactOS AMD PCNet Driver + * FILE: pcnet/pci.h + * PURPOSE: PCI configuration constants + * PROGRAMMER: Vizzini (vizzini@plasmic.com) + * REVISIONS: + * 1-Sept-2003 vizzini - Created + */ + + +/* PCI Config Space Offset Definitions */ +#define PCI_PCIID 0x0 /* pci id - query 32 bits */ +#define PCI_VENID 0x0 /* vendor ID */ +#define PCI_DEVID 0x2 /* device ID */ +#define PCI_COMMAND 0x4 /* command register */ +#define PCI_STATUS 0x6 /* status register */ +#define PCI_REVID 0x8 /* revision ID */ +#define PCI_PIR 0x9 /* programming interface register */ +#define PCI_SCR 0xa /* sub-class register */ +#define PCI_BCR 0xb /* base-class register */ +#define PCI_LTR 0xd /* latency timer register */ +#define PCI_HTR 0xe /* header type register */ +#define PCI_IOBAR 0x10 /* i/o base address register */ +#define PCI_MMBAR 0x14 /* i/o memory-mapped base address register */ +#define PCI_ERBAR 0x30 /* expansion rom base address register */ +#define PCI_ILR 0x3c /* interrupt line register */ +#define PCI_IPR 0x3d /* interrupt pin register */ +#define PCI_MINGNT 0x3e /* min_gnt register */ +#define PCI_MAXLAT 0x3f /* max_lat register */ + +/* PCI Command Register Bits */ +#define PCI_IOEN 0x1 /* i/o space access enable */ +#define PCI_MEMEN 0x2 /* memory space access enable */ +#define PCI_BMEN 0x4 /* bus master enable */ +#define PCI_SCYCEN 0x8 /* special cycle enable */ +#define PCI_MWIEN 0X10 /* memory write and invalidate cycle enable */ +#define PCI_VGASNOOP 0x20 /* vga palette snoop */ +#define PCI_PERREN 0x40 /* parity error response enable */ +#define PCI_ADSTEP 0x80 /* address/data stepping */ +#define PCI_SERREN 0x100 /* signalled error enable */ +#define PCI_FBTBEN 0X200 /* fast back-to-back enable */ + +/* PCI Status Register Bits */ +#define PCI_FBTBC 0x80 /* fast back-to-back capable */ +#define PCI_DATAPERR 0x100 /* data parity error detected */ +#define PCI_DEVSEL1 0x200 /* device select timing lsb */ +#define PCI_DEVSEL2 0x400 /* device select timing msb */ +#define PCI_STABORT 0x800 /* send target abort */ +#define PCI_RTABORT 0x1000 /* received target abort */ +#define PCI_SERR 0x2000 /* signalled error */ +#define PCI_PERR 0x4000 /* parity error */ + diff --git a/reactos/drivers/net/dd/pcnet/pcnet.c b/reactos/drivers/net/dd/pcnet/pcnet.c new file mode 100644 index 00000000000..71746583701 --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/pcnet.c @@ -0,0 +1,949 @@ +/* + * ReactOS AMD PCNet Driver + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * PROJECT: ReactOS AMD PCNet Driver + * FILE: drivers/net/dd/pcnet/pcnet.c + * PURPOSE: PCNet Device Driver + * PROGRAMMER: Vizzini (vizzini@plasmic.com) + * REVISIONS: + * 9-Sept-2003 vizzini - Created + * NOTES: + * - this is hard-coded to NDIS4 + * - this assumes a little-endian machine + * - this assumes a 32-bit machine + * - this doesn't handle multiple PCNET NICs yet + * - this driver includes both NdisRaw and NdisImmediate calls + * for NDIS testing purposes. Pick your poison below. + */ +#include +#include "pci.h" +#include "pcnethw.h" +#include "pcnet.h" + +#define USE_IMMEDIATE_PORT_IO 1 + +VOID +STDCALL +MiniportHalt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Stop the miniport and prepare for unload + * ARGUMENTS: + * MiniportAdapterContext: context specified to NdisMSetAttributes + * NOTES: + * - Called by NDIS at PASSIVE_LEVEL + */ +{ + /* XXX Implement me */ + PCNET_DbgPrint(("Called\n")); +} + + +VOID +STDCALL +MiniportHandleInterrupt( + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Handle an interrupt if told to by MiniportISR + * ARGUMENTS: + * MiniportAdapterContext: context specified to NdisMSetAttributes + * NOTES: + * - Called by NDIS at DISPATCH_LEVEL + */ +{ + /* XXX Implement me */ + PCNET_DbgPrint(("Called\n")); +} + + +NDIS_STATUS +MiQueryCard( + IN PADAPTER Adapter) +/* + * FUNCTION: Detect the PCNET NIC in the configured slot and query its I/O address and interrupt vector + * ARGUMENTS: + * MiniportAdapterContext: context supplied to NdisMSetAttributes + * RETURNS: + * NDIS_STATUS_FAILURE on a general error + * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter + * NDIS_STATUS_SUCCESS on succes + */ +{ + ULONG buf32 = 0; + UCHAR buf8 = 0; + NDIS_STATUS Status; + + /* Detect the card in the configured slot */ + Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_PCIID, &buf32, 4); + if(Status != 4) + { + Status = NDIS_STATUS_FAILURE; + PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n")); + BREAKPOINT; + return Status; + } + + if(buf32 != PCI_ID) + { + Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + PCNET_DbgPrint(("card in slot 0x%x isn't us: 0x%x\n", Adapter->SlotNumber, buf32)); + BREAKPOINT; + return Status; + } + + Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, + PCI_COMMAND, &buf32, 4); + if(Status != 4) + { + PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n")); + BREAKPOINT; + return NDIS_STATUS_FAILURE; + } + + PCNET_DbgPrint(("config/status register: 0x%x\n", buf32)); + + if(buf32 & 0x1) + { + PCNET_DbgPrint(("io space access is enabled.\n")); + } + else + { + PCNET_DbgPrint(("io space is NOT enabled!\n")); + BREAKPOINT; + return NDIS_STATUS_FAILURE; + } + + /* get IO base physical address */ + buf32 = 0; + Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_IOBAR, &buf32, 4); + if(Status != 4) + { + Status = NDIS_STATUS_FAILURE; + PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n")); + BREAKPOINT; + return Status; + } + + if(!buf32) + { + PCNET_DbgPrint(("No base i/o address set\n")); + return NDIS_STATUS_FAILURE; + } + + buf32 &= ~1; /* even up address - comes out odd for some reason */ + + PCNET_DbgPrint(("detected io address 0x%x\n", buf32)); + Adapter->IoBaseAddress = buf32; + + /* get interrupt vector */ + Status = NdisReadPciSlotInformation(Adapter->MiniportAdapterHandle, Adapter->SlotNumber, PCI_ILR, &buf8, 1); + if(Status != 1) + { + Status = NDIS_STATUS_FAILURE; + PCNET_DbgPrint(("NdisReadPciSlotInformation failed\n")); + BREAKPOINT; + return Status; + } + + PCNET_DbgPrint(("interrupt: 0x%x\n", buf8)); + Adapter->InterruptVector = buf8; + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +MiGetConfig( + PADAPTER Adapter, + NDIS_HANDLE WrapperConfigurationContext) +/* + * FUNCTION: Get configuration parameters from the registry + * ARGUMENTS: + * Adapter: pointer to the Adapter struct for this NIC + * WrapperConfigurationContext: Context passed into MiniportInitialize + * RETURNS: + * NDIS_STATUS_SUCCESS on success + * NDIS_STATUS_{something} on failure (return val from other Ndis calls) + */ +{ + PNDIS_CONFIGURATION_PARAMETER Parameter; + NDIS_HANDLE ConfigurationHandle = 0; + UNICODE_STRING Keyword; + NDIS_STATUS Status; + + NdisOpenConfiguration(&Status, &ConfigurationHandle, WrapperConfigurationContext); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("Unable to open configuration: 0x%x\n", Status)); + BREAKPOINT; + return Status; + } + + RtlInitUnicodeString(&Keyword, L"SlotNumber"); + NdisReadConfiguration(&Status, &Parameter, ConfigurationHandle, &Keyword, NdisParameterInteger); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("Unable to read slot number: 0x%x\n", Status)); + BREAKPOINT; + } + else + Adapter->SlotNumber = Parameter->ParameterData.IntegerData; + + NdisCloseConfiguration(ConfigurationHandle); + + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +MiAllocateSharedMemory( + PADAPTER Adapter) +/* + * FUNCTION: Allocate all shared memory used by the miniport + * ARGUMENTS: + * Adapter: Pointer to the miniport's adapter object + * RETURNS: + * NDIS_STATUS_RESOURCES on insufficient memory + * NDIS_STATUS_SUCCESS on success + */ +{ + PTRANSMIT_DESCRIPTOR TransmitDescriptor; + PRECEIVE_DESCRIPTOR ReceiveDescriptor; + ULONG i; + + /* allocate the initialization block */ + Adapter->InitializationBlockLength = sizeof(INITIALIZATION_BLOCK); + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength, + FALSE, (PVOID *)&Adapter->InitializationBlockVirt, &Adapter->InitializationBlockPhys); + if(!Adapter->InitializationBlockVirt) + { + PCNET_DbgPrint(("insufficient resources\n")); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + if(((ULONG)Adapter->InitializationBlockVirt & 0x00000003) != 0) + { + PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->InitializationBlockVirt)); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + memset(Adapter->InitializationBlockVirt, 0, sizeof(INITIALIZATION_BLOCK)); + + /* allocate the transport descriptor ring */ + Adapter->TransmitDescriptorRingLength = sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS; + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength, + FALSE, (PVOID *)&Adapter->TransmitDescriptorRingVirt, &Adapter->TransmitDescriptorRingPhys); + if(!Adapter->TransmitDescriptorRingVirt) + { + PCNET_DbgPrint(("insufficient resources\n")); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + if(((ULONG)Adapter->TransmitDescriptorRingVirt & 0x00000003) != 0) + { + PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->TransmitDescriptorRingVirt)); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + memset(Adapter->TransmitDescriptorRingVirt, 0, sizeof(TRANSMIT_DESCRIPTOR) * NUMBER_OF_BUFFERS); + + /* allocate the receive descriptor ring */ + Adapter->ReceiveDescriptorRingLength = sizeof(RECEIVE_DESCRIPTOR) * NUMBER_OF_BUFFERS; + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength, + FALSE, (PVOID *)&Adapter->ReceiveDescriptorRingVirt, &Adapter->ReceiveDescriptorRingPhys); + if(!Adapter->ReceiveDescriptorRingVirt) + { + PCNET_DbgPrint(("insufficient resources\n")); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + if(((ULONG)Adapter->ReceiveDescriptorRingVirt & 0x00000003) != 0) + { + PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->ReceiveDescriptorRingVirt)); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + memset(Adapter->ReceiveDescriptorRingVirt, 0, sizeof(RECEIVE_DESCRIPTOR) * NUMBER_OF_BUFFERS); + + /* allocate transmit buffers */ + Adapter->TransmitBufferLength = BUFFER_SIZE * NUMBER_OF_BUFFERS; + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength, + FALSE, (PVOID *)&Adapter->TransmitBufferPtrVirt, &Adapter->TransmitBufferPtrPhys); + if(!Adapter->TransmitBufferPtrVirt) + { + PCNET_DbgPrint(("insufficient resources\n")); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + if(((ULONG)Adapter->TransmitBufferPtrVirt & 0x00000003) != 0) + { + PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->TransmitBufferPtrVirt)); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + memset(Adapter->TransmitBufferPtrVirt, 0, BUFFER_SIZE * NUMBER_OF_BUFFERS); + + /* allocate receive buffers */ + Adapter->ReceiveBufferLength = BUFFER_SIZE * NUMBER_OF_BUFFERS; + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength, + FALSE, (PVOID *)&Adapter->ReceiveBufferPtrVirt, &Adapter->ReceiveBufferPtrPhys); + if(!Adapter->ReceiveBufferPtrVirt) + { + PCNET_DbgPrint(("insufficient resources\n")); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + if(((ULONG)Adapter->ReceiveBufferPtrVirt & 0x00000003) != 0) + { + PCNET_DbgPrint(("address 0x%x not dword-aligned\n", Adapter->ReceiveBufferPtrVirt)); + BREAKPOINT; + return NDIS_STATUS_RESOURCES; + } + + memset(Adapter->ReceiveBufferPtrVirt, 0, BUFFER_SIZE * NUMBER_OF_BUFFERS); + + /* initialize tx descriptors */ + TransmitDescriptor = Adapter->TransmitDescriptorRingVirt; + for(i = 0; i < NUMBER_OF_BUFFERS; i++) + { + (TransmitDescriptor+i)->TBADR = NdisGetPhysicalAddressLow(Adapter->TransmitBufferPtrPhys) + i * BUFFER_SIZE; + (TransmitDescriptor+i)->BCNT = 0xf000; + (TransmitDescriptor+i)->FLAGS = TD1_STP | TD1_ENP; + } + + PCNET_DbgPrint(("transmit ring initialized\n")); + + /* initialize rx */ + ReceiveDescriptor = Adapter->ReceiveDescriptorRingVirt; + for(i = 0; i < NUMBER_OF_BUFFERS; i++) + { + (ReceiveDescriptor+i)->RBADR = NdisGetPhysicalAddressLow(Adapter->ReceiveBufferPtrPhys) + i * BUFFER_SIZE; + (ReceiveDescriptor+i)->BCNT = 0xf000 | -BUFFER_SIZE; /* 2's compliment */ + (ReceiveDescriptor+i)->FLAGS |= RD_OWN; + } + + PCNET_DbgPrint(("receive ring initialized\n")); + + return NDIS_STATUS_SUCCESS; +} + + +VOID +MiPrepareInitializationBlock( + PADAPTER Adapter) +/* + * FUNCTION: Initialize the initialization block + * ARGUMENTS: + * Adapter: pointer to the miniport's adapter object + */ +{ + ULONG i = 0; + + /* read burned-in address from card */ + for(i = 0; i < 6; i++) +#if USE_IMMEDIATE_PORT_IO + NdisImmediateReadPortUchar(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + i, + Adapter->InitializationBlockVirt->PADR); +#else + NdisRawReadPortUchar(Adapter->PortOffset + i, Adapter->InitializationBlockVirt->PADR + i); +#endif + + /* set up receive ring */ + Adapter->InitializationBlockVirt->RDRA = NdisGetPhysicalAddressLow(Adapter->ReceiveDescriptorRingPhys); + Adapter->InitializationBlockVirt->RLEN = LOG_NUMBER_OF_BUFFERS; + + /* set up transmit ring */ + Adapter->InitializationBlockVirt->TDRA = NdisGetPhysicalAddressLow(Adapter->TransmitDescriptorRingPhys); + Adapter->InitializationBlockVirt->TLEN = LOG_NUMBER_OF_BUFFERS; +} + + +VOID +MiFreeSharedMemory( + PADAPTER Adapter) +/* + * FUNCTION: Free all allocated shared memory + * ARGUMENTS: + * Adapter: pointer to the miniport's adapter struct + */ +{ + if(Adapter->InitializationBlockVirt) + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->InitializationBlockLength, + FALSE, (PVOID *)&Adapter->InitializationBlockVirt, &Adapter->InitializationBlockPhys); + + if(Adapter->TransmitDescriptorRingVirt) + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitDescriptorRingLength, + FALSE, (PVOID *)&Adapter->TransmitDescriptorRingVirt, &Adapter->TransmitDescriptorRingPhys); + + if(Adapter->ReceiveDescriptorRingVirt) + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveDescriptorRingLength, + FALSE, (PVOID *)&Adapter->ReceiveDescriptorRingVirt, &Adapter->ReceiveDescriptorRingPhys); + + if(Adapter->TransmitBufferPtrVirt) + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->TransmitBufferLength, + FALSE, (PVOID *)&Adapter->TransmitBufferPtrVirt, &Adapter->TransmitBufferPtrPhys); + + if(Adapter->ReceiveBufferPtrVirt) + NdisMAllocateSharedMemory(Adapter->MiniportAdapterHandle, Adapter->ReceiveBufferLength, + FALSE, (PVOID *)&Adapter->ReceiveBufferPtrVirt, &Adapter->ReceiveBufferPtrPhys); +} + + +VOID +MiInitChip( + PADAPTER Adapter) +/* + * FUNCTION: Initialize and start the PCNET chip + * ARGUMENTS: + * Adapter: pointer to the miniport's adapter struct + * NOTES: + * - should be coded to detect failure and return an error + */ +{ + ULONG Data = 0; + + PCNET_DbgPrint(("Called\n")); + + /* stop the chip */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR0); + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, CSR0_STOP); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR0); + NdisRawWritePortUlong(Adapter->PortOffset + RDP, CSR0_STOP); +#endif + + NdisStallExecution(5); + + PCNET_DbgPrint(("chip stopped\n")); + + /* set the software style to 32 bits */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR58); + NdisImmediateReadPortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, &Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR58); + NdisRawReadPortUlong(Adapter->PortOffset + RDP, &Data); +#endif + + Data |= CSR58_SSIZE32; + Data |= SW_STYLE_2; + +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RDP, Data); +#endif + + PCNET_DbgPrint(("software style set to 2 / 32-bit\n")); + + /* set up csr4: auto transmit pad, disable polling, disable transmit interrupt, dmaplus */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR4); + NdisImmediateReadPortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, &Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR4); + NdisRawReadPortUlong(Adapter->PortOffset + RDP, &Data); +#endif + + Data |= CSR4_APAD_XMT | CSR4_DPOLL | CSR4_TXSTRTM | CSR4_DMAPLUS; +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RDP, Data); +#endif + + /* set up bcr18: burst read/write enable */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, BCR18); + NdisImmediateReadPortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + BDP, &Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, BCR18); + NdisRawReadPortUlong(Adapter->PortOffset + BDP, &Data); +#endif + + Data |= BCR18_BREADE | BCR18_BWRITE ; +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + BDP, Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + BDP, Data); +#endif + + /* set up csr1 and csr2 with init block */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR1); + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, + NdisGetPhysicalAddressLow(Adapter->InitializationBlockPhys) & 0xffff); + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, + (NdisGetPhysicalAddressLow(Adapter->InitializationBlockPhys) >> 16) & 0xffff); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR1); + NdisRawWritePortUlong(Adapter->PortOffset + RDP, NdisGetPhysicalAddressLow(Adapter->InitializationBlockPhys) & 0xffff); + NdisRawWritePortUlong(Adapter->PortOffset + RDP, (NdisGetPhysicalAddressLow(Adapter->InitializationBlockPhys) >> 16) & 0xffff); +#endif + + PCNET_DbgPrint(("programmed with init block\n")); + + /* load init block and start the card */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR0); + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR0); + NdisRawWritePortUlong(Adapter->PortOffset + RDP, CSR0_STRT|CSR0_INIT|CSR0_IENA); +#endif + + PCNET_DbgPrint(("card started\n")); + + Adapter->Flags &= ~RESET_IN_PROGRESS; +} + + +BOOLEAN +MiTestCard( + PADAPTER Adapter) +/* + * FUNCTION: Test the NIC + * ARGUMENTS: + * Adapter: pointer to the miniport's adapter struct + * RETURNS: + * TRUE if the test succeeds + * FALSE otherwise + * NOTES: + * - this is where to add diagnostics. This is called + * at the very end of initialization. + */ +{ + int i = 0; + UCHAR address[6]; + +#if !(USE_IMMEDIATE_PORT_IO) + /* see if we can read/write now */ + { + ULONG Data = 0; + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR0); + NdisRawReadPortUlong(Adapter->PortOffset + RDP, &Data); + + 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)); + } +#endif + + /* read the BIA */ + for(i=0; i < 6; i++) + { +#if USE_IMMEDIATE_PORT_IO + NdisImmediateReadPortUchar(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + i, &address[i]); +#else + NdisRawReadPortUchar(Adapter->PortOffset + i, &address[i]); +#endif + } + + PCNET_DbgPrint(("burned-in address: %x:%x:%x:%x:%x:%x\n", address[0], address[1], address[2], address[3], + address[4], address[5])); + + return TRUE; +} + + +NDIS_STATUS +STDCALL +MiniportInitialize( + OUT PNDIS_STATUS OpenErrorStatus, + OUT PUINT SelectedMediumIndex, + IN PNDIS_MEDIUM MediumArray, + IN UINT MediumArraySize, + IN NDIS_HANDLE MiniportAdapterHandle, + IN NDIS_HANDLE WrapperConfigurationContext) +/* + * FUNCTION: Initialize a new miniport + * ARGUMENTS: + * OpenErrorStatus: pointer to a var to return status info in + * SelectedMediumIndex: index of the selected medium (will be NdisMedium802_3) + * MediumArray: array of media that we can pick from + * MediumArraySize: size of MediumArray + * MiniportAdapterHandle: NDIS-assigned handle for this miniport instance + * WrapperConfigurationContext: temporary NDIS-assigned handle for passing + * to configuration APIs + * RETURNS: + * NDIS_STATUS_SUCCESS on success + * NDIS_STATUS_FAILURE on general failure + * NDIS_STATUS_UNSUPPORTED_MEDIA on not finding 802_3 in the MediaArray + * NDIS_STATUS_RESOURCES on insufficient system resources + * NDIS_STATUS_ADAPTER_NOT_FOUND on not finding the adapter + * NOTES: + * - Called by NDIS at PASSIVE_LEVEL, once per detected card + * - Will int 3 on failure of MiTestCard if DBG=1 + */ +{ + UINT i = 0; + PADAPTER Adapter = 0; + NDIS_STATUS Status = NDIS_STATUS_FAILURE; + BOOLEAN InterruptRegistered = FALSE; + + /* Pick a medium */ + for(i = 0; i < MediumArraySize; i++) + if(MediumArray[i] == NdisMedium802_3) + break; + + if(i == MediumArraySize) + { + Status = NDIS_STATUS_UNSUPPORTED_MEDIA; + PCNET_DbgPrint(("unsupported media\n")); + BREAKPOINT; + *OpenErrorStatus = Status; + return Status; + } + + *SelectedMediumIndex = i; + + /* allocate our adapter struct */ + Status = NdisAllocateMemoryWithTag((PVOID *)&Adapter, sizeof(ADAPTER), PCNET_TAG); + if(Status != NDIS_STATUS_SUCCESS) + { + Status = NDIS_STATUS_RESOURCES; + PCNET_DbgPrint(("Insufficient resources\n")); + BREAKPOINT; + *OpenErrorStatus = Status; + return Status; + } + + memset(Adapter,0,sizeof(ADAPTER)); + + Adapter->MiniportAdapterHandle = MiniportAdapterHandle; + + /* register our adapter structwith ndis */ + NdisMSetAttributesEx(Adapter->MiniportAdapterHandle, Adapter, 0, NDIS_ATTRIBUTE_BUS_MASTER, NdisInterfacePci); + + do + { + /* get registry config */ + Status = MiGetConfig(Adapter, WrapperConfigurationContext); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("MiGetConfig failed\n")); + Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + BREAKPOINT; + break; + } + + /* Card-specific detection and setup */ + Status = MiQueryCard(Adapter); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("MiQueryCard failed\n")); + Status = NDIS_STATUS_ADAPTER_NOT_FOUND; + BREAKPOINT; + break; + } + + /* register an IO port range */ + Status = NdisMRegisterIoPortRange(&Adapter->PortOffset, Adapter->MiniportAdapterHandle, + Adapter->IoBaseAddress, NUMBER_OF_PORTS); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("NdisMRegisterIoPortRange failed: 0x%x\n", Status)); + BREAKPOINT + break; + } + + /* Allocate map registers */ + Status = NdisMAllocateMapRegisters(Adapter->MiniportAdapterHandle, 0, + NDIS_DMA_32BITS, 8, BUFFER_SIZE); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("NdisMAllocateMapRegisters failed: 0x%x\n", Status)); + BREAKPOINT + break; + } + + /* set up the interrupt */ + memset(&Adapter->InterruptObject, 0, sizeof(NDIS_MINIPORT_INTERRUPT)); + Status = NdisMRegisterInterrupt(&Adapter->InterruptObject, Adapter->MiniportAdapterHandle, Adapter->InterruptVector, + Adapter->InterruptVector, FALSE, TRUE, NdisInterruptLevelSensitive); + if(Status != NDIS_STATUS_SUCCESS) + { + PCNET_DbgPrint(("NdisMRegisterInterrupt failed: 0x%x\n", Status)); + BREAKPOINT + break; + } + + InterruptRegistered = TRUE; + + /* Allocate and initialize shared data structures */ + Status = MiAllocateSharedMemory(Adapter); + if(Status != NDIS_STATUS_SUCCESS) + { + Status = NDIS_STATUS_RESOURCES; + PCNET_DbgPrint(("MiAllocateSharedMemory failed", Status)); + BREAKPOINT + break; + } + + /* set up the initialization block */ + MiPrepareInitializationBlock(Adapter); + + PCNET_DbgPrint(("Interrupt registered successfully\n")); + + /* Initialize and start the chip */ + MiInitChip(Adapter); + + Status = NDIS_STATUS_SUCCESS; + } + while(0); + + if(Status != NDIS_STATUS_SUCCESS && Adapter) + { + PCNET_DbgPrint(("Error; freeing stuff\n")); + + NdisMFreeMapRegisters(Adapter->MiniportAdapterHandle); /* doesn't hurt to free if we never alloc'd? */ + + if(Adapter->PortOffset) + NdisMDeregisterIoPortRange(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress, NUMBER_OF_PORTS, Adapter->PortOffset); + + if(InterruptRegistered) + NdisMDeregisterInterrupt(&Adapter->InterruptObject); + + MiFreeSharedMemory(Adapter); + + NdisFreeMemory(Adapter, 0, 0); + } + +#if DBG + if(!MiTestCard(Adapter)) + __asm__("int $3\n"); +#endif + + PCNET_DbgPrint(("returning 0x%x\n", Status)); + *OpenErrorStatus = Status; + return Status; +} + + +VOID +STDCALL +MiniportISR( + OUT PBOOLEAN InterruptRecognized, + OUT PBOOLEAN QueueMiniportHandleInterrupt, + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Miniport interrupt service routine + * ARGUMENTS: + * InterruptRecognized: the interrupt was ours + * QueueMiniportHandleInterrupt: whether to queue a DPC to handle this interrupt + * MiniportAdapterContext: the context originally passed to NdisMSetAttributes + * NOTES: + * - called by NDIS at DIRQL + * - by setting QueueMiniportHandleInterrupt to TRUE, MiniportHandleInterrupt + * will be called + */ +{ + ULONG Data; + PADAPTER Adapter = (PADAPTER)MiniportAdapterContext; + + PCNET_DbgPrint(("Called\n")); + + /* XXX change this once MiniportHandleInterrupt does something */ + *QueueMiniportHandleInterrupt = FALSE; + + /* is this ours? */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RAP, CSR0); + NdisImmediateReadPortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, &Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RAP, CSR0); + NdisRawReadPortUlong(Adapter->PortOffset + RDP, &Data); +#endif + + if(!(Data & CSR0_INTR)) + { + *InterruptRecognized = FALSE; + return; + } + + /* clear the interrupt by writing back what we read */ +#if USE_IMMEDIATE_PORT_IO + NdisImmediateWritePortUlong(Adapter->MiniportAdapterHandle, Adapter->IoBaseAddress + RDP, Data); +#else + NdisRawWritePortUlong(Adapter->PortOffset + RDP, Data); +#endif + + *InterruptRecognized = TRUE; +} + + +NDIS_STATUS +STDCALL +MiniportQueryInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesWritten, + OUT PULONG BytesNeeded) +/* + * FUNCTION: Query an OID from the driver + * ARGUMENTS: + * MiniportAdapterContext: context originally passed to NdisMSetAttributes + * Oid: OID NDIS is querying + * InformationBuffer: pointer to buffer into which to write the results of the query + * InformationBufferLength: size in bytes of InformationBuffer + * BytesWritten: number of bytes written into InformationBuffer in response to the query + * BytesNeeded: number of bytes needed to answer the query + * RETURNS: + * NDIS_STATUS_SUCCESS on all queries + * NOTES: + * - Called by NDIS at PASSIVE_LEVEL + * - If InformationBufferLength is insufficient to store the results, return the amount + * needed in BytesNeeded and return NDIS_STATUS_INVALID_LENGTH + */ +{ + PCNET_DbgPrint(("Called\n")); + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +STDCALL +MiniportReset( + OUT PBOOLEAN AddressingReset, + IN NDIS_HANDLE MiniportAdapterContext) +/* + * FUNCTION: Reset the miniport + * ARGUMENTS: + * AddressingReset: Whether or not we want NDIS to subsequently call MiniportSetInformation + * to reset our addresses and filters + * MiniportAdapterContext: context originally passed to NdisMSetAttributes + * RETURNS: + * NDIS_STATUS_SUCCESS on all requests + * Notes: + * - Called by NDIS at PASSIVE_LEVEL when it thinks we need a reset + */ +{ + PCNET_DbgPrint(("Called\n")); + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +STDCALL +MiniportSetInformation( + IN NDIS_HANDLE MiniportAdapterContext, + IN NDIS_OID Oid, + IN PVOID InformationBuffer, + IN ULONG InformationBufferLength, + OUT PULONG BytesRead, + OUT PULONG BytesNeeded) +/* + * FUNCTION: Set a miniport variable (OID) + * ARGUMENTS: + * MiniportAdapterContext: context originally passed into NdisMSetAttributes + * Oid: the variable being set + * InformationBuffer: the data to set the variable to + * InformationBufferLength: number of bytes in InformationBuffer + * BytesRead: number of bytes read by us out of the buffer + * BytesNeeded: number of bytes required to satisfy the request if InformationBufferLength + * is insufficient + * RETURNS: + * NDIS_STATUS_SUCCESS on all requests + * NOTES: + * - Called by NDIS at PASSIVE_LEVEL + */ +{ + PCNET_DbgPrint(("Called\n")); + return NDIS_STATUS_SUCCESS; +} + + +NDIS_STATUS +STDCALL +MiniportSend( + IN NDIS_HANDLE MiniportAdapterContext, + IN PNDIS_PACKET Packet, + IN UINT Flags) +/* + * FUNCTION: Called by NDIS when it has a packet for the NIC to send out + * ARGUMENTS: + * MiniportAdapterContext: context originally input to NdisMSetAttributes + * Packet: The NDIS_PACKET to be sent + * Flags: Flags associated with Packet + * RETURNS: + * NDIS_STATUS_SUCCESS on all requests + * NOTES: + * - Called by NDIS at DISPATCH_LEVEL + */ +{ + PCNET_DbgPrint(("Called\n")); + return NDIS_STATUS_SUCCESS; +} + + +NTSTATUS +STDCALL +DriverEntry( + IN PDRIVER_OBJECT DriverObject, + IN PUNICODE_STRING RegistryPath) +/* + * FUNCTION: Start this driver + * ARGUMENTS: + * DriverObject: Pointer to the system-allocated driver object + * RegistryPath: Pointer to our SCM database entry + * RETURNS: + * NDIS_STATUS_SUCCESS on success + * NDIS_STATUS_FAILURE on failure + * NOTES: + * - Called by the I/O manager when the driver starts at PASSIVE_LEVEL + * - TODO: convert this to NTSTATUS return values + */ +{ + NDIS_HANDLE WrapperHandle; + NDIS_MINIPORT_CHARACTERISTICS Characteristics; + NDIS_STATUS Status; + + memset(&Characteristics, 0, sizeof(Characteristics)); + Characteristics.MajorNdisVersion = 4; + Characteristics.HaltHandler = MiniportHalt; + Characteristics.HandleInterruptHandler = MiniportHandleInterrupt; + Characteristics.InitializeHandler = MiniportInitialize; + Characteristics.ISRHandler = MiniportISR; + Characteristics.QueryInformationHandler = MiniportQueryInformation; + Characteristics.ResetHandler = MiniportReset; + Characteristics.SetInformationHandler = MiniportSetInformation; + Characteristics.u1.SendHandler = MiniportSend; + + NdisMInitializeWrapper(&WrapperHandle, DriverObject, RegistryPath, 0); + + Status = NdisMRegisterMiniport(WrapperHandle, &Characteristics, sizeof(Characteristics)); + if(Status != NDIS_STATUS_SUCCESS) + { + NdisTerminateWrapper(WrapperHandle, 0); + return NDIS_STATUS_FAILURE; + } + + return NDIS_STATUS_SUCCESS; +} + diff --git a/reactos/drivers/net/dd/pcnet/pcnet.h b/reactos/drivers/net/dd/pcnet/pcnet.h new file mode 100644 index 00000000000..ad5e14f52aa --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/pcnet.h @@ -0,0 +1,111 @@ +/* + * ReactOS AMD PCNet Driver + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * PROJECT: ReactOS AMD PCNet Driver + * FILE: pcnet/pcnet.h + * PURPOSE: PCNet Device Driver + * PROGRAMMER: Vizzini (vizzini@plasmic.com) + * REVISIONS: + * 1-Sept-2003 vizzini - Created + * NOTES: + * - this is hard-coded to NDIS4 + * - this assumes a little-endian machine + */ + +#ifndef _PCNET_H_ +#define _PCNET_H_ + +/* adapter struct */ +typedef struct _ADAPTER +{ + NDIS_HANDLE MiniportAdapterHandle; + ULONG Flags; + ULONG BusNumber; + ULONG SlotNumber; + ULONG InterruptVector; + ULONG IoBaseAddress; + PVOID PortOffset; + NDIS_MINIPORT_INTERRUPT InterruptObject; + + /* initialization block */ + ULONG InitializationBlockLength; + PINITIALIZATION_BLOCK InitializationBlockVirt; + NDIS_PHYSICAL_ADDRESS InitializationBlockPhys; + + /* transmit descriptor ring */ + ULONG TransmitDescriptorRingLength; + PTRANSMIT_DESCRIPTOR TransmitDescriptorRingVirt; + NDIS_PHYSICAL_ADDRESS TransmitDescriptorRingPhys; + + /* transmit buffers */ + ULONG TransmitBufferLength; + PCHAR TransmitBufferPtrVirt; + NDIS_PHYSICAL_ADDRESS TransmitBufferPtrPhys; + + /* receive descriptor ring */ + ULONG ReceiveDescriptorRingLength; + PRECEIVE_DESCRIPTOR ReceiveDescriptorRingVirt; + NDIS_PHYSICAL_ADDRESS ReceiveDescriptorRingPhys; + + /* receive buffers */ + ULONG ReceiveBufferLength; + PCHAR ReceiveBufferPtrVirt; + NDIS_PHYSICAL_ADDRESS ReceiveBufferPtrPhys; + +} ADAPTER, *PADAPTER; + +/* operational constants */ +#define NUMBER_OF_BUFFERS 0x20 +#define LOG_NUMBER_OF_BUFFERS 5 /* log2(NUMBER_OF_BUFFERS) */ +#define BUFFER_SIZE 0x600 + +/* flags */ +#define RESET_IN_PROGRESS 0x1 + +/* debugging */ +#if DBG +#define PCNET_DbgPrint(_x) \ +{\ + DbgPrint("%s:%d %s: ", __FILE__, __LINE__, __FUNCTION__); \ + DbgPrint _x; \ +} +#else +#define PCNET_DbgPrint(_x) +#endif + +#if DBG +#define BREAKPOINT __asm__ ("int $3\n"); +#else +#define BREAKPOINT +#endif + +/* memory pool tag */ +#define PCNET_TAG 0xbaadf00d + +/* stack validation */ +#define STACKENTER __asm__("movl %%esp, %0\n" : "=m" (esp)); + +#define STACKLEAVE {\ + unsigned long esptemp = esp; \ + __asm__ ("movl %%esp, %0\n": "=m" (esp)); \ + if(esp != esptemp) \ + __asm__ ("int $3\n"); \ +} + +#endif // _PCNET_H_ + diff --git a/reactos/drivers/net/dd/pcnet/pcnet.rc b/reactos/drivers/net/dd/pcnet/pcnet.rc new file mode 100644 index 00000000000..5c0dceaa8b3 --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/pcnet.rc @@ -0,0 +1,38 @@ +#include +#include + +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US + +VS_VERSION_INFO VERSIONINFO + FILEVERSION RES_UINT_FV_MAJOR,RES_UINT_FV_MINOR,RES_UINT_FV_REVISION,RES_UINT_FV_BUILD + PRODUCTVERSION RES_UINT_PV_MAJOR,RES_UINT_PV_MINOR,RES_UINT_PV_REVISION,RES_UINT_PV_BUILD + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "CompanyName", RES_STR_COMPANY_NAME + VALUE "FileDescription", "PCNet Ethernet PCI Driver\0" + VALUE "FileVersion", "0.0.1\0" + VALUE "InternalName", "pcnet\0" + VALUE "LegalCopyright", RES_STR_LEGAL_COPYRIGHT + VALUE "OriginalFilename", "pcnet.sys\0" + VALUE "ProductName", RES_STR_PRODUCT_NAME + VALUE "ProductVersion", RES_STR_PRODUCT_VERSION + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + diff --git a/reactos/drivers/net/dd/pcnet/pcnethw.h b/reactos/drivers/net/dd/pcnet/pcnethw.h new file mode 100644 index 00000000000..e63f4fe3cd7 --- /dev/null +++ b/reactos/drivers/net/dd/pcnet/pcnethw.h @@ -0,0 +1,399 @@ +/* + * ReactOS AMD PCNet Driver + * Copyright (C) 1998, 1999, 2000, 2001 ReactOS Team + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * PROJECT: ReactOS AMD PCNet Driver + * FILE: drivers/net/dd/pcnet/pcnethw.h + * PURPOSE: PCNet hardware configuration constants + * PROGRAMMER: Vizzini (vizzini@plasmic.com) + * REVISIONS: + * 1-Sept-2003 vizzini - Created + * NOTES: + * - This file represents a clean re-implementation from the AMD + * PCNet II chip documentation (Am79C790A, pub# 19436). + */ + +#define NUMBER_OF_PORTS 0x20 /* number of i/o ports the board requires */ + +/* offsets of important registers */ +#define RDP 0x10 +#define RAP 0x12 +#define RESET 0x14 +#define BDP 0x16 + +/* pci id of the device */ +#define PCI_ID 0x20001022 +#define VEN_ID 0x1022 +#define DEV_ID 0x2000 + +/* software style constants */ +#define SW_STYLE_0 0 +#define SW_STYLE_1 1 +#define SW_STYLE_2 2 +#define SW_STYLE_3 3 + +/* control and status registers */ +#define CSR0 0x0 /* controller status register */ +#define CSR1 0x1 /* init block address 0 */ +#define CSR2 0x2 /* init block address 1 */ +#define CSR3 0x3 /* interrupt masks and deferral control */ +#define CSR4 0x4 /* test and features control */ +#define CSR5 0x5 /* extended control and interrupt */ +#define CSR6 0x6 /* rx/tx descriptor table length */ +#define CSR8 0x8 /* logical address filter 0 */ +#define CSR9 0x9 /* logical address filter 1 */ +#define CSR10 0xa /* logical address filter 2 */ +#define CSR11 0xb /* logical address filter 3 */ +#define CSR12 0xc /* physical address register 0 */ +#define CSR13 0xd /* physical address register 1 */ +#define CSR14 0xe /* physical address register 2 */ +#define CSR15 0xf /* Mode */ +#define CSR16 0x10 /* initialization block address lower */ +#define CSR17 0x11 /* initialization block address upper */ +#define CSR18 0x12 /* current receive buffer address lower */ +#define CSR19 0x13 /* current receive buffer address upper */ +#define CSR20 0x14 /* current transmit buffer address lower */ +#define CSR21 0x15 /* current transmit buffer address upper */ +#define CSR22 0x16 /* next receive buffer address lower */ +#define CSR23 0x17 /* next receive buffer address upper */ +#define CSR24 0x18 /* base address of receive descriptor ring lower */ +#define CSR25 0x19 /* base address of receive descriptor ring upper */ +#define CSR26 0x1a /* next receive descriptor address lower */ +#define CSR27 0x1b /* next receive descriptor address upper */ +#define CSR28 0x1c /* current receive descriptor address lower */ +#define CSR29 0x1d /* current receive descriptor address upper */ +#define CSR30 0x1e /* base address of transmit descriptor ring lower */ +#define CSR31 0x1f /* base address of transmit descriptor ring upper */ +#define CSR32 0x20 /* next transmit descriptor address lower */ +#define CSR33 0x21 /* next transmit descriptor address upper */ +#define CSR34 0x22 /* current transmit descriptor address lower */ +#define CSR35 0x23 /* current transmit descriptor address upper */ +#define CSR36 0x24 /* next next receive descriptor address lower */ +#define CSR37 0x25 /* next next receive descriptor address upper */ +#define CSR38 0x26 /* next next transmit descriptor address lower */ +#define CSR39 0x27 /* next next transmit descriptor address upper */ +#define CSR40 0x28 /* current receive byte count */ +#define CSR41 0x29 /* current receive status */ +#define CSR42 0x2a /* current transmit byte count */ +#define CSR43 0x2b /* current transmit status */ +#define CSR44 0x2c /* next receive byte count */ +#define CSR45 0x2d /* next receive status */ +#define CSR46 0x2e /* poll time counter */ +#define CSR47 0x2f /* polling interval */ +#define CSR58 0x3a /* software style */ +#define CSR60 0x3c /* previous transmit descriptor address lower */ +#define CSR61 0x3d /* previous transmit descriptor address upper */ +#define CSR62 0x3e /* previous transmit byte count */ +#define CSR63 0x3f /* previous transmit status */ +#define CSR64 0x40 /* next transmit buffer address lower */ +#define CSR65 0x41 /* next transmit buffer address upper */ +#define CSR66 0x42 /* next transmit byte count */ +#define CSR67 0x43 /* next transmit status */ +#define CSR72 0x48 /* receive descriptor ring counter */ +#define CSR74 0x4a /* transmit descriptor ring counter */ +#define CSR76 0x4c /* receive descriptor ring length */ +#define CSR78 0x4e /* transmit descriptor ring length */ +#define CSR80 0x50 /* dma transfer counter and fifo watermark control */ +#define CSR82 0x52 /* bus activity timer */ +#define CSR84 0x54 /* dma address register lower */ +#define CSR85 0x55 /* dma address register upper */ +#define CSR86 0x56 /* buffer byte counter */ +#define CSR88 0x58 /* chip id register lower */ +#define CSR89 0x59 /* chip id register upper */ +#define CSR94 0x5e /* transmit time domain reflectometry count */ +#define CSR100 0x64 /* bus timeout */ +#define CSR112 0x70 /* missed frame count */ +#define CSR114 0x72 /* receive collision count */ +#define CSR122 0x7a /* advanced feature control */ +#define CSR124 0x7c /* test register control */ + +/* bus configuration registers */ +#define BCR2 0x2 /* miscellaneous configuration */ +#define BCR4 0x4 /* link status led */ +#define BCR5 0x5 /* led1 status */ +#define BCR6 0x6 /* led2 status */ +#define BCR7 0x7 /* led3 status */ +#define BCR9 0x9 /* full-duplex control */ +#define BCR16 0x10 /* i/o base address lower */ +#define BCR17 0x11 /* i/o base address upper */ +#define BCR18 0x12 /* burst and bus control register */ +#define BCR19 0x13 /* eeprom control and status */ +#define BCR20 0x14 /* software style */ +#define BCR21 0x15 /* interrupt control */ +#define BCR22 0x16 /* pci latency register */ + +/* CSR0 bits */ +#define CSR0_INIT 0x1 /* read initialization block */ +#define CSR0_STRT 0x2 /* start the chip */ +#define CSR0_STOP 0x4 /* stop the chip */ +#define CSR0_TDMD 0x8 /* transmit demand */ +#define CSR0_TXON 0x10 /* transmit on */ +#define CSR0_RXON 0x20 /* receive on */ +#define CSR0_IENA 0x40 /* interrupt enabled */ +#define CSR0_INTR 0x80 /* interrupting */ +#define CSR0_IDON 0x100 /* initialization done */ +#define CSR0_TINT 0x200 /* transmit interrupt */ +#define CSR0_RINT 0x400 /* receive interrupt */ +#define CSR0_MERR 0x800 /* memory error */ +#define CSR0_MISS 0x1000 /* missed frame */ +#define CSR0_CERR 0x2000 /* collision error */ +#define CSR0_BABL 0x4000 /* babble */ +#define CSR0_ERR 0x8000 /* error */ + +/* CSR3 bits */ +#define CSR3_BSWP 0x4 /* byte swap */ +#define CSR3_EMBA 0x8 /* enable modified backoff algorithm */ +#define CSR3_DXMT2PD 0x10 /* disable transmit two-part deferral */ +#define CSR3_LAPPEN 0x20 /* lookahead packet processing enable */ +#define CSR3_DXSUFLO 0x40 /* disable transmit stop on underflow */ +#define CSR3_IDONM 0x100 /* initialization done mask */ +#define CSR3_TINTM 0x200 /* transmit interrupt mask */ +#define CSR3_RINTM 0x400 /* receive interrupt mask */ +#define CSR3_MERRM 0x800 /* memory error interrupt mask */ +#define CSR3_MISSM 0x1000 /* missed frame interrupt mask */ +#define CSR3_BABLM 0x4000 /* babble interrupt mask */ + +/* CSR4 bits */ +#define CSR4_JABM 0x1 /* jabber interrupt mask */ +#define CSR4_JAB 0x2 /* interrupt on jabber error */ +#define CSR4_TXSTRTM 0x4 /* transmit start interrupt mask */ +#define CSR4_TXSTRT 0x8 /* interrupt on transmit start */ +#define CSR4_RCVCCOM 0x10 /* receive collision counter overflow mask */ +#define CSR4_RCVCCO 0X20 /* interrupt on receive collision counter overflow */ +#define CSR4_UINT 0x40 /* user interrupt */ +#define CSR4_UINTCMD 0x80 /* user interrupt command */ +#define CSR4_MFCOM 0x100 /* missed frame counter overflow mask */ +#define CSR4_MFCO 0x200 /* interrupt on missed frame counter overflow */ +#define CSR4_ASTRP_RCV 0x400 /* auto pad strip on receive */ +#define CSR4_APAD_XMT 0x800 /* auto pad on transmit */ +#define CSR4_DPOLL 0x1000 /* disable transmit polling */ +#define CSR4_TIMER 0x2000 /* enable bus activity timer */ +#define CSR4_DMAPLUS 0x4000 /* set to 1 for pci */ +#define CSR4_EN124 0x8000 /* enable CSR124 access */ + +/* CSR5 bits */ +#define CSR5_SPND 0x1 /* suspend */ +#define CSR5_MPMODE 0x2 /* magic packet mode */ +#define CSR5_MPEN 0x4 /* magic packet enable */ +#define CSR5_MPINTE 0x8 /* magic packet interrupt enable */ +#define CSR5_MPINT 0x10 /* magic packet interrupt */ +#define CSR5_MPPLBA 0x20 /* magic packet physical logical broadcast accept */ +#define CSR5_EXDINTE 0x40 /* excessive deferral interrupt enable */ +#define CSR5_EXDINT 0x80 /* excessive deferral interrupt */ +#define CSR5_SLPINTE 0x100 /* sleep interrupt enable */ +#define CSR5_SLPINT 0x200 /* sleep interrupt */ +#define CSR5_SINE 0x400 /* system interrupt enable */ +#define CSR5_SINT 0x800 /* system interrupt */ +#define CSR5_LTINTEN 0x4000 /* last transmit interrupt enable */ +#define CSR5_TOKINTD 0x8000 /* transmit ok interrupt disable */ + +/* CSR15 bits */ +#define CSR15_DRX 0x1 /* disable receiver */ +#define CSR15_DTX 0x2 /* disable transmitter */ +#define CSR15_LOOP 0x4 /* loopback enable */ +#define CSR15_DXMTFCS 0x8 /* disable transmit fcs */ +#define CSR15_FCOLL 0x10 /* force collision */ +#define CSR15_DRTY 0x20 /* disable retry */ +#define CSR15_INTL 0x40 /* internal loopback */ +#define CSR15_PORTSEL0 0x80 /* port selection bit 0 */ +#define CSR15_PORTSEL1 0x100 /* port selection bit 1 */ +#define CSR15_LRT 0x200 /* low receive threshold - same as TSEL */ +#define CSR15_TSEL 0x200 /* transmit mode select - same as LRT */ +#define CSR15_MENDECL 0x400 /* mendec loopback mode */ +#define CSR15_DAPC 0x800 /* disable automatic parity correction */ +#define CSR15_DLNKTST 0x1000 /* disable link status */ +#define CSR15_DRCVPA 0x2000 /* disable receive physical address */ +#define CSR15_DRCVBC 0x4000 /* disable receive broadcast */ +#define CSR15_PROM 0x8000 /* promiscuous mode */ + +/* CSR58 bits */ +#define CSR58_SSIZE32 0x100 /* 32-bit software size */ +#define CSR58_CSRPCNET 0x200 /* csr pcnet-isa configuration */ +#define CSR58_APERREN 0x400 /* advanced parity error handling enable */ + +/* CSR124 bits */ +#define CSR124_RPA 0x4 /* runt packet accept */ + +/* BCR2 bits */ +#define BCR2_ASEL 0x2 /* auto-select media */ +#define BCR2_AWAKE 0x4 /* select sleep mode */ +#define BCR2_EADISEL 0x8 /* eadi select */ +#define BCR2_DXCVRPOL 0x10 /* dxcvr polarity */ +#define BCR2_DXCVRCTL 0x20 /* dxcvr control */ +#define BCR2_INTLEVEL 0x80 /* interrupt level/edge */ +#define BCR2_APROMWE 0x100 /* address prom write enable */ +#define BCR2_TMAULOOP 0x4000 /* t-mau transmit on loopback */ + +/* BCR4 bits */ +#define BCR4_COLE 0x1 /* collision status enable */ +#define BCR4_JABE 0x2 /* jabber status enable */ +#define BCR4_RCVE 0x4 /* receive status enable */ +#define BCR4_RXPOLE 0x8 /* receive polarity status enable */ +#define BCR4_XMTE 0x10 /* transmit status enable */ +#define BCR4_RCVME 0x20 /* receive match status enable */ +#define BCR4_LNKSTE 0x40 /* link status enable */ +#define BCR4_PSE 0x80 /* pulse stretcher enable */ +#define BCR4_FDLSE 0x100 /* full-duplex link status enable */ +#define BCR4_MPSE 0x200 /* magic packet status enable */ +#define BCR4_LEDDIS 0x2000 /* led disable */ +#define BCR4_LEDPOL 0x4000 /* led polarity */ +#define BCR4_LEDOUT 0x8000 /* led output pin value */ + +/* BCR5 bits */ +#define BCR5_COLE 0x1 /* collision status enable */ +#define BCR5_JABE 0x2 /* jabber status enable */ +#define BCR5_RCVE 0x4 /* receive status enable */ +#define BCR5_RXPOLE 0x8 /* receive polarity status enable */ +#define BCR5_XMTE 0x10 /* transmit status enable */ +#define BCR5_RCVME 0x20 /* receive match status enable */ +#define BCR5_LNKSTE 0x40 /* link status enable */ +#define BCR5_PSE 0x80 /* pulse stretcher enable */ +#define BCR5_FDLSE 0x100 /* full-duplex link status enable */ +#define BCR5_MPSE 0x200 /* magic packet status enable */ +#define BCR5_LEDDIS 0x2000 /* led disable */ +#define BCR5_LEDPOL 0x4000 /* led polarity */ +#define BCR5_LEDOUT 0x8000 /* led output pin value */ + +/* BCR6 bits */ +#define BCR6_COLE 0x1 /* collision status enable */ +#define BCR6_JABE 0x2 /* jabber status enable */ +#define BCR6_RCVE 0x4 /* receive status enable */ +#define BCR6_RXPOLE 0x8 /* receive polarity status enable */ +#define BCR6_XMTE 0x10 /* transmit status enable */ +#define BCR6_RCVME 0x20 /* receive match status enable */ +#define BCR6_LNKSTE 0x40 /* link status enable */ +#define BCR6_PSE 0x80 /* pulse stretcher enable */ +#define BCR6_FDLSE 0x100 /* full-duplex link status enable */ +#define BCR6_MPSE 0x200 /* magic packet status enable */ +#define BCR6_LEDDIS 0x2000 /* led disable */ +#define BCR6_LEDPOL 0x4000 /* led polarity */ +#define BCR6_LEDOUT 0x8000 /* led output pin value */ + +/* BCR7 bits */ +#define BCR7_COLE 0x1 /* collision status enable */ +#define BCR7_JABE 0x2 /* jabber status enable */ +#define BCR7_RCVE 0x4 /* receive status enable */ +#define BCR7_RXPOLE 0x8 /* receive polarity status enable */ +#define BCR7_XMTE 0x10 /* transmit status enable */ +#define BCR7_RCVME 0x20 /* receive match status enable */ +#define BCR7_LNKSTE 0x40 /* link status enable */ +#define BCR7_PSE 0x80 /* pulse stretcher enable */ +#define BCR7_FDLSE 0x100 /* full-duplex link status enable */ +#define BCR7_MPSE 0x200 /* magic packet status enable */ +#define BCR7_LEDDIS 0x2000 /* led disable */ +#define BCR7_LEDPOL 0x4000 /* led polarity */ +#define BCR7_LEDOUT 0x8000 /* led output pin value */ + +/* BCR9 bits */ +#define BCR9_FDEN 0x1 /* full-duplex enable */ +#define BCR9_AUIFD 0x2 /* aui full-duplex */ +#define BCR9_FDRPAD 0x4 /* full-duplex runt packet accept disable */ + +/* BCR18 bits */ +#define BCR18_BWRITE 0x20 /* burst write enable */ +#define BCR18_BREADE 0x40 /* burst read enable */ +#define BCR18_DWIO 0x80 /* dword i/o enable */ +#define BCR18_EXTREQ 0x100 /* extended request */ +#define BCR18_MEMCMD 0x200 /* memory command */ + +/* BCR19 bits */ +#define BCR19_EDI 0x1 /* eeprom data in - same as EDO */ +#define BCR19_ED0 0x1 /* eeprom data out - same as EDI */ +#define BCR19_ESK 0x2 /* eeprom serial clock */ +#define BCR19_ECS 0x4 /* eeprom chip select */ +#define BCR19_EEN 0x8 /* eeprom port enable */ +#define BCR19_EEDET 0x2000 /* eeprom detect */ +#define BCR19_PREAD 0x4000 /* eeprom read */ +#define BCR19_PVALID 0x8000 /* eeprom valid */ + +/* BCR20 bits */ +#define BCR20_SSIZE32 0x100 /* 32-bit software size */ +#define BCR20_CSRPCNET 0x200 /* csr pcnet-isa configuration */ +#define BCR20_APERREN 0x400 /* advanced parity error handling enable */ + +/* initialization block for 32-bit software style */ +typedef struct _INITIALIZATION_BLOCK +{ + USHORT MODE; /* card mode (csr15) */ + UCHAR RLEN; /* encoded number of receive descriptor ring entries */ + UCHAR TLEN; /* encoded number of transmit descriptor ring entries */ + UCHAR PADR[6]; /* physical address */ + USHORT RES; /* reserved */ + UCHAR LADR[8]; /* logical address */ + ULONG RDRA; /* receive descriptor ring address */ + ULONG TDRA; /* transmit descriptor ring address */ +} INITIALIZATION_BLOCK, *PINITIALIZATION_BLOCK; + +/* receive descriptor, software stle 2 (32-bit) */ +typedef struct _RECEIVE_DESCRIPTOR +{ + ULONG RBADR; /* receive buffer address */ + USHORT BCNT; /* two's compliment buffer byte count - NOTE: always OR with 0xf000 */ + UCHAR FLAGS; /* flags - always and with 0xfff0 */ + USHORT MCNT; /* message byte count ; always AND with 0x0fff */ + UCHAR RPC; /* runt packet count */ + UCHAR RCC; /* receive collision count */ + ULONG RES; /* resereved */ +} RECEIVE_DESCRIPTOR, *PRECEIVE_DESCRIPTOR; + +/* receive descriptor flags */ +#define RD_BAM 0x10 /* broadcast address match */ +#define RD_LAFM 0x20 /* logical address filter match */ +#define RD_PAM 0x40 /* physical address match */ +#define RD_BPE 0x80 /* bus parity error */ +#define RD_ENP 0x100 /* end of packet */ +#define RD_STP 0x200 /* start of packet */ +#define RD_BUFF 0x400 /* buffer error */ +#define RD_CRC 0x800 /* crc error */ +#define RD_OFLO 0x1000 /* overflow error */ +#define RD_FRAM 0x2000 /* framing error */ +#define RD_ERR 0x4000 /* an error bit is set */ +#define RD_OWN 0x8000 /* buffer ownership (0=host, 1=nic) */ + +/* transmit descriptor, software style 2 */ +typedef struct _TRANSMIT_DESCRIPTOR +{ + ULONG TBADR; /* transmit buffer address */ + USHORT BCNT; /* two's compliment buffer byte count - OR with 0xf000 */ + USHORT FLAGS; /* flags */ + USHORT TRC; /* transmit retry count (AND with 0x000f */ + USHORT FLAGS2; /* more flags */ + ULONG RES; /* reserved */ +} TRANSMIT_DESCRIPTOR, *PTRANSMIT_DESCRIPTOR; + +/* transmit descriptor flags */ +#define TD1_BPE 0x80 /* bus parity error */ +#define TD1_ENP 0x100 /* end of packet */ +#define TD1_STP 0x200 /* start of packet */ +#define TD1_DEF 0x400 /* frame transmission deferred */ +#define TD1_ONE 0x800 /* exactly one retry was needed for transmission */ +#define TD1_MORE 0x1000 /* more than 1 transmission retry required - same as LTINT */ +#define TD1_LTINT 0x1000 /* suppress transmit success interrupt - same as MORE */ +#define TD1_ADD_FCS 0x2000 /* force fcs generation - same as NO_FCS */ +#define TD1_NO_FCS 0x2000 /* prevent fcs generation - same as ADD_FCS */ +#define TD1_ERR 0x4000 /* an error bit is set */ +#define TD1_OWN 0x8000 /* buffer ownership */ + +/* transmit descriptor flags2 flags */ +#define TD2_RTRY 0x400 /* retry error */ +#define TD2_LCAR 0x800 /* loss of carrier */ +#define TD2_LCOL 0x1000 /* late collision */ +#define TD2_EXDEF 0x2000 /* excessive deferral */ +#define TD2_UFLO 0x4000 /* buffer underflow */ +#define TD2_BUFF 0x8000 /* buffer error */ + +