899 lines
24 KiB
C
899 lines
24 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
atp.h
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
This module contains definitions for the ATP code.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Jameel Hyder (jameelh@microsoft.com)
|
|||
|
Nikhil Kamkolkar (nikhilk@microsoft.com)
|
|||
|
|
|||
|
Revision History:
|
|||
|
19 Jun 1992 Initial Version
|
|||
|
|
|||
|
Notes: Tab stop: 4
|
|||
|
--*/
|
|||
|
|
|||
|
#ifndef _ATP_
|
|||
|
#define _ATP_
|
|||
|
|
|||
|
// Command/control bit masks.
|
|||
|
#define ATP_REL_TIMER_MASK 0x07
|
|||
|
#define ATP_STS_MASK 0x08
|
|||
|
#define ATP_EOM_MASK 0x10
|
|||
|
#define ATP_XO_MASK 0x20
|
|||
|
|
|||
|
// Values for function code
|
|||
|
#define ATP_REQUEST 0x40
|
|||
|
#define ATP_RESPONSE 0x80
|
|||
|
#define ATP_RELEASE 0xC0
|
|||
|
#define ATP_FUNC_MASK 0xC0
|
|||
|
|
|||
|
#define ATP_CMD_CONTROL_OFF 0
|
|||
|
#define ATP_BITMAP_OFF 1
|
|||
|
#define ATP_SEQ_NUM_OFF 1
|
|||
|
#define ATP_TRANS_ID_OFF 2
|
|||
|
#define ATP_USER_BYTES_OFF 4
|
|||
|
#define ATP_DATA_OFF 8
|
|||
|
|
|||
|
#define ATP_MAX_RESP_PKTS 8
|
|||
|
#define ATP_USERBYTES_SIZE 4
|
|||
|
#define ATP_HEADER_SIZE 8
|
|||
|
|
|||
|
// NOTE: Event handler routines- ATP has no event handling support
|
|||
|
|
|||
|
|
|||
|
// ATP Address Object
|
|||
|
|
|||
|
#define ATP_DEF_MAX_SINGLE_PKT_SIZE 578
|
|||
|
#define ATP_MAX_TOTAL_RESPONSE_SIZE (ATP_MAX_RESP_PKTS * ATP_DEF_MAX_SINGLE_PKT_SIZE)
|
|||
|
#define ATP_DEF_SEND_USER_BYTES_ALL ((BOOLEAN)FALSE)
|
|||
|
|
|||
|
#define ATP_DEF_RETRY_INTERVAL 20 // 2 seconds in 100ms units
|
|||
|
#define ATP_INFINITE_RETRIES -1
|
|||
|
|
|||
|
#define ATP_REQ_HASH_SIZE 29
|
|||
|
#define ATP_RESP_HASH_SIZE 37
|
|||
|
|
|||
|
// Values for the release timer (.5, 1, 2, 4, 8 minutes).
|
|||
|
typedef LONG RELEASE_TIMERVALUE;
|
|||
|
|
|||
|
#define FIRSTVALID_TIMER 0
|
|||
|
#define THIRTY_SEC_TIMER 0
|
|||
|
#define ONE_MINUTE_TIMER 1
|
|||
|
#define TWO_MINUTE_TIMER 2
|
|||
|
#define FOUR_MINUTE_TIMER 3
|
|||
|
#define EIGHT_MINUTE_TIMER 4
|
|||
|
#define LAST_VALID_TIMER 4
|
|||
|
#define MAX_VALID_TIMERS 5
|
|||
|
|
|||
|
// Different subtypes for ATP indication type.
|
|||
|
#define ATP_ALLOC_BUF 0
|
|||
|
#define ATP_USER_BUF 1
|
|||
|
#define ATP_USER_BUFX 2 // Do not indicate the packet to Atp with this.
|
|||
|
|
|||
|
struct _ATP_RESP;
|
|||
|
|
|||
|
typedef VOID (*ATPAO_CLOSECOMPLETION)(
|
|||
|
IN ATALK_ERROR CloseResult,
|
|||
|
IN PVOID CloseContext
|
|||
|
);
|
|||
|
|
|||
|
typedef VOID (*ATP_REQ_HANDLER)(
|
|||
|
IN ATALK_ERROR Error,
|
|||
|
IN PVOID CompletionContext,
|
|||
|
IN struct _ATP_RESP * pAtpResp,
|
|||
|
IN PATALK_ADDR SourceAddress,
|
|||
|
IN USHORT RequestLength,
|
|||
|
IN PBYTE RequestPacket,
|
|||
|
IN PBYTE RequestUserBytes // 4 bytes of user bytes
|
|||
|
);
|
|||
|
|
|||
|
typedef VOID (*ATP_RESP_HANDLER)(
|
|||
|
IN ATALK_ERROR Error,
|
|||
|
IN PVOID CompletionContext,
|
|||
|
IN PAMDL RequestBuffer,
|
|||
|
IN PAMDL ResponseBuffer,
|
|||
|
IN USHORT ResponseSize,
|
|||
|
IN PBYTE ResponseUserBytes // 4 bytes of user bytes
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
typedef VOID (FASTCALL *ATP_REL_HANDLER)(
|
|||
|
IN ATALK_ERROR Error,
|
|||
|
IN PVOID CompletionContext
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
// ATP ADDRESS OBJECT STATES
|
|||
|
|
|||
|
#define ATPAO_OPEN 0x00000001
|
|||
|
#define ATPAO_SENDUSERBYTESALL 0x00000002
|
|||
|
#define ATPAO_CACHED 0x00000004
|
|||
|
#define ATPAO_TIMERS 0x00000008
|
|||
|
#define ATPAO_CLEANUP 0x40000000
|
|||
|
#define ATPAO_CLOSING 0x80000000
|
|||
|
|
|||
|
#define ATPAO_SIGNATURE (*(PULONG)"ATPA")
|
|||
|
|
|||
|
#if DBG
|
|||
|
#define VALID_ATPAO(pAtpAddr) (((pAtpAddr) != NULL) && \
|
|||
|
((pAtpAddr)->atpao_Signature == ATPAO_SIGNATURE))
|
|||
|
#else
|
|||
|
#define VALID_ATPAO(pAtpAddr) ((pAtpAddr) != NULL)
|
|||
|
#endif
|
|||
|
typedef struct _ATP_ADDROBJ
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
ULONG atpao_Signature;
|
|||
|
#endif
|
|||
|
|
|||
|
LONG atpao_RefCount;
|
|||
|
|
|||
|
// State of the address object
|
|||
|
ULONG atpao_Flags;
|
|||
|
|
|||
|
// We pass a pointer to the ATP Address object to the upper layers to
|
|||
|
// use as the endpoint, and this same pointer is passed to DDP Open
|
|||
|
// Address as the ATP address handler context.
|
|||
|
|
|||
|
// Linkage list for all responses to AtLeastOnce (ALO) transactions.
|
|||
|
// These are not kept in the resp hash table for efficiency. These
|
|||
|
// happen very infrequently and only exist on the list until the
|
|||
|
// SENDs complete.
|
|||
|
struct _ATP_RESP * atpao_AloRespLinkage;
|
|||
|
|
|||
|
// next Transaction id to be used
|
|||
|
USHORT atpao_NextTid;
|
|||
|
|
|||
|
// Maximum single packet size to be used (PAP needs this to be 512)
|
|||
|
USHORT atpao_MaxSinglePktSize;
|
|||
|
|
|||
|
// Pointer to the DDP address object that this will create
|
|||
|
PDDP_ADDROBJ atpao_DdpAddr;
|
|||
|
|
|||
|
// Completion routine to be called when socket is closed
|
|||
|
ATPAO_CLOSECOMPLETION atpao_CloseComp;
|
|||
|
PVOID atpao_CloseCtx;
|
|||
|
|
|||
|
// Hash table of pending ATP PostReq
|
|||
|
struct _ATP_REQ * atpao_ReqHash[ATP_REQ_HASH_SIZE];
|
|||
|
|
|||
|
LIST_ENTRY atpao_ReqList; // List of requests for retry timer
|
|||
|
TIMERLIST atpao_RetryTimer; // Retry timer for ALL requests
|
|||
|
|
|||
|
// Hash table of pending ATP PostResponses
|
|||
|
struct _ATP_RESP * atpao_RespHash[ATP_RESP_HASH_SIZE];
|
|||
|
|
|||
|
LIST_ENTRY atpao_RespList; // List of requests for release timer
|
|||
|
TIMERLIST atpao_RelTimer; // Release timer for ALL XO responses
|
|||
|
|
|||
|
// handler and corres. contexts for requests
|
|||
|
ATP_REQ_HANDLER atpao_ReqHandler;
|
|||
|
PVOID atpao_ReqCtx;
|
|||
|
|
|||
|
PATALK_DEV_CTX atpao_DevCtx;
|
|||
|
ATALK_SPIN_LOCK atpao_Lock;
|
|||
|
} ATP_ADDROBJ, *PATP_ADDROBJ;
|
|||
|
|
|||
|
|
|||
|
#define ATP_REQ_EXACTLY_ONCE 0x0001
|
|||
|
#define ATP_REQ_RETRY_TIMER 0x0002
|
|||
|
#define ATP_REQ_REMOTE 0x0004
|
|||
|
#define ATP_REQ_RESPONSE_COMPLETE 0x0008
|
|||
|
#define ATP_REQ_CLOSING 0x8000
|
|||
|
|
|||
|
#define ATP_REQ_SIGNATURE (*(PULONG)"ATRQ")
|
|||
|
#if DBG
|
|||
|
#define VALID_ATPRQ(pAtpReq) (((pAtpReq) != NULL) && \
|
|||
|
((pAtpReq)->req_Signature == ATP_REQ_SIGNATURE))
|
|||
|
#else
|
|||
|
#define VALID_ATPRQ(pAtpReq) ((pAtpReq) != NULL)
|
|||
|
#endif
|
|||
|
typedef struct _ATP_REQ
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
ULONG req_Signature;
|
|||
|
#endif
|
|||
|
|
|||
|
LONG req_RefCount;
|
|||
|
|
|||
|
// Linkage of requests on this address object (hash overflow)
|
|||
|
struct _ATP_REQ * req_Next;
|
|||
|
struct _ATP_REQ ** req_Prev;
|
|||
|
|
|||
|
LIST_ENTRY req_List; // List of requests for retry timer
|
|||
|
|
|||
|
// BackPointer to the ATP address object. Need for reference/Dereference.
|
|||
|
PATP_ADDROBJ req_pAtpAddr;
|
|||
|
|
|||
|
// State of the request
|
|||
|
USHORT req_Flags;
|
|||
|
|
|||
|
// ATP Bitmap showing the response packets we are waiting for/expect.
|
|||
|
BYTE req_Bitmap;
|
|||
|
|
|||
|
BYTE req_RecdBitmap;
|
|||
|
|
|||
|
// Destination of this request
|
|||
|
ATALK_ADDR req_Dest;
|
|||
|
|
|||
|
// Request buffer for retransmission
|
|||
|
PAMDL req_Buf;
|
|||
|
USHORT req_BufLen;
|
|||
|
|
|||
|
// Transaction id
|
|||
|
USHORT req_Tid;
|
|||
|
|
|||
|
union
|
|||
|
{
|
|||
|
BYTE req_UserBytes[ATP_USERBYTES_SIZE];
|
|||
|
DWORD req_dwUserBytes;
|
|||
|
};
|
|||
|
|
|||
|
// User's response buffer
|
|||
|
PAMDL req_RespBuf;
|
|||
|
|
|||
|
// Buffer descriptors for parts of the resp buf.
|
|||
|
PNDIS_BUFFER req_NdisBuf[ATP_MAX_RESP_PKTS];
|
|||
|
|
|||
|
USHORT req_RespBufLen;
|
|||
|
|
|||
|
// Received response length
|
|||
|
USHORT req_RespRecdLen;
|
|||
|
BYTE req_RespUserBytes[ATP_USERBYTES_SIZE];
|
|||
|
|
|||
|
LONG req_RetryInterval;
|
|||
|
LONG req_RetryCnt;
|
|||
|
|
|||
|
// Release timer value to send to the remote end.
|
|||
|
RELEASE_TIMERVALUE req_RelTimerValue;
|
|||
|
|
|||
|
// Retry time stamp, time at which the request will be retried if no response
|
|||
|
LONG req_RetryTimeStamp;
|
|||
|
|
|||
|
// Completion routine to be called when request is done
|
|||
|
ATALK_ERROR req_CompStatus;
|
|||
|
ATP_RESP_HANDLER req_Comp;
|
|||
|
PVOID req_Ctx;
|
|||
|
ATALK_SPIN_LOCK req_Lock;
|
|||
|
} ATP_REQ, *PATP_REQ;
|
|||
|
|
|||
|
// ATP_RESP_REMOTE indicates that the response is not to a local socket in which
|
|||
|
// case we can avoid trying to deliver to our sockets
|
|||
|
#define ATP_RESP_EXACTLY_ONCE 0x0001
|
|||
|
#define ATP_RESP_ONLY_USER_BYTES 0x0002
|
|||
|
#define ATP_RESP_REL_TIMER 0x0004
|
|||
|
#define ATP_RESP_VALID_RESP 0x0008
|
|||
|
#define ATP_RESP_SENT 0x0010
|
|||
|
#define ATP_RESP_TRANSMITTING 0x0020
|
|||
|
#define ATP_RESP_REMOTE 0x0040
|
|||
|
#define ATP_RESP_HANDLER_NOTIFIED 0x0080
|
|||
|
#define ATP_RESP_CANCELLED 0x0100
|
|||
|
#define ATP_RESP_RELEASE_RECD 0x0200
|
|||
|
#define ATP_RESP_CLOSING 0x8000
|
|||
|
|
|||
|
#define ATP_RESP_SIGNATURE (*(PULONG)"ATRS")
|
|||
|
#if DBG
|
|||
|
#define VALID_ATPRS(pAtpResp) (((pAtpResp) != NULL) && \
|
|||
|
((pAtpResp)->resp_Signature == ATP_RESP_SIGNATURE))
|
|||
|
#else
|
|||
|
#define VALID_ATPRS(pAtpResp) ((pAtpResp) != NULL)
|
|||
|
#endif
|
|||
|
typedef struct _ATP_RESP
|
|||
|
{
|
|||
|
#if DBG
|
|||
|
ULONG resp_Signature;
|
|||
|
#endif
|
|||
|
|
|||
|
LONG resp_RefCount;
|
|||
|
|
|||
|
// Linkage of responses on this address object (hash overflow)
|
|||
|
struct _ATP_RESP * resp_Next;
|
|||
|
struct _ATP_RESP ** resp_Prev;
|
|||
|
|
|||
|
LIST_ENTRY resp_List; // List of resp for release timer
|
|||
|
|
|||
|
// BackPointer to the ATP address object
|
|||
|
PATP_ADDROBJ resp_pAtpAddr;
|
|||
|
|
|||
|
// Transaction id
|
|||
|
USHORT resp_Tid;
|
|||
|
|
|||
|
// ATP Bitmap from corresponding request
|
|||
|
BYTE resp_Bitmap;
|
|||
|
BYTE resp_UserBytesOnly;
|
|||
|
|
|||
|
// Destination of this request
|
|||
|
ATALK_ADDR resp_Dest;
|
|||
|
|
|||
|
// State of the response
|
|||
|
USHORT resp_Flags;
|
|||
|
|
|||
|
// User's response buffer
|
|||
|
USHORT resp_BufLen;
|
|||
|
PAMDL resp_Buf;
|
|||
|
union
|
|||
|
{
|
|||
|
BYTE resp_UserBytes[ATP_USERBYTES_SIZE];
|
|||
|
DWORD resp_dwUserBytes;
|
|||
|
};
|
|||
|
|
|||
|
// Release timer value, How long do we wait before release.
|
|||
|
LONG resp_RelTimerTicks;
|
|||
|
|
|||
|
// Release time stamp, time at which the request arrived.
|
|||
|
LONG resp_RelTimeStamp;
|
|||
|
|
|||
|
// Routine to call when release comes in, or release timer expires
|
|||
|
ATALK_ERROR resp_CompStatus;
|
|||
|
ATP_REL_HANDLER resp_Comp;
|
|||
|
PVOID resp_Ctx;
|
|||
|
ATALK_SPIN_LOCK resp_Lock;
|
|||
|
} ATP_RESP, *PATP_RESP;
|
|||
|
|
|||
|
|
|||
|
#define ATP_RETRY_TIMER_INTERVAL 10 // 1 second in 100ms units
|
|||
|
// NOTE: This will essentially put dampers on
|
|||
|
// the RT stuff. Thats not too bad since
|
|||
|
// we are guaranteed to try every second atleast
|
|||
|
#define ATP_RELEASE_TIMER_INTERVAL 300 // 30 seconds in 100ms units
|
|||
|
|
|||
|
// Values for the 0.5, 1, 2, 4, 8 minute timer in ATP_RELEASE_TIMER_INTERVAL units.
|
|||
|
extern SHORT AtalkAtpRelTimerTicks[MAX_VALID_TIMERS];
|
|||
|
|
|||
|
// Bitmaps for the sequence numbers in response packets.
|
|||
|
extern BYTE AtpBitmapForSeqNum[ATP_MAX_RESP_PKTS];
|
|||
|
|
|||
|
extern BYTE AtpEomBitmapForSeqNum[ATP_MAX_RESP_PKTS];
|
|||
|
|
|||
|
typedef struct
|
|||
|
{
|
|||
|
BYTE atph_CmdCtrl;
|
|||
|
union
|
|||
|
{
|
|||
|
BYTE atph_SeqNum;
|
|||
|
BYTE atph_Bitmap;
|
|||
|
};
|
|||
|
USHORT atph_Tid;
|
|||
|
union
|
|||
|
{
|
|||
|
BYTE atph_UserBytes[ATP_USERBYTES_SIZE];
|
|||
|
DWORD atph_dwUserBytes;
|
|||
|
};
|
|||
|
} ATP_HEADER, *PATP_HEADER;
|
|||
|
|
|||
|
// Exported prototypes
|
|||
|
#define AtalkAtpGetDdpAddress(pAtpAddr) ((pAtpAddr)->atpao_DdpAddr)
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpOpenAddress(
|
|||
|
IN PPORT_DESCRIPTOR pPort,
|
|||
|
IN BYTE Socket,
|
|||
|
IN OUT PATALK_NODEADDR pDesiredNode OPTIONAL,
|
|||
|
IN USHORT MaxSinglePktSize,
|
|||
|
IN BOOLEAN SendUserBytesAll,
|
|||
|
IN PATALK_DEV_CTX pDevCtx OPTIONAL,
|
|||
|
IN BOOLEAN CacheSocket,
|
|||
|
OUT PATP_ADDROBJ * ppAtpAddr);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpCleanupAddress(
|
|||
|
IN PATP_ADDROBJ pAtpAddr);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpCloseAddress(
|
|||
|
IN PATP_ADDROBJ pAddr,
|
|||
|
IN ATPAO_CLOSECOMPLETION pCloseCmp OPTIONAL,
|
|||
|
IN PVOID pCloseCtx OPTIONAL);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpPostReq(
|
|||
|
IN PATP_ADDROBJ pAddr,
|
|||
|
IN PATALK_ADDR pDest,
|
|||
|
OUT PUSHORT pTid,
|
|||
|
IN USHORT Flags,
|
|||
|
IN PAMDL pReq,
|
|||
|
IN USHORT ReqLen,
|
|||
|
IN PBYTE pUserBytes OPTIONAL,
|
|||
|
IN OUT PAMDL pResp OPTIONAL,
|
|||
|
IN USHORT RespLen,
|
|||
|
IN SHORT RetryCnt,
|
|||
|
IN LONG RetryInterval,
|
|||
|
IN RELEASE_TIMERVALUE timerVal,
|
|||
|
IN ATP_RESP_HANDLER pCmpRoutine OPTIONAL,
|
|||
|
IN PVOID pCtx OPTIONAL);
|
|||
|
|
|||
|
extern
|
|||
|
VOID
|
|||
|
AtalkAtpSetReqHandler(
|
|||
|
IN PATP_ADDROBJ pAddr,
|
|||
|
IN ATP_REQ_HANDLER ReqHandler,
|
|||
|
IN PVOID ReqCtx OPTIONAL);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpPostResp(
|
|||
|
IN PATP_RESP pAtpResp,
|
|||
|
IN PATALK_ADDR pDest,
|
|||
|
IN OUT PAMDL pResp,
|
|||
|
IN USHORT RespLen,
|
|||
|
IN PBYTE pUbytes OPTIONAL,
|
|||
|
IN ATP_REL_HANDLER pCmpRoutine,
|
|||
|
IN PVOID pCtx OPTIONAL);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpCancelReq(
|
|||
|
IN PATP_ADDROBJ pAtpAddr,
|
|||
|
IN USHORT Tid,
|
|||
|
IN PATALK_ADDR pDest);
|
|||
|
|
|||
|
extern
|
|||
|
BOOLEAN
|
|||
|
AtalkAtpIsReqComplete(
|
|||
|
IN PATP_ADDROBJ pAtpAddr,
|
|||
|
IN USHORT Tid,
|
|||
|
IN PATALK_ADDR pDest);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpCancelResp(
|
|||
|
IN PATP_RESP pAtpResp);
|
|||
|
|
|||
|
extern
|
|||
|
ATALK_ERROR
|
|||
|
AtalkAtpCancelRespByTid(
|
|||
|
IN PATP_ADDROBJ pAtpAddr,
|
|||
|
IN PATALK_ADDR pDest,
|
|||
|
IN USHORT Tid);
|
|||
|
|
|||
|
extern
|
|||
|
VOID
|
|||
|
AtalkAtpPacketIn(
|
|||
|
IN PPORT_DESCRIPTOR pPortDesc,
|
|||
|
IN PDDP_ADDROBJ pDdpAddr,
|
|||
|
IN PBYTE pPkt,
|
|||
|
IN USHORT PktLen,
|
|||
|
IN PATALK_ADDR pSrcAddr,
|
|||
|
IN PATALK_ADDR pDstAddr,
|
|||
|
IN ATALK_ERROR ErrorCode,
|
|||
|
IN BYTE DdpType,
|
|||
|
IN PATP_ADDROBJ pAtpAddr,
|
|||
|
IN BOOLEAN OptimizePath,
|
|||
|
IN PVOID OptimizeCtx);
|
|||
|
|
|||
|
#define AtalkAtpAddrReference(_pAtpAddr, _pError) \
|
|||
|
{ \
|
|||
|
KIRQL OldIrql; \
|
|||
|
\
|
|||
|
ACQUIRE_SPIN_LOCK(&(_pAtpAddr)->atpao_Lock, &OldIrql); \
|
|||
|
atalkAtpAddrRefNonInterlock((_pAtpAddr), _pError); \
|
|||
|
RELEASE_SPIN_LOCK(&(_pAtpAddr)->atpao_Lock, OldIrql); \
|
|||
|
}
|
|||
|
|
|||
|
#define AtalkAtpAddrReferenceDpc(_pAtpAddr, _pError) \
|
|||
|
{ \
|
|||
|
ACQUIRE_SPIN_LOCK_DPC(&(_pAtpAddr)->atpao_Lock); \
|
|||
|
atalkAtpAddrRefNonInterlock((_pAtpAddr), _pError); \
|
|||
|
RELEASE_SPIN_LOCK_DPC(&(_pAtpAddr)->atpao_Lock); \
|
|||
|
}
|
|||
|
|
|||
|
#define atalkAtpAddrRefNonInterlock(_pAtpAddr, _pError) \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_NO_ERROR; \
|
|||
|
if (((_pAtpAddr)->atpao_Flags & (ATPAO_CLOSING|ATPAO_OPEN))==ATPAO_OPEN)\
|
|||
|
{ \
|
|||
|
ASSERT((_pAtpAddr)->atpao_RefCount >= 1); \
|
|||
|
(_pAtpAddr)->atpao_RefCount++; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_ATP_CLOSING; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("atalkAtpAddrRefNonInterlock: %lx %s (%ld) Failure\n", \
|
|||
|
_pAtpAddr, __FILE__, __LINE__)); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
AtalkAtpAddrDeref(
|
|||
|
IN OUT PATP_ADDROBJ pAtpAddr,
|
|||
|
IN BOOLEAN AtDpc);
|
|||
|
|
|||
|
#define AtalkAtpAddrDereference(_pAtpAddr) \
|
|||
|
AtalkAtpAddrDeref(_pAtpAddr, FALSE)
|
|||
|
|
|||
|
#define AtalkAtpAddrDereferenceDpc(_pAtpAddr) \
|
|||
|
AtalkAtpAddrDeref(_pAtpAddr, TRUE)
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
AtalkAtpRespDeref(
|
|||
|
IN PATP_RESP pAtpResp,
|
|||
|
IN BOOLEAN AtDpc);
|
|||
|
|
|||
|
#define AtalkAtpRespDereference(_pAtrpResp) \
|
|||
|
AtalkAtpRespDeref(_pAtrpResp, FALSE)
|
|||
|
|
|||
|
#define AtalkAtpRespDereferenceDpc(_pAtrpResp) \
|
|||
|
AtalkAtpRespDeref(_pAtrpResp, TRUE)
|
|||
|
|
|||
|
#define AtalkAtpRespReferenceByPtr(_pAtpResp, _pError) \
|
|||
|
{ \
|
|||
|
KIRQL OldIrql; \
|
|||
|
\
|
|||
|
*(_pError) = ATALK_NO_ERROR; \
|
|||
|
\
|
|||
|
ACQUIRE_SPIN_LOCK(&(_pAtpResp)->resp_Lock, &OldIrql); \
|
|||
|
if (((_pAtpResp)->resp_Flags & ATP_RESP_CLOSING) == 0) \
|
|||
|
{ \
|
|||
|
(_pAtpResp)->resp_RefCount++; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("AtalkAtpRespReferenceByPtr: %lx %s (%ld) Failure\n", \
|
|||
|
_pAtpResp, __FILE__, __LINE__)); \
|
|||
|
*(_pError) = ATALK_ATP_RESP_CLOSING; \
|
|||
|
} \
|
|||
|
RELEASE_SPIN_LOCK(&(_pAtpResp)->resp_Lock, OldIrql); \
|
|||
|
}
|
|||
|
|
|||
|
#define AtalkAtpRespReferenceByPtrDpc(_pAtpResp, _pError) \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_NO_ERROR; \
|
|||
|
\
|
|||
|
ACQUIRE_SPIN_LOCK_DPC(&(_pAtpResp)->resp_Lock); \
|
|||
|
if (((_pAtpResp)->resp_Flags & ATP_RESP_CLOSING) == 0) \
|
|||
|
{ \
|
|||
|
(_pAtpResp)->resp_RefCount++; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_ATP_RESP_CLOSING; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("atalkAtpRespRefByPtrDpc: %lx %s (%ld) Failure\n", \
|
|||
|
_pAtpResp, __FILE__, __LINE__)); \
|
|||
|
} \
|
|||
|
RELEASE_SPIN_LOCK_DPC(&(_pAtpResp)->resp_Lock); \
|
|||
|
}
|
|||
|
|
|||
|
ATALK_ERROR
|
|||
|
AtalkIndAtpPkt(
|
|||
|
IN PPORT_DESCRIPTOR pPortDesc,
|
|||
|
IN PBYTE pLookahead,
|
|||
|
IN USHORT PktLen,
|
|||
|
IN OUT PUINT pXferOffset,
|
|||
|
IN PBYTE pLinkHdr,
|
|||
|
IN BOOLEAN ShortDdpHdr,
|
|||
|
OUT PBYTE SubType,
|
|||
|
OUT PBYTE * ppPacket,
|
|||
|
OUT PNDIS_PACKET * pNdisPkt);
|
|||
|
|
|||
|
ATALK_ERROR
|
|||
|
AtalkIndAtpCacheSocket(
|
|||
|
IN struct _ATP_ADDROBJ * pAtpAddr,
|
|||
|
IN PPORT_DESCRIPTOR pPortDesc);
|
|||
|
|
|||
|
VOID
|
|||
|
AtalkIndAtpUnCacheSocket(
|
|||
|
IN struct _ATP_ADDROBJ * pAtpAddr);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
AtalkAtpGenericRespComplete(
|
|||
|
IN ATALK_ERROR ErrorCode,
|
|||
|
IN PATP_RESP pAtpResp
|
|||
|
);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
AtalkIndAtpSetupNdisBuffer(
|
|||
|
IN OUT PATP_REQ pAtpReq,
|
|||
|
IN ULONG MaxSinglePktSize
|
|||
|
);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
AtalkIndAtpReleaseNdisBuffer(
|
|||
|
IN OUT PATP_REQ pAtpReq
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
// ATALK_ERROR
|
|||
|
// AtalkIndAtpCacheLkUpSocket(
|
|||
|
// IN PATALK_ADDR pDestAddr,
|
|||
|
// OUT struct _ATP_ADDROBJ ** ppAtpAddr,
|
|||
|
// OUT ATALK_ERROR * pError);
|
|||
|
//
|
|||
|
#define AtalkIndAtpCacheLkUpSocket(pDestAddr, ppAtpAddr, pError) \
|
|||
|
{ \
|
|||
|
USHORT i; \
|
|||
|
struct ATALK_CACHED_SKT *pCachedSkt; \
|
|||
|
\
|
|||
|
*(pError) = ATALK_FAILURE; \
|
|||
|
\
|
|||
|
if (((pDestAddr)->ata_Network == AtalkSktCache.ac_Network) && \
|
|||
|
((pDestAddr)->ata_Node == AtalkSktCache.ac_Node)) \
|
|||
|
{ \
|
|||
|
ACQUIRE_SPIN_LOCK_DPC(&AtalkSktCacheLock); \
|
|||
|
\
|
|||
|
for (i = 0, pCachedSkt = &AtalkSktCache.ac_Cache[0]; \
|
|||
|
i < ATALK_CACHE_SKTMAX; \
|
|||
|
i++, pCachedSkt++) \
|
|||
|
{ \
|
|||
|
if ((pCachedSkt->Type == (ATALK_CACHE_INUSE | ATALK_CACHE_ATPSKT)) && \
|
|||
|
(pCachedSkt->Socket == (pDestAddr)->ata_Socket))\
|
|||
|
{ \
|
|||
|
AtalkAtpAddrReferenceDpc(pCachedSkt->u.pAtpAddr,\
|
|||
|
pError); \
|
|||
|
\
|
|||
|
if (ATALK_SUCCESS(*pError)) \
|
|||
|
{ \
|
|||
|
*(ppAtpAddr) = pCachedSkt->u.pAtpAddr; \
|
|||
|
} \
|
|||
|
break; \
|
|||
|
} \
|
|||
|
} \
|
|||
|
\
|
|||
|
RELEASE_SPIN_LOCK_DPC(&AtalkSktCacheLock); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpReqDeref(
|
|||
|
IN PATP_REQ pAtpReq,
|
|||
|
IN BOOLEAN AtDpc);
|
|||
|
|
|||
|
// MACROS
|
|||
|
// Top byte of network number is pretty static so we get rid of it and add
|
|||
|
// in the tid.
|
|||
|
#define ATP_HASH_TID_DESTADDR(_tid, _pAddr, _BucketSize) \
|
|||
|
(((_pAddr)->ata_Node+((_pAddr)->ata_Network & 0xFF)+_tid)%(_BucketSize))
|
|||
|
|
|||
|
#define atalkAtpReqReferenceByAddrTidDpc(_pAtpAddr, _pAddr, _Tid, _ppAtpReq, _pErr) \
|
|||
|
{ \
|
|||
|
PATP_REQ __p; \
|
|||
|
ULONG __i; \
|
|||
|
\
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO, \
|
|||
|
("atalkAtpReqRefByAddrTid: %lx.%lx.%lx tid %lx\n", \
|
|||
|
(_pAddr)->ata_Network, (_pAddr)->ata_Node, \
|
|||
|
(_pAddr)->ata_Socket, (_Tid))); \
|
|||
|
\
|
|||
|
__i = ATP_HASH_TID_DESTADDR((_Tid), (_pAddr), ATP_REQ_HASH_SIZE); \
|
|||
|
for (__p = (_pAtpAddr)->atpao_ReqHash[(__i)]; \
|
|||
|
__p != NULL; \
|
|||
|
__p = __p->req_Next) \
|
|||
|
{ \
|
|||
|
if ((ATALK_ADDRS_EQUAL(&__p->req_Dest, (_pAddr))) && \
|
|||
|
(__p->req_Tid == (_Tid))) \
|
|||
|
{ \
|
|||
|
AtalkAtpReqReferenceByPtrDpc(__p, _pErr); \
|
|||
|
if (ATALK_SUCCESS(*(_pErr))) \
|
|||
|
{ \
|
|||
|
*(_ppAtpReq) = __p; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO, \
|
|||
|
("atalkAtpReqRefByAddrTid: FOUND %lx\n", __p)); \
|
|||
|
} \
|
|||
|
break; \
|
|||
|
} \
|
|||
|
} \
|
|||
|
if (__p == NULL) \
|
|||
|
*(_pErr) = ATALK_ATP_NOT_FOUND; \
|
|||
|
}
|
|||
|
|
|||
|
#define AtalkAtpReqReferenceByPtr(_pAtpReq, _pErr) \
|
|||
|
{ \
|
|||
|
KIRQL OldIrql; \
|
|||
|
\
|
|||
|
*(_pErr) = ATALK_NO_ERROR; \
|
|||
|
\
|
|||
|
ACQUIRE_SPIN_LOCK(&(_pAtpReq)->req_Lock, &OldIrql); \
|
|||
|
if (((_pAtpReq)->req_Flags & ATP_REQ_CLOSING) == 0) \
|
|||
|
{ \
|
|||
|
(_pAtpReq)->req_RefCount++; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("AtalkAtpReqReferenceByPtr: %lx %s (%ld) Failure\n", \
|
|||
|
_pAtpReq, __FILE__, __LINE__)); \
|
|||
|
*(_pErr) = ATALK_ATP_REQ_CLOSING; \
|
|||
|
} \
|
|||
|
RELEASE_SPIN_LOCK(&(_pAtpReq)->req_Lock, OldIrql); \
|
|||
|
}
|
|||
|
|
|||
|
#define AtalkAtpReqReferenceByPtrDpc(_pAtpReq, _pErr) \
|
|||
|
{ \
|
|||
|
*(_pErr) = ATALK_NO_ERROR; \
|
|||
|
\
|
|||
|
ACQUIRE_SPIN_LOCK_DPC(&(_pAtpReq)->req_Lock); \
|
|||
|
if (((_pAtpReq)->req_Flags & ATP_REQ_CLOSING) == 0) \
|
|||
|
{ \
|
|||
|
(_pAtpReq)->req_RefCount++; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
*(_pErr) = ATALK_ATP_REQ_CLOSING; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("AtalkAtpReqReferenceByPtrDpc: %lx %s (%ld) Failure\n", \
|
|||
|
_pAtpReq, __FILE__, __LINE__)); \
|
|||
|
} \
|
|||
|
RELEASE_SPIN_LOCK_DPC(&(_pAtpReq)->req_Lock); \
|
|||
|
}
|
|||
|
|
|||
|
#define atalkAtpRespReferenceNDpc(_pAtpResp, _N, _pError) \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_NO_ERROR; \
|
|||
|
ACQUIRE_SPIN_LOCK_DPC(&(_pAtpResp)->resp_Lock); \
|
|||
|
if (((_pAtpResp)->resp_Flags & ATP_RESP_CLOSING) == 0) \
|
|||
|
{ \
|
|||
|
(_pAtpResp)->resp_RefCount += _N; \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
*(_pError) = ATALK_ATP_RESP_CLOSING; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_WARN, \
|
|||
|
("atalkAtpRespReferenceNDpc: %lx %d %s (%ld) Failure\n", \
|
|||
|
_pAtpResp, _N, __FILE__, __LINE__)); \
|
|||
|
} \
|
|||
|
RELEASE_SPIN_LOCK_DPC(&(_pAtpResp)->resp_Lock); \
|
|||
|
}
|
|||
|
|
|||
|
// THIS SHOULD BE CALLED WITH ADDRESS LOCK HELD !!!
|
|||
|
|
|||
|
#define atalkAtpRespReferenceByAddrTidDpc(_pAtpAddr, _pAddr, _Tid, _ppAtpResp, _pErr)\
|
|||
|
{ \
|
|||
|
PATP_RESP __p; \
|
|||
|
ULONG __i; \
|
|||
|
\
|
|||
|
__i = ATP_HASH_TID_DESTADDR((_Tid), (_pAddr), ATP_RESP_HASH_SIZE); \
|
|||
|
\
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO, \
|
|||
|
("atalkAtpRespRefByAddrTid: %lx.%lx.%lx tid %lx\n", \
|
|||
|
(_pAddr)->ata_Network, (_pAddr)->ata_Node, \
|
|||
|
(_pAddr)->ata_Socket, (_Tid))); \
|
|||
|
\
|
|||
|
for (__p = (_pAtpAddr)->atpao_RespHash[__i]; \
|
|||
|
__p != NULL; \
|
|||
|
__p = __p->resp_Next) \
|
|||
|
{ \
|
|||
|
if (ATALK_ADDRS_EQUAL(&__p->resp_Dest, _pAddr) && \
|
|||
|
(__p->resp_Tid == (_Tid))) \
|
|||
|
{ \
|
|||
|
AtalkAtpRespReferenceByPtrDpc(__p, _pErr); \
|
|||
|
if (ATALK_SUCCESS((*(_pErr)))) \
|
|||
|
{ \
|
|||
|
*(_ppAtpResp) = __p; \
|
|||
|
DBGPRINT(DBG_COMP_ATP, DBG_LEVEL_INFO, \
|
|||
|
("atalkAtpRespRefByAddrTid: FOUND %lx\n", __p)); \
|
|||
|
} \
|
|||
|
break; \
|
|||
|
} \
|
|||
|
} \
|
|||
|
if (__p == NULL) \
|
|||
|
*(_pErr) = ATALK_ATP_NOT_FOUND; \
|
|||
|
}
|
|||
|
|
|||
|
#define AtalkAtpReqDereference(_pAtpReq) \
|
|||
|
atalkAtpReqDeref(_pAtpReq, FALSE)
|
|||
|
|
|||
|
#define AtalkAtpReqDereferenceDpc(_pAtpReq) \
|
|||
|
atalkAtpReqDeref(_pAtpReq, TRUE)
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpTransmitReq(
|
|||
|
IN PATP_REQ pAtpReq);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpTransmitResp(
|
|||
|
IN PATP_RESP pAtpResp);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpTransmitRel(
|
|||
|
IN PATP_REQ pAtpReq);
|
|||
|
|
|||
|
VOID
|
|||
|
atalkAtpGetNextTidForAddr(
|
|||
|
IN PATP_ADDROBJ pAtpAddr,
|
|||
|
IN PATALK_ADDR pRemoteAddr,
|
|||
|
OUT PUSHORT pTid,
|
|||
|
OUT PULONG pIndex);
|
|||
|
|
|||
|
LOCAL LONG FASTCALL
|
|||
|
atalkAtpReqTimer(
|
|||
|
IN PTIMERLIST pTimer,
|
|||
|
IN BOOLEAN TimerShuttingDown);
|
|||
|
|
|||
|
LOCAL LONG FASTCALL
|
|||
|
atalkAtpRelTimer(
|
|||
|
IN PTIMERLIST pTimer,
|
|||
|
IN BOOLEAN TimerShuttingDown);
|
|||
|
|
|||
|
#define atalkAtpBufferSizeToBitmap(_Bitmap, _BufSize, _SinglePktSize) \
|
|||
|
{ \
|
|||
|
SHORT __bufSize = (_BufSize); \
|
|||
|
\
|
|||
|
(_Bitmap) = 0; \
|
|||
|
while(__bufSize > 0) \
|
|||
|
{ \
|
|||
|
(_Bitmap) = ((_Bitmap) <<= 1) | 1; \
|
|||
|
__bufSize -= (_SinglePktSize); \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
#define atalkAtpBitmapToBufferSize(_Size, _Bitmap, _SinglePktSize) \
|
|||
|
{ \
|
|||
|
BYTE __bitmap = (_Bitmap); \
|
|||
|
BOOLEAN __bitOn; \
|
|||
|
\
|
|||
|
_Size = 0; \
|
|||
|
while (__bitmap) \
|
|||
|
{ \
|
|||
|
__bitOn = (__bitmap & 1); \
|
|||
|
__bitmap >>= 1; \
|
|||
|
if (__bitOn) \
|
|||
|
{ \
|
|||
|
(_Size) += (_SinglePktSize); \
|
|||
|
} \
|
|||
|
else \
|
|||
|
{ \
|
|||
|
if (__bitmap) \
|
|||
|
{ \
|
|||
|
(_Size) = -1; \
|
|||
|
} \
|
|||
|
break; \
|
|||
|
} \
|
|||
|
} \
|
|||
|
}
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpSendReqComplete(
|
|||
|
IN NDIS_STATUS Status,
|
|||
|
IN PSEND_COMPL_INFO pSendInfo);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpSendRespComplete(
|
|||
|
IN NDIS_STATUS Status,
|
|||
|
IN PSEND_COMPL_INFO pSendInfo);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpSendRelComplete(
|
|||
|
IN NDIS_STATUS Status,
|
|||
|
IN PSEND_COMPL_INFO pSendInfo);
|
|||
|
|
|||
|
VOID
|
|||
|
atalkAtpRespRefNextNc(
|
|||
|
IN PATP_RESP pAtpResp,
|
|||
|
OUT PATP_RESP * ppNextNcResp,
|
|||
|
OUT PATALK_ERROR pError);
|
|||
|
|
|||
|
VOID
|
|||
|
atalkAtpReqRefNextNc(
|
|||
|
IN PATP_REQ pAtpReq,
|
|||
|
OUT PATP_REQ * pNextNcReq,
|
|||
|
OUT PATALK_ERROR pError);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpRespComplete(
|
|||
|
IN OUT PATP_RESP pAtpResp,
|
|||
|
IN ATALK_ERROR CompletionStatus);
|
|||
|
|
|||
|
VOID FASTCALL
|
|||
|
atalkAtpReqComplete(
|
|||
|
IN OUT PATP_REQ pAtpReq,
|
|||
|
IN ATALK_ERROR CompletionStatus);
|
|||
|
|
|||
|
#endif // _ATP_
|
|||
|
|