// Copyright (c) 1998-1999, Microsoft Corporation, all rights reserved // // priv.h // // IEEE 1394 NDIS mini-port/call-manager driver // // Main private header // // 12/28/1998 JosephJ Created (adapted from the l2tp project) // // //----------------------------------------------------------------------------- // Constants //----------------------------------------------------------------------------- extern ULONG g_IsochTag; extern LONG g_ulMedium; extern ULONGLONG g_ullOne; // // Add checks for #defines that are meant for special purposes and // should not be turned on for general use // #ifdef PKT_LOG #error #endif //----------------------------------------------------------------------------- // Advance Declarations and simple typedefs //----------------------------------------------------------------------------- // Forward declarations. // typedef union _VCCB VCCB; typedef struct _ADAPTERCB ADAPTERCB, *PADAPTERCB; typedef struct _RECVFIFO_VCCB RECVFIFO_VCCB, *PRECVFIFO_VCCB; typedef struct _ETHERNET_VCCB ETHERNET_VCCB, *PETHERNET_VCCB; typedef struct _RECV_FIFO_DATA RECV_FIFO_DATA, *PRECV_FIFO_DATA; typedef struct _ISOCH_DESCRIPTOR ISOCH_DESCRIPTOR, *PISOCH_DESCRIPTOR, **PPISOCH_DESCRIPTOR; typedef struct _TOPOLOGY_MAP TOPOLOGY_MAP, *PTOPOLOGY_MAP, **PPTOPOLOGY_MAP; typedef struct _CHANNEL_VCCB CHANNEL_VCCB, *PCHANNEL_VCCB; typedef struct _GASP_HEADER GASP_HEADER; typedef struct _NDIS1394_FRAGMENT_HEADER NDIS1394_FRAGMENT_HEADER, *PNDIS1394_FRAGMENT_HEADER; typedef struct _NDIS1394_REASSEMBLY_STRUCTURE NDIS1394_REASSEMBLY_STRUCTURE, *PNDIS1394_REASSEMBLY_STRUCTURE; typedef struct _REMOTE_NODE REMOTE_NODE, *PREMOTE_NODE; typedef union _NDIS1394_UNFRAGMENTED_HEADER NDIS1394_UNFRAGMENTED_HEADER, *PNDIS1394_UNFRAGMENTED_HEADER; typedef union _NIC_WORK_ITEM NIC_WORK_ITEM, *PNIC_WORK_ITEM; #define NIC1394_STATUS_INVALID_GENERATION ((NDIS_STATUS)STATUS_INVALID_GENERATION) //----------------------------------------------------------------------------- // Data types //----------------------------------------------------------------------------- // // This is a table of the Remote nodes and it is used to keep a track of the number of nodes // on the bus. To stop overflows, yhis structure is usally accessed by // NODE_ADDRESS.NA_Node_Number which is a 6 bit entity. // typedef struct _NODE_TABLE { PREMOTE_NODE RemoteNode[NIC1394_MAX_NUMBER_NODES]; } NODE_TABLE, *PNODE_TABLE; typedef struct _GASP_HEADER { union { // // Ist Quadlet // struct { ULONG GH_Specifier_ID_Hi:16; ULONG GH_Source_ID:16; } Bitmap; struct { USHORT GH_Specifier_ID_Hi; USHORT GH_Source_ID; } u; struct { USHORT GH_Specifier_ID_Hi; NODE_ADDRESS GH_NodeAddress; } u1; ULONG GaspHeaderHigh; } FirstQuadlet; union { struct { ULONG GH_Version:24; // Bits 0-23 ULONG GH_Specifier_ID_Lo:8; //Bits 24-31 } Bitmap; ULONG GaspHeaderLow; } SecondQuadlet; } GASP_HEADER, *PGASP_HEADER; // // The Ndis miniport's wrapper around the Packet Pool // typedef struct _NIC_PACKET_POOL { ULONG AllocatedPackets; NDIS_HANDLE Handle; } NIC_PACKET_POOL, *PNIC_PACKET_POOL; // // The Ndis miniport's wrapper around the Packet Pool // typedef struct _NIC_BUFFER_POOL { ULONG AllocatedBuffers; NDIS_HANDLE Handle; } NIC_BUFFER_POOL, *PNIC_BUFFER_POOL; // // The structure that defines the lookaside list used by this miniport // typedef struct _NIC_NPAGED_LOOKASIDE_LIST { // // The lookaside list structure // NPAGED_LOOKASIDE_LIST List; // // The size of an individual buffer // ULONG Size; // // Outstanding Fragments - Interlocked access only // ULONG OutstandingPackets; // // Lookaside Lists are used for sends. So this is a maximum // send packet size that this lookaside list can handle // ULONG MaxSendSize; } NIC_NPAGED_LOOKASIDE_LIST , *PNIC_NPAGED_LOOKASIDE_LIST ; // // Structure used for references, Adapted from Ndis // The Event will be signalled when the refcount goes down to zero // The filed closing signifies that the object that the reference belongs to is // closing and it;s refernces will not be incremented anymore // typedef struct _REF { // NDIS_SPIN_LOCK SpinLock; ULONG ReferenceCount; BOOLEAN Closing; NDIS_EVENT RefZeroEvent; } REF, * PREF; typedef enum _EVENT_CODE { Nic1394EventCode_InvalidEventCode, Nic1394EventCode_NewNodeArrived, nic1394EventCode_BusReset, nic1394EventCode_FreedAddressRange, nic1394EventCode_ReassemblyTimerComplete, nic1394EventCode_QueryPowerLowPower } EVENT_CODE, *PEVENT_CODE; typedef struct _NIC1394_EVENT { NDIS_EVENT NdisEvent; EVENT_CODE EventCode; } NIC1394_EVENT, *PNIC1394_EVENT; typedef ENetAddr MAC_ADDRESS, *PMAC_ADDRESS; // // nic Spin lock structure. Keeps track of the file and line numer // that last touched the lock // #define LOCK_FILE_NAME_LEN 48 typedef struct _NIC_SPIN_LOCK { #ifdef TRACK_LOCKS ULONG IsAcquired; // Internal tracking of lock state PKTHREAD OwnerThread; // thread that has the lock UCHAR TouchedByFileName[LOCK_FILE_NAME_LEN]; // File name which called Acquire Lock ULONG TouchedInLineNumber; // Line Number in the file #endif NDIS_SPIN_LOCK NdisLock; // Actual Lock } NIC_SPIN_LOCK, *PNIC_SPIN_LOCK; // // Statistics Structure - to be collected on a per adapter basis // typedef struct _NIC_SEND_RECV_STATS { ULONG ulSendNicSucess; ULONG ulSendBusSuccess; ULONG ulSendBusFail; ULONG ulSendNicFail; ULONG ulRecv; } NIC_SEND_RECV_STATS; // // These are stats that can be reset // typedef struct _RESETTABLE_STATS { ULONG ulNumOutstandingReassemblies; ULONG ulMaxOutstandingReassemblies; ULONG ulAbortedReassemblies; ULONG ulNumResetsIssued ; ULONG ulNumSends; ULONG ulNumSendsCompleted; ULONG ulNumBusSends; ULONG ulNumBusSendsCompleted; NIC_SEND_RECV_STATS Fifo; NIC_SEND_RECV_STATS Channel; } RESETTABLE_STATS, *PRESETTABLE_STATS; typedef struct _ADAPT_STATS { ULONG ulXmitOk; ULONG ulXmitError ; ULONG ulRcvOk ; ULONG ulRcvError ; ULONG ulNumResetsIssued ; ULONG ulNumResetCallbacks ; ULONG ulBCMIterations ; ULONG ulNumRemoteNodes; ULONG ulResetTime; RESETTABLE_STATS TempStats; } ADAPT_STATS, *PADAPT_STATS; // // Can be used to keep data in buckets of 10 // typedef struct _STAT_BUCKET { ULONG Bucket[16]; } STAT_BUCKET, *PSTAT_BUCKET; // // Generic structure to be used to serialize send and receives, workitems // typedef struct _NIC_SERIALIZATION { UINT PktsInQueue; // Number of packets in queue. BOOLEAN bTimerAlreadySet; BOOLEAN bInitialized; USHORT usPad; LIST_ENTRY Queue; // Serialized by adapter lock. union { NDIS_MINIPORT_TIMER Timer; NDIS_WORK_ITEM WorkItem; }; NIC1394_EVENT CompleteEvent; } NIC_SERIALIZATION, *PNIC_SERIALIZATION; // // Each request to allocate and address range // returns certain values that need to be stored for the // request to free the address range. This structure contains // those values // typedef struct _ADDRESS_RANGE_CONTEXT { // // Handle returned by the bus driver // HANDLE hAddressRange; // // Address Range returnded by the bus driver // ADDRESS_RANGE AddressRange; // // Number of Address returned from the call to // allocate address range // ULONG AddressesReturned; // // Mdl used in allocate address range . can be NULL // PMDL pMdl; } ADDRESS_RANGE_CONTEXT, *PADDRESS_RANGE_CONTEXT; // This structure is the Per Pdo/ per RecvFIFOVc structure. // This will be included in every Pdo Strcuture. And should contain // the fields that are related to the recvFifo and the Pdo block // typedef struct _RECV_FIFO_DATA { // // Indicates whether the address range was allocated regardless of the Make // Call State (pending or success) // BOOLEAN AllocatedAddressRange; // // Recv Vc's related data structures // ADDRESS_RANGE VcAddressRange; // The Bus Driver's Handle to the Address ranges that // the Nic was allocated // HANDLE hAddressRange; // This is the number of address ranges that the bus driver // returned. For now, it is expected to be one. // UINT AddressesReturned; // The Recv Fifo Vc that this structure is associated with // PRECVFIFO_VCCB pRecvFIFOVc; // The Pdo Associated with this structure // //DEVICE_OBJECT *pPdo; } RECV_FIFO_DATA, *PRECV_FIFO_DATA; // // Flags for the Broadcast Channel // #define BCR_LocalHostIsIRM 0x00000001 #define BCR_ChannelAllocated 0x00000002 #define BCR_LocalHostBCRUpdated 0x00000004 #define BCR_MakeCallPending 0x00000008 #define BCR_Initialized 0x00000010 #define BCR_BCMFailed 0x00000020 // Informational purposes only . Do not Test or REad #define BCR_InformingRemoteNodes 0x00000040 #define BCR_BCMInProgress 0x00000100 #define BCR_LastNodeRemoved 0x00000200 #define BCR_Freed 0x00000400 #define BCR_BCRNeedsToBeFreed 0x00000800 #define BCR_NewNodeArrived 0x00001000 #define BCR_NoNodesPresent 0x00002000 // // This is information useful in maintaining the BCR // Broadcast Channels Register. // typedef struct _BROADCAST_CHANNEL_DATA { // // Flags // ULONG Flags; // // IRM;s BCR. This is the actual record of the bus's IRM. And is meant to indicate the current state // NETWORK_CHANNELSR IRM_BCR; // // Broadcast Channels Register for the local host. This is the one a remote node will write to and read from // pLocalBcRMdl points to this structure . This is Byteswapped to reppresent the BigEndian 1394 Bus Format // ULONG LocalHostBCRBigEndian; // // Mdl pointing to Local Host BCR. Other machines will write to this MDL. // PMDL pLocalBCRMdl; // // Data pointed to by the pRemoteBCRMdl and will copied to IRM_BCR. The data that will be read will // be in the BigEndian format Pointed to by RemoteBCRMDl // ULONG RemoteBCRMdlData; // // MDL pointing to Remote Nodes' BCR. This will be used in reading other machine's // BCR. This points to the RemoteBCRMdlData // PMDL pRemoteBCRMdl; // // Make a copy of the BCR that is used in informing other nodes // about this node's BCR when the local node is the IRM // ULONG AsyncWriteBCRBigEndian; PMDL pAsyncWriteBCRMdl; // // Local Node Address. This changes from Reset to Reset // NODE_ADDRESS LocalNodeAddress; ULONG LocalNodeNumber; // // Address Range Context needed for Broadcast Channels // Register // ADDRESS_RANGE_CONTEXT AddressRangeContext; // // Topology Buffer // PTOPOLOGY_MAP pTopologyMap; // // Event that the Make call will pend on for completion of the BCM // NIC1394_EVENT MakeCallWaitEvent; // // BoadcastChannelVc // PCHANNEL_VCCB pBroadcastChanneVc; // // Locally Allocated Channel Num. Is only valid when the // ULONG LocallyAllocatedChannel; // // The Generation at which the IRM was set. This can then be used to check the // validity of the IRM ULONG IrmGeneration; // // Event To specify that a new node has come in and waiting threads can continue // NIC1394_EVENT BCRWaitForNewRemoteNode; // // Event to synchronize the shutting down of the adapter and freeing the address range // NIC1394_EVENT BCRFreeAddressRange; } BROADCAST_CHANNEL_DATA, *PBROADCAST_CHANNEL_DATA; // // Flags for the PDO Control Block // #define PDO_NotValid 0x00000001 #define PDO_Activated 0x00000002 #define PDO_Removed 0x00000004 #define PDO_BeingRemoved 0x00000008 #define PDO_AllocateAddressRangeFailure 0x00000010 #define PDO_AllocateAddressRangeSucceeded 0x00000020 #define PDO_AddressRangeFreed 0x00000040 #define PDO_AllocateAddressRangeFlags 0x000000F0 #define PDO_ResetRegistered 0x00000100 #define PDO_NotInsertedInTable 0x00000200 // Informational purposes typedef struct _REMOTE_NODE { // The Tag should MTAG_REMOTE_NODE // ULONG ulTag; // // The Vurrent Node Address // NODE_ADDRESS RemoteAddress; // // Ushort Gap // USHORT Gap; // The PDO itself // PDEVICE_OBJECT pPdo; // This is the pointer to the next field in the PDO // LIST_ENTRY linkPdo; // 64 bit Unique Id associated with a 1394 Node // UINT64 UniqueId; // // Enum1394 handle for the node // PVOID Enum1394NodeHandle; // flags can be one of the following. Essentially marks the PDO as // good or bad // ULONG ulFlags; // Back link to the Adapter that PDO hangs off // PADAPTERCB pAdapter; // The refcount associated with the Pdo // REF Ref; // This is the linked list of VCs, that are using the Pdo to preform // LIST_ENTRY VcList; // All the fields that are related to the Recv Fifo are present in this // structure // RECV_FIFO_DATA RecvFIFOData; // // Lock to synchronize all the reassembly operations in the Node // NIC_SPIN_LOCK ReassemblyLock; // // Linked list of Reassembly Structure // LIST_ENTRY ReassemblyList; // This structure maintains cached information about the remote node. // struct { UINT SpeedTo; // From GetMaxSpeedBetweenNodes. UINT MaxRec; // From the node's config ROM. UINT EffectiveMaxBufferSize; // Computed from the SpeedTo, MaxRec, // and local speed. } CachedCaps; // // Ethernet Address - to be used by the bridge to recognize packets // originating from this node. An MD5 Signature of the Euid // ENetAddr ENetAddress; } REMOTE_NODE, *PREMOTE_NODE, **PPREMOTE_NODE; // // These flags are common to the Adapter // // //fADAPTER_IndicatedMediaDisonnect - indicateds that the miniport has already // called NdisMIndicateStatus // #define fADAPTER_Halting 0x00000001 #define fADAPTER_RegisteredWithEnumerator 0x00000002 #define fADAPTER_FailedRegisteration 0x00000004 #define fADAPTER_IndicatedMediaDisonnect 0x00000008 #define fADAPTER_InvalidGenerationCount 0x00000010 //#define fADAPTER_BCMWorkItem 0x00000020 #define fADAPTER_RegisteredAF 0x00000040 #define fADAPTER_Reset10Sec 0x00000080 #define fADAPTER_FailedInit 0x00000100 #define fADAPTER_VDOInactive 0x00000200 #define fADAPTER_FreedRcvTimers 0x00001000 // debugging purposes #define fADAPTER_FreedTimers 0x00002000 // debugging purposes #define fADAPTER_DeletedLookasideLists 0x00004000 // debugging purposes #define fADAPTER_UpdateNodeTable 0x00008000 // set if no remote node for reassembly #define fADAPTER_DoStatusIndications 0x00010000 // if set, call NdisMIndicateStatus #define fADAPTER_DeletedWorkItems 0x00100000 // debugging purposes #define fADAPTER_NoMoreReassembly 0x00200000 #define fADAPTER_RemoteNodeInThisBoot 0x00400000 //was a remote node in this boot #define fADAPTER_BridgeMode 0x00800000 // is the Adapter in bridge mode #define fADAPTER_LowPowerState 0x01000000 // adapter is in low power state // Adapter control block defining the state of a single L2TP mini-port // adapter. An adapter commonly supports multiple VPN devices. Adapter // blocks are allocated in MiniportInitialize and deallocated in MiniportHalt. // typedef struct _ADAPTERCB { // Set to MTAG_ADAPTERCB for easy identification in memory dumps and use // in assertions. // ULONG ulTag; // Next/prev adapter control block. LIST_ENTRY linkAdapter; // ACBF_* bit flags indicating various options. Access restrictions are // indicated for each individual flag. Many of these flags are set // permanently at initialization and so have no access limitation. // // ULONG ulFlags; // // List of PDO control blocks, each representing a remote // device. // LIST_ENTRY PDOList; // // Reference count on this control block. The reference pairs are: // // // Access is via ReferenceAdapter and DereferenceAdapter only. // Serialization is via interlocked operations. // LONG lRef; // // This is the adapter-wide lock, serializing access to everything except // to the contents of VCs, which are serialized by their own lock. // NDIS_SPIN_LOCK lock; // // Generation Count of the physical Bus 1394 // UINT Generation; // // NDIS's handle for this mini-port adapter passed to us in // MiniportInitialize. This is passed back to various NdisXxx calls. // NDIS_HANDLE MiniportAdapterHandle; // // unique ID for the local host controller this adapter is representing // UINT64 UniqueId; // // List of address-family control blocks, each representing // an open address family binding. // LIST_ENTRY AFList; // // List of Recv-FIFO control blocks, each representing one // local receive FIFO. // PRECVFIFO_VCCB pRecvFIFOVc; // // This event is used to wake up the work Item that will complete // the RecvFIFO make call // NDIS_EVENT RecvFIFOEvent; // // The is the LocalHost information that is used in identifying // the local host. This contains the PDO and the Unique ID // for the Host and is a per Adapter quantity // PDEVICE_OBJECT pNextDeviceObject; // Stores information about the Hardware Status of the NIc // NDIS_HARDWARE_STATUS HardwareStatus; // Store the MediaConnectStatus that Ndis requests // NDIS_MEDIA_STATE MediaConnectStatus; // NodeAddress of the physical bus // NODE_ADDRESS NodeAddress; // // enum1394 handle for the adapter // PVOID EnumAdapterHandle; // // BCR Related Information is stored here // BROADCAST_CHANNEL_DATA BCRData; // // Bitmap Channnels allocated by this adapter // ULONGLONG ChannelsAllocatedByLocalHost; // // Speed - of the local network // ULONG SpeedMbps; // // Speed according to the 1394 speed codes // ULONG Speed; // // Gasp header that will bew inserted before every Broadcast write // GASP_HEADER GaspHeader; // // Lookaside List to handle packets of 2k // NIC_NPAGED_LOOKASIDE_LIST SendLookasideList2K; // // Small Lookaside list for packets less than 100 bytes // NIC_NPAGED_LOOKASIDE_LIST SendLookasideList100; // // Datagram Label Number - used in fragmentation // ULONG dgl; USHORT MaxRec; USHORT Gap; // // Node Table - Mapping of Node Address with RemoteNodes // NODE_TABLE NodeTable; // // Number of remote nodes present // ULONG NumRemoteNodes; // // Timer used for reassembly invalidation // NDIS_MINIPORT_TIMER ReassemblyTimer; // // Packet pool for loopback packets. // NIC_PACKET_POOL LoopbackPool; // // Buffer pool for loopback packets. // NDIS_HANDLE LoopbackBufferPool; // // Handle for the config rom that was added to the bus driver // HANDLE hCromData; // // WaitForRemoteNode - threads which need to wait for // the arrival of a remote node use this event // NIC1394_EVENT WaitForRemoteNode; // // Config Rom Mdl that points to the config rom string // PMDL pConfigRomMdl; PREMOTE_NODE pLastRemoteNode; // // Packet Log (used only for tracking packets). // PNIC1394_PKTLOG pPktLog; // // Per adapter stats // ADAPT_STATS AdaptStats; // // Read/WriteCapabilities // GET_LOCAL_HOST_INFO2 ReadWriteCaps; // // SCode - speed of the bus // ULONG SCode; // // Max packet size that this adapter can read // ULONG MaxSendBufferSize; ULONG MaxRecvBufferSize; ULONG CurrentLookahead; // // PacketFilter - Ethernet structs // PETHERNET_VCCB pEthernetVc; ULONG CurPacketFilter ; ULONG ProtocolOptions; MAC_ADDRESS McastAddrs[MCAST_LIST_SIZE]; ULONG McastAddrCount; ULONG CurLookAhead ; MAC_ADDRESS MacAddressEth; // // ReceivePacket Serialization // NIC_SERIALIZATION SerRcv; NIC_SERIALIZATION SerSend; NIC_SERIALIZATION Status; NIC_SERIALIZATION Reassembly; NIC_SERIALIZATION LoadArp; // // Outstanding work Items ULONG OutstandingWorkItems; // // Outstanding Reassemblies // ULONG OutstandingReassemblies; // // Miniport Name // WCHAR AdapterName[ADAPTER_NAME_SIZE]; // // Size of Name in Bytes // ULONG AdapterNameSize; // // Ioctl Sent to the Arp module // ARP1394_IOCTL_COMMAND ArpIoctl; // // Is Arp Started // BOOLEAN fIsArpStarted; // // Power State - informational use // NET_DEVICE_POWER_STATE PowerState; } ADAPTERCB, *PADAPTERCB; // // Address Family Flags // #define ACBF_Allocated 0x00000001 #define ACBF_Initialized 0x00000002 #define ACBF_ClosePending 0x00000100 #define ACBF_CloseComplete 0x00000200 // Address family control block, describing the state of an ndis address family. // Each block may have zero or more VCs associated with it. // typedef struct _AFCB { // Set to MTAG_AFCB for easy identification in memory dumps and use in // assertions. // ULONG ulTag; // ACBF_* bit flags indicating various options. Access restrictions are // indicated for each individual flag. Many of these flags are set // permanently at initialization and so have no access limitation. // // ULONG ulFlags; // Reference count on this control block. The reference pairs are: // // (a) A reference is added when this block is linked to the adapter's // list of af blocks, and removed when it is unlinked. // // (a) A reference is added when a call on a VCCB is created // removed when it is deleted. // // Access is via ReferenceTunnel and DereferenceTunnel only which use // 'ADAPTERCB.lockTunnels' for protection. // LONG lRef; // Links to the prev/next AFCB in the owning adapter's AF list. // Access to the list links is protected by 'ADAPTERCB.lock'. // LIST_ENTRY linkAFCB; // List of all VCs associated with this address family. // Access is protected by the adapter lock. // LIST_ENTRY AFVCList; // Back pointer to owning adapter's control block. // PADAPTERCB pAdapter; // NDIS's handle for our Address Family as passed to our CmOpenAfHandler // or NULL if none. // NDIS_HANDLE NdisAfHandle; } AFCB, *PAFCB; // Call statistics block. // typedef struct _CALLSTATS { // System time call reached established state. When the block is being // used for cumulative statistics of multiple calls, this is the number of // calls instead. // LONGLONG llCallUp; // Duration in seconds of now idle call. // ULONG ulSeconds; // Total data bytes received and sent. // ULONG ulDataBytesRecd; ULONG ulDataBytesSent; // Number of received packets indicated up. // ULONG ulRecdDataPackets; // TODO: add more stats if required. ULONG ulSentPkts; // // NDis Packet failures // ULONG ulSendFailures; // // Bus AsyncWrite or Stream failires // ULONG ulBusSendFailures; ULONG ulBusSendSuccess; } CALLSTATS; typedef NDIS_STATUS (*PFN_INITVCHANDLER) ( VCCB *pVc ); typedef NDIS_STATUS (*PFN_SENDPACKETHANDLER) ( VCCB *pVc, NDIS_PACKET * pPacket ); typedef NDIS_STATUS (*PFN_CLOSECALLHANDLER) ( VCCB *pVc ); typedef VOID (*PFN_RETURNHANDLER) ( VCCB *pVc, PNDIS_PACKET *pPacket ); // Table of vc-type-specific handler functions. // typedef struct _VC_HANDLERS { PFN_INITVCHANDLER MakeCallHandler; PFN_CLOSECALLHANDLER CloseCallHandler; PFN_SENDPACKETHANDLER SendPackets; } VC_HANDLERS; typedef enum _NIC1394_VC_TYPE { NIC1394_Invalid_Type, NIC1394_SendRecvChannel, NIC1394_RecvFIFO, NIC1394_SendFIFO, NIC1394_MultiChannel, NIC1394_Ethernet, NIC1394_SendChannel, NIC1394_RecvChannel, Nic1394_NoMoreVcTypes } NIC1394_VC_TYPE, *PNIC1394_VC_TYPE; // Virtual circuit control block header defining the state of a single VC that // is common to all the different types of VCs. // typedef struct _VCHDR { // Set to MTAG_VCCB_* for easy identification in memory dumps and use in // assertions. // ULONG ulTag; // The Pdo Block that will be used to perform all the operations for this Vc // // PREMOTE_NODE pRemoteNode; // // pLocalHostVdo - local host's VDO that will be used for all channel and // recv fifo allocations // PDEVICE_OBJECT pLocalHostVDO; // Links to the prev/next VCCB in the owning AF's control block. // Access is protected by 'ADAPTERCB.lock'. // LIST_ENTRY linkAFVcs; // The VCType and Destination of the call that has been set up on the VC // The VCType can be either Isoch or Async, Sends or Recieve. Each type // of VC has an address associated with it NIC1394_VC_TYPE VcType; // This stores the generation of the physical adapter. And should match the value // kept in the adapter block PUINT pGeneration; // VCBF_* bit flags indicating various options and states. Access is via // the interlocked ReadFlags/SetFlags/ClearFlags routines. // // VCBF_IndicateReceivedTime: Set if MakeCall caller sets the // MediaParameters.Flags RECEIVE_TIME_INDICATION flag requesting the // TimeReceived field of the NDIS packet be filled with a timestamp. // // VCBF_CallClosableByClient: Set when a call is in a state where // NicCmCloseCall requests to initiate clean-up should be accepted. // This may be set when VCBF_CallClosableByPeer is not, which means we // have indicated an incoming close to client and are waiting for him // to do a client close in response (in that weird CoNDIS way). The // flag is protected by 'lockV'. // // VCBF_VcCreated: Set when the VC has been created successfully. This is // the "creation" that occurs with the client, not the mini-port. // VCBF_VcActivated: Set when the VC has been activated successfully. // VCBM_VcState: Bit mask including each of the above 3 NDIS state flags. // // VCBF_VcDeleted: Set when the DeleteVC handler has been called on this // VC. This guards against NDPROXY double-deleting VCs which it has // been known to do. // // The pending bits below are mutually exclusive (except ClientClose which // may occur after but simultaneous with ClientOpen), and so require lock // protection by 'lockV': // // VCBF_ClientOpenPending: Set when client attempts to establish a call, // and the result is not yet known. // VCBF_ClientClosePending: Set when client attempts to close an // established call and the result is not yet known. Access is // protected by 'lockV'. // VCBM_Pending: Bit mask that includes each of the 4 pending flags. // // VCBF_ClientCloseCompletion: Set when client close completion is in // progress. // // VCBF_WaitCloseCall: Set when the client is expected to call our call // manager's CloseCall handler. This is strictly a debug aid. // // VCBF_FreedResources - VC This is a channel VC and because the last // node in the network was being removed, its resources have been freed ULONG ulFlags; #define VCBF_IndicateTimeReceived 0x00000001 #define VCBF_CallClosableByClient 0x00000002 #define VCBF_VcCreated 0x00000100 #define VCBF_VcActivated 0x00000200 #define VCBF_VcDispatchedCloseCall 0x00000400 #define VCBF_MakeCallPending 0x00002000 #define VCBF_CloseCallPending 0x00008000 #define VCBF_VcDeleted 0x00010000 #define VCBF_MakeCallFailed 0x00020000 #define VCBF_CloseCallCompleted 0x00040000 #define VCBF_WaitCloseCall 0x00200000 #define VCBF_NewPdoIsActivatingFifo 0x01000000 #define VCBF_PdoIsBeingRemoved 0x02000000 #define VCBF_NeedsToAllocateChannel 0x04000000 #define VCBF_GenerationWorkItem 0x10000000 #define VCBF_AllocatedChannel 0x20000000 #define VCBF_BroadcastVc 0x40000000 #define VCBF_FreedResources 0x80000000 #define VCBM_VcState 0x00000700 #define VCBM_Pending 0x0000F000 #define VCBM_NoActiveCall 0x000F0000 #define VCBM_PdoFlags 0x0F000000 // Back pointer to owning address family control block. // AFCB* pAF; // Reference count on the active call. // References may only be added // when the VCCB_VcActivated flag is set, and this is enforced by // ReferenceCall. The reference pairs are: // // (a) A reference is added when a VC is activated and removed when it is // de-activated. // // (b) A reference is added when the send handler accepts a packet. // // The field is accessed only by the ReferenceCall and DereferenceCall // routines, which protect the field with 'lock'. // REF CallRef; // Reference count on this VC control block. The reference pairs are: // // (a) NicCoCreateVc adds a reference that is removed by NicCoDeleteVc. // This covers all clients that learn of the VCCB via NDIS. // // The field is accessed only by the ReferenceVc and DereferenceVc // routines, which protect with Interlocked routines. // LONG lRef; // // This is a copy the parameters that are passed to the VC in // a Make Call. Each VC needs to keep a copy. This is stored here // NIC1394_MEDIA_PARAMETERS Nic1394MediaParams; // NDIS BOOKKEEPING ------------------------------------------------------ // NDIS's handle for this VC passed to us in MiniportCoCreateVcHandler. // This is passed back to NDIS in various NdisXxx calls. // NDIS_HANDLE NdisVcHandle; // This linked list is used to designate all the VCs that are using a single PdoCb // The head of this list resides in a REMOTE_NODE. So that when a Pdo goes away, we can go and // close all the Vcs that are dependent on it. No RecvFIFO included LIST_ENTRY SinglePdoVcLink; // CALL SETUP ------------------------------------------------------------ // Address of the call parameters passed down in CmMakeCall. This field // will only be valid until the NdisMCmMakeCallComplete notification for // the associated call is made, at which time it is reset to NULL. Access // is via Interlocked routines. // PCO_CALL_PARAMETERS pCallParameters; UINT MTU; // This is the initialize handler used to initialize the Vc // Each Vc has its own specific initialize handler so that all the // data structures that specific to it, can be filled // VC_HANDLERS VcHandlers; // STATISTICS ------------------------------------------------------------ // Statistics for the current call. Access is protected by 'lock'. // CALLSTATS stats; // This is a pointer to the lock in the adapater // structure. PNDIS_SPIN_LOCK plock; // // MaxPayload that this VC will send in a single IRP // To be used in Lookaside lists // ULONG MaxPayload; } VCHDR; // // Virtual circuit control block defining the state of a single SendFIFO VC. // typedef struct _SENDFIFO_VCCB { // Common header for all types of VCs // VCHDR Hdr; // Prev/next in the list of SendFIFO VCs for a particular destination // PDO // LIST_ENTRY SendFIFOLink; // SendFIFO-specific VC Info // NIC1394_FIFO_ADDRESS FifoAddress; // Shortcuts to the Values we were passed in the Make call // that activated the VC // // UINT MaxSendBlockSize; UINT MaxSendSpeed; } SENDFIFO_VCCB, *PSENDFIFO_VCCB; // Virtual circuit control block defining the state of a single RecvFIFO VC. // typedef struct _RECVFIFO_VCCB { // Common header for all types of VCs // VCHDR Hdr; // Prev/next in the list of RecvFIFO VCs for a particular Recv FIFO // address. // LIST_ENTRY RecvFIFOLink; // Packet Pool Handle // NIC_PACKET_POOL PacketPool; //NDIS_HANDLE PacketPoolHandle; // Slist Header. All buffers are posted here, using Interlocked routines // SLIST_HEADER FifoSListHead; // Slist Spin lock that protects the Slist // KSPIN_LOCK FifoSListSpinLock; // // Num Fifo Elements allocated // ULONG NumAllocatedFifos; // Num of Fifo that have been indicated to the miniport // Count of Fifo that the Nic has not returned to the bus driver // ULONG NumIndicatedFifos; // This is the address range that is returned in the allocate // address irb. Will be changed to a pointer or an array // ADDRESS_RANGE VcAddressRange; // This is the number of address ranges that the bus driver // returned. For now, it is expected to be one. // UINT AddressesReturned; // // Handle to the address range // HANDLE hAddressRange; // // Buffer pool // NIC_BUFFER_POOL BufferPool; //NIC_WORK_ITEM FifoWorkItem; BOOLEAN FifoWorkItemInProgress ; UINT NumOfFifosInSlistInCloseCall; } RECVFIFO_VCCB, *PRECVFIFO_VCCB; // Virtual circuit control block defining the state of a single CHANNEL VC. // typedef struct _CHANNEL_VCCB { // Common header for all types of VCs // VCHDR Hdr; // Prev/next in the list of channel VCs for a particular destination // channel // LIST_ENTRY ChannelLink; // Channel-specific VC Info // UINT Channel; // The speed at which this Channel will stream data // UINT Speed; // Indicates the Sy field in packets that will indicated up // ULONG ulSynch; // the Tag used in submitting asyncstream irps // ULONG ulTag; // MaxBytesPerFrameRequested and available // ULONG MaxBytesPerFrameRequested; ULONG BytesPerFrameAvailable; // Handle to the Resources allocated // HANDLE hResource; // Speeds Requested and speed returned // ULONG SpeedRequested; ULONG SpeedSelected; // Maximum Buffer Size // ULONG MaxBufferSize; // Num of descriptors that were attached to the resources // ULONG NumDescriptors; // Pointer to an array of isochDescriptors used in AttachBuffers // PISOCH_DESCRIPTOR pIsochDescriptor; // PacketPool Handle // NIC_PACKET_POOL PacketPool; //NDIS_HANDLE hPacketPoolHandle; // // Temporary // UINT PacketLength; // // Number of Isoch Descriptors that the Bus driver has indicated to the miniport // ULONG NumIndicatedIsochDesc; // // Event to signal that the last of the Isoch descriptors have // been returned to the bus driver. Only set when Vc is closing (after IsochStop) // NDIS_EVENT LastDescReturned; // // Channel Map used in Multichannel Vcs // ULARGE_INTEGER uliChannelMap; } CHANNEL_VCCB, *PCHANNEL_VCCB; typedef struct _ETHERNET_VCCB { // Common header for all types of VCs // VCHDR Hdr; NIC_PACKET_POOL PacketPool; } ETHERNET_VCCB, *PETHERNET_VCCB; // The following union has enough space to hold any of the type-specific // VC control blocks. // typedef union _VCCB { VCHDR Hdr; CHANNEL_VCCB ChannelVc; SENDFIFO_VCCB SendFIFOVc; RECVFIFO_VCCB RecvFIFOVc; ETHERNET_VCCB EthernetVc; } VCCB, *PVCCB; // The next structure is used when sending a packet, to store context // information in an NdisPacket. These are pointers to the Vc and the Irb // and are stored in the MiniportWrapperReserved field of the NdisPacket // and has a limit of 2 PVOIDs // typedef union _PKT_CONTEXT { struct { PVCCB pVc; PVOID pLookasideListBuffer; } AsyncWrite; struct { PVCCB pVc; PVOID pLookasideListBuffer; } AsyncStream; // // For receives make sure the first element is the Vc or we will break; // struct { PRECVFIFO_VCCB pRecvFIFOVc; PADDRESS_FIFO pIndicatedFifo; } AllocateAddressRange; struct { PCHANNEL_VCCB pChannelVc; PISOCH_DESCRIPTOR pIsochDescriptor; } IsochListen; struct { // // First DWORD is the Vc // PVCCB pVc; // // Second is the isoch descriptor or Fifo // union { PISOCH_DESCRIPTOR pIsochDescriptor; // channels use isoch desc PADDRESS_FIFO pIndicatedFifo; // fifo use AddressFifo PVOID pCommon; // to be used in the common code path } IndicatedStruct; } Receive; struct { PNDIS_PACKET pOrigPacket; } EthernetSend; } PKT_CONTEXT,*PPKT_CONTEXT,**PPPKT_CONTEXT; typedef struct _NDIS1394_FRAGMENT_HEADER { union { struct { ULONG FH_fragment_offset:12; ULONG FH_rsv_0:4; ULONG FH_buffersize:12; ULONG FH_rsv_1:2; ULONG FH_lf:2; } FirstQuadlet; struct { ULONG FH_EtherType:16; ULONG FH_buffersize:12; ULONG FH_rsv_1:2; ULONG FH_lf:2; } FirstQuadlet_FirstFragment; ULONG FH_High; } u; union { struct { ULONG FH_rsv:16; ULONG FH_dgl:16; } SecondQuadlet; ULONG FH_Low; } u1; } NDIS1394_FRAGMENT_HEADER, *PNDIS1394_FRAGMENT_HEADER; #define LOOKASIDE_HEADER_No_More_Framgents 1 #define LOOKASIDE_HEADER_SendPacketFrees 2 #define LOOKASIDE_HEADER_SendCompleteFrees 4 // // This structure is used with the above flags to maintain state within the lookaside buffer // typedef union _LOOKASIDE_BUFFER_STATE { struct { USHORT Refcount; USHORT Flags; } u; LONG FlagRefcount; } LOOKASIDE_BUFFER_STATE, *PLOOKASIDE_BUFFER_STATE; typedef enum _BUS_OPERATION { InvalidOperation, AsyncWrite, AsyncStream, AddressRange, IsochReceive } BUS_OPERATION, *PBUS_OPERATION; // // This will be used as a local variable // during a send operation and will // keep all the state information // regarding fragmentation // typedef struct _FRAGMENTATION_STRUCTURE { // // Start of the buffer that will be used in the send. // Usually from a lookaside list // PVOID pLookasideListBuffer; // // Fragment Length // ULONG FragmentLength ; // // Start of the this fragment to be used // PVOID pStartFragment; // // Specified if an async write or an asyncstream operation is occurring // BUS_OPERATION AsyncOp; // // LookasideBuffer associated with the fragmentation // PVOID pLookasideBuffer; // // Start of the next fragment // // PVOID pStartNextFragment; // // Length of each fragment // ULONG MaxFragmentLength; // // NumFragments that will be generated // ULONG NumFragmentsNeeded ; // // Current NdisBuffer which is being fragmented // PNDIS_BUFFER pCurrNdisBuffer; // // Length that needs to be copied in CurrNdisBuffer // ULONG NdisBufferLengthRemaining; // // Point to which copying has occurred in the pCurrNdisBuffer // PVOID pSourceAddressInNdisBuffer; // // UnFragment Header from this NdisPacket // NDIS1394_UNFRAGMENTED_HEADER UnfragmentedHeader; // // Fragmented Header to be used by all the fragments // generated by this NdisPackets // NDIS1394_FRAGMENT_HEADER FragmentationHeader; // // Status of the lf field in the fragment header. Also serves as an // implicit flag about the state of the fragmentation // NDIS1394_FRAGMENT_LF lf; // // Length of the Ip Datagram, to be used as the buffersize in fragment header // USHORT IPDatagramLength; // // An AsyncStream will have a gasp header as well . So the starting // offset can either be either 8 or 16. Only applicable for fragmentation code path // ULONG TxHeaderSize; // // Pointer to the lookaside list that this buffer was allocated from // PNIC_NPAGED_LOOKASIDE_LIST pLookasideList; // // Adapter - local host // PADAPTERCB pAdapter; // // Pointer to the IRB to be used in the current fragment // PIRB pCurrentIrb; // // Current Fragment Number // ULONG CurrFragmentNum; PVOID pStartOfFirstFragment; }FRAGMENTATION_STRUCTURE, *PFRAGMENTATION_STRUCTURE; typedef struct _LOOKASIDE_BUFFER_HEADER { // // Refcount // ULONG OutstandingFragments; // // NumOfFragments generated by the NdisPacket So Far // ULONG FragmentsGenerated; // // Will this Buffer contain fragments // BOOLEAN IsFragmented; // // Pointer to the NdisPacket whose data is being transmitted // by the lookaside buffer // PNDIS_PACKET pNdisPacket; // // pVc Pointer to the Vc on which the packet was indicated // Used to complete the packet // PVCCB pVc; // // Pointer to the lookaside list that this buffer was allocated from // PNIC_NPAGED_LOOKASIDE_LIST pLookasideList; // // Bus Op AsyncStream or AsyncWrite. // AsyncWrite reference the RemoteNode. AsuncWrite does not // BUS_OPERATION AsyncOp; // // Start of Data // PVOID pStartOfData; } LOOKASIDE_BUFFER_HEADER, *PLOOKASIDE_BUFFER_HEADER; typedef enum _ENUM_LOOKASIDE_LIST { NoLookasideList, SendLookasideList100, SendLookasideList2K, } ENUM_LOOKASIDE_LIST, *PENUM_LOOKASIDE_LIST; // // Unfragmented Buffer // typedef struct _UNFRAGMENTED_BUFFER { LOOKASIDE_BUFFER_HEADER Header; IRB Irb; UCHAR Data [1]; } UNFRAGMENTED_BUFFER, *PUNFRAGMENTED_BUFFER; #define PAYLOAD_100 100 // // A simple packet with no fragmentation . This will primarily be used for the IP Acks and ARP req // typedef struct _PAYLOAD_100_LOOKASIDE_BUFFER { LOOKASIDE_BUFFER_HEADER Header; IRB Irb; UCHAR Data [PAYLOAD_100 + sizeof (GASP_HEADER)]; } PAYLOAD_100_LOOKASIDE_BUFFER; // // This lookaside will handle packets upto 2K. // // Calculate the theoretical maximum number of fragments that can occur for a // a 2K Packet // #define PAYLOAD_2K ASYNC_PAYLOAD_400_RATE #define NUM_FRAGMENT_2K ((PAYLOAD_2K/ASYNC_PAYLOAD_100_RATE) +1) typedef struct _PAYLOAD_2K_LOOKASIDE_BUFFER { LOOKASIDE_BUFFER_HEADER Header; // // There can be a maximum of 2048 bytes in 1 Async Packet fragment // on ASYNC_PAYLOAD_400 so this will cater to // that, but it will be prepared for the worst // // IRB Irb[NUM_FRAGMENT_2K]; // // We get a data size large enough to handle 2048 bytes of data chopped up // into the max num of fragments and leave room for header (fragmentation and Gasp) // To access we'll just use simple pointer arithmetic // UCHAR Data[PAYLOAD_2K+ (NUM_FRAGMENT_2K *(sizeof (GASP_HEADER)+sizeof (NDIS1394_FRAGMENT_HEADER)))]; } PAYLOAD_2K_LOOKASIDE_BUFFER, *PPAYLOAD_2K_LOOKASIDE_BUFFER; // // The 1394 fragment that is passed down can have a gasp header, fragmentation header, // unfragmented header. Define Types to format these headers so that we can make // compiler do the pointer arithmetic for us. // typedef union _PACKET_FORMAT { struct { GASP_HEADER GaspHeader; NDIS1394_FRAGMENT_HEADER FragmentHeader; UCHAR Data[1]; } AsyncStreamFragmented; struct { GASP_HEADER GaspHeader; NDIS1394_UNFRAGMENTED_HEADER NonFragmentedHeader; UCHAR Data[1]; } AsyncStreamNonFragmented; struct { NDIS1394_FRAGMENT_HEADER FragmentHeader; UCHAR Data[1]; } AsyncWriteFragmented; struct { NDIS1394_UNFRAGMENTED_HEADER NonFragmentedHeader; UCHAR Data[1]; }AsyncWriteNonFragmented; struct { // // Isoch receive header has a prefix, isoch header, gasp header // ULONG Prefix; ISOCH_HEADER IsochHeader; GASP_HEADER GaspHeader; NDIS1394_UNFRAGMENTED_HEADER NonFragmentedHeader; UCHAR Data[1]; } IsochReceiveNonFragmented; struct { // // Isoch receive header has a prefix, isoch header, gasp header // ULONG Prefix; ISOCH_HEADER IsochHeader; GASP_HEADER GaspHeader; NDIS1394_FRAGMENT_HEADER FragmentHeader; UCHAR Data[1]; }IsochReceiveFragmented; }PACKET_FORMAT, DATA_FORMAT, *PPACKET_FORMAT, *PDATA_FORMAT; // // Used as an Info Struct for Out of Order Reassembly // typedef struct _REASSEMBLY_CURRENT_INFO { PMDL pCurrMdl; PNDIS_BUFFER pCurrNdisBuffer; PADDRESS_FIFO pCurrFifo; PISOCH_DESCRIPTOR pCurrIsoch; } REASSEMBLY_CURRENT_INFO, *PREASSEMBLY_CURRENT_INFO ; typedef enum _REASSEMBLY_INSERT_TYPE { Unacceptable, InsertAsFirst, InsertInMiddle, InsertAtEnd }REASSEMBLY_INSERT_TYPE, *PREASSEMBLY_INSERT_TYPE; // // This is used as a descriptor for indicated fragments that are waiting for reassembly // typedef struct _FRAGMENT_DESCRIPTOR { ULONG Offset; // Offset of the incoming fragment ULONG IPLength; // Length of the fragment PNDIS_BUFFER pNdisBuffer; // NdisBufferpointing to actual data PMDL pMdl; // Mdl that belongs to the bus NDIS1394_FRAGMENT_HEADER FragHeader; // Fragment header of the Descriptor union { PADDRESS_FIFO pFifo; PISOCH_DESCRIPTOR pIsoch; PVOID pCommon; PSINGLE_LIST_ENTRY pListEntry; }IndicatedStructure; } FRAGMENT_DESCRIPTOR, *PFRAGMENT_DESCRIPTOR; // // Reassembly structure : An instance of the reassembly is created for // every packet that is being reassembled. It contains all the relevant // bookkeeping information // // This needs to be allocated from a lookaside list // Each PDO will contain a list of all outstanding packets that are being reassembled/ // // // REASSEMBLY_NOT_TOUCHED - Each reassembly structure will be marked as Not touched // in the timer routine. If the flag is not cleared by the next // invocation of the timer, this structure will be freed // REASSMEBLY_FREED - The structure is about to be thrown away. #define REASSEMBLY_NOT_TOUCHED 1 #define REASSEMBLY_FREED 2 #define REASSEMBLY_ABORTED 4 typedef struct _NDIS1394_REASSEMBLY_STRUCTURE { // // Reference Count - Interlocked access only // ULONG Ref; // // Next Reassembly Structure // LIST_ENTRY ReassemblyListEntry; // // Tag - used for memory validatation // ULONG Tag; // // Receive Operation // BUS_OPERATION ReceiveOp; // // Dgl - Datagram label. Unique for every reassembly structure gernerated by this local host // USHORT Dgl; // // Ether type of the reassembled packet . Populated in the first fragment // USHORT EtherType; // // pRemoteNode -> RemoteNode + Dgl are unique for each reassembly structure // PREMOTE_NODE pRemoteNode; // // Flags pertaining to the reassembly // ULONG Flags; // // ExpectedFragmentOffset is computed by the LAST Fragment's Offset + // length of fragment. Does not account for gaps in the reassembled packet. // ULONG ExpectedFragmentOffset; // Last is based on offset, not time of indication // // Buffer Size - total length of the datagram being reassembled // ULONG BufferSize; // // Bytes Received So far // ULONG BytesRecvSoFar; // // Head NdisBuffer // PNDIS_BUFFER pHeadNdisBuffer; // // LastNdisBuffer that was appended to the packet // PNDIS_BUFFER pTailNdisBuffer; // // Mdl chain Head - pointing to the actual indicated fragment // PMDL pHeadMdl; // //Mdl Chain Tail - pointing to the last Mdl in the list // PMDL pTailMdl ; // // Packet that is being reassembled // PNDIS_PACKET pNdisPacket; // // NumOfFragmentsSoFar; // ULONG NumOfFragmentsSoFar; // // Pointer to the head of the MDL chain that the 1394 bus // driver is indicating up. Will be used to return the buffers to // the BusDriver // union { PADDRESS_FIFO pAddressFifo; PISOCH_DESCRIPTOR pIsochDescriptor; PVOID pCommon; } Head; // // Last - Last Mdl that was appended to this packet in the reassembly structure // union { PADDRESS_FIFO pAddressFifo; PISOCH_DESCRIPTOR pIsochDescriptor; PVOID pCommon; } Tail; // // Flag to signal if any out of order fragments were received. Default FALSE // BOOLEAN OutOfOrder; // // Flag to indicate if all fragments are completed . Default False // BOOLEAN fReassemblyComplete; // // Vc that this packet is being assembled for // PVCCB pVc; // // MaxIndex in the Fragment Table. // At all times, MaxOffset points to an first empty element in the array // ULONG MaxOffsetTableIndex; // // FragmentOffset Table // FRAGMENT_DESCRIPTOR FragTable[MAX_ALLOWED_FRAGMENTS]; } NDIS1394_REASSEMBLY_STRUCTURE, *PDIS1394_REASSEMBLY_STRUCTURE, *PPDIS1394_REASSEMBLY_STRUCTURE; // // This structure is local to each Isoch descriptor or fifo that is indicated up // to the nic1394 miniport. It stores all the local information extracted // from the GASP header and Isoch Header // typedef struct { BUS_OPERATION RecvOp; // Fifo or Isoch Receive PDATA_FORMAT p1394Data; // Start of 1394 pkt ULONG Length1394; // Length of the 1394 data PVOID pEncapHeader; // Points to start of frag/defrag encap header ULONG DataLength; // length of the packet, from the EncapHeader BOOLEAN fGasp; // Has GASP header NDIS1394_UNFRAGMENTED_HEADER UnfragHeader; // Unfragmented header NDIS1394_FRAGMENT_HEADER FragmentHeader; // Fragment Header PGASP_HEADER pGaspHeader; // Gasp Header PVOID pIndicatedData; // Data indicated up, includes the isoch header, unfrag headers PMDL pMdl; // // Following information from the fragmented/unfragmented header... // BOOLEAN fFragmented; // Is fragmented BOOLEAN fFirstFragment; // Is the First fragment ULONG BufferSize; ULONG FragmentOffset; USHORT Dgl; // Dgl ULONG lf; // Lf - Fragmented or not ULONG EtherType; // Ethertype PNDIS_BUFFER pNdisBuffer; // Ndis buffer - used to indicate data up. PVOID pNdisBufferData; // Points to the start of the data that the Ndis Buffer points to // // Sender specific information here // USHORT SourceID; PREMOTE_NODE pRemoteNode; // // Vc Specific Information here // PVCCB pVc; PNIC_PACKET_POOL pPacketPool; // // Indication data // union { PADDRESS_FIFO pFifoContext; PISOCH_DESCRIPTOR pIsochContext; PVOID pCommon; // to be used in the common code path }NdisPktContext; } NIC_RECV_DATA_INFO, *PNIC_RECV_DATA_INFO; // // Fragment Header as defined in the IP/1394 spec. Each packet greater than the MaxPayload // will be split up into fragments and this header will be attached. // #define FRAGMENT_HEADER_LF_UNFRAGMENTED 0 #define FRAGMENT_HEADER_LF_FIRST_FRAGMENT 1 #define FRAGMENT_HEADER_LF_LAST_FRAGMENT 2 #define FRAGMENT_HEADER_LF_INTERIOR_FRAGMENT 3 typedef struct _INDICATE_RSVD { PNDIS_PACKET pPacket; PVCCB pVc; PADAPTERCB pAdapter; LIST_ENTRY Link; ULONG Tag; } INDICATE_RSVD, *PINDICATE_RSVD; typedef struct _RSVD { UCHAR Mandatory[PROTOCOL_RESERVED_SIZE_IN_PACKET]; // mandatory ndis requirement INDICATE_RSVD IndicateRsvd; // to be used as extra context } RSVD, *PRSVD; // // Used only in Win9x as a context for the send timer routine // typedef struct _NDIS_SEND_CONTEXT { LIST_ENTRY Link; PVCCB pVc; }NDIS_SEND_CONTEXT, *PNDIS_SEND_CONTEXT; typedef struct _NDIS_STATUS_CONTEXT { LIST_ENTRY Link; IN NDIS_STATUS GeneralStatus; IN PVOID StatusBuffer; IN UINT StatusBufferSize; }NDIS_STATUS_CONTEXT, *PNDIS_STATUS_CONTEXT; // // This is the Irb structure used by the Bus Driver. // There is extra room allocated at the end for the miniport's Context // typedef struct _NDIS1394_IRB { // // Original Irb used by the bus driver // IRB Irb; // // Adapter - local host -optional // PADAPTERCB pAdapter; // // remote node to which the Irp was sent - optional // PREMOTE_NODE pRemoteNode; // // VC for which the Irp was sent. - optional // PVCCB pVc; // // Context if any - optinal // PVOID Context; }NDIS1394_IRB, *PNDIS1394_IRB; // // The following structure is used to log the cause of a Reference or Dereference. // It is ignored unless LOG_REMOTE_NODE_REF is not zero // typedef enum _REMOTE_NODE_REF_CAUSE { FindIrmAmongRemoteNodes, InformAllRemoteNodesOfBCM, UpdateNodeTable, FindRemoteNodeFromAdapter, SubmitIrp_Synch, AddRemoteNode, ReassemblyTimer, GetRemoteNodeFromTable, UpdateRemoteNodeCaps, UpdateRemoteNodeTable, UpdateLocalHostSpeed, InitializeReassemblyStructure, FreeAllPendingReassemblyStructures, AsyncWriteSendPackets, FindRemoteNodeFromAdapterFail, RemoveRemoteNode, ReassemblyTimer_Removing, FreeReassembliesOnRemoteNode, FillRemoteNodeInfo, InsertFragmentInReassembly, AsyncSendComplete, } REMOTE_NODE_REF_CAUSE; #pragma pack (push, 1) typedef ULONG IP_ADDRESS; //* Structure of an Ethernet header (taken from ip\arpdef.h). typedef struct ENetHeader { ENetAddr eh_daddr; ENetAddr eh_saddr; USHORT eh_type; } ENetHeader; // Structure of an Ethernet ARP packet. // typedef struct { ENetHeader header; USHORT hardware_type; USHORT protocol_type; UCHAR hw_addr_len; UCHAR IP_addr_len; USHORT opcode; // Opcode. ENetAddr sender_hw_address; IP_ADDRESS sender_IP_address; ENetAddr target_hw_address; IP_ADDRESS target_IP_address; } ETH_ARP_PKT, *PETH_ARP_PKT; #pragma pack (pop) // These are ethernet arp specific constants // #define ARP_ETH_ETYPE_IP 0x800 #define ARP_ETH_ETYPE_ARP 0x806 #define ARP_ETH_REQUEST 1 #define ARP_ETH_RESPONSE 2 #define ARP_ETH_HW_ENET 1 #define ARP_ETH_HW_802 6 typedef enum _ARP_ACTION { LoadArp = 1, UnloadArp , UnloadArpNoRequest, BindArp }ARP_ACTION , *PARP_ACTION; typedef struct _ARP_INFO{ // // List entry to handle serialization of requests to ARP // LIST_ENTRY Link; // // Action to be done by the Arp module // ARP_ACTION Action; // // Request to be compeleted - optional // PNDIS_REQUEST pRequest; } ARP_INFO, *PARP_INFO; //----------------------------------------------------------------------------- // Macros/inlines //----------------------------------------------------------------------------- // These basics are not in the DDK headers for some reason. // #define min( a, b ) (((a) < (b)) ? (a) : (b)) #define max( a, b ) (((a) > (b)) ? (a) : (b)) #define InsertBefore( pNewL, pL ) \ { \ (pNewL)->Flink = (pL); \ (pNewL)->Blink = (pL)->Blink; \ (pNewL)->Flink->Blink = (pNewL); \ (pNewL)->Blink->Flink = (pNewL); \ } #define InsertAfter( pNewL, pL ) \ { \ (pNewL)->Flink = (pL)->Flink; \ (pNewL)->Blink = (pL); \ (pNewL)->Flink->Blink = (pNewL); \ (pNewL)->Blink->Flink = (pNewL); \ } // Winsock-ish host/network byte order converters for short and long integers. // #if (defined(_M_IX86) && (_MSC_FULL_VER > 13009037)) || ((defined(_M_AMD64) || defined(_M_IA64)) && (_MSC_FULL_VER > 13009175)) #define htons(x) _byteswap_ushort((USHORT)(x)) #define htonl(x) _byteswap_ulong((ULONG)(x)) #else #define htons( a ) ((((a) & 0xFF00) >> 8) |\ (((a) & 0x00FF) << 8)) #define htonl( a ) ((((a) & 0xFF000000) >> 24) | \ (((a) & 0x00FF0000) >> 8) | \ (((a) & 0x0000FF00) << 8) | \ (((a) & 0x000000FF) << 24)) #endif #define ntohs( a ) htons(a) #define ntohl( a ) htonl(a) // Place in a TRACE argument list to correspond with a format of "%d.%d.%d.%d" // to print network byte-ordered IP address 'x' in human readable form. // #define IPADDRTRACE( x ) ((x) & 0x000000FF), \ (((x) >> 8) & 0x000000FF), \ (((x) >> 16) & 0x000000FF), \ (((x) >> 24) & 0x000000FF) // Place in a TRACE argument list to correspond with a format of "%d" to print // a percentage of two integers, or an average of two integers, or those // values rounded. // #define PCTTRACE( n, d ) ((d) ? (((n) * 100) / (d)) : 0) #define AVGTRACE( t, c ) ((c) ? ((t) / (c)) : 0) #define PCTRNDTRACE( n, d ) ((d) ? (((((n) * 1000) / (d)) + 5) / 10) : 0) #define AVGRNDTRACE( t, c ) ((c) ? (((((t) * 10) / (c)) + 5) / 10) : 0) // All memory allocations and frees are done with these ALLOC_*/FREE_* // macros/inlines to allow memory management scheme changes without global // editing. For example, might choose to lump several lookaside lists of // nearly equal sized items into a single list for efficiency. // // NdisFreeMemory requires the length of the allocation as an argument. NT // currently doesn't use this for non-paged memory, but according to JameelH, // Windows95 does. These inlines stash the length at the beginning of the // allocation, providing the traditional malloc/free interface. The // stash-area is a ULONGLONG so that all allocated blocks remain ULONGLONG // aligned as they would be otherwise, preventing problems on Alphas. // __inline VOID* ALLOC_NONPAGED( IN ULONG ulBufLength, IN ULONG ulTag ) { CHAR* pBuf; NdisAllocateMemoryWithTag( &pBuf, (UINT )(ulBufLength + MEMORY_ALLOCATION_ALIGNMENT), ulTag ); if (!pBuf) { return NULL; } ((ULONG* )pBuf)[ 0 ] = ulBufLength; ((ULONG* )pBuf)[ 1 ] = ulTag; return (pBuf + MEMORY_ALLOCATION_ALIGNMENT); } __inline VOID FREE_NONPAGED( IN VOID* pBuf ) { ULONG ulBufLen; ulBufLen = *((ULONG* )(((CHAR* )pBuf) - MEMORY_ALLOCATION_ALIGNMENT)); NdisFreeMemory( ((CHAR* )pBuf) - MEMORY_ALLOCATION_ALIGNMENT, (UINT )(ulBufLen + MEMORY_ALLOCATION_ALIGNMENT), 0 ); } #define ALLOC_NDIS_WORK_ITEM( pA ) \ NdisAllocateFromNPagedLookasideList( &(pA)->llistWorkItems ) #define FREE_NDIS_WORK_ITEM( pA, pNwi ) \ NdisFreeToNPagedLookasideList( &(pA)->llistWorkItems, (pNwi) ) #define ALLOC_TIMERQITEM( pA ) \ NdisAllocateFromNPagedLookasideList( &(pA)->llistTimerQItems ) #define FREE_TIMERQITEM( pA, pTqi ) \ NdisFreeToNPagedLookasideList( &(pA)->llistTimerQItems, (pTqi) ) #define ALLOC_TUNNELCB( pA ) \ ALLOC_NONPAGED( sizeof(TUNNELCB), MTAG_TUNNELCB ) #define FREE_TUNNELCB( pA, pT ) \ FREE_NONPAGED( pT ) #define ALLOC_VCCB( pA ) \ ALLOC_NONPAGED( sizeof(VCCB), MTAG_VCCB ) #define FREE_VCCB( pA, pV ) \ FREE_NONPAGED( pV ) #define ALLOC_TIMERQ( pA ) \ ALLOC_NONPAGED( sizeof(TIMERQ), MTAG_TIMERQ ) #define FREE_TIMERQ( pA, pTq ) \ FREE_NONPAGED( pTq ) // // Log packet macro // #ifdef PKT_LOG #define NIC1394_ALLOC_PKTLOG(_pAdapter) \ nic1394AllocPktLog(_pAdapter) #define NIC1394_DEALLOC_PKTLOG(_pAdapter) \ Nic1394DeallocPktLog(_pAdapter) #define NIC1394_LOG_PKT(_pAdapter, _Flags, _SourceID, _DestID, _pvData, _cbData)\ (((_pAdapter)->pPktLog) ? \ Nic1394LogPkt( \ (_pAdapter)->pPktLog, \ (_Flags), \ (_SourceID), \ (_DestID), \ (_pvData), \ (_cbData) \ ) \ : 0) #else #define NIC1394_ALLOC_PKTLOG(_pAdapter) #define NIC1394_DEALLOC_PKTLOG(_pAdapter) #define NIC1394_LOG_PKT(_pAdapter, _Flags, _SourceID, _DestID, _pvData, _cbData) #endif #define NIC1394_LOGFLAGS_RECV_CHANNEL 0x00000001 #define NIC1394_LOGFLAGS_SEND_FIFO 0x00000010 #define NIC1394_LOGFLAGS_SEND_CHANNEL 0x00000011 #define NIC1394_LOGFLAGS_RECV_FIFO 0x00000100 #define NIC1394_LOGFLAGS_BCM_FAILED 0x00001000 #define NIC1394_LOGFLAGS_BCM_IS_IRM_TIMEOUT 0x00002000 #define NIC1394_LOGFLAGS_BCM_NOT_IRM_TIMEOUT 0x00004000 #define NIC1394_LOGFLAGS_BCM_IRM_NOT_FOUND 0x00008000 #if 0 // // To get the MaxRec we extract the 0xf000 nibble // #define GET_MAXREC_FROM_BUSCAPS(_pBus, _pMaxRec) \ { \ ULONG _LitEnd = SWAPBYTES_ULONG(_pBus); \ _LitEnd = _LitEnd & 0xf000; \ _LitEnd = _LitEnd >> 12; \ *(_pBusRec) = _LitEnd; \ } #endif // // To get the MaxRec we extract the 0xf000 nibble // #define GET_MAXREC_FROM_BUSCAPS(_Bus) (((_Bus) & 0xf00000) >> 20); //----------------------------------------------------------------------------- // F L A G S & L O C K S //----------------------------------------------------------------------------- // // These macros are just present to make accessing the VC's flags easier // and concentrate the implementations at one place // #define VC_TEST_FLAG(_V, _F) ((nicReadFlags(&(_V)->Hdr.ulFlags) & (_F))!= 0) #define VC_SET_FLAG(_V, _F) (nicSetFlags(&(_V)->Hdr.ulFlags, (_F))) #define VC_CLEAR_FLAGS(_V, _F) (nicClearFlags(&(_V)->Hdr.ulFlags , (_F))) #define VC_TEST_FLAGS(_V, _F) ((nicReadFlags(&(_V)->Hdr.ulFlags) & (_F)) == (_F)) #define VC_READ_FLAGS(_V) ((nicReadFlags(&(_V)->Hdr.ulFlags) #define VC_ACTIVE(_V) (((_V)->Hdr.ulFlags & (VCBF_CloseCallPending | VCBF_VcDeleted | VCBF_VcActivated |VCBF_MakeCallPending )) == VCBF_VcActivated) #define REMOTE_NODE_TEST_FLAG(_P, _F ) ((nicReadFlags(&(_P)->ulFlags) & (_F))!= 0) #define REMOTE_NODE_SET_FLAG(_P, _F) (nicSetFlags(&(_P)->ulFlags, (_F))) #define REMOTE_NODE_CLEAR_FLAGS(_P, _F) (nicClearFlags(&(_P)->ulFlags , (_F))) #define REMOTE_NODE_TEST_FLAGS(_P, _F) ((nicReadFlags(&(_P)->ulFlags) & (_F)) == (_F)) #define REMOTE_NODE_READ_FLAGS(_P) ((nicReadFlags(&(_P)->ulFlags) #define REMOTE_NODE_ACTIVE(_P) (((_P)->ulFlags & (PDO_Activated | PDO_BeingRemoved)) == PDO_Activated) #define ADAPTER_TEST_FLAG(_A, _F) ((nicReadFlags(&(_A)->ulFlags) & (_F))!= 0) #define ADAPTER_SET_FLAG(_A, _F) (nicSetFlags(&(_A)->ulFlags, (_F))) #define ADAPTER_CLEAR_FLAG(_A, _F) (nicClearFlags(&(_A)->ulFlags , (_F))) #define ADAPTER_TEST_FLAGS(_A, _F) ((nicReadFlags(&(_A)->ulFlags) & (_F)) == (_F)) #define ADAPTER_READ_FLAGS(_A) ((nicReadFlags(&(_A)->ulFlags) #define ADAPTER_ACTIVE(_A) ((((_A)->ulFlags) & fADAPTER_VDOInactive) != fADAPTER_VDOInactive) #define BCR_TEST_FLAG(_A, _F) ((nicReadFlags(&(_A)->BCRData.Flags) & (_F))!= 0) #define BCR_SET_FLAG(_A, _F) (nicSetFlags(&(_A)->BCRData.Flags, (_F))) #define BCR_CLEAR_FLAG(_A, _F) (nicClearFlags(&(_A)->BCRData.Flags , (_F))) #define BCR_CLEAR_ALL_FLAGS(_A) ((_A)->BCRData.Flags = 0) #define BCR_TEST_FLAGS(_A, _F) ((nicReadFlags(&(_A)->BCRData.Flags) & (_F)) != 0) #define BCR_READ_FLAGS(_A) ((nicReadFlags(&(_A)->BCRData.Flags) #define BCR_IS_VALID(_B) ((_B)->NC_One == 1 && (_B)->NC_Valid ==1) #define IS_A_BCR(_B) ((_B)->NC_One == 1 ) #define LOOKASIDE_HEADER_SET_FLAG(_H, _F) (nicSetFlags(&(_H)->State.u.Flags, (_F))) #define LOOKASIDE_HEADER_TEST_FLAG(_H, _F) ((nicReadFlags(&(_H)->State.u.Flags) & (_F))!= 0) #define REASSEMBLY_ACTIVE(_R) (((_R)->Flags & (REASSEMBLY_ABORTED | REASSEMBLY_FREED)) == 0) #define REASSEMBLY_TEST_FLAG(_R,_F) ((nicReadFlags(&(_R)->Flags) & (_F))!= 0) #define REASSEMBLY_SET_FLAG(_R,_F) (nicSetFlags(&(_R)->Flags, (_F))) #define REASSEMBLY_CLEAR_FLAG(_R,_F) (nicClearFlags(&(_R)->Flags , (_F))) #define NIC_GET_SYSTEM_ADDRESS_FOR_MDL(_M) MmGetSystemAddressForMdl(_M) #define NIC_GET_BYTE_COUNT_FOR_MDL(_M) MmGetMdlByteCount(_M) #define nicNdisBufferVirtualAddress(_N) NdisBufferVirtualAddress(_N) #define nicNdisBufferLength(_N) NdisBufferLength(_N) // // These macros are used to assert that the IRQL level remains the same // at the beginning and end of a function // #if DBG #define STORE_CURRENT_IRQL UCHAR OldIrql = KeGetCurrentIrql(); #define MATCH_IRQL ASSERT (OldIrql == KeGetCurrentIrql() ); #else #define STORE_CURRENT_IRQL #define MATCH_IRQL #endif // if DBG #define nicInitializeCallRef(_pV) nicInitializeRef (&(_pV)->Hdr.CallRef); #define nicCloseCallRef(_pV) nicCloseRef (&(_pV)->Hdr.CallRef); // // Macros used to acquire and release lock by the data structures (Vc, AF, Adapter) // Right now, they all point to the same lock (i.e.) the lock in the Adapter structure // #define VC_ACQUIRE_LOCK(_pVc) NdisAcquireSpinLock (_pVc->Hdr.plock); #define VC_RELEASE_LOCK(_pVc) NdisReleaseSpinLock (_pVc->Hdr.plock); #define AF_ACQUIRE_LOCK(_pAF) NdisAcquireSpinLock (&_pAF->pAdapter->lock); #define AF_RELEASE_LOCK(_pAF) NdisReleaseSpinLock (&_pAF->pAdapter->lock); #define ADAPTER_ACQUIRE_LOCK(_pA) NdisAcquireSpinLock (&_pA->lock); #define ADAPTER_RELEASE_LOCK(_pA) NdisReleaseSpinLock (&_pA->lock); #define REMOTE_NODE_ACQUIRE_LOCK(_pP) NdisAcquireSpinLock (&_pP->pAdapter->lock); #define REMOTE_NODE_RELEASE_LOCK(_pP) NdisReleaseSpinLock (&_pP->pAdapter->lock); #define REASSEMBLY_ACQUIRE_LOCK(_R) REMOTE_NODE_REASSEMBLY_ACQUIRE_LOCK(_R->pRemoteNode); #define REASSEMBLY_RELEASE_LOCK(_R) REMOTE_NODE_REASSEMBLY_RELEASE_LOCK(_R->pRemoteNode); #ifdef TRACK_LOCKS #define REMOTE_NODE_REASSEMBLY_ACQUIRE_LOCK(_Remote) \ nicAcquireSpinLock (&_Remote->ReassemblyLock , __FILE__ , __LINE__); #define REMOTE_NODE_REASSEMBLY_RELEASE_LOCK(_Remote) \ nicReleaseSpinLock (&_Remote->ReassemblyLock , __FILE__ , __LINE__); #else #define REMOTE_NODE_REASSEMBLY_ACQUIRE_LOCK(_Remote) NdisAcquireSpinLock (&_Remote->ReassemblyLock.NdisLock); #define REMOTE_NODE_REASSEMBLY_RELEASE_LOCK(_Remote) NdisReleaseSpinLock (&_Remote->ReassemblyLock.NdisLock); #endif #define REASSEMBLY_APPEND_FRAG_DESC(_pR, _Off, _Len) \ _pR->FragTable[_pR->MaxOffsetTableIndex].Offset =_Off; \ _pR->FragTable[_pR->MaxOffsetTableIndex].IPLength = _Len; \ _pR->MaxOffsetTableIndex++; //----------------------------------------------------------------------------- // S T A T S & F A I L U R E M A C R O S //----------------------------------------------------------------------------- // Used to distinguish stats collected that are collected in the various code paths typedef enum { ChannelCodePath, FifoCodePath, ReceiveCodePath, NoMoreCodePaths }; #if TRACK_FAILURE extern ULONG BusFailure; extern ULONG MallocFailure; extern ULONG IsochOverwrite; extern ULONG MaxIndicatedFifos; #define nicInitTrackFailure() BusFailure = 0;MallocFailure= 0; #define nicIncrementBusFailure() NdisInterlockedIncrement(&BusFailure); #define nicIncrementMallocFailure() NdisInterlockedIncrement(&MallocFailure); #define nicIsochOverwritten() NdisInterlockedIncrement(&IsochOverwrite); #define nicStatsRecordNumIndicatedFifos(_Num) \ { \ ULONG _N_ = (_Num); \ MaxIndicatedFifos = max((_N_), MaxIndicatedFifos); \ } #define nicIncChannelSendMdl() NdisInterlockedIncrement(&MdlsAllocated[ChannelCodePath]); #define nicIncFifoSendMdl() NdisInterlockedIncrement(&MdlsAllocated[FifoCodePath]); #define nicDecChannelSendMdl() NdisInterlockedIncrement(&MdlsFreed[ChannelCodePath]); #define nicDecFifoSendMdl() NdisInterlockedIncrement(&MdlsFreed[FifoCodePath]); #define nicIncChannelRecvBuffer() NdisInterlockedIncrement(&NdisBufferAllocated[ChannelCodePath]); #define nicIncFifoRecvBuffer() NdisInterlockedIncrement(&NdisBufferAllocated[FifoCodePath]); #define nicDecChannelRecvBuffer() NdisInterlockedIncrement(&NdisBufferFreed[ChannelCodePath]); #define nicDecFifoRecvBuffer() NdisInterlockedIncrement(&NdisBufferFreed[FifoCodePath]); #define nicIncRecvBuffer(_bisFifo) \ { \ if (_bisFifo) \ { nicIncFifoRecvBuffer(); } \ else \ { nicIncChannelRecvBuffer();} \ } #define nicDecRecvBuffer(_bisFifo) \ { \ if (_bisFifo) \ { nicDecFifoRecvBuffer(); } \ else \ { nicDecChannelRecvBuffer(); }\ } #else #define nicInitTrackFailure() #define nicIncrementBusFailure() #define nicIncrementMallocFailure() #define nicIsochOverwritten() #define nicStatsRecordNumIndicatedFifos(_Num) #define nicIncChannelSendMdl() #define nicIncFifoSendMdl() #define nicDecChannelSendMdl() #define nicDecFifoSendMdl() #define nicFreeMdlRecordStat() #endif #define nicInitQueueStats() #define nicSetCountInHistogram(_PktsInQueue, _Stats) #define nicSetMax(_nicMax, _PktsInQueue) #define nicIncrementRcvTimerCount() #define nicIncrementSendTimerCount() // // Isoch descriptor macros - Used in the send/recv code path // typedef enum { IsochNext, IsochTag, IsochChannelVc, MaxIsochContextIndex } IsochContextIndex; // // The following structure is used to add more contexts to a work item. // NOTE: the Adapter is passed in as the context always. // typedef union _NIC_WORK_ITEM { NDIS_WORK_ITEM NdisWorkItem; struct{ NDIS_WORK_ITEM NdisWorkItem; PNDIS_REQUEST pNdisRequest; VCCB* pVc; } RequestInfo; struct{ NDIS_WORK_ITEM NdisWorkItem; ULONG Start; PNDIS_REQUEST pNdisRequest; } StartArpInfo; struct { NDIS_WORK_ITEM NdisWorkItem; } Fifo; } NIC_WORK_ITEM, *PNIC_WORK_ITEM; #define STORE_CHANNELVC_IN_DESCRIPTOR(_pI,_pVc) (_pI)->DeviceReserved[IsochChannelVc] =(ULONG_PTR) _pVc #define GET_CHANNELVC_FROM_DESCRIPTOR(_pI) (_pI)->DeviceReserved[IsochChannelVc] #define MARK_ISOCH_DESCRIPTOR_INDICATED(_pI) \ (_pI)->DeviceReserved[IsochTag] = (ULONG)NIC1394_TAG_INDICATED; \ (_pI)->DeviceReserved[IsochNext] = 0; #define MARK_ISOCH_DESCRIPTOR_IN_REASSEMBLY(_pI) \ (_pI)->DeviceReserved[IsochTag] = (ULONG)NIC1394_TAG_REASSEMBLY; #define CLEAR_DESCRIPTOR_OF_NDIS_TAG(_pI) \ (_pI)->DeviceReserved[IsochTag] = 0; #define APPEND_ISOCH_DESCRIPTOR(_Old, _New) \ (_Old)->DeviceReserved[IsochNext] = (ULONG_PTR)&((_New)->DeviceReserved[IsochNext]); #define NEXT_ISOCH_DESCRIPTOR(_pI) (_pI)->DeviceReserved[IsochNext] #define CLEAR_DESCRIPTOR_NEXT(_pI) (_pI)->DeviceReserved[IsochNext] = 0; #define GET_MDL_FROM_IRB(_pM, _pI, _Op) \ if (_Op==AsyncWrite) \ { \ _pM = _pI->u.AsyncWrite.Mdl; \ } \ else \ { \ ASSERT (_Op == AsyncStream); \ _pM = _pI->u.AsyncStream.Mdl ; \ } // // Macros used to walk a doubly linked list. Only macros that are not defined in ndis.h // The List Next macro will work on Single and Doubly linked list as Flink is a common // field name in both // /* PLIST_ENTRY ListNext ( IN PLIST_ENTRY ); PSINGLE_LIST_ENTRY ListNext ( IN PSINGLE_LIST_ENTRY ); */ #define ListNext(_pL) (_pL)->Flink /* PLIST_ENTRY ListPrev ( IN LIST_ENTRY * ); */ #define ListPrev(_pL) (_pL)->Blink #define OnlyElementInList(_pL) (_pL->Flink == _pL->Blink ? TRUE : FALSE) #define BREAK(_TM_Mode, _String) \ { \ TRACE( TL_A, _TM_Mode, ( _String ) ); \ break; \ } // USHORT // SWAPBYTES_USHORT(USHORT Val ) // #define SWAPBYTES_USHORT(Val) \ ((((Val) & 0xff) << 8) | (((Val) & 0xff00) >> 8)) // ULONG // SWAPBYTES_ULONG(ULONG Val ) // #define SWAPBYTES_ULONG(Val) \ ((((Val) & 0x000000ff) << 24) | \ (((Val) & 0x0000ff00) << 8) | \ (((Val) & 0x00ff0000) >> 8) | \ (((Val) & 0xff000000) >> 24) ) // // nicRemoveEntry List // Just add a check to make sure that we are actually pointing to a valid next // #define nicRemoveEntryList(_L) \ { \ ASSERT ((_L)->Flink != (_L)); \ RemoveEntryList (_L); \ } //#define nicFreeToNPagedLookasideList(_L, _E) NdisFreeToNPagedLookasideList(_L, _E) //#define nicDeleteLookasideList(_L) NdisDeleteNPagedLookasideList(_L) // // Timing Query Routines // #define nicQueryTickCount() \ LARGE_INTEGER TickStart; \ KeQueryTickCount(&TickStart); #define nicPrintElapsedTicks(_s) \ { \ LARGE_INTEGER TickEnd, TickDiff; \ ULONG Increment = KeQueryTimeIncrement() ; \ KeQueryTickCount(&TickEnd); \ TickDiff.QuadPart = TickEnd.QuadPart - TickStart.QuadPart; \ TickDiff.QuadPart = (TickDiff.QuadPart * Increment); \ DbgPrint (_s); \ DbgPrint(" TickStart %x %x, Time End %x %x Time Diff %x %x Increment %x\n",TickStart.HighPart , TickStart.LowPart , TickEnd.HighPart, TickEnd.LowPart, TickDiff.HighPart, TickDiff.LowPart, Increment); \ } #define nicEntryTimeStamp() \ UINT EntryMilliSec; \ EntryMilliSec= nicGetSystemTimeMilliSeconds(); #if DO_TIMESTAMPS void nicTimeStamp( char *szFormatString, UINT Val ); #define TIMESTAMP(_FormatString) nicTimeStamp("TIMESTAMP %lu:%lu.%lu nic1394 " _FormatString "\n" , 0) #define TIMESTAMP1(_FormatString, _Val) nicTimeStamp( "TIMESTAMP %lu:%lu.%lu ARP1394 " _FormatString "\n" , (_Val)) #else // !DO_TIMESTAMPS #define TIMESTAMP(_FormatString) #define TIMESTAMP1(_FormatString, _Val) #endif // !DO_TIMESTAMPS #if ENTRY_EXIT_TIME #define TIMESTAMP_ENTRY(_String) TIMESTAMP(_String) #define TIMESTAMP_EXIT(_String) TIMESTAMP(_String) #else #define TIMESTAMP_ENTRY(s); #define TIMESTAMP_EXIT(s); #endif #if INIT_HALT_TIME #define TIMESTAMP_INITIALIZE() TIMESTAMP("==>InitializeHandler"); #define TIMESTAMP_HALT() TIMESTAMP("<==Halt"); #else #define TIMESTAMP_INITIALIZE() #define TIMESTAMP_HALT() #endif //----------------------------------------------------------------------------- // S T A T I S T I C M A C R O S //----------------------------------------------------------------------------- // // Reasembly counts // #define nicReassemblyStarted(_pAdapter) \ { \ NdisInterlockedIncrement( &(_pAdapter->AdaptStats.TempStats.ulNumOutstandingReassemblies)); \ NdisInterlockedIncrement ( &(_pAdapter->Reassembly.PktsInQueue)); \ NdisInterlockedIncrement ( &(_pAdapter->OutstandingReassemblies));\ } #define nicReassemblyCompleted(_A) \ { \ NdisInterlockedDecrement(&(_A->AdaptStats.TempStats.ulNumOutstandingReassemblies));\ NdisInterlockedDecrement(&(_A->Reassembly.PktsInQueue));\ NdisInterlockedDecrement ( &(_A->OutstandingReassemblies));\ } #define nicReassemblyAborted(_A) \ { \ NdisInterlockedDecrement ( &(_A->OutstandingReassemblies)); \ NdisInterlockedIncrement (&(_A->AdaptStats.TempStats.ulAbortedReassemblies)); \ } // // Top level stat collection macros // #define nicIncrementRcvVcPktCount(_Vc, _Pkt) \ { \ if ((_Vc)->Hdr.VcType == NIC1394_RecvFIFO) \ { \ nicIncrementFifoRcvPktCount(_Vc, _Pkt); \ } \ else \ { \ nicIncrementChannelRcvPktCount(_Vc, _Pkt); \ } \ } #define nicIncrementVcSendPktCount(_Vc, _Pkt) \ { \ if ((_Vc)->Hdr.VcType == NIC1394_SendFIFO) \ { \ nicIncrementFifoSendPktCount(_Vc, _Pkt); \ } \ else \ { \ nicIncrementChannelSendPktCount(_Vc, _Pkt); \ } \ } #define nicIncrementVcSendFailures(_Vc, _Pkt) \ { \ if ((_Vc)->Hdr.VcType == NIC1394_SendFIFO) \ { \ nicIncrementFifoSendFailures(_Vc, _Pkt); \ } \ else \ { \ nicIncrementChannelSendFailures(_Vc, _Pkt); \ } \ } #define nicIncrementVcBusSendFailures(_Vc, _Pkt) \ { \ if ((_Vc)->Hdr.VcType == NIC1394_SendFIFO) \ { \ nicIncrementFifoBusSendFailures(_Vc, _Pkt); \ } \ else \ { \ nicIncrementChannelBusSendFailures(_Vc, _Pkt); \ } \ } #define nicIncrementVcBusSendSucess(_Vc, _Pkt) \ { \ if ((_Vc)->Hdr.VcType == NIC1394_SendFIFO) \ { \ nicIncrementFifoBusSendSucess(_Vc, _Pkt); \ } \ else \ { \ nicIncrementChannelBusSendSucess(_Vc, _Pkt); \ } \ } // // Fifo counts // #define nicIncrementFifoSendPktCount(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Fifo.ulSendNicSucess)); #define nicIncrementFifoSendFailures(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Fifo.ulSendNicFail)); #define nicIncrementFifoBusSendFailures(_Vc,_Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Fifo.ulSendBusFail)); #define nicIncrementFifoBusSendSucess(_Vc,_Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Fifo.ulSendBusSuccess)); #define nicIncrementFifoRcvPktCount(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Fifo.ulRecv)); // // Channel Counts // #define nicIncrementChannelSendPktCount(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Channel.ulSendNicSucess)); #define nicIncrementChannelSendFailures(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Channel.ulSendNicFail)); #define nicIncrementChannelBusSendFailures(_Vc,_Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Channel.ulSendBusFail)); #define nicIncrementChannelBusSendSucess(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Channel.ulSendBusSuccess)); #define nicIncrementChannelRcvPktCount(_Vc, _Pkt) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.Channel.ulRecv)); // // Generic counts // #define nicIncrementSendCompletes(_Vc) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.ulNumSendsCompleted )); \ NdisInterlockedIncrement(&NicSendCompletes); #define nicIncrementSends(_Vc) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.ulNumSends)); \ NdisInterlockedIncrement (&NicSends); #define nicIncrementBusSends(_Vc) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.ulNumBusSends)); \ NdisInterlockedIncrement (&BusSends); #define nicIncrementBusSendCompletes(_Vc) NdisInterlockedIncrement(&((_Vc)->Hdr.pAF->pAdapter->AdaptStats.TempStats.ulNumBusSendsCompleted )); \ NdisInterlockedIncrement(&BusSendCompletes); //----------------------------------------------------------------------------- // N I C E R R O R C O D E S //----------------------------------------------------------------------------- #define NIC_ERROR_CODE_INVALID_UNIQUE_ID_0 0xbad0000 #define NIC_ERROR_CODE_INVALID_UNIQUE_ID_FF 0xbadffff //----------------------------------------------------------------------------- // R E M O T E N O D E F U N C T I O N S //----------------------------------------------------------------------------- #if 0 VOID NicMpNotifyHandler( IN PDEVICE_OBJECT RemoteNodePhysicalDeviceObject, IN PDEVICE_OBJECT LocalHostPhysicalDeviceObject, IN ULONG UniqueId0, IN ULONG UniqueId1, IN NDIS1394ENUM_NOTIFY_CODE NotificationCode ); #endif NDIS_STATUS nicInitializeRemoteNode( OUT REMOTE_NODE **ppRemoteNode, IN PDEVICE_OBJECT p1394DeviceObject, IN UINT64 UniqueId ); NTSTATUS nicAddRemoteNode( IN PVOID Nic1394AdapterContext, // Nic1394 handle for the local host adapter IN PVOID Enum1394NodeHandle, // Enum1394 handle for the remote node IN PDEVICE_OBJECT RemoteNodePhysicalDeviceObject, // physical device object for the remote node IN ULONG UniqueId0, // unique ID Low for the remote node IN ULONG UniqueId1, // unique ID High for the remote node OUT PVOID * pNic1394NodeContext // Nic1394 context for the remote node ); NTSTATUS nicRemoveRemoteNode( IN PVOID Nic1394NodeContext // Nic1394 context for the remote node ); NDIS_STATUS nicFindRemoteNodeFromAdapter( IN PADAPTERCB pAdapter, IN PDEVICE_OBJECT pRemotePdo, IN UINT64 UniqueId, IN OUT REMOTE_NODE ** ppRemoteNode ); NDIS_STATUS nicGetLocalHostPdoBlock ( IN PVCCB pVc, IN OUT REMOTE_NODE **ppRemoteNode ); NDIS_STATUS nicRemoteNodeRemoveVcCleanUp ( IN PREMOTE_NODE pRemoteNode ); UINT nicNumOfActiveRemoteNodes( IN PADAPTERCB pAdapter ); BOOLEAN nicReferenceRemoteNode ( IN REMOTE_NODE *pRemoteNode, IN REMOTE_NODE_REF_CAUSE Cause ); BOOLEAN nicDereferenceRemoteNode ( IN REMOTE_NODE *pRemoteNode, IN REMOTE_NODE_REF_CAUSE Cause ); VOID nicInitalizeRefRemoteNode( IN REMOTE_NODE *pRemoteNode ); BOOLEAN nicCloseRefRemoteNode( IN REMOTE_NODE *pRemoteNode ); //----------------------------------------------------------------------------- // U T I L I T Y F U N C T I O N S //----------------------------------------------------------------------------- VOID nicCallCleanUp( IN VCCB* pVc ); VOID nicClearFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask ); BOOLEAN nicCloseRef( IN PREF RefP ); VOID nicReferenceAdapter( IN ADAPTERCB* pAdapter , IN PCHAR pDebugPrint ); BOOLEAN nicDereferenceCall( IN VCCB* pVc, IN PCHAR pDebugPrint ); BOOLEAN nicDereferenceRef( IN PREF RefP, IN PLONG pRefCount ); VOID nicDereferenceAdapter( IN PADAPTERCB pAdapter, IN PCHAR pDebugPrint ); VOID nicDereferenceVc( IN VCCB* pVc ); NDIS_STATUS nicExecuteWork( IN ADAPTERCB* pAdapter, IN NDIS_PROC pProc, IN PVOID pContext, IN ULONG ulArg1, IN ULONG ulArg2, IN ULONG ulArg3, IN ULONG ulArg4 ); VOID nicInitializeRef( IN PREF RefP ); ULONG nicReadFlags( IN ULONG* pulFlags ); VOID nicReferenceAdapter( IN ADAPTERCB* pAdapter, IN PCHAR pDebugPrint ); BOOLEAN nicReferenceCall( IN VCCB* pVc, IN PCHAR pDebugPrint ); BOOLEAN nicReferenceRef( IN PREF RefP, OUT PLONG pNumber ); VOID nicReferenceVc( IN VCCB* pVc ); NDIS_STATUS nicScheduleWork( IN ADAPTERCB* pAdapter, IN NDIS_PROC pProc, IN PVOID pContext ); VOID nicSetFlags( IN OUT ULONG* pulFlags, IN ULONG ulMask ); CHAR* nicStrDup( IN CHAR* psz ); CHAR* nicStrDupNdisString( IN NDIS_STRING* pNdisString ); CHAR* nicStrDupSized( IN CHAR* psz, IN ULONG ulLength, IN ULONG ulExtra ); VOID nicUpdateGlobalCallStats( IN VCCB *pVc ); NDIS_STATUS NtStatusToNdisStatus ( NTSTATUS NtStatus ); VOID PrintNdisPacket ( ULONG TM_Comp, PNDIS_PACKET pMyPacket ); VOID nicAllocatePacket( OUT PNDIS_STATUS pNdisStatus, OUT PNDIS_PACKET *ppNdisPacket, IN PNIC_PACKET_POOL pPacketPool ); VOID nicFreePacket( IN PNDIS_PACKET pNdisPacket, IN PNIC_PACKET_POOL pPacketPool ); VOID nicFreePacketPool ( IN PNIC_PACKET_POOL pPacketPool ); VOID nicAcquireSpinLock ( IN PNIC_SPIN_LOCK pNicSpinLock, IN PUCHAR FileName, IN UINT LineNumber ); VOID nicReleaseSpinLock ( IN PNIC_SPIN_LOCK pNicSpinLock, IN PUCHAR FileName, IN UINT LineNumber ); VOID nicInitializeNicSpinLock ( IN PNIC_SPIN_LOCK pNicSpinLock ); VOID nicFreeNicSpinLock ( IN PNIC_SPIN_LOCK pNicSpinLock ); VOID nic1394DeallocPktLog( IN ADAPTERCB* pAdapter ); VOID nic1394AllocPktLog( IN ADAPTERCB* pAdapter ); VOID Nic1394LogPkt ( PNIC1394_PKTLOG pPktLog, ULONG Flags, ULONG SourceID, ULONG DestID, PVOID pvData, ULONG cbData ); VOID Nic1394InitPktLog( PNIC1394_PKTLOG pPktLog ); ULONG SwapBytesUlong( IN ULONG Val ); VOID nicUpdatePacketState ( IN PNDIS_PACKET pPacket, IN ULONG Tag ); UINT nicGetSystemTime( VOID ); UINT nicGetSystemTimeMilliSeconds( VOID ); VOID nicGetFakeMacAddress( UINT64 *Euid, MAC_ADDRESS *MacAddr ); VOID nicWriteErrorLog ( IN PADAPTERCB pAdapter, IN NDIS_ERROR_CODE ErrorCode, IN ULONG ErrorValue ); NDIS_STATUS nicScheduleWorkItem ( IN PADAPTERCB pAdapter, IN PNDIS_WORK_ITEM pWorkItem ); //----------------------------------------------------------------------------- // G L O B A L V A R I A B L E S //----------------------------------------------------------------------------- UINT NumChannels; //----------------------------------------------------------------------------- // E N U M E R A T O R F U N C T I O N S //----------------------------------------------------------------------------- extern ENUM1394_REGISTER_DRIVER_HANDLER NdisEnum1394RegisterDriver; extern ENUM1394_DEREGISTER_DRIVER_HANDLER NdisEnum1394DeregisterDriver; extern ENUM1394_REGISTER_ADAPTER_HANDLER NdisEnum1394RegisterAdapter; extern ENUM1394_DEREGISTER_ADAPTER_HANDLER NdisEnum1394DeregisterAdapter; extern NIC1394_CHARACTERISTICS Nic1394Characteristics; NTSTATUS NicRegisterEnum1394( IN PNDISENUM1394_CHARACTERISTICS NdisEnum1394Characteristcis ); VOID NicDeregisterEnum1394( VOID ); VOID Nic1394Callback( PVOID CallBackContext, PVOID Source, PVOID Characteristics ); VOID Nic1394RegisterAdapters( VOID ); NTSTATUS Nic1394BusRequest( PDEVICE_OBJECT DeviceObject, PIRB Irb ); NTSTATUS Nic1394PassIrpDownTheStack( IN PIRP pIrp, IN PDEVICE_OBJECT pNextDeviceObject ); NTSTATUS Nic1394IrpCompletion( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context ); VOID nicDumpMdl ( IN PMDL pMdl, IN ULONG LengthToPrint, IN CHAR *str ); VOID nicDumpPkt ( IN PNDIS_PACKET pPacket, CHAR * str ); VOID nicCheckForEthArps ( IN PNDIS_PACKET pPkt ); VOID nicGetMacAddressFromEuid ( UINT64 *pEuid, MAC_ADDRESS *pMacAddr ); VOID nicInitializeLoadArpStruct( PADAPTERCB pAdapter ); extern PCALLBACK_OBJECT Nic1394CallbackObject; extern PVOID Nic1394CallbackRegisterationHandle; //----------------------------------------------------------------------------- // S T A T I S T I C B U C K E T S //----------------------------------------------------------------------------- extern STAT_BUCKET SendStats; extern STAT_BUCKET RcvStats; extern ULONG nicMaxRcv; extern ULONG nicMaxSend; extern ULONG SendTimer; // In ms extern ULONG RcvTimer; // In ms