From a072e1310958feb09a4ef9b87dc5593c461da60c Mon Sep 17 00:00:00 2001 From: Joerg Sonnenberger Date: Sat, 28 Aug 2004 15:08:02 +0000 Subject: [PATCH] Add support for Nforce onboard ethernet. This is the content of net/nvnet. Wrapper-written-by: Quinton Dolon In-correspondenc-with: Nick Triantos (NVidia) --- sys/contrib/dev/nv/NVLicense.txt | 121 +++ sys/contrib/dev/nv/README | 5 + sys/contrib/dev/nv/adapter.h | 414 ++++++++ sys/contrib/dev/nv/basetype.h | 41 + sys/contrib/dev/nv/nvnetlib.o.uu | 481 +++++++++ sys/contrib/dev/nv/os.h | 106 ++ sys/contrib/dev/nv/phy.h | 128 +++ sys/dev/netif/Makefile | 4 +- sys/dev/netif/nv/Makefile | 14 + sys/dev/netif/nv/adapter.h.patch | 383 +++++++ sys/dev/netif/nv/basetype.h.patch | 42 + sys/dev/netif/nv/if_nv.c | 1623 +++++++++++++++++++++++++++++ sys/dev/netif/nv/if_nvreg.h | 169 +++ sys/dev/netif/nv/os.h.patch | 62 ++ sys/dev/netif/nv/phy.h.patch | 130 +++ 15 files changed, 3721 insertions(+), 2 deletions(-) create mode 100644 sys/contrib/dev/nv/NVLicense.txt create mode 100644 sys/contrib/dev/nv/README create mode 100644 sys/contrib/dev/nv/adapter.h create mode 100644 sys/contrib/dev/nv/basetype.h create mode 100644 sys/contrib/dev/nv/nvnetlib.o.uu create mode 100644 sys/contrib/dev/nv/os.h create mode 100644 sys/contrib/dev/nv/phy.h create mode 100644 sys/dev/netif/nv/Makefile create mode 100644 sys/dev/netif/nv/adapter.h.patch create mode 100644 sys/dev/netif/nv/basetype.h.patch create mode 100644 sys/dev/netif/nv/if_nv.c create mode 100644 sys/dev/netif/nv/if_nvreg.h create mode 100644 sys/dev/netif/nv/os.h.patch create mode 100644 sys/dev/netif/nv/phy.h.patch diff --git a/sys/contrib/dev/nv/NVLicense.txt b/sys/contrib/dev/nv/NVLicense.txt new file mode 100644 index 0000000000..04aca9e17f --- /dev/null +++ b/sys/contrib/dev/nv/NVLicense.txt @@ -0,0 +1,121 @@ + License For Customer Use of NVIDIA Software + + +IMPORTANT NOTICE -- READ CAREFULLY: This License For Customer Use of +NVIDIA Software ("LICENSE") is the agreement which governs use of the +software of NVIDIA Corporation and its subsidiaries ("NVIDIA") downloadable +herefrom, including computer software and associated printed materials +("SOFTWARE"). By downloading, installing, copying, or otherwise using the +SOFTWARE, you agree to be bound by the terms of this LICENSE. If you do not +agree to the terms of this LICENSE, do not download the SOFTWARE. + +RECITALS + +Use of NVIDIA's products requires three elements: the SOFTWARE, the +hardware on a graphics controller board, and a personal computer. The +SOFTWARE is protected by copyright laws and international copyright treaties, +as well as other intellectual property laws and treaties. The SOFTWARE is not +sold, and instead is only licensed for use, strictly in accordance with this +document. The hardware is protected by various patents, and is sold, but this +agreement does not cover that sale, since it may not necessarily be sold as a +package with the SOFTWARE. This agreement sets forth the terms and conditions +of the SOFTWARE LICENSE only. + +1. DEFINITIONS + +1.1 Customer. Customer means the entity or individual that downloads the +SOFTWARE. + +2. GRANT OF LICENSE + +2.1 Rights and Limitations of Grant. NVIDIA hereby grants Customer the +following non-exclusive, non-transferable right to use the SOFTWARE, with the +following limitations: + +2.1.1 Rights. Customer may install and use one copy of the SOFTWARE on a +single computer, and except for making one back-up copy of the Software, may +not otherwise copy the SOFTWARE. This LICENSE of SOFTWARE may not be shared +or used concurrently on different computers. + +2.1.2 Linux/FreeBSD Exception. Notwithstanding the foregoing terms of +Section 2.1.1, SOFTWARE designed exclusively for use on the Linux or +FreeBSD operating systems, or other operating systems derived from the +source code to these operating systems, may be copied and redistributed, +provided that the binary files thereof are not modified in any way +(except for unzipping of compressed files). + +2.1.3 Limitations. + +No Reverse Engineering. Customer may not reverse engineer, decompile, or +disassemble the SOFTWARE, nor attempt in any other manner to obtain the +source code. + +No Separation of Components. The SOFTWARE is licensed as a single product. +Its component parts may not be separated for use on more than one computer, +nor otherwise used separately from the other parts. + +No Rental. Customer may not rent or lease the SOFTWARE to someone else. + +3. TERMINATION + +This LICENSE will automatically terminate if Customer fails to comply with +any of the terms and conditions hereof. In such event, Customer must +destroy all copies of the SOFTWARE and all of its component parts. + +Defensive Suspension. If Customer commences or participates in any +legal proceeding against NVIDIA, then NVIDIA may, in its sole +discretion, suspend or terminate all license grants and any other rights +provided under this LICENSE during the pendency of such legal +proceedings. + +4. COPYRIGHT + +All title and copyrights in and to the SOFTWARE (including but not limited to +all images, photographs, animations, video, audio, music, text, and other +information incorporated into the SOFTWARE), the accompanying printed +materials, and any copies of the SOFTWARE, are owned by NVIDIA, or its +suppliers. The SOFTWARE is protected by copyright laws and international +treaty provisions. Accordingly, Customer is required to treat the SOFTWARE +like any other copyrighted material, except as otherwise allowed pursuant to +this LICENSE and that it may make one copy of the SOFTWARE solely for backup +or archive purposes. + +5. APPLICABLE LAW + +This agreement shall be deemed to have been made in, and shall be construed +pursuant to, the laws of the State of California. The United +Nations Convention on Contracts for the International Sale of Goods is +specifically disclaimed. + +6. DISCLAIMER OF WARRANTIES AND LIMITATION ON LIABILITY + +6.1 No Warranties. TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE +LAW, THE SOFTWARE IS PROVIDED "AS IS" AND NVIDIA AND ITS SUPPLIERS +DISCLAIM ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING, BUT +NOT LIMITED TO, IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. + +6.2 No Liability for Consequential Damages. TO THE MAXIMUM EXTENT +PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL NVIDIA OR ITS SUPPLIERS +BE LIABLE FOR ANY SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL +DAMAGES WHATSOEVER (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS +OF BUSINESS PROFITS, BUSINESS INTERRUPTION, LOSS OF BUSINESS INFORMATION, +OR ANY OTHER PECUNIARY LOSS) ARISING OUT OF THE USE OF OR INABILITY +TO USE THE SOFTWARE, EVEN IF NVIDIA HAS BEEN ADVISED OF THE POSSIBILITY +OF SUCH DAMAGES. + +7. MISCELLANEOUS + +The United Nations Convention on Contracts for the International Sale of Goods +is specifically disclaimed. If any provision of this LICENSE is inconsistent +with, or cannot be fully enforced under, the law, such provision will be +construed as limited to the extent necessary to be consistent with and fully +enforceable under the law. This agreement is the final, complete and +exclusive agreement between the parties relating to the subject matter hereof, +and supersedes all prior or contemporaneous understandings and agreements +relating to such subject matter, whether oral or written. Customer agrees +that it will not ship, transfer or export the SOFTWARE into any country, or +use the SOFTWARE in any manner, prohibited by the United States Bureau of +Export Administration or any export laws, restrictions or regulations. This +LICENSE may only be modified in writing signed by an authorized officer of +NVIDIA. diff --git a/sys/contrib/dev/nv/README b/sys/contrib/dev/nv/README new file mode 100644 index 0000000000..368fc0c17d --- /dev/null +++ b/sys/contrib/dev/nv/README @@ -0,0 +1,5 @@ +This directory include the NVnet part of Nvidia's nforce driver +collection for Linux. They are directly copied from the archive at +http://download.nvidia.com/XFree86/nforce/1.0-20031214/ + +For copyright and license information, read NVLicense.html. diff --git a/sys/contrib/dev/nv/adapter.h b/sys/contrib/dev/nv/adapter.h new file mode 100644 index 0000000000..41670ac5df --- /dev/null +++ b/sys/contrib/dev/nv/adapter.h @@ -0,0 +1,414 @@ +/* + FILE: adapter.h + DATE: 2/7/00 + + This file contains the hardware interface to the ethernet adapter. +*/ + +#ifndef _ADAPTER_H_ +#define _ADAPTER_H_ + +#ifdef __cplusplus +extern "C" { +#endif + +#define HDA_VERSION_STRING "HDR A: $Revision: #47 $" + +////////////////////////////////////////////////////////////////// +// For the set and get configuration calls. +typedef struct _ADAPTER_CONFIG +{ + ULONG ulFlags; +} ADAPTER_CONFIG, *PADAPTER_CONFIG; +////////////////////////////////////////////////////////////////// + +#if defined(_WIN32) +////////////////////////////////////////////////////////////////// +// For the ADAPTER_Write1 call. +/* This scatter gather list should be same as defined in ndis.h by MS. + For ULONG_PTR MS header file says that it will be of same size as + pointer. It has been defined to take care of casting between differenet + sizes. +*/ +typedef struct _NVSCATTER_GATHER_ELEMENT { + ULONG PhysLow; + ULONG PhysHigh; + ULONG Length; + void *Reserved; +} NVSCATTER_GATHER_ELEMENT, *PNVSCATTER_GATHER_ELEMENT; + +#pragma warning(disable:4200) +typedef struct _NVSCATTER_GATHER_LIST { + ULONG NumberOfElements; + void *Reserved; + NVSCATTER_GATHER_ELEMENT Elements[]; +} NVSCATTER_GATHER_LIST, *PNVSCATTER_GATHER_LIST; +#pragma warning(default:4200) + +typedef struct _ADAPTER_WRITE_DATA1 +{ + ULONG ulTotalLength; + PVOID pvID; + UCHAR uc8021pPriority; + PNVSCATTER_GATHER_LIST pNVSGL; +} ADAPTER_WRITE_DATA1, *PADAPTER_WRITE_DATA1; + +#endif + +// For the ADAPTER_Write call. +typedef struct _ADAPTER_WRITE_ELEMENT +{ + PVOID pPhysical; + ULONG ulLength; +} ADAPTER_WRITE_ELEMENT, *PADAPTER_WRITE_ELEMENT; + +// pvID is a value that will be passed back into OSAPI.pfnPacketWasSent +// when the transmission completes. if pvID is NULL, the ADAPTER code +// assumes the caller does not want the pfnPacketWasSent callback. +typedef struct _ADAPTER_WRITE_DATA +{ + ULONG ulNumberOfElements; + ULONG ulTotalLength; + PVOID pvID; + UCHAR uc8021pPriority; + ADAPTER_WRITE_ELEMENT sElement[100]; +} ADAPTER_WRITE_DATA, *PADAPTER_WRITE_DATA; +////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////// +// For the ADAPTER_Read call. +typedef struct _ADAPTER_READ_ELEMENT +{ + PVOID pPhysical; + ULONG ulLength; +} ADAPTER_READ_ELEMENT, *PADAPTER_READ_ELEMENT; + +typedef struct _ADAPTER_READ_DATA +{ + ULONG ulNumberOfElements; + ULONG ulTotalLength; + PVOID pvID; + ULONG ulFilterMatch; + ADAPTER_READ_ELEMENT sElement[10]; +} ADAPTER_READ_DATA, *PADAPTER_READ_DATA; + +// The ulFilterMatch flag can be a logical OR of the following +#define ADREADFL_UNICAST_MATCH 0x00000001 +#define ADREADFL_MULTICAST_MATCH 0x00000002 +#define ADREADFL_BROADCAST_MATCH 0x00000004 +////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////// +// For the ADAPTER_GetStatistics call. +#define MAX_TRANSMIT_COLISION_STATS 16 +typedef struct _ADAPTER_STATS +{ + ULONG ulSuccessfulTransmissions; + ULONG ulFailedTransmissions; + ULONG ulRetryErrors; + ULONG ulUnderflowErrors; + ULONG ulLossOfCarrierErrors; + ULONG ulLateCollisionErrors; + ULONG ulDeferredTransmissions; + ULONG ulExcessDeferredTransmissions; + ULONG aulSuccessfulTransmitsAfterCollisions[MAX_TRANSMIT_COLISION_STATS]; + + ULONG ulMissedFrames; + ULONG ulSuccessfulReceptions; + ULONG ulFailedReceptions; + ULONG ulCRCErrors; + ULONG ulFramingErrors; + ULONG ulOverFlowErrors; + ULONG ulFrameErrorsPrivate; //Not for public. + ULONG ulNullBufferReceivePrivate; //Not for public, These are the packets which we didn't indicate to OS + + //interrupt related statistics + ULONG ulRxInterrupt; + ULONG ulRxInterruptUnsuccessful; + ULONG ulTxInterrupt; + ULONG ulTxInterruptUnsuccessful; + ULONG ulPhyInterrupt; +} ADAPTER_STATS, *PADAPTER_STATS; +////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////// +// For the ADAPTER_GetPowerCapabilities call. +typedef struct _ADAPTER_POWERCAPS +{ + ULONG ulPowerFlags; + ULONG ulMagicPacketWakeUpFlags; + ULONG ulPatternWakeUpFlags; + ULONG ulLinkChangeWakeUpFlags; + int iMaxWakeUpPatterns; +} ADAPTER_POWERCAPS, *PADAPTER_POWERCAPS; + +// For the ADAPTER_GetPowerState and ADAPTER_SetPowerState call. +typedef struct _ADAPTER_POWERSTATE +{ + ULONG ulPowerFlags; + ULONG ulMagicPacketWakeUpFlags; + ULONG ulPatternWakeUpFlags; + ULONG ulLinkChangeWakeUpFlags; +} ADAPTER_POWERSTATE, *PADAPTER_POWERSTATE; + +// Each of the flag fields in the POWERCAPS structure above can have +// any of the following bitflags set giving the capabilites of the +// adapter. In the case of the wake up fields, these flags mean that +// wake up can happen from the specified power state. + +// For the POWERSTATE structure, the ulPowerFlags field should just +// have one of these bits set to go to that particular power state. +// The WakeUp fields can have one or more of these bits set to indicate +// what states should be woken up from. +#define POWER_STATE_D0 0x00000001 +#define POWER_STATE_D1 0x00000002 +#define POWER_STATE_D2 0x00000004 +#define POWER_STATE_D3 0x00000008 + +#define POWER_STATE_ALL (POWER_STATE_D0 | \ + POWER_STATE_D1 | \ + POWER_STATE_D2 | \ + POWER_STATE_D3) +////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////// +// The ADAPTER_GetPacketFilterCaps call returns a ULONG that can +// have the following capability bits set. +#define ACCEPT_UNICAST_PACKETS 0x00000001 +#define ACCEPT_MULTICAST_PACKETS 0x00000002 +#define ACCEPT_BROADCAST_PACKETS 0x00000004 +#define ACCEPT_ALL_PACKETS 0x00000008 + +#define ETH_LENGTH_OF_ADDRESS 6 + +// The ADAPTER_SetPacketFilter call uses this structure to know what +// packet filter to set. The ulPacketFilter field can contain some +// union of the bit flags above. The acMulticastMask array holds a +// 48 bit MAC address mask with a 0 in every bit position that should +// be ignored on compare and a 1 in every bit position that should +// be taken into account when comparing to see if the destination +// address of a packet should be accepted for multicast. +typedef struct _PACKET_FILTER +{ + ULONG ulFilterFlags; + UCHAR acMulticastAddress[ETH_LENGTH_OF_ADDRESS]; + UCHAR acMulticastMask[ETH_LENGTH_OF_ADDRESS]; +} PACKET_FILTER, *PPACKET_FILTER; +////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////// +// A WAKE_UP_PATTERN is a 128-byte pattern that the adapter can +// look for in incoming packets to decide when to wake up. Higher- +// level protocols can use this to, for example, wake up the +// adapter whenever it sees an IP packet that is addressed to it. +// A pattern consists of 128 bits of byte masks that indicate +// which bytes in the packet are relevant to the pattern, plus +// values for each byte. +#define WAKE_UP_PATTERN_SIZE 128 + +typedef struct _WAKE_UP_PATTERN +{ + ULONG aulByteMask[WAKE_UP_PATTERN_SIZE/32]; + UCHAR acData[WAKE_UP_PATTERN_SIZE]; +} WAKE_UP_PATTERN, *PWAKE_UP_PATTERN; + + + +// +// +// Adapter offload +// +typedef struct _ADAPTER_OFFLOAD { + + ULONG Type; + ULONG Value0; + +} ADAPTER_OFFLOAD, *PADAPTER_OFFLOAD; + +#define ADAPTER_OFFLOAD_VLAN 0x00000001 +#define ADAPTER_OFFLOAD_IEEE802_1P 0x00000002 +#define ADAPTER_OFFLOAD_IEEE802_1PQ_PAD 0x00000004 + +////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////// +// The functional typedefs for the ADAPTER Api +typedef int (* PFN_ADAPTER_CLOSE) (PVOID pvContext); +typedef int (* PFN_ADAPTER_INIT) (PVOID pvContext, USHORT usForcedSpeed, UCHAR ucForceDpx, UCHAR ucForceMode, UINT *puiLinkState); +typedef int (* PFN_ADAPTER_DEINIT) (PVOID pvContext, UCHAR ucIsPowerDown); +typedef int (* PFN_ADAPTER_START) (PVOID pvContext); +typedef int (* PFN_ADAPTER_STOP) (PVOID pvContext, UCHAR ucIsPowerDown); +typedef int (* PFN_ADAPTER_QUERY_WRITE_SLOTS) (PVOID pvContext); +typedef int (* PFN_ADAPTER_WRITE) (PVOID pvContext, ADAPTER_WRITE_DATA *pADWriteData); + +#if defined(_WIN32) +typedef int (* PFN_ADAPTER_WRITE1) (PVOID pvContext, ADAPTER_WRITE_DATA1 *pADWriteData1); +#endif + +typedef int (* PFN_ADAPTER_QUERY_INTERRUPT) (PVOID pvContext); +typedef int (* PFN_ADAPTER_HANDLE_INTERRUPT) (PVOID pvContext); +typedef int (* PFN_ADAPTER_DISABLE_INTERRUPTS) (PVOID pvContext); +typedef int (* PFN_ADAPTER_ENABLE_INTERRUPTS) (PVOID pvContext); +typedef int (* PFN_ADAPTER_CLEAR_INTERRUPTS) (PVOID pvContext); +typedef int (* PFN_ADAPTER_CLEAR_TX_DESC) (PVOID pvContext); +typedef int (* PFN_ADAPTER_GET_LINK_SPEED) (PVOID pvContext); +typedef int (* PFN_ADAPTER_GET_LINK_STATE) (PVOID pvContext, ULONG *pulLinkState); +typedef int (* PFN_ADAPTER_IS_LINK_INITIALIZING) (PVOID pvContext); +typedef int (* PFN_ADAPTER_RESET_PHY_INIT_STATE) (PVOID pvContext); +typedef int (* PFN_ADAPTER_GET_TRANSMIT_QUEUE_SIZE) (PVOID pvContext); +typedef int (* PFN_ADAPTER_GET_RECEIVE_QUEUE_SIZE) (PVOID pvContext); +typedef int (* PFN_ADAPTER_GET_STATISTICS) (PVOID pvContext, PADAPTER_STATS pADStats); +typedef int (* PFN_ADAPTER_GET_POWER_CAPS) (PVOID pvContext, PADAPTER_POWERCAPS pADPowerCaps); +typedef int (* PFN_ADAPTER_GET_POWER_STATE) (PVOID pvContext, PADAPTER_POWERSTATE pADPowerState); +typedef int (* PFN_ADAPTER_SET_POWER_STATE) (PVOID pvContext, PADAPTER_POWERSTATE pADPowerState); +typedef int (* PFN_ADAPTER_GET_PACKET_FILTER_CAPS) (PVOID pvContext); +typedef int (* PFN_ADAPTER_SET_PACKET_FILTER) (PVOID pvContext, PPACKET_FILTER pPacketFilter); +typedef int (* PFN_ADAPTER_SET_WAKE_UP_PATTERN) (PVOID pvContext, int iPattern, PWAKE_UP_PATTERN pPattern); +typedef int (* PFN_ADAPTER_ENABLE_WAKE_UP_PATTERN) (PVOID pvContext, int iPattern, int iEnable); +typedef int (* PFN_SET_NODE_ADDRESS) (PVOID pvContext, UCHAR *pNodeAddress); +typedef int (* PFN_GET_NODE_ADDRESS) (PVOID pvContext, UCHAR *pNodeAddress); +typedef int (* PFN_GET_ADAPTER_INFO) (PVOID pvContext, PVOID pVoidPtr, int iType, int *piLength); +typedef int (* PFN_ADAPTER_READ_PHY) (PVOID pvContext, ULONG ulPhyAddr, ULONG ulPhyReg, ULONG *pulValue); +typedef int (* PFN_ADAPTER_WRITE_PHY) (PVOID pvContext, ULONG ulPhyAddr, ULONG ulPhyReg, ULONG ulValue); +typedef void(* PFN_ADAPTER_SET_SPPED_DUPLEX) (PVOID pvContext); +typedef int (*PFN_REGISTER_OFFLOAD) (PVOID pvContext, PADAPTER_OFFLOAD pOffload); +typedef int (*PFN_DEREGISTER_OFFLOAD) (PVOID pvContext, PADAPTER_OFFLOAD pOffload); +typedef int (*PFN_RX_BUFF_READY) (PVOID pvContext, PMEMORY_BLOCK pMemBlock, PVOID pvID); + +typedef struct _ADAPTER_API +{ + // The adapter context + PVOID pADCX; + + // The adapter interface + PFN_ADAPTER_CLOSE pfnClose; + PFN_ADAPTER_INIT pfnInit; + PFN_ADAPTER_DEINIT pfnDeinit; + PFN_ADAPTER_START pfnStart; + PFN_ADAPTER_STOP pfnStop; + PFN_ADAPTER_QUERY_WRITE_SLOTS pfnQueryWriteSlots; + PFN_ADAPTER_WRITE pfnWrite; + +#if defined(_WIN32) + PFN_ADAPTER_WRITE1 pfnWrite1; +#endif + PFN_ADAPTER_QUERY_INTERRUPT pfnQueryInterrupt; + PFN_ADAPTER_HANDLE_INTERRUPT pfnHandleInterrupt; + PFN_ADAPTER_DISABLE_INTERRUPTS pfnDisableInterrupts; + PFN_ADAPTER_ENABLE_INTERRUPTS pfnEnableInterrupts; + PFN_ADAPTER_CLEAR_INTERRUPTS pfnClearInterrupts; + PFN_ADAPTER_CLEAR_TX_DESC pfnClearTxDesc; + PFN_ADAPTER_GET_LINK_SPEED pfnGetLinkSpeed; + PFN_ADAPTER_GET_LINK_STATE pfnGetLinkState; + PFN_ADAPTER_IS_LINK_INITIALIZING pfnIsLinkInitializing; + PFN_ADAPTER_RESET_PHY_INIT_STATE pfnResetPhyInitState; + PFN_ADAPTER_GET_TRANSMIT_QUEUE_SIZE pfnGetTransmitQueueSize; + PFN_ADAPTER_GET_RECEIVE_QUEUE_SIZE pfnGetReceiveQueueSize; + PFN_ADAPTER_GET_STATISTICS pfnGetStatistics; + PFN_ADAPTER_GET_POWER_CAPS pfnGetPowerCaps; + PFN_ADAPTER_GET_POWER_STATE pfnGetPowerState; + PFN_ADAPTER_SET_POWER_STATE pfnSetPowerState; + PFN_ADAPTER_GET_PACKET_FILTER_CAPS pfnGetPacketFilterCaps; + PFN_ADAPTER_SET_PACKET_FILTER pfnSetPacketFilter; + PFN_ADAPTER_SET_WAKE_UP_PATTERN pfnSetWakeUpPattern; + PFN_ADAPTER_ENABLE_WAKE_UP_PATTERN pfnEnableWakeUpPattern; + PFN_SET_NODE_ADDRESS pfnSetNodeAddress; + PFN_GET_NODE_ADDRESS pfnGetNodeAddress; + PFN_GET_ADAPTER_INFO pfnGetAdapterInfo; + PFN_ADAPTER_SET_SPPED_DUPLEX pfnSetSpeedDuplex; + PFN_ADAPTER_READ_PHY pfnReadPhy; + PFN_ADAPTER_WRITE_PHY pfnWritePhy; + PFN_REGISTER_OFFLOAD pfnRegisterOffload; + PFN_DEREGISTER_OFFLOAD pfnDeRegisterOffload; + PFN_RX_BUFF_READY pfnRxBuffReady; +} ADAPTER_API, *PADAPTER_API; +////////////////////////////////////////////////////////////////// + +#define MAX_PACKET_TO_ACCUMULATE 16 + +typedef struct _ADAPTER_OPEN_PARAMS +{ + PVOID pOSApi; //pointer to OSAPI structure passed from higher layer + PVOID pvHardwareBaseAddress; //memory mapped address passed from higher layer + ULONG ulPollInterval; //poll interval in micro seconds. Used in polling mode + ULONG MaxDpcLoop; //Maximum number of times we loop to in function ADAPTER_HandleInterrupt + ULONG MaxRxPkt; //Maximum number of packet we process each time in function UpdateReceiveDescRingData + ULONG MaxTxPkt; //Maximum number of packet we process each time in function UpdateTransmitDescRingData + ULONG MaxRxPktToAccumulate; //maximum number of rx packet we accumulate in UpdateReceiveDescRingData before + //indicating packets to OS. + ULONG SentPacketStatusSuccess; //Status returned from adapter layer to higher layer when packet was sent successfully + ULONG SentPacketStatusFailure; ////Status returned from adapter layer to higher layer when packet send was unsuccessful + ULONG SetForcedModeEveryNthRxPacket; //NOT USED: For experiment with descriptor based interrupt + ULONG SetForcedModeEveryNthTxPacket; //NOT USED: For experiment with descriptor based interrupt + ULONG RxForcedInterrupt; //NOT USED: For experiment with descriptor based interrupt + ULONG TxForcedInterrupt; //NOT USED: For experiment with descriptor based interrupt + ULONG DeviceId; //Of MAC + ULONG PollIntervalInusForThroughputMode; //Of MAC +}ADAPTER_OPEN_PARAMS, *PADAPTER_OPEN_PARAMS; + +////////////////////////////////////////////////////////////////// +// This is the one function in the adapter interface that is publicly +// available. The rest of the interface is returned in the pAdapterApi. +// The first argument needs to be cast to a OSAPI structure pointer. +// The second argument should be cast to a ADPATER_API structure pointer. +int ADAPTER_Open (PADAPTER_OPEN_PARAMS pAdapterOpenParams, PVOID *pvpAdapterApi, ULONG *pulPhyAddr); + +////////////////////////////////////////////////////////////////// + + + +////////////////////////////////////////////////////////////////// +// Here are the error codes the adapter function calls return. +#define ADAPTERERR_NONE 0x0000 +#define ADAPTERERR_COULD_NOT_ALLOC_CONTEXT 0x0001 +#define ADAPTERERR_COULD_NOT_CREATE_CONTEXT 0x0002 +#define ADAPTERERR_COULD_NOT_OPEN_PHY 0x0003 +#define ADAPTERERR_TRANSMIT_QUEUE_FULL 0x0004 +#define ADAPTERERR_COULD_NOT_INIT_PHY 0x0005 +#define ADAPTERERR_PHYS_SIZE_SMALL 0x0006 +////////////////////////////////////////////////////////////////// + +#define REDUCE_LENGTH_BY 48 +#define EXTRA_WRITE_SLOT_TO_REDUCE_PER_SEND 3 +#define MAX_TX_DESCS 256 //32 //256 //512 //64 //256 + +typedef struct _TX_INFO_ADAP +{ + ULONG NoOfDesc; + PVOID pvVar2; +}TX_INFO_ADAP, *PTX_INFO_ADAP; + +#define WORKAROUND_FOR_MCP3_TX_STALL + +#ifdef WORKAROUND_FOR_MCP3_TX_STALL +int ADAPTER_WorkaroundTXHang(PVOID pvContext); +#endif + +//#define TRACK_INIT_TIME + +#ifdef TRACK_INIT_TIME +//This routine is defined in entry.c adapter doesn't link int64.lib +//We defined here so that its easy to use it in phy as well as mswin + +#define MAX_PRINT_INDEX 32 +extern void PrintTime(ULONG ulIndex); +#define PRINT_INIT_TIME(_a) PrintTime((_a)) +#else +#define PRINT_INIT_TIME(_a) +#endif + +#ifdef __cplusplus +} // extern "C" +#endif + +#endif // _ADAPTER_H_ diff --git a/sys/contrib/dev/nv/basetype.h b/sys/contrib/dev/nv/basetype.h new file mode 100644 index 0000000000..be2a99f98a --- /dev/null +++ b/sys/contrib/dev/nv/basetype.h @@ -0,0 +1,41 @@ +/* + FILE: basetype.h + DATE: 2/7/00 + + This file contains the basetypes used by the network driver code. +*/ + +#ifndef _BASETYPE_H_ +#define _BASETYPE_H_ + +#define HDB_VERSION_STRING "HDR B: $Revision: #4 $" + +// Fundamental data types +// UCHAR 8 bit unsigned +// UINT either 16bit or 32bit unsigned depending upon compiler +// USHORT 16 bit unsigned +// ULONG 32 bit unsigned + +typedef unsigned char UCHAR; +typedef unsigned int UINT; +typedef unsigned short USHORT; +typedef unsigned long ULONG; +#define VOID void + +// Constructed types +typedef VOID *PVOID; + +// These are USEFUL "types" +#ifndef NULL +#define NULL 0 +#endif + +#ifndef TRUE +#define TRUE 1 +#endif + +#ifndef FALSE +#define FALSE 0 +#endif + +#endif // _BASETYPE_H_ diff --git a/sys/contrib/dev/nv/nvnetlib.o.uu b/sys/contrib/dev/nv/nvnetlib.o.uu new file mode 100644 index 0000000000..008ed10d73 --- /dev/null +++ b/sys/contrib/dev/nv/nvnetlib.o.uu @@ -0,0 +1,481 @@ +begin 644 nvnetlib.o +M?T5,1@$!`0````````````$``P`!``````````````"00````````#0````` +M`"@`#``)`````````````````%6)Y8/L$%=64XMU"(L^BT4,QP``````QT7\ +MJ!,``,=%^`````"-1?10BP=0BT<$_]"#Q`B%P'4*N`$```#I'P<``(M=](E; +M!(M%^(E#"(M%_(E##(7V#X6'````QX-X$P``!0```,>#?!,``$````#'@X`3 +M`````0``QX.($P```0```,>#C!,```````#'@X03```'````QX-T$P`````` +M`,>#I!,``/0!``#'@Y`3````````QX.4$P```````,>#F!,```````#'@YP3 +M````````QX.@$P``PP$``.GR````BT8,B8-X$P``A#>!,```4```"+ +M1A")@WP3``"%P'4*QX-\$P``0````(M&%(F#@!,``(7`=0K'@X`3`````0`` +MBT8#A!,```<```"+1@B) +M@W03``"+5B2)DY`3``"+1BB)@Y03``"+1BR)@Y@3``"%P'0.A=)U"L>#D!,` +M``<```"+1C")@YP3``"%P'03@[N4$P```'4*QX.4$P``!P```(M&-(F#H!,` +M`(7`=0K'@Z`3``##`0``BT8XB8.D$P``A#I!,``/0!``")N[````"+ +M1@2)`\=#%`````#'0Q@`````QT,<`````,=#(`````#'0R0`````QT,H```` +M`,=#+`````#'0S``````@[MT$P```'4/QT,T`````.L-C;8`````QT,T```` +M`,=#.`````#'0SP`````QT-``````,=#1`````#'0T@`````QT-,`````,=# +M4`````#'0U0`````QT-8`````,=#7`````#'0V``````QT-D`````,=#:``` +M``#'0VP`````QT-P`````,=#=`````#'0W@`````QT-\`````,>#@``````` +M``#'@X0`````````QX.(`````````,>#C`````````#'@Y``````````QX.4 +M`````````,>#F`````````#'@YP`````````QX.@`````````(E;$(U+$(M5 +M#(D*C8,L`P``4&H`BP=0BT=0_]"#Q`R%P`^$^@,``,>#]`(````(``#'@P`# +M``!D````@;N@$P``PP$``'4:9L>#%`(`````QX,$`P``7P```.L8D(UT)@!F +MQX,4`@````''@P0#``!'`0``QX,(`P``9P```(.[=!,```!U.FF3I!,``-P% +M``")T/#_`(```(```#K.(VT +M)@````!IDW03``##T`$````(``#'@\P!```!````9L>#U`$` +M``(`9L>#U@$``$``C8/(`0``4(L'4(M'#/_0@\0(A<`/A.4"``"+@\@!``") +M@^@!``"+D\`!``"-1-#XB8/L`0``P>("B9/\`0``QX/X`0```````(V#]`$` +M`%"+!U"+1P3_T(/$"(7`#X2<`@``BX/T`0``B8,``@``B8,$`@``BY/``0`` +MP>("C400_(F#"`(``(/"0(F36!,``,>#5!,```$```"-@U`3``!0BP=0BT<$ +M_]"#Q`B%P`^$2@(``(N#4!,``#'VB?;'!+``````1H/^#W;S,?8[L\`!``!S +M%HN#4!,``&;'1+!`@0!&.[/``0```%BY/``0`` +MP>(#BTWPB10(QX08P`````$```!FQX08R`````(`9L>$&,H```!``(V$`[P` +M``!0BP=0BT<,_]"#Q`B%P`^$N@$``$:#_@=VK,>#P`(````(``#'@[P"```! +M````C8.X`@``4(L'4(M'!/_0@\0(A<`/A(8!``#'@W@"``!`````QX.$`@`` +M``(``,>#@`(```$```!FQX.(`@```@!FQX.*`@``0`"-@WP"``!0BP=0BT<, +M_]"#Q`B%P`^$/`$``(N3?`(``(F3G`(``(N#>`(``,'@`XU$`OB)@Z`"```Q +M]CNS>`(``',;C78`BY.<`@``BX.\`@``B03R1CNS>`(``'+HBXMX`@``P>$" +MB8NP`@``QX.L`@```````(V#J`(``%"+!U"+1P3_T(/$"(7`#X3%````BX.P +M`@``4(N#J`(``%"+!U"+1Q3_T(N#J`(``(F#M`(``(N#L`(``%"+@Z@"``!0 +MBP=0BT<4_]`Q]H/$&#NS>`(``',#*`,````(``")FZ0```#'@Z@`````````QX.L`````````(V#I``` +M`(F#M````(V#)`,``%"-@S0#``!0C8,P`P``4(V#M````%!7Z/S___^%P'05 +MN`4```#K.(VT)@````"X`@```.LJBX,P`P``B8.X````/0#,,@!U"L>#.`,` +M``$```"+DS0#``"+11")$#'`C67D6UY?B>Q=PY"-="8`58GE@^P(5U93BW4( +MA?8/A$P"``"+AK````")1?QJ`%;H_/___X/$"(.^M`````!T&XN&M````(L0 +M4HM`$/_0QX:T`````````(/$!(.^G`(```!T03'_.[YX`@``0BX:<`@`` +MC03X4%;H_/___XN&G`(``&;'1/@&``"+AIP"``!FQT3X!```@\0(1SN^>`(` +M`'+*@[ZH`@```'0IC8:H`@``4(M5_(L"4(M""/_0QX:H`@```````,>&M`(` +M``````"#Q`B#OGP"````=#V-AGP"``!0BU7\BP)0BT(0_]#'AGP"```````` +MQX:<`@```````,>&H`(```````#'AJ0"````````@\0(@[ZX`@```'0?C8:X +M`@``4(M5_(L"4(M""/_0QX:X`@```````(/$"(.^]`$```!T48V&]`$``%"+ +M5?R+`E"+0@C_T,>&]`$```````#'A@`"````````QX8$`@```````,>&"`(` +M``````#'A@P"````````QX80`@```````(/$"(.^R`$```!T/8V&R`$``%"+ +M5?R+`E"+0A#_T,>&R`$```````#'AN@!````````QX;L`0```````,>&\`$` +M``````"#Q`B#OE`3````=!^-AE`3``!0BU7\BP)0BT((_]#'AE`3```````` +M@\0(,?^-AKP```")1?B-M"8`````B?O!XP6+5?B#/!,`=""-A!Z\````4(M5 +M_(L"4(M"$/_0BT7XQP0#`````(/$"$>#_P=VS,>&O`$```````"+EK````"- +M1@10BP)0BT((_]`QP(UE[%M>7XGL7<.-="8`58GE@^P(5U93BT4,9HE%_HI5 +M$(A5_8I%%(A%_(M="(N3L````(E5^(L[:@!3Z/S____'A[``````````QX>T +M`````````,>'N````/_____'A[P```#__P``QX>(`0```````(N#T`$``%"+ +M@^@!``!0BU7XBP)0BT(4_]!J8(V#&`(``%"+5?B+`E"+0A3_T(/$(&HPC8/$ +M`@``4(M5^(L"4(M"%/_0,?:#Q`P[LW@"``!S38N#G`(``&:#?/`&`'P+@YP"``!F +MQT3P!@"`1CNS>`(``'*SBX.<`@``B8.D`@``BX,$`@``B8,,`@``B8,0`@`` +MBX/H`0``B8/P`0``BX/``0``B8/$`0``QX<0`0```````,>'#`$```````#' +MAT0!```4````:@2+5?B+`E"+0AC_T,>'1`$```0```#'1P@`````BX/,`0`` +MB8<``0``BX.``@``B8<$`0``BY/``0``2H'B_P,``(N#>`(``$C!X!`E``#_ +M`PG"B9<(`0``QX<0`0``"@`!`,>'/`$``!``(`#'AT0!````````QX=$`0`` +M`@```#'V@\0(BX$`0```````,>'@`$``!\```#'!_\!``"+AXP!```E_P`` +M`&G(`)`!`+K336(0B@&P>`"B8,H`P``BY.T````#[9%_%`/MD7] +M4`^W1?Y0BP)0BT(H_]"#Q!"+51B#.@!T#XN#M````%*+$%*+0`3K$(N#M``` +M`(M5&%*+$%*+0`C_T(/$"(7`=`JX!0```.GB`0``QX>`````/@\[`(N'B``` +M`(F'B````,>'C````"@`?P"#NS`#````=!''AY`````!!@``ZR^0C70F`(.[ +M7!,```!U"8.[8!,```!T#L>'D````/(%``#K#(GVQX>0````[@4``(N'F``` +M`(F'F````(GZP>H(B?C!Z!`PPHG8P>@(,,*)V,'H$##"=0*R"`^VPH#,?XF' +MG````,>'H`````\'%@#'AZ0````6````@[MT$P```'48BX,(`P``B8,,`P`` +MQX/\`@```@```.L6BX,``P``B8,,`P``QX/\`@```````,>#%`,```````"+ +M@Q`#``")1PS'1P@#````BX,T`P``P>`8)0```!\-```$`(F'B`$``%/H_/__ +M_X/$!(7`=1&+AX@!```-```0`(F'B`$``,>'C`$```4!``#'AX0!```(```` +MQX<``@``<'<``(N';`(``&:%P'T/BX=L`@``@,R`B8=L`@``QX>``0``'P`` +M`,<'_P$``(N';`(``(#,`8F';`(``(-]&`!T38M%&(,X`'1%@(L8`P``!(N# +MM````(L04HM`&/_0B8,@`P``@\0$@_@"=0Z+AX`````D_8F'@````(N#M``` +M`(L04HM`%/_0B8,<`P``,<"-9>Q;7E^)[%W#C;0F`````(V\)P````!5B>6# +M[!175E.+?0B+!XE%_(N7L````(E5^(N'O`$``(/@!\'@!8V$![P```")1?3_ +MA[P!``"+"(E-\(M=](M#"%!1BP)0BT(4_]!J`(M%"%#H_/___XM5_,>"B``` +M`/____^+30B+B0P"``")3>R#Q!2+70@[BQ`"``!T>(UV`(M%[(L0BTH$BS*+ +M7?"-!/.-6/B)1?")6@2%]GXUC78`BP&)`P^W001FB4,$#[=!!H#,@&:)0P:) +MR(/!^#N'Z`$``'4&BX_L`0``3H/#^(7V?\Z+1>R#1>P$.X<(`@``=0F+EP0" +M``")5>R+3>P[CQ`"``!UBXN7R`$``(M=](L#B8?(`0``B1.+E\P!``"+0P2) +MA\P!``")4P2+E\@!``")E^@!``"+A\`!``#!X`.-1`+XB8?L`0``BT7PB8?P +M`0``BX><`@``B8>D`@``BU7\QX(0`0```````,>"#`$```````#'@D0!```4 +M````:@2+3?B+`5"+01C_T(M=_,>#1`$```0```#'0P@`````BX?,`0``B8,` +M`0``BX>``@``B8,$`0``BY?``0``2H'B_P,``(N'>`(``$C!X!`E``#_`PG" +MB9,(`0``QX-$`0```````,>#1`$```(````QVX/$"(M5_(N",`$``(7`?"9J +M!8M-^(L!4(M!&/_00X/$"(M5_(N",`$``(7`?`B!^P\G``!VVHM-"%'H_/__ +M_XM=_,>#1`$```$````QP(UEX%M>7XGL7<.-M@````!5B>6+50B*10R%TG0* +M#[;`4%+H_/___S'`B>Q=PXUV`%6)Y593BUT(A=MT3(NSL````.LVBX,,`@`` +MBQ"#@PP"```$.X,(`@``=0R+@P0"``")@PP"``"+@XP3``!04HL&4(M&)/_0 +M@\0,BX,,`@``.X,0`@``=;PQP(UE^%M>B>Q=PXVV`````(V\)P````!5B>53 +MBUT(B=F+$XN";`(``&:%P'T/BX)L`@``@,R`B8)L`@``BX)L`@``@,P!B8)L +M`@``@[LP`P```'41BX*(`0``#0``$`")@H@!``!1Z/S___]J`U/H_/___S'` +MBUW\B>Q=PXUT)@"-O"<`````58GE@^P(5U93BU4(BT4,B$7_B=>+'XN/L``` +M`(E-^(3`=!6+AS0#``#!X!@E````'PT``!0`ZPN+@X@!```E___O_XF#B`$` +M`%+H_/___\>#1`$```0````Q]H/$!.L!1H'^#R<``'<#1`$```0````QP(UE[%M>7XGL7<.0C;0F```` +M`%6)Y8M%"(.X7!,```!U"8.X8!,```!T"XN`Q`$``(/`_.L'BX#$`0``2(GL +M7<.)]E6)Y8/L'%=64XM]"(L'B47\BU4,BE(,B%7K@[]<$P````^%"0$``(._ +M8!,````/A?P```"+A\0!``"+70P[`P^&WP```(M;"(MU#"L&B8?$`0``BP:) +M`XN7Z`$``(N/\`$``"G1B?%`(``('+`8#__V:) +M7?:%R0^,G0(``(M5^(L"B08/MUH$2V:)7@0/MT7V9HE&!F;'1?8`@(GP@\;X +M.X?H`0``=0:+M^P!``"#1?CX27G(Z6`"``"X!````.EE`@``B?;'1?`````` +MQT7L`````(._7!,```!T"<=%\`(```#K(8._8!,```!T-'00N`(```"`?>L` +M#T1%\(E%\(-]\`!T'(M=#(-[!#MW$X._9!,```!T"O]%\,=%[`$```"+1?"+ +M=0P#!BF'Q`$``(N'\`$``(E%Y(N/Z`$``(N7\`$``"G*P?H#BT7P`P8!PHU" +M_R7_````C33!#[;2P>(#`0KE^@!``#!Z@.-%)5`````B=,#GU`3``"*3>O`X06+AV@3``#!Z`@D +M#PC!B$L"BH=H$P``B$,#`Y=4$P``B19FQT8$`P`/MU7V9HE6!HGP@\;X.X?H +M`0``=0:+M^P!``"+7?B+`XD&9L=&!`L`#[=%]F:)1@;K/(M5^(L"B08/MUH$ +M2V:)7@0/MT7V9HE&!F;'1?8`@(GP@\;X.X?H`0``=0:+M^P!``"#1?CX20^) +MO/[__XM5_,>"1`$```$````QP%M>7XGL7<.-M@````!5B>6+30R+50B+`8/X +M`G0P=PZ#^`%T$.M'C;0F`````(/X!'0KZSG'@EP3```!````BT$$B8)H$P`` +MZRN-="8`QX)@$P```0```.L;C70F`,>"9!,```$```#K"XUT)@"X`@```.L" +M,<")[%W#C78`58GEBT4,BU4(BP"#^`)T,'<.@_@!=!#K1XVT)@````"#^`1T +M*^LYQX)<$P```````,>":!,```````#K*HUV`,>"8!,```````#K&XUT)@#' +M@F03````````ZPN-="8`N`(```#K`C'`B>Q=PXUV`%6)Y5=64XM5"(L:B[*P +M````BT4,J`%T#HN#E````"3^B8.4````BT4,J`)T#HN#A````"3^B8.$```` +M]H(8`P``!'4)@[HD`P```'1#,?_K`4>!_T_#``!W-O9%#`%T"HN#F````*@! +M=1#V10P"=""+@X@```"H`706:@J+!E"+1AC_T(/$".O(C;0F`````&HRBP90 +MBT88_]!J,HL&4(M&&/_0BT4,J`%T"L>#$`$```````"+10RH`G0*QX,,`0`` +M`````#'`C67T6UY?B>Q=PXVT)@````"-O"<`````58GE5E.+30B+50R+&;[H +M`P``]L("=`Z+@X0````,`8F#A````/;"`70^BY&T````BP)0BT(4_]")PKAD +M````@?H`X?4%#T3PB?`E__\```T```$`B8,0`0``BX.4````#`&)@Y0````Q +MP(UE^%M>B>Q=PXVV`````(V\)P````!5B>6+10B+D+0```"+`E"+0B3_T(GL +M7<.0C;0F`````%6)Y8M%"(N0M````(L"4(M"(/_0B>Q=PY"-M"8`````58GE +MBT4(BU4,BXBT````4HL!4(M!'/_0,<")[%W#B?95B>6+10B+D+0```"#N!P# +M``#_=`N+@!P#``#K&XUV`(.X,`,```!T![B`EI@`ZPB+`E"+0A3_T(GL7<.- +M="8`58GEBT4(BX#``0``B>Q=PU6)Y8M%"(N`>`(``(GL7<-5B>6#[`A75E.+ +M=0R+70B+@Q@"``")!HN#'`(``(E&!(N#+`(``(E&"(N#(`(``(E&#(N#*`(` +M`(E&$(N#)`(``(E&%(N#,`(``(E&&(N#-`(``(E&'#')C48@B47\C;LX`@`` +MB7WXC12-`````(M]^(L$.HM]_(D$.D&#^1!RYX/Y#W<0C48@QP2(`````$&# +M^0]V\XN#S`(``(E&8(N#Q`(``(E&9(N#R`(``(E&:(N#V`(``(E&;(N#T`(` +M`(E&<(N#U`(``(E&=(N#/`,``(F&@````(N#0`,``(F&A````(N#1`,``(F& +MB````(N#2`,``(F&C````(N#3`,``(F&D````#'`6UY?B>Q=PU6)Y8M%"(M5 +M#(L`QP(!````BX!H`@``J0```$!T!L<""0```*D````$=`.`"@2I`````G0# +M@`H"QT($#P```,=""`\```#'0@P/````QT(0!0```#'`B>Q=PXVV`````%6) +MY8M%"(M5#(L(BX%L`@``@^`#B0)U",<"`0```.LF@SH!=0O'`@(```#K&8UV +M`(,Z`G4+QP($````ZPF-=@#'`@@```"+@0`"``#'0@0`````J`%T!\="!`$` +M``"H$'0$@$H$`O;$`70$@$H$!/;$$'0$@$H$",=""`````"H`G0'QT((`0`` +M`*@@=`2`2@@"]L0"=`2`2@@$]L0@=`2`2@@(QT(,`````*@$=`?'0@P!```` +MJ$!T!(!*#`+VQ`1T!(!*#`3VQ$!T!(!*#`@QP(GL7<.-=@"-O"<`````58GE +M5E.+10B+30R+,(N&``(``"6(B/__BUD$@^,!B<*#R@&%VP]%PHM9!(/C`HG" +M@\H0A=L/1<*+602#XP2)PH#.`87;#T7"BUD$@^,(B<*`SA"%VP]%PHM9"(/C +M`8G"@\H"A=L/1<*+60B#XP*)PH/*((7;#T7"BUD(@^,$B<*`S@*%VP]%PHM9 +M"(/C"(G"@,X@A=L/1<*+60R#XP&)PH/*!(7;#T7"BUD,@^,"B<*#RD"%VP]% +MPHM9#(/C!(G"@,X$A=L/1<*+60R#XPB)PH#.0(7;#T7"B88``@``BQF#XP$Q +MTH7;#T7"BQF#XP*Z`0```(7;#T7"BQF#XP2Z`@```(7;#T7"BPF#X0BZ`P`` +M`(7)#T7"@,P!B89L`@``,Q=PXUT +M)@!5B>6#[`Q75E.+10B)1?R+,(N>C````(/CWX#+@(M%#(L0@^(!B=@,((72 +M#T78BU4,]@("=&R#RR")UX/'!(/""HE5](N&E````(E%^*@!=`YJ`8M5_%+H +M_/___X/$"(L'#`&)AK````"+1P0E__\``(F&M````(M5](L"B8:X````BT($ +M)?__``")AKP```"+1?BH`70+:@&+5?Q2Z/S___^+10SV``1T!H/+((#C?XM% +M#(L0@^((B=@DWX72#T78B9Z,````,<"-9>A;7E^)[%W#C;8`````C;PG```` +M`%6)Y8/L#%=64XM%"(N0L````(E5_(LPO_____\QVXGVC5,?@_O_#T_3P?H% +MB=F#X1^X`0```-/@BTT0(P21="V)^#)$"Q`/ML`QTI"-="8`J`%T#-'H-2"# +MN.WK!8UV`-'H0H/Z!W[HP>\(,<=#@_M_?JWWUXN>``(``(E=^+@```$`BTT, +MT^"%PW0*]]`AV(F&``(``#';N`````&+30S3X(E%].L!0X/[8W\CBX8``@`` +MA47T=!AJ,HM5_(L"4(M"&/_0@\0(Z]V-M@````"+30R-%(G!X@*-A@0"``") +M/`*-C@@"``"+71"+`XD$"HV.#`(``(M#!(D$"HV.$`(``(M#"(D$"HV.%`(` +M`(M##(D$"K@```$`BTT,T^"%1?AT"8M=^(F>``(``#'`C67H6UY?B>Q=PY"- +MM"8`````58GE4XM%"(M-#(L8BY,``@``@WT0`'0+N````0#3X`G"ZPNX```! +M`-/@]]`APHF3``(``#'`6XGL7<.0C70F`%6)Y5=64XMU"(L>B[N4````]\Q=PXVV`````(V_`````%6)Y8M%"(M-#(L0BX*H +M````B0&+@JP```")000QP(GL7<.-M"8`````C;PG`````%6)Y5=64XM5#(M% +M$(MU"(M-%,`(``'-+BX:<`@``BU3(!(L$R(D#B5,$ +M@\,(03N.>`(``'+BZRN)TS').X[``0``$#BT44B0@QP%M>7XGL7<.058GEBT4(BP"+$(D0BY"` +M`0``B9"``0``,<")[%W#B?95B>6+50B+`L=`!`````#'@O@"````````,<") +M[%W#D%6)Y8M%"(L(BY`,`P``B9#X`@``B5$$,<")[%W#C78`58GEBU4(BPJ+ +M`2."^`(``'4$,<#K%L=!!`````#'@O@"````````N`$```")[%W#58GE@^P, +M5U93BUT(BSO'1?@`````QT7T`````(UT)@`Q]HL'"47\BX.D`@``9H-X!@!\ +M"U/H_/___XG&@\0$BX,,`@``.X,0`@``=!>+`(M`!&:#>`8`?`M3Z/S___\! +MQH/$!`%U]/]%^(7V=`N+1?@[@W@3``!RI\<'_____XM%_*A`=!>+AX`!``#' +MAX`!``#_____4%/H_/___X.[_`(```!U,(-]]`!U0/^#%`,``(&[%`,``,0) +M``!V.(N#!`,``(F##`,``,>#_`(```$```#K%HN#``,``(F##`,``,>#_`(` +M``````#'@Q0#````````,<"-9>A;7E^)[%W#C;0F`````(V\)P````!5B>6# +M[`Q75E.+70B+.\=%^`````#'1?0`````C70F`#'VBP<)1?R+@Z0"``!F@W@& +M`'P+4^C\____B<:#Q`2+@PP"```[@Q`"``!T%XL`BT`$9H-X!@!\"U/H_/__ +M_P'&@\0$`77T_T7XA?9T"XM%^#N#>!,``'*GQP?_____BT7\J$!T%XN'@`$` +M`,>'@`$``/____]04^C\____@[O\`@```G4P@WWT`'5`_X,4`P``@;L4`P`` +MQ`D``'8XBX,$`P``B8,,`P``QX/\`@```0```.L6BX,(`P``B8,,`P``QX/\ +M`@```@```,>#%`,````````QP(UEZ%M>7XGL7<.-M"8`````C;PG`````%6) +MY8/L<%=64XMU"(N&L````(E%G,=%F`````#'190!````_T68BYZD`@``@X:D +M`@``"#N>H`(``'4,BX:<`@``B8:D`@``B=@KAIP"``#!^`.+EK0"``"+/(*% +M_P^$QP$``/9#!@$/A#,!``#V0P=`=!,/MT,&)8)_``!F/0!@#X4:`0``_X;$ +M`@``#[=#!`^W2P:!X00@``"-4/]F@?D$(&8/1,(/M\")1:2)?:B#OEP3```` +M=1B#OF`3````=0]J`&H`Z;H```"-M@`````Q_\9%DP"-1:!0BU60R!``^%?@```(.^7!,```!T18I!#B0/#[;`P>`(#[91#PG0 +M.89H$P``=!AFQT,$SP=FQT,&`(#'190`````Z?H```"#OF`3````=!2*00[` +MZ`6(19/K"8I1#L#J!8A5DXM!"(E!#(M!!(E!"(L!B4$$@\$$@T6D_(-]I#MW +M"\=%I#P```#K`C')A?\/A:P````/MD634%%J`8U%H%"+59R+`E"+0BC_T(/$ +M%.F-````C78`A?\/A((```#'190`````]D,&`71F_X;(`@``]D,&`G0&_X;, +M`@``]D,'('0&_X;0`@``]D,'$'0&_X;4`@``]D,'"'0&_X;8`@``]D,'!'0& +M_X;<`@``]D,'`G0&_X;@`@``]D,'`70&_X;D`@``@'L&`'T&_X;H`@``B7VH +M9L=#!,\'9L=#!@"`@WV4`'004U;H_/___X/$".L+C70F`,=%E`$```"+AJ0" +M``!F@W@&`'P/BT68.X9\$P``#X+`_?__BT68C66$6UY?B>Q=PU6)Y5=64XM= +M"(NSL````#'_ZR*+@PP"``"+`(M`!&:#>`8`#XRV````.[N`$P``#X.J```` +MBX,,`@``BPB#@PP"```$.X,(`@``=0R+@P0"``")@PP"``"+402+`0&#Q`$` +M`/9"!T!U&O^#&`(``/9"!P1T!O^#,`(``(N#B!,``.L\_X,<`@``]D('('0& +M_X,@`@``]D('$'0&_X,D`@``]D('"'0&_X,H`@``]D(&"'0&_X,L`@``BX., +M$P``4%&+!E"+1B3_T(/$#$>+@PP"```[@Q`"```/A33___^)^(UE]%M>7XGL +M7<.0C70F`%6)Y5=64XM="(L#B[NP````B["(`0``B?`S@Q@#``#V10P(=$.H +M!'0_]\8$````=!]J`U/H_/___U/H_/___VH#4^C\____@\04ZPZ-="8`QX,< +M`P``_____XGP@^`$4(L'4(M'+/_0B;,8`P``,<"-9?1;7E^)[%W#C;8````` +M58GE@^P$5U93BUT(BS/'1?P`````@[LP`P```'4>BX:(`0``J0``$`!U$8N& +MB`$```T``!``B8:(`0``BY.T````C47\4(L"4(M"'/_0@\0(@WW\`'1C@(L8 +M`P``!(N3M````(L"4(M"&/_0B<>+D[0```"+`E"+0A3_T(G".[L@`P``=0H[ +MDQP#``!T+.L>@_\"=0N+AH`````D_>L)D(N&@`````P"B8:`````B;L@`P`` +MB9,<`P``C67P6UY?B>Q=PXVV`````(V_`````%6)Y8/L"%=64XM%"(E%_(LP +MQT7X`````(M5%,<"`````(NXL````(M5_(N"+`,``%!J`(L'4(M'5/_0QX:` +M`0``#P```(N&B`$``(/$#*D``!``=!C'1?@!````BX:(`0``)?__[_^)AH@! +M``"+AI`!``!FA&D`$```"```!J,HL'4(M'&/_0@\0(BU40@^(?BT4, +MP>`%)>`#```)PHF6D`$``(#.@#';BT7\.Y@H`P``Q=PXGVC;PG +M`````%6)Y8/L"%=64XM%"(E%_(LPQT7X`````(NXL````(N`+`,``%!J`(L' +M4(M'5/_0QX:``0``#P```(N&B`$``(/$#*D``!``=!C'1?@!````BX:(`0`` +M)?__[_^)AH@!``"+AI`!``!FA&D`$```"```!J,HL'4(M'&/_0@\0( +MBT44B8:4`0``BU40@^(?BT4,P>`%)>`#```)PH#.!(F6D`$``(#.@#';ZQ>0 +M:@J+!U"+1QC_T(/#"HN6D`$``(/$"(M%_#N8*`,``',%9H72?-J[`0```#'` +M9H72#TS8@WWX`'01BX:(`0``#0``$`")AH@!``"+5?R+@BP#``!0:@"+!U"+ +M1UC_T(G8C67L6UY?B>Q=PXVV`````%6)Y8/L$%93BW4(BUT,BY:P````QT7\ +M``@``(U%\%"-1?10BP)0BT(<_]"%P'4QB=@KAIP"``#!^`.+EK0"``#'!((` +M````BX:\`@``B0-FQT,$SP=FQT,&`(`QP.LRD(G8*X:<`@``P?@#BXZT`@`` +MBU7PB12!BT7XB0.+1?R#P,]FB4,$9L=#!@"`N`$```"-9>A;7HGL7<.-M@`` +M``!5B>4QP(GL7<.-M"8`````58GE@^P,5E.+70B+=0R+B[````"+!CN#O`(` +M`'4$,<#K7HGP*X.<`@``P?@#BY.T`@``BQ2"BP:)1?C'1?P`"```9L=&!@`` +M9L=&!```4HU%]%"+`5"+02#_T(GP*X.<`@``P?@#BY.T`@``QP2"`````(N# +MO`(``(D&N`$```"-9>Q;7HGL7<.-M"8`````58GE@^P05U93BW4(QT7P```` +M`(M%#(LXQP``````QT7\:````,=%^`````"-1?10BP90BT8$_]"#Q`B%P'41 +MN`$```#I`0$``(VT)@````"+7?2),XE[-%/H_/___XG!@\0$B5L$QT,(```` +M`,=##`````#'0Q``````QT,8`````,=#'`````#'0R``````QT,D`````,=# +M*`````#'0Q0`````QT,P`````,=#+`````"-0P2+50R)`HM30(M%%(D0BT-` +MC02`BQ2%$````(M%&(D0@ST``````'1B@?D``!C@=`B!^0#,,@!U"(E+3(M% +M$(D(BQ.#>C``=$F-0U!0BP.+`%"+0C#_T(/$"(7`=!V+$U-H`````(M#4%"+ +M`XL`4(M"./_0ZQR0C70F`,=%\`D```#K#HVT)@````#'1?`(````BT7PC67D +M6UY?B>Q=PXVV`````(V_`````%6)Y8/L#%.+70B%VW1+@WM0`'0FBQ.+0U!0 +MBP)0BT)`_]"+$XM#4%"+`E"+0C3_T,=#4`````"#Q!")7?3'1?@`````QT7\ +M:````(L3C47T4(L"4(M""/_0,<"+7?")[%W#C;0F`````(V\)P````!5B>6# +M[`175E.+70B+=0R)WXM#-(M(!(L0@SX`#Y7`B$-DQP8`````QD-E`8U%_%"A +M`````%"+0T!04O_1QT-4!````(/$$/=#8/___P!U(%/H_/___\9#9`"#Q`2% +MP'4M5E/H_/___^LBC;8`````QD=D`5/H_/___\9'9`"#Q`2%P'4)5E/H_/__ +M_S'`C67P6UY?B>Q=PY"-M"8`````58GE@^P05U93BU40BW4(BT8TBT@$B4WX +MBP")1?2+10S'```````!THE5\(U%_%"A`````$!0BT9`4(M5]%+_T8/$$(7` +M=0FX!@```.M5B?8Q_^LW,=N+!FHRBQ!2BT`8_]"#Q`A#@_L)?NN-1?Q0H0`` +M``!`4(M&0%"+3?11BU7X_]*#Q!"%P'2]1SM]\'T&]D7\!'2^BT7\@^`$BTT, +MB0$QP(UEY%M>7XGL7<.-=@!5B>6#[`A75E.+70B+0S2+>`2+,(U%_%"A```` +M`%"+0T!05O_7@\00ATP`=0]J +M9(M%#%!3Z/S___^#Q`Q3Z/S___\QP(UE[%M>7XGL7<.-=@"-O"<`````58GE +MBT4(@WA4`P^6P`^VP(GL7<.-M@````"-OP````!5B>6+10C'0%0`````,<") +M[%W#C;8`````C;PG`````%6)Y8/L&%=64XM="(E=\(M#-(MX!(M0"(E5[(LP +MBT-4@_@!#X1_````#^`(/A$T!``"#^`,/A,,!``#I!0(``(U%_%"A```` +M`%"+0T!05O_7@\00A<`/A.(!``"`3?V`BT7\4*$`````4(M#0%!6BU7L_]*# +MQ!"%P`^$OP$``,=#5`$```"+$V@2`@``BT-04(L"4(M"//_0A<`/A:0!``#I +MF`$``(U%_%"A`````%"+0T!05O_7@\00A<`/A'P!``#'1>@`````9H-]_`!] +M.XL3:C*+`E"+0AC_T(U%_%"A`````%"+0T!05O_7@\08A<`/A$8!``#_1>B! +M?>CG`P``?P=F@WW\`'S%]T-@____`'4:QT-4`@```,=#6"`#``"+$V@@`P`` +MZ5____^-1?Q0H0````!0BT-`4%;_UX/$$(7`#X3T````@&7];XM%_%"A```` +M`%"+0T!05HM5[/_2@\00A<`/A-$```"-1?A0BT7P4.C\____Z<8```"-1?10 +MH0````!`4(M#0%!6_]>#Q!"%P`^$H@```/9%]"!U'(%[6+<+``!W$X%#6"8" +M``"+$V@F`@``Z<_^__^-1?Q0H0````!0BT-`4%;_UX/$$(7`=&CV1?T"=0;V +M1?0@=1/'0U0#````C47X4%/H_/___^M04^C\____ZT&0C47T4*$`````0%"+ +M0T!05O_7@\00A7XGL7<.-=@"-O"<` +M````58GE@^P$5U93BUT(A=MT?H,]``````!T=8M#-(MX!(LPBT-`4%/H_/__ +M_X/$"(7`=5Z-1?Q0H0````!`4(M#0%!6_]>#Q!"%P'4'N`8```#K/O9%_`1T +M!H![9`!T,(M#0%!3Z/S___^#Q`B%P'4ABT-`4%/H_/___X/$"(7`=1"+0T!0 +M4^C\____AQ=PXVV`````%6)Y5.+70AF@WM@`'4&4^C\ +M____BT,XBUW\B>Q=PXGV58GE4XM="(![8@!U!E/H_/___XM#/(M=_(GL7<.- +M=@!5B>6#[!Q75E.+70B+0S2+4`2)5?"+4`B)5>R+.`^WO'1>0` +M````C47\4*$`````0%"+0T!05XM5\/_2C47X4*$`````4(M#0%!7BU7P_]*+ +M1?B)1?2#Q"!F@_X*=2K'0SB`EI@`@&7YWX!]ZP%U"?9%_0AT8NLRD(!]ZP)U +M6?9%_1!T4^L_B?9F@_YD=4G'0S@`X?4%@$WY((!]ZP%U&O9%_:!T,H!E^?[' +M1>0!````QT,\`0```.L>@'WK`G48]D7]0'02@$WY`<=%Y`$```#'0SP"```` +M@WWD`'4+N`4```#IWP```)"`9?7OBT7T4*$`````4(M#0%!7BU7L_]*-1?10 +MH0````!0BT-`4%>+5?#_TC'V@\0@]D7U$'0VBQ-J,HL"4(M"&/_0C47T4*$` +M````4(M#0%!7BU7P_]*#Q!A&@?[S`0``?PKV1?40#X7*____@&7Y[XM%^%"A +M`````%"+0T!05XM5[/_2@\00@'ME`'0BQT-4!````&A@"0``BT4,4(M%"%#H +M_/___^LSC;0F`````,=#5`,```#'0UB6````BQ-HE@```(M#4%"+`E"+0CS_ +MT(7`=0?'0U0$````,<"-9=A;7E^)[%W#D(VT)@````!5B>6#[!175E.+70B+ +M0S2+<`2+4`B)5?2+`(E%\`^W0V!FB47NBE-BB%7M,?]FAT!=1*`Y*^!ST`!``#K%HVT)@`` +M``"`?>T"=0F`Y%>!SZ`"```C1?QU$<=#5`0```"X!0```.FK````B?CWT"-# +M7%"A`````(/`!%"+0T!0BU7P4HM5]/_2@\00AV4` +M="G'0U0$````BT-`4%/H_/___X/$"(7`=3&+10Q0BU4(4NC\____ZR*)]HL3 +M:"`#``"+0U!0BP)0BT(\_]"%P'4'QT-4!````#'`C67@6UY?B>Q=PXVV```` +M`%6)Y5.+10B+50R+31"+711FB5!@B$ABB%AC,Q=P^L-D)"0D)"0D)"0 +MD)"0D%6)Y3'`B>Q=PXVT)@````!5B>6#[!175E/'1?@`````BU4(BT(TBSB+ +M0`2)1?3'1?``````QT7L(````+X!````B?-3BT4(4.C\____@\0(A<`/A<@` +M``"-1?Q0H0````!`4%-7BU7T_]*#Q!"%P`^$JP```(-]_``/A*$```"A```` +M`(T$@,'@`HM5_(/B!(F0$````(F8`````/9%_`%T,P4(````4&H#4U>+5?3_ +MTH/$$(7`=!VA`````(T$@(T$A00```!0:@)35XM5]/_2A$0BQ4(````@>(` +M_```"=&)#(4,````_P4`````ZQF)]D:-1A^#_O\/3\8DX"G&_TWL#X4*____ +M@ST```````^$X````(,]``````%U$Z$,````B47XH0````#IOP```)`QV[D0 +M````O@P```"_`````(L5`````.L(C;0F`````$,YTW,FC02;P>`"@SP(``^$ +MZ____XLT,(EU^(L$.(M5"(E"0,=%\`$````QVSL=`````'-(N@P```"Y```` +M`)"-!)O!X`*!/!```!C@=`F!/!``S#(`=1B-!)O!X`*+%!")5?B+!`CK-8VT +M)@````!#.QT`````#X+#____@WWP`'4AH0````!(C02`P>`"BY`,````B57X +MBX``````BU4(B4)`BT7XC67@6UY?B>Q=P^L-D)"0D)"0D)"0D)"0D%6)Y8/L +M!%=64XM5"(M"-(LPBW@$BU@(@WI,``^%O@```(U%_%"A`````%"+10Q05O_7 +M@\00AS';9H-]_`!]<)"+50B+`FHRBQ!2BT`8_]"#Q`A#@?L/)P``=PMF +M@WW\``^,VO___S';9H-]_`!]0)"+10B+$&HRBP)0BT(8_]"-1?Q0H0````!0 +MBU4,4E;_UX/$&(7`#X1N____0X'[YP,``'<+9H-]_``/C,'___\QP(UE\%M> +M7XGL7<.0C70F`%6)Y8/L!%=64XM5"(M"-(LPBW@$BU@(C47\4*$`````4(M% +M#%!6_]>#Q!"%P`^$C0```/9%_0P/A(H```"`9?WSBT7\4*$`````4(M5#%)6 +M_].#Q!"%P'4'N`<```#K:8U%_%"A`````%"+10Q05O_7,=N#Q!#V1?T,=$N- +M="8`BT4(BQ!J,HL"4(M"&/_0C47\4*$`````4(M5#%)6_]>#Q!B%P'090X'[ +MYP,``'<7]D7]#`^%QO___^L+C70F`+@&````ZP(QP(UE\%M>7XGL7<.-M@`` +M``"-O"<`````58GE@^P(5U93BUT(BT,TBSB+4`2)5?B+<`C'0U0`````C47\ +M4*$`````4(M#0%!7_]*#Q!"%P`^$HP```/=#8/___P!T%XM#7%"A`````(/` +M!%"+0T!05__6@\00QT7\``@``(M%_%"A`````%"+0T!05__6@\00A+5?C_TC'V@\00]D7]"'5%BQ-J,HL"4(M" +M&/_0C47\4*$`````4(M#0%!7BU7X_]*#Q!B%P'071H/^"7<8]D7]"`^$R?__ +M_^L,D(UT)@"X!@```.L",<"-9>Q;7E^)[%W#C;8`````C;PG`````%6)Y8/L +M#%=64XMU"(M&-(L0B57XBT`$B47T@WY,`'5_C47\4*$`````0%"+1D!0BT7X +M4(M5]/_2@\00AQ=PY"-="8`58GE@^P$4XM5 +M"(M"-(L(BU@$C47\4*$`````0%"+0D!04?_3A6#[`13BU4(BT(TBPB+6`2- +M1?Q0H0````!`4(M"0%!1_].%P'4(N`8```#K$I#V1?P$=`F+10S'``$````Q +MP(M=^(GL7<.0C;0F`````%6)Y8/L$%=64XM="(M#-(MX!(M0"(E5\(LPC47\ +M4*$`````4(M#0%!6_]>#Q!"%P'09C47X4*$`````0%"+0T!05O_7@\00A1;7E^)[%W# +MD(UT)@!5B>6#[`A75E.+50B+0C2+<`2+&(U%_%"A`````(/`!%"+0D!04__6 +MB<>-1?A0H0````"#P`50BU4(BT)`4%/_U@G'=0NX!@```.M5C70F`(M%_"-% +M^*F``0``=!.+50C'0C@`X?4%ZQ6-M"8`````J&!T"HM5",=".("6F`"I0`$` +M`'0,BT4(QT`\`@```.L.J*!T"HM5",="/`$````QP(UE[%M>7XGL7<.0C70F +M``````````````````@``````````0```#`Q+C`Q````4U)#($$Z("12979I +M````P!```!T````2``$`;0`` +M`%`1``!E````$@`!`'L```#`$0``R````!(``0"(````D!(``"X````2``$` +MH````,`2``":`P``$@`!`*X```#P(```,````!(``0#%````,"(```(!```2 +M``$`YP```"`A```"`0``$@`!`/\```"P(```'P```!(``0`9`0``T"```!T` +M```2``$`,@$``)`@```>````$@`!`$H!``#@$```8P```!(``0!>`0```!D` +M`#P````2``$`````$@`!`(@!``#`&```&````!(``0"C`0`` +MH!@``!@````2``$`O0$``$`9```0````$@`!`-H!``!0&0``$````!(``0#V +M`0``8!D``!`!```2``$`#`(``'`:``!:````$@`!`"D"``#0&@``U@```!(` +M`0`_`@``L!L``"@!```2``$`50(``.`<```,````$@`!`'$"``#P'```TP`` +M`!(``0")`@``T!T``#@!```2``$`H@(``!`?```[````$@`!`+X"``!0'P`` +M5````!(``0#5`@``L!\``"(````2``$`[`(``.`?``"O````$@`!``,#```@ +M)P``Q````!(``0`:`P``\"<``$$1E4EN:713=&%T90!!1$%05$527T=E=%1R +M86YS;6ET475E=653:7IE`$%$05!415)?1V5T4F5C96EV95%U975E4VEZ90!! +M1$%05$527T=E=%-T871I0!0 +M2%E?1V5T06-T:79E4&AY`%!(65]);FET`%!(65]);FET1F%S=`!02%E?1&5I +M;FET`%!(65]'971,:6YK4W!E960`4$A97T=E=$QI;FM-;V1E`%!(65]'971, +M:6YK4W1A=&5%>'1E4EN:713=&%T90!02%E?0VQO`!A4&AY061D51I;65R1G5N8P!0 +M2%E?1&]0;W-T075T;VYE9V]T:6%T:6]N4')O8V5S$9O +M diff --git a/sys/dev/netif/nv/Makefile b/sys/dev/netif/nv/Makefile new file mode 100644 index 0000000000..fd9a607916 --- /dev/null +++ b/sys/dev/netif/nv/Makefile @@ -0,0 +1,14 @@ +# $DragonFly: src/sys/dev/netif/nv/Attic/Makefile,v 1.1 2004/08/28 15:08:02 joerg Exp $ + +CONTRIBDIR= ${.CURDIR}/../../../contrib/dev/nv + +KMOD= if_nv +SRCS= if_nv.c miibus_if.h device_if.h bus_if.h pci_if.h +SRCS+= adapter.h.patch basetype.h.patch os.h.patch phy.h.patch +OBJS+= nvnetlib.o +KMODDEPS = miibus + +nvnetlib.o: ${CONTRIBDIR}/nvnetlib.o.uu + uudecode < ${CONTRIBDIR}/nvnetlib.o.uu + +.include diff --git a/sys/dev/netif/nv/adapter.h.patch b/sys/dev/netif/nv/adapter.h.patch new file mode 100644 index 0000000000..d2309ab524 --- /dev/null +++ b/sys/dev/netif/nv/adapter.h.patch @@ -0,0 +1,383 @@ +$DragonFly: src/sys/dev/netif/nv/Attic/adapter.h.patch,v 1.1 2004/08/28 15:08:02 joerg Exp $ + +diff -u nvnet/adapter.h nv/adapter.h +--- nvnet/adapter.h 2003-05-06 21:39:38.000000000 +0200 ++++ nv/adapter.h 2004-08-19 18:25:19.000000000 +0200 +@@ -14,17 +14,18 @@ + + #define HDA_VERSION_STRING "HDR A: $Revision: #47 $" + +-////////////////////////////////////////////////////////////////// +-// For the set and get configuration calls. ++/**************************************************************** ++ * For the set and get configuration calls. ++ */ + typedef struct _ADAPTER_CONFIG + { + ULONG ulFlags; + } ADAPTER_CONFIG, *PADAPTER_CONFIG; +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + #if defined(_WIN32) +-////////////////////////////////////////////////////////////////// +-// For the ADAPTER_Write1 call. ++/**************************************************************** ++ * For the ADAPTER_Write1 call. */ + /* This scatter gather list should be same as defined in ndis.h by MS. + For ULONG_PTR MS header file says that it will be of same size as + pointer. It has been defined to take care of casting between differenet +@@ -55,16 +56,18 @@ + + #endif + +-// For the ADAPTER_Write call. ++/* For the ADAPTER_Write call. */ + typedef struct _ADAPTER_WRITE_ELEMENT + { + PVOID pPhysical; + ULONG ulLength; + } ADAPTER_WRITE_ELEMENT, *PADAPTER_WRITE_ELEMENT; + +-// pvID is a value that will be passed back into OSAPI.pfnPacketWasSent +-// when the transmission completes. if pvID is NULL, the ADAPTER code +-// assumes the caller does not want the pfnPacketWasSent callback. ++/* ++ * pvID is a value that will be passed back into OSAPI.pfnPacketWasSent ++ * when the transmission completes. if pvID is NULL, the ADAPTER code ++ * assumes the caller does not want the pfnPacketWasSent callback. ++ */ + typedef struct _ADAPTER_WRITE_DATA + { + ULONG ulNumberOfElements; +@@ -73,12 +76,12 @@ + UCHAR uc8021pPriority; + ADAPTER_WRITE_ELEMENT sElement[100]; + } ADAPTER_WRITE_DATA, *PADAPTER_WRITE_DATA; +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + +- +-////////////////////////////////////////////////////////////////// +-// For the ADAPTER_Read call. ++/**************************************************************** ++ * For the ADAPTER_Read call. ++ */ + typedef struct _ADAPTER_READ_ELEMENT + { + PVOID pPhysical; +@@ -94,16 +97,17 @@ + ADAPTER_READ_ELEMENT sElement[10]; + } ADAPTER_READ_DATA, *PADAPTER_READ_DATA; + +-// The ulFilterMatch flag can be a logical OR of the following ++/* The ulFilterMatch flag can be a logical OR of the following */ + #define ADREADFL_UNICAST_MATCH 0x00000001 + #define ADREADFL_MULTICAST_MATCH 0x00000002 + #define ADREADFL_BROADCAST_MATCH 0x00000004 +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + + +-////////////////////////////////////////////////////////////////// +-// For the ADAPTER_GetStatistics call. ++/**************************************************************** ++ * For the ADAPTER_GetStatistics call. ++ */ + #define MAX_TRANSMIT_COLISION_STATS 16 + typedef struct _ADAPTER_STATS + { +@@ -123,22 +127,23 @@ + ULONG ulCRCErrors; + ULONG ulFramingErrors; + ULONG ulOverFlowErrors; +- ULONG ulFrameErrorsPrivate; //Not for public. +- ULONG ulNullBufferReceivePrivate; //Not for public, These are the packets which we didn't indicate to OS ++ ULONG ulFrameErrorsPrivate; /* Not for public. */ ++ ULONG ulNullBufferReceivePrivate; /* Not for public, These are the packets which we didn't indicate to OS */ + +- //interrupt related statistics ++ /* interrupt related statistics */ + ULONG ulRxInterrupt; + ULONG ulRxInterruptUnsuccessful; + ULONG ulTxInterrupt; + ULONG ulTxInterruptUnsuccessful; + ULONG ulPhyInterrupt; + } ADAPTER_STATS, *PADAPTER_STATS; +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + + +-////////////////////////////////////////////////////////////////// +-// For the ADAPTER_GetPowerCapabilities call. ++/**************************************************************** ++ * For the ADAPTER_GetPowerCapabilities call. ++ */ + typedef struct _ADAPTER_POWERCAPS + { + ULONG ulPowerFlags; +@@ -148,7 +153,7 @@ + int iMaxWakeUpPatterns; + } ADAPTER_POWERCAPS, *PADAPTER_POWERCAPS; + +-// For the ADAPTER_GetPowerState and ADAPTER_SetPowerState call. ++/* For the ADAPTER_GetPowerState and ADAPTER_SetPowerState call. */ + typedef struct _ADAPTER_POWERSTATE + { + ULONG ulPowerFlags; +@@ -157,15 +162,19 @@ + ULONG ulLinkChangeWakeUpFlags; + } ADAPTER_POWERSTATE, *PADAPTER_POWERSTATE; + +-// Each of the flag fields in the POWERCAPS structure above can have +-// any of the following bitflags set giving the capabilites of the +-// adapter. In the case of the wake up fields, these flags mean that +-// wake up can happen from the specified power state. +- +-// For the POWERSTATE structure, the ulPowerFlags field should just +-// have one of these bits set to go to that particular power state. +-// The WakeUp fields can have one or more of these bits set to indicate +-// what states should be woken up from. ++/* ++ * Each of the flag fields in the POWERCAPS structure above can have ++ * any of the following bitflags set giving the capabilites of the ++ * adapter. In the case of the wake up fields, these flags mean that ++ * wake up can happen from the specified power state. ++ */ ++ ++/* ++ * For the POWERSTATE structure, the ulPowerFlags field should just ++ * have one of these bits set to go to that particular power state. ++ * The WakeUp fields can have one or more of these bits set to indicate ++ * what states should be woken up from. ++ */ + #define POWER_STATE_D0 0x00000001 + #define POWER_STATE_D1 0x00000002 + #define POWER_STATE_D2 0x00000004 +@@ -175,13 +184,14 @@ + POWER_STATE_D1 | \ + POWER_STATE_D2 | \ + POWER_STATE_D3) +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + + +-////////////////////////////////////////////////////////////////// +-// The ADAPTER_GetPacketFilterCaps call returns a ULONG that can +-// have the following capability bits set. ++/**************************************************************** ++ * The ADAPTER_GetPacketFilterCaps call returns a ULONG that can ++ * have the following capability bits set. ++ */ + #define ACCEPT_UNICAST_PACKETS 0x00000001 + #define ACCEPT_MULTICAST_PACKETS 0x00000002 + #define ACCEPT_BROADCAST_PACKETS 0x00000004 +@@ -189,30 +199,33 @@ + + #define ETH_LENGTH_OF_ADDRESS 6 + +-// The ADAPTER_SetPacketFilter call uses this structure to know what +-// packet filter to set. The ulPacketFilter field can contain some +-// union of the bit flags above. The acMulticastMask array holds a +-// 48 bit MAC address mask with a 0 in every bit position that should +-// be ignored on compare and a 1 in every bit position that should +-// be taken into account when comparing to see if the destination +-// address of a packet should be accepted for multicast. ++/* ++ * The ADAPTER_SetPacketFilter call uses this structure to know what ++ * packet filter to set. The ulPacketFilter field can contain some ++ * union of the bit flags above. The acMulticastMask array holds a ++ * 48 bit MAC address mask with a 0 in every bit position that should ++ * be ignored on compare and a 1 in every bit position that should ++ * be taken into account when comparing to see if the destination ++ * address of a packet should be accepted for multicast. ++ */ + typedef struct _PACKET_FILTER + { + ULONG ulFilterFlags; + UCHAR acMulticastAddress[ETH_LENGTH_OF_ADDRESS]; + UCHAR acMulticastMask[ETH_LENGTH_OF_ADDRESS]; + } PACKET_FILTER, *PPACKET_FILTER; +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + +-////////////////////////////////////////////////////////////////// +-// A WAKE_UP_PATTERN is a 128-byte pattern that the adapter can +-// look for in incoming packets to decide when to wake up. Higher- +-// level protocols can use this to, for example, wake up the +-// adapter whenever it sees an IP packet that is addressed to it. +-// A pattern consists of 128 bits of byte masks that indicate +-// which bytes in the packet are relevant to the pattern, plus +-// values for each byte. ++/**************************************************************** ++ * A WAKE_UP_PATTERN is a 128-byte pattern that the adapter can ++ * look for in incoming packets to decide when to wake up. Higher- ++ * level protocols can use this to, for example, wake up the ++ * adapter whenever it sees an IP packet that is addressed to it. ++ * A pattern consists of 128 bits of byte masks that indicate ++ * which bytes in the packet are relevant to the pattern, plus ++ * values for each byte. ++ */ + #define WAKE_UP_PATTERN_SIZE 128 + + typedef struct _WAKE_UP_PATTERN +@@ -223,10 +236,9 @@ + + + +-// +-// +-// Adapter offload +-// ++/* ++ * Adapter offload ++ */ + typedef struct _ADAPTER_OFFLOAD { + + ULONG Type; +@@ -238,11 +250,12 @@ + #define ADAPTER_OFFLOAD_IEEE802_1P 0x00000002 + #define ADAPTER_OFFLOAD_IEEE802_1PQ_PAD 0x00000004 + +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + +-////////////////////////////////////////////////////////////////// +-// The functional typedefs for the ADAPTER Api ++/**************************************************************** ++ * The functional typedefs for the ADAPTER Api ++ */ + typedef int (* PFN_ADAPTER_CLOSE) (PVOID pvContext); + typedef int (* PFN_ADAPTER_INIT) (PVOID pvContext, USHORT usForcedSpeed, UCHAR ucForceDpx, UCHAR ucForceMode, UINT *puiLinkState); + typedef int (* PFN_ADAPTER_DEINIT) (PVOID pvContext, UCHAR ucIsPowerDown); +@@ -287,10 +300,10 @@ + + typedef struct _ADAPTER_API + { +- // The adapter context ++ /* The adapter context */ + PVOID pADCX; + +- // The adapter interface ++ /* The adapter interface */ + PFN_ADAPTER_CLOSE pfnClose; + PFN_ADAPTER_INIT pfnInit; + PFN_ADAPTER_DEINIT pfnDeinit; +@@ -332,43 +345,45 @@ + PFN_DEREGISTER_OFFLOAD pfnDeRegisterOffload; + PFN_RX_BUFF_READY pfnRxBuffReady; + } ADAPTER_API, *PADAPTER_API; +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + #define MAX_PACKET_TO_ACCUMULATE 16 + + typedef struct _ADAPTER_OPEN_PARAMS + { +- PVOID pOSApi; //pointer to OSAPI structure passed from higher layer +- PVOID pvHardwareBaseAddress; //memory mapped address passed from higher layer +- ULONG ulPollInterval; //poll interval in micro seconds. Used in polling mode +- ULONG MaxDpcLoop; //Maximum number of times we loop to in function ADAPTER_HandleInterrupt +- ULONG MaxRxPkt; //Maximum number of packet we process each time in function UpdateReceiveDescRingData +- ULONG MaxTxPkt; //Maximum number of packet we process each time in function UpdateTransmitDescRingData +- ULONG MaxRxPktToAccumulate; //maximum number of rx packet we accumulate in UpdateReceiveDescRingData before +- //indicating packets to OS. +- ULONG SentPacketStatusSuccess; //Status returned from adapter layer to higher layer when packet was sent successfully +- ULONG SentPacketStatusFailure; ////Status returned from adapter layer to higher layer when packet send was unsuccessful +- ULONG SetForcedModeEveryNthRxPacket; //NOT USED: For experiment with descriptor based interrupt +- ULONG SetForcedModeEveryNthTxPacket; //NOT USED: For experiment with descriptor based interrupt +- ULONG RxForcedInterrupt; //NOT USED: For experiment with descriptor based interrupt +- ULONG TxForcedInterrupt; //NOT USED: For experiment with descriptor based interrupt +- ULONG DeviceId; //Of MAC +- ULONG PollIntervalInusForThroughputMode; //Of MAC ++ PVOID pOSApi; /* pointer to OSAPI structure passed from higher layer */ ++ PVOID pvHardwareBaseAddress; /* memory mapped address passed from higher layer */ ++ ULONG ulPollInterval; /* poll interval in micro seconds. Used in polling mode */ ++ ULONG MaxDpcLoop; /* Maximum number of times we loop to in function ADAPTER_HandleInterrupt */ ++ ULONG MaxRxPkt; /* Maximum number of packet we process each time in function UpdateReceiveDescRingData */ ++ ULONG MaxTxPkt; /* Maximum number of packet we process each time in function UpdateTransmitDescRingData */ ++ ULONG MaxRxPktToAccumulate; /* maximum number of rx packet we accumulate in UpdateReceiveDescRingData before ++ indicating packets to OS. */ ++ ULONG SentPacketStatusSuccess; /* Status returned from adapter layer to higher layer when packet was sent successfully */ ++ ULONG SentPacketStatusFailure; /* 1;2AStatus returned from adapter layer to higher layer when packet send was unsuccessful */ ++ ULONG SetForcedModeEveryNthRxPacket; /* NOT USED: For experiment with descriptor based interrupt */ ++ ULONG SetForcedModeEveryNthTxPacket; /* NOT USED: For experiment with descriptor based interrupt */ ++ ULONG RxForcedInterrupt; /* NOT USED: For experiment with descriptor based interrupt */ ++ ULONG TxForcedInterrupt; /* NOT USED: For experiment with descriptor based interrupt */ ++ ULONG DeviceId; /* Of MAC */ ++ ULONG PollIntervalInusForThroughputMode; /* Of MAC */ + }ADAPTER_OPEN_PARAMS, *PADAPTER_OPEN_PARAMS; + +-////////////////////////////////////////////////////////////////// +-// This is the one function in the adapter interface that is publicly +-// available. The rest of the interface is returned in the pAdapterApi. +-// The first argument needs to be cast to a OSAPI structure pointer. +-// The second argument should be cast to a ADPATER_API structure pointer. ++/**************************************************************** ++ * This is the one function in the adapter interface that is publicly ++ * available. The rest of the interface is returned in the pAdapterApi. ++ * The first argument needs to be cast to a OSAPI structure pointer. ++ * The second argument should be cast to a ADPATER_API structure pointer. ++ */ + int ADAPTER_Open (PADAPTER_OPEN_PARAMS pAdapterOpenParams, PVOID *pvpAdapterApi, ULONG *pulPhyAddr); + +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + + +-////////////////////////////////////////////////////////////////// +-// Here are the error codes the adapter function calls return. ++/**************************************************************** ++ * Here are the error codes the adapter function calls return. ++ */ + #define ADAPTERERR_NONE 0x0000 + #define ADAPTERERR_COULD_NOT_ALLOC_CONTEXT 0x0001 + #define ADAPTERERR_COULD_NOT_CREATE_CONTEXT 0x0002 +@@ -376,11 +391,11 @@ + #define ADAPTERERR_TRANSMIT_QUEUE_FULL 0x0004 + #define ADAPTERERR_COULD_NOT_INIT_PHY 0x0005 + #define ADAPTERERR_PHYS_SIZE_SMALL 0x0006 +-////////////////////////////////////////////////////////////////// ++/****************************************************************/ + + #define REDUCE_LENGTH_BY 48 + #define EXTRA_WRITE_SLOT_TO_REDUCE_PER_SEND 3 +-#define MAX_TX_DESCS 256 //32 //256 //512 //64 //256 ++#define MAX_TX_DESCS 256 /* 32 256 512 64 256 */ + + typedef struct _TX_INFO_ADAP + { +@@ -394,11 +409,13 @@ + int ADAPTER_WorkaroundTXHang(PVOID pvContext); + #endif + +-//#define TRACK_INIT_TIME ++/* #define TRACK_INIT_TIME */ + + #ifdef TRACK_INIT_TIME +-//This routine is defined in entry.c adapter doesn't link int64.lib +-//We defined here so that its easy to use it in phy as well as mswin ++/* ++ * This routine is defined in entry.c adapter doesn't link int64.lib ++ * We defined here so that its easy to use it in phy as well as mswin ++ */ + + #define MAX_PRINT_INDEX 32 + extern void PrintTime(ULONG ulIndex); +@@ -408,7 +425,7 @@ + #endif + + #ifdef __cplusplus +-} // extern "C" ++} /* extern "C" */ + #endif + +-#endif // _ADAPTER_H_ ++#endif /* _ADAPTER_H_ */ diff --git a/sys/dev/netif/nv/basetype.h.patch b/sys/dev/netif/nv/basetype.h.patch new file mode 100644 index 0000000000..a375978022 --- /dev/null +++ b/sys/dev/netif/nv/basetype.h.patch @@ -0,0 +1,42 @@ +$DragonFly: src/sys/dev/netif/nv/Attic/basetype.h.patch,v 1.1 2004/08/28 15:08:02 joerg Exp $ + +diff -u nvnet/basetype.h nv/basetype.h +--- nvnet/basetype.h 2003-05-06 21:39:38.000000000 +0200 ++++ nv/basetype.h 2004-08-19 18:11:43.000000000 +0200 +@@ -10,11 +10,12 @@ + + #define HDB_VERSION_STRING "HDR B: $Revision: #4 $" + +-// Fundamental data types +-// UCHAR 8 bit unsigned +-// UINT either 16bit or 32bit unsigned depending upon compiler +-// USHORT 16 bit unsigned +-// ULONG 32 bit unsigned ++/* Fundamental data types ++ * UCHAR 8 bit unsigned ++ * UINT either 16bit or 32bit unsigned depending upon compiler ++ * USHORT 16 bit unsigned ++ * ULONG 32 bit unsigned ++ */ + + typedef unsigned char UCHAR; + typedef unsigned int UINT; +@@ -22,10 +23,10 @@ + typedef unsigned long ULONG; + #define VOID void + +-// Constructed types ++/* Constructed types */ + typedef VOID *PVOID; + +-// These are USEFUL "types" ++/* These are USEFUL "types" */ + #ifndef NULL + #define NULL 0 + #endif +@@ -38,4 +39,4 @@ + #define FALSE 0 + #endif + +-#endif // _BASETYPE_H_ ++#endif /* _BASETYPE_H_ */ diff --git a/sys/dev/netif/nv/if_nv.c b/sys/dev/netif/nv/if_nv.c new file mode 100644 index 0000000000..d0f9073755 --- /dev/null +++ b/sys/dev/netif/nv/if_nv.c @@ -0,0 +1,1623 @@ +/* + * Copyright (c) 2003 by Quinton Dolan . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: if_nv.c,v 1.9 2003/12/13 15:27:40 q Exp $ + * $DragonFly: src/sys/dev/netif/nv/Attic/if_nv.c,v 1.1 2004/08/28 15:08:02 joerg Exp $ + */ + +/* + * NVIDIA nForce MCP Networking Adapter driver + * + * This is a port of the NVIDIA MCP Linux ethernet driver distributed by NVIDIA + * through their web site. + * + * All mainstream nForce and nForce2 motherboards are supported. This module + * is as stable, sometimes more stable, than the linux version. (This seems to + * be related to some issues with newer distributions using GCC 3.2, however + * this don't appear to effect FreeBSD 5.x). + * + * In accordance with the NVIDIA distribution license it is necessary to link + * this module against the nvlibnet.o binary object included in the Linux + * driver source distribution. The binary component is not modified in any + * way and is simply linked against a FreeBSD equivalent of the nvnet.c linux + * kernel module "wrapper". + * + * The Linux driver uses a common code API that is shared between Win32 and + * Linux. This abstracts the low level driver functions and uses callbacks + * and hooks to access the underlying hardware device. By using this same API + * in a FreeBSD kernel module it is possible to support the hardware without + * breaching the Linux source distributions licensing requirements, or + * obtaining the hardware programming specifications. + * + * Although not conventional, it works, and given the relatively small amount of + * hardware centric code, it's hopefully no more buggy than its linux + * counterpart. + * + * Written by Quinton Dolan + * Portions based on existing FreeBSD network drivers. + * NVIDIA API usage derived from distributed NVIDIA NVNET driver source files. + * + * $Id: if_nv.c,v 1.9 2003/12/13 15:27:40 q Exp $ + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#include + +#include + +#include +#include +#include + +#include /* for vtophys */ +#include /* for vtophys */ +#include /* for DELAY */ +#include +#include + +#include +#include + +#include +#include + +MODULE_DEPEND(nv, pci, 1, 1, 1); +MODULE_DEPEND(nv, ether, 1, 1, 1); +MODULE_DEPEND(nv, miibus, 1, 1, 1); + +#include "if_nvreg.h" +#include "miibus_if.h" + +static int nv_probe(device_t); +static int nv_attach(device_t); +static int nv_detach(device_t); +static void nv_init(void *); +static void nv_stop(struct nv_softc *); +static void nv_shutdown(device_t); +static int nv_init_rings(struct nv_softc *); +static void nv_free_rings(struct nv_softc *); + +static void nv_ifstart(struct ifnet *); +static int nv_ioctl(struct ifnet *, u_long, caddr_t, struct ucred *); +static void nv_intr(void *); +static void nv_tick(void *); +static void nv_setmulti(struct nv_softc *); +static void nv_watchdog(struct ifnet *); +static void nv_update_stats(struct nv_softc *); + +static int nv_ifmedia_upd(struct ifnet *); +static void nv_ifmedia_sts(struct ifnet *, struct ifmediareq *); +static int nv_miibus_readreg(device_t, int, int); +static void nv_miibus_writereg(device_t, int, int, int); + +static void nv_dmamap_cb(void *, bus_dma_segment_t *, int, int); +static void nv_dmamap_tx_cb(void *, bus_dma_segment_t *, int, bus_size_t, int); + +static int nv_osalloc(void *, MEMORY_BLOCK *); +static int nv_osfree(void *, MEMORY_BLOCK *); +static int nv_osallocex(void *, MEMORY_BLOCKEX *); +static int nv_osfreeex(void *, MEMORY_BLOCKEX *); +static int nv_osclear(void *, void *, int); +static int nv_osdelay(void *, unsigned long); +static int nv_osallocrxbuf(void *, MEMORY_BLOCK *, void **); +static int nv_osfreerxbuf(void *, MEMORY_BLOCK *, void *); +static int nv_ospackettx(void *, void *, unsigned long); +static int nv_ospacketrx(void *, void *, unsigned long, unsigned char *, unsigned char); +static int nv_oslinkchg(void *, int); +static int nv_osalloctimer(void *, void **); +static int nv_osfreetimer(void *, void *); +static int nv_osinittimer(void *, void *, PTIMER_FUNC, void *); +static int nv_ossettimer(void *, void *, unsigned long); +static int nv_oscanceltimer(void *, void *); +static int nv_ospreprocpkt(void *, void *, void **, unsigned char *, unsigned char); +static void *nv_ospreprocpktnopq(void *, void *); +static int nv_osindicatepkt(void *, void **, unsigned long); +static int nv_oslockalloc(void *, int, void **); +static int nv_oslockacquire(void *, int, void *); +static int nv_oslockrelease(void *, int, void *); +static void *nv_osreturnbufvirt(void *, void *); + +static device_method_t nv_methods[] = { + /* Device interface */ + DEVMETHOD(device_probe, nv_probe), + DEVMETHOD(device_attach, nv_attach), + DEVMETHOD(device_detach, nv_detach), + DEVMETHOD(device_shutdown, nv_shutdown), + + /* Bus interface */ + DEVMETHOD(bus_print_child, bus_generic_print_child), + DEVMETHOD(bus_driver_added, bus_generic_driver_added), + + /* MII interface */ + DEVMETHOD(miibus_readreg, nv_miibus_readreg), + DEVMETHOD(miibus_writereg, nv_miibus_writereg), + + {0, 0} +}; + +static driver_t nv_driver = { + "nv", + nv_methods, + sizeof(struct nv_softc) +}; + +static devclass_t nv_devclass; + +static int nv_pollinterval = 0; +SYSCTL_INT(_hw, OID_AUTO, nv_pollinterval, CTLFLAG_RW, + &nv_pollinterval, 0, "delay between interface polls"); + +DRIVER_MODULE(nv, pci, nv_driver, nv_devclass, 0, 0); +DRIVER_MODULE(miibus, nv, miibus_driver, miibus_devclass, 0, 0); + +static struct nv_type nv_devs[] = { + {NVIDIA_VENDORID, NFORCE_MCPNET1_DEVICEID, + "NVIDIA nForce MCP Networking Adapter"}, + {NVIDIA_VENDORID, NFORCE_MCPNET2_DEVICEID, + "NVIDIA nForce MCP2 Networking Adapter"}, + {NVIDIA_VENDORID, NFORCE_MCPNET3_DEVICEID, + "NVIDIA nForce MCP3 Networking Adapter"}, + {0, 0, NULL} +}; + +/* DMA MEM map callback function to get data segment physical address */ +static void +nv_dmamap_cb(void *arg, bus_dma_segment_t * segs, int nsegs, int error) +{ + if (error) + return; + + KASSERT(nsegs == 1, + ("Too many DMA segments returned when mapping DMA memory")); + *(bus_addr_t *)arg = segs->ds_addr; +} + +/* DMA RX map callback function to get data segment physical address */ +static void +nv_dmamap_rx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, bus_size_t mapsize, int error) +{ + if (error) + return; + *(bus_addr_t *)arg = segs->ds_addr; +} + +/* + * DMA TX buffer callback function to allocate fragment data segment + * addresses + */ +static void +nv_dmamap_tx_cb(void *arg, bus_dma_segment_t * segs, int nsegs, bus_size_t mapsize, int error) +{ + struct nv_tx_desc *info = arg; + + if (error) + return; + KASSERT(nsegs < NV_MAX_FRAGS, + ("Too many DMA segments returned when mapping mbuf")); + info->numfrags = nsegs; + bcopy(segs, info->frags, nsegs * sizeof(bus_dma_segment_t)); +} + +/* Probe for supported hardware ID's */ +static int +nv_probe(device_t dev) +{ + struct nv_type *t = nv_devs; + + /* Check for matching PCI DEVICE ID's */ + while (t->name != NULL) { + if ((pci_get_vendor(dev) == t->vid_id) && + (pci_get_device(dev) == t->dev_id)) { + device_set_desc(dev, t->name); + return (0); + } + t++; + } + + return (ENXIO); +} + +/* Attach driver and initialise hardware for use */ +static int +nv_attach(device_t dev) +{ + u_char eaddr[ETHER_ADDR_LEN]; + struct nv_softc *sc; + struct ifnet *ifp; + OS_API *osapi; + ADAPTER_OPEN_PARAMS OpenParams; + int error = 0, i, rid, unit; + + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_attach - entry\n"); + + sc = device_get_softc(dev); + unit = device_get_unit(dev); + + sc->dev = dev; + sc->unit = unit; + + /* Preinitialize data structures */ + bzero(&OpenParams, sizeof(ADAPTER_OPEN_PARAMS)); + + /* Enable bus mastering */ + pci_enable_busmaster(dev); + + /* Allocate memory mapped address space */ + rid = NV_RID; + sc->res = bus_alloc_resource(dev, SYS_RES_MEMORY, &rid, + 0, ~0, 1, RF_ACTIVE); + + if (sc->res == NULL) { + device_printf(dev, "couldn't map memory\n"); + error = ENXIO; + goto fail; + } + sc->sc_st = rman_get_bustag(sc->res); + sc->sc_sh = rman_get_bushandle(sc->res); + + /* Allocate interrupt */ + rid = 0; + sc->irq = bus_alloc_resource(dev, SYS_RES_IRQ, &rid, 0, ~0, 1, + RF_SHAREABLE | RF_ACTIVE); + + if (sc->irq == NULL) { + device_printf(dev, "couldn't map interrupt\n"); + error = ENXIO; + goto fail; + } + /* Allocate DMA tags */ + error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, MCLBYTES * NV_MAX_FRAGS, + NV_MAX_FRAGS, MCLBYTES, 0, + &sc->mtag); + if (error) { + device_printf(dev, "couldn't allocate dma tag\n"); + goto fail; + } + error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, + sizeof(struct nv_rx_desc) * RX_RING_SIZE, 1, + sizeof(struct nv_rx_desc) * RX_RING_SIZE, 0, + &sc->rtag); + if (error) { + device_printf(dev, "couldn't allocate dma tag\n"); + goto fail; + } + error = bus_dma_tag_create(NULL, 4, 0, BUS_SPACE_MAXADDR_32BIT, + BUS_SPACE_MAXADDR, NULL, NULL, + sizeof(struct nv_tx_desc) * TX_RING_SIZE, 1, + sizeof(struct nv_tx_desc) * TX_RING_SIZE, 0, + &sc->ttag); + if (error) { + device_printf(dev, "couldn't allocate dma tag\n"); + goto fail; + } + /* Allocate DMA safe memory and get the DMA addresses. */ + error = bus_dmamem_alloc(sc->ttag, (void **)&sc->tx_desc, + BUS_DMA_NOWAIT, &sc->tmap); + if (error) { + device_printf(dev, "couldn't allocate dma memory\n"); + goto fail; + } + bzero(sc->tx_desc, sizeof(struct nv_tx_desc) * TX_RING_SIZE); + error = bus_dmamap_load(sc->ttag, sc->tmap, sc->tx_desc, + sizeof(struct nv_tx_desc) * TX_RING_SIZE, nv_dmamap_cb, + &sc->tx_addr, 0); + if (error) { + device_printf(dev, "couldn't map dma memory\n"); + goto fail; + } + error = bus_dmamem_alloc(sc->rtag, (void **)&sc->rx_desc, + BUS_DMA_NOWAIT, &sc->rmap); + if (error) { + device_printf(dev, "couldn't allocate dma memory\n"); + goto fail; + } + bzero(sc->rx_desc, sizeof(struct nv_rx_desc) * RX_RING_SIZE); + error = bus_dmamap_load(sc->rtag, sc->rmap, sc->rx_desc, + sizeof(struct nv_rx_desc) * RX_RING_SIZE, nv_dmamap_cb, + &sc->rx_addr, 0); + if (error) { + device_printf(dev, "couldn't map dma memory\n"); + goto fail; + } + /* Initialize rings. */ + if (nv_init_rings(sc)) { + device_printf(dev, "failed to init rings\n"); + error = ENXIO; + goto fail; + } + /* Setup NVIDIA API callback routines */ + osapi = &sc->osapi; + osapi->pOSCX = sc; + osapi->pfnAllocMemory = nv_osalloc; + osapi->pfnFreeMemory = nv_osfree; + osapi->pfnAllocMemoryEx = nv_osallocex; + osapi->pfnFreeMemoryEx = nv_osfreeex; + osapi->pfnClearMemory = nv_osclear; + osapi->pfnStallExecution = nv_osdelay; + osapi->pfnAllocReceiveBuffer = nv_osallocrxbuf; + osapi->pfnFreeReceiveBuffer = nv_osfreerxbuf; + osapi->pfnPacketWasSent = nv_ospackettx; + osapi->pfnPacketWasReceived = nv_ospacketrx; + osapi->pfnLinkStateHasChanged = nv_oslinkchg; + osapi->pfnAllocTimer = nv_osalloctimer; + osapi->pfnFreeTimer = nv_osfreetimer; + osapi->pfnInitializeTimer = nv_osinittimer; + osapi->pfnSetTimer = nv_ossettimer; + osapi->pfnCancelTimer = nv_oscanceltimer; + osapi->pfnPreprocessPacket = nv_ospreprocpkt; + osapi->pfnPreprocessPacketNopq = nv_ospreprocpktnopq; + osapi->pfnIndicatePackets = nv_osindicatepkt; + osapi->pfnLockAlloc = nv_oslockalloc; + osapi->pfnLockAcquire = nv_oslockacquire; + osapi->pfnLockRelease = nv_oslockrelease; + osapi->pfnReturnBufferVirtual = nv_osreturnbufvirt; + + /* Set NVIDIA API startup parameters */ + OpenParams.MaxDpcLoop = 2; + OpenParams.MaxRxPkt = RX_RING_SIZE; + OpenParams.MaxTxPkt = TX_RING_SIZE; + OpenParams.SentPacketStatusSuccess = 1; + OpenParams.SentPacketStatusFailure = 0; + OpenParams.MaxRxPktToAccumulate = 6; + OpenParams.ulPollInterval = nv_pollinterval; + OpenParams.SetForcedModeEveryNthRxPacket = 0; + OpenParams.SetForcedModeEveryNthTxPacket = 0; + OpenParams.RxForcedInterrupt = 0; + OpenParams.TxForcedInterrupt = 0; + OpenParams.pOSApi = osapi; + OpenParams.pvHardwareBaseAddress = rman_get_virtual(sc->res); + sc->linkup = 0; + + /* Open NVIDIA Hardware API */ + error = ADAPTER_Open(&OpenParams, (void **)&(sc->hwapi), &sc->phyaddr); + if (error) { + device_printf(dev, "failed to open NVIDIA Hardware API: 0x%x\n", error); + goto fail; + } + /* MAC is loaded backwards into h/w reg */ + sc->hwapi->pfnGetNodeAddress(sc->hwapi->pADCX, sc->original_mac_addr); + for (i = 0; i < 6; i++) { + eaddr[i] = sc->original_mac_addr[5 - i]; + } + sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, eaddr); + bcopy(eaddr, (char *)&sc->sc_macaddr, ETHER_ADDR_LEN); + + /* Display ethernet address ,... */ + device_printf(dev, "Ethernet address %6D\n", sc->sc_macaddr, ":"); + + DEBUGOUT(NV_DEBUG_INIT, "nv: do mii_phy_probe\n"); + + /* Probe device for MII interface to PHY */ + if (mii_phy_probe(dev, &sc->miibus, + nv_ifmedia_upd, nv_ifmedia_sts)) { + device_printf(dev, "MII without any phy!\n"); + error = ENXIO; + goto fail; + } + /* Setup interface parameters */ + ifp = &sc->sc_if; + ifp->if_softc = sc; + if_initname(ifp, "nv", unit); + ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; + ifp->if_ioctl = nv_ioctl; + ifp->if_start = nv_ifstart; + ifp->if_watchdog = nv_watchdog; + ifp->if_timer = 0; + ifp->if_init = nv_init; + ifp->if_mtu = ETHERMTU; + ifp->if_baudrate = IF_Mbps(100); + ifp->if_snd.ifq_maxlen = IFQ_MAXLEN; + + /* Attach to OS's managers. */ + ether_ifattach(ifp, sc->sc_macaddr); + callout_handle_init(&sc->stat_ch); + + /* Activate our interrupt handler. - attach last to avoid lock */ + error = bus_setup_intr(sc->dev, sc->irq, INTR_TYPE_NET, + nv_intr, sc, &sc->sc_ih); + if (error) { + device_printf(sc->dev, "couldn't set up interrupt handler\n"); + goto fail; + } + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_attach - exit\n"); + +fail: + if (error) + nv_detach(dev); + + return (error); +} + +/* Detach interface for module unload */ +static int +nv_detach(device_t dev) +{ + struct nv_softc *sc = device_get_softc(dev); + struct ifnet *ifp; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_detach - entry\n"); + + ifp = &sc->arpcom.ac_if; + + if (device_is_attached(dev)) { + nv_stop(sc); + ether_ifdetach(ifp); + } + + if (sc->miibus) + device_delete_child(dev, sc->miibus); + bus_generic_detach(dev); + + /* Reload unreversed address back into MAC in original state */ + if (sc->original_mac_addr) + sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, sc->original_mac_addr); + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: do pfnClose\n"); + /* Detach from NVIDIA hardware API */ + if (sc->hwapi->pfnClose) + sc->hwapi->pfnClose(sc->hwapi->pADCX); + /* Release resources */ + if (sc->sc_ih) + bus_teardown_intr(sc->dev, sc->irq, sc->sc_ih); + if (sc->irq) + bus_release_resource(sc->dev, SYS_RES_IRQ, 0, sc->irq); + if (sc->res) + bus_release_resource(sc->dev, SYS_RES_MEMORY, NV_RID, sc->res); + + nv_free_rings(sc); + + if (sc->tx_desc) { + bus_dmamap_unload(sc->rtag, sc->rmap); + bus_dmamem_free(sc->rtag, sc->rx_desc, sc->rmap); + bus_dmamap_destroy(sc->rtag, sc->rmap); + } + if (sc->mtag) + bus_dma_tag_destroy(sc->mtag); + if (sc->ttag) + bus_dma_tag_destroy(sc->ttag); + if (sc->rtag) + bus_dma_tag_destroy(sc->rtag); + + NV_UNLOCK(sc); + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_detach - exit\n"); + + return (0); +} + +/* Initialise interface and start it "RUNNING" */ +static void +nv_init(void *xsc) +{ + struct nv_softc *sc = xsc; + struct ifnet *ifp; + int error; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init - entry (%d)\n", sc->linkup); + + ifp = &sc->sc_if; + + /* Do nothing if already running */ + if (ifp->if_flags & IFF_RUNNING) + goto fail; + + nv_stop(sc); + + DEBUGOUT(NV_DEBUG_INIT, "nv: do pfnInit\n"); + /* Setup Hardware interface and allocate memory structures */ + error = sc->hwapi->pfnInit(sc->hwapi->pADCX, 0, 0, 0, &sc->linkup); + if (error) { + device_printf(sc->dev, "failed to start NVIDIA Hardware interface\n"); + goto fail; + } + /* Set the MAC address */ + sc->hwapi->pfnSetNodeAddress(sc->hwapi->pADCX, sc->sc_macaddr); + sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); + sc->hwapi->pfnStart(sc->hwapi->pADCX); + + /* Setup multicast filter */ + nv_setmulti(sc); + nv_ifmedia_upd(ifp); + + /* Update interface parameters */ + ifp->if_flags |= IFF_RUNNING; + ifp->if_flags &= ~IFF_OACTIVE; + + sc->stat_ch = timeout(nv_tick, sc, hz); + + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init - exit\n"); + +fail: + NV_UNLOCK(sc); + + return; +} + +/* Stop interface activity ie. not "RUNNING" */ +static void +nv_stop(struct nv_softc *sc) +{ + struct ifnet *ifp; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_stop - entry\n"); + + ifp = &sc->sc_if; + ifp->if_timer = 0; + + /* Cancel tick timer */ + untimeout(nv_tick, sc, sc->stat_ch); + + /* Stop hardware activity */ + sc->hwapi->pfnDisableInterrupts(sc->hwapi->pADCX); + sc->hwapi->pfnStop(sc->hwapi->pADCX, 0); + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: do pfnDeinit\n"); + /* Shutdown interface and deallocate memory buffers */ + if (sc->hwapi->pfnDeinit) + sc->hwapi->pfnDeinit(sc->hwapi->pADCX, 0); + + sc->linkup = 0; + sc->cur_rx = 0; + + ifp->if_flags &= ~(IFF_RUNNING | IFF_OACTIVE); + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_stop - exit\n"); + + NV_UNLOCK(sc); + + return; +} + +/* Shutdown interface for unload/reboot */ +static void +nv_shutdown(device_t dev) +{ + struct nv_softc *sc; + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_shutdown\n"); + + sc = device_get_softc(dev); + + /* Stop hardware activity */ + nv_stop(sc); +} + +/* Allocate TX ring buffers */ +static int +nv_init_rings(struct nv_softc *sc) +{ + int error, i; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init_rings - entry\n"); + + sc->cur_rx = sc->cur_tx = sc->pending_rxs = sc->pending_txs = 0; + /* Initialise RX ring */ + for (i = 0; i < RX_RING_SIZE; i++) { + struct nv_rx_desc *desc = sc->rx_desc + i; + struct nv_map_buffer *buf = &desc->buf; + + buf->mbuf = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); + if (buf->mbuf == NULL) { + device_printf(sc->dev, "couldn't allocate mbuf\n"); + nv_free_rings(sc); + error = ENOBUFS; + goto fail; + } + buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES; + m_adj(buf->mbuf, ETHER_ALIGN); + + error = bus_dmamap_create(sc->mtag, 0, &buf->map); + if (error) { + device_printf(sc->dev, "couldn't create dma map\n"); + nv_free_rings(sc); + goto fail; + } + error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf, + nv_dmamap_rx_cb, &desc->paddr, 0); + if (error) { + device_printf(sc->dev, "couldn't dma map mbuf\n"); + nv_free_rings(sc); + goto fail; + } + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD); + + desc->buflength = buf->mbuf->m_len; + desc->vaddr = mtod(buf->mbuf, PVOID); + } + bus_dmamap_sync(sc->rtag, sc->rmap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + /* Initialize TX ring */ + for (i = 0; i < TX_RING_SIZE; i++) { + struct nv_tx_desc *desc = sc->tx_desc + i; + struct nv_map_buffer *buf = &desc->buf; + + buf->mbuf = NULL; + + error = bus_dmamap_create(sc->mtag, 0, &buf->map); + if (error) { + device_printf(sc->dev, "couldn't create dma map\n"); + nv_free_rings(sc); + goto fail; + } + } + bus_dmamap_sync(sc->ttag, sc->tmap, + BUS_DMASYNC_PREREAD | BUS_DMASYNC_PREWRITE); + + DEBUGOUT(NV_DEBUG_INIT, "nv: nv_init_rings - exit\n"); + +fail: + NV_UNLOCK(sc); + + return (error); +} + +/* Free the TX ring buffers */ +static void +nv_free_rings(struct nv_softc *sc) +{ + int i; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_free_rings - entry\n"); + + for (i = 0; i < RX_RING_SIZE; i++) { + struct nv_rx_desc *desc = sc->rx_desc + i; + struct nv_map_buffer *buf = &desc->buf; + + if (buf->mbuf) { + bus_dmamap_unload(sc->mtag, buf->map); + bus_dmamap_destroy(sc->mtag, buf->map); + m_freem(buf->mbuf); + } + buf->mbuf = NULL; + } + + for (i = 0; i < TX_RING_SIZE; i++) { + struct nv_tx_desc *desc = sc->tx_desc + i; + struct nv_map_buffer *buf = &desc->buf; + + if (buf->mbuf) { + bus_dmamap_unload(sc->mtag, buf->map); + bus_dmamap_destroy(sc->mtag, buf->map); + m_freem(buf->mbuf); + } + buf->mbuf = NULL; + } + + DEBUGOUT(NV_DEBUG_DEINIT, "nv: nv_free_rings - exit\n"); + + NV_UNLOCK(sc); +} + +/* Main loop for sending packets from OS to interface */ +static void +nv_ifstart(struct ifnet *ifp) +{ + struct nv_softc *sc = ifp->if_softc; + struct nv_map_buffer *buf; + struct mbuf *m0, *m; + struct nv_tx_desc *desc; + ADAPTER_WRITE_DATA txdata; + int error, i; + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_ifstart - entry\n"); + + /* If link is down/busy or queue is empty do nothing */ + if (ifp->if_flags & IFF_OACTIVE || ifp->if_snd.ifq_head == NULL) + return; + + /* Transmit queued packets until sent or TX ring is full */ + while (sc->pending_txs < TX_RING_SIZE) { + desc = sc->tx_desc + sc->cur_tx; + buf = &desc->buf; + + /* Get next packet to send. */ + IF_DEQUEUE(&ifp->if_snd, m0); + + /* If nothing to send, return. */ + if (m0 == NULL) + return; + + /* Map MBUF for DMA access */ + error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m0, + nv_dmamap_tx_cb, desc, BUS_DMA_NOWAIT); + + if (error && error != EFBIG) { + m_freem(m0); + sc->tx_errors++; + continue; + } + /* + * Packet has too many fragments - defrag into new mbuf + * cluster + */ + if (error) { + m = m_defrag(m0, MB_DONTWAIT); + if (m == NULL) { + m_freem(m0); + sc->tx_errors++; + continue; + } + m_freem(m0); + m0 = m; + + error = bus_dmamap_load_mbuf(sc->mtag, buf->map, m, + nv_dmamap_tx_cb, desc, BUS_DMA_NOWAIT); + if (error) { + m_freem(m); + sc->tx_errors++; + continue; + } + } + /* Do sync on DMA bounce buffer */ + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREWRITE); + + buf->mbuf = m0; + txdata.ulNumberOfElements = desc->numfrags; + txdata.pvID = (PVOID)desc; + + /* Put fragments into API element list */ + txdata.ulTotalLength = buf->mbuf->m_len; + for (i = 0; i < desc->numfrags; i++) { + txdata.sElement[i].ulLength = (ulong)desc->frags[i].ds_len; + txdata.sElement[i].pPhysical = (PVOID)desc->frags[i].ds_addr; + } + + /* Send packet to Nvidia API for transmission */ + error = sc->hwapi->pfnWrite(sc->hwapi->pADCX, &txdata); + + switch (error) { + case ADAPTERERR_NONE: + /* Packet was queued in API TX queue successfully */ + sc->pending_txs++; + sc->cur_tx = (sc->cur_tx + 1) % TX_RING_SIZE; + break; + + case ADAPTERERR_TRANSMIT_QUEUE_FULL: + /* The API TX queue is full - requeue the packet */ + device_printf(sc->dev, "nv_ifstart: transmit queue is full\n"); + ifp->if_flags |= IFF_OACTIVE; + bus_dmamap_unload(sc->mtag, buf->map); + IF_PREPEND(&ifp->if_snd, buf->mbuf); + buf->mbuf = NULL; + return; + + default: + /* The API failed to queue/send the packet so dump it */ + device_printf(sc->dev, "nv_ifstart: transmit error\n"); + bus_dmamap_unload(sc->mtag, buf->map); + m_freem(buf->mbuf); + buf->mbuf = NULL; + sc->tx_errors++; + return; + } + /* Set watchdog timer. */ + ifp->if_timer = 8; + + /* Copy packet to BPF tap */ + BPF_MTAP(ifp, m0); + } + ifp->if_flags |= IFF_OACTIVE; + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_ifstart - exit\n"); +} + +/* Handle IOCTL events */ +static int +nv_ioctl(struct ifnet *ifp, u_long command, caddr_t data, struct ucred *cr) +{ + struct nv_softc *sc = ifp->if_softc; + struct ifreq *ifr = (struct ifreq *) data; + struct mii_data *mii; + int error = 0; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_IOCTL, "nv: nv_ioctl - entry\n"); + + switch (command) { + case SIOCSIFMTU: + /* Set MTU size */ + if (ifp->if_mtu == ifr->ifr_mtu) + break; + if (ifr->ifr_mtu + ifp->if_hdrlen <= MAX_PACKET_SIZE) { + ifp->if_mtu = ifr->ifr_mtu; + nv_stop(sc); + nv_init(sc); + } else + error = EINVAL; + break; + + case SIOCSIFFLAGS: + /* Setup interface flags */ + if (ifp->if_flags & IFF_UP) { + if ((ifp->if_flags & IFF_RUNNING) == 0) { + nv_init(sc); + break; + } + } else { + if (ifp->if_flags & IFF_RUNNING) { + nv_stop(sc); + break; + } + } + + /* Handle IFF_PROMISC and IFF_ALLMULTI flags. */ + nv_setmulti(sc); + break; + + case SIOCADDMULTI: + case SIOCDELMULTI: + /* Setup multicast filter */ + if (ifp->if_flags & IFF_RUNNING) { + nv_setmulti(sc); + } + break; + case SIOCGIFMEDIA: + case SIOCSIFMEDIA: + /* Get/Set interface media parameters */ + mii = device_get_softc(sc->miibus); + error = ifmedia_ioctl(ifp, ifr, &mii->mii_media, command); + break; + + default: + /* Everything else we forward to generic ether ioctl */ + error = ether_ioctl(ifp, (int)command, data); + break; + } + + DEBUGOUT(NV_DEBUG_IOCTL, "nv: nv_ioctl - exit\n"); + + NV_UNLOCK(sc); + + return (error); +} + +/* Interrupt service routine */ +static void +nv_intr(void *arg) +{ + struct nv_softc *sc = arg; + struct ifnet *ifp = &sc->sc_if; + + DEBUGOUT(NV_DEBUG_INTERRUPT, "nv: nv_intr - entry\n"); + + if (!ifp->if_flags & IFF_UP) { + nv_stop(sc); + return; + } + /* Handle interrupt event */ + if (sc->hwapi->pfnQueryInterrupt(sc->hwapi->pADCX)) { + sc->hwapi->pfnHandleInterrupt(sc->hwapi->pADCX); + sc->hwapi->pfnEnableInterrupts(sc->hwapi->pADCX); + } + if (ifp->if_snd.ifq_head != NULL) + nv_ifstart(ifp); + + /* If no pending packets we don't need a timeout */ + if (sc->pending_txs == 0) + sc->sc_if.if_timer = 0; + + DEBUGOUT(NV_DEBUG_INTERRUPT, "nv: nv_intr - exit\n"); + + return; +} + +/* Setup multicast filters */ +static void +nv_setmulti(struct nv_softc *sc) +{ + struct ifnet *ifp; + struct ifmultiaddr *ifma; + PACKET_FILTER hwfilter; + int i; + u_int8_t oraddr[6]; + u_int8_t andaddr[6]; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_setmulti - entry\n"); + + ifp = &sc->sc_if; + + /* Initialize filter */ + hwfilter.ulFilterFlags = 0; + for (i = 0; i < 6; i++) { + hwfilter.acMulticastAddress[i] = 0; + hwfilter.acMulticastMask[i] = 0; + } + + if (ifp->if_flags & (IFF_PROMISC | IFF_ALLMULTI)) { + /* Accept all packets */ + hwfilter.ulFilterFlags |= ACCEPT_ALL_PACKETS; + sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter); + NV_UNLOCK(sc); + return; + } + /* Setup multicast filter */ + LIST_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { + u_char *addrp; + + if (ifma->ifma_addr->sa_family != AF_LINK) + continue; + + addrp = LLADDR((struct sockaddr_dl *) ifma->ifma_addr); + for (i = 0; i < 6; i++) { + u_int8_t mcaddr = addrp[i]; + andaddr[i] &= mcaddr; + oraddr[i] |= mcaddr; + } + } + for (i = 0; i < 6; i++) { + hwfilter.acMulticastAddress[i] = andaddr[i] & oraddr[i]; + hwfilter.acMulticastMask[i] = andaddr[i] | (~oraddr[i]); + } + + /* Send filter to NVIDIA API */ + sc->hwapi->pfnSetPacketFilter(sc->hwapi->pADCX, &hwfilter); + + NV_UNLOCK(sc); + + DEBUGOUT(NV_DEBUG_RUNNING, "nv: nv_setmulti - exit\n"); + + return; +} + +/* Change the current media/mediaopts */ +static int +nv_ifmedia_upd(struct ifnet *ifp) +{ + struct nv_softc *sc = ifp->if_softc; + struct mii_data *mii; + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_ifmedia_upd\n"); + + mii = device_get_softc(sc->miibus); + + if (mii->mii_instance) { + struct mii_softc *miisc; + for (miisc = LIST_FIRST(&mii->mii_phys); miisc != NULL; + miisc = LIST_NEXT(miisc, mii_list)) { + mii_phy_reset(miisc); + } + } + mii_mediachg(mii); + + return (0); +} + +/* Update current miibus PHY status of media */ +static void +nv_ifmedia_sts(struct ifnet *ifp, struct ifmediareq *ifmr) +{ + struct nv_softc *sc; + struct mii_data *mii; + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_ifmedia_sts\n"); + + sc = ifp->if_softc; + mii = device_get_softc(sc->miibus); + mii_pollstat(mii); + + ifmr->ifm_active = mii->mii_media_active; + ifmr->ifm_status = mii->mii_media_status; + + return; +} + +/* miibus tick timer - maintain link status */ +static void +nv_tick(void *xsc) +{ + struct nv_softc *sc = xsc; + struct mii_data *mii; + struct ifnet *ifp; + + NV_LOCK(sc); + + ifp = &sc->sc_if; + nv_update_stats(sc); + + mii = device_get_softc(sc->miibus); + mii_tick(mii); + + if (mii->mii_media_status & IFM_ACTIVE && + IFM_SUBTYPE(mii->mii_media_active) != IFM_NONE) { + if (ifp->if_snd.ifq_head != NULL) + nv_ifstart(ifp); + } + sc->stat_ch = timeout(nv_tick, sc, hz); + + NV_UNLOCK(sc); + + return; +} + +/* Update ifnet data structure with collected interface stats from API */ +static void +nv_update_stats(struct nv_softc *sc) +{ + struct ifnet *ifp = &sc->sc_if; + ADAPTER_STATS stats; + + NV_LOCK(sc); + + if (sc->hwapi) { + sc->hwapi->pfnGetStatistics(sc->hwapi->pADCX, &stats); + + ifp->if_ipackets = stats.ulSuccessfulReceptions; + ifp->if_ierrors = stats.ulMissedFrames + + stats.ulFailedReceptions + + stats.ulCRCErrors + + stats.ulFramingErrors + + stats.ulOverFlowErrors; + + ifp->if_opackets = stats.ulSuccessfulTransmissions; + ifp->if_oerrors = sc->tx_errors + + stats.ulFailedTransmissions + + stats.ulRetryErrors + + stats.ulUnderflowErrors + + stats.ulLossOfCarrierErrors + + stats.ulLateCollisionErrors; + + ifp->if_collisions = stats.ulLateCollisionErrors; + } + NV_UNLOCK(sc); + + return; +} + +/* miibus Read PHY register wrapper - calls Nvidia API entry point */ +static int +nv_miibus_readreg(device_t dev, int phy, int reg) +{ + struct nv_softc *sc = device_get_softc(dev); + ulong data; + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_readreg - entry\n"); + + ADAPTER_ReadPhy(sc->hwapi->pADCX, phy, reg, &data); + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_readreg - exit\n"); + + return (data); +} + +/* miibus Write PHY register wrapper - calls Nvidia API entry point */ +static void +nv_miibus_writereg(device_t dev, int phy, int reg, int data) +{ + struct nv_softc *sc = device_get_softc(dev); + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_writereg - entry\n"); + + ADAPTER_WritePhy(sc->hwapi->pADCX, phy, reg, (ulong)data); + + DEBUGOUT(NV_DEBUG_MII, "nv: nv_miibus_writereg - exit\n"); + + return; +} + +/* Watchdog timer to prevent PHY lockups */ +static void +nv_watchdog(struct ifnet *ifp) +{ + struct nv_softc *sc = ifp->if_softc; + + device_printf(sc->dev, "device timeout\n"); + + sc->tx_errors++; + + nv_stop(sc); + ifp->if_flags &= ~IFF_RUNNING; + nv_init(sc); + + if (ifp->if_snd.ifq_head != NULL) + nv_ifstart(ifp); + + return; +} + +/* --- Start of NVOSAPI interface --- */ + +/* Allocate DMA enabled general use memory for API */ +static int +nv_osalloc(void *ctx, MEMORY_BLOCK *mem) +{ + struct nv_softc *sc; + bus_addr_t mem_physical; + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osalloc - %d\n", mem->uiLength); + + sc = (struct nv_softc *)ctx; + + mem->pLogical = (PVOID)contigmalloc(mem->uiLength, M_DEVBUF, + M_NOWAIT | M_ZERO, 0, ~0, PAGE_SIZE, 0); + + if (!mem->pLogical) { + device_printf(sc->dev, "memory allocation failed\n"); + return (0); + } + memset(mem->pLogical, 0, (ulong)mem->uiLength); + mem_physical = vtophys(mem->pLogical); + mem->pPhysical = (PVOID)mem_physical; + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osalloc 0x%x/0x%x - %d\n", + (u_int32_t) mem->pLogical, + (u_int32_t) mem->pPhysical, mem->uiLength); + + return (1); +} + +/* Free allocated memory */ +static int +nv_osfree(void *ctx, MEMORY_BLOCK *mem) +{ + DEBUGOUT(NV_DEBUG_API, "nv: nv_osfree - 0x%x - %d\n", + (u_int32_t) mem->pLogical, mem->uiLength); + + contigfree(mem->pLogical, PAGE_SIZE, M_DEVBUF); + return (1); +} + +/* Copied directly from nvnet.c */ +static int +nv_osallocex(void *ctx, MEMORY_BLOCKEX *mem_block_ex) +{ + MEMORY_BLOCK mem_block; + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osallocex\n"); + + mem_block_ex->pLogical = NULL; + mem_block_ex->uiLengthOrig = mem_block_ex->uiLength; + + if ((mem_block_ex->AllocFlags & ALLOC_MEMORY_ALIGNED) && + (mem_block_ex->AlignmentSize > 1)) { + DEBUGOUT(NV_DEBUG_API, " aligning on %d\n", + mem_block_ex->AlignmentSize); + mem_block_ex->uiLengthOrig += mem_block_ex->AlignmentSize; + } + mem_block.uiLength = mem_block_ex->uiLengthOrig; + + if (nv_osalloc(ctx, &mem_block) == 0) { + return (0); + } + mem_block_ex->pLogicalOrig = mem_block.pLogical; + mem_block_ex->pPhysicalOrigLow = (ULONG)mem_block.pPhysical; + mem_block_ex->pPhysicalOrigHigh = 0; + + mem_block_ex->pPhysical = mem_block.pPhysical; + mem_block_ex->pLogical = mem_block.pLogical; + + if (mem_block_ex->uiLength != mem_block_ex->uiLengthOrig) { + unsigned int offset; + offset = mem_block_ex->pPhysicalOrigLow & (mem_block_ex->AlignmentSize - 1); + + if (offset) { + mem_block_ex->pPhysical = (PVOID)((ULONG)mem_block_ex->pPhysical + + mem_block_ex->AlignmentSize - offset); + mem_block_ex->pLogical = (PVOID)((ULONG)mem_block_ex->pLogical + + mem_block_ex->AlignmentSize - offset); + } /* if (offset) */ + } /* if (mem_block_ex->uiLength != + * mem_block_ex->uiLengthOrig) */ + return (1); +} + +/* Copied directly from nvnet.c */ +static int +nv_osfreeex(void *ctx, MEMORY_BLOCKEX *mem_block_ex) +{ + MEMORY_BLOCK mem_block; + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osfreeex\n"); + + mem_block.pLogical = mem_block_ex->pLogicalOrig; + mem_block.pPhysical = (PVOID)mem_block_ex->pPhysicalOrigLow; + mem_block.uiLength = mem_block_ex->uiLengthOrig; + + return (nv_osfree(ctx, &mem_block)); +} + +/* Clear memory region */ +static int +nv_osclear(void *ctx, void *mem, int length) +{ + DEBUGOUT(NV_DEBUG_API, "nv: nv_osclear\n"); + memset(mem, 0, length); + return (1); +} + +/* Sleep for a tick */ +static int +nv_osdelay(void *ctx, unsigned long usec) +{ + DELAY(usec); + return (1); +} + +/* Allocate memory for rx buffer */ +static int +nv_osallocrxbuf(void *ctx, MEMORY_BLOCK *mem, void **id) +{ + struct nv_softc *sc = ctx; + struct nv_rx_desc *desc; + struct nv_map_buffer *buf; + int error; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osallocrxbuf\n"); + + if (sc->pending_rxs == RX_RING_SIZE) { + device_printf(sc->dev, "rx ring buffer is full\n"); + goto fail; + } + desc = sc->rx_desc + sc->cur_rx; + buf = &desc->buf; + + if (buf->mbuf == NULL) { + buf->mbuf = m_getcl(MB_DONTWAIT, MT_DATA, M_PKTHDR); + if (buf->mbuf == NULL) { + device_printf(sc->dev, "failed to allocate memory\n"); + goto fail; + } + buf->mbuf->m_len = buf->mbuf->m_pkthdr.len = MCLBYTES; + m_adj(buf->mbuf, ETHER_ALIGN); + + error = bus_dmamap_load_mbuf(sc->mtag, buf->map, buf->mbuf, + nv_dmamap_rx_cb, &desc->paddr, 0); + if (error) { + device_printf(sc->dev, "failed to dmamap mbuf\n"); + m_freem(buf->mbuf); + buf->mbuf = NULL; + goto fail; + } + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_PREREAD); + desc->buflength = buf->mbuf->m_len; + desc->vaddr = mtod(buf->mbuf, PVOID); + } + sc->pending_rxs++; + sc->cur_rx = (sc->cur_rx + 1) % RX_RING_SIZE; + + mem->pLogical = (void *)desc->vaddr; + mem->pPhysical = (void *)desc->paddr; + mem->uiLength = desc->buflength; + *id = (void *)desc; + +fail: + NV_UNLOCK(sc); + + return (1); +} + + +/* Free the rx buffer */ +static int +nv_osfreerxbuf(void *ctx, MEMORY_BLOCK *mem, void *id) +{ + struct nv_softc *sc = ctx; + struct nv_rx_desc *desc; + struct nv_map_buffer *buf; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_API, "nv: nv_osfreerxbuf\n"); + + desc = (struct nv_rx_desc *) id; + buf = &desc->buf; + + if (buf->mbuf) { + bus_dmamap_unload(sc->mtag, buf->map); + bus_dmamap_destroy(sc->mtag, buf->map); + m_freem(buf->mbuf); + } + sc->pending_rxs--; + buf->mbuf = NULL; + + NV_UNLOCK(sc); + + return (1); +} + +/* This gets called by the Nvidia API after our TX packet has been sent */ +static int +nv_ospackettx(void *ctx, void *id, unsigned long success) +{ + struct nv_softc *sc = ctx; + struct nv_map_buffer *buf; + struct nv_tx_desc *desc = (struct nv_tx_desc *) id; + struct ifnet *ifp; + + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_API, "nv: nv_ospackettx\n"); + + ifp = &sc->sc_if; + + buf = &desc->buf; + + if (buf->mbuf == NULL) + goto fail; + + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTWRITE); + bus_dmamap_unload(sc->mtag, buf->map); + m_freem(buf->mbuf); + buf->mbuf = NULL; + + sc->pending_txs--; + + if (ifp->if_snd.ifq_head != NULL && sc->pending_txs < TX_RING_SIZE) + nv_ifstart(ifp); + +fail: + NV_UNLOCK(sc); + + return (1); +} + +/* This gets called by the Nvidia API when a new packet has been received */ +/* XXX What is newbuf used for? XXX */ +static int +nv_ospacketrx(void *ctx, void *data, unsigned long success, + unsigned char *newbuf, unsigned char priority) +{ + struct nv_softc *sc = ctx; + struct ifnet *ifp; + struct nv_rx_desc *desc; + struct nv_map_buffer *buf; + ADAPTER_READ_DATA *readdata; + NV_LOCK(sc); + + DEBUGOUT(NV_DEBUG_API, "nv: nv_ospacketrx\n"); + + ifp = &sc->sc_if; + + readdata = (ADAPTER_READ_DATA *) data; + desc = readdata->pvID; + buf = &desc->buf; + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); + + if (success) { + /* Sync DMA bounce buffer. */ + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); + + /* First mbuf in packet holds the ethernet and packet headers */ + buf->mbuf->m_pkthdr.rcvif = ifp; + buf->mbuf->m_pkthdr.len = buf->mbuf->m_len = readdata->ulTotalLength; + + bus_dmamap_unload(sc->mtag, buf->map); + + /* Give mbuf to OS. */ + (*ifp->if_input) (ifp, buf->mbuf); + if (readdata->ulFilterMatch & ADREADFL_MULTICAST_MATCH) + ifp->if_imcasts++; + + /* Blat the mbuf pointer, kernel will free the mbuf cluster */ + buf->mbuf = NULL; + } else { + bus_dmamap_sync(sc->mtag, buf->map, BUS_DMASYNC_POSTREAD); + bus_dmamap_unload(sc->mtag, buf->map); + m_freem(buf->mbuf); + buf->mbuf = NULL; + } + + sc->cur_rx = desc - sc->rx_desc; + sc->pending_rxs--; + + NV_UNLOCK(sc); + + return (1); +} + +/* This gets called by NVIDIA API when the PHY link state changes */ +static int +nv_oslinkchg(void *ctx, int enabled) +{ + struct nv_softc *sc = (struct nv_softc *)ctx; + struct ifnet *ifp; + + DEBUGOUT(NV_DEBUG_API, "nv: nv_oslinkchg\n"); + + ifp = &sc->sc_if; + + if (enabled) + ifp->if_flags |= IFF_UP; + else + ifp->if_flags &= ~IFF_UP; + + + return (1); +} + + +/* Setup a watchdog timer */ +static int +nv_osalloctimer(void *ctx, void **timer) +{ + struct nv_softc *sc = (struct nv_softc *)ctx; + + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osalloctimer\n"); + + callout_handle_init(&sc->ostimer); + *timer = &sc->ostimer; + + return (1); +} + +/* Free the timer */ +static int +nv_osfreetimer(void *ctx, void *timer) +{ + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osfreetimer\n"); + + return (1); +} + +/* Setup timer parameters */ +static int +nv_osinittimer(void *ctx, void *timer, PTIMER_FUNC func, void *parameters) +{ + struct nv_softc *sc = (struct nv_softc *)ctx; + + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osinittimer\n"); + + sc->ostimer_func = func; + sc->ostimer_params = parameters; + + return (1); +} + +/* Set the timer to go off */ +static int +nv_ossettimer(void *ctx, void *timer, unsigned long delay) +{ + struct nv_softc *sc = ctx; + + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ossettimer\n"); + + *(struct callout_handle *) timer = timeout(sc->ostimer_func, sc->ostimer_params, delay); + + return (1); +} + +/* Cancel the timer */ +static int +nv_oscanceltimer(void *ctx, void *timer) +{ + struct nv_softc *sc = ctx; + + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_oscanceltimer\n"); + + untimeout(sc->ostimer_func, sc->ostimer_params, *(struct callout_handle *) timer); + + return (1); +} + +static int +nv_ospreprocpkt(void *ctx, void *readdata, void **id, unsigned char *newbuffer, + unsigned char priority) +{ + /* Not implemented */ + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ospreprocpkt\n"); + + return (1); +} + +static void + * +nv_ospreprocpktnopq(void *ctx, void *readdata) +{ + /* Not implemented */ + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_ospreprocpkt\n"); + + return (NULL); +} + +static int +nv_osindicatepkt(void *ctx, void **id, unsigned long pktno) +{ + /* Not implemented */ + DEBUGOUT(NV_DEBUG_BROKEN, "nv: nv_osindicatepkt\n"); + + return (1); +} + +/* Allocate mutex context (already done in nv_attach) */ +static int +nv_oslockalloc(void *ctx, int type, void **pLock) +{ + struct nv_softc *sc = (struct nv_softc *)ctx; + + DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockalloc\n"); + + *pLock = (void **)sc; + + return (1); +} + +/* Obtain a spin lock */ +static int +nv_oslockacquire(void *ctx, int type, void *lock) +{ + DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockacquire\n"); + + NV_OSLOCK((struct nv_softc *)lock); + + return (1); +} + +/* Release lock */ +static int +nv_oslockrelease(void *ctx, int type, void *lock) +{ + DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_oslockrelease\n"); + + NV_OSUNLOCK((struct nv_softc *)lock); + + return (1); +} + +/* I have no idea what this is for */ +static void * +nv_osreturnbufvirt(void *ctx, void *readdata) +{ + /* Not implemented */ + DEBUGOUT(NV_DEBUG_LOCK, "nv: nv_osreturnbufvirt\n"); + panic("nv: nv_osreturnbufvirtual not implemented\n"); + + return (NULL); +} + + +/* --- End on NVOSAPI interface --- */ diff --git a/sys/dev/netif/nv/if_nvreg.h b/sys/dev/netif/nv/if_nvreg.h new file mode 100644 index 0000000000..55c82e8113 --- /dev/null +++ b/sys/dev/netif/nv/if_nvreg.h @@ -0,0 +1,169 @@ +/* + * Copyright (c) 2003 by Quinton Dolan . + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS `AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $Id: if_nvreg.h,v 1.3 2003/11/08 13:03:01 q Exp $ + * $DragonFly: src/sys/dev/netif/nv/Attic/if_nvreg.h,v 1.1 2004/08/28 15:08:02 joerg Exp $ + */ + +#ifndef _IF_NVREG_H_ +#define _IF_NVREG_H_ + +#include "basetype.h" +#include "os.h" +#include "adapter.h" + +#ifndef NVIDIA_VENDORID +#define NVIDIA_VENDORID 0x10DE +#endif + +#define NFORCE_MCPNET1_DEVICEID 0x01C3 +#define NFORCE_MCPNET2_DEVICEID 0x0066 +#define NFORCE_MCPNET3_DEVICEID 0x00D6 + +#define NV_RID 0x10 + +#define TX_RING_SIZE 64 +#define RX_RING_SIZE 64 + +#define NV_MAX_FRAGS 63 + +#define NV_DEBUG_INIT 0x0001 +#define NV_DEBUG_RUNNING 0x0002 +#define NV_DEBUG_DEINIT 0x0004 +#define NV_DEBUG_IOCTL 0x0008 +#define NV_DEBUG_INTERRUPT 0x0010 +#define NV_DEBUG_API 0x0020 +#define NV_DEBUG_LOCK 0x0040 +#define NV_DEBUG_BROKEN 0x0080 +#define NV_DEBUG_MII 0x0100 +#define NV_DEBUG_ALL 0xFFFF + +#define NV_DEBUG 0x0000 + +#if NV_DEBUG +#define DEBUGOUT(level, fmt, args...) if (NV_DEBUG & level) \ + printf(fmt, ## args) +#else +#define DEBUGOUT(level, fmt, args...) +#endif + +typedef unsigned long ulong; + +struct nv_map_buffer { + struct mbuf *mbuf; /* mbuf receiving packet */ + bus_dmamap_t map; /* DMA map */ +}; + +struct nv_dma_info { + bus_dma_tag_t tag; + struct nv_map_buffer buf; + u_int16_t buflength; + caddr_t vaddr; /* Virtual memory address */ + bus_addr_t paddr; /* DMA physical address */ +}; + +struct nv_rx_desc { + struct nv_rx_desc *next; + struct nv_map_buffer buf; + u_int16_t buflength; + caddr_t vaddr; + bus_addr_t paddr; +}; + +struct nv_tx_desc { + /* Don't add anything above this structure */ + TX_INFO_ADAP TxInfoAdap; + struct nv_tx_desc *next; + struct nv_map_buffer buf; + u_int16_t buflength; + u_int32_t numfrags; + bus_dma_segment_t frags[NV_MAX_FRAGS + 1]; +}; + +struct nv_softc { + struct arpcom arpcom; /* interface info */ + struct resource *res; + struct resource *irq; + + ADAPTER_API *hwapi; + OS_API osapi; + + device_t miibus; + device_t dev; + struct callout_handle stat_ch; + + u_int32_t unit; + void *sc_ih; + bus_space_tag_t sc_st; + bus_space_handle_t sc_sh; + bus_dma_tag_t mtag; + bus_dma_tag_t rtag; + bus_dmamap_t rmap; + bus_dma_tag_t ttag; + bus_dmamap_t tmap; + + struct nv_rx_desc *rx_desc; + struct nv_tx_desc *tx_desc; + bus_addr_t rx_addr; + bus_addr_t tx_addr; + u_int16_t rx_ring_full; + u_int16_t tx_ring_full; + u_int32_t cur_rx; + u_int32_t cur_tx; + u_int32_t pending_rxs; + u_int32_t pending_txs; + + u_int32_t flags; + u_int32_t miicfg; + int spl; + + /* Stuff for dealing with the NVIDIA OS API */ + struct callout_handle ostimer; + PTIMER_FUNC ostimer_func; + void *ostimer_params; + unsigned int linkup; + ulong tx_errors; + ulong phyaddr; + unsigned char original_mac_addr[6]; +}; + +struct nv_type { + u_int16_t vid_id; + u_int16_t dev_id; + char *name; +}; + +#define sc_if arpcom.ac_if +#define sc_macaddr arpcom.ac_enaddr + +#define NV_LOCK(_sc) int s = splimp() +#define NV_UNLOCK(_sc) splx(s) +#define NV_OSLOCK(_sc) (int)(_sc)->spl = splimp() +#define NV_OSUNLOCK(_sc) splx((int)(_sc)->spl) + +extern int ADAPTER_ReadPhy (PVOID pContext, ULONG ulPhyAddr, ULONG ulReg, ULONG *pulVal); +extern int ADAPTER_WritePhy (PVOID pContext, ULONG ulPhyAddr, ULONG ulReg, ULONG ulVal); +extern int ADAPTER_Init (PVOID pContext, USHORT usForcedSpeed, UCHAR ucForceDpx, UCHAR ucForceMode, UINT *puiLinkState); +#endif diff --git a/sys/dev/netif/nv/os.h.patch b/sys/dev/netif/nv/os.h.patch new file mode 100644 index 0000000000..cd2636e550 --- /dev/null +++ b/sys/dev/netif/nv/os.h.patch @@ -0,0 +1,62 @@ +$DragonFly: src/sys/dev/netif/nv/Attic/os.h.patch,v 1.1 2004/08/28 15:08:02 joerg Exp $ + +diff -u nvnet/os.h nv/os.h +--- nvnet/os.h 2003-05-06 21:39:38.000000000 +0200 ++++ nv/os.h 2004-08-19 18:17:37.000000000 +0200 +@@ -13,9 +13,9 @@ + + #define HDO_VERSION_STRING "HDR O: $Revision: #21 $"; + +-// This is the maximum packet size that we will be sending ++/* This is the maximum packet size that we will be sending */ + #define MAX_PACKET_SIZE 2048 +-//#define RX_BUFFER_SIZE 2048 ++/* #define RX_BUFFER_SIZE 2048 */ + + typedef struct _MEMORY_BLOCK + { +@@ -34,7 +34,7 @@ + UINT uiLength; + /* Parameter to OS layer to indicate what type of memory is needed */ + USHORT AllocFlags; +- USHORT AlignmentSize; //always power of 2 ++ USHORT AlignmentSize; /* always power of 2 */ + /* Following three fields used for aligned memory allocation */ + PVOID pLogicalOrig; + ULONG pPhysicalOrigLow; +@@ -43,7 +43,7 @@ + } MEMORY_BLOCKEX, *PMEMORY_BLOCKEX; + + +-// The typedefs for the OS functions ++/* The typedefs for the OS functions */ + typedef int (* PFN_MEMORY_ALLOC) (PVOID pOSCX, PMEMORY_BLOCK pMem); + typedef int (* PFN_MEMORY_FREE) (PVOID pOSCX, PMEMORY_BLOCK pMem); + typedef int (* PFN_MEMORY_ALLOCEX) (PVOID pOSCX, PMEMORY_BLOCKEX pMem); +@@ -70,14 +70,16 @@ + typedef int (* PFN_LOCK_RELEASE) (PVOID pOSCX, int iLockType, PVOID pvLock); + typedef PVOID (* PFN_RETURN_BUFFER_VIRTUAL) (PVOID pvContext, PVOID pvADReadData); + +-// Here are the OS functions that those objects below the OS interface +-// can call up to. ++/* ++ * Here are the OS functions that those objects below the OS interface ++ * can call up to. ++ */ + typedef struct _OS_API + { +- // OS Context -- this is a parameter to every OS API call ++ /* OS Context -- this is a parameter to every OS API call */ + PVOID pOSCX; + +- // Basic OS functions ++ /* Basic OS functions */ + PFN_MEMORY_ALLOC pfnAllocMemory; + PFN_MEMORY_FREE pfnFreeMemory; + PFN_MEMORY_ALLOCEX pfnAllocMemoryEx; +@@ -103,4 +105,4 @@ + PFN_RETURN_BUFFER_VIRTUAL pfnReturnBufferVirtual; + } OS_API, *POS_API; + +-#endif // _OS_H_ ++#endif /* _OS_H_ */ diff --git a/sys/dev/netif/nv/phy.h.patch b/sys/dev/netif/nv/phy.h.patch new file mode 100644 index 0000000000..0fe6e40efa --- /dev/null +++ b/sys/dev/netif/nv/phy.h.patch @@ -0,0 +1,130 @@ +$DragonFly: src/sys/dev/netif/nv/Attic/phy.h.patch,v 1.1 2004/08/28 15:08:02 joerg Exp $ + +diff -u nvnet/phy.h nv/phy.h +--- nvnet/phy.h 2003-05-06 21:39:38.000000000 +0200 ++++ nv/phy.h 2004-08-19 18:16:29.000000000 +0200 +@@ -20,13 +20,14 @@ + + #define HDP_VERSION_STRING "HDR P: $Revision: #23 $" + +-///////////////////////////////////////////////////////////////////////// +-// The phy module knows the values that need to go into the phy registers +-// but typically the method of writing those registers is controlled by +-// another module (usually the adapter because it is really the hardware +-// interface.) Hence, the phy needs routines to call to read and write the +-// phy registers. This structure with appropriate routines will be provided +-// in the PHY_Open call. ++/************************************************************************** ++ * The phy module knows the values that need to go into the phy registers ++ * but typically the method of writing those registers is controlled by ++ * another module (usually the adapter because it is really the hardware ++ * interface.) Hence, the phy needs routines to call to read and write the ++ * phy registers. This structure with appropriate routines will be provided ++ * in the PHY_Open call. ++ */ + + typedef int (* PFN_READ_PHY) (PVOID pvData, ULONG ulPhyAddr, ULONG ulPhyReg, ULONG *pulValue); + typedef int (* PFN_WRITE_PHY) (PVOID pvData, ULONG ulPhyAddr, ULONG ulPhyReg, ULONG ulValue); +@@ -37,11 +38,11 @@ + PFN_READ_PHY pfnRead; + PFN_WRITE_PHY pfnWrite; + } PHY_SUPPORT_API, *PPHY_SUPPORT_API; +-///////////////////////////////////////////////////////////////////////// ++/***********************************************************************/ + +- +-///////////////////////////////////////////////////////////////////////// +-// The functional typedefs for the PHY Api ++/*********************************************************************** ++ * The functional typedefs for the PHY Api ++ */ + typedef int (* PFN_PHY_INIT) (PVOID pvContext, ULONG *pulLinkState); + typedef int (* PFN_PHY_DEINIT) (PVOID pvContext); + typedef int (* PFN_PHY_CLOSE) (PVOID pvContext); +@@ -55,8 +56,10 @@ + + typedef struct _PHY_API + { +- // This is the context to pass back in as the first arg on all +- // the calls in the API below. ++ /* ++ * This is the context to pass back in as the first arg on all ++ * the calls in the API below. ++ */ + PVOID pPHYCX; + + PFN_PHY_INIT pfnInit; +@@ -71,22 +74,24 @@ + PFN_FORCE_SPEED_DUPLEX pfnForceSpeedDuplex; + PFN_PHY_POWERDOWN pfnPowerdown; + } PHY_API, *PPHY_API; +-///////////////////////////////////////////////////////////////////////// ++/***********************************************************************/ + + +-///////////////////////////////////////////////////////////////////////// +-// This is the one function in the PHY interface that is publicly +-// available. The rest of the interface is returned in the pPhyApi; +-// The first argument needs to be cast to a POS_API structure ptr. +-// On input the second argument is a ptr to a PPHY_SUPPORT_API. +-// On output, the second argument should be treated as a ptr to a +-// PPHY_API and set appropriately. ++/*********************************************************************** ++ * This is the one function in the PHY interface that is publicly ++ * available. The rest of the interface is returned in the pPhyApi; ++ * The first argument needs to be cast to a POS_API structure ptr. ++ * On input the second argument is a ptr to a PPHY_SUPPORT_API. ++ * On output, the second argument should be treated as a ptr to a ++ * PPHY_API and set appropriately. ++ */ + extern int PHY_Open (PVOID pvOSApi, PVOID pPhyApi, ULONG *pulIsHPNAPhy, ULONG *pulPhyAddr, ULONG *pulPhyConnected); +-///////////////////////////////////////////////////////////////////////// ++/***********************************************************************/ + + +-///////////////////////////////////////////////////////////////////////// +-// Here are the error codes the phy functions can return. ++/*********************************************************************** ++ * Here are the error codes the phy functions can return. ++ */ + #define PHYERR_NONE 0x0000 + #define PHYERR_COULD_NOT_ALLOC_CONTEXT 0x0001 + #define PHYERR_RESET_NEVER_FINISHED 0x0002 +@@ -99,12 +104,13 @@ + + #define PHY_INVALID_PHY_ADDR 0xFFFF; + +-///////////////////////////////////////////////////////////////////////// ++/***********************************************************************/ + + + #ifdef AMDHPNA10 +-///////////////////////////////////////////////////////////////////////// +-// Here are the Phy Timer related structure. (For AMD HPNA) ++/*********************************************************************** ++ * Here are the Phy Timer related structure. (For AMD HPNA) ++ */ + typedef void (* PFN_PHY_TIMER) (PVOID pvData, ULONG macActive); + + typedef struct PHY_TIMER_API +@@ -113,16 +119,16 @@ + ULONG ulPeriod; // unit of MilliSeconds + PFN_PHY_TIMER pfnPhyTimer; + } PHY_TIMER_API, *PPHY_TIMER_API; +-///////////////////////////////////////////////////////////////////////// ++/***********************************************************************/ + #endif + +-// This value can be used in the ulPhyLinkSpeed field. ++/* This value can be used in the ulPhyLinkSpeed field. */ + #define PHY_LINK_SPEED_UNKNOWN 0x0FFFFFFFF + + typedef void (* PTIMER_FUNC) (PVOID pvContext); + + #ifdef __cplusplus +-} // extern "C" ++} /* extern "C" */ + #endif + +-#endif //_PHY_H_ ++#endif /*_PHY_H_ */ -- 2.41.0