/*++ Copyright (c) 1992 Microsoft Corporation Module Name: adsp.h Abstract: This module contains definitions for the ADSP code. Author: Jameel Hyder (jameelh@microsoft.com) Nikhil Kamkolkar (nikhilk@microsoft.com) Revision History: 20 May 1993 Initial Version Notes: Tab stop: 4 --*/ #ifndef _ADSP_ #define _ADSP_ // ADSP_ version. #define ADSP_VERSION 0x0100 // ADSP_ field offsets within a Ddp datagram. #define ADSP_SRC_CONNID_OFF 0 #define ADSP_FIRST_BYTE_SEQNUM_OFF 2 #define ADSP_THIS_ATTEN_SEQNUM_OFF 2 #define ADSP_NEXT_RX_BYTESEQNUM_OFF 6 #define ADSP_NEXT_RX_ATTNSEQNUM_OFF 6 #define ADSP_RX_WINDOW_SIZE_OFF 10 #define ADSP_RX_ATTEN_SIZE_OFF 10 #define ADSP_DESCRIPTOR_OFF 12 #define ADSP_DATA_OFF 13 #define ADSP_VERSION_STAMP_OFF 13 #define ADSP_ATTEN_CODE_OFF 13 #define ADSP_ATTEN_DATA_OFF 15 #define ADSP_DEST_CONNID_OFF 15 #define ADSP_NEXT_ATTEN_SEQNUM_OFF 17 // Bit fields in the ADSP_ descriptor #define ADSP_CONTROL_FLAG 0x80 #define ADSP_ACK_REQ_FLAG 0x40 #define ADSP_EOM_FLAG 0x20 #define ADSP_ATTEN_FLAG 0x10 // Control codes in the ADSP_ descriptor: #define ADSP_CONTROL_MASK 0x0F #define ADSP_PROBE_OR_ACK_CODE 0 #define ADSP_OPENCONN_REQ_CODE 1 #define ADSP_OPENCONN_ACK_CODE 2 #define ADSP_OPENCONN_REQANDACK_CODE 3 #define ADSP_OPENCONN_DENY_CODE 4 #define ADSP_CLOSE_CONN_CODE 5 #define ADSP_FORWARD_RESET_CODE 6 #define ADSP_FORWARD_RESETACK_CODE 7 #define ADSP_RETRANSMIT_CODE 8 // Data sizes: #define ADSP_MAX_DATA_SIZE 572 #define ADSP_MAX_ATTEN_DATA_SIZE 570 #define ADSP_MAX_ATTEN_PKT_SIZE 572 #define ADSP_MIN_ATTEN_PKT_SIZE sizeof(USHORT) // Largest allowed send/receive window size. #define ADSP_MAX_SEND_RX_WINDOW_SIZE 0xFFFF #define ADSP_DEF_SEND_RX_WINDOW_SIZE ((1024*8)+1) // 8K + 1 (EOM) // Attention code info: #define ADSP_MIN_ATTENCODE 0x0000 #define ADSP_MAX_ATTENCODE 0xEFFF // How long do we try Open's for? #define ADSP_MAX_OPEN_ATTEMPTS 10 #define ADSP_OPEN_INTERVAL 20 // In 100ms units // Connection maintenance timer values: #define ADSP_PROBE_INTERVAL 30 #define ADSP_CONNECTION_INTERVAL 1200 // In 100ms units // Retransmit timer values: #define ADSP_RETRANSMIT_INTERVAL 20 // In 100ms units // How often do we retransmit attentions? #define ADSP_ATTENTION_INTERVAL 20 // In 100ms units #define ADSP_DISCONNECT_DELAY 7 // In 100ms units // How often do we retransmit forward resets? #define ADSP_FORWARD_RESET_INTERVAL 20 // In 100ms units // How many out of sequence packets do we allow before requesting a retransmition. #define ADSP_OUT_OF_SEQ_PACKETS_MAX 3 // For resolving forward references struct _ADSP_CONNOBJ; struct _ADSP_ADDROBJ; typedef enum { ADSP_SEND_QUEUE, ADSP_RECV_QUEUE } ADSP_QUEUE_TYPE; #define BC_EOM (USHORT)0x0001 #define BC_SEND (USHORT)0x0002 #define BC_DISCONNECT (USHORT)0x4000 #define BC_CLOSING (USHORT)0x8000 // We use buffer chunks for the send receive queues typedef struct _BUFFER_CHUNK { struct _BUFFER_CHUNK * bc_Next; ATALK_SPIN_LOCK bc_Lock; ULONG bc_RefCount; // Size of data copied over from the users mdl. This // could be less than the size of the users data. USHORT bc_DataSize; USHORT bc_Flags; // Write completion information. This is only valid if // the BC_SEND bit is set. With a week left to ship, i'm // wimping out and making a copy to keep things as consistent // and stable as possible. Eventually though, we should just // use the User's buffer to make mdl's out of. PAMDL bc_WriteBuf; GENERIC_WRITE_COMPLETION bc_WriteCompletion; PVOID bc_WriteCtx; ATALK_ERROR bc_WriteError; // Backpointer to the connection object on which this is queued struct _ADSP_CONNOBJ * bc_ConnObj; // // BYTE bc_Data[] // } BUFFER_CHUNK, *PBUFFER_CHUNK; // Buffer queues used for send/receive typedef struct _BUFFER_QUEUE { ULONG bq_StartIndex; PBUFFER_CHUNK bq_Head; PBUFFER_CHUNK bq_Tail; } BUFFER_QUEUE, *PBUFFER_QUEUE; #define ADSP_CONN_HASH_SIZE 23 // ADSP ADDRESS OBJECT STATES #define ADSPAO_LISTENER 0x00000001 #define ADSPAO_CONNECT 0x00000002 #define ADSPAO_MESSAGE 0x00000010 #define ADSPAO_CLOSING 0x80000000 #define ADSPAO_SIGNATURE (*(PULONG)"ADAO") #define VALID_ADSPAO(pAdspAddr) (((pAdspAddr) != NULL) && \ (((struct _ADSP_ADDROBJ *)(pAdspAddr))->adspao_Signature == ADSPAO_SIGNATURE)) typedef struct _ADSP_ADDROBJ { ULONG adspao_Signature; // Global list of address objects. struct _ADSP_ADDROBJ * adspao_pNextGlobal; ULONG adspao_Flags; ULONG adspao_RefCount; ATALK_SPIN_LOCK adspao_Lock; PATALK_DEV_CTX adspao_pDevCtx; // List of connections associated with this address object. // Potentially greater than one if this address object is a listener. struct _ADSP_CONNOBJ * adspao_pAssocConn; // List of connections that are associated, but also have a listen/connect // posted on them. union { struct _ADSP_CONNOBJ * adspao_pListenConn; struct _ADSP_CONNOBJ * adspao_pConnectConn; }; // List of indicated connections waiting for acceptance. struct _ADSP_OPEN_REQ * adspao_OpenReq; // Lookup list of all active connections hashed by connId and remote // address. struct _ADSP_CONNOBJ * adspao_pActiveHash[ADSP_CONN_HASH_SIZE]; // Next connection to use. USHORT adspao_NextConnId; // Event support routines. // // This function pointer points to a connection indication handler for this // Address. Any time a connect request is received on the address, this // routine is invoked. PTDI_IND_CONNECT adspao_ConnHandler; PVOID adspao_ConnHandlerCtx; PTDI_IND_DISCONNECT adspao_DisconnectHandler; PVOID adspao_DisconnectHandlerCtx; PTDI_IND_RECEIVE adspao_RecvHandler; PVOID adspao_RecvHandlerCtx; PTDI_IND_RECEIVE_EXPEDITED adspao_ExpRecvHandler; PVOID adspao_ExpRecvHandlerCtx; PTDI_IND_SEND_POSSIBLE adspao_SendPossibleHandler; PVOID adspao_SendPossibleHandlerCtx; // DDP Address for this adsp address. If this is a listener, then the DDP // address will be what the listens effectively will be posted on. This // will also be the address over which the connections will be active. // if this is a connect address object, then this ddp address will be what the // associated connection be active over. PDDP_ADDROBJ adspao_pDdpAddr; // Completion routine to be called when address is closed GENERIC_COMPLETION adspao_CloseComp; PVOID adspao_CloseCtx; } ADSP_ADDROBJ, *PADSP_ADDROBJ; #define ADSPCO_ASSOCIATED 0x00000001 #define ADSPCO_IND_RECV 0x00000002 #define ADSPCO_LISTENING 0x00000004 #define ADSPCO_CONNECTING 0x00000008 #define ADSPCO_ACCEPT_IRP 0x00000010 #define ADSPCO_LISTEN_IRP 0x00000020 #define ADSPCO_HALF_ACTIVE 0x00000040 #define ADSPCO_ACTIVE 0x00000080 #define ADSPCO_SEEN_REMOTE_OPEN 0x00000100 #define ADSPCO_DISCONNECTING 0x00000200 #define ADSPCO_SERVER_JOB 0x00000400 #define ADSPCO_REMOTE_CLOSE 0x00000800 #define ADSPCO_SEND_IN_PROGRESS 0x00001000 #define ADSPCO_SEND_DENY 0x00002000 #define ADSPCO_SEND_OPENACK 0x00004000 #define ADSPCO_SEND_WINDOW_CLOSED 0x00008000 #define ADSPCO_READ_PENDING 0x00010000 #define ADSPCO_EXREAD_PENDING 0x00020000 #define ADSPCO_FORWARD_RESET_RECD 0x00040000 #define ADSPCO_ATTN_DATA_RECD 0x00080000 #define ADSPCO_ATTN_DATA_EOM 0x00100000 #define ADSPCO_EXSEND_IN_PROGRESS 0x00200000 #define ADSPCO_OPEN_TIMER 0x01000000 #define ADSPCO_RETRANSMIT_TIMER 0x02000000 #define ADSPCO_CONN_TIMER 0x04000000 #define ADSPCO_LOCAL_DISCONNECT 0x08000000 #define ADSPCO_REMOTE_DISCONNECT 0x10000000 #define ADSPCO_DELAYED_DISCONNECT 0x20000000 #define ADSPCO_STOPPING 0x40000000 #define ADSPCO_CLOSING 0x80000000 #define ADSPCO_SIGNATURE (*(PULONG)"ADCO") #define VALID_ADSPCO(pAdspConn) (((pAdspConn) != NULL) && \ (((struct _ADSP_CONNOBJ *)(pAdspConn))->adspco_Signature == ADSPCO_SIGNATURE)) // This will represent a 'job' on the Pap address. This could either be a // workstation job or a server job. In the latter case it could either // be in a 'listen' state or active state. In the former case it is either // active or 'waiting' typedef struct _ADSP_CONNOBJ { ULONG adspco_Signature; // Used to queue into the address object's associated list. struct _ADSP_CONNOBJ * adspco_pNextAssoc; ULONG adspco_Flags; ULONG adspco_RefCount; ATALK_SPIN_LOCK adspco_Lock; PATALK_DEV_CTX adspco_pDevCtx; // !!!NOTE!!! // The address this connection uses will be the address object's DDP address. PDDP_ADDROBJ adspco_pDdpAddr; // Used to queue into the address object's listen/connect list. When it // is removed from the listen/connect, it goes into the active list of the // address object. union { struct _ADSP_CONNOBJ * adspco_pNextListen; struct _ADSP_CONNOBJ * adspco_pNextConnect; struct _ADSP_CONNOBJ * adspco_pNextActive; }; // Global list of connection objects. struct _ADSP_CONNOBJ * adspco_pNextGlobal; // Used to queue into the lookup by remote connid/remote address // list in address obj. struct _ADSP_CONNOBJ * adspco_pHashNext; // Backpointer to the associated address struct _ADSP_ADDROBJ * adspco_pAssocAddr; // Address of remote end of the connection ATALK_ADDR adspco_RemoteAddr; // Connection ids USHORT adspco_LocalConnId; USHORT adspco_RemoteConnId; // Connection timer. During open time this will be the open timer. union { TIMERLIST adspco_ConnTimer; TIMERLIST adspco_OpenTimer; }; TIMERLIST adspco_RetransmitTimer; ULONG adspco_LastTimerRtmtSeq; LONG adspco_LastContactTime; // Connection context PVOID adspco_ConnCtx; // List of pended sends LIST_ENTRY adspco_PendedSends; // Sequence numbers ULONG adspco_SendSeq; ULONG adspco_FirstRtmtSeq; ULONG adspco_SendWindowSeq; ULONG adspco_SendAttnSeq; ULONG adspco_RecvSeq; ULONG adspco_RecvAttnSeq; // Window/buffers LONG adspco_RecvWindow; LONG adspco_SendQueueMax; LONG adspco_RecvQueueMax; // Previously indicated data ULONG adspco_PrevIndicatedData; // Buffer queues BUFFER_QUEUE adspco_SendQueue; BUFFER_QUEUE adspco_NextSendQueue; BUFFER_QUEUE adspco_RecvQueue; // Number of out of sequence packets received ULONG adspco_OutOfSeqCount; // The connection object can have either a CONNECT or a LISTEN posted // on it, but not both. union { struct { // Pending Listen routine. GENERIC_COMPLETION adspco_ListenCompletion; PVOID adspco_ListenCtx; }; struct { // Pending Connect routine. The status buffer is remember and // returned via socket options. The pConnectRespBuf is remembered // to avoid having to get the system address for it. It is freed // when connection is taken off the connectlist. GENERIC_COMPLETION adspco_ConnectCompletion; PVOID adspco_ConnectCtx; ULONG adspco_ConnectAttempts; }; }; // Read completion information ULONG adspco_ReadFlags; PAMDL adspco_ReadBuf; USHORT adspco_ReadBufLen; GENERIC_READ_COMPLETION adspco_ReadCompletion; PVOID adspco_ReadCtx; PBYTE adspco_ExRecdData; USHORT adspco_ExRecdLen; // Expedited Read completion information ULONG adspco_ExReadFlags; USHORT adspco_ExReadBufLen; PAMDL adspco_ExReadBuf; GENERIC_READ_COMPLETION adspco_ExReadCompletion; PVOID adspco_ExReadCtx; // Expedited Write completion information TIMERLIST adspco_ExRetryTimer; PBYTE adspco_ExWriteChBuf; ULONG adspco_ExWriteFlags; USHORT adspco_ExWriteBufLen; PAMDL adspco_ExWriteBuf; GENERIC_WRITE_COMPLETION adspco_ExWriteCompletion; PVOID adspco_ExWriteCtx; // Disconnect inform routine GENERIC_COMPLETION adspco_DisconnectInform; PVOID adspco_DisconnectInformCtx; // Disconnect request completion ATALK_ERROR adspco_DisconnectStatus; GENERIC_COMPLETION adspco_DisconnectCompletion; PVOID adspco_DisconnectCtx; // The following is a hack to get around the problem of rcv/disconnet race condn. // Since this involves major rework, a safe approach is taken TIMERLIST adspco_DisconnectTimer; // Cleanup irp completion GENERIC_COMPLETION adspco_CleanupComp; PVOID adspco_CleanupCtx; // Completion routine to be called when socket is closed GENERIC_COMPLETION adspco_CloseComp; PVOID adspco_CloseCtx; } ADSP_CONNOBJ, *PADSP_CONNOBJ; // Used for the list of indicated connections waiting acceptance typedef struct _ADSP_OPEN_REQ { struct _ADSP_OPEN_REQ * or_Next; ATALK_ADDR or_RemoteAddr; ULONG or_FirstByteSeq; ULONG or_NextRecvSeq; LONG or_RecvWindow; USHORT or_RemoteConnId; } ADSP_OPEN_REQ, *PADSP_OPEN_REQ; // Routine prototypes VOID AtalkInitAdspInitialize( VOID); ATALK_ERROR AtalkAdspCreateAddress( IN PATALK_DEV_CTX pDevCtx OPTIONAL, IN BYTE SocketType, OUT PADSP_ADDROBJ * ppAdspAddr); ATALK_ERROR AtalkAdspCleanupAddress( IN PADSP_ADDROBJ pAdspAddr); ATALK_ERROR AtalkAdspCloseAddress( IN PADSP_ADDROBJ pAdspAddr, IN GENERIC_COMPLETION CompletionRoutine, IN PVOID pCloseCtx); ATALK_ERROR AtalkAdspCreateConnection( IN PVOID pConnCtx, // Context to associate with the session IN PATALK_DEV_CTX pDevCtx OPTIONAL, OUT PADSP_CONNOBJ * ppAdspConn); ATALK_ERROR AtalkAdspCloseConnection( IN PADSP_CONNOBJ pAdspConn, IN GENERIC_COMPLETION CompletionRoutine, IN PVOID pCloseCtx); ATALK_ERROR AtalkAdspCleanupConnection( IN PADSP_CONNOBJ pAdspConn); ATALK_ERROR AtalkAdspAssociateAddress( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_CONNOBJ pAdspConn); ATALK_ERROR AtalkAdspDissociateAddress( IN PADSP_CONNOBJ pAdspConn); ATALK_ERROR AtalkAdspPostListen( IN PADSP_CONNOBJ pAdspConn, IN PVOID pListenCtx, IN GENERIC_COMPLETION CompletionRoutine); ATALK_ERROR AtalkAdspCancelListen( IN PADSP_CONNOBJ pAdspConn) ; ATALK_ERROR AtalkAdspPostConnect( IN PADSP_CONNOBJ pAdspConn, IN PATALK_ADDR pRemoteAddr, IN PVOID pConnectCtx, IN GENERIC_COMPLETION CompletionRoutine); ATALK_ERROR AtalkAdspDisconnect( IN PADSP_CONNOBJ pAdspConn, IN ATALK_DISCONNECT_TYPE DisconnectType, IN PVOID pDisconnectCtx, IN GENERIC_COMPLETION CompletionRoutine); ATALK_ERROR AtalkAdspRead( IN PADSP_CONNOBJ pAdspConn, IN PAMDL pReadBuf, IN USHORT ReadBufLen, IN ULONG ReadFlags, IN PVOID pReadCtx, IN GENERIC_READ_COMPLETION CompletionRoutine); ATALK_ERROR AtalkAdspWrite( IN PADSP_CONNOBJ pAdspConn, IN PAMDL pWriteBuf, IN USHORT WriteBufLen, IN ULONG SendFlags, IN PVOID pWriteCtx, IN GENERIC_WRITE_COMPLETION CompletionRoutine); VOID AtalkAdspQuery( IN PVOID pObject, IN ULONG ObjectType, IN PAMDL pAmdl, OUT PULONG BytesWritten); VOID atalkAdspAddrRefNonInterlock( IN PADSP_ADDROBJ pAdspAddr, OUT PATALK_ERROR pError); VOID atalkAdspAddrDeref( IN PADSP_ADDROBJ pAdspAddr); VOID atalkAdspConnRefByPtrNonInterlock( IN PADSP_CONNOBJ pAdspConn, IN ULONG NumCount, OUT PATALK_ERROR pError); VOID atalkAdspConnRefByCtxNonInterlock( IN PADSP_ADDROBJ pAdspAddr, IN CONNECTION_CONTEXT Ctx, OUT PADSP_CONNOBJ * pAdspConn, OUT PATALK_ERROR pError); VOID atalkAdspConnRefBySrcAddr( IN PADSP_ADDROBJ pAdspAddr, IN PATALK_ADDR pRemoteAddr, IN USHORT RemoteConnId, OUT PADSP_CONNOBJ * ppAdspConn, OUT PATALK_ERROR pError); VOID atalkAdspConnRefNextNc( IN PADSP_CONNOBJ pAdspConn, IN PADSP_CONNOBJ * ppAdspConnNext, OUT PATALK_ERROR pError); VOID AtalkAdspProcessQueuedSend( IN PADSP_CONNOBJ pAdspConn); VOID atalkAdspConnDeref( IN PADSP_CONNOBJ pAdspConn); // MACROS #define UNSIGNED_BETWEEN_WITH_WRAP(Low, High, Target) \ ((Low <= High) ? ((Target >= Low) && (Target <= High)) : \ ((Target >= Low) || (Target <= High))) // This didnt make sense until JameelH explained what was going on. // This is with the assumption that the window size will never be greater // than the difference of 0x80000 and 0x10000. If High is < 10000 and Low // is > 80000 then we can assume a wrap happened. Otherwise, we assume no // wrap and do a straight compare. #define UNSIGNED_GREATER_WITH_WRAP(High, Low) \ (((High < 0x10000) && (Low > 0x80000)) ? TRUE : (High > Low)) // (((High < 0x80000) && (Low > 0x10000)) ? TRUE : (High > Low)) #define AtalkAdspGetDdpAddress(pAdspAddr) \ ((pAdspAddr)->adspao_pDdpAddr) #define AtalkAdspAddrReferenceNonInterlock(pAdspAddr, pError) \ { \ DBGPRINT(DBG_COMP_ADSP, DBG_LEVEL_INFO, ("RefAddr %lx at %s %d - %d\n", \ pAdspAddr, __FILE__, __LINE__, ((pAdspAddr)->adspao_RefCount))); \ atalkAdspAddrRefNonInterlock(pAdspAddr, pError); \ } #define AtalkAdspAddrReference(pAdspAddr, pError) \ { \ KIRQL OldIrql; \ \ ACQUIRE_SPIN_LOCK(&(pAdspAddr)->adspao_Lock, &OldIrql); \ AtalkAdspAddrReferenceNonInterlock(pAdspAddr, pError); \ RELEASE_SPIN_LOCK(&(pAdspAddr)->adspao_Lock, OldIrql); \ } #define AtalkAdspAddrDereference(pAdspAddr) \ { \ DBGPRINT(DBG_COMP_ADSP, DBG_LEVEL_INFO, ("DerefAddr %lx at %s %d - %d\n",\ pAdspAddr, __FILE__, __LINE__, ((pAdspAddr)->adspao_RefCount))); \ atalkAdspAddrDeref(pAdspAddr); \ } #define AtalkAdspConnReferenceByPtrNonInterlock(pAdspConn, NumCount, pError) \ { \ atalkAdspConnRefByPtrNonInterlock(pAdspConn, NumCount, pError); \ } #define AtalkAdspConnReferenceByPtr(pAdspConn, pError) \ { \ KIRQL OldIrql; \ \ ACQUIRE_SPIN_LOCK(&(pAdspConn)->adspco_Lock, &OldIrql); \ AtalkAdspConnReferenceByPtrNonInterlock(pAdspConn, 1, pError);\ RELEASE_SPIN_LOCK(&(pAdspConn)->adspco_Lock, OldIrql); \ } #define AtalkAdspConnReferenceByCtxNonInterlock(pAdspAddr, Ctx, ppAdspConn, pError) \ atalkAdspConnRefByCtxNonInterlock(pAdspAddr, Ctx, ppAdspConn, pError) #define AtalkAdspConnReferenceBySrcAddr(pAdspAddr, pSrc, SessId, pErr) \ atalkAdspConnRefBySrcAddr(pAdspAddr, pSrc, SessId, pErr) #define AtalkAdspConnDereference(pAdspConn) \ { \ DBGPRINT(DBG_COMP_ADSP, DBG_LEVEL_INFO, \ ("DerefConn %lx at %s %d - %d\n", \ pAdspConn, __FILE__, __LINE__, \ (pAdspConn)->adspco_RefCount)); \ atalkAdspConnDeref(pAdspConn); \ } // How many bytes/seqnums does eom occupy? #define BYTECOUNT(eom) ((ULONG)((eom) ? 1 : 0)) // // PLIST_ENTRY // WRITECTX_LINKAGE( // IN PVOID WriteCtx // ); // // Returns a pointer to a linkage field in the write context (Assumed to be IRP). // #define WRITECTX_LINKAGE(_Request) \ (&(((PIRP)_Request)->Tail.Overlay.ListEntry)) #define WRITECTX(_Request) ((PIRP)(_Request)) // // PVOID // LIST_ENTRY_TO_WRITECTX( // IN PLIST_ENTRY ListEntry // ); // // Returns a request given a linkage field in it. // #define LIST_ENTRY_TO_WRITECTX(_ListEntry) \ ((PVOID)(CONTAINING_RECORD(_ListEntry, IRP, Tail.Overlay.ListEntry))) // // PVOID // WRITECTX_TDI_BUFFER // IN PVOID Request // ); // // Returns the TDI buffer chain associated with a request. // #define WRITECTX_TDI_BUFFER(_Request) \ ((PVOID)(((PIRP)(_Request))->MdlAddress)) // // ULONG // WRITECTX_SIZE( // IN PVOID Request // ); // // Obtains size of send // #define WRITECTX_SIZE(_Request) \ (((PTDI_REQUEST_KERNEL_SEND)(&((IoGetCurrentIrpStackLocation((PIRP)_Request))->Parameters)))->SendLength) // // ULONG // WRITECTX_FLAGS( // IN PVOID Request // ); // // Obtains size of send // #define WRITECTX_FLAGS(_Request) \ (((PTDI_REQUEST_KERNEL_SEND)(&((IoGetCurrentIrpStackLocation((PIRP)_Request))->Parameters)))->SendFlags) extern PADSP_ADDROBJ atalkAdspAddrList; extern PADSP_CONNOBJ atalkAdspConnList; extern ATALK_SPIN_LOCK atalkAdspLock; PBUFFER_CHUNK atalkAdspAllocCopyChunk( IN PVOID pWriteBuf, IN USHORT WriteBufLen, IN BOOLEAN Eom, IN BOOLEAN IsCharBuffer); VOID atalkAdspPacketIn( IN PPORT_DESCRIPTOR pPortDesc, IN PDDP_ADDROBJ pDdpAddr, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN PATALK_ADDR pDestAddr, IN ATALK_ERROR ErrorCode, IN BYTE DdpType, IN PADSP_ADDROBJ pAdspAddr, IN BOOLEAN OptimizePath, IN PVOID OptimizeCtx); LOCAL VOID atalkAdspHandleOpenControl( IN PADSP_ADDROBJ pAdspAddr, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN USHORT RemoteConnId, IN ULONG RemoteFirstByteSeq, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow, IN BYTE Descriptor); LOCAL VOID atalkAdspHandleAttn( IN PADSP_CONNOBJ pAdspConn, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN ULONG RemoteFirstByteSeq, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow, IN BYTE Descriptor); LOCAL VOID atalkAdspHandlePiggyBackAck( IN PADSP_CONNOBJ pAdspConn, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow); LOCAL VOID atalkAdspHandleControl( IN PADSP_CONNOBJ pAdspConn, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN ULONG RemoteFirstByteSeq, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow, IN BYTE Descriptor); LOCAL VOID atalkAdspHandleData( IN PADSP_CONNOBJ pAdspConn, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN ULONG RemoteFirstByteSeq, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow, IN BYTE Descriptor); LOCAL VOID atalkAdspHandleOpenReq( IN PADSP_ADDROBJ pAdspAddr, IN PBYTE pPkt, IN USHORT PktLen, IN PATALK_ADDR pSrcAddr, IN USHORT RemoteConnId, IN ULONG RemoteFirstByteSeq, IN ULONG RemoteNextRecvSeq, IN ULONG RemoteRecvWindow, IN BYTE Descriptor); LOCAL VOID atalkAdspListenIndicateNonInterlock( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_OPEN_REQ pOpenReq, IN PADSP_CONNOBJ * ppAdspConn, IN PATALK_ERROR pError); ATALK_ERROR atalkAdspSendExpedited( IN PADSP_CONNOBJ pAdspConn, IN PAMDL pWriteBuf, IN USHORT WriteBufLen, IN ULONG SendFlags, IN PVOID pWriteCtx, IN GENERIC_WRITE_COMPLETION CompletionRoutine); LOCAL VOID atalkAdspSendOpenControl( IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspSendControl( IN PADSP_CONNOBJ pAdspConn, IN BYTE Descriptor); LOCAL VOID atalkAdspSendAttn( IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspSendData( IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspRecvAttn( IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspRecvData( IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspSendDeny( IN PADSP_ADDROBJ pAdspAddr, IN PATALK_ADDR pRemoteAddr, IN USHORT pRemoteConnId); VOID FASTCALL atalkAdspSendAttnComplete( IN NDIS_STATUS Status, IN PSEND_COMPL_INFO pSendInfo); VOID FASTCALL atalkAdspConnSendComplete( IN NDIS_STATUS Status, IN PSEND_COMPL_INFO pSendInfo); VOID FASTCALL atalkAdspAddrSendComplete( IN NDIS_STATUS Status, IN PSEND_COMPL_INFO pSendInfo); VOID FASTCALL atalkAdspSendDataComplete( IN NDIS_STATUS Status, IN PSEND_COMPL_INFO pSendInfo); LOCAL LONG FASTCALL atalkAdspConnMaintenanceTimer( IN PTIMERLIST pTimer, IN BOOLEAN TimerShuttingDown); LOCAL LONG FASTCALL atalkAdspRetransmitTimer( IN PTIMERLIST pTimer, IN BOOLEAN TimerShuttingDown); LOCAL LONG FASTCALL atalkAdspAttnRetransmitTimer( IN PTIMERLIST pTimer, IN BOOLEAN TimerShuttingDown); LOCAL LONG FASTCALL atalkAdspOpenTimer( IN PTIMERLIST pTimer, IN BOOLEAN TimerShuttingDown); LOCAL LONG FASTCALL atalkAdspDisconnectTimer( IN PTIMERLIST pTimer, IN BOOLEAN TimerShuttingDown); VOID atalkAdspDecodeHeader( IN PBYTE Datagram, OUT PUSHORT RemoteConnId, OUT PULONG FirstByteSeq, OUT PULONG NextRecvSeq, OUT PLONG Window, OUT PBYTE Descriptor); LOCAL USHORT atalkAdspGetNextConnId( IN PADSP_ADDROBJ pAdspAddr, OUT PATALK_ERROR pError); LOCAL BOOLEAN atalkAdspConnDeQueueAssocList( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_CONNOBJ pAdspConn); LOCAL BOOLEAN atalkAdspConnDeQueueConnectList( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_CONNOBJ pAdspConn); LOCAL BOOLEAN atalkAdspConnDeQueueListenList( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_CONNOBJ pAdspConn); LOCAL BOOLEAN atalkAdspConnDeQueueActiveList( IN PADSP_ADDROBJ pAdspAddr, IN PADSP_CONNOBJ pAdspConn); LOCAL VOID atalkAdspAddrQueueGlobalList( IN PADSP_ADDROBJ pAdspAddr); LOCAL VOID atalkAdspAddrDeQueueGlobalList( IN PADSP_ADDROBJ pAdspAddr); LOCAL VOID atalkAdspConnDeQueueGlobalList( IN PADSP_CONNOBJ pAdspConn); LOCAL BOOLEAN atalkAdspAddrDeQueueOpenReq( IN PADSP_ADDROBJ pAdspAddr, IN USHORT RemoteConnId, IN PATALK_ADDR pSrcAddr, OUT PADSP_OPEN_REQ * ppOpenReq); LOCAL BOOLEAN atalkAdspIsDuplicateOpenReq( IN PADSP_ADDROBJ pAdspAddr, IN USHORT RemoteConnId, IN PATALK_ADDR pSrcAddr); LOCAL VOID atalkAdspGenericComplete( IN ATALK_ERROR ErrorCode, IN PIRP pIrp); ULONG atalkAdspMaxSendSize( IN PADSP_CONNOBJ pAdspConn); ULONG atalkAdspMaxNextReadSize( IN PBUFFER_QUEUE pQueue, OUT PBOOLEAN pEom, OUT PBUFFER_CHUNK * pBufferChunk); ULONG atalkAdspBufferQueueSize( IN PBUFFER_QUEUE pQueue); ULONG atalkAdspMessageSize( IN PBUFFER_QUEUE pQueue, IN PBOOLEAN pEom); PBYTE atalkAdspGetLookahead( IN PBUFFER_QUEUE pQueue, OUT PULONG pLookaheadSize); ULONG atalkAdspReadFromBufferQueue( IN PBUFFER_QUEUE pQueue, IN ULONG pFlags, OUT PAMDL pReadBuf, IN OUT PUSHORT pReadLen, OUT PBOOLEAN pEom); BOOLEAN atalkAdspDiscardFromBufferQueue( IN PBUFFER_QUEUE pQueue, IN ULONG DataSize, OUT PBUFFER_QUEUE pAuxQueue, IN ATALK_ERROR Error, IN PADSP_CONNOBJ pAdspConn OPTIONAL); VOID atalkAdspAddToBufferQueue( IN OUT PBUFFER_QUEUE pQueue, IN PBUFFER_CHUNK pChunk, IN OUT PBUFFER_QUEUE pAuxQueue OPTIONAL); VOID atalkAdspBufferChunkReference( IN PBUFFER_CHUNK pBufferChunk); VOID atalkAdspBufferChunkDereference( IN PBUFFER_CHUNK pBufferChunk, IN BOOLEAN CreationDeref, IN PADSP_CONNOBJ pAdspConn OPTIONAL); VOID atalkAdspConnFindInConnect( IN PADSP_ADDROBJ pAdspAddr, IN USHORT DestConnId, IN PATALK_ADDR pRemoteAddr, OUT PADSP_CONNOBJ * ppAdspConn, IN PATALK_ERROR pError); ULONG atalkAdspDescribeFromBufferQueue( IN PBUFFER_QUEUE pQueue, OUT PBOOLEAN pEom, IN ULONG WindowSize, OUT PBUFFER_CHUNK * ppBufferChunk, OUT PBUFFER_DESC * ppBufDesc); #endif // _ADSP_